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

ath9k: Enable WoW only for AR9462

The only card with which WoW has been tested and verified is
AR9462. Do not enable it for all cards since WoW is really quirky
and needs to be tested properly with each chip.

Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>

authored by

Sujith Manoharan and committed by
John W. Linville
846e438f 74a97755

+35 -207
-4
drivers/net/wireless/ath/ath9k/ar9002_hw.c
··· 38 38 else 39 39 INIT_INI_ARRAY(&ah->iniPcieSerdes, 40 40 ar9280PciePhy_clkreq_always_on_L1_9280); 41 - #ifdef CONFIG_PM_SLEEP 42 - INIT_INI_ARRAY(&ah->iniPcieSerdesWow, 43 - ar9280PciePhy_awow); 44 - #endif 45 41 46 42 if (AR_SREV_9287_11_OR_LATER(ah)) { 47 43 INIT_INI_ARRAY(&ah->iniModes, ar9287Modes_9287_1_1);
-14
drivers/net/wireless/ath/ath9k/ar9002_initvals.h
··· 925 925 {0x00004044, 0x00000000}, 926 926 }; 927 927 928 - static const u32 ar9280PciePhy_awow[][2] = { 929 - /* Addr allmodes */ 930 - {0x00004040, 0x9248fd00}, 931 - {0x00004040, 0x24924924}, 932 - {0x00004040, 0xa8000019}, 933 - {0x00004040, 0x13160820}, 934 - {0x00004040, 0xe5980560}, 935 - {0x00004040, 0xc01dcffd}, 936 - {0x00004040, 0x1aaabe41}, 937 - {0x00004040, 0xbe105554}, 938 - {0x00004040, 0x00043007}, 939 - {0x00004044, 0x00000000}, 940 - }; 941 - 942 928 static const u32 ar9285Modes_9285_1_2[][5] = { 943 929 /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ 944 930 {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160},
+2 -7
drivers/net/wireless/ath/ath9k/hw.c
··· 2595 2595 pCap->hw_caps |= ATH9K_HW_CAP_RTT; 2596 2596 } 2597 2597 2598 - if (AR_SREV_9280_20_OR_LATER(ah)) { 2599 - pCap->hw_caps |= ATH9K_HW_WOW_DEVICE_CAPABLE | 2600 - ATH9K_HW_WOW_PATTERN_MATCH_EXACT; 2601 - 2602 - if (AR_SREV_9280(ah)) 2603 - pCap->hw_caps |= ATH9K_HW_WOW_PATTERN_MATCH_DWORD; 2604 - } 2598 + if (AR_SREV_9462(ah)) 2599 + pCap->hw_caps |= ATH9K_HW_WOW_DEVICE_CAPABLE; 2605 2600 2606 2601 if (AR_SREV_9300_20_OR_LATER(ah) && 2607 2602 ah->eep_ops->get_eeprom(ah, EEP_PAPRD))
+1 -8
drivers/net/wireless/ath/ath9k/hw.h
··· 246 246 ATH9K_HW_CAP_MCI = BIT(15), 247 247 ATH9K_HW_CAP_DFS = BIT(16), 248 248 ATH9K_HW_WOW_DEVICE_CAPABLE = BIT(17), 249 - ATH9K_HW_WOW_PATTERN_MATCH_EXACT = BIT(18), 250 - ATH9K_HW_WOW_PATTERN_MATCH_DWORD = BIT(19), 251 - ATH9K_HW_CAP_PAPRD = BIT(20), 249 + ATH9K_HW_CAP_PAPRD = BIT(18), 252 250 }; 253 251 254 252 /* ··· 880 882 struct ar5416IniArray iniBank6; 881 883 struct ar5416IniArray iniAddac; 882 884 struct ar5416IniArray iniPcieSerdes; 883 - #ifdef CONFIG_PM_SLEEP 884 - struct ar5416IniArray iniPcieSerdesWow; 885 - #endif 886 885 struct ar5416IniArray iniPcieSerdesLowPower; 887 886 struct ar5416IniArray iniModesFastClock; 888 887 struct ar5416IniArray iniAdditional; ··· 1159 1164 { 1160 1165 } 1161 1166 #endif 1162 - 1163 - 1164 1167 1165 1168 #define ATH9K_CLOCK_RATE_CCK 22 1166 1169 #define ATH9K_CLOCK_RATE_5GHZ_OFDM 40
-4
drivers/net/wireless/ath/ath9k/init.c
··· 800 800 hw->wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL; 801 801 802 802 #ifdef CONFIG_PM_SLEEP 803 - 804 803 if ((ah->caps.hw_caps & ATH9K_HW_WOW_DEVICE_CAPABLE) && 805 804 device_can_wakeup(sc->dev)) { 806 - 807 805 hw->wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT | 808 806 WIPHY_WOWLAN_DISCONNECT; 809 807 hw->wiphy->wowlan.n_patterns = MAX_NUM_USER_PATTERN; 810 808 hw->wiphy->wowlan.pattern_min_len = 1; 811 809 hw->wiphy->wowlan.pattern_max_len = MAX_PATTERN_SIZE; 812 - 813 810 } 814 811 815 812 atomic_set(&sc->wow_sleep_proc_intr, -1); 816 813 atomic_set(&sc->wow_got_bmiss_intr, -1); 817 - 818 814 #endif 819 815 820 816 hw->queues = 4;
+3 -31
drivers/net/wireless/ath/ath9k/main.c
··· 2003 2003 { 2004 2004 struct ath_hw *ah = sc->sc_ah; 2005 2005 struct ath_common *common = ath9k_hw_common(ah); 2006 - struct ath9k_hw_capabilities *pcaps = &ah->caps; 2007 2006 int pattern_count = 0; 2008 2007 int i, byte_cnt; 2009 2008 u8 dis_deauth_pattern[MAX_PATTERN_SIZE]; ··· 2072 2073 2073 2074 /* Create Disassociate pattern mask */ 2074 2075 2075 - if (pcaps->hw_caps & ATH9K_HW_WOW_PATTERN_MATCH_EXACT) { 2076 - 2077 - if (pcaps->hw_caps & ATH9K_HW_WOW_PATTERN_MATCH_DWORD) { 2078 - /* 2079 - * for AR9280, because of hardware limitation, the 2080 - * first 4 bytes have to be matched for all patterns. 2081 - * the mask for disassociation and de-auth pattern 2082 - * matching need to enable the first 4 bytes. 2083 - * also the duration field needs to be filled. 2084 - */ 2085 - dis_deauth_mask[0] = 0xf0; 2086 - 2087 - /* 2088 - * fill in duration field 2089 - FIXME: what is the exact value ? 2090 - */ 2091 - dis_deauth_pattern[2] = 0xff; 2092 - dis_deauth_pattern[3] = 0xff; 2093 - } else { 2094 - dis_deauth_mask[0] = 0xfe; 2095 - } 2096 - 2097 - dis_deauth_mask[1] = 0x03; 2098 - dis_deauth_mask[2] = 0xc0; 2099 - } else { 2100 - dis_deauth_mask[0] = 0xef; 2101 - dis_deauth_mask[1] = 0x3f; 2102 - dis_deauth_mask[2] = 0x00; 2103 - dis_deauth_mask[3] = 0xfc; 2104 - } 2076 + dis_deauth_mask[0] = 0xfe; 2077 + dis_deauth_mask[1] = 0x03; 2078 + dis_deauth_mask[2] = 0xc0; 2105 2079 2106 2080 ath_dbg(common, WOW, "Adding disassoc/deauth patterns for WoW\n"); 2107 2081
+29 -139
drivers/net/wireless/ath/ath9k/wow.c
··· 34 34 } 35 35 EXPORT_SYMBOL(ath9k_hw_wow_event_to_string); 36 36 37 - static void ath9k_hw_config_serdes_wow_sleep(struct ath_hw *ah) 38 - { 39 - int i; 40 - 41 - for (i = 0; i < ah->iniPcieSerdesWow.ia_rows; i++) 42 - REG_WRITE(ah, INI_RA(&ah->iniPcieSerdesWow, i, 0), 43 - INI_RA(&ah->iniPcieSerdesWow, i, 1)); 44 - 45 - usleep_range(1000, 1500); 46 - } 47 - 48 37 static void ath9k_hw_set_powermode_wow_sleep(struct ath_hw *ah) 49 38 { 50 39 struct ath_common *common = ath9k_hw_common(ah); ··· 47 58 ath_err(common, "Failed to stop Rx DMA in 10ms AR_CR=0x%08x AR_DIAG_SW=0x%08x\n", 48 59 REG_READ(ah, AR_CR), REG_READ(ah, AR_DIAG_SW)); 49 60 return; 50 - } else { 51 - if (!AR_SREV_9300_20_OR_LATER(ah)) 52 - REG_WRITE(ah, AR_RXDP, 0x0); 53 61 } 54 - 55 - /* AR9280 WoW has sleep issue, do not set it to sleep */ 56 - if (AR_SREV_9280_20(ah)) 57 - return; 58 62 59 63 REG_WRITE(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_ON_INT); 60 64 } ··· 66 84 67 85 /* set the transmit buffer */ 68 86 ctl[0] = (KAL_FRAME_LEN | (MAX_RATE_POWER << 16)); 69 - 70 - if (!(AR_SREV_9300_20_OR_LATER(ah))) 71 - ctl[0] += (KAL_ANTENNA_MODE << 25); 72 - 73 87 ctl[1] = 0; 74 88 ctl[3] = 0xb; /* OFDM_6M hardware value for this rate */ 75 89 ctl[4] = 0; 76 90 ctl[7] = (ah->txchainmask) << 2; 77 - 78 - if (AR_SREV_9300_20_OR_LATER(ah)) 79 - ctl[2] = 0xf << 16; /* tx_tries 0 */ 80 - else 81 - ctl[2] = 0x7 << 16; /* tx_tries 0 */ 82 - 91 + ctl[2] = 0xf << 16; /* tx_tries 0 */ 83 92 84 93 for (i = 0; i < KAL_NUM_DESC_WORDS; i++) 85 94 REG_WRITE(ah, (AR_WOW_KA_DESC_WORD2 + i * 4), ctl[i]); 86 95 87 - /* for AR9300 family 13 descriptor words */ 88 - if (AR_SREV_9300_20_OR_LATER(ah)) 89 - REG_WRITE(ah, (AR_WOW_KA_DESC_WORD2 + i * 4), ctl[i]); 96 + REG_WRITE(ah, (AR_WOW_KA_DESC_WORD2 + i * 4), ctl[i]); 90 97 91 98 data_word[0] = (KAL_FRAME_TYPE << 2) | (KAL_FRAME_SUB_TYPE << 4) | 92 99 (KAL_TO_DS << 8) | (KAL_DURATION_ID << 16); ··· 154 183 155 184 ah->wow_event_mask |= BIT(pattern_count + AR_WOW_PAT_FOUND_SHIFT); 156 185 157 - if (!AR_SREV_9285_12_OR_LATER(ah)) 158 - return; 159 - 160 186 if (pattern_count < 4) { 161 187 /* Pattern 0-3 uses AR_WOW_LENGTH1 register */ 162 188 set = (pattern_len & AR_WOW_LENGTH_MAX) << ··· 175 207 { 176 208 u32 wow_status = 0; 177 209 u32 val = 0, rval; 210 + 178 211 /* 179 212 * read the WoW status register to know 180 213 * the wakeup reason ··· 192 223 val &= ah->wow_event_mask; 193 224 194 225 if (val) { 195 - 196 226 if (val & AR_WOW_MAGIC_PAT_FOUND) 197 227 wow_status |= AH_WOW_MAGIC_PATTERN_EN; 198 - 199 228 if (AR_WOW_PATTERN_FOUND(val)) 200 229 wow_status |= AH_WOW_USER_PATTERN_EN; 201 - 202 230 if (val & AR_WOW_KEEP_ALIVE_FAIL) 203 231 wow_status |= AH_WOW_LINK_CHANGE; 204 - 205 232 if (val & AR_WOW_BEACON_FAIL) 206 233 wow_status |= AH_WOW_BEACON_MISS; 207 - 208 234 } 209 235 210 236 /* ··· 219 255 AR_WOW_CLEAR_EVENTS(REG_READ(ah, AR_WOW_PATTERN))); 220 256 221 257 /* 222 - * tie reset register for AR9002 family of chipsets 223 - * NB: not tieing it back might have some repurcussions. 224 - */ 225 - 226 - if (!AR_SREV_9300_20_OR_LATER(ah)) { 227 - REG_SET_BIT(ah, AR_WA, AR_WA_UNTIE_RESET_EN | 228 - AR_WA_POR_SHORT | AR_WA_RESET_EN); 229 - } 230 - 231 - 232 - /* 233 258 * restore the beacon threshold to init value 234 259 */ 235 260 REG_WRITE(ah, AR_RSSI_THR, INIT_RSSI_THR); ··· 230 277 * reset to our Chip's Power On Reset so that any PCI-E 231 278 * reset from the bus will not reset our chip 232 279 */ 233 - 234 - if (AR_SREV_9280_20_OR_LATER(ah) && ah->is_pciexpress) 280 + if (ah->is_pciexpress) 235 281 ath9k_hw_configpcipowersave(ah, false); 236 282 237 283 ah->wow_event_mask = 0; ··· 250 298 * are from the 'pattern_enable' in this function and 251 299 * 'pattern_count' of ath9k_hw_wow_apply_pattern() 252 300 */ 253 - 254 301 wow_event_mask = ah->wow_event_mask; 255 302 256 303 /* ··· 257 306 * WOW sleep, we do want the Reset from the PCI-E to disturb 258 307 * our hw state 259 308 */ 260 - 261 309 if (ah->is_pciexpress) { 262 - 263 310 /* 264 311 * we need to untie the internal POR (power-on-reset) 265 312 * to the external PCI-E reset. We also need to tie 266 313 * the PCI-E Phy reset to the PCI-E reset. 267 314 */ 268 - 269 - if (AR_SREV_9300_20_OR_LATER(ah)) { 270 - set = AR_WA_RESET_EN | AR_WA_POR_SHORT; 271 - clr = AR_WA_UNTIE_RESET_EN | AR_WA_D3_L1_DISABLE; 272 - REG_RMW(ah, AR_WA, set, clr); 273 - } else { 274 - if (AR_SREV_9285(ah) || AR_SREV_9287(ah)) 275 - set = AR9285_WA_DEFAULT; 276 - else 277 - set = AR9280_WA_DEFAULT; 278 - 279 - /* 280 - * In AR9280 and AR9285, bit 14 in WA register 281 - * (disable L1) should only be set when device 282 - * enters D3 state and be cleared when device 283 - * comes back to D0 284 - */ 285 - 286 - if (ah->config.pcie_waen & AR_WA_D3_L1_DISABLE) 287 - set |= AR_WA_D3_L1_DISABLE; 288 - 289 - clr = AR_WA_UNTIE_RESET_EN; 290 - set |= AR_WA_RESET_EN | AR_WA_POR_SHORT; 291 - REG_RMW(ah, AR_WA, set, clr); 292 - 293 - /* 294 - * for WoW sleep, we reprogram the SerDes so that the 295 - * PLL and CLK REQ are both enabled. This uses more 296 - * power but otherwise WoW sleep is unstable and the 297 - * chip may disappear. 298 - */ 299 - 300 - if (AR_SREV_9285_12_OR_LATER(ah)) 301 - ath9k_hw_config_serdes_wow_sleep(ah); 302 - 303 - } 315 + set = AR_WA_RESET_EN | AR_WA_POR_SHORT; 316 + clr = AR_WA_UNTIE_RESET_EN | AR_WA_D3_L1_DISABLE; 317 + REG_RMW(ah, AR_WA, set, clr); 304 318 } 305 319 306 320 /* ··· 294 378 * Program default values for pattern backoff, aifs/slot/KAL count, 295 379 * beacon miss timeout, KAL timeout, etc. 296 380 */ 297 - 298 381 set = AR_WOW_BACK_OFF_SHIFT(AR_WOW_PAT_BACKOFF); 299 382 REG_SET_BIT(ah, AR_WOW_PATTERN, set); 300 383 ··· 313 398 /* 314 399 * Keep alive timo in ms except AR9280 315 400 */ 316 - if (!pattern_enable || AR_SREV_9280(ah)) 401 + if (!pattern_enable) 317 402 set = AR_WOW_KEEP_ALIVE_NEVER; 318 403 else 319 404 set = KAL_TIMEOUT * 32; ··· 335 420 /* 336 421 * Configure MAC WoW Registers 337 422 */ 338 - 339 423 set = 0; 340 424 /* Send keep alive timeouts anyway */ 341 425 clr = AR_WOW_KEEP_ALIVE_AUTO_DIS; ··· 344 430 else 345 431 set = AR_WOW_KEEP_ALIVE_FAIL_DIS; 346 432 347 - /* 348 - * FIXME: For now disable keep alive frame 349 - * failure. This seems to sometimes trigger 350 - * unnecessary wake up with AR9485 chipsets. 351 - */ 352 433 set = AR_WOW_KEEP_ALIVE_FAIL_DIS; 353 - 354 434 REG_RMW(ah, AR_WOW_KEEP_ALIVE, set, clr); 355 - 356 435 357 436 /* 358 437 * we are relying on a bmiss failure. ensure we have ··· 380 473 set |= AR_WOW_MAC_INTR_EN; 381 474 REG_RMW(ah, AR_WOW_PATTERN, set, clr); 382 475 383 - /* 384 - * For AR9285 and later version of chipsets 385 - * enable WoW pattern match for packets less 386 - * than 256 bytes for all patterns 387 - */ 388 - if (AR_SREV_9285_12_OR_LATER(ah)) 389 - REG_WRITE(ah, AR_WOW_PATTERN_MATCH_LT_256B, 390 - AR_WOW_PATTERN_SUPPORTED); 476 + REG_WRITE(ah, AR_WOW_PATTERN_MATCH_LT_256B, 477 + AR_WOW_PATTERN_SUPPORTED); 391 478 392 479 /* 393 480 * Set the power states appropriately and enable PME ··· 389 488 clr = 0; 390 489 set = AR_PMCTRL_PWR_STATE_D1D3 | AR_PMCTRL_HOST_PME_EN | 391 490 AR_PMCTRL_PWR_PM_CTRL_ENA; 392 - /* 393 - * This is needed for AR9300 chipsets to wake-up 394 - * the host. 395 - */ 396 - if (AR_SREV_9300_20_OR_LATER(ah)) 397 - clr = AR_PCIE_PM_CTRL_ENA; 398 491 492 + clr = AR_PCIE_PM_CTRL_ENA; 399 493 REG_RMW(ah, AR_PCIE_PM_CTRL, set, clr); 400 494 401 - if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) { 402 - /* 403 - * this is needed to prevent the chip waking up 404 - * the host within 3-4 seconds with certain 405 - * platform/BIOS. The fix is to enable 406 - * D1 & D3 to match original definition and 407 - * also match the OTP value. Anyway this 408 - * is more related to SW WOW. 409 - */ 410 - clr = AR_PMCTRL_PWR_STATE_D1D3; 411 - REG_CLR_BIT(ah, AR_PCIE_PM_CTRL, clr); 495 + /* 496 + * this is needed to prevent the chip waking up 497 + * the host within 3-4 seconds with certain 498 + * platform/BIOS. The fix is to enable 499 + * D1 & D3 to match original definition and 500 + * also match the OTP value. Anyway this 501 + * is more related to SW WOW. 502 + */ 503 + clr = AR_PMCTRL_PWR_STATE_D1D3; 504 + REG_CLR_BIT(ah, AR_PCIE_PM_CTRL, clr); 412 505 413 - set = AR_PMCTRL_PWR_STATE_D1D3_REAL; 414 - REG_SET_BIT(ah, AR_PCIE_PM_CTRL, set); 415 - } 416 - 417 - 506 + set = AR_PMCTRL_PWR_STATE_D1D3_REAL; 507 + REG_SET_BIT(ah, AR_PCIE_PM_CTRL, set); 418 508 419 509 REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_PRESERVE_SEQNUM); 420 510 421 - if (AR_SREV_9300_20_OR_LATER(ah)) { 422 - /* to bring down WOW power low margin */ 423 - set = BIT(13); 424 - REG_SET_BIT(ah, AR_PCIE_PHY_REG3, set); 425 - /* HW WoW */ 426 - clr = BIT(5); 427 - REG_CLR_BIT(ah, AR_PCU_MISC_MODE3, clr); 428 - } 511 + /* to bring down WOW power low margin */ 512 + set = BIT(13); 513 + REG_SET_BIT(ah, AR_PCIE_PHY_REG3, set); 514 + /* HW WoW */ 515 + clr = BIT(5); 516 + REG_CLR_BIT(ah, AR_PCU_MISC_MODE3, clr); 429 517 430 518 ath9k_hw_set_powermode_wow_sleep(ah); 431 519 ah->wow_event_mask = wow_event_mask;