diff options
author | Vasanthakumar Thiagarajan <vasanth@atheros.com> | 2010-04-15 17:39:26 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2010-04-16 15:43:44 -0400 |
commit | cc610ac0557b0ad0dcffdff1230cef28a970d755 (patch) | |
tree | 975cd15e3d2b42a2b1a5b7a178c595dd35a1b77c | |
parent | d8903a5361817bd96ceed212ad27a380e7ef4d8e (diff) |
ath9k_hw: Define abstraction for tx desc access
Signed-off-by: Vasanthakumar Thiagarajan <vasanth@atheros.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r-- | drivers/net/wireless/ath/ath9k/ar9003_mac.c | 73 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/beacon.c | 3 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/hw-ops.h | 71 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/hw.h | 27 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/mac.c | 508 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/mac.h | 27 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/xmit.c | 3 |
7 files changed, 431 insertions, 281 deletions
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.c b/drivers/net/wireless/ath/ath9k/ar9003_mac.c index 2319456f2f0e..c270bbe25168 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c | |||
@@ -167,6 +167,69 @@ static bool ar9003_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked) | |||
167 | return true; | 167 | return true; |
168 | } | 168 | } |
169 | 169 | ||
170 | static void ar9003_hw_fill_txdesc(struct ath_hw *ah, void *ds, u32 seglen, | ||
171 | bool is_firstseg, bool is_lastseg, | ||
172 | const void *ds0, dma_addr_t buf_addr, | ||
173 | unsigned int qcu) | ||
174 | { | ||
175 | } | ||
176 | |||
177 | static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds, | ||
178 | struct ath_tx_status *ts) | ||
179 | { | ||
180 | return 0; | ||
181 | } | ||
182 | static void ar9003_hw_set11n_txdesc(struct ath_hw *ah, void *ds, | ||
183 | u32 pktLen, enum ath9k_pkt_type type, u32 txPower, | ||
184 | u32 keyIx, enum ath9k_key_type keyType, u32 flags) | ||
185 | { | ||
186 | |||
187 | } | ||
188 | |||
189 | static void ar9003_hw_set11n_ratescenario(struct ath_hw *ah, void *ds, | ||
190 | void *lastds, | ||
191 | u32 durUpdateEn, u32 rtsctsRate, | ||
192 | u32 rtsctsDuration, | ||
193 | struct ath9k_11n_rate_series series[], | ||
194 | u32 nseries, u32 flags) | ||
195 | { | ||
196 | |||
197 | } | ||
198 | |||
199 | static void ar9003_hw_set11n_aggr_first(struct ath_hw *ah, void *ds, | ||
200 | u32 aggrLen) | ||
201 | { | ||
202 | |||
203 | } | ||
204 | |||
205 | static void ar9003_hw_set11n_aggr_middle(struct ath_hw *ah, void *ds, | ||
206 | u32 numDelims) | ||
207 | { | ||
208 | |||
209 | } | ||
210 | |||
211 | static void ar9003_hw_set11n_aggr_last(struct ath_hw *ah, void *ds) | ||
212 | { | ||
213 | |||
214 | } | ||
215 | |||
216 | static void ar9003_hw_clr11n_aggr(struct ath_hw *ah, void *ds) | ||
217 | { | ||
218 | |||
219 | } | ||
220 | |||
221 | static void ar9003_hw_set11n_burstduration(struct ath_hw *ah, void *ds, | ||
222 | u32 burstDuration) | ||
223 | { | ||
224 | |||
225 | } | ||
226 | |||
227 | static void ar9003_hw_set11n_virtualmorefrag(struct ath_hw *ah, void *ds, | ||
228 | u32 vmf) | ||
229 | { | ||
230 | |||
231 | } | ||
232 | |||
170 | void ar9003_hw_attach_mac_ops(struct ath_hw *hw) | 233 | void ar9003_hw_attach_mac_ops(struct ath_hw *hw) |
171 | { | 234 | { |
172 | struct ath_hw_ops *ops = ath9k_hw_ops(hw); | 235 | struct ath_hw_ops *ops = ath9k_hw_ops(hw); |
@@ -175,6 +238,16 @@ void ar9003_hw_attach_mac_ops(struct ath_hw *hw) | |||
175 | ops->set_desc_link = ar9003_hw_set_desc_link; | 238 | ops->set_desc_link = ar9003_hw_set_desc_link; |
176 | ops->get_desc_link = ar9003_hw_get_desc_link; | 239 | ops->get_desc_link = ar9003_hw_get_desc_link; |
177 | ops->get_isr = ar9003_hw_get_isr; | 240 | ops->get_isr = ar9003_hw_get_isr; |
241 | ops->fill_txdesc = ar9003_hw_fill_txdesc; | ||
242 | ops->proc_txdesc = ar9003_hw_proc_txdesc; | ||
243 | ops->set11n_txdesc = ar9003_hw_set11n_txdesc; | ||
244 | ops->set11n_ratescenario = ar9003_hw_set11n_ratescenario; | ||
245 | ops->set11n_aggr_first = ar9003_hw_set11n_aggr_first; | ||
246 | ops->set11n_aggr_middle = ar9003_hw_set11n_aggr_middle; | ||
247 | ops->set11n_aggr_last = ar9003_hw_set11n_aggr_last; | ||
248 | ops->clr11n_aggr = ar9003_hw_clr11n_aggr; | ||
249 | ops->set11n_burstduration = ar9003_hw_set11n_burstduration; | ||
250 | ops->set11n_virtualmorefrag = ar9003_hw_set11n_virtualmorefrag; | ||
178 | } | 251 | } |
179 | 252 | ||
180 | void ath9k_hw_set_rx_bufsize(struct ath_hw *ah, u16 buf_size) | 253 | void ath9k_hw_set_rx_bufsize(struct ath_hw *ah, u16 buf_size) |
diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c index 268b598746f6..c8a4558f79ba 100644 --- a/drivers/net/wireless/ath/ath9k/beacon.c +++ b/drivers/net/wireless/ath/ath9k/beacon.c | |||
@@ -107,7 +107,8 @@ static void ath_beacon_setup(struct ath_softc *sc, struct ath_vif *avp, | |||
107 | 107 | ||
108 | /* NB: beacon's BufLen must be a multiple of 4 bytes */ | 108 | /* NB: beacon's BufLen must be a multiple of 4 bytes */ |
109 | ath9k_hw_filltxdesc(ah, ds, roundup(skb->len, 4), | 109 | ath9k_hw_filltxdesc(ah, ds, roundup(skb->len, 4), |
110 | true, true, ds, bf->bf_buf_addr); | 110 | true, true, ds, bf->bf_buf_addr, |
111 | sc->beacon.beaconq); | ||
111 | 112 | ||
112 | memset(series, 0, sizeof(struct ath9k_11n_rate_series) * 4); | 113 | memset(series, 0, sizeof(struct ath9k_11n_rate_series) * 4); |
113 | series[0].Tries = 1; | 114 | series[0].Tries = 1; |
diff --git a/drivers/net/wireless/ath/ath9k/hw-ops.h b/drivers/net/wireless/ath/ath9k/hw-ops.h index b444ce5f09f8..624422a8169e 100644 --- a/drivers/net/wireless/ath/ath9k/hw-ops.h +++ b/drivers/net/wireless/ath/ath9k/hw-ops.h | |||
@@ -57,6 +57,77 @@ static inline bool ath9k_hw_getisr(struct ath_hw *ah, enum ath9k_int *masked) | |||
57 | return ath9k_hw_ops(ah)->get_isr(ah, masked); | 57 | return ath9k_hw_ops(ah)->get_isr(ah, masked); |
58 | } | 58 | } |
59 | 59 | ||
60 | static inline void ath9k_hw_filltxdesc(struct ath_hw *ah, void *ds, u32 seglen, | ||
61 | bool is_firstseg, bool is_lastseg, | ||
62 | const void *ds0, dma_addr_t buf_addr, | ||
63 | unsigned int qcu) | ||
64 | { | ||
65 | ath9k_hw_ops(ah)->fill_txdesc(ah, ds, seglen, is_firstseg, is_lastseg, | ||
66 | ds0, buf_addr, qcu); | ||
67 | } | ||
68 | |||
69 | static inline int ath9k_hw_txprocdesc(struct ath_hw *ah, void *ds, | ||
70 | struct ath_tx_status *ts) | ||
71 | { | ||
72 | return ath9k_hw_ops(ah)->proc_txdesc(ah, ds, ts); | ||
73 | } | ||
74 | |||
75 | static inline void ath9k_hw_set11n_txdesc(struct ath_hw *ah, void *ds, | ||
76 | u32 pktLen, enum ath9k_pkt_type type, | ||
77 | u32 txPower, u32 keyIx, | ||
78 | enum ath9k_key_type keyType, | ||
79 | u32 flags) | ||
80 | { | ||
81 | ath9k_hw_ops(ah)->set11n_txdesc(ah, ds, pktLen, type, txPower, keyIx, | ||
82 | keyType, flags); | ||
83 | } | ||
84 | |||
85 | static inline void ath9k_hw_set11n_ratescenario(struct ath_hw *ah, void *ds, | ||
86 | void *lastds, | ||
87 | u32 durUpdateEn, u32 rtsctsRate, | ||
88 | u32 rtsctsDuration, | ||
89 | struct ath9k_11n_rate_series series[], | ||
90 | u32 nseries, u32 flags) | ||
91 | { | ||
92 | ath9k_hw_ops(ah)->set11n_ratescenario(ah, ds, lastds, durUpdateEn, | ||
93 | rtsctsRate, rtsctsDuration, series, | ||
94 | nseries, flags); | ||
95 | } | ||
96 | |||
97 | static inline void ath9k_hw_set11n_aggr_first(struct ath_hw *ah, void *ds, | ||
98 | u32 aggrLen) | ||
99 | { | ||
100 | ath9k_hw_ops(ah)->set11n_aggr_first(ah, ds, aggrLen); | ||
101 | } | ||
102 | |||
103 | static inline void ath9k_hw_set11n_aggr_middle(struct ath_hw *ah, void *ds, | ||
104 | u32 numDelims) | ||
105 | { | ||
106 | ath9k_hw_ops(ah)->set11n_aggr_middle(ah, ds, numDelims); | ||
107 | } | ||
108 | |||
109 | static inline void ath9k_hw_set11n_aggr_last(struct ath_hw *ah, void *ds) | ||
110 | { | ||
111 | ath9k_hw_ops(ah)->set11n_aggr_last(ah, ds); | ||
112 | } | ||
113 | |||
114 | static inline void ath9k_hw_clr11n_aggr(struct ath_hw *ah, void *ds) | ||
115 | { | ||
116 | ath9k_hw_ops(ah)->clr11n_aggr(ah, ds); | ||
117 | } | ||
118 | |||
119 | static inline void ath9k_hw_set11n_burstduration(struct ath_hw *ah, void *ds, | ||
120 | u32 burstDuration) | ||
121 | { | ||
122 | ath9k_hw_ops(ah)->set11n_burstduration(ah, ds, burstDuration); | ||
123 | } | ||
124 | |||
125 | static inline void ath9k_hw_set11n_virtualmorefrag(struct ath_hw *ah, void *ds, | ||
126 | u32 vmf) | ||
127 | { | ||
128 | ath9k_hw_ops(ah)->set11n_virtualmorefrag(ah, ds, vmf); | ||
129 | } | ||
130 | |||
60 | /* Private hardware call ops */ | 131 | /* Private hardware call ops */ |
61 | 132 | ||
62 | /* PHY ops */ | 133 | /* PHY ops */ |
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index affb848a2b98..457d8ddebf83 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h | |||
@@ -556,6 +556,33 @@ struct ath_hw_ops { | |||
556 | u8 rxchainmask, | 556 | u8 rxchainmask, |
557 | bool longcal); | 557 | bool longcal); |
558 | bool (*get_isr)(struct ath_hw *ah, enum ath9k_int *masked); | 558 | bool (*get_isr)(struct ath_hw *ah, enum ath9k_int *masked); |
559 | void (*fill_txdesc)(struct ath_hw *ah, void *ds, u32 seglen, | ||
560 | bool is_firstseg, bool is_is_lastseg, | ||
561 | const void *ds0, dma_addr_t buf_addr, | ||
562 | unsigned int qcu); | ||
563 | int (*proc_txdesc)(struct ath_hw *ah, void *ds, | ||
564 | struct ath_tx_status *ts); | ||
565 | void (*set11n_txdesc)(struct ath_hw *ah, void *ds, | ||
566 | u32 pktLen, enum ath9k_pkt_type type, | ||
567 | u32 txPower, u32 keyIx, | ||
568 | enum ath9k_key_type keyType, | ||
569 | u32 flags); | ||
570 | void (*set11n_ratescenario)(struct ath_hw *ah, void *ds, | ||
571 | void *lastds, | ||
572 | u32 durUpdateEn, u32 rtsctsRate, | ||
573 | u32 rtsctsDuration, | ||
574 | struct ath9k_11n_rate_series series[], | ||
575 | u32 nseries, u32 flags); | ||
576 | void (*set11n_aggr_first)(struct ath_hw *ah, void *ds, | ||
577 | u32 aggrLen); | ||
578 | void (*set11n_aggr_middle)(struct ath_hw *ah, void *ds, | ||
579 | u32 numDelims); | ||
580 | void (*set11n_aggr_last)(struct ath_hw *ah, void *ds); | ||
581 | void (*clr11n_aggr)(struct ath_hw *ah, void *ds); | ||
582 | void (*set11n_burstduration)(struct ath_hw *ah, void *ds, | ||
583 | u32 burstDuration); | ||
584 | void (*set11n_virtualmorefrag)(struct ath_hw *ah, void *ds, | ||
585 | u32 vmf); | ||
559 | }; | 586 | }; |
560 | 587 | ||
561 | struct ath_hw { | 588 | struct ath_hw { |
diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c index 4a36ec53f732..22fa5125abff 100644 --- a/drivers/net/wireless/ath/ath9k/mac.c +++ b/drivers/net/wireless/ath/ath9k/mac.c | |||
@@ -183,226 +183,25 @@ static bool ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked) | |||
183 | return true; | 183 | return true; |
184 | } | 184 | } |
185 | 185 | ||
186 | void ar9002_hw_attach_mac_ops(struct ath_hw *ah) | 186 | static void ar9002_hw_fill_txdesc(struct ath_hw *ah, void *ds, u32 seglen, |
187 | { | 187 | bool is_firstseg, bool is_lastseg, |
188 | struct ath_hw_ops *ops = ath9k_hw_ops(ah); | 188 | const void *ds0, dma_addr_t buf_addr, |
189 | 189 | unsigned int qcu) | |
190 | ops->rx_enable = ar9002_hw_rx_enable; | ||
191 | ops->set_desc_link = ar9002_hw_set_desc_link; | ||
192 | ops->get_desc_link = ar9002_hw_get_desc_link; | ||
193 | ops->get_isr = ar9002_hw_get_isr; | ||
194 | } | ||
195 | |||
196 | static void ath9k_hw_set_txq_interrupts(struct ath_hw *ah, | ||
197 | struct ath9k_tx_queue_info *qi) | ||
198 | { | ||
199 | ath_print(ath9k_hw_common(ah), ATH_DBG_INTERRUPT, | ||
200 | "tx ok 0x%x err 0x%x desc 0x%x eol 0x%x urn 0x%x\n", | ||
201 | ah->txok_interrupt_mask, ah->txerr_interrupt_mask, | ||
202 | ah->txdesc_interrupt_mask, ah->txeol_interrupt_mask, | ||
203 | ah->txurn_interrupt_mask); | ||
204 | |||
205 | REG_WRITE(ah, AR_IMR_S0, | ||
206 | SM(ah->txok_interrupt_mask, AR_IMR_S0_QCU_TXOK) | ||
207 | | SM(ah->txdesc_interrupt_mask, AR_IMR_S0_QCU_TXDESC)); | ||
208 | REG_WRITE(ah, AR_IMR_S1, | ||
209 | SM(ah->txerr_interrupt_mask, AR_IMR_S1_QCU_TXERR) | ||
210 | | SM(ah->txeol_interrupt_mask, AR_IMR_S1_QCU_TXEOL)); | ||
211 | |||
212 | ah->imrs2_reg &= ~AR_IMR_S2_QCU_TXURN; | ||
213 | ah->imrs2_reg |= (ah->txurn_interrupt_mask & AR_IMR_S2_QCU_TXURN); | ||
214 | REG_WRITE(ah, AR_IMR_S2, ah->imrs2_reg); | ||
215 | } | ||
216 | |||
217 | u32 ath9k_hw_gettxbuf(struct ath_hw *ah, u32 q) | ||
218 | { | ||
219 | return REG_READ(ah, AR_QTXDP(q)); | ||
220 | } | ||
221 | EXPORT_SYMBOL(ath9k_hw_gettxbuf); | ||
222 | |||
223 | void ath9k_hw_puttxbuf(struct ath_hw *ah, u32 q, u32 txdp) | ||
224 | { | ||
225 | REG_WRITE(ah, AR_QTXDP(q), txdp); | ||
226 | } | ||
227 | EXPORT_SYMBOL(ath9k_hw_puttxbuf); | ||
228 | |||
229 | void ath9k_hw_txstart(struct ath_hw *ah, u32 q) | ||
230 | { | ||
231 | ath_print(ath9k_hw_common(ah), ATH_DBG_QUEUE, | ||
232 | "Enable TXE on queue: %u\n", q); | ||
233 | REG_WRITE(ah, AR_Q_TXE, 1 << q); | ||
234 | } | ||
235 | EXPORT_SYMBOL(ath9k_hw_txstart); | ||
236 | |||
237 | u32 ath9k_hw_numtxpending(struct ath_hw *ah, u32 q) | ||
238 | { | ||
239 | u32 npend; | ||
240 | |||
241 | npend = REG_READ(ah, AR_QSTS(q)) & AR_Q_STS_PEND_FR_CNT; | ||
242 | if (npend == 0) { | ||
243 | |||
244 | if (REG_READ(ah, AR_Q_TXE) & (1 << q)) | ||
245 | npend = 1; | ||
246 | } | ||
247 | |||
248 | return npend; | ||
249 | } | ||
250 | EXPORT_SYMBOL(ath9k_hw_numtxpending); | ||
251 | |||
252 | /** | ||
253 | * ath9k_hw_updatetxtriglevel - adjusts the frame trigger level | ||
254 | * | ||
255 | * @ah: atheros hardware struct | ||
256 | * @bIncTrigLevel: whether or not the frame trigger level should be updated | ||
257 | * | ||
258 | * The frame trigger level specifies the minimum number of bytes, | ||
259 | * in units of 64 bytes, that must be DMA'ed into the PCU TX FIFO | ||
260 | * before the PCU will initiate sending the frame on the air. This can | ||
261 | * mean we initiate transmit before a full frame is on the PCU TX FIFO. | ||
262 | * Resets to 0x1 (meaning 64 bytes or a full frame, whichever occurs | ||
263 | * first) | ||
264 | * | ||
265 | * Caution must be taken to ensure to set the frame trigger level based | ||
266 | * on the DMA request size. For example if the DMA request size is set to | ||
267 | * 128 bytes the trigger level cannot exceed 6 * 64 = 384. This is because | ||
268 | * there need to be enough space in the tx FIFO for the requested transfer | ||
269 | * size. Hence the tx FIFO will stop with 512 - 128 = 384 bytes. If we set | ||
270 | * the threshold to a value beyond 6, then the transmit will hang. | ||
271 | * | ||
272 | * Current dual stream devices have a PCU TX FIFO size of 8 KB. | ||
273 | * Current single stream devices have a PCU TX FIFO size of 4 KB, however, | ||
274 | * there is a hardware issue which forces us to use 2 KB instead so the | ||
275 | * frame trigger level must not exceed 2 KB for these chipsets. | ||
276 | */ | ||
277 | bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel) | ||
278 | { | ||
279 | u32 txcfg, curLevel, newLevel; | ||
280 | enum ath9k_int omask; | ||
281 | |||
282 | if (ah->tx_trig_level >= ah->config.max_txtrig_level) | ||
283 | return false; | ||
284 | |||
285 | omask = ath9k_hw_set_interrupts(ah, ah->imask & ~ATH9K_INT_GLOBAL); | ||
286 | |||
287 | txcfg = REG_READ(ah, AR_TXCFG); | ||
288 | curLevel = MS(txcfg, AR_FTRIG); | ||
289 | newLevel = curLevel; | ||
290 | if (bIncTrigLevel) { | ||
291 | if (curLevel < ah->config.max_txtrig_level) | ||
292 | newLevel++; | ||
293 | } else if (curLevel > MIN_TX_FIFO_THRESHOLD) | ||
294 | newLevel--; | ||
295 | if (newLevel != curLevel) | ||
296 | REG_WRITE(ah, AR_TXCFG, | ||
297 | (txcfg & ~AR_FTRIG) | SM(newLevel, AR_FTRIG)); | ||
298 | |||
299 | ath9k_hw_set_interrupts(ah, omask); | ||
300 | |||
301 | ah->tx_trig_level = newLevel; | ||
302 | |||
303 | return newLevel != curLevel; | ||
304 | } | ||
305 | EXPORT_SYMBOL(ath9k_hw_updatetxtriglevel); | ||
306 | |||
307 | bool ath9k_hw_stoptxdma(struct ath_hw *ah, u32 q) | ||
308 | { | ||
309 | #define ATH9K_TX_STOP_DMA_TIMEOUT 4000 /* usec */ | ||
310 | #define ATH9K_TIME_QUANTUM 100 /* usec */ | ||
311 | struct ath_common *common = ath9k_hw_common(ah); | ||
312 | struct ath9k_hw_capabilities *pCap = &ah->caps; | ||
313 | struct ath9k_tx_queue_info *qi; | ||
314 | u32 tsfLow, j, wait; | ||
315 | u32 wait_time = ATH9K_TX_STOP_DMA_TIMEOUT / ATH9K_TIME_QUANTUM; | ||
316 | |||
317 | if (q >= pCap->total_queues) { | ||
318 | ath_print(common, ATH_DBG_QUEUE, "Stopping TX DMA, " | ||
319 | "invalid queue: %u\n", q); | ||
320 | return false; | ||
321 | } | ||
322 | |||
323 | qi = &ah->txq[q]; | ||
324 | if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) { | ||
325 | ath_print(common, ATH_DBG_QUEUE, "Stopping TX DMA, " | ||
326 | "inactive queue: %u\n", q); | ||
327 | return false; | ||
328 | } | ||
329 | |||
330 | REG_WRITE(ah, AR_Q_TXD, 1 << q); | ||
331 | |||
332 | for (wait = wait_time; wait != 0; wait--) { | ||
333 | if (ath9k_hw_numtxpending(ah, q) == 0) | ||
334 | break; | ||
335 | udelay(ATH9K_TIME_QUANTUM); | ||
336 | } | ||
337 | |||
338 | if (ath9k_hw_numtxpending(ah, q)) { | ||
339 | ath_print(common, ATH_DBG_QUEUE, | ||
340 | "%s: Num of pending TX Frames %d on Q %d\n", | ||
341 | __func__, ath9k_hw_numtxpending(ah, q), q); | ||
342 | |||
343 | for (j = 0; j < 2; j++) { | ||
344 | tsfLow = REG_READ(ah, AR_TSF_L32); | ||
345 | REG_WRITE(ah, AR_QUIET2, | ||
346 | SM(10, AR_QUIET2_QUIET_DUR)); | ||
347 | REG_WRITE(ah, AR_QUIET_PERIOD, 100); | ||
348 | REG_WRITE(ah, AR_NEXT_QUIET_TIMER, tsfLow >> 10); | ||
349 | REG_SET_BIT(ah, AR_TIMER_MODE, | ||
350 | AR_QUIET_TIMER_EN); | ||
351 | |||
352 | if ((REG_READ(ah, AR_TSF_L32) >> 10) == (tsfLow >> 10)) | ||
353 | break; | ||
354 | |||
355 | ath_print(common, ATH_DBG_QUEUE, | ||
356 | "TSF has moved while trying to set " | ||
357 | "quiet time TSF: 0x%08x\n", tsfLow); | ||
358 | } | ||
359 | |||
360 | REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH); | ||
361 | |||
362 | udelay(200); | ||
363 | REG_CLR_BIT(ah, AR_TIMER_MODE, AR_QUIET_TIMER_EN); | ||
364 | |||
365 | wait = wait_time; | ||
366 | while (ath9k_hw_numtxpending(ah, q)) { | ||
367 | if ((--wait) == 0) { | ||
368 | ath_print(common, ATH_DBG_FATAL, | ||
369 | "Failed to stop TX DMA in 100 " | ||
370 | "msec after killing last frame\n"); | ||
371 | break; | ||
372 | } | ||
373 | udelay(ATH9K_TIME_QUANTUM); | ||
374 | } | ||
375 | |||
376 | REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH); | ||
377 | } | ||
378 | |||
379 | REG_WRITE(ah, AR_Q_TXD, 0); | ||
380 | return wait != 0; | ||
381 | |||
382 | #undef ATH9K_TX_STOP_DMA_TIMEOUT | ||
383 | #undef ATH9K_TIME_QUANTUM | ||
384 | } | ||
385 | EXPORT_SYMBOL(ath9k_hw_stoptxdma); | ||
386 | |||
387 | void ath9k_hw_filltxdesc(struct ath_hw *ah, struct ath_desc *ds, | ||
388 | u32 segLen, bool firstSeg, | ||
389 | bool lastSeg, const struct ath_desc *ds0, | ||
390 | dma_addr_t buf_addr) | ||
391 | { | 190 | { |
392 | struct ar5416_desc *ads = AR5416DESC(ds); | 191 | struct ar5416_desc *ads = AR5416DESC(ds); |
393 | 192 | ||
394 | ads->ds_data = buf_addr; | 193 | ads->ds_data = buf_addr; |
395 | 194 | ||
396 | if (firstSeg) { | 195 | if (is_firstseg) { |
397 | ads->ds_ctl1 |= segLen | (lastSeg ? 0 : AR_TxMore); | 196 | ads->ds_ctl1 |= seglen | (is_lastseg ? 0 : AR_TxMore); |
398 | } else if (lastSeg) { | 197 | } else if (is_lastseg) { |
399 | ads->ds_ctl0 = 0; | 198 | ads->ds_ctl0 = 0; |
400 | ads->ds_ctl1 = segLen; | 199 | ads->ds_ctl1 = seglen; |
401 | ads->ds_ctl2 = AR5416DESC_CONST(ds0)->ds_ctl2; | 200 | ads->ds_ctl2 = AR5416DESC_CONST(ds0)->ds_ctl2; |
402 | ads->ds_ctl3 = AR5416DESC_CONST(ds0)->ds_ctl3; | 201 | ads->ds_ctl3 = AR5416DESC_CONST(ds0)->ds_ctl3; |
403 | } else { | 202 | } else { |
404 | ads->ds_ctl0 = 0; | 203 | ads->ds_ctl0 = 0; |
405 | ads->ds_ctl1 = segLen | AR_TxMore; | 204 | ads->ds_ctl1 = seglen | AR_TxMore; |
406 | ads->ds_ctl2 = 0; | 205 | ads->ds_ctl2 = 0; |
407 | ads->ds_ctl3 = 0; | 206 | ads->ds_ctl3 = 0; |
408 | } | 207 | } |
@@ -412,22 +211,9 @@ void ath9k_hw_filltxdesc(struct ath_hw *ah, struct ath_desc *ds, | |||
412 | ads->ds_txstatus6 = ads->ds_txstatus7 = 0; | 211 | ads->ds_txstatus6 = ads->ds_txstatus7 = 0; |
413 | ads->ds_txstatus8 = ads->ds_txstatus9 = 0; | 212 | ads->ds_txstatus8 = ads->ds_txstatus9 = 0; |
414 | } | 213 | } |
415 | EXPORT_SYMBOL(ath9k_hw_filltxdesc); | ||
416 | 214 | ||
417 | void ath9k_hw_cleartxdesc(struct ath_hw *ah, struct ath_desc *ds) | 215 | static int ar9002_hw_proc_txdesc(struct ath_hw *ah, void *ds, |
418 | { | 216 | struct ath_tx_status *ts) |
419 | struct ar5416_desc *ads = AR5416DESC(ds); | ||
420 | |||
421 | ads->ds_txstatus0 = ads->ds_txstatus1 = 0; | ||
422 | ads->ds_txstatus2 = ads->ds_txstatus3 = 0; | ||
423 | ads->ds_txstatus4 = ads->ds_txstatus5 = 0; | ||
424 | ads->ds_txstatus6 = ads->ds_txstatus7 = 0; | ||
425 | ads->ds_txstatus8 = ads->ds_txstatus9 = 0; | ||
426 | } | ||
427 | EXPORT_SYMBOL(ath9k_hw_cleartxdesc); | ||
428 | |||
429 | int ath9k_hw_txprocdesc(struct ath_hw *ah, struct ath_desc *ds, | ||
430 | struct ath_tx_status *ts) | ||
431 | { | 217 | { |
432 | struct ar5416_desc *ads = AR5416DESC(ds); | 218 | struct ar5416_desc *ads = AR5416DESC(ds); |
433 | 219 | ||
@@ -503,11 +289,11 @@ int ath9k_hw_txprocdesc(struct ath_hw *ah, struct ath_desc *ds, | |||
503 | 289 | ||
504 | return 0; | 290 | return 0; |
505 | } | 291 | } |
506 | EXPORT_SYMBOL(ath9k_hw_txprocdesc); | ||
507 | 292 | ||
508 | void ath9k_hw_set11n_txdesc(struct ath_hw *ah, struct ath_desc *ds, | 293 | static void ar9002_hw_set11n_txdesc(struct ath_hw *ah, void *ds, |
509 | u32 pktLen, enum ath9k_pkt_type type, u32 txPower, | 294 | u32 pktLen, enum ath9k_pkt_type type, |
510 | u32 keyIx, enum ath9k_key_type keyType, u32 flags) | 295 | u32 txPower, u32 keyIx, |
296 | enum ath9k_key_type keyType, u32 flags) | ||
511 | { | 297 | { |
512 | struct ar5416_desc *ads = AR5416DESC(ds); | 298 | struct ar5416_desc *ads = AR5416DESC(ds); |
513 | 299 | ||
@@ -539,14 +325,13 @@ void ath9k_hw_set11n_txdesc(struct ath_hw *ah, struct ath_desc *ds, | |||
539 | ads->ds_ctl11 = 0; | 325 | ads->ds_ctl11 = 0; |
540 | } | 326 | } |
541 | } | 327 | } |
542 | EXPORT_SYMBOL(ath9k_hw_set11n_txdesc); | 328 | |
543 | 329 | static void ar9002_hw_set11n_ratescenario(struct ath_hw *ah, void *ds, | |
544 | void ath9k_hw_set11n_ratescenario(struct ath_hw *ah, struct ath_desc *ds, | 330 | void *lastds, |
545 | struct ath_desc *lastds, | 331 | u32 durUpdateEn, u32 rtsctsRate, |
546 | u32 durUpdateEn, u32 rtsctsRate, | 332 | u32 rtsctsDuration, |
547 | u32 rtsctsDuration, | 333 | struct ath9k_11n_rate_series series[], |
548 | struct ath9k_11n_rate_series series[], | 334 | u32 nseries, u32 flags) |
549 | u32 nseries, u32 flags) | ||
550 | { | 335 | { |
551 | struct ar5416_desc *ads = AR5416DESC(ds); | 336 | struct ar5416_desc *ads = AR5416DESC(ds); |
552 | struct ar5416_desc *last_ads = AR5416DESC(lastds); | 337 | struct ar5416_desc *last_ads = AR5416DESC(lastds); |
@@ -595,10 +380,9 @@ void ath9k_hw_set11n_ratescenario(struct ath_hw *ah, struct ath_desc *ds, | |||
595 | last_ads->ds_ctl2 = ads->ds_ctl2; | 380 | last_ads->ds_ctl2 = ads->ds_ctl2; |
596 | last_ads->ds_ctl3 = ads->ds_ctl3; | 381 | last_ads->ds_ctl3 = ads->ds_ctl3; |
597 | } | 382 | } |
598 | EXPORT_SYMBOL(ath9k_hw_set11n_ratescenario); | ||
599 | 383 | ||
600 | void ath9k_hw_set11n_aggr_first(struct ath_hw *ah, struct ath_desc *ds, | 384 | static void ar9002_hw_set11n_aggr_first(struct ath_hw *ah, void *ds, |
601 | u32 aggrLen) | 385 | u32 aggrLen) |
602 | { | 386 | { |
603 | struct ar5416_desc *ads = AR5416DESC(ds); | 387 | struct ar5416_desc *ads = AR5416DESC(ds); |
604 | 388 | ||
@@ -606,10 +390,9 @@ void ath9k_hw_set11n_aggr_first(struct ath_hw *ah, struct ath_desc *ds, | |||
606 | ads->ds_ctl6 &= ~AR_AggrLen; | 390 | ads->ds_ctl6 &= ~AR_AggrLen; |
607 | ads->ds_ctl6 |= SM(aggrLen, AR_AggrLen); | 391 | ads->ds_ctl6 |= SM(aggrLen, AR_AggrLen); |
608 | } | 392 | } |
609 | EXPORT_SYMBOL(ath9k_hw_set11n_aggr_first); | ||
610 | 393 | ||
611 | void ath9k_hw_set11n_aggr_middle(struct ath_hw *ah, struct ath_desc *ds, | 394 | static void ar9002_hw_set11n_aggr_middle(struct ath_hw *ah, void *ds, |
612 | u32 numDelims) | 395 | u32 numDelims) |
613 | { | 396 | { |
614 | struct ar5416_desc *ads = AR5416DESC(ds); | 397 | struct ar5416_desc *ads = AR5416DESC(ds); |
615 | unsigned int ctl6; | 398 | unsigned int ctl6; |
@@ -621,9 +404,8 @@ void ath9k_hw_set11n_aggr_middle(struct ath_hw *ah, struct ath_desc *ds, | |||
621 | ctl6 |= SM(numDelims, AR_PadDelim); | 404 | ctl6 |= SM(numDelims, AR_PadDelim); |
622 | ads->ds_ctl6 = ctl6; | 405 | ads->ds_ctl6 = ctl6; |
623 | } | 406 | } |
624 | EXPORT_SYMBOL(ath9k_hw_set11n_aggr_middle); | ||
625 | 407 | ||
626 | void ath9k_hw_set11n_aggr_last(struct ath_hw *ah, struct ath_desc *ds) | 408 | static void ar9002_hw_set11n_aggr_last(struct ath_hw *ah, void *ds) |
627 | { | 409 | { |
628 | struct ar5416_desc *ads = AR5416DESC(ds); | 410 | struct ar5416_desc *ads = AR5416DESC(ds); |
629 | 411 | ||
@@ -631,28 +413,25 @@ void ath9k_hw_set11n_aggr_last(struct ath_hw *ah, struct ath_desc *ds) | |||
631 | ads->ds_ctl1 &= ~AR_MoreAggr; | 413 | ads->ds_ctl1 &= ~AR_MoreAggr; |
632 | ads->ds_ctl6 &= ~AR_PadDelim; | 414 | ads->ds_ctl6 &= ~AR_PadDelim; |
633 | } | 415 | } |
634 | EXPORT_SYMBOL(ath9k_hw_set11n_aggr_last); | ||
635 | 416 | ||
636 | void ath9k_hw_clr11n_aggr(struct ath_hw *ah, struct ath_desc *ds) | 417 | static void ar9002_hw_clr11n_aggr(struct ath_hw *ah, void *ds) |
637 | { | 418 | { |
638 | struct ar5416_desc *ads = AR5416DESC(ds); | 419 | struct ar5416_desc *ads = AR5416DESC(ds); |
639 | 420 | ||
640 | ads->ds_ctl1 &= (~AR_IsAggr & ~AR_MoreAggr); | 421 | ads->ds_ctl1 &= (~AR_IsAggr & ~AR_MoreAggr); |
641 | } | 422 | } |
642 | EXPORT_SYMBOL(ath9k_hw_clr11n_aggr); | ||
643 | 423 | ||
644 | void ath9k_hw_set11n_burstduration(struct ath_hw *ah, struct ath_desc *ds, | 424 | static void ar9002_hw_set11n_burstduration(struct ath_hw *ah, void *ds, |
645 | u32 burstDuration) | 425 | u32 burstDuration) |
646 | { | 426 | { |
647 | struct ar5416_desc *ads = AR5416DESC(ds); | 427 | struct ar5416_desc *ads = AR5416DESC(ds); |
648 | 428 | ||
649 | ads->ds_ctl2 &= ~AR_BurstDur; | 429 | ads->ds_ctl2 &= ~AR_BurstDur; |
650 | ads->ds_ctl2 |= SM(burstDuration, AR_BurstDur); | 430 | ads->ds_ctl2 |= SM(burstDuration, AR_BurstDur); |
651 | } | 431 | } |
652 | EXPORT_SYMBOL(ath9k_hw_set11n_burstduration); | ||
653 | 432 | ||
654 | void ath9k_hw_set11n_virtualmorefrag(struct ath_hw *ah, struct ath_desc *ds, | 433 | static void ar9002_hw_set11n_virtualmorefrag(struct ath_hw *ah, void *ds, |
655 | u32 vmf) | 434 | u32 vmf) |
656 | { | 435 | { |
657 | struct ar5416_desc *ads = AR5416DESC(ds); | 436 | struct ar5416_desc *ads = AR5416DESC(ds); |
658 | 437 | ||
@@ -662,6 +441,229 @@ void ath9k_hw_set11n_virtualmorefrag(struct ath_hw *ah, struct ath_desc *ds, | |||
662 | ads->ds_ctl0 &= ~AR_VirtMoreFrag; | 441 | ads->ds_ctl0 &= ~AR_VirtMoreFrag; |
663 | } | 442 | } |
664 | 443 | ||
444 | void ar9002_hw_attach_mac_ops(struct ath_hw *ah) | ||
445 | { | ||
446 | struct ath_hw_ops *ops = ath9k_hw_ops(ah); | ||
447 | |||
448 | ops->rx_enable = ar9002_hw_rx_enable; | ||
449 | ops->set_desc_link = ar9002_hw_set_desc_link; | ||
450 | ops->get_desc_link = ar9002_hw_get_desc_link; | ||
451 | ops->get_isr = ar9002_hw_get_isr; | ||
452 | ops->fill_txdesc = ar9002_hw_fill_txdesc; | ||
453 | ops->proc_txdesc = ar9002_hw_proc_txdesc; | ||
454 | ops->set11n_txdesc = ar9002_hw_set11n_txdesc; | ||
455 | ops->set11n_ratescenario = ar9002_hw_set11n_ratescenario; | ||
456 | ops->set11n_aggr_first = ar9002_hw_set11n_aggr_first; | ||
457 | ops->set11n_aggr_middle = ar9002_hw_set11n_aggr_middle; | ||
458 | ops->set11n_aggr_last = ar9002_hw_set11n_aggr_last; | ||
459 | ops->clr11n_aggr = ar9002_hw_clr11n_aggr; | ||
460 | ops->set11n_burstduration = ar9002_hw_set11n_burstduration; | ||
461 | ops->set11n_virtualmorefrag = ar9002_hw_set11n_virtualmorefrag; | ||
462 | } | ||
463 | |||
464 | static void ath9k_hw_set_txq_interrupts(struct ath_hw *ah, | ||
465 | struct ath9k_tx_queue_info *qi) | ||
466 | { | ||
467 | ath_print(ath9k_hw_common(ah), ATH_DBG_INTERRUPT, | ||
468 | "tx ok 0x%x err 0x%x desc 0x%x eol 0x%x urn 0x%x\n", | ||
469 | ah->txok_interrupt_mask, ah->txerr_interrupt_mask, | ||
470 | ah->txdesc_interrupt_mask, ah->txeol_interrupt_mask, | ||
471 | ah->txurn_interrupt_mask); | ||
472 | |||
473 | REG_WRITE(ah, AR_IMR_S0, | ||
474 | SM(ah->txok_interrupt_mask, AR_IMR_S0_QCU_TXOK) | ||
475 | | SM(ah->txdesc_interrupt_mask, AR_IMR_S0_QCU_TXDESC)); | ||
476 | REG_WRITE(ah, AR_IMR_S1, | ||
477 | SM(ah->txerr_interrupt_mask, AR_IMR_S1_QCU_TXERR) | ||
478 | | SM(ah->txeol_interrupt_mask, AR_IMR_S1_QCU_TXEOL)); | ||
479 | |||
480 | ah->imrs2_reg &= ~AR_IMR_S2_QCU_TXURN; | ||
481 | ah->imrs2_reg |= (ah->txurn_interrupt_mask & AR_IMR_S2_QCU_TXURN); | ||
482 | REG_WRITE(ah, AR_IMR_S2, ah->imrs2_reg); | ||
483 | } | ||
484 | |||
485 | u32 ath9k_hw_gettxbuf(struct ath_hw *ah, u32 q) | ||
486 | { | ||
487 | return REG_READ(ah, AR_QTXDP(q)); | ||
488 | } | ||
489 | EXPORT_SYMBOL(ath9k_hw_gettxbuf); | ||
490 | |||
491 | void ath9k_hw_puttxbuf(struct ath_hw *ah, u32 q, u32 txdp) | ||
492 | { | ||
493 | REG_WRITE(ah, AR_QTXDP(q), txdp); | ||
494 | } | ||
495 | EXPORT_SYMBOL(ath9k_hw_puttxbuf); | ||
496 | |||
497 | void ath9k_hw_txstart(struct ath_hw *ah, u32 q) | ||
498 | { | ||
499 | ath_print(ath9k_hw_common(ah), ATH_DBG_QUEUE, | ||
500 | "Enable TXE on queue: %u\n", q); | ||
501 | REG_WRITE(ah, AR_Q_TXE, 1 << q); | ||
502 | } | ||
503 | EXPORT_SYMBOL(ath9k_hw_txstart); | ||
504 | |||
505 | void ath9k_hw_cleartxdesc(struct ath_hw *ah, void *ds) | ||
506 | { | ||
507 | struct ar5416_desc *ads = AR5416DESC(ds); | ||
508 | |||
509 | ads->ds_txstatus0 = ads->ds_txstatus1 = 0; | ||
510 | ads->ds_txstatus2 = ads->ds_txstatus3 = 0; | ||
511 | ads->ds_txstatus4 = ads->ds_txstatus5 = 0; | ||
512 | ads->ds_txstatus6 = ads->ds_txstatus7 = 0; | ||
513 | ads->ds_txstatus8 = ads->ds_txstatus9 = 0; | ||
514 | } | ||
515 | EXPORT_SYMBOL(ath9k_hw_cleartxdesc); | ||
516 | |||
517 | u32 ath9k_hw_numtxpending(struct ath_hw *ah, u32 q) | ||
518 | { | ||
519 | u32 npend; | ||
520 | |||
521 | npend = REG_READ(ah, AR_QSTS(q)) & AR_Q_STS_PEND_FR_CNT; | ||
522 | if (npend == 0) { | ||
523 | |||
524 | if (REG_READ(ah, AR_Q_TXE) & (1 << q)) | ||
525 | npend = 1; | ||
526 | } | ||
527 | |||
528 | return npend; | ||
529 | } | ||
530 | EXPORT_SYMBOL(ath9k_hw_numtxpending); | ||
531 | |||
532 | /** | ||
533 | * ath9k_hw_updatetxtriglevel - adjusts the frame trigger level | ||
534 | * | ||
535 | * @ah: atheros hardware struct | ||
536 | * @bIncTrigLevel: whether or not the frame trigger level should be updated | ||
537 | * | ||
538 | * The frame trigger level specifies the minimum number of bytes, | ||
539 | * in units of 64 bytes, that must be DMA'ed into the PCU TX FIFO | ||
540 | * before the PCU will initiate sending the frame on the air. This can | ||
541 | * mean we initiate transmit before a full frame is on the PCU TX FIFO. | ||
542 | * Resets to 0x1 (meaning 64 bytes or a full frame, whichever occurs | ||
543 | * first) | ||
544 | * | ||
545 | * Caution must be taken to ensure to set the frame trigger level based | ||
546 | * on the DMA request size. For example if the DMA request size is set to | ||
547 | * 128 bytes the trigger level cannot exceed 6 * 64 = 384. This is because | ||
548 | * there need to be enough space in the tx FIFO for the requested transfer | ||
549 | * size. Hence the tx FIFO will stop with 512 - 128 = 384 bytes. If we set | ||
550 | * the threshold to a value beyond 6, then the transmit will hang. | ||
551 | * | ||
552 | * Current dual stream devices have a PCU TX FIFO size of 8 KB. | ||
553 | * Current single stream devices have a PCU TX FIFO size of 4 KB, however, | ||
554 | * there is a hardware issue which forces us to use 2 KB instead so the | ||
555 | * frame trigger level must not exceed 2 KB for these chipsets. | ||
556 | */ | ||
557 | bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel) | ||
558 | { | ||
559 | u32 txcfg, curLevel, newLevel; | ||
560 | enum ath9k_int omask; | ||
561 | |||
562 | if (ah->tx_trig_level >= ah->config.max_txtrig_level) | ||
563 | return false; | ||
564 | |||
565 | omask = ath9k_hw_set_interrupts(ah, ah->imask & ~ATH9K_INT_GLOBAL); | ||
566 | |||
567 | txcfg = REG_READ(ah, AR_TXCFG); | ||
568 | curLevel = MS(txcfg, AR_FTRIG); | ||
569 | newLevel = curLevel; | ||
570 | if (bIncTrigLevel) { | ||
571 | if (curLevel < ah->config.max_txtrig_level) | ||
572 | newLevel++; | ||
573 | } else if (curLevel > MIN_TX_FIFO_THRESHOLD) | ||
574 | newLevel--; | ||
575 | if (newLevel != curLevel) | ||
576 | REG_WRITE(ah, AR_TXCFG, | ||
577 | (txcfg & ~AR_FTRIG) | SM(newLevel, AR_FTRIG)); | ||
578 | |||
579 | ath9k_hw_set_interrupts(ah, omask); | ||
580 | |||
581 | ah->tx_trig_level = newLevel; | ||
582 | |||
583 | return newLevel != curLevel; | ||
584 | } | ||
585 | EXPORT_SYMBOL(ath9k_hw_updatetxtriglevel); | ||
586 | |||
587 | bool ath9k_hw_stoptxdma(struct ath_hw *ah, u32 q) | ||
588 | { | ||
589 | #define ATH9K_TX_STOP_DMA_TIMEOUT 4000 /* usec */ | ||
590 | #define ATH9K_TIME_QUANTUM 100 /* usec */ | ||
591 | struct ath_common *common = ath9k_hw_common(ah); | ||
592 | struct ath9k_hw_capabilities *pCap = &ah->caps; | ||
593 | struct ath9k_tx_queue_info *qi; | ||
594 | u32 tsfLow, j, wait; | ||
595 | u32 wait_time = ATH9K_TX_STOP_DMA_TIMEOUT / ATH9K_TIME_QUANTUM; | ||
596 | |||
597 | if (q >= pCap->total_queues) { | ||
598 | ath_print(common, ATH_DBG_QUEUE, "Stopping TX DMA, " | ||
599 | "invalid queue: %u\n", q); | ||
600 | return false; | ||
601 | } | ||
602 | |||
603 | qi = &ah->txq[q]; | ||
604 | if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) { | ||
605 | ath_print(common, ATH_DBG_QUEUE, "Stopping TX DMA, " | ||
606 | "inactive queue: %u\n", q); | ||
607 | return false; | ||
608 | } | ||
609 | |||
610 | REG_WRITE(ah, AR_Q_TXD, 1 << q); | ||
611 | |||
612 | for (wait = wait_time; wait != 0; wait--) { | ||
613 | if (ath9k_hw_numtxpending(ah, q) == 0) | ||
614 | break; | ||
615 | udelay(ATH9K_TIME_QUANTUM); | ||
616 | } | ||
617 | |||
618 | if (ath9k_hw_numtxpending(ah, q)) { | ||
619 | ath_print(common, ATH_DBG_QUEUE, | ||
620 | "%s: Num of pending TX Frames %d on Q %d\n", | ||
621 | __func__, ath9k_hw_numtxpending(ah, q), q); | ||
622 | |||
623 | for (j = 0; j < 2; j++) { | ||
624 | tsfLow = REG_READ(ah, AR_TSF_L32); | ||
625 | REG_WRITE(ah, AR_QUIET2, | ||
626 | SM(10, AR_QUIET2_QUIET_DUR)); | ||
627 | REG_WRITE(ah, AR_QUIET_PERIOD, 100); | ||
628 | REG_WRITE(ah, AR_NEXT_QUIET_TIMER, tsfLow >> 10); | ||
629 | REG_SET_BIT(ah, AR_TIMER_MODE, | ||
630 | AR_QUIET_TIMER_EN); | ||
631 | |||
632 | if ((REG_READ(ah, AR_TSF_L32) >> 10) == (tsfLow >> 10)) | ||
633 | break; | ||
634 | |||
635 | ath_print(common, ATH_DBG_QUEUE, | ||
636 | "TSF has moved while trying to set " | ||
637 | "quiet time TSF: 0x%08x\n", tsfLow); | ||
638 | } | ||
639 | |||
640 | REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH); | ||
641 | |||
642 | udelay(200); | ||
643 | REG_CLR_BIT(ah, AR_TIMER_MODE, AR_QUIET_TIMER_EN); | ||
644 | |||
645 | wait = wait_time; | ||
646 | while (ath9k_hw_numtxpending(ah, q)) { | ||
647 | if ((--wait) == 0) { | ||
648 | ath_print(common, ATH_DBG_FATAL, | ||
649 | "Failed to stop TX DMA in 100 " | ||
650 | "msec after killing last frame\n"); | ||
651 | break; | ||
652 | } | ||
653 | udelay(ATH9K_TIME_QUANTUM); | ||
654 | } | ||
655 | |||
656 | REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH); | ||
657 | } | ||
658 | |||
659 | REG_WRITE(ah, AR_Q_TXD, 0); | ||
660 | return wait != 0; | ||
661 | |||
662 | #undef ATH9K_TX_STOP_DMA_TIMEOUT | ||
663 | #undef ATH9K_TIME_QUANTUM | ||
664 | } | ||
665 | EXPORT_SYMBOL(ath9k_hw_stoptxdma); | ||
666 | |||
665 | void ath9k_hw_gettxintrtxqs(struct ath_hw *ah, u32 *txqs) | 667 | void ath9k_hw_gettxintrtxqs(struct ath_hw *ah, u32 *txqs) |
666 | { | 668 | { |
667 | *txqs &= ah->intr_txqs; | 669 | *txqs &= ah->intr_txqs; |
diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h index 7c0d75490211..0d492192de94 100644 --- a/drivers/net/wireless/ath/ath9k/mac.h +++ b/drivers/net/wireless/ath/ath9k/mac.h | |||
@@ -687,35 +687,10 @@ struct ath9k_channel; | |||
687 | u32 ath9k_hw_gettxbuf(struct ath_hw *ah, u32 q); | 687 | u32 ath9k_hw_gettxbuf(struct ath_hw *ah, u32 q); |
688 | void ath9k_hw_puttxbuf(struct ath_hw *ah, u32 q, u32 txdp); | 688 | void ath9k_hw_puttxbuf(struct ath_hw *ah, u32 q, u32 txdp); |
689 | void ath9k_hw_txstart(struct ath_hw *ah, u32 q); | 689 | void ath9k_hw_txstart(struct ath_hw *ah, u32 q); |
690 | void ath9k_hw_cleartxdesc(struct ath_hw *ah, void *ds); | ||
690 | u32 ath9k_hw_numtxpending(struct ath_hw *ah, u32 q); | 691 | u32 ath9k_hw_numtxpending(struct ath_hw *ah, u32 q); |
691 | bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel); | 692 | bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel); |
692 | bool ath9k_hw_stoptxdma(struct ath_hw *ah, u32 q); | 693 | bool ath9k_hw_stoptxdma(struct ath_hw *ah, u32 q); |
693 | void ath9k_hw_filltxdesc(struct ath_hw *ah, struct ath_desc *ds, | ||
694 | u32 segLen, bool firstSeg, | ||
695 | bool lastSeg, const struct ath_desc *ds0, | ||
696 | dma_addr_t buf_addr); | ||
697 | void ath9k_hw_cleartxdesc(struct ath_hw *ah, struct ath_desc *ds); | ||
698 | int ath9k_hw_txprocdesc(struct ath_hw *ah, struct ath_desc *ds, | ||
699 | struct ath_tx_status *ts); | ||
700 | void ath9k_hw_set11n_txdesc(struct ath_hw *ah, struct ath_desc *ds, | ||
701 | u32 pktLen, enum ath9k_pkt_type type, u32 txPower, | ||
702 | u32 keyIx, enum ath9k_key_type keyType, u32 flags); | ||
703 | void ath9k_hw_set11n_ratescenario(struct ath_hw *ah, struct ath_desc *ds, | ||
704 | struct ath_desc *lastds, | ||
705 | u32 durUpdateEn, u32 rtsctsRate, | ||
706 | u32 rtsctsDuration, | ||
707 | struct ath9k_11n_rate_series series[], | ||
708 | u32 nseries, u32 flags); | ||
709 | void ath9k_hw_set11n_aggr_first(struct ath_hw *ah, struct ath_desc *ds, | ||
710 | u32 aggrLen); | ||
711 | void ath9k_hw_set11n_aggr_middle(struct ath_hw *ah, struct ath_desc *ds, | ||
712 | u32 numDelims); | ||
713 | void ath9k_hw_set11n_aggr_last(struct ath_hw *ah, struct ath_desc *ds); | ||
714 | void ath9k_hw_clr11n_aggr(struct ath_hw *ah, struct ath_desc *ds); | ||
715 | void ath9k_hw_set11n_burstduration(struct ath_hw *ah, struct ath_desc *ds, | ||
716 | u32 burstDuration); | ||
717 | void ath9k_hw_set11n_virtualmorefrag(struct ath_hw *ah, struct ath_desc *ds, | ||
718 | u32 vmf); | ||
719 | void ath9k_hw_gettxintrtxqs(struct ath_hw *ah, u32 *txqs); | 694 | void ath9k_hw_gettxintrtxqs(struct ath_hw *ah, u32 *txqs); |
720 | bool ath9k_hw_set_txq_props(struct ath_hw *ah, int q, | 695 | bool ath9k_hw_set_txq_props(struct ath_hw *ah, int q, |
721 | const struct ath9k_tx_queue_info *qinfo); | 696 | const struct ath9k_tx_queue_info *qinfo); |
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 6ab20992ba30..550253fe61fb 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c | |||
@@ -1669,7 +1669,8 @@ static void ath_tx_start_dma(struct ath_softc *sc, struct ath_buf *bf, | |||
1669 | true, /* first segment */ | 1669 | true, /* first segment */ |
1670 | true, /* last segment */ | 1670 | true, /* last segment */ |
1671 | ds, /* first descriptor */ | 1671 | ds, /* first descriptor */ |
1672 | bf->bf_buf_addr); | 1672 | bf->bf_buf_addr, |
1673 | txctl->txq->axq_qnum); | ||
1673 | 1674 | ||
1674 | spin_lock_bh(&txctl->txq->axq_lock); | 1675 | spin_lock_bh(&txctl->txq->axq_lock); |
1675 | 1676 | ||