blob: 743ad228b833675262d5e3b5036729ff2926d41b [file] [log] [blame]
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001/*
2 * Copyright (c) 2008 Atheros Communications Inc.
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
Luis R. Rodriguezf078f202008-08-04 00:16:41 -070017#include "core.h"
18
19/*
20 * Setup and link descriptors.
21 *
22 * 11N: we can no longer afford to self link the last descriptor.
23 * MAC acknowledges BA status as long as it copies frames to host
24 * buffer (or rx fifo). This can incorrectly acknowledge packets
25 * to a sender if last desc is self-linked.
Luis R. Rodriguezf078f202008-08-04 00:16:41 -070026 */
Luis R. Rodriguezf078f202008-08-04 00:16:41 -070027static void ath_rx_buf_link(struct ath_softc *sc, struct ath_buf *bf)
28{
29 struct ath_hal *ah = sc->sc_ah;
30 struct ath_desc *ds;
31 struct sk_buff *skb;
32
33 ATH_RXBUF_RESET(bf);
34
35 ds = bf->bf_desc;
Sujithbe0418a2008-11-18 09:05:55 +053036 ds->ds_link = 0; /* link to null */
Luis R. Rodriguezf078f202008-08-04 00:16:41 -070037 ds->ds_data = bf->bf_buf_addr;
38
Sujithbe0418a2008-11-18 09:05:55 +053039 /* virtual addr of the beginning of the buffer. */
Luis R. Rodriguezf078f202008-08-04 00:16:41 -070040 skb = bf->bf_mpdu;
41 ASSERT(skb != NULL);
42 ds->ds_vdata = skb->data;
43
44 /* setup rx descriptors */
Sujithbe0418a2008-11-18 09:05:55 +053045 ath9k_hw_setuprxdesc(ah, ds,
46 skb_tailroom(skb), /* buffer size */
Luis R. Rodriguezf078f202008-08-04 00:16:41 -070047 0);
48
49 if (sc->sc_rxlink == NULL)
50 ath9k_hw_putrxbuf(ah, bf->bf_daddr);
51 else
52 *sc->sc_rxlink = bf->bf_daddr;
53
54 sc->sc_rxlink = &ds->ds_link;
55 ath9k_hw_rxena(ah);
56}
57
Sujithff37e332008-11-24 12:07:55 +053058static void ath_setdefantenna(struct ath_softc *sc, u32 antenna)
59{
60 /* XXX block beacon interrupts */
61 ath9k_hw_setantenna(sc->sc_ah, antenna);
62 sc->sc_defant = antenna;
63 sc->sc_rxotherant = 0;
64}
65
66/*
67 * Extend 15-bit time stamp from rx descriptor to
68 * a full 64-bit TSF using the current h/w TSF.
69*/
70static u64 ath_extend_tsf(struct ath_softc *sc, u32 rstamp)
71{
72 u64 tsf;
73
74 tsf = ath9k_hw_gettsf64(sc->sc_ah);
75 if ((tsf & 0x7fff) < rstamp)
76 tsf -= 0x8000;
77 return (tsf & ~0x7fff) | rstamp;
78}
79
Sujithbe0418a2008-11-18 09:05:55 +053080static struct sk_buff *ath_rxbuf_alloc(struct ath_softc *sc, u32 len)
Luis R. Rodriguezf078f202008-08-04 00:16:41 -070081{
82 struct sk_buff *skb;
83 u32 off;
84
85 /*
86 * Cache-line-align. This is important (for the
87 * 5210 at least) as not doing so causes bogus data
88 * in rx'd frames.
89 */
90
91 skb = dev_alloc_skb(len + sc->sc_cachelsz - 1);
92 if (skb != NULL) {
93 off = ((unsigned long) skb->data) % sc->sc_cachelsz;
94 if (off != 0)
95 skb_reserve(skb, sc->sc_cachelsz - off);
96 } else {
97 DPRINTF(sc, ATH_DBG_FATAL,
98 "%s: skbuff alloc of size %u failed\n",
99 __func__, len);
100 return NULL;
101 }
102
103 return skb;
104}
105
Sujithbe0418a2008-11-18 09:05:55 +0530106static int ath_rate2idx(struct ath_softc *sc, int rate)
107{
108 int i = 0, cur_band, n_rates;
109 struct ieee80211_hw *hw = sc->hw;
110
111 cur_band = hw->conf.channel->band;
112 n_rates = sc->sbands[cur_band].n_bitrates;
113
114 for (i = 0; i < n_rates; i++) {
115 if (sc->sbands[cur_band].bitrates[i].bitrate == rate)
116 break;
117 }
118
119 /*
120 * NB:mac80211 validates rx rate index against the supported legacy rate
121 * index only (should be done against ht rates also), return the highest
122 * legacy rate index for rx rate which does not match any one of the
123 * supported basic and extended rates to make mac80211 happy.
124 * The following hack will be cleaned up once the issue with
125 * the rx rate index validation in mac80211 is fixed.
126 */
127 if (i == n_rates)
128 return n_rates - 1;
129
130 return i;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700131}
132
133/*
Sujithbe0418a2008-11-18 09:05:55 +0530134 * For Decrypt or Demic errors, we only mark packet status here and always push
135 * up the frame up to let mac80211 handle the actual error case, be it no
136 * decryption key or real decryption error. This let us keep statistics there.
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700137 */
Sujithbe0418a2008-11-18 09:05:55 +0530138static int ath_rx_prepare(struct sk_buff *skb, struct ath_desc *ds,
139 struct ieee80211_rx_status *rx_status, bool *decrypt_error,
140 struct ath_softc *sc)
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700141{
Sujithe63835b2008-11-18 09:07:53 +0530142 struct ath_rate_table *rate_table = sc->hw_rate_table[sc->sc_curmode];
Sujithbe0418a2008-11-18 09:05:55 +0530143 struct ieee80211_hdr *hdr;
Sujithe63835b2008-11-18 09:07:53 +0530144 int ratekbps, rix;
Sujithbe0418a2008-11-18 09:05:55 +0530145 u8 ratecode;
146 __le16 fc;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700147
Sujithbe0418a2008-11-18 09:05:55 +0530148 hdr = (struct ieee80211_hdr *)skb->data;
149 fc = hdr->frame_control;
150 memset(rx_status, 0, sizeof(struct ieee80211_rx_status));
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700151
Sujithbe0418a2008-11-18 09:05:55 +0530152 if (ds->ds_rxstat.rs_more) {
153 /*
154 * Frame spans multiple descriptors; this cannot happen yet
155 * as we don't support jumbograms. If not in monitor mode,
156 * discard the frame. Enable this if you want to see
157 * error frames in Monitor mode.
158 */
159 if (sc->sc_ah->ah_opmode != ATH9K_M_MONITOR)
160 goto rx_next;
161 } else if (ds->ds_rxstat.rs_status != 0) {
162 if (ds->ds_rxstat.rs_status & ATH9K_RXERR_CRC)
163 rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
164 if (ds->ds_rxstat.rs_status & ATH9K_RXERR_PHY)
165 goto rx_next;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700166
Sujithbe0418a2008-11-18 09:05:55 +0530167 if (ds->ds_rxstat.rs_status & ATH9K_RXERR_DECRYPT) {
168 *decrypt_error = true;
169 } else if (ds->ds_rxstat.rs_status & ATH9K_RXERR_MIC) {
170 if (ieee80211_is_ctl(fc))
171 /*
172 * Sometimes, we get invalid
173 * MIC failures on valid control frames.
174 * Remove these mic errors.
175 */
176 ds->ds_rxstat.rs_status &= ~ATH9K_RXERR_MIC;
177 else
178 rx_status->flag |= RX_FLAG_MMIC_ERROR;
179 }
180 /*
181 * Reject error frames with the exception of
182 * decryption and MIC failures. For monitor mode,
183 * we also ignore the CRC error.
184 */
185 if (sc->sc_ah->ah_opmode == ATH9K_M_MONITOR) {
186 if (ds->ds_rxstat.rs_status &
187 ~(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC |
188 ATH9K_RXERR_CRC))
189 goto rx_next;
190 } else {
191 if (ds->ds_rxstat.rs_status &
192 ~(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC)) {
193 goto rx_next;
194 }
195 }
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700196 }
197
Sujithbe0418a2008-11-18 09:05:55 +0530198 ratecode = ds->ds_rxstat.rs_rate;
Sujithe63835b2008-11-18 09:07:53 +0530199 rix = rate_table->rateCodeToIndex[ratecode];
200 ratekbps = rate_table->info[rix].ratekbps;
Sujithbe0418a2008-11-18 09:05:55 +0530201
202 /* HT rate */
203 if (ratecode & 0x80) {
204 if (ds->ds_rxstat.rs_flags & ATH9K_RX_2040)
205 ratekbps = (ratekbps * 27) / 13;
206 if (ds->ds_rxstat.rs_flags & ATH9K_RX_GI)
207 ratekbps = (ratekbps * 10) / 9;
208 }
209
210 rx_status->mactime = ath_extend_tsf(sc, ds->ds_rxstat.rs_tstamp);
211 rx_status->band = sc->hw->conf.channel->band;
212 rx_status->freq = sc->hw->conf.channel->center_freq;
213 rx_status->noise = sc->sc_ani.sc_noise_floor;
214 rx_status->signal = rx_status->noise + ds->ds_rxstat.rs_rssi;
215 rx_status->rate_idx = ath_rate2idx(sc, (ratekbps / 100));
216 rx_status->antenna = ds->ds_rxstat.rs_antenna;
217
218 /* at 45 you will be able to use MCS 15 reliably. A more elaborate
219 * scheme can be used here but it requires tables of SNR/throughput for
220 * each possible mode used. */
221 rx_status->qual = ds->ds_rxstat.rs_rssi * 100 / 45;
222
223 /* rssi can be more than 45 though, anything above that
224 * should be considered at 100% */
225 if (rx_status->qual > 100)
226 rx_status->qual = 100;
227
228 rx_status->flag |= RX_FLAG_TSFT;
229
230 return 1;
231rx_next:
232 return 0;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700233}
234
235static void ath_opmode_init(struct ath_softc *sc)
236{
237 struct ath_hal *ah = sc->sc_ah;
238 u32 rfilt, mfilt[2];
239
240 /* configure rx filter */
241 rfilt = ath_calcrxfilter(sc);
242 ath9k_hw_setrxfilter(ah, rfilt);
243
244 /* configure bssid mask */
Sujith60b67f52008-08-07 10:52:38 +0530245 if (ah->ah_caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK)
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700246 ath9k_hw_setbssidmask(ah, sc->sc_bssidmask);
247
248 /* configure operational mode */
249 ath9k_hw_setopmode(ah);
250
251 /* Handle any link-level address change. */
252 ath9k_hw_setmac(ah, sc->sc_myaddr);
253
254 /* calculate and install multicast filter */
255 mfilt[0] = mfilt[1] = ~0;
256
257 ath9k_hw_setmcastfilter(ah, mfilt[0], mfilt[1]);
258 DPRINTF(sc, ATH_DBG_CONFIG ,
259 "%s: RX filter 0x%x, MC filter %08x:%08x\n",
260 __func__, rfilt, mfilt[0], mfilt[1]);
261}
262
263int ath_rx_init(struct ath_softc *sc, int nbufs)
264{
265 struct sk_buff *skb;
266 struct ath_buf *bf;
267 int error = 0;
268
269 do {
270 spin_lock_init(&sc->sc_rxflushlock);
Sujith98deeea2008-08-11 14:05:46 +0530271 sc->sc_flags &= ~SC_OP_RXFLUSH;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700272 spin_lock_init(&sc->sc_rxbuflock);
273
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700274 sc->sc_rxbufsize = roundup(IEEE80211_MAX_MPDU_LEN,
275 min(sc->sc_cachelsz,
276 (u16)64));
277
278 DPRINTF(sc, ATH_DBG_CONFIG, "%s: cachelsz %u rxbufsize %u\n",
279 __func__, sc->sc_cachelsz, sc->sc_rxbufsize);
280
281 /* Initialize rx descriptors */
282
283 error = ath_descdma_setup(sc, &sc->sc_rxdma, &sc->sc_rxbuf,
284 "rx", nbufs, 1);
285 if (error != 0) {
286 DPRINTF(sc, ATH_DBG_FATAL,
287 "%s: failed to allocate rx descriptors: %d\n",
288 __func__, error);
289 break;
290 }
291
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700292 list_for_each_entry(bf, &sc->sc_rxbuf, list) {
293 skb = ath_rxbuf_alloc(sc, sc->sc_rxbufsize);
294 if (skb == NULL) {
295 error = -ENOMEM;
296 break;
297 }
298
299 bf->bf_mpdu = skb;
Sujith927e70e2008-08-14 13:26:34 +0530300 bf->bf_buf_addr = pci_map_single(sc->pdev, skb->data,
301 skb_end_pointer(skb) - skb->head,
302 PCI_DMA_FROMDEVICE);
303 bf->bf_dmacontext = bf->bf_buf_addr;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700304 }
305 sc->sc_rxlink = NULL;
306
307 } while (0);
308
309 if (error)
310 ath_rx_cleanup(sc);
311
312 return error;
313}
314
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700315void ath_rx_cleanup(struct ath_softc *sc)
316{
317 struct sk_buff *skb;
318 struct ath_buf *bf;
319
320 list_for_each_entry(bf, &sc->sc_rxbuf, list) {
321 skb = bf->bf_mpdu;
322 if (skb)
323 dev_kfree_skb(skb);
324 }
325
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700326 if (sc->sc_rxdma.dd_desc_len != 0)
327 ath_descdma_cleanup(sc, &sc->sc_rxdma, &sc->sc_rxbuf);
328}
329
330/*
331 * Calculate the receive filter according to the
332 * operating mode and state:
333 *
334 * o always accept unicast, broadcast, and multicast traffic
335 * o maintain current state of phy error reception (the hal
336 * may enable phy error frames for noise immunity work)
337 * o probe request frames are accepted only when operating in
338 * hostap, adhoc, or monitor modes
339 * o enable promiscuous mode according to the interface state
340 * o accept beacons:
341 * - when operating in adhoc mode so the 802.11 layer creates
342 * node table entries for peers,
343 * - when operating in station mode for collecting rssi data when
344 * the station is otherwise quiet, or
345 * - when operating as a repeater so we see repeater-sta beacons
346 * - when scanning
347 */
348
349u32 ath_calcrxfilter(struct ath_softc *sc)
350{
351#define RX_FILTER_PRESERVE (ATH9K_RX_FILTER_PHYERR | ATH9K_RX_FILTER_PHYRADAR)
Sujith7dcfdcd2008-08-11 14:03:13 +0530352
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700353 u32 rfilt;
354
355 rfilt = (ath9k_hw_getrxfilter(sc->sc_ah) & RX_FILTER_PRESERVE)
356 | ATH9K_RX_FILTER_UCAST | ATH9K_RX_FILTER_BCAST
357 | ATH9K_RX_FILTER_MCAST;
358
359 /* If not a STA, enable processing of Probe Requests */
Sujithb4696c8b2008-08-11 14:04:52 +0530360 if (sc->sc_ah->ah_opmode != ATH9K_M_STA)
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700361 rfilt |= ATH9K_RX_FILTER_PROBEREQ;
362
363 /* Can't set HOSTAP into promiscous mode */
Sujithb4696c8b2008-08-11 14:04:52 +0530364 if (((sc->sc_ah->ah_opmode != ATH9K_M_HOSTAP) &&
Sujith7dcfdcd2008-08-11 14:03:13 +0530365 (sc->rx_filter & FIF_PROMISC_IN_BSS)) ||
Sujithb4696c8b2008-08-11 14:04:52 +0530366 (sc->sc_ah->ah_opmode == ATH9K_M_MONITOR)) {
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700367 rfilt |= ATH9K_RX_FILTER_PROM;
368 /* ??? To prevent from sending ACK */
369 rfilt &= ~ATH9K_RX_FILTER_UCAST;
370 }
371
Luis R. Rodriguezffb82672008-11-03 14:43:01 -0800372 if (sc->sc_ah->ah_opmode == ATH9K_M_STA ||
Sujithbe0418a2008-11-18 09:05:55 +0530373 sc->sc_ah->ah_opmode == ATH9K_M_IBSS)
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700374 rfilt |= ATH9K_RX_FILTER_BEACON;
375
376 /* If in HOSTAP mode, want to enable reception of PSPOLL frames
377 & beacon frames */
Sujithb4696c8b2008-08-11 14:04:52 +0530378 if (sc->sc_ah->ah_opmode == ATH9K_M_HOSTAP)
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700379 rfilt |= (ATH9K_RX_FILTER_BEACON | ATH9K_RX_FILTER_PSPOLL);
Sujithbe0418a2008-11-18 09:05:55 +0530380
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700381 return rfilt;
Sujith7dcfdcd2008-08-11 14:03:13 +0530382
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700383#undef RX_FILTER_PRESERVE
384}
385
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700386int ath_startrecv(struct ath_softc *sc)
387{
388 struct ath_hal *ah = sc->sc_ah;
389 struct ath_buf *bf, *tbf;
390
391 spin_lock_bh(&sc->sc_rxbuflock);
392 if (list_empty(&sc->sc_rxbuf))
393 goto start_recv;
394
395 sc->sc_rxlink = NULL;
396 list_for_each_entry_safe(bf, tbf, &sc->sc_rxbuf, list) {
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700397 ath_rx_buf_link(sc, bf);
398 }
399
400 /* We could have deleted elements so the list may be empty now */
401 if (list_empty(&sc->sc_rxbuf))
402 goto start_recv;
403
404 bf = list_first_entry(&sc->sc_rxbuf, struct ath_buf, list);
405 ath9k_hw_putrxbuf(ah, bf->bf_daddr);
Sujithbe0418a2008-11-18 09:05:55 +0530406 ath9k_hw_rxena(ah);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700407
408start_recv:
409 spin_unlock_bh(&sc->sc_rxbuflock);
Sujithbe0418a2008-11-18 09:05:55 +0530410 ath_opmode_init(sc);
411 ath9k_hw_startpcureceive(ah);
412
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700413 return 0;
414}
415
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700416bool ath_stoprecv(struct ath_softc *sc)
417{
418 struct ath_hal *ah = sc->sc_ah;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700419 bool stopped;
420
Sujithbe0418a2008-11-18 09:05:55 +0530421 ath9k_hw_stoppcurecv(ah);
422 ath9k_hw_setrxfilter(ah, 0);
423 stopped = ath9k_hw_stopdmarecv(ah);
424 mdelay(3); /* 3ms is long enough for 1 frame */
425 sc->sc_rxlink = NULL;
426
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700427 return stopped;
428}
429
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700430void ath_flushrecv(struct ath_softc *sc)
431{
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700432 spin_lock_bh(&sc->sc_rxflushlock);
Sujith98deeea2008-08-11 14:05:46 +0530433 sc->sc_flags |= SC_OP_RXFLUSH;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700434 ath_rx_tasklet(sc, 1);
Sujith98deeea2008-08-11 14:05:46 +0530435 sc->sc_flags &= ~SC_OP_RXFLUSH;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700436 spin_unlock_bh(&sc->sc_rxflushlock);
437}
438
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700439int ath_rx_tasklet(struct ath_softc *sc, int flush)
440{
441#define PA2DESC(_sc, _pa) \
442 ((struct ath_desc *)((caddr_t)(_sc)->sc_rxdma.dd_desc + \
443 ((_pa) - (_sc)->sc_rxdma.dd_desc_paddr)))
444
Sujithbe0418a2008-11-18 09:05:55 +0530445 struct ath_buf *bf;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700446 struct ath_desc *ds;
Luis R. Rodriguezcb71d9b2008-11-21 17:41:33 -0800447 struct sk_buff *skb = NULL, *requeue_skb;
Sujithbe0418a2008-11-18 09:05:55 +0530448 struct ieee80211_rx_status rx_status;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700449 struct ath_hal *ah = sc->sc_ah;
Sujithbe0418a2008-11-18 09:05:55 +0530450 struct ieee80211_hdr *hdr;
451 int hdrlen, padsize, retval;
452 bool decrypt_error = false;
453 u8 keyix;
454
455 spin_lock_bh(&sc->sc_rxbuflock);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700456
457 do {
458 /* If handling rx interrupt and flush is in progress => exit */
Sujith98deeea2008-08-11 14:05:46 +0530459 if ((sc->sc_flags & SC_OP_RXFLUSH) && (flush == 0))
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700460 break;
461
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700462 if (list_empty(&sc->sc_rxbuf)) {
463 sc->sc_rxlink = NULL;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700464 break;
465 }
466
467 bf = list_first_entry(&sc->sc_rxbuf, struct ath_buf, list);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700468 ds = bf->bf_desc;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700469
470 /*
471 * Must provide the virtual address of the current
472 * descriptor, the physical address, and the virtual
473 * address of the next descriptor in the h/w chain.
474 * This allows the HAL to look ahead to see if the
475 * hardware is done with a descriptor by checking the
476 * done bit in the following descriptor and the address
477 * of the current descriptor the DMA engine is working
478 * on. All this is necessary because of our use of
479 * a self-linked list to avoid rx overruns.
480 */
Sujithbe0418a2008-11-18 09:05:55 +0530481 retval = ath9k_hw_rxprocdesc(ah, ds,
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700482 bf->bf_daddr,
483 PA2DESC(sc, ds->ds_link),
484 0);
485 if (retval == -EINPROGRESS) {
486 struct ath_buf *tbf;
487 struct ath_desc *tds;
488
489 if (list_is_last(&bf->list, &sc->sc_rxbuf)) {
Sujithbe0418a2008-11-18 09:05:55 +0530490 sc->sc_rxlink = NULL;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700491 break;
492 }
493
494 tbf = list_entry(bf->list.next, struct ath_buf, list);
495
496 /*
497 * On some hardware the descriptor status words could
498 * get corrupted, including the done bit. Because of
499 * this, check if the next descriptor's done bit is
500 * set or not.
501 *
502 * If the next descriptor's done bit is set, the current
503 * descriptor has been corrupted. Force s/w to discard
504 * this descriptor and continue...
505 */
506
507 tds = tbf->bf_desc;
Sujithbe0418a2008-11-18 09:05:55 +0530508 retval = ath9k_hw_rxprocdesc(ah, tds, tbf->bf_daddr,
509 PA2DESC(sc, tds->ds_link), 0);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700510 if (retval == -EINPROGRESS) {
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700511 break;
512 }
513 }
514
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700515 skb = bf->bf_mpdu;
Sujithbe0418a2008-11-18 09:05:55 +0530516 if (!skb)
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700517 continue;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700518
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700519 /*
Sujithbe0418a2008-11-18 09:05:55 +0530520 * If we're asked to flush receive queue, directly
521 * chain it back at the queue without processing it.
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700522 */
Sujithbe0418a2008-11-18 09:05:55 +0530523 if (flush)
Luis R. Rodriguezcb71d9b2008-11-21 17:41:33 -0800524 goto requeue;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700525
Sujithbe0418a2008-11-18 09:05:55 +0530526 if (!ds->ds_rxstat.rs_datalen)
Luis R. Rodriguezcb71d9b2008-11-21 17:41:33 -0800527 goto requeue;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700528
Sujithbe0418a2008-11-18 09:05:55 +0530529 /* The status portion of the descriptor could get corrupted. */
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700530 if (sc->sc_rxbufsize < ds->ds_rxstat.rs_datalen)
Luis R. Rodriguezcb71d9b2008-11-21 17:41:33 -0800531 goto requeue;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700532
Sujithbe0418a2008-11-18 09:05:55 +0530533 if (!ath_rx_prepare(skb, ds, &rx_status, &decrypt_error, sc))
Luis R. Rodriguezcb71d9b2008-11-21 17:41:33 -0800534 goto requeue;
535
536 /* Ensure we always have an skb to requeue once we are done
537 * processing the current buffer's skb */
538 requeue_skb = ath_rxbuf_alloc(sc, sc->sc_rxbufsize);
539
540 /* If there is no memory we ignore the current RX'd frame,
541 * tell hardware it can give us a new frame using the old
542 * skb and put it at the tail of the sc->sc_rxbuf list for
543 * processing. */
544 if (!requeue_skb)
545 goto requeue;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700546
Sujithbe0418a2008-11-18 09:05:55 +0530547 /* Sync and unmap the frame */
548 pci_dma_sync_single_for_cpu(sc->pdev, bf->bf_buf_addr,
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700549 skb_tailroom(skb),
550 PCI_DMA_FROMDEVICE);
Sujithbe0418a2008-11-18 09:05:55 +0530551 pci_unmap_single(sc->pdev, bf->bf_buf_addr,
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700552 sc->sc_rxbufsize,
553 PCI_DMA_FROMDEVICE);
554
Sujithbe0418a2008-11-18 09:05:55 +0530555 skb_put(skb, ds->ds_rxstat.rs_datalen);
556 skb->protocol = cpu_to_be16(ETH_P_CONTROL);
557
558 /* see if any padding is done by the hw and remove it */
559 hdr = (struct ieee80211_hdr *)skb->data;
560 hdrlen = ieee80211_get_hdrlen_from_skb(skb);
561
562 if (hdrlen & 3) {
563 padsize = hdrlen % 4;
564 memmove(skb->data + padsize, skb->data, hdrlen);
565 skb_pull(skb, padsize);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700566 }
567
Sujithbe0418a2008-11-18 09:05:55 +0530568 keyix = ds->ds_rxstat.rs_keyix;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700569
Sujithbe0418a2008-11-18 09:05:55 +0530570 if (!(keyix == ATH9K_RXKEYIX_INVALID) && !decrypt_error) {
571 rx_status.flag |= RX_FLAG_DECRYPTED;
572 } else if ((le16_to_cpu(hdr->frame_control) & IEEE80211_FCTL_PROTECTED)
573 && !decrypt_error && skb->len >= hdrlen + 4) {
574 keyix = skb->data[hdrlen + 3] >> 6;
575
576 if (test_bit(keyix, sc->sc_keymap))
577 rx_status.flag |= RX_FLAG_DECRYPTED;
578 }
579
580 /* Send the frame to mac80211 */
581 __ieee80211_rx(sc->hw, skb, &rx_status);
Luis R. Rodriguezcb71d9b2008-11-21 17:41:33 -0800582
583 /* We will now give hardware our shiny new allocated skb */
584 bf->bf_mpdu = requeue_skb;
585 bf->bf_buf_addr = pci_map_single(sc->pdev, requeue_skb->data,
586 sc->sc_rxbufsize,
587 PCI_DMA_FROMDEVICE);
588 bf->bf_dmacontext = bf->bf_buf_addr;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700589
590 /*
591 * change the default rx antenna if rx diversity chooses the
592 * other antenna 3 times in a row.
593 */
594 if (sc->sc_defant != ds->ds_rxstat.rs_antenna) {
595 if (++sc->sc_rxotherant >= 3)
Sujithbe0418a2008-11-18 09:05:55 +0530596 ath_setdefantenna(sc, ds->ds_rxstat.rs_antenna);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700597 } else {
598 sc->sc_rxotherant = 0;
599 }
Luis R. Rodriguezcb71d9b2008-11-21 17:41:33 -0800600requeue:
601 list_move_tail(&bf->list, &sc->sc_rxbuf);
602 ath_rx_buf_link(sc, bf);
Sujithbe0418a2008-11-18 09:05:55 +0530603 } while (1);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700604
Sujithbe0418a2008-11-18 09:05:55 +0530605 spin_unlock_bh(&sc->sc_rxbuflock);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700606
607 return 0;
608#undef PA2DESC
609}