diff options
author | Senthil Balasubramanian <senthilkumar@atheros.com> | 2009-07-14 20:17:08 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-07-24 15:05:17 -0400 |
commit | dd8b15b027d96f7097ae9dbaebd822a114a03c34 (patch) | |
tree | 580e0d651226724921b2c246d58da2057ab585f1 /drivers/net/wireless/ath/ath9k/mac.c | |
parent | a59b5a5e684652eec035c869ab8911a1689c8f53 (diff) |
ath9k: RX stucks during heavy traffic in HT40 mode.
Running iperf along with p2p traffic on both TX and RX side then
stop one side, then stop the other side, then start it up again,
eventually the STA gets into a mode that it can not pass data at
all.
A hardware workaround for invalid RSSI can make FIFO write pointer
to jump over read pointer, causing RX data corruption and repeated
DMA. Both TX and RX works fine when the workaround is disabled.
To replace the original hardware work around, software looks for
frames with post delimiter CRC error and mark the RSSI invalid so
that the upperlayer will not use the RSSI associated with this
frame. So disable the hardware workaround by updating the appropriate
registers.
Signed-off-by: Senthil Balasubramanian <senthilkumar@atheros.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/mac.c')
-rw-r--r-- | drivers/net/wireless/ath/ath9k/mac.c | 30 |
1 files changed, 23 insertions, 7 deletions
diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c index 8ae4ec21667..6f923e31872 100644 --- a/drivers/net/wireless/ath/ath9k/mac.c +++ b/drivers/net/wireless/ath/ath9k/mac.c @@ -825,13 +825,29 @@ int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds, ds->ds_rxstat.rs_datalen = ads.ds_rxstatus1 & AR_DataLen; ds->ds_rxstat.rs_tstamp = ads.AR_RcvTimestamp; - ds->ds_rxstat.rs_rssi = MS(ads.ds_rxstatus4, AR_RxRSSICombined); - ds->ds_rxstat.rs_rssi_ctl0 = MS(ads.ds_rxstatus0, AR_RxRSSIAnt00); - ds->ds_rxstat.rs_rssi_ctl1 = MS(ads.ds_rxstatus0, AR_RxRSSIAnt01); - ds->ds_rxstat.rs_rssi_ctl2 = MS(ads.ds_rxstatus0, AR_RxRSSIAnt02); - ds->ds_rxstat.rs_rssi_ext0 = MS(ads.ds_rxstatus4, AR_RxRSSIAnt10); - ds->ds_rxstat.rs_rssi_ext1 = MS(ads.ds_rxstatus4, AR_RxRSSIAnt11); - ds->ds_rxstat.rs_rssi_ext2 = MS(ads.ds_rxstatus4, AR_RxRSSIAnt12); + if (ads.ds_rxstatus8 & AR_PostDelimCRCErr) { + ds->ds_rxstat.rs_rssi = ATH9K_RSSI_BAD; + ds->ds_rxstat.rs_rssi_ctl0 = ATH9K_RSSI_BAD; + ds->ds_rxstat.rs_rssi_ctl1 = ATH9K_RSSI_BAD; + ds->ds_rxstat.rs_rssi_ctl2 = ATH9K_RSSI_BAD; + ds->ds_rxstat.rs_rssi_ext0 = ATH9K_RSSI_BAD; + ds->ds_rxstat.rs_rssi_ext1 = ATH9K_RSSI_BAD; + ds->ds_rxstat.rs_rssi_ext2 = ATH9K_RSSI_BAD; + } else { + ds->ds_rxstat.rs_rssi = MS(ads.ds_rxstatus4, AR_RxRSSICombined); + ds->ds_rxstat.rs_rssi_ctl0 = MS(ads.ds_rxstatus0, + AR_RxRSSIAnt00); + ds->ds_rxstat.rs_rssi_ctl1 = MS(ads.ds_rxstatus0, + AR_RxRSSIAnt01); + ds->ds_rxstat.rs_rssi_ctl2 = MS(ads.ds_rxstatus0, + AR_RxRSSIAnt02); + ds->ds_rxstat.rs_rssi_ext0 = MS(ads.ds_rxstatus4, + AR_RxRSSIAnt10); + ds->ds_rxstat.rs_rssi_ext1 = MS(ads.ds_rxstatus4, + AR_RxRSSIAnt11); + ds->ds_rxstat.rs_rssi_ext2 = MS(ads.ds_rxstatus4, + AR_RxRSSIAnt12); + } if (ads.ds_rxstatus8 & AR_RxKeyIdxValid) ds->ds_rxstat.rs_keyix = MS(ads.ds_rxstatus8, AR_KeyIdx); else |