diff options
author | Nick Kossifidis <mick@madwifi.org> | 2008-09-28 18:23:07 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2008-09-30 14:07:26 -0400 |
commit | 509a106e68aa42acc1a0c44ab365d0de6869bd9e (patch) | |
tree | 2477b692d65bec9489f4db281b8ddcb7d0018a71 /drivers/net | |
parent | ee81c5544bbf49ea5b301784a605d865947ac1b0 (diff) |
ath5k: Use QUIET mechanism on tx dma stop
* Use QUIET mechanism to drain tx buffer on PCU for newer chips
* Make sure that INTPEND is really 1 and not 0xffffffff while checking for pending interrupts
Changes-Licensed-under: ISC
Signed-Off-by: Nick Kossifidis <mickflemm@gmail.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/wireless/ath5k/dma.c | 49 | ||||
-rw-r--r-- | drivers/net/wireless/ath5k/reg.h | 4 |
2 files changed, 46 insertions, 7 deletions
diff --git a/drivers/net/wireless/ath5k/dma.c b/drivers/net/wireless/ath5k/dma.c index a28090be9603..7adceb2c7fab 100644 --- a/drivers/net/wireless/ath5k/dma.c +++ b/drivers/net/wireless/ath5k/dma.c | |||
@@ -68,7 +68,7 @@ int ath5k_hw_stop_rx_dma(struct ath5k_hw *ah) | |||
68 | /* | 68 | /* |
69 | * It may take some time to disable the DMA receive unit | 69 | * It may take some time to disable the DMA receive unit |
70 | */ | 70 | */ |
71 | for (i = 2000; i > 0 && | 71 | for (i = 1000; i > 0 && |
72 | (ath5k_hw_reg_read(ah, AR5K_CR) & AR5K_CR_RXE) != 0; | 72 | (ath5k_hw_reg_read(ah, AR5K_CR) & AR5K_CR_RXE) != 0; |
73 | i--) | 73 | i--) |
74 | udelay(10); | 74 | udelay(10); |
@@ -182,11 +182,10 @@ int ath5k_hw_start_tx_dma(struct ath5k_hw *ah, unsigned int queue) | |||
182 | * have any pending frames. Returns -EBUSY if we still have pending frames, | 182 | * have any pending frames. Returns -EBUSY if we still have pending frames, |
183 | * -EINVAL if queue number is out of range. | 183 | * -EINVAL if queue number is out of range. |
184 | * | 184 | * |
185 | * TODO: Test queue drain code | ||
186 | */ | 185 | */ |
187 | int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue) | 186 | int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue) |
188 | { | 187 | { |
189 | unsigned int i = 100; | 188 | unsigned int i = 40; |
190 | u32 tx_queue, pending; | 189 | u32 tx_queue, pending; |
191 | 190 | ||
192 | ATH5K_TRACE(ah->ah_sc); | 191 | ATH5K_TRACE(ah->ah_sc); |
@@ -233,13 +232,53 @@ int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue) | |||
233 | udelay(100); | 232 | udelay(100); |
234 | } while (--i && pending); | 233 | } while (--i && pending); |
235 | 234 | ||
235 | /* For 2413+ order PCU to drop packets using | ||
236 | * QUIET mechanism */ | ||
237 | if (ah->ah_mac_version >= (AR5K_SREV_AR2414 >> 4) && | ||
238 | pending){ | ||
239 | /* Set periodicity and duration */ | ||
240 | ath5k_hw_reg_write(ah, | ||
241 | AR5K_REG_SM(100, AR5K_QUIET_CTL2_QT_PER)| | ||
242 | AR5K_REG_SM(10, AR5K_QUIET_CTL2_QT_DUR), | ||
243 | AR5K_QUIET_CTL2); | ||
244 | |||
245 | /* Enable quiet period for current TSF */ | ||
246 | ath5k_hw_reg_write(ah, | ||
247 | AR5K_QUIET_CTL1_QT_EN | | ||
248 | AR5K_REG_SM(ath5k_hw_reg_read(ah, | ||
249 | AR5K_TSF_L32_5211) >> 10, | ||
250 | AR5K_QUIET_CTL1_NEXT_QT_TSF), | ||
251 | AR5K_QUIET_CTL1); | ||
252 | |||
253 | /* Force channel idle high */ | ||
254 | AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW_5211, | ||
255 | AR5K_DIAG_SW_CHANEL_IDLE_HIGH); | ||
256 | |||
257 | /* Wait a while and disable mechanism */ | ||
258 | udelay(200); | ||
259 | AR5K_REG_DISABLE_BITS(ah, AR5K_QUIET_CTL1, | ||
260 | AR5K_QUIET_CTL1_QT_EN); | ||
261 | |||
262 | /* Re-check for pending frames */ | ||
263 | i = 40; | ||
264 | do { | ||
265 | pending = ath5k_hw_reg_read(ah, | ||
266 | AR5K_QUEUE_STATUS(queue)) & | ||
267 | AR5K_QCU_STS_FRMPENDCNT; | ||
268 | udelay(100); | ||
269 | } while (--i && pending); | ||
270 | |||
271 | AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW_5211, | ||
272 | AR5K_DIAG_SW_CHANEL_IDLE_HIGH); | ||
273 | } | ||
274 | |||
236 | /* Clear register */ | 275 | /* Clear register */ |
237 | ath5k_hw_reg_write(ah, 0, AR5K_QCU_TXD); | 276 | ath5k_hw_reg_write(ah, 0, AR5K_QCU_TXD); |
238 | if (pending) | 277 | if (pending) |
239 | return -EBUSY; | 278 | return -EBUSY; |
240 | } | 279 | } |
241 | 280 | ||
242 | /* TODO: Check for success else return error */ | 281 | /* TODO: Check for success on 5210 else return error */ |
243 | return 0; | 282 | return 0; |
244 | } | 283 | } |
245 | 284 | ||
@@ -415,7 +454,7 @@ done: | |||
415 | bool ath5k_hw_is_intr_pending(struct ath5k_hw *ah) | 454 | bool ath5k_hw_is_intr_pending(struct ath5k_hw *ah) |
416 | { | 455 | { |
417 | ATH5K_TRACE(ah->ah_sc); | 456 | ATH5K_TRACE(ah->ah_sc); |
418 | return ath5k_hw_reg_read(ah, AR5K_INTPEND); | 457 | return ath5k_hw_reg_read(ah, AR5K_INTPEND) == 1 ? 1 : 0; |
419 | } | 458 | } |
420 | 459 | ||
421 | /** | 460 | /** |
diff --git a/drivers/net/wireless/ath5k/reg.h b/drivers/net/wireless/ath5k/reg.h index 55054b575e83..e557fe178bbf 100644 --- a/drivers/net/wireless/ath5k/reg.h +++ b/drivers/net/wireless/ath5k/reg.h | |||
@@ -1424,7 +1424,7 @@ | |||
1424 | #define AR5K_DIAG_SW_OBSPT_S 18 | 1424 | #define AR5K_DIAG_SW_OBSPT_S 18 |
1425 | #define AR5K_DIAG_SW_RX_CLEAR_HIGH 0x0010000 /* Force RX Clear high */ | 1425 | #define AR5K_DIAG_SW_RX_CLEAR_HIGH 0x0010000 /* Force RX Clear high */ |
1426 | #define AR5K_DIAG_SW_IGNORE_CARR_SENSE 0x0020000 /* Ignore virtual carrier sense */ | 1426 | #define AR5K_DIAG_SW_IGNORE_CARR_SENSE 0x0020000 /* Ignore virtual carrier sense */ |
1427 | #define AR5K_DIAG_SW_CHANEL_IDLE_HIGH 0x0040000 /* Force channel idle high (?) */ | 1427 | #define AR5K_DIAG_SW_CHANEL_IDLE_HIGH 0x0040000 /* Force channel idle high */ |
1428 | #define AR5K_DIAG_SW_PHEAR_ME 0x0080000 /* ??? */ | 1428 | #define AR5K_DIAG_SW_PHEAR_ME 0x0080000 /* ??? */ |
1429 | 1429 | ||
1430 | /* | 1430 | /* |
@@ -1660,7 +1660,7 @@ | |||
1660 | */ | 1660 | */ |
1661 | #define AR5K_QUIET_CTL1 0x80fc /* Register Address */ | 1661 | #define AR5K_QUIET_CTL1 0x80fc /* Register Address */ |
1662 | #define AR5K_QUIET_CTL1_NEXT_QT_TSF 0x0000ffff /* Next quiet period TSF (TU) */ | 1662 | #define AR5K_QUIET_CTL1_NEXT_QT_TSF 0x0000ffff /* Next quiet period TSF (TU) */ |
1663 | #define AR5K_QUIET_CTL1_NEXT_QT_TSF_0 | 1663 | #define AR5K_QUIET_CTL1_NEXT_QT_TSF_S 0 |
1664 | #define AR5K_QUIET_CTL1_QT_EN 0x00010000 /* Enable quiet period */ | 1664 | #define AR5K_QUIET_CTL1_QT_EN 0x00010000 /* Enable quiet period */ |
1665 | #define AR5K_QUIET_CTL1_ACK_CTS_EN 0x00020000 /* Send ACK/CTS during quiet period */ | 1665 | #define AR5K_QUIET_CTL1_ACK_CTS_EN 0x00020000 /* Send ACK/CTS during quiet period */ |
1666 | 1666 | ||