diff options
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/ar9003_mac.c')
-rw-r--r-- | drivers/net/wireless/ath/ath9k/ar9003_mac.c | 331 |
1 files changed, 127 insertions, 204 deletions
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.c b/drivers/net/wireless/ath/ath9k/ar9003_mac.c index d08ab930e430..6cabc85bf61b 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c | |||
@@ -21,6 +21,132 @@ static void ar9003_hw_rx_enable(struct ath_hw *hw) | |||
21 | REG_WRITE(hw, AR_CR, 0); | 21 | REG_WRITE(hw, AR_CR, 0); |
22 | } | 22 | } |
23 | 23 | ||
24 | static void | ||
25 | ar9003_set_txdesc(struct ath_hw *ah, void *ds, struct ath_tx_info *i) | ||
26 | { | ||
27 | struct ar9003_txc *ads = ds; | ||
28 | int checksum = 0; | ||
29 | u32 val, ctl12, ctl17; | ||
30 | |||
31 | val = (ATHEROS_VENDOR_ID << AR_DescId_S) | | ||
32 | (1 << AR_TxRxDesc_S) | | ||
33 | (1 << AR_CtrlStat_S) | | ||
34 | (i->qcu << AR_TxQcuNum_S) | 0x17; | ||
35 | |||
36 | checksum += val; | ||
37 | ACCESS_ONCE(ads->info) = val; | ||
38 | |||
39 | checksum += i->link; | ||
40 | ACCESS_ONCE(ads->link) = i->link; | ||
41 | |||
42 | checksum += i->buf_addr[0]; | ||
43 | ACCESS_ONCE(ads->data0) = i->buf_addr[0]; | ||
44 | checksum += i->buf_addr[1]; | ||
45 | ACCESS_ONCE(ads->data1) = i->buf_addr[1]; | ||
46 | checksum += i->buf_addr[2]; | ||
47 | ACCESS_ONCE(ads->data2) = i->buf_addr[2]; | ||
48 | checksum += i->buf_addr[3]; | ||
49 | ACCESS_ONCE(ads->data3) = i->buf_addr[3]; | ||
50 | |||
51 | checksum += (val = (i->buf_len[0] << AR_BufLen_S) & AR_BufLen); | ||
52 | ACCESS_ONCE(ads->ctl3) = val; | ||
53 | checksum += (val = (i->buf_len[1] << AR_BufLen_S) & AR_BufLen); | ||
54 | ACCESS_ONCE(ads->ctl5) = val; | ||
55 | checksum += (val = (i->buf_len[2] << AR_BufLen_S) & AR_BufLen); | ||
56 | ACCESS_ONCE(ads->ctl7) = val; | ||
57 | checksum += (val = (i->buf_len[3] << AR_BufLen_S) & AR_BufLen); | ||
58 | ACCESS_ONCE(ads->ctl9) = val; | ||
59 | |||
60 | checksum = (u16) (((checksum & 0xffff) + (checksum >> 16)) & 0xffff); | ||
61 | ACCESS_ONCE(ads->ctl10) = checksum; | ||
62 | |||
63 | if (i->is_first || i->is_last) { | ||
64 | ACCESS_ONCE(ads->ctl13) = set11nTries(i->rates, 0) | ||
65 | | set11nTries(i->rates, 1) | ||
66 | | set11nTries(i->rates, 2) | ||
67 | | set11nTries(i->rates, 3) | ||
68 | | (i->dur_update ? AR_DurUpdateEna : 0) | ||
69 | | SM(0, AR_BurstDur); | ||
70 | |||
71 | ACCESS_ONCE(ads->ctl14) = set11nRate(i->rates, 0) | ||
72 | | set11nRate(i->rates, 1) | ||
73 | | set11nRate(i->rates, 2) | ||
74 | | set11nRate(i->rates, 3); | ||
75 | } else { | ||
76 | ACCESS_ONCE(ads->ctl13) = 0; | ||
77 | ACCESS_ONCE(ads->ctl14) = 0; | ||
78 | } | ||
79 | |||
80 | ads->ctl20 = 0; | ||
81 | ads->ctl21 = 0; | ||
82 | ads->ctl22 = 0; | ||
83 | |||
84 | ctl17 = SM(i->keytype, AR_EncrType); | ||
85 | if (!i->is_first) { | ||
86 | ACCESS_ONCE(ads->ctl11) = 0; | ||
87 | ACCESS_ONCE(ads->ctl12) = i->is_last ? 0 : AR_TxMore; | ||
88 | ACCESS_ONCE(ads->ctl15) = 0; | ||
89 | ACCESS_ONCE(ads->ctl16) = 0; | ||
90 | ACCESS_ONCE(ads->ctl17) = ctl17; | ||
91 | ACCESS_ONCE(ads->ctl18) = 0; | ||
92 | ACCESS_ONCE(ads->ctl19) = 0; | ||
93 | return; | ||
94 | } | ||
95 | |||
96 | ACCESS_ONCE(ads->ctl11) = (i->pkt_len & AR_FrameLen) | ||
97 | | (i->flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0) | ||
98 | | SM(i->txpower, AR_XmitPower) | ||
99 | | (i->flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0) | ||
100 | | (i->keyix != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0) | ||
101 | | (i->flags & ATH9K_TXDESC_LOWRXCHAIN ? AR_LowRxChain : 0) | ||
102 | | (i->flags & ATH9K_TXDESC_CLRDMASK ? AR_ClrDestMask : 0) | ||
103 | | (i->flags & ATH9K_TXDESC_RTSENA ? AR_RTSEnable : | ||
104 | (i->flags & ATH9K_TXDESC_CTSENA ? AR_CTSEnable : 0)); | ||
105 | |||
106 | ctl12 = (i->keyix != ATH9K_TXKEYIX_INVALID ? | ||
107 | SM(i->keyix, AR_DestIdx) : 0) | ||
108 | | SM(i->type, AR_FrameType) | ||
109 | | (i->flags & ATH9K_TXDESC_NOACK ? AR_NoAck : 0) | ||
110 | | (i->flags & ATH9K_TXDESC_EXT_ONLY ? AR_ExtOnly : 0) | ||
111 | | (i->flags & ATH9K_TXDESC_EXT_AND_CTL ? AR_ExtAndCtl : 0); | ||
112 | |||
113 | ctl17 |= (i->flags & ATH9K_TXDESC_LDPC ? AR_LDPC : 0); | ||
114 | switch (i->aggr) { | ||
115 | case AGGR_BUF_FIRST: | ||
116 | ctl17 |= SM(i->aggr_len, AR_AggrLen); | ||
117 | /* fall through */ | ||
118 | case AGGR_BUF_MIDDLE: | ||
119 | ctl12 |= AR_IsAggr | AR_MoreAggr; | ||
120 | ctl17 |= SM(i->ndelim, AR_PadDelim); | ||
121 | break; | ||
122 | case AGGR_BUF_LAST: | ||
123 | ctl12 |= AR_IsAggr; | ||
124 | break; | ||
125 | case AGGR_BUF_NONE: | ||
126 | break; | ||
127 | } | ||
128 | |||
129 | val = (i->flags & ATH9K_TXDESC_PAPRD) >> ATH9K_TXDESC_PAPRD_S; | ||
130 | ctl12 |= SM(val, AR_PAPRDChainMask); | ||
131 | |||
132 | ACCESS_ONCE(ads->ctl12) = ctl12; | ||
133 | ACCESS_ONCE(ads->ctl17) = ctl17; | ||
134 | |||
135 | ACCESS_ONCE(ads->ctl15) = set11nPktDurRTSCTS(i->rates, 0) | ||
136 | | set11nPktDurRTSCTS(i->rates, 1); | ||
137 | |||
138 | ACCESS_ONCE(ads->ctl16) = set11nPktDurRTSCTS(i->rates, 2) | ||
139 | | set11nPktDurRTSCTS(i->rates, 3); | ||
140 | |||
141 | ACCESS_ONCE(ads->ctl18) = set11nRateFlags(i->rates, 0) | ||
142 | | set11nRateFlags(i->rates, 1) | ||
143 | | set11nRateFlags(i->rates, 2) | ||
144 | | set11nRateFlags(i->rates, 3) | ||
145 | | SM(i->rtscts_rate, AR_RTSCTSRate); | ||
146 | |||
147 | ACCESS_ONCE(ads->ctl19) = AR_Not_Sounding; | ||
148 | } | ||
149 | |||
24 | static u16 ar9003_calc_ptr_chksum(struct ar9003_txc *ads) | 150 | static u16 ar9003_calc_ptr_chksum(struct ar9003_txc *ads) |
25 | { | 151 | { |
26 | int checksum; | 152 | int checksum; |
@@ -185,47 +311,6 @@ static bool ar9003_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked) | |||
185 | return true; | 311 | return true; |
186 | } | 312 | } |
187 | 313 | ||
188 | static void ar9003_hw_fill_txdesc(struct ath_hw *ah, void *ds, u32 seglen, | ||
189 | bool is_firstseg, bool is_lastseg, | ||
190 | const void *ds0, dma_addr_t buf_addr, | ||
191 | unsigned int qcu) | ||
192 | { | ||
193 | struct ar9003_txc *ads = (struct ar9003_txc *) ds; | ||
194 | unsigned int descid = 0; | ||
195 | |||
196 | ads->info = (ATHEROS_VENDOR_ID << AR_DescId_S) | | ||
197 | (1 << AR_TxRxDesc_S) | | ||
198 | (1 << AR_CtrlStat_S) | | ||
199 | (qcu << AR_TxQcuNum_S) | 0x17; | ||
200 | |||
201 | ads->data0 = buf_addr; | ||
202 | ads->data1 = 0; | ||
203 | ads->data2 = 0; | ||
204 | ads->data3 = 0; | ||
205 | |||
206 | ads->ctl3 = (seglen << AR_BufLen_S); | ||
207 | ads->ctl3 &= AR_BufLen; | ||
208 | |||
209 | /* Fill in pointer checksum and descriptor id */ | ||
210 | ads->ctl10 = ar9003_calc_ptr_chksum(ads); | ||
211 | ads->ctl10 |= (descid << AR_TxDescId_S); | ||
212 | |||
213 | if (is_firstseg) { | ||
214 | ads->ctl12 |= (is_lastseg ? 0 : AR_TxMore); | ||
215 | } else if (is_lastseg) { | ||
216 | ads->ctl11 = 0; | ||
217 | ads->ctl12 = 0; | ||
218 | ads->ctl13 = AR9003TXC_CONST(ds0)->ctl13; | ||
219 | ads->ctl14 = AR9003TXC_CONST(ds0)->ctl14; | ||
220 | } else { | ||
221 | /* XXX Intermediate descriptor in a multi-descriptor frame.*/ | ||
222 | ads->ctl11 = 0; | ||
223 | ads->ctl12 = AR_TxMore; | ||
224 | ads->ctl13 = 0; | ||
225 | ads->ctl14 = 0; | ||
226 | } | ||
227 | } | ||
228 | |||
229 | static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds, | 314 | static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds, |
230 | struct ath_tx_status *ts) | 315 | struct ath_tx_status *ts) |
231 | { | 316 | { |
@@ -310,161 +395,6 @@ static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds, | |||
310 | return 0; | 395 | return 0; |
311 | } | 396 | } |
312 | 397 | ||
313 | static void ar9003_hw_set11n_txdesc(struct ath_hw *ah, void *ds, | ||
314 | u32 pktlen, enum ath9k_pkt_type type, u32 txpower, | ||
315 | u8 keyIx, enum ath9k_key_type keyType, u32 flags) | ||
316 | { | ||
317 | struct ar9003_txc *ads = (struct ar9003_txc *) ds; | ||
318 | |||
319 | if (txpower > ah->txpower_limit) | ||
320 | txpower = ah->txpower_limit; | ||
321 | |||
322 | if (txpower > 63) | ||
323 | txpower = 63; | ||
324 | |||
325 | ads->ctl11 = (pktlen & AR_FrameLen) | ||
326 | | (flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0) | ||
327 | | SM(txpower, AR_XmitPower) | ||
328 | | (flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0) | ||
329 | | (keyIx != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0) | ||
330 | | (flags & ATH9K_TXDESC_LOWRXCHAIN ? AR_LowRxChain : 0); | ||
331 | |||
332 | ads->ctl12 = | ||
333 | (keyIx != ATH9K_TXKEYIX_INVALID ? SM(keyIx, AR_DestIdx) : 0) | ||
334 | | SM(type, AR_FrameType) | ||
335 | | (flags & ATH9K_TXDESC_NOACK ? AR_NoAck : 0) | ||
336 | | (flags & ATH9K_TXDESC_EXT_ONLY ? AR_ExtOnly : 0) | ||
337 | | (flags & ATH9K_TXDESC_EXT_AND_CTL ? AR_ExtAndCtl : 0); | ||
338 | |||
339 | ads->ctl17 = SM(keyType, AR_EncrType) | | ||
340 | (flags & ATH9K_TXDESC_LDPC ? AR_LDPC : 0); | ||
341 | ads->ctl18 = 0; | ||
342 | ads->ctl19 = AR_Not_Sounding; | ||
343 | |||
344 | ads->ctl20 = 0; | ||
345 | ads->ctl21 = 0; | ||
346 | ads->ctl22 = 0; | ||
347 | } | ||
348 | |||
349 | static void ar9003_hw_set_clrdmask(struct ath_hw *ah, void *ds, bool val) | ||
350 | { | ||
351 | struct ar9003_txc *ads = (struct ar9003_txc *) ds; | ||
352 | |||
353 | if (val) | ||
354 | ads->ctl11 |= AR_ClrDestMask; | ||
355 | else | ||
356 | ads->ctl11 &= ~AR_ClrDestMask; | ||
357 | } | ||
358 | |||
359 | static void ar9003_hw_set11n_ratescenario(struct ath_hw *ah, void *ds, | ||
360 | void *lastds, | ||
361 | u32 durUpdateEn, u32 rtsctsRate, | ||
362 | u32 rtsctsDuration, | ||
363 | struct ath9k_11n_rate_series series[], | ||
364 | u32 nseries, u32 flags) | ||
365 | { | ||
366 | struct ar9003_txc *ads = (struct ar9003_txc *) ds; | ||
367 | struct ar9003_txc *last_ads = (struct ar9003_txc *) lastds; | ||
368 | u_int32_t ctl11; | ||
369 | |||
370 | if (flags & (ATH9K_TXDESC_RTSENA | ATH9K_TXDESC_CTSENA)) { | ||
371 | ctl11 = ads->ctl11; | ||
372 | |||
373 | if (flags & ATH9K_TXDESC_RTSENA) { | ||
374 | ctl11 &= ~AR_CTSEnable; | ||
375 | ctl11 |= AR_RTSEnable; | ||
376 | } else { | ||
377 | ctl11 &= ~AR_RTSEnable; | ||
378 | ctl11 |= AR_CTSEnable; | ||
379 | } | ||
380 | |||
381 | ads->ctl11 = ctl11; | ||
382 | } else { | ||
383 | ads->ctl11 = (ads->ctl11 & ~(AR_RTSEnable | AR_CTSEnable)); | ||
384 | } | ||
385 | |||
386 | ads->ctl13 = set11nTries(series, 0) | ||
387 | | set11nTries(series, 1) | ||
388 | | set11nTries(series, 2) | ||
389 | | set11nTries(series, 3) | ||
390 | | (durUpdateEn ? AR_DurUpdateEna : 0) | ||
391 | | SM(0, AR_BurstDur); | ||
392 | |||
393 | ads->ctl14 = set11nRate(series, 0) | ||
394 | | set11nRate(series, 1) | ||
395 | | set11nRate(series, 2) | ||
396 | | set11nRate(series, 3); | ||
397 | |||
398 | ads->ctl15 = set11nPktDurRTSCTS(series, 0) | ||
399 | | set11nPktDurRTSCTS(series, 1); | ||
400 | |||
401 | ads->ctl16 = set11nPktDurRTSCTS(series, 2) | ||
402 | | set11nPktDurRTSCTS(series, 3); | ||
403 | |||
404 | ads->ctl18 = set11nRateFlags(series, 0) | ||
405 | | set11nRateFlags(series, 1) | ||
406 | | set11nRateFlags(series, 2) | ||
407 | | set11nRateFlags(series, 3) | ||
408 | | SM(rtsctsRate, AR_RTSCTSRate); | ||
409 | ads->ctl19 = AR_Not_Sounding; | ||
410 | |||
411 | last_ads->ctl13 = ads->ctl13; | ||
412 | last_ads->ctl14 = ads->ctl14; | ||
413 | } | ||
414 | |||
415 | static void ar9003_hw_set11n_aggr_first(struct ath_hw *ah, void *ds, | ||
416 | u32 aggrLen) | ||
417 | { | ||
418 | struct ar9003_txc *ads = (struct ar9003_txc *) ds; | ||
419 | |||
420 | ads->ctl12 |= (AR_IsAggr | AR_MoreAggr); | ||
421 | |||
422 | ads->ctl17 &= ~AR_AggrLen; | ||
423 | ads->ctl17 |= SM(aggrLen, AR_AggrLen); | ||
424 | } | ||
425 | |||
426 | static void ar9003_hw_set11n_aggr_middle(struct ath_hw *ah, void *ds, | ||
427 | u32 numDelims) | ||
428 | { | ||
429 | struct ar9003_txc *ads = (struct ar9003_txc *) ds; | ||
430 | unsigned int ctl17; | ||
431 | |||
432 | ads->ctl12 |= (AR_IsAggr | AR_MoreAggr); | ||
433 | |||
434 | /* | ||
435 | * We use a stack variable to manipulate ctl6 to reduce uncached | ||
436 | * read modify, modfiy, write. | ||
437 | */ | ||
438 | ctl17 = ads->ctl17; | ||
439 | ctl17 &= ~AR_PadDelim; | ||
440 | ctl17 |= SM(numDelims, AR_PadDelim); | ||
441 | ads->ctl17 = ctl17; | ||
442 | } | ||
443 | |||
444 | static void ar9003_hw_set11n_aggr_last(struct ath_hw *ah, void *ds) | ||
445 | { | ||
446 | struct ar9003_txc *ads = (struct ar9003_txc *) ds; | ||
447 | |||
448 | ads->ctl12 |= AR_IsAggr; | ||
449 | ads->ctl12 &= ~AR_MoreAggr; | ||
450 | ads->ctl17 &= ~AR_PadDelim; | ||
451 | } | ||
452 | |||
453 | static void ar9003_hw_clr11n_aggr(struct ath_hw *ah, void *ds) | ||
454 | { | ||
455 | struct ar9003_txc *ads = (struct ar9003_txc *) ds; | ||
456 | |||
457 | ads->ctl12 &= (~AR_IsAggr & ~AR_MoreAggr); | ||
458 | } | ||
459 | |||
460 | void ar9003_hw_set_paprd_txdesc(struct ath_hw *ah, void *ds, u8 chains) | ||
461 | { | ||
462 | struct ar9003_txc *ads = ds; | ||
463 | |||
464 | ads->ctl12 |= SM(chains, AR_PAPRDChainMask); | ||
465 | } | ||
466 | EXPORT_SYMBOL(ar9003_hw_set_paprd_txdesc); | ||
467 | |||
468 | void ar9003_hw_attach_mac_ops(struct ath_hw *hw) | 398 | void ar9003_hw_attach_mac_ops(struct ath_hw *hw) |
469 | { | 399 | { |
470 | struct ath_hw_ops *ops = ath9k_hw_ops(hw); | 400 | struct ath_hw_ops *ops = ath9k_hw_ops(hw); |
@@ -472,15 +402,8 @@ void ar9003_hw_attach_mac_ops(struct ath_hw *hw) | |||
472 | ops->rx_enable = ar9003_hw_rx_enable; | 402 | ops->rx_enable = ar9003_hw_rx_enable; |
473 | ops->set_desc_link = ar9003_hw_set_desc_link; | 403 | ops->set_desc_link = ar9003_hw_set_desc_link; |
474 | ops->get_isr = ar9003_hw_get_isr; | 404 | ops->get_isr = ar9003_hw_get_isr; |
475 | ops->fill_txdesc = ar9003_hw_fill_txdesc; | 405 | ops->set_txdesc = ar9003_set_txdesc; |
476 | ops->proc_txdesc = ar9003_hw_proc_txdesc; | 406 | ops->proc_txdesc = ar9003_hw_proc_txdesc; |
477 | ops->set11n_txdesc = ar9003_hw_set11n_txdesc; | ||
478 | ops->set11n_ratescenario = ar9003_hw_set11n_ratescenario; | ||
479 | ops->set11n_aggr_first = ar9003_hw_set11n_aggr_first; | ||
480 | ops->set11n_aggr_middle = ar9003_hw_set11n_aggr_middle; | ||
481 | ops->set11n_aggr_last = ar9003_hw_set11n_aggr_last; | ||
482 | ops->clr11n_aggr = ar9003_hw_clr11n_aggr; | ||
483 | ops->set_clrdmask = ar9003_hw_set_clrdmask; | ||
484 | } | 407 | } |
485 | 408 | ||
486 | void ath9k_hw_set_rx_bufsize(struct ath_hw *ah, u16 buf_size) | 409 | void ath9k_hw_set_rx_bufsize(struct ath_hw *ah, u16 buf_size) |