aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSujith Manoharan <c_manoha@qca.qualcomm.com>2015-02-02 07:51:10 -0500
committerKalle Valo <kvalo@codeaurora.org>2015-02-06 01:39:26 -0500
commitbb6313140b3c8356cf36675a8edbf6782dc6c3d0 (patch)
treee49581d79905c11f30619437ea280d9f0d599b2e
parente68e9c10fbe0d4e49732783aae534ba0a328887f (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.c181
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.h2
-rw-r--r--drivers/net/wireless/ath/ath9k/reg_wow.h5
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);
222void ath9k_hw_wow_enable(struct ath_hw *ah, u32 pattern_enable) 222void 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))