aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorFelix Fietkau <nbd@openwrt.org>2010-10-15 14:03:30 -0400
committerJohn W. Linville <linville@tuxdriver.com>2010-11-09 16:13:24 -0500
commite0e9bc82fb0813fd353b0abbba0f1d6a680cc77c (patch)
treed81c63dd8cb99cc29a6f53f5b5fca1eea860ddc8 /drivers
parent45684c75f9aa80eb477465bddcf79c9ad95206c7 (diff)
ath9k_hw: optimize tx status descriptor processing
Disassembly shows, that at least on MIPS, the compiler generates a lot of memory accesses to the same location in the descriptor field parsing. Since it is operating on uncached memory, this can be quite expensive in this hot path. Change the code a bit to help the compiler optimize it properly, and get rid of some unused fields in the ath_tx_status struct. Signed-off-by: Felix Fietkau <nbd@openwrt.org> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9002_mac.c81
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_mac.c69
-rw-r--r--drivers/net/wireless/ath/ath9k/mac.h3
3 files changed, 72 insertions, 81 deletions
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_mac.c b/drivers/net/wireless/ath/ath9k/ar9002_mac.c
index f5ed73dac254..3b4c52c9181c 100644
--- a/drivers/net/wireless/ath/ath9k/ar9002_mac.c
+++ b/drivers/net/wireless/ath/ath9k/ar9002_mac.c
@@ -208,77 +208,68 @@ static int ar9002_hw_proc_txdesc(struct ath_hw *ah, void *ds,
208 struct ath_tx_status *ts) 208 struct ath_tx_status *ts)
209{ 209{
210 struct ar5416_desc *ads = AR5416DESC(ds); 210 struct ar5416_desc *ads = AR5416DESC(ds);
211 u32 status;
211 212
212 if ((ads->ds_txstatus9 & AR_TxDone) == 0) 213 status = ACCESS_ONCE(ads->ds_txstatus9);
214 if ((status & AR_TxDone) == 0)
213 return -EINPROGRESS; 215 return -EINPROGRESS;
214 216
215 ts->ts_seqnum = MS(ads->ds_txstatus9, AR_SeqNum);
216 ts->ts_tstamp = ads->AR_SendTimestamp; 217 ts->ts_tstamp = ads->AR_SendTimestamp;
217 ts->ts_status = 0; 218 ts->ts_status = 0;
218 ts->ts_flags = 0; 219 ts->ts_flags = 0;
219 220
220 if (ads->ds_txstatus1 & AR_FrmXmitOK) 221 if (status & AR_TxOpExceeded)
222 ts->ts_status |= ATH9K_TXERR_XTXOP;
223 ts->tid = MS(status, AR_TxTid);
224 ts->ts_rateindex = MS(status, AR_FinalTxIdx);
225 ts->ts_seqnum = MS(status, AR_SeqNum);
226
227 status = ACCESS_ONCE(ads->ds_txstatus0);
228 ts->ts_rssi_ctl0 = MS(status, AR_TxRSSIAnt00);
229 ts->ts_rssi_ctl1 = MS(status, AR_TxRSSIAnt01);
230 ts->ts_rssi_ctl2 = MS(status, AR_TxRSSIAnt02);
231 if (status & AR_TxBaStatus) {
232 ts->ts_flags |= ATH9K_TX_BA;
233 ts->ba_low = ads->AR_BaBitmapLow;
234 ts->ba_high = ads->AR_BaBitmapHigh;
235 }
236
237 status = ACCESS_ONCE(ads->ds_txstatus1);
238 if (status & AR_FrmXmitOK)
221 ts->ts_status |= ATH9K_TX_ACKED; 239 ts->ts_status |= ATH9K_TX_ACKED;
222 if (ads->ds_txstatus1 & AR_ExcessiveRetries) 240 if (status & AR_ExcessiveRetries)
223 ts->ts_status |= ATH9K_TXERR_XRETRY; 241 ts->ts_status |= ATH9K_TXERR_XRETRY;
224 if (ads->ds_txstatus1 & AR_Filtered) 242 if (status & AR_Filtered)
225 ts->ts_status |= ATH9K_TXERR_FILT; 243 ts->ts_status |= ATH9K_TXERR_FILT;
226 if (ads->ds_txstatus1 & AR_FIFOUnderrun) { 244 if (status & AR_FIFOUnderrun) {
227 ts->ts_status |= ATH9K_TXERR_FIFO; 245 ts->ts_status |= ATH9K_TXERR_FIFO;
228 ath9k_hw_updatetxtriglevel(ah, true); 246 ath9k_hw_updatetxtriglevel(ah, true);
229 } 247 }
230 if (ads->ds_txstatus9 & AR_TxOpExceeded) 248 if (status & AR_TxTimerExpired)
231 ts->ts_status |= ATH9K_TXERR_XTXOP;
232 if (ads->ds_txstatus1 & AR_TxTimerExpired)
233 ts->ts_status |= ATH9K_TXERR_TIMER_EXPIRED; 249 ts->ts_status |= ATH9K_TXERR_TIMER_EXPIRED;
234 250 if (status & AR_DescCfgErr)
235 if (ads->ds_txstatus1 & AR_DescCfgErr)
236 ts->ts_flags |= ATH9K_TX_DESC_CFG_ERR; 251 ts->ts_flags |= ATH9K_TX_DESC_CFG_ERR;
237 if (ads->ds_txstatus1 & AR_TxDataUnderrun) { 252 if (status & AR_TxDataUnderrun) {
238 ts->ts_flags |= ATH9K_TX_DATA_UNDERRUN; 253 ts->ts_flags |= ATH9K_TX_DATA_UNDERRUN;
239 ath9k_hw_updatetxtriglevel(ah, true); 254 ath9k_hw_updatetxtriglevel(ah, true);
240 } 255 }
241 if (ads->ds_txstatus1 & AR_TxDelimUnderrun) { 256 if (status & AR_TxDelimUnderrun) {
242 ts->ts_flags |= ATH9K_TX_DELIM_UNDERRUN; 257 ts->ts_flags |= ATH9K_TX_DELIM_UNDERRUN;
243 ath9k_hw_updatetxtriglevel(ah, true); 258 ath9k_hw_updatetxtriglevel(ah, true);
244 } 259 }
245 if (ads->ds_txstatus0 & AR_TxBaStatus) { 260 ts->ts_shortretry = MS(status, AR_RTSFailCnt);
246 ts->ts_flags |= ATH9K_TX_BA; 261 ts->ts_longretry = MS(status, AR_DataFailCnt);
247 ts->ba_low = ads->AR_BaBitmapLow; 262 ts->ts_virtcol = MS(status, AR_VirtRetryCnt);
248 ts->ba_high = ads->AR_BaBitmapHigh;
249 }
250 263
251 ts->ts_rateindex = MS(ads->ds_txstatus9, AR_FinalTxIdx); 264 status = ACCESS_ONCE(ads->ds_txstatus5);
252 switch (ts->ts_rateindex) { 265 ts->ts_rssi = MS(status, AR_TxRSSICombined);
253 case 0: 266 ts->ts_rssi_ext0 = MS(status, AR_TxRSSIAnt10);
254 ts->ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate0); 267 ts->ts_rssi_ext1 = MS(status, AR_TxRSSIAnt11);
255 break; 268 ts->ts_rssi_ext2 = MS(status, AR_TxRSSIAnt12);
256 case 1:
257 ts->ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate1);
258 break;
259 case 2:
260 ts->ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate2);
261 break;
262 case 3:
263 ts->ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate3);
264 break;
265 }
266 269
267 ts->ts_rssi = MS(ads->ds_txstatus5, AR_TxRSSICombined);
268 ts->ts_rssi_ctl0 = MS(ads->ds_txstatus0, AR_TxRSSIAnt00);
269 ts->ts_rssi_ctl1 = MS(ads->ds_txstatus0, AR_TxRSSIAnt01);
270 ts->ts_rssi_ctl2 = MS(ads->ds_txstatus0, AR_TxRSSIAnt02);
271 ts->ts_rssi_ext0 = MS(ads->ds_txstatus5, AR_TxRSSIAnt10);
272 ts->ts_rssi_ext1 = MS(ads->ds_txstatus5, AR_TxRSSIAnt11);
273 ts->ts_rssi_ext2 = MS(ads->ds_txstatus5, AR_TxRSSIAnt12);
274 ts->evm0 = ads->AR_TxEVM0; 270 ts->evm0 = ads->AR_TxEVM0;
275 ts->evm1 = ads->AR_TxEVM1; 271 ts->evm1 = ads->AR_TxEVM1;
276 ts->evm2 = ads->AR_TxEVM2; 272 ts->evm2 = ads->AR_TxEVM2;
277 ts->ts_shortretry = MS(ads->ds_txstatus1, AR_RTSFailCnt);
278 ts->ts_longretry = MS(ads->ds_txstatus1, AR_DataFailCnt);
279 ts->ts_virtcol = MS(ads->ds_txstatus1, AR_VirtRetryCnt);
280 ts->tid = MS(ads->ds_txstatus9, AR_TxTid);
281 ts->ts_antenna = 0;
282 273
283 return 0; 274 return 0;
284} 275}
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.c b/drivers/net/wireless/ath/ath9k/ar9003_mac.c
index 3b424ca1ba84..10c812e353a6 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c
@@ -237,10 +237,12 @@ static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds,
237 struct ath_tx_status *ts) 237 struct ath_tx_status *ts)
238{ 238{
239 struct ar9003_txs *ads; 239 struct ar9003_txs *ads;
240 u32 status;
240 241
241 ads = &ah->ts_ring[ah->ts_tail]; 242 ads = &ah->ts_ring[ah->ts_tail];
242 243
243 if ((ads->status8 & AR_TxDone) == 0) 244 status = ACCESS_ONCE(ads->status8);
245 if ((status & AR_TxDone) == 0)
244 return -EINPROGRESS; 246 return -EINPROGRESS;
245 247
246 ah->ts_tail = (ah->ts_tail + 1) % ah->ts_size; 248 ah->ts_tail = (ah->ts_tail + 1) % ah->ts_size;
@@ -253,57 +255,58 @@ static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds,
253 return -EIO; 255 return -EIO;
254 } 256 }
255 257
258 if (status & AR_TxOpExceeded)
259 ts->ts_status |= ATH9K_TXERR_XTXOP;
260 ts->ts_rateindex = MS(status, AR_FinalTxIdx);
261 ts->ts_seqnum = MS(status, AR_SeqNum);
262 ts->tid = MS(status, AR_TxTid);
263
256 ts->qid = MS(ads->ds_info, AR_TxQcuNum); 264 ts->qid = MS(ads->ds_info, AR_TxQcuNum);
257 ts->desc_id = MS(ads->status1, AR_TxDescId); 265 ts->desc_id = MS(ads->status1, AR_TxDescId);
258 ts->ts_seqnum = MS(ads->status8, AR_SeqNum);
259 ts->ts_tstamp = ads->status4; 266 ts->ts_tstamp = ads->status4;
260 ts->ts_status = 0; 267 ts->ts_status = 0;
261 ts->ts_flags = 0; 268 ts->ts_flags = 0;
262 269
263 if (ads->status3 & AR_ExcessiveRetries) 270 status = ACCESS_ONCE(ads->status2);
271 ts->ts_rssi_ctl0 = MS(status, AR_TxRSSIAnt00);
272 ts->ts_rssi_ctl1 = MS(status, AR_TxRSSIAnt01);
273 ts->ts_rssi_ctl2 = MS(status, AR_TxRSSIAnt02);
274 if (status & AR_TxBaStatus) {
275 ts->ts_flags |= ATH9K_TX_BA;
276 ts->ba_low = ads->status5;
277 ts->ba_high = ads->status6;
278 }
279
280 status = ACCESS_ONCE(ads->status3);
281 if (status & AR_ExcessiveRetries)
264 ts->ts_status |= ATH9K_TXERR_XRETRY; 282 ts->ts_status |= ATH9K_TXERR_XRETRY;
265 if (ads->status3 & AR_Filtered) 283 if (status & AR_Filtered)
266 ts->ts_status |= ATH9K_TXERR_FILT; 284 ts->ts_status |= ATH9K_TXERR_FILT;
267 if (ads->status3 & AR_FIFOUnderrun) { 285 if (status & AR_FIFOUnderrun) {
268 ts->ts_status |= ATH9K_TXERR_FIFO; 286 ts->ts_status |= ATH9K_TXERR_FIFO;
269 ath9k_hw_updatetxtriglevel(ah, true); 287 ath9k_hw_updatetxtriglevel(ah, true);
270 } 288 }
271 if (ads->status8 & AR_TxOpExceeded) 289 if (status & AR_TxTimerExpired)
272 ts->ts_status |= ATH9K_TXERR_XTXOP;
273 if (ads->status3 & AR_TxTimerExpired)
274 ts->ts_status |= ATH9K_TXERR_TIMER_EXPIRED; 290 ts->ts_status |= ATH9K_TXERR_TIMER_EXPIRED;
275 291 if (status & AR_DescCfgErr)
276 if (ads->status3 & AR_DescCfgErr)
277 ts->ts_flags |= ATH9K_TX_DESC_CFG_ERR; 292 ts->ts_flags |= ATH9K_TX_DESC_CFG_ERR;
278 if (ads->status3 & AR_TxDataUnderrun) { 293 if (status & AR_TxDataUnderrun) {
279 ts->ts_flags |= ATH9K_TX_DATA_UNDERRUN; 294 ts->ts_flags |= ATH9K_TX_DATA_UNDERRUN;
280 ath9k_hw_updatetxtriglevel(ah, true); 295 ath9k_hw_updatetxtriglevel(ah, true);
281 } 296 }
282 if (ads->status3 & AR_TxDelimUnderrun) { 297 if (status & AR_TxDelimUnderrun) {
283 ts->ts_flags |= ATH9K_TX_DELIM_UNDERRUN; 298 ts->ts_flags |= ATH9K_TX_DELIM_UNDERRUN;
284 ath9k_hw_updatetxtriglevel(ah, true); 299 ath9k_hw_updatetxtriglevel(ah, true);
285 } 300 }
286 if (ads->status2 & AR_TxBaStatus) { 301 ts->ts_shortretry = MS(status, AR_RTSFailCnt);
287 ts->ts_flags |= ATH9K_TX_BA; 302 ts->ts_longretry = MS(status, AR_DataFailCnt);
288 ts->ba_low = ads->status5; 303 ts->ts_virtcol = MS(status, AR_VirtRetryCnt);
289 ts->ba_high = ads->status6; 304
290 } 305 status = ACCESS_ONCE(ads->status7);
291 306 ts->ts_rssi = MS(status, AR_TxRSSICombined);
292 ts->ts_rateindex = MS(ads->status8, AR_FinalTxIdx); 307 ts->ts_rssi_ext0 = MS(status, AR_TxRSSIAnt10);
293 308 ts->ts_rssi_ext1 = MS(status, AR_TxRSSIAnt11);
294 ts->ts_rssi = MS(ads->status7, AR_TxRSSICombined); 309 ts->ts_rssi_ext2 = MS(status, AR_TxRSSIAnt12);
295 ts->ts_rssi_ctl0 = MS(ads->status2, AR_TxRSSIAnt00);
296 ts->ts_rssi_ctl1 = MS(ads->status2, AR_TxRSSIAnt01);
297 ts->ts_rssi_ctl2 = MS(ads->status2, AR_TxRSSIAnt02);
298 ts->ts_rssi_ext0 = MS(ads->status7, AR_TxRSSIAnt10);
299 ts->ts_rssi_ext1 = MS(ads->status7, AR_TxRSSIAnt11);
300 ts->ts_rssi_ext2 = MS(ads->status7, AR_TxRSSIAnt12);
301 ts->ts_shortretry = MS(ads->status3, AR_RTSFailCnt);
302 ts->ts_longretry = MS(ads->status3, AR_DataFailCnt);
303 ts->ts_virtcol = MS(ads->status3, AR_VirtRetryCnt);
304 ts->ts_antenna = 0;
305
306 ts->tid = MS(ads->status8, AR_TxTid);
307 310
308 memset(ads, 0, sizeof(*ads)); 311 memset(ads, 0, sizeof(*ads));
309 312
diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h
index 538c676e799c..fdc25074ca1f 100644
--- a/drivers/net/wireless/ath/ath9k/mac.h
+++ b/drivers/net/wireless/ath/ath9k/mac.h
@@ -104,13 +104,11 @@ struct ath_tx_status {
104 u32 ts_tstamp; 104 u32 ts_tstamp;
105 u16 ts_seqnum; 105 u16 ts_seqnum;
106 u8 ts_status; 106 u8 ts_status;
107 u8 ts_ratecode;
108 u8 ts_rateindex; 107 u8 ts_rateindex;
109 int8_t ts_rssi; 108 int8_t ts_rssi;
110 u8 ts_shortretry; 109 u8 ts_shortretry;
111 u8 ts_longretry; 110 u8 ts_longretry;
112 u8 ts_virtcol; 111 u8 ts_virtcol;
113 u8 ts_antenna;
114 u8 ts_flags; 112 u8 ts_flags;
115 int8_t ts_rssi_ctl0; 113 int8_t ts_rssi_ctl0;
116 int8_t ts_rssi_ctl1; 114 int8_t ts_rssi_ctl1;
@@ -121,7 +119,6 @@ struct ath_tx_status {
121 u8 qid; 119 u8 qid;
122 u16 desc_id; 120 u16 desc_id;
123 u8 tid; 121 u8 tid;
124 u8 pad[2];
125 u32 ba_low; 122 u32 ba_low;
126 u32 ba_high; 123 u32 ba_high;
127 u32 evm0; 124 u32 evm0;