diff options
author | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
---|---|---|
committer | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
commit | ada47b5fe13d89735805b566185f4885f5a3f750 (patch) | |
tree | 644b88f8a71896307d71438e9b3af49126ffb22b /drivers/net/wireless/ath/ath9k/mac.c | |
parent | 43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff) | |
parent | 3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff) |
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/mac.c')
-rw-r--r-- | drivers/net/wireless/ath/ath9k/mac.c | 200 |
1 files changed, 142 insertions, 58 deletions
diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c index 800bfab94635..efc420cd42bf 100644 --- a/drivers/net/wireless/ath/ath9k/mac.c +++ b/drivers/net/wireless/ath/ath9k/mac.c | |||
@@ -14,16 +14,16 @@ | |||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include "ath9k.h" | 17 | #include "hw.h" |
18 | 18 | ||
19 | static void ath9k_hw_set_txq_interrupts(struct ath_hw *ah, | 19 | static void ath9k_hw_set_txq_interrupts(struct ath_hw *ah, |
20 | struct ath9k_tx_queue_info *qi) | 20 | struct ath9k_tx_queue_info *qi) |
21 | { | 21 | { |
22 | DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT, | 22 | ath_print(ath9k_hw_common(ah), ATH_DBG_INTERRUPT, |
23 | "tx ok 0x%x err 0x%x desc 0x%x eol 0x%x urn 0x%x\n", | 23 | "tx ok 0x%x err 0x%x desc 0x%x eol 0x%x urn 0x%x\n", |
24 | ah->txok_interrupt_mask, ah->txerr_interrupt_mask, | 24 | ah->txok_interrupt_mask, ah->txerr_interrupt_mask, |
25 | ah->txdesc_interrupt_mask, ah->txeol_interrupt_mask, | 25 | ah->txdesc_interrupt_mask, ah->txeol_interrupt_mask, |
26 | ah->txurn_interrupt_mask); | 26 | ah->txurn_interrupt_mask); |
27 | 27 | ||
28 | REG_WRITE(ah, AR_IMR_S0, | 28 | REG_WRITE(ah, AR_IMR_S0, |
29 | SM(ah->txok_interrupt_mask, AR_IMR_S0_QCU_TXOK) | 29 | SM(ah->txok_interrupt_mask, AR_IMR_S0_QCU_TXOK) |
@@ -39,17 +39,21 @@ u32 ath9k_hw_gettxbuf(struct ath_hw *ah, u32 q) | |||
39 | { | 39 | { |
40 | return REG_READ(ah, AR_QTXDP(q)); | 40 | return REG_READ(ah, AR_QTXDP(q)); |
41 | } | 41 | } |
42 | EXPORT_SYMBOL(ath9k_hw_gettxbuf); | ||
42 | 43 | ||
43 | void ath9k_hw_puttxbuf(struct ath_hw *ah, u32 q, u32 txdp) | 44 | void ath9k_hw_puttxbuf(struct ath_hw *ah, u32 q, u32 txdp) |
44 | { | 45 | { |
45 | REG_WRITE(ah, AR_QTXDP(q), txdp); | 46 | REG_WRITE(ah, AR_QTXDP(q), txdp); |
46 | } | 47 | } |
48 | EXPORT_SYMBOL(ath9k_hw_puttxbuf); | ||
47 | 49 | ||
48 | void ath9k_hw_txstart(struct ath_hw *ah, u32 q) | 50 | void ath9k_hw_txstart(struct ath_hw *ah, u32 q) |
49 | { | 51 | { |
50 | DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Enable TXE on queue: %u\n", q); | 52 | ath_print(ath9k_hw_common(ah), ATH_DBG_QUEUE, |
53 | "Enable TXE on queue: %u\n", q); | ||
51 | REG_WRITE(ah, AR_Q_TXE, 1 << q); | 54 | REG_WRITE(ah, AR_Q_TXE, 1 << q); |
52 | } | 55 | } |
56 | EXPORT_SYMBOL(ath9k_hw_txstart); | ||
53 | 57 | ||
54 | u32 ath9k_hw_numtxpending(struct ath_hw *ah, u32 q) | 58 | u32 ath9k_hw_numtxpending(struct ath_hw *ah, u32 q) |
55 | { | 59 | { |
@@ -64,13 +68,39 @@ u32 ath9k_hw_numtxpending(struct ath_hw *ah, u32 q) | |||
64 | 68 | ||
65 | return npend; | 69 | return npend; |
66 | } | 70 | } |
71 | EXPORT_SYMBOL(ath9k_hw_numtxpending); | ||
67 | 72 | ||
73 | /** | ||
74 | * ath9k_hw_updatetxtriglevel - adjusts the frame trigger level | ||
75 | * | ||
76 | * @ah: atheros hardware struct | ||
77 | * @bIncTrigLevel: whether or not the frame trigger level should be updated | ||
78 | * | ||
79 | * The frame trigger level specifies the minimum number of bytes, | ||
80 | * in units of 64 bytes, that must be DMA'ed into the PCU TX FIFO | ||
81 | * before the PCU will initiate sending the frame on the air. This can | ||
82 | * mean we initiate transmit before a full frame is on the PCU TX FIFO. | ||
83 | * Resets to 0x1 (meaning 64 bytes or a full frame, whichever occurs | ||
84 | * first) | ||
85 | * | ||
86 | * Caution must be taken to ensure to set the frame trigger level based | ||
87 | * on the DMA request size. For example if the DMA request size is set to | ||
88 | * 128 bytes the trigger level cannot exceed 6 * 64 = 384. This is because | ||
89 | * there need to be enough space in the tx FIFO for the requested transfer | ||
90 | * size. Hence the tx FIFO will stop with 512 - 128 = 384 bytes. If we set | ||
91 | * the threshold to a value beyond 6, then the transmit will hang. | ||
92 | * | ||
93 | * Current dual stream devices have a PCU TX FIFO size of 8 KB. | ||
94 | * Current single stream devices have a PCU TX FIFO size of 4 KB, however, | ||
95 | * there is a hardware issue which forces us to use 2 KB instead so the | ||
96 | * frame trigger level must not exceed 2 KB for these chipsets. | ||
97 | */ | ||
68 | bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel) | 98 | bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel) |
69 | { | 99 | { |
70 | u32 txcfg, curLevel, newLevel; | 100 | u32 txcfg, curLevel, newLevel; |
71 | enum ath9k_int omask; | 101 | enum ath9k_int omask; |
72 | 102 | ||
73 | if (ah->tx_trig_level >= MAX_TX_FIFO_THRESHOLD) | 103 | if (ah->tx_trig_level >= ah->config.max_txtrig_level) |
74 | return false; | 104 | return false; |
75 | 105 | ||
76 | omask = ath9k_hw_set_interrupts(ah, ah->mask_reg & ~ATH9K_INT_GLOBAL); | 106 | omask = ath9k_hw_set_interrupts(ah, ah->mask_reg & ~ATH9K_INT_GLOBAL); |
@@ -79,7 +109,7 @@ bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel) | |||
79 | curLevel = MS(txcfg, AR_FTRIG); | 109 | curLevel = MS(txcfg, AR_FTRIG); |
80 | newLevel = curLevel; | 110 | newLevel = curLevel; |
81 | if (bIncTrigLevel) { | 111 | if (bIncTrigLevel) { |
82 | if (curLevel < MAX_TX_FIFO_THRESHOLD) | 112 | if (curLevel < ah->config.max_txtrig_level) |
83 | newLevel++; | 113 | newLevel++; |
84 | } else if (curLevel > MIN_TX_FIFO_THRESHOLD) | 114 | } else if (curLevel > MIN_TX_FIFO_THRESHOLD) |
85 | newLevel--; | 115 | newLevel--; |
@@ -93,27 +123,28 @@ bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel) | |||
93 | 123 | ||
94 | return newLevel != curLevel; | 124 | return newLevel != curLevel; |
95 | } | 125 | } |
126 | EXPORT_SYMBOL(ath9k_hw_updatetxtriglevel); | ||
96 | 127 | ||
97 | bool ath9k_hw_stoptxdma(struct ath_hw *ah, u32 q) | 128 | bool ath9k_hw_stoptxdma(struct ath_hw *ah, u32 q) |
98 | { | 129 | { |
99 | #define ATH9K_TX_STOP_DMA_TIMEOUT 4000 /* usec */ | 130 | #define ATH9K_TX_STOP_DMA_TIMEOUT 4000 /* usec */ |
100 | #define ATH9K_TIME_QUANTUM 100 /* usec */ | 131 | #define ATH9K_TIME_QUANTUM 100 /* usec */ |
101 | 132 | struct ath_common *common = ath9k_hw_common(ah); | |
102 | struct ath9k_hw_capabilities *pCap = &ah->caps; | 133 | struct ath9k_hw_capabilities *pCap = &ah->caps; |
103 | struct ath9k_tx_queue_info *qi; | 134 | struct ath9k_tx_queue_info *qi; |
104 | u32 tsfLow, j, wait; | 135 | u32 tsfLow, j, wait; |
105 | u32 wait_time = ATH9K_TX_STOP_DMA_TIMEOUT / ATH9K_TIME_QUANTUM; | 136 | u32 wait_time = ATH9K_TX_STOP_DMA_TIMEOUT / ATH9K_TIME_QUANTUM; |
106 | 137 | ||
107 | if (q >= pCap->total_queues) { | 138 | if (q >= pCap->total_queues) { |
108 | DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Stopping TX DMA, " | 139 | ath_print(common, ATH_DBG_QUEUE, "Stopping TX DMA, " |
109 | "invalid queue: %u\n", q); | 140 | "invalid queue: %u\n", q); |
110 | return false; | 141 | return false; |
111 | } | 142 | } |
112 | 143 | ||
113 | qi = &ah->txq[q]; | 144 | qi = &ah->txq[q]; |
114 | if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) { | 145 | if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) { |
115 | DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Stopping TX DMA, " | 146 | ath_print(common, ATH_DBG_QUEUE, "Stopping TX DMA, " |
116 | "inactive queue: %u\n", q); | 147 | "inactive queue: %u\n", q); |
117 | return false; | 148 | return false; |
118 | } | 149 | } |
119 | 150 | ||
@@ -126,9 +157,9 @@ bool ath9k_hw_stoptxdma(struct ath_hw *ah, u32 q) | |||
126 | } | 157 | } |
127 | 158 | ||
128 | if (ath9k_hw_numtxpending(ah, q)) { | 159 | if (ath9k_hw_numtxpending(ah, q)) { |
129 | DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, | 160 | ath_print(common, ATH_DBG_QUEUE, |
130 | "%s: Num of pending TX Frames %d on Q %d\n", | 161 | "%s: Num of pending TX Frames %d on Q %d\n", |
131 | __func__, ath9k_hw_numtxpending(ah, q), q); | 162 | __func__, ath9k_hw_numtxpending(ah, q), q); |
132 | 163 | ||
133 | for (j = 0; j < 2; j++) { | 164 | for (j = 0; j < 2; j++) { |
134 | tsfLow = REG_READ(ah, AR_TSF_L32); | 165 | tsfLow = REG_READ(ah, AR_TSF_L32); |
@@ -142,9 +173,9 @@ bool ath9k_hw_stoptxdma(struct ath_hw *ah, u32 q) | |||
142 | if ((REG_READ(ah, AR_TSF_L32) >> 10) == (tsfLow >> 10)) | 173 | if ((REG_READ(ah, AR_TSF_L32) >> 10) == (tsfLow >> 10)) |
143 | break; | 174 | break; |
144 | 175 | ||
145 | DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, | 176 | ath_print(common, ATH_DBG_QUEUE, |
146 | "TSF has moved while trying to set " | 177 | "TSF has moved while trying to set " |
147 | "quiet time TSF: 0x%08x\n", tsfLow); | 178 | "quiet time TSF: 0x%08x\n", tsfLow); |
148 | } | 179 | } |
149 | 180 | ||
150 | REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH); | 181 | REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH); |
@@ -155,9 +186,9 @@ bool ath9k_hw_stoptxdma(struct ath_hw *ah, u32 q) | |||
155 | wait = wait_time; | 186 | wait = wait_time; |
156 | while (ath9k_hw_numtxpending(ah, q)) { | 187 | while (ath9k_hw_numtxpending(ah, q)) { |
157 | if ((--wait) == 0) { | 188 | if ((--wait) == 0) { |
158 | DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, | 189 | ath_print(common, ATH_DBG_FATAL, |
159 | "Failed to stop TX DMA in 100 " | 190 | "Failed to stop TX DMA in 100 " |
160 | "msec after killing last frame\n"); | 191 | "msec after killing last frame\n"); |
161 | break; | 192 | break; |
162 | } | 193 | } |
163 | udelay(ATH9K_TIME_QUANTUM); | 194 | udelay(ATH9K_TIME_QUANTUM); |
@@ -172,6 +203,7 @@ bool ath9k_hw_stoptxdma(struct ath_hw *ah, u32 q) | |||
172 | #undef ATH9K_TX_STOP_DMA_TIMEOUT | 203 | #undef ATH9K_TX_STOP_DMA_TIMEOUT |
173 | #undef ATH9K_TIME_QUANTUM | 204 | #undef ATH9K_TIME_QUANTUM |
174 | } | 205 | } |
206 | EXPORT_SYMBOL(ath9k_hw_stoptxdma); | ||
175 | 207 | ||
176 | void ath9k_hw_filltxdesc(struct ath_hw *ah, struct ath_desc *ds, | 208 | void ath9k_hw_filltxdesc(struct ath_hw *ah, struct ath_desc *ds, |
177 | u32 segLen, bool firstSeg, | 209 | u32 segLen, bool firstSeg, |
@@ -198,6 +230,7 @@ void ath9k_hw_filltxdesc(struct ath_hw *ah, struct ath_desc *ds, | |||
198 | ads->ds_txstatus6 = ads->ds_txstatus7 = 0; | 230 | ads->ds_txstatus6 = ads->ds_txstatus7 = 0; |
199 | ads->ds_txstatus8 = ads->ds_txstatus9 = 0; | 231 | ads->ds_txstatus8 = ads->ds_txstatus9 = 0; |
200 | } | 232 | } |
233 | EXPORT_SYMBOL(ath9k_hw_filltxdesc); | ||
201 | 234 | ||
202 | void ath9k_hw_cleartxdesc(struct ath_hw *ah, struct ath_desc *ds) | 235 | void ath9k_hw_cleartxdesc(struct ath_hw *ah, struct ath_desc *ds) |
203 | { | 236 | { |
@@ -209,6 +242,7 @@ void ath9k_hw_cleartxdesc(struct ath_hw *ah, struct ath_desc *ds) | |||
209 | ads->ds_txstatus6 = ads->ds_txstatus7 = 0; | 242 | ads->ds_txstatus6 = ads->ds_txstatus7 = 0; |
210 | ads->ds_txstatus8 = ads->ds_txstatus9 = 0; | 243 | ads->ds_txstatus8 = ads->ds_txstatus9 = 0; |
211 | } | 244 | } |
245 | EXPORT_SYMBOL(ath9k_hw_cleartxdesc); | ||
212 | 246 | ||
213 | int ath9k_hw_txprocdesc(struct ath_hw *ah, struct ath_desc *ds) | 247 | int ath9k_hw_txprocdesc(struct ath_hw *ah, struct ath_desc *ds) |
214 | { | 248 | { |
@@ -222,6 +256,8 @@ int ath9k_hw_txprocdesc(struct ath_hw *ah, struct ath_desc *ds) | |||
222 | ds->ds_txstat.ts_status = 0; | 256 | ds->ds_txstat.ts_status = 0; |
223 | ds->ds_txstat.ts_flags = 0; | 257 | ds->ds_txstat.ts_flags = 0; |
224 | 258 | ||
259 | if (ads->ds_txstatus1 & AR_FrmXmitOK) | ||
260 | ds->ds_txstat.ts_status |= ATH9K_TX_ACKED; | ||
225 | if (ads->ds_txstatus1 & AR_ExcessiveRetries) | 261 | if (ads->ds_txstatus1 & AR_ExcessiveRetries) |
226 | ds->ds_txstat.ts_status |= ATH9K_TXERR_XRETRY; | 262 | ds->ds_txstat.ts_status |= ATH9K_TXERR_XRETRY; |
227 | if (ads->ds_txstatus1 & AR_Filtered) | 263 | if (ads->ds_txstatus1 & AR_Filtered) |
@@ -284,6 +320,7 @@ int ath9k_hw_txprocdesc(struct ath_hw *ah, struct ath_desc *ds) | |||
284 | 320 | ||
285 | return 0; | 321 | return 0; |
286 | } | 322 | } |
323 | EXPORT_SYMBOL(ath9k_hw_txprocdesc); | ||
287 | 324 | ||
288 | void ath9k_hw_set11n_txdesc(struct ath_hw *ah, struct ath_desc *ds, | 325 | void ath9k_hw_set11n_txdesc(struct ath_hw *ah, struct ath_desc *ds, |
289 | u32 pktLen, enum ath9k_pkt_type type, u32 txPower, | 326 | u32 pktLen, enum ath9k_pkt_type type, u32 txPower, |
@@ -319,6 +356,7 @@ void ath9k_hw_set11n_txdesc(struct ath_hw *ah, struct ath_desc *ds, | |||
319 | ads->ds_ctl11 = 0; | 356 | ads->ds_ctl11 = 0; |
320 | } | 357 | } |
321 | } | 358 | } |
359 | EXPORT_SYMBOL(ath9k_hw_set11n_txdesc); | ||
322 | 360 | ||
323 | void ath9k_hw_set11n_ratescenario(struct ath_hw *ah, struct ath_desc *ds, | 361 | void ath9k_hw_set11n_ratescenario(struct ath_hw *ah, struct ath_desc *ds, |
324 | struct ath_desc *lastds, | 362 | struct ath_desc *lastds, |
@@ -374,6 +412,7 @@ void ath9k_hw_set11n_ratescenario(struct ath_hw *ah, struct ath_desc *ds, | |||
374 | last_ads->ds_ctl2 = ads->ds_ctl2; | 412 | last_ads->ds_ctl2 = ads->ds_ctl2; |
375 | last_ads->ds_ctl3 = ads->ds_ctl3; | 413 | last_ads->ds_ctl3 = ads->ds_ctl3; |
376 | } | 414 | } |
415 | EXPORT_SYMBOL(ath9k_hw_set11n_ratescenario); | ||
377 | 416 | ||
378 | void ath9k_hw_set11n_aggr_first(struct ath_hw *ah, struct ath_desc *ds, | 417 | void ath9k_hw_set11n_aggr_first(struct ath_hw *ah, struct ath_desc *ds, |
379 | u32 aggrLen) | 418 | u32 aggrLen) |
@@ -384,6 +423,7 @@ void ath9k_hw_set11n_aggr_first(struct ath_hw *ah, struct ath_desc *ds, | |||
384 | ads->ds_ctl6 &= ~AR_AggrLen; | 423 | ads->ds_ctl6 &= ~AR_AggrLen; |
385 | ads->ds_ctl6 |= SM(aggrLen, AR_AggrLen); | 424 | ads->ds_ctl6 |= SM(aggrLen, AR_AggrLen); |
386 | } | 425 | } |
426 | EXPORT_SYMBOL(ath9k_hw_set11n_aggr_first); | ||
387 | 427 | ||
388 | void ath9k_hw_set11n_aggr_middle(struct ath_hw *ah, struct ath_desc *ds, | 428 | void ath9k_hw_set11n_aggr_middle(struct ath_hw *ah, struct ath_desc *ds, |
389 | u32 numDelims) | 429 | u32 numDelims) |
@@ -398,6 +438,7 @@ void ath9k_hw_set11n_aggr_middle(struct ath_hw *ah, struct ath_desc *ds, | |||
398 | ctl6 |= SM(numDelims, AR_PadDelim); | 438 | ctl6 |= SM(numDelims, AR_PadDelim); |
399 | ads->ds_ctl6 = ctl6; | 439 | ads->ds_ctl6 = ctl6; |
400 | } | 440 | } |
441 | EXPORT_SYMBOL(ath9k_hw_set11n_aggr_middle); | ||
401 | 442 | ||
402 | void ath9k_hw_set11n_aggr_last(struct ath_hw *ah, struct ath_desc *ds) | 443 | void ath9k_hw_set11n_aggr_last(struct ath_hw *ah, struct ath_desc *ds) |
403 | { | 444 | { |
@@ -407,6 +448,7 @@ void ath9k_hw_set11n_aggr_last(struct ath_hw *ah, struct ath_desc *ds) | |||
407 | ads->ds_ctl1 &= ~AR_MoreAggr; | 448 | ads->ds_ctl1 &= ~AR_MoreAggr; |
408 | ads->ds_ctl6 &= ~AR_PadDelim; | 449 | ads->ds_ctl6 &= ~AR_PadDelim; |
409 | } | 450 | } |
451 | EXPORT_SYMBOL(ath9k_hw_set11n_aggr_last); | ||
410 | 452 | ||
411 | void ath9k_hw_clr11n_aggr(struct ath_hw *ah, struct ath_desc *ds) | 453 | void ath9k_hw_clr11n_aggr(struct ath_hw *ah, struct ath_desc *ds) |
412 | { | 454 | { |
@@ -414,6 +456,7 @@ void ath9k_hw_clr11n_aggr(struct ath_hw *ah, struct ath_desc *ds) | |||
414 | 456 | ||
415 | ads->ds_ctl1 &= (~AR_IsAggr & ~AR_MoreAggr); | 457 | ads->ds_ctl1 &= (~AR_IsAggr & ~AR_MoreAggr); |
416 | } | 458 | } |
459 | EXPORT_SYMBOL(ath9k_hw_clr11n_aggr); | ||
417 | 460 | ||
418 | void ath9k_hw_set11n_burstduration(struct ath_hw *ah, struct ath_desc *ds, | 461 | void ath9k_hw_set11n_burstduration(struct ath_hw *ah, struct ath_desc *ds, |
419 | u32 burstDuration) | 462 | u32 burstDuration) |
@@ -423,6 +466,7 @@ void ath9k_hw_set11n_burstduration(struct ath_hw *ah, struct ath_desc *ds, | |||
423 | ads->ds_ctl2 &= ~AR_BurstDur; | 466 | ads->ds_ctl2 &= ~AR_BurstDur; |
424 | ads->ds_ctl2 |= SM(burstDuration, AR_BurstDur); | 467 | ads->ds_ctl2 |= SM(burstDuration, AR_BurstDur); |
425 | } | 468 | } |
469 | EXPORT_SYMBOL(ath9k_hw_set11n_burstduration); | ||
426 | 470 | ||
427 | void ath9k_hw_set11n_virtualmorefrag(struct ath_hw *ah, struct ath_desc *ds, | 471 | void ath9k_hw_set11n_virtualmorefrag(struct ath_hw *ah, struct ath_desc *ds, |
428 | u32 vmf) | 472 | u32 vmf) |
@@ -440,28 +484,30 @@ void ath9k_hw_gettxintrtxqs(struct ath_hw *ah, u32 *txqs) | |||
440 | *txqs &= ah->intr_txqs; | 484 | *txqs &= ah->intr_txqs; |
441 | ah->intr_txqs &= ~(*txqs); | 485 | ah->intr_txqs &= ~(*txqs); |
442 | } | 486 | } |
487 | EXPORT_SYMBOL(ath9k_hw_gettxintrtxqs); | ||
443 | 488 | ||
444 | bool ath9k_hw_set_txq_props(struct ath_hw *ah, int q, | 489 | bool ath9k_hw_set_txq_props(struct ath_hw *ah, int q, |
445 | const struct ath9k_tx_queue_info *qinfo) | 490 | const struct ath9k_tx_queue_info *qinfo) |
446 | { | 491 | { |
447 | u32 cw; | 492 | u32 cw; |
493 | struct ath_common *common = ath9k_hw_common(ah); | ||
448 | struct ath9k_hw_capabilities *pCap = &ah->caps; | 494 | struct ath9k_hw_capabilities *pCap = &ah->caps; |
449 | struct ath9k_tx_queue_info *qi; | 495 | struct ath9k_tx_queue_info *qi; |
450 | 496 | ||
451 | if (q >= pCap->total_queues) { | 497 | if (q >= pCap->total_queues) { |
452 | DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Set TXQ properties, " | 498 | ath_print(common, ATH_DBG_QUEUE, "Set TXQ properties, " |
453 | "invalid queue: %u\n", q); | 499 | "invalid queue: %u\n", q); |
454 | return false; | 500 | return false; |
455 | } | 501 | } |
456 | 502 | ||
457 | qi = &ah->txq[q]; | 503 | qi = &ah->txq[q]; |
458 | if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) { | 504 | if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) { |
459 | DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Set TXQ properties, " | 505 | ath_print(common, ATH_DBG_QUEUE, "Set TXQ properties, " |
460 | "inactive queue: %u\n", q); | 506 | "inactive queue: %u\n", q); |
461 | return false; | 507 | return false; |
462 | } | 508 | } |
463 | 509 | ||
464 | DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Set queue properties for: %u\n", q); | 510 | ath_print(common, ATH_DBG_QUEUE, "Set queue properties for: %u\n", q); |
465 | 511 | ||
466 | qi->tqi_ver = qinfo->tqi_ver; | 512 | qi->tqi_ver = qinfo->tqi_ver; |
467 | qi->tqi_subtype = qinfo->tqi_subtype; | 513 | qi->tqi_subtype = qinfo->tqi_subtype; |
@@ -510,23 +556,25 @@ bool ath9k_hw_set_txq_props(struct ath_hw *ah, int q, | |||
510 | 556 | ||
511 | return true; | 557 | return true; |
512 | } | 558 | } |
559 | EXPORT_SYMBOL(ath9k_hw_set_txq_props); | ||
513 | 560 | ||
514 | bool ath9k_hw_get_txq_props(struct ath_hw *ah, int q, | 561 | bool ath9k_hw_get_txq_props(struct ath_hw *ah, int q, |
515 | struct ath9k_tx_queue_info *qinfo) | 562 | struct ath9k_tx_queue_info *qinfo) |
516 | { | 563 | { |
564 | struct ath_common *common = ath9k_hw_common(ah); | ||
517 | struct ath9k_hw_capabilities *pCap = &ah->caps; | 565 | struct ath9k_hw_capabilities *pCap = &ah->caps; |
518 | struct ath9k_tx_queue_info *qi; | 566 | struct ath9k_tx_queue_info *qi; |
519 | 567 | ||
520 | if (q >= pCap->total_queues) { | 568 | if (q >= pCap->total_queues) { |
521 | DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Get TXQ properties, " | 569 | ath_print(common, ATH_DBG_QUEUE, "Get TXQ properties, " |
522 | "invalid queue: %u\n", q); | 570 | "invalid queue: %u\n", q); |
523 | return false; | 571 | return false; |
524 | } | 572 | } |
525 | 573 | ||
526 | qi = &ah->txq[q]; | 574 | qi = &ah->txq[q]; |
527 | if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) { | 575 | if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) { |
528 | DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Get TXQ properties, " | 576 | ath_print(common, ATH_DBG_QUEUE, "Get TXQ properties, " |
529 | "inactive queue: %u\n", q); | 577 | "inactive queue: %u\n", q); |
530 | return false; | 578 | return false; |
531 | } | 579 | } |
532 | 580 | ||
@@ -547,10 +595,12 @@ bool ath9k_hw_get_txq_props(struct ath_hw *ah, int q, | |||
547 | 595 | ||
548 | return true; | 596 | return true; |
549 | } | 597 | } |
598 | EXPORT_SYMBOL(ath9k_hw_get_txq_props); | ||
550 | 599 | ||
551 | int ath9k_hw_setuptxqueue(struct ath_hw *ah, enum ath9k_tx_queue type, | 600 | int ath9k_hw_setuptxqueue(struct ath_hw *ah, enum ath9k_tx_queue type, |
552 | const struct ath9k_tx_queue_info *qinfo) | 601 | const struct ath9k_tx_queue_info *qinfo) |
553 | { | 602 | { |
603 | struct ath_common *common = ath9k_hw_common(ah); | ||
554 | struct ath9k_tx_queue_info *qi; | 604 | struct ath9k_tx_queue_info *qi; |
555 | struct ath9k_hw_capabilities *pCap = &ah->caps; | 605 | struct ath9k_hw_capabilities *pCap = &ah->caps; |
556 | int q; | 606 | int q; |
@@ -574,23 +624,23 @@ int ath9k_hw_setuptxqueue(struct ath_hw *ah, enum ath9k_tx_queue type, | |||
574 | ATH9K_TX_QUEUE_INACTIVE) | 624 | ATH9K_TX_QUEUE_INACTIVE) |
575 | break; | 625 | break; |
576 | if (q == pCap->total_queues) { | 626 | if (q == pCap->total_queues) { |
577 | DPRINTF(ah->ah_sc, ATH_DBG_FATAL, | 627 | ath_print(common, ATH_DBG_FATAL, |
578 | "No available TX queue\n"); | 628 | "No available TX queue\n"); |
579 | return -1; | 629 | return -1; |
580 | } | 630 | } |
581 | break; | 631 | break; |
582 | default: | 632 | default: |
583 | DPRINTF(ah->ah_sc, ATH_DBG_FATAL, "Invalid TX queue type: %u\n", | 633 | ath_print(common, ATH_DBG_FATAL, |
584 | type); | 634 | "Invalid TX queue type: %u\n", type); |
585 | return -1; | 635 | return -1; |
586 | } | 636 | } |
587 | 637 | ||
588 | DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Setup TX queue: %u\n", q); | 638 | ath_print(common, ATH_DBG_QUEUE, "Setup TX queue: %u\n", q); |
589 | 639 | ||
590 | qi = &ah->txq[q]; | 640 | qi = &ah->txq[q]; |
591 | if (qi->tqi_type != ATH9K_TX_QUEUE_INACTIVE) { | 641 | if (qi->tqi_type != ATH9K_TX_QUEUE_INACTIVE) { |
592 | DPRINTF(ah->ah_sc, ATH_DBG_FATAL, | 642 | ath_print(common, ATH_DBG_FATAL, |
593 | "TX queue: %u already active\n", q); | 643 | "TX queue: %u already active\n", q); |
594 | return -1; | 644 | return -1; |
595 | } | 645 | } |
596 | memset(qi, 0, sizeof(struct ath9k_tx_queue_info)); | 646 | memset(qi, 0, sizeof(struct ath9k_tx_queue_info)); |
@@ -613,25 +663,27 @@ int ath9k_hw_setuptxqueue(struct ath_hw *ah, enum ath9k_tx_queue type, | |||
613 | 663 | ||
614 | return q; | 664 | return q; |
615 | } | 665 | } |
666 | EXPORT_SYMBOL(ath9k_hw_setuptxqueue); | ||
616 | 667 | ||
617 | bool ath9k_hw_releasetxqueue(struct ath_hw *ah, u32 q) | 668 | bool ath9k_hw_releasetxqueue(struct ath_hw *ah, u32 q) |
618 | { | 669 | { |
619 | struct ath9k_hw_capabilities *pCap = &ah->caps; | 670 | struct ath9k_hw_capabilities *pCap = &ah->caps; |
671 | struct ath_common *common = ath9k_hw_common(ah); | ||
620 | struct ath9k_tx_queue_info *qi; | 672 | struct ath9k_tx_queue_info *qi; |
621 | 673 | ||
622 | if (q >= pCap->total_queues) { | 674 | if (q >= pCap->total_queues) { |
623 | DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Release TXQ, " | 675 | ath_print(common, ATH_DBG_QUEUE, "Release TXQ, " |
624 | "invalid queue: %u\n", q); | 676 | "invalid queue: %u\n", q); |
625 | return false; | 677 | return false; |
626 | } | 678 | } |
627 | qi = &ah->txq[q]; | 679 | qi = &ah->txq[q]; |
628 | if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) { | 680 | if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) { |
629 | DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Release TXQ, " | 681 | ath_print(common, ATH_DBG_QUEUE, "Release TXQ, " |
630 | "inactive queue: %u\n", q); | 682 | "inactive queue: %u\n", q); |
631 | return false; | 683 | return false; |
632 | } | 684 | } |
633 | 685 | ||
634 | DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Release TX queue: %u\n", q); | 686 | ath_print(common, ATH_DBG_QUEUE, "Release TX queue: %u\n", q); |
635 | 687 | ||
636 | qi->tqi_type = ATH9K_TX_QUEUE_INACTIVE; | 688 | qi->tqi_type = ATH9K_TX_QUEUE_INACTIVE; |
637 | ah->txok_interrupt_mask &= ~(1 << q); | 689 | ah->txok_interrupt_mask &= ~(1 << q); |
@@ -643,28 +695,30 @@ bool ath9k_hw_releasetxqueue(struct ath_hw *ah, u32 q) | |||
643 | 695 | ||
644 | return true; | 696 | return true; |
645 | } | 697 | } |
698 | EXPORT_SYMBOL(ath9k_hw_releasetxqueue); | ||
646 | 699 | ||
647 | bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q) | 700 | bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q) |
648 | { | 701 | { |
649 | struct ath9k_hw_capabilities *pCap = &ah->caps; | 702 | struct ath9k_hw_capabilities *pCap = &ah->caps; |
703 | struct ath_common *common = ath9k_hw_common(ah); | ||
650 | struct ath9k_channel *chan = ah->curchan; | 704 | struct ath9k_channel *chan = ah->curchan; |
651 | struct ath9k_tx_queue_info *qi; | 705 | struct ath9k_tx_queue_info *qi; |
652 | u32 cwMin, chanCwMin, value; | 706 | u32 cwMin, chanCwMin, value; |
653 | 707 | ||
654 | if (q >= pCap->total_queues) { | 708 | if (q >= pCap->total_queues) { |
655 | DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Reset TXQ, " | 709 | ath_print(common, ATH_DBG_QUEUE, "Reset TXQ, " |
656 | "invalid queue: %u\n", q); | 710 | "invalid queue: %u\n", q); |
657 | return false; | 711 | return false; |
658 | } | 712 | } |
659 | 713 | ||
660 | qi = &ah->txq[q]; | 714 | qi = &ah->txq[q]; |
661 | if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) { | 715 | if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) { |
662 | DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Reset TXQ, " | 716 | ath_print(common, ATH_DBG_QUEUE, "Reset TXQ, " |
663 | "inactive queue: %u\n", q); | 717 | "inactive queue: %u\n", q); |
664 | return true; | 718 | return true; |
665 | } | 719 | } |
666 | 720 | ||
667 | DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Reset TX queue: %u\n", q); | 721 | ath_print(common, ATH_DBG_QUEUE, "Reset TX queue: %u\n", q); |
668 | 722 | ||
669 | if (qi->tqi_cwmin == ATH9K_TXQ_USEDEFAULT) { | 723 | if (qi->tqi_cwmin == ATH9K_TXQ_USEDEFAULT) { |
670 | if (chan && IS_CHAN_B(chan)) | 724 | if (chan && IS_CHAN_B(chan)) |
@@ -799,6 +853,7 @@ bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q) | |||
799 | 853 | ||
800 | return true; | 854 | return true; |
801 | } | 855 | } |
856 | EXPORT_SYMBOL(ath9k_hw_resettxqueue); | ||
802 | 857 | ||
803 | int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds, | 858 | int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds, |
804 | u32 pa, struct ath_desc *nds, u64 tsf) | 859 | u32 pa, struct ath_desc *nds, u64 tsf) |
@@ -880,6 +935,7 @@ int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds, | |||
880 | 935 | ||
881 | return 0; | 936 | return 0; |
882 | } | 937 | } |
938 | EXPORT_SYMBOL(ath9k_hw_rxprocdesc); | ||
883 | 939 | ||
884 | void ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds, | 940 | void ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds, |
885 | u32 size, u32 flags) | 941 | u32 size, u32 flags) |
@@ -895,7 +951,15 @@ void ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds, | |||
895 | if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) | 951 | if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) |
896 | memset(&(ads->u), 0, sizeof(ads->u)); | 952 | memset(&(ads->u), 0, sizeof(ads->u)); |
897 | } | 953 | } |
954 | EXPORT_SYMBOL(ath9k_hw_setuprxdesc); | ||
898 | 955 | ||
956 | /* | ||
957 | * This can stop or re-enables RX. | ||
958 | * | ||
959 | * If bool is set this will kill any frame which is currently being | ||
960 | * transferred between the MAC and baseband and also prevent any new | ||
961 | * frames from getting started. | ||
962 | */ | ||
899 | bool ath9k_hw_setrxabort(struct ath_hw *ah, bool set) | 963 | bool ath9k_hw_setrxabort(struct ath_hw *ah, bool set) |
900 | { | 964 | { |
901 | u32 reg; | 965 | u32 reg; |
@@ -911,8 +975,9 @@ bool ath9k_hw_setrxabort(struct ath_hw *ah, bool set) | |||
911 | AR_DIAG_RX_ABORT)); | 975 | AR_DIAG_RX_ABORT)); |
912 | 976 | ||
913 | reg = REG_READ(ah, AR_OBS_BUS_1); | 977 | reg = REG_READ(ah, AR_OBS_BUS_1); |
914 | DPRINTF(ah->ah_sc, ATH_DBG_FATAL, | 978 | ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL, |
915 | "RX failed to go idle in 10 ms RXSM=0x%x\n", reg); | 979 | "RX failed to go idle in 10 ms RXSM=0x%x\n", |
980 | reg); | ||
916 | 981 | ||
917 | return false; | 982 | return false; |
918 | } | 983 | } |
@@ -923,16 +988,19 @@ bool ath9k_hw_setrxabort(struct ath_hw *ah, bool set) | |||
923 | 988 | ||
924 | return true; | 989 | return true; |
925 | } | 990 | } |
991 | EXPORT_SYMBOL(ath9k_hw_setrxabort); | ||
926 | 992 | ||
927 | void ath9k_hw_putrxbuf(struct ath_hw *ah, u32 rxdp) | 993 | void ath9k_hw_putrxbuf(struct ath_hw *ah, u32 rxdp) |
928 | { | 994 | { |
929 | REG_WRITE(ah, AR_RXDP, rxdp); | 995 | REG_WRITE(ah, AR_RXDP, rxdp); |
930 | } | 996 | } |
997 | EXPORT_SYMBOL(ath9k_hw_putrxbuf); | ||
931 | 998 | ||
932 | void ath9k_hw_rxena(struct ath_hw *ah) | 999 | void ath9k_hw_rxena(struct ath_hw *ah) |
933 | { | 1000 | { |
934 | REG_WRITE(ah, AR_CR, AR_CR_RXE); | 1001 | REG_WRITE(ah, AR_CR, AR_CR_RXE); |
935 | } | 1002 | } |
1003 | EXPORT_SYMBOL(ath9k_hw_rxena); | ||
936 | 1004 | ||
937 | void ath9k_hw_startpcureceive(struct ath_hw *ah) | 1005 | void ath9k_hw_startpcureceive(struct ath_hw *ah) |
938 | { | 1006 | { |
@@ -942,6 +1010,7 @@ void ath9k_hw_startpcureceive(struct ath_hw *ah) | |||
942 | 1010 | ||
943 | REG_CLR_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT)); | 1011 | REG_CLR_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT)); |
944 | } | 1012 | } |
1013 | EXPORT_SYMBOL(ath9k_hw_startpcureceive); | ||
945 | 1014 | ||
946 | void ath9k_hw_stoppcurecv(struct ath_hw *ah) | 1015 | void ath9k_hw_stoppcurecv(struct ath_hw *ah) |
947 | { | 1016 | { |
@@ -949,12 +1018,13 @@ void ath9k_hw_stoppcurecv(struct ath_hw *ah) | |||
949 | 1018 | ||
950 | ath9k_hw_disable_mib_counters(ah); | 1019 | ath9k_hw_disable_mib_counters(ah); |
951 | } | 1020 | } |
1021 | EXPORT_SYMBOL(ath9k_hw_stoppcurecv); | ||
952 | 1022 | ||
953 | bool ath9k_hw_stopdmarecv(struct ath_hw *ah) | 1023 | bool ath9k_hw_stopdmarecv(struct ath_hw *ah) |
954 | { | 1024 | { |
955 | #define AH_RX_STOP_DMA_TIMEOUT 10000 /* usec */ | 1025 | #define AH_RX_STOP_DMA_TIMEOUT 10000 /* usec */ |
956 | #define AH_RX_TIME_QUANTUM 100 /* usec */ | 1026 | #define AH_RX_TIME_QUANTUM 100 /* usec */ |
957 | 1027 | struct ath_common *common = ath9k_hw_common(ah); | |
958 | int i; | 1028 | int i; |
959 | 1029 | ||
960 | REG_WRITE(ah, AR_CR, AR_CR_RXD); | 1030 | REG_WRITE(ah, AR_CR, AR_CR_RXD); |
@@ -967,12 +1037,12 @@ bool ath9k_hw_stopdmarecv(struct ath_hw *ah) | |||
967 | } | 1037 | } |
968 | 1038 | ||
969 | if (i == 0) { | 1039 | if (i == 0) { |
970 | DPRINTF(ah->ah_sc, ATH_DBG_FATAL, | 1040 | ath_print(common, ATH_DBG_FATAL, |
971 | "DMA failed to stop in %d ms " | 1041 | "DMA failed to stop in %d ms " |
972 | "AR_CR=0x%08x AR_DIAG_SW=0x%08x\n", | 1042 | "AR_CR=0x%08x AR_DIAG_SW=0x%08x\n", |
973 | AH_RX_STOP_DMA_TIMEOUT / 1000, | 1043 | AH_RX_STOP_DMA_TIMEOUT / 1000, |
974 | REG_READ(ah, AR_CR), | 1044 | REG_READ(ah, AR_CR), |
975 | REG_READ(ah, AR_DIAG_SW)); | 1045 | REG_READ(ah, AR_DIAG_SW)); |
976 | return false; | 1046 | return false; |
977 | } else { | 1047 | } else { |
978 | return true; | 1048 | return true; |
@@ -981,3 +1051,17 @@ bool ath9k_hw_stopdmarecv(struct ath_hw *ah) | |||
981 | #undef AH_RX_TIME_QUANTUM | 1051 | #undef AH_RX_TIME_QUANTUM |
982 | #undef AH_RX_STOP_DMA_TIMEOUT | 1052 | #undef AH_RX_STOP_DMA_TIMEOUT |
983 | } | 1053 | } |
1054 | EXPORT_SYMBOL(ath9k_hw_stopdmarecv); | ||
1055 | |||
1056 | int ath9k_hw_beaconq_setup(struct ath_hw *ah) | ||
1057 | { | ||
1058 | struct ath9k_tx_queue_info qi; | ||
1059 | |||
1060 | memset(&qi, 0, sizeof(qi)); | ||
1061 | qi.tqi_aifs = 1; | ||
1062 | qi.tqi_cwmin = 0; | ||
1063 | qi.tqi_cwmax = 0; | ||
1064 | /* NB: don't enable any interrupts */ | ||
1065 | return ath9k_hw_setuptxqueue(ah, ATH9K_TX_QUEUE_BEACON, &qi); | ||
1066 | } | ||
1067 | EXPORT_SYMBOL(ath9k_hw_beaconq_setup); | ||