aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVasanthakumar Thiagarajan <vasanth@atheros.com>2010-04-15 17:39:26 -0400
committerJohn W. Linville <linville@tuxdriver.com>2010-04-16 15:43:44 -0400
commitcc610ac0557b0ad0dcffdff1230cef28a970d755 (patch)
tree975cd15e3d2b42a2b1a5b7a178c595dd35a1b77c
parentd8903a5361817bd96ceed212ad27a380e7ef4d8e (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.c73
-rw-r--r--drivers/net/wireless/ath/ath9k/beacon.c3
-rw-r--r--drivers/net/wireless/ath/ath9k/hw-ops.h71
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.h27
-rw-r--r--drivers/net/wireless/ath/ath9k/mac.c508
-rw-r--r--drivers/net/wireless/ath/ath9k/mac.h27
-rw-r--r--drivers/net/wireless/ath/ath9k/xmit.c3
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
170static 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
177static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds,
178 struct ath_tx_status *ts)
179{
180 return 0;
181}
182static 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
189static 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
199static void ar9003_hw_set11n_aggr_first(struct ath_hw *ah, void *ds,
200 u32 aggrLen)
201{
202
203}
204
205static void ar9003_hw_set11n_aggr_middle(struct ath_hw *ah, void *ds,
206 u32 numDelims)
207{
208
209}
210
211static void ar9003_hw_set11n_aggr_last(struct ath_hw *ah, void *ds)
212{
213
214}
215
216static void ar9003_hw_clr11n_aggr(struct ath_hw *ah, void *ds)
217{
218
219}
220
221static void ar9003_hw_set11n_burstduration(struct ath_hw *ah, void *ds,
222 u32 burstDuration)
223{
224
225}
226
227static void ar9003_hw_set11n_virtualmorefrag(struct ath_hw *ah, void *ds,
228 u32 vmf)
229{
230
231}
232
170void ar9003_hw_attach_mac_ops(struct ath_hw *hw) 233void 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
180void ath9k_hw_set_rx_bufsize(struct ath_hw *ah, u16 buf_size) 253void 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
60static 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
69static 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
75static 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
85static 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
97static 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
103static 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
109static 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
114static inline void ath9k_hw_clr11n_aggr(struct ath_hw *ah, void *ds)
115{
116 ath9k_hw_ops(ah)->clr11n_aggr(ah, ds);
117}
118
119static 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
125static 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
561struct ath_hw { 588struct 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
186void ar9002_hw_attach_mac_ops(struct ath_hw *ah) 186static 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
196static 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
217u32 ath9k_hw_gettxbuf(struct ath_hw *ah, u32 q)
218{
219 return REG_READ(ah, AR_QTXDP(q));
220}
221EXPORT_SYMBOL(ath9k_hw_gettxbuf);
222
223void ath9k_hw_puttxbuf(struct ath_hw *ah, u32 q, u32 txdp)
224{
225 REG_WRITE(ah, AR_QTXDP(q), txdp);
226}
227EXPORT_SYMBOL(ath9k_hw_puttxbuf);
228
229void 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}
235EXPORT_SYMBOL(ath9k_hw_txstart);
236
237u32 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}
250EXPORT_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 */
277bool 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}
305EXPORT_SYMBOL(ath9k_hw_updatetxtriglevel);
306
307bool 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}
385EXPORT_SYMBOL(ath9k_hw_stoptxdma);
386
387void 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}
415EXPORT_SYMBOL(ath9k_hw_filltxdesc);
416 214
417void ath9k_hw_cleartxdesc(struct ath_hw *ah, struct ath_desc *ds) 215static 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}
427EXPORT_SYMBOL(ath9k_hw_cleartxdesc);
428
429int 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}
506EXPORT_SYMBOL(ath9k_hw_txprocdesc);
507 292
508void ath9k_hw_set11n_txdesc(struct ath_hw *ah, struct ath_desc *ds, 293static 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}
542EXPORT_SYMBOL(ath9k_hw_set11n_txdesc); 328
543 329static void ar9002_hw_set11n_ratescenario(struct ath_hw *ah, void *ds,
544void 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}
598EXPORT_SYMBOL(ath9k_hw_set11n_ratescenario);
599 383
600void ath9k_hw_set11n_aggr_first(struct ath_hw *ah, struct ath_desc *ds, 384static 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}
609EXPORT_SYMBOL(ath9k_hw_set11n_aggr_first);
610 393
611void ath9k_hw_set11n_aggr_middle(struct ath_hw *ah, struct ath_desc *ds, 394static 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}
624EXPORT_SYMBOL(ath9k_hw_set11n_aggr_middle);
625 407
626void ath9k_hw_set11n_aggr_last(struct ath_hw *ah, struct ath_desc *ds) 408static 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}
634EXPORT_SYMBOL(ath9k_hw_set11n_aggr_last);
635 416
636void ath9k_hw_clr11n_aggr(struct ath_hw *ah, struct ath_desc *ds) 417static 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}
642EXPORT_SYMBOL(ath9k_hw_clr11n_aggr);
643 423
644void ath9k_hw_set11n_burstduration(struct ath_hw *ah, struct ath_desc *ds, 424static 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}
652EXPORT_SYMBOL(ath9k_hw_set11n_burstduration);
653 432
654void ath9k_hw_set11n_virtualmorefrag(struct ath_hw *ah, struct ath_desc *ds, 433static 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
444void 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
464static 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
485u32 ath9k_hw_gettxbuf(struct ath_hw *ah, u32 q)
486{
487 return REG_READ(ah, AR_QTXDP(q));
488}
489EXPORT_SYMBOL(ath9k_hw_gettxbuf);
490
491void ath9k_hw_puttxbuf(struct ath_hw *ah, u32 q, u32 txdp)
492{
493 REG_WRITE(ah, AR_QTXDP(q), txdp);
494}
495EXPORT_SYMBOL(ath9k_hw_puttxbuf);
496
497void 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}
503EXPORT_SYMBOL(ath9k_hw_txstart);
504
505void 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}
515EXPORT_SYMBOL(ath9k_hw_cleartxdesc);
516
517u32 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}
530EXPORT_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 */
557bool 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}
585EXPORT_SYMBOL(ath9k_hw_updatetxtriglevel);
586
587bool 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}
665EXPORT_SYMBOL(ath9k_hw_stoptxdma);
666
665void ath9k_hw_gettxintrtxqs(struct ath_hw *ah, u32 *txqs) 667void 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;
687u32 ath9k_hw_gettxbuf(struct ath_hw *ah, u32 q); 687u32 ath9k_hw_gettxbuf(struct ath_hw *ah, u32 q);
688void ath9k_hw_puttxbuf(struct ath_hw *ah, u32 q, u32 txdp); 688void ath9k_hw_puttxbuf(struct ath_hw *ah, u32 q, u32 txdp);
689void ath9k_hw_txstart(struct ath_hw *ah, u32 q); 689void ath9k_hw_txstart(struct ath_hw *ah, u32 q);
690void ath9k_hw_cleartxdesc(struct ath_hw *ah, void *ds);
690u32 ath9k_hw_numtxpending(struct ath_hw *ah, u32 q); 691u32 ath9k_hw_numtxpending(struct ath_hw *ah, u32 q);
691bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel); 692bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel);
692bool ath9k_hw_stoptxdma(struct ath_hw *ah, u32 q); 693bool ath9k_hw_stoptxdma(struct ath_hw *ah, u32 q);
693void 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);
697void ath9k_hw_cleartxdesc(struct ath_hw *ah, struct ath_desc *ds);
698int ath9k_hw_txprocdesc(struct ath_hw *ah, struct ath_desc *ds,
699 struct ath_tx_status *ts);
700void 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);
703void 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);
709void ath9k_hw_set11n_aggr_first(struct ath_hw *ah, struct ath_desc *ds,
710 u32 aggrLen);
711void ath9k_hw_set11n_aggr_middle(struct ath_hw *ah, struct ath_desc *ds,
712 u32 numDelims);
713void ath9k_hw_set11n_aggr_last(struct ath_hw *ah, struct ath_desc *ds);
714void ath9k_hw_clr11n_aggr(struct ath_hw *ah, struct ath_desc *ds);
715void ath9k_hw_set11n_burstduration(struct ath_hw *ah, struct ath_desc *ds,
716 u32 burstDuration);
717void ath9k_hw_set11n_virtualmorefrag(struct ath_hw *ah, struct ath_desc *ds,
718 u32 vmf);
719void ath9k_hw_gettxintrtxqs(struct ath_hw *ah, u32 *txqs); 694void ath9k_hw_gettxintrtxqs(struct ath_hw *ah, u32 *txqs);
720bool ath9k_hw_set_txq_props(struct ath_hw *ah, int q, 695bool 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