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