Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ath9k: Fix issues with WoW enable

This patch addresses several issues with the
ath9k_hw_wow_enable() routine:

* The usage of set/clr variables is removed. Writing
the required values to registers is cleaner.

* The shift value of 28 for the contention window field
in AR_WOW_PATTERN is incorrect, change it to 27.

* Disabling Keep Alive needs to be done based on the
LINK_CHANGE option. This is done unconditionally now,
fix this.

* The workaround for the D1/D3 issue is required only
for AR9462.

* The bitfield for enabling pattern matching for packets
less than 256 bytes has expanded for new chips, handle
this accordingly.

* General cleanup.

Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>

authored by

Sujith Manoharan and committed by
Kalle Valo
bb631314 e68e9c10

+94 -96
+90 -93
drivers/net/wireless/ath/ath9k/ar9003_wow.c
··· 222 222 void ath9k_hw_wow_enable(struct ath_hw *ah, u32 pattern_enable) 223 223 { 224 224 u32 wow_event_mask; 225 + u32 keep_alive, magic_pattern, host_pm_ctrl; 225 226 u32 set, clr; 226 227 227 - /* 228 - * wow_event_mask is a mask to the AR_WOW_PATTERN register to 229 - * indicate which WoW events we have enabled. The WoW events 230 - * are from the 'pattern_enable' in this function and 231 - * 'pattern_count' of ath9k_hw_wow_apply_pattern() 232 - */ 233 228 wow_event_mask = ah->wow.wow_event_mask; 234 229 235 230 /* ··· 244 249 } 245 250 246 251 /* 247 - * set the power states appropriately and enable PME 248 - */ 249 - set = AR_PMCTRL_HOST_PME_EN | AR_PMCTRL_PWR_PM_CTRL_ENA | 250 - AR_PMCTRL_AUX_PWR_DET | AR_PMCTRL_WOW_PME_CLR; 251 - 252 - /* 253 - * set and clear WOW_PME_CLEAR registers for the chip 252 + * AR_PMCTRL_HOST_PME_EN - Override PME enable in configuration 253 + * space and allow MAC to generate WoW anyway. 254 + * 255 + * AR_PMCTRL_PWR_PM_CTRL_ENA - ??? 256 + * 257 + * AR_PMCTRL_AUX_PWR_DET - PCI core SYS_AUX_PWR_DET signal, 258 + * needs to be set for WoW in PCI mode. 259 + * 260 + * AR_PMCTRL_WOW_PME_CLR - WoW Clear Signal going to the MAC. 261 + * 262 + * Set the power states appropriately and enable PME. 263 + * 264 + * Set and clear WOW_PME_CLEAR for the chip 254 265 * to generate next wow signal. 255 266 */ 256 - REG_SET_BIT(ah, AR_PCIE_PM_CTRL, set); 257 - clr = AR_PMCTRL_WOW_PME_CLR; 258 - REG_CLR_BIT(ah, AR_PCIE_PM_CTRL, clr); 267 + REG_SET_BIT(ah, AR_PCIE_PM_CTRL, AR_PMCTRL_HOST_PME_EN | 268 + AR_PMCTRL_PWR_PM_CTRL_ENA | 269 + AR_PMCTRL_AUX_PWR_DET | 270 + AR_PMCTRL_WOW_PME_CLR); 271 + REG_CLR_BIT(ah, AR_PCIE_PM_CTRL, AR_PMCTRL_WOW_PME_CLR); 259 272 260 273 /* 261 - * Setup for: 262 - * - beacon misses 263 - * - magic pattern 264 - * - keep alive timeout 265 - * - pattern matching 274 + * Random Backoff. 275 + * 276 + * 31:28 in AR_WOW_PATTERN : Indicates the number of bits used in the 277 + * contention window. For value N, 278 + * the random backoff will be selected between 279 + * 0 and (2 ^ N) - 1. 266 280 */ 281 + REG_SET_BIT(ah, AR_WOW_PATTERN, 282 + AR_WOW_BACK_OFF_SHIFT(AR_WOW_PAT_BACKOFF)); 267 283 268 284 /* 269 - * Program default values for pattern backoff, aifs/slot/KAL count, 270 - * beacon miss timeout, KAL timeout, etc. 285 + * AIFS time, Slot time, Keep Alive count. 271 286 */ 272 - set = AR_WOW_BACK_OFF_SHIFT(AR_WOW_PAT_BACKOFF); 273 - REG_SET_BIT(ah, AR_WOW_PATTERN, set); 274 - 275 - set = AR_WOW_AIFS_CNT(AR_WOW_CNT_AIFS_CNT) | 276 - AR_WOW_SLOT_CNT(AR_WOW_CNT_SLOT_CNT) | 277 - AR_WOW_KEEP_ALIVE_CNT(AR_WOW_CNT_KA_CNT); 278 - REG_SET_BIT(ah, AR_WOW_COUNT, set); 279 - 287 + REG_SET_BIT(ah, AR_WOW_COUNT, AR_WOW_AIFS_CNT(AR_WOW_CNT_AIFS_CNT) | 288 + AR_WOW_SLOT_CNT(AR_WOW_CNT_SLOT_CNT) | 289 + AR_WOW_KEEP_ALIVE_CNT(AR_WOW_CNT_KA_CNT)); 290 + /* 291 + * Beacon timeout. 292 + */ 280 293 if (pattern_enable & AH_WOW_BEACON_MISS) 281 - set = AR_WOW_BEACON_TIMO; 282 - /* We are not using beacon miss, program a large value */ 294 + REG_WRITE(ah, AR_WOW_BCN_TIMO, AR_WOW_BEACON_TIMO); 283 295 else 284 - set = AR_WOW_BEACON_TIMO_MAX; 285 - 286 - REG_WRITE(ah, AR_WOW_BCN_TIMO, set); 296 + REG_WRITE(ah, AR_WOW_BCN_TIMO, AR_WOW_BEACON_TIMO_MAX); 287 297 288 298 /* 289 - * Keep alive timo in ms except AR9280 299 + * Keep alive timeout in ms. 290 300 */ 291 301 if (!pattern_enable) 292 - set = AR_WOW_KEEP_ALIVE_NEVER; 302 + REG_WRITE(ah, AR_WOW_KEEP_ALIVE_TIMO, AR_WOW_KEEP_ALIVE_NEVER); 293 303 else 294 - set = KAL_TIMEOUT * 32; 295 - 296 - REG_WRITE(ah, AR_WOW_KEEP_ALIVE_TIMO, set); 304 + REG_WRITE(ah, AR_WOW_KEEP_ALIVE_TIMO, KAL_TIMEOUT * 32); 297 305 298 306 /* 299 - * Keep alive delay in us. based on 'power on clock', 300 - * therefore in usec 307 + * Keep alive delay in us. 301 308 */ 302 - set = KAL_DELAY * 1000; 303 - REG_WRITE(ah, AR_WOW_KEEP_ALIVE_DELAY, set); 309 + REG_WRITE(ah, AR_WOW_KEEP_ALIVE_DELAY, KAL_DELAY * 1000); 304 310 305 311 /* 306 - * Create keep alive pattern to respond to beacons 312 + * Create keep alive pattern to respond to beacons. 307 313 */ 308 314 ath9k_wow_create_keep_alive_pattern(ah); 309 315 310 316 /* 311 - * Configure MAC WoW Registers 317 + * Configure keep alive register. 312 318 */ 313 - set = 0; 319 + keep_alive = REG_READ(ah, AR_WOW_KEEP_ALIVE); 320 + 314 321 /* Send keep alive timeouts anyway */ 315 - clr = AR_WOW_KEEP_ALIVE_AUTO_DIS; 322 + keep_alive &= ~AR_WOW_KEEP_ALIVE_AUTO_DIS; 316 323 317 - if (pattern_enable & AH_WOW_LINK_CHANGE) 324 + if (pattern_enable & AH_WOW_LINK_CHANGE) { 325 + keep_alive &= ~AR_WOW_KEEP_ALIVE_FAIL_DIS; 318 326 wow_event_mask |= AR_WOW_KEEP_ALIVE_FAIL; 319 - else 320 - set = AR_WOW_KEEP_ALIVE_FAIL_DIS; 327 + } else { 328 + keep_alive |= AR_WOW_KEEP_ALIVE_FAIL_DIS; 329 + } 321 330 322 - set = AR_WOW_KEEP_ALIVE_FAIL_DIS; 323 - REG_RMW(ah, AR_WOW_KEEP_ALIVE, set, clr); 331 + REG_WRITE(ah, AR_WOW_KEEP_ALIVE, keep_alive); 324 332 325 333 /* 326 - * we are relying on a bmiss failure. ensure we have 327 - * enough threshold to prevent false positives 334 + * We are relying on a bmiss failure, ensure we have 335 + * enough threshold to prevent false positives. 328 336 */ 329 337 REG_RMW_FIELD(ah, AR_RSSI_THR, AR_RSSI_THR_BM_THR, 330 338 AR_WOW_BMISSTHRESHOLD); 331 339 332 - set = 0; 333 - clr = 0; 334 - 335 340 if (pattern_enable & AH_WOW_BEACON_MISS) { 336 - set = AR_WOW_BEACON_FAIL_EN; 337 341 wow_event_mask |= AR_WOW_BEACON_FAIL; 342 + REG_SET_BIT(ah, AR_WOW_BCN_EN, AR_WOW_BEACON_FAIL_EN); 338 343 } else { 339 - clr = AR_WOW_BEACON_FAIL_EN; 344 + REG_CLR_BIT(ah, AR_WOW_BCN_EN, AR_WOW_BEACON_FAIL_EN); 340 345 } 341 346 342 - REG_RMW(ah, AR_WOW_BCN_EN, set, clr); 343 - 344 - set = 0; 345 - clr = 0; 346 347 /* 347 - * Enable the magic packet registers 348 + * Enable the magic packet registers. 348 349 */ 350 + magic_pattern = REG_READ(ah, AR_WOW_PATTERN); 351 + magic_pattern |= AR_WOW_MAC_INTR_EN; 352 + 349 353 if (pattern_enable & AH_WOW_MAGIC_PATTERN_EN) { 350 - set = AR_WOW_MAGIC_EN; 354 + magic_pattern |= AR_WOW_MAGIC_EN; 351 355 wow_event_mask |= AR_WOW_MAGIC_PAT_FOUND; 352 356 } else { 353 - clr = AR_WOW_MAGIC_EN; 357 + magic_pattern &= ~AR_WOW_MAGIC_EN; 354 358 } 355 - set |= AR_WOW_MAC_INTR_EN; 356 - REG_RMW(ah, AR_WOW_PATTERN, set, clr); 357 359 360 + REG_WRITE(ah, AR_WOW_PATTERN, magic_pattern); 361 + 362 + /* 363 + * Enable pattern matching for packets which are less 364 + * than 256 bytes. 365 + */ 358 366 REG_WRITE(ah, AR_WOW_PATTERN_MATCH_LT_256B, 359 367 AR_WOW_PATTERN_SUPPORTED); 360 368 361 369 /* 362 - * Set the power states appropriately and enable PME 370 + * Set the power states appropriately and enable PME. 363 371 */ 364 - clr = 0; 365 - set = AR_PMCTRL_PWR_STATE_D1D3 | AR_PMCTRL_HOST_PME_EN | 366 - AR_PMCTRL_PWR_PM_CTRL_ENA; 372 + host_pm_ctrl = REG_READ(ah, AR_PCIE_PM_CTRL); 373 + host_pm_ctrl |= AR_PMCTRL_PWR_STATE_D1D3 | 374 + AR_PMCTRL_HOST_PME_EN | 375 + AR_PMCTRL_PWR_PM_CTRL_ENA; 376 + host_pm_ctrl &= ~AR_PCIE_PM_CTRL_ENA; 367 377 368 - clr = AR_PCIE_PM_CTRL_ENA; 369 - REG_RMW(ah, AR_PCIE_PM_CTRL, set, clr); 378 + if (AR_SREV_9462(ah)) { 379 + /* 380 + * This is needed to prevent the chip waking up 381 + * the host within 3-4 seconds with certain 382 + * platform/BIOS. 383 + */ 384 + host_pm_ctrl &= ~AR_PMCTRL_PWR_STATE_D1D3; 385 + host_pm_ctrl |= AR_PMCTRL_PWR_STATE_D1D3_REAL; 386 + } 387 + 388 + REG_WRITE(ah, AR_PCIE_PM_CTRL, host_pm_ctrl); 370 389 371 390 /* 372 - * this is needed to prevent the chip waking up 373 - * the host within 3-4 seconds with certain 374 - * platform/BIOS. The fix is to enable 375 - * D1 & D3 to match original definition and 376 - * also match the OTP value. Anyway this 377 - * is more related to SW WOW. 391 + * Enable sequence number generation when asleep. 378 392 */ 379 - clr = AR_PMCTRL_PWR_STATE_D1D3; 380 - REG_CLR_BIT(ah, AR_PCIE_PM_CTRL, clr); 381 - 382 - set = AR_PMCTRL_PWR_STATE_D1D3_REAL; 383 - REG_SET_BIT(ah, AR_PCIE_PM_CTRL, set); 384 - 385 393 REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_PRESERVE_SEQNUM); 386 394 387 - /* to bring down WOW power low margin */ 388 - set = BIT(13); 389 - REG_SET_BIT(ah, AR_PCIE_PHY_REG3, set); 395 + /* To bring down WOW power low margin */ 396 + REG_SET_BIT(ah, AR_PCIE_PHY_REG3, BIT(13)); 397 + 390 398 /* HW WoW */ 391 - clr = BIT(5); 392 - REG_CLR_BIT(ah, AR_PCU_MISC_MODE3, clr); 399 + REG_CLR_BIT(ah, AR_PCU_MISC_MODE3, BIT(5)); 393 400 394 401 ath9k_hw_set_powermode_wow_sleep(ah); 395 402 ah->wow.wow_event_mask = wow_event_mask;
+1 -1
drivers/net/wireless/ath/ath9k/hw.h
··· 199 199 #define KAL_NUM_DESC_WORDS 12 200 200 #define KAL_ANTENNA_MODE 1 201 201 #define KAL_TO_DS 1 202 - #define KAL_DELAY 4 /*delay of 4ms between 2 KAL frames */ 202 + #define KAL_DELAY 4 /* delay of 4ms between 2 KAL frames */ 203 203 #define KAL_TIMEOUT 900 204 204 205 205 #define MAX_PATTERN_SIZE 256
+3 -2
drivers/net/wireless/ath/ath9k/reg_wow.h
··· 68 68 #define AR_CLR_MAC_INTERRUPT 0x20 69 69 #define AR_CLR_KA_INTERRUPT 0x40 70 70 71 - #define AR_WOW_BACK_OFF_SHIFT(x) ((x & 0xf) << 28) /* in usecs */ 71 + #define AR_WOW_BACK_OFF_SHIFT(x) ((x & 0xf) << 27) /* in usecs */ 72 72 #define AR_WOW_MAC_INTR_EN 0x00040000 73 73 #define AR_WOW_MAGIC_EN 0x00010000 74 74 #define AR_WOW_PATTERN_EN(x) (x & 0xff) ··· 113 113 #define AR_WOW_KA_DESC_WORD2 0xe000 114 114 #define AR_WOW_TB_PATTERN(i) (0xe100 + (i << 8)) 115 115 #define AR_WOW_TB_MASK(i) (0xec00 + (i << 5)) 116 - #define AR_WOW_PATTERN_SUPPORTED 0xff 116 + #define AR_WOW_PATTERN_SUPPORTED_LEGACY 0xff 117 + #define AR_WOW_PATTERN_SUPPORTED 0xffff 117 118 #define AR_WOW_LENGTH_MAX 0xff 118 119 #define AR_WOW_LEN1_SHIFT(_i) ((0x3 - ((_i) & 0x3)) << 0x3) 119 120 #define AR_WOW_LENGTH1_MASK(_i) (AR_WOW_LENGTH_MAX << AR_WOW_LEN1_SHIFT(_i))