1dd1de374Slin wang - Sun Microsystems - Beijing China /*
2*c0c93480Slin wang - Sun Microsystems - Beijing China * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
3dd1de374Slin wang - Sun Microsystems - Beijing China * Use is subject to license terms.
4dd1de374Slin wang - Sun Microsystems - Beijing China */
5dd1de374Slin wang - Sun Microsystems - Beijing China
6dd1de374Slin wang - Sun Microsystems - Beijing China /*
7dd1de374Slin wang - Sun Microsystems - Beijing China * Copyright (c) 2008 Atheros Communications Inc.
8dd1de374Slin wang - Sun Microsystems - Beijing China *
9dd1de374Slin wang - Sun Microsystems - Beijing China * Permission to use, copy, modify, and/or distribute this software for any
10dd1de374Slin wang - Sun Microsystems - Beijing China * purpose with or without fee is hereby granted, provided that the above
11dd1de374Slin wang - Sun Microsystems - Beijing China * copyright notice and this permission notice appear in all copies.
12dd1de374Slin wang - Sun Microsystems - Beijing China *
13dd1de374Slin wang - Sun Microsystems - Beijing China * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
14dd1de374Slin wang - Sun Microsystems - Beijing China * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15dd1de374Slin wang - Sun Microsystems - Beijing China * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
16dd1de374Slin wang - Sun Microsystems - Beijing China * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17dd1de374Slin wang - Sun Microsystems - Beijing China * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18dd1de374Slin wang - Sun Microsystems - Beijing China * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
19dd1de374Slin wang - Sun Microsystems - Beijing China * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20dd1de374Slin wang - Sun Microsystems - Beijing China */
21dd1de374Slin wang - Sun Microsystems - Beijing China
22dd1de374Slin wang - Sun Microsystems - Beijing China #include <sys/byteorder.h>
23dd1de374Slin wang - Sun Microsystems - Beijing China
24dd1de374Slin wang - Sun Microsystems - Beijing China #include "arn_core.h"
25dd1de374Slin wang - Sun Microsystems - Beijing China
26*c0c93480Slin wang - Sun Microsystems - Beijing China /*
27*c0c93480Slin wang - Sun Microsystems - Beijing China * Setup and link descriptors.
28*c0c93480Slin wang - Sun Microsystems - Beijing China *
29*c0c93480Slin wang - Sun Microsystems - Beijing China * 11N: we can no longer afford to self link the last descriptor.
30*c0c93480Slin wang - Sun Microsystems - Beijing China * MAC acknowledges BA status as long as it copies frames to host
31*c0c93480Slin wang - Sun Microsystems - Beijing China * buffer (or rx fifo). This can incorrectly acknowledge packets
32*c0c93480Slin wang - Sun Microsystems - Beijing China * to a sender if last desc is self-linked.
33*c0c93480Slin wang - Sun Microsystems - Beijing China */
34*c0c93480Slin wang - Sun Microsystems - Beijing China void
arn_rx_buf_link(struct arn_softc * sc,struct ath_buf * bf)35*c0c93480Slin wang - Sun Microsystems - Beijing China arn_rx_buf_link(struct arn_softc *sc, struct ath_buf *bf)
36*c0c93480Slin wang - Sun Microsystems - Beijing China {
37*c0c93480Slin wang - Sun Microsystems - Beijing China struct ath_desc *ds;
38*c0c93480Slin wang - Sun Microsystems - Beijing China
39*c0c93480Slin wang - Sun Microsystems - Beijing China ds = bf->bf_desc;
40*c0c93480Slin wang - Sun Microsystems - Beijing China ds->ds_link = 0;
41*c0c93480Slin wang - Sun Microsystems - Beijing China ds->ds_data = bf->bf_dma.cookie.dmac_address;
42*c0c93480Slin wang - Sun Microsystems - Beijing China
43*c0c93480Slin wang - Sun Microsystems - Beijing China /* virtual addr of the beginning of the buffer. */
44*c0c93480Slin wang - Sun Microsystems - Beijing China ds->ds_vdata = bf->bf_dma.mem_va;
45*c0c93480Slin wang - Sun Microsystems - Beijing China
46*c0c93480Slin wang - Sun Microsystems - Beijing China /*
47*c0c93480Slin wang - Sun Microsystems - Beijing China * setup rx descriptors. The bf_dma.alength here tells the H/W
48*c0c93480Slin wang - Sun Microsystems - Beijing China * how much data it can DMA to us and that we are prepared
49*c0c93480Slin wang - Sun Microsystems - Beijing China * to process
50*c0c93480Slin wang - Sun Microsystems - Beijing China */
51*c0c93480Slin wang - Sun Microsystems - Beijing China (void) ath9k_hw_setuprxdesc(sc->sc_ah, ds,
52*c0c93480Slin wang - Sun Microsystems - Beijing China bf->bf_dma.alength, /* buffer size */
53*c0c93480Slin wang - Sun Microsystems - Beijing China 0);
54*c0c93480Slin wang - Sun Microsystems - Beijing China
55*c0c93480Slin wang - Sun Microsystems - Beijing China if (sc->sc_rxlink == NULL)
56*c0c93480Slin wang - Sun Microsystems - Beijing China ath9k_hw_putrxbuf(sc->sc_ah, bf->bf_daddr);
57*c0c93480Slin wang - Sun Microsystems - Beijing China else
58*c0c93480Slin wang - Sun Microsystems - Beijing China *sc->sc_rxlink = bf->bf_daddr;
59*c0c93480Slin wang - Sun Microsystems - Beijing China
60*c0c93480Slin wang - Sun Microsystems - Beijing China sc->sc_rxlink = &ds->ds_link;
61*c0c93480Slin wang - Sun Microsystems - Beijing China ath9k_hw_rxena(sc->sc_ah);
62*c0c93480Slin wang - Sun Microsystems - Beijing China }
63*c0c93480Slin wang - Sun Microsystems - Beijing China
64dd1de374Slin wang - Sun Microsystems - Beijing China void
arn_setdefantenna(struct arn_softc * sc,uint32_t antenna)65dd1de374Slin wang - Sun Microsystems - Beijing China arn_setdefantenna(struct arn_softc *sc, uint32_t antenna)
66dd1de374Slin wang - Sun Microsystems - Beijing China {
67dd1de374Slin wang - Sun Microsystems - Beijing China /* XXX block beacon interrupts */
68dd1de374Slin wang - Sun Microsystems - Beijing China ath9k_hw_setantenna(sc->sc_ah, antenna);
69dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_defant = (uint8_t)antenna; /* LINT */
70dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_rxotherant = 0;
71dd1de374Slin wang - Sun Microsystems - Beijing China }
72dd1de374Slin wang - Sun Microsystems - Beijing China
73dd1de374Slin wang - Sun Microsystems - Beijing China /*
74dd1de374Slin wang - Sun Microsystems - Beijing China * Extend 15-bit time stamp from rx descriptor to
75dd1de374Slin wang - Sun Microsystems - Beijing China * a full 64-bit TSF using the current h/w TSF.
76dd1de374Slin wang - Sun Microsystems - Beijing China */
77dd1de374Slin wang - Sun Microsystems - Beijing China
78dd1de374Slin wang - Sun Microsystems - Beijing China static uint64_t
arn_extend_tsf(struct arn_softc * sc,uint32_t rstamp)79dd1de374Slin wang - Sun Microsystems - Beijing China arn_extend_tsf(struct arn_softc *sc, uint32_t rstamp)
80dd1de374Slin wang - Sun Microsystems - Beijing China {
81dd1de374Slin wang - Sun Microsystems - Beijing China uint64_t tsf;
82dd1de374Slin wang - Sun Microsystems - Beijing China
83dd1de374Slin wang - Sun Microsystems - Beijing China tsf = ath9k_hw_gettsf64(sc->sc_ah);
84dd1de374Slin wang - Sun Microsystems - Beijing China if ((tsf & 0x7fff) < rstamp)
85dd1de374Slin wang - Sun Microsystems - Beijing China tsf -= 0x8000;
86dd1de374Slin wang - Sun Microsystems - Beijing China return ((tsf & ~0x7fff) | rstamp);
87dd1de374Slin wang - Sun Microsystems - Beijing China }
88dd1de374Slin wang - Sun Microsystems - Beijing China
89*c0c93480Slin wang - Sun Microsystems - Beijing China static int
arn_rx_prepare(struct ath_desc * ds,struct arn_softc * sc)90*c0c93480Slin wang - Sun Microsystems - Beijing China arn_rx_prepare(struct ath_desc *ds, struct arn_softc *sc)
91*c0c93480Slin wang - Sun Microsystems - Beijing China {
92*c0c93480Slin wang - Sun Microsystems - Beijing China uint8_t phyerr;
93*c0c93480Slin wang - Sun Microsystems - Beijing China
94*c0c93480Slin wang - Sun Microsystems - Beijing China if (ds->ds_rxstat.rs_more) {
95*c0c93480Slin wang - Sun Microsystems - Beijing China /*
96*c0c93480Slin wang - Sun Microsystems - Beijing China * Frame spans multiple descriptors; this cannot happen yet
97*c0c93480Slin wang - Sun Microsystems - Beijing China * as we don't support jumbograms. If not in monitor mode,
98*c0c93480Slin wang - Sun Microsystems - Beijing China * discard the frame. Enable this if you want to see
99*c0c93480Slin wang - Sun Microsystems - Beijing China * error frames in Monitor mode.
100*c0c93480Slin wang - Sun Microsystems - Beijing China */
101*c0c93480Slin wang - Sun Microsystems - Beijing China if (sc->sc_ah->ah_opmode != ATH9K_M_MONITOR)
102*c0c93480Slin wang - Sun Microsystems - Beijing China goto rx_next;
103*c0c93480Slin wang - Sun Microsystems - Beijing China } else if (ds->ds_rxstat.rs_status != 0) {
104*c0c93480Slin wang - Sun Microsystems - Beijing China if (ds->ds_rxstat.rs_status & ATH9K_RXERR_CRC) {
105*c0c93480Slin wang - Sun Microsystems - Beijing China sc->sc_stats.ast_rx_crcerr++;
106*c0c93480Slin wang - Sun Microsystems - Beijing China goto rx_next; /* should ignore? */
107*c0c93480Slin wang - Sun Microsystems - Beijing China }
108*c0c93480Slin wang - Sun Microsystems - Beijing China
109*c0c93480Slin wang - Sun Microsystems - Beijing China if (ds->ds_rxstat.rs_status & ATH9K_RXERR_FIFO) {
110*c0c93480Slin wang - Sun Microsystems - Beijing China sc->sc_stats.ast_rx_fifoerr++;
111*c0c93480Slin wang - Sun Microsystems - Beijing China }
112*c0c93480Slin wang - Sun Microsystems - Beijing China
113*c0c93480Slin wang - Sun Microsystems - Beijing China if (ds->ds_rxstat.rs_status & ATH9K_RXERR_PHY) {
114*c0c93480Slin wang - Sun Microsystems - Beijing China sc->sc_stats.ast_rx_phyerr++;
115*c0c93480Slin wang - Sun Microsystems - Beijing China phyerr = ds->ds_rxstat.rs_phyerr & 0x1f;
116*c0c93480Slin wang - Sun Microsystems - Beijing China sc->sc_stats.ast_rx_phy[phyerr]++;
117*c0c93480Slin wang - Sun Microsystems - Beijing China goto rx_next;
118*c0c93480Slin wang - Sun Microsystems - Beijing China }
119*c0c93480Slin wang - Sun Microsystems - Beijing China
120*c0c93480Slin wang - Sun Microsystems - Beijing China if (ds->ds_rxstat.rs_status & ATH9K_RXERR_DECRYPT) {
121*c0c93480Slin wang - Sun Microsystems - Beijing China sc->sc_stats.ast_rx_badcrypt++;
122*c0c93480Slin wang - Sun Microsystems - Beijing China }
123*c0c93480Slin wang - Sun Microsystems - Beijing China
124*c0c93480Slin wang - Sun Microsystems - Beijing China /*
125*c0c93480Slin wang - Sun Microsystems - Beijing China * Reject error frames with the exception of
126*c0c93480Slin wang - Sun Microsystems - Beijing China * decryption and MIC failures. For monitor mode,
127*c0c93480Slin wang - Sun Microsystems - Beijing China * we also ignore the CRC error.
128*c0c93480Slin wang - Sun Microsystems - Beijing China */
129*c0c93480Slin wang - Sun Microsystems - Beijing China if (sc->sc_ah->ah_opmode == ATH9K_M_MONITOR) {
130*c0c93480Slin wang - Sun Microsystems - Beijing China if (ds->ds_rxstat.rs_status &
131*c0c93480Slin wang - Sun Microsystems - Beijing China ~(ATH9K_RXERR_DECRYPT |
132*c0c93480Slin wang - Sun Microsystems - Beijing China ATH9K_RXERR_MIC |
133*c0c93480Slin wang - Sun Microsystems - Beijing China ATH9K_RXERR_CRC))
134*c0c93480Slin wang - Sun Microsystems - Beijing China goto rx_next;
135*c0c93480Slin wang - Sun Microsystems - Beijing China } else {
136*c0c93480Slin wang - Sun Microsystems - Beijing China if (ds->ds_rxstat.rs_status &
137*c0c93480Slin wang - Sun Microsystems - Beijing China ~(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC)) {
138*c0c93480Slin wang - Sun Microsystems - Beijing China goto rx_next;
139*c0c93480Slin wang - Sun Microsystems - Beijing China }
140*c0c93480Slin wang - Sun Microsystems - Beijing China }
141*c0c93480Slin wang - Sun Microsystems - Beijing China }
142*c0c93480Slin wang - Sun Microsystems - Beijing China
143*c0c93480Slin wang - Sun Microsystems - Beijing China return (1);
144*c0c93480Slin wang - Sun Microsystems - Beijing China rx_next:
145*c0c93480Slin wang - Sun Microsystems - Beijing China return (0);
146*c0c93480Slin wang - Sun Microsystems - Beijing China }
147*c0c93480Slin wang - Sun Microsystems - Beijing China
148*c0c93480Slin wang - Sun Microsystems - Beijing China
149dd1de374Slin wang - Sun Microsystems - Beijing China static void
arn_opmode_init(struct arn_softc * sc)150dd1de374Slin wang - Sun Microsystems - Beijing China arn_opmode_init(struct arn_softc *sc)
151dd1de374Slin wang - Sun Microsystems - Beijing China {
152dd1de374Slin wang - Sun Microsystems - Beijing China struct ath_hal *ah = sc->sc_ah;
153dd1de374Slin wang - Sun Microsystems - Beijing China uint32_t rfilt;
154dd1de374Slin wang - Sun Microsystems - Beijing China uint32_t mfilt[2];
155dd1de374Slin wang - Sun Microsystems - Beijing China ieee80211com_t *ic = (ieee80211com_t *)sc;
156dd1de374Slin wang - Sun Microsystems - Beijing China
157dd1de374Slin wang - Sun Microsystems - Beijing China /* configure rx filter */
158dd1de374Slin wang - Sun Microsystems - Beijing China rfilt = arn_calcrxfilter(sc);
159dd1de374Slin wang - Sun Microsystems - Beijing China ath9k_hw_setrxfilter(ah, rfilt);
160dd1de374Slin wang - Sun Microsystems - Beijing China
161dd1de374Slin wang - Sun Microsystems - Beijing China /* configure bssid mask */
162dd1de374Slin wang - Sun Microsystems - Beijing China if (ah->ah_caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK)
163dd1de374Slin wang - Sun Microsystems - Beijing China (void) ath9k_hw_setbssidmask(ah, sc->sc_bssidmask);
164dd1de374Slin wang - Sun Microsystems - Beijing China
165dd1de374Slin wang - Sun Microsystems - Beijing China /* configure operational mode */
166dd1de374Slin wang - Sun Microsystems - Beijing China ath9k_hw_setopmode(ah);
167dd1de374Slin wang - Sun Microsystems - Beijing China
168dd1de374Slin wang - Sun Microsystems - Beijing China /* Handle any link-level address change. */
169dd1de374Slin wang - Sun Microsystems - Beijing China (void) ath9k_hw_setmac(ah, sc->sc_myaddr);
170dd1de374Slin wang - Sun Microsystems - Beijing China
171dd1de374Slin wang - Sun Microsystems - Beijing China /* calculate and install multicast filter */
172dd1de374Slin wang - Sun Microsystems - Beijing China mfilt[0] = ~((uint32_t)0); /* LINT */
173dd1de374Slin wang - Sun Microsystems - Beijing China mfilt[1] = ~((uint32_t)0); /* LINT */
174dd1de374Slin wang - Sun Microsystems - Beijing China
175dd1de374Slin wang - Sun Microsystems - Beijing China ath9k_hw_setmcastfilter(ah, mfilt[0], mfilt[1]);
176dd1de374Slin wang - Sun Microsystems - Beijing China
177dd1de374Slin wang - Sun Microsystems - Beijing China ARN_DBG((ARN_DBG_RECV, "arn: arn_opmode_init(): "
178dd1de374Slin wang - Sun Microsystems - Beijing China "mode = %d RX filter 0x%x, MC filter %08x:%08x\n",
179dd1de374Slin wang - Sun Microsystems - Beijing China ic->ic_opmode, rfilt, mfilt[0], mfilt[1]));
180dd1de374Slin wang - Sun Microsystems - Beijing China }
181dd1de374Slin wang - Sun Microsystems - Beijing China
182dd1de374Slin wang - Sun Microsystems - Beijing China /*
183dd1de374Slin wang - Sun Microsystems - Beijing China * Calculate the receive filter according to the
184dd1de374Slin wang - Sun Microsystems - Beijing China * operating mode and state:
185dd1de374Slin wang - Sun Microsystems - Beijing China *
186dd1de374Slin wang - Sun Microsystems - Beijing China * o always accept unicast, broadcast, and multicast traffic
187dd1de374Slin wang - Sun Microsystems - Beijing China * o maintain current state of phy error reception (the hal
188dd1de374Slin wang - Sun Microsystems - Beijing China * may enable phy error frames for noise immunity work)
189dd1de374Slin wang - Sun Microsystems - Beijing China * o probe request frames are accepted only when operating in
190dd1de374Slin wang - Sun Microsystems - Beijing China * hostap, adhoc, or monitor modes
191dd1de374Slin wang - Sun Microsystems - Beijing China * o enable promiscuous mode according to the interface state
192dd1de374Slin wang - Sun Microsystems - Beijing China * o accept beacons:
193dd1de374Slin wang - Sun Microsystems - Beijing China * - when operating in adhoc mode so the 802.11 layer creates
194dd1de374Slin wang - Sun Microsystems - Beijing China * node table entries for peers,
195dd1de374Slin wang - Sun Microsystems - Beijing China * - when operating in station mode for collecting rssi data when
196dd1de374Slin wang - Sun Microsystems - Beijing China * the station is otherwise quiet, or
197dd1de374Slin wang - Sun Microsystems - Beijing China * - when operating as a repeater so we see repeater-sta beacons
198dd1de374Slin wang - Sun Microsystems - Beijing China * - when scanning
199dd1de374Slin wang - Sun Microsystems - Beijing China */
200dd1de374Slin wang - Sun Microsystems - Beijing China
201dd1de374Slin wang - Sun Microsystems - Beijing China uint32_t
arn_calcrxfilter(struct arn_softc * sc)202dd1de374Slin wang - Sun Microsystems - Beijing China arn_calcrxfilter(struct arn_softc *sc)
203dd1de374Slin wang - Sun Microsystems - Beijing China {
204dd1de374Slin wang - Sun Microsystems - Beijing China #define RX_FILTER_PRESERVE (ATH9K_RX_FILTER_PHYERR | \
205dd1de374Slin wang - Sun Microsystems - Beijing China ATH9K_RX_FILTER_PHYRADAR)
206dd1de374Slin wang - Sun Microsystems - Beijing China
207dd1de374Slin wang - Sun Microsystems - Beijing China uint32_t rfilt;
208dd1de374Slin wang - Sun Microsystems - Beijing China
209dd1de374Slin wang - Sun Microsystems - Beijing China rfilt = (ath9k_hw_getrxfilter(sc->sc_ah) & RX_FILTER_PRESERVE) |
210dd1de374Slin wang - Sun Microsystems - Beijing China ATH9K_RX_FILTER_UCAST | ATH9K_RX_FILTER_BCAST |
211dd1de374Slin wang - Sun Microsystems - Beijing China ATH9K_RX_FILTER_MCAST;
212dd1de374Slin wang - Sun Microsystems - Beijing China
213dd1de374Slin wang - Sun Microsystems - Beijing China /* If not a STA, enable processing of Probe Requests */
214dd1de374Slin wang - Sun Microsystems - Beijing China if (sc->sc_ah->ah_opmode != ATH9K_M_STA)
215dd1de374Slin wang - Sun Microsystems - Beijing China rfilt |= ATH9K_RX_FILTER_PROBEREQ;
216dd1de374Slin wang - Sun Microsystems - Beijing China
217dd1de374Slin wang - Sun Microsystems - Beijing China /* Can't set HOSTAP into promiscous mode */
218dd1de374Slin wang - Sun Microsystems - Beijing China if (((sc->sc_ah->ah_opmode != ATH9K_M_HOSTAP) &&
219dd1de374Slin wang - Sun Microsystems - Beijing China (sc->sc_promisc)) ||
220dd1de374Slin wang - Sun Microsystems - Beijing China (sc->sc_ah->ah_opmode == ATH9K_M_MONITOR)) {
221dd1de374Slin wang - Sun Microsystems - Beijing China rfilt |= ATH9K_RX_FILTER_PROM;
222dd1de374Slin wang - Sun Microsystems - Beijing China /* ??? To prevent from sending ACK */
223dd1de374Slin wang - Sun Microsystems - Beijing China rfilt &= ~ATH9K_RX_FILTER_UCAST;
224dd1de374Slin wang - Sun Microsystems - Beijing China }
225dd1de374Slin wang - Sun Microsystems - Beijing China
226dd1de374Slin wang - Sun Microsystems - Beijing China if (sc->sc_ah->ah_opmode == ATH9K_M_STA ||
227dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_ah->ah_opmode == ATH9K_M_IBSS)
228dd1de374Slin wang - Sun Microsystems - Beijing China rfilt |= ATH9K_RX_FILTER_BEACON;
229dd1de374Slin wang - Sun Microsystems - Beijing China
230dd1de374Slin wang - Sun Microsystems - Beijing China /*
231dd1de374Slin wang - Sun Microsystems - Beijing China * If in HOSTAP mode, want to enable reception of PSPOLL
232dd1de374Slin wang - Sun Microsystems - Beijing China * frames & beacon frames
233dd1de374Slin wang - Sun Microsystems - Beijing China */
234dd1de374Slin wang - Sun Microsystems - Beijing China if (sc->sc_ah->ah_opmode == ATH9K_M_HOSTAP)
235dd1de374Slin wang - Sun Microsystems - Beijing China rfilt |= (ATH9K_RX_FILTER_BEACON | ATH9K_RX_FILTER_PSPOLL);
236dd1de374Slin wang - Sun Microsystems - Beijing China
237dd1de374Slin wang - Sun Microsystems - Beijing China return (rfilt);
238dd1de374Slin wang - Sun Microsystems - Beijing China
239dd1de374Slin wang - Sun Microsystems - Beijing China #undef RX_FILTER_PRESERVE
240dd1de374Slin wang - Sun Microsystems - Beijing China }
241dd1de374Slin wang - Sun Microsystems - Beijing China
242*c0c93480Slin wang - Sun Microsystems - Beijing China /*
243*c0c93480Slin wang - Sun Microsystems - Beijing China * When block ACK agreement has been set up between station and AP,
244*c0c93480Slin wang - Sun Microsystems - Beijing China * Net80211 module will call this function to inform hardware about
245*c0c93480Slin wang - Sun Microsystems - Beijing China * informations of this BA agreement.
246*c0c93480Slin wang - Sun Microsystems - Beijing China * When AP wants to delete BA agreement that was originated by it,
247*c0c93480Slin wang - Sun Microsystems - Beijing China * Net80211 modele will call this function to clean up relevant
248*c0c93480Slin wang - Sun Microsystems - Beijing China * information in hardware.
249*c0c93480Slin wang - Sun Microsystems - Beijing China */
250*c0c93480Slin wang - Sun Microsystems - Beijing China
251*c0c93480Slin wang - Sun Microsystems - Beijing China void
arn_ampdu_recv_action(struct ieee80211_node * in,const uint8_t * frm,const uint8_t * efrm)252*c0c93480Slin wang - Sun Microsystems - Beijing China arn_ampdu_recv_action(struct ieee80211_node *in,
253*c0c93480Slin wang - Sun Microsystems - Beijing China const uint8_t *frm,
254*c0c93480Slin wang - Sun Microsystems - Beijing China const uint8_t *efrm)
255*c0c93480Slin wang - Sun Microsystems - Beijing China {
256*c0c93480Slin wang - Sun Microsystems - Beijing China struct ieee80211com *ic;
257*c0c93480Slin wang - Sun Microsystems - Beijing China struct arn_softc *sc;
258*c0c93480Slin wang - Sun Microsystems - Beijing China
259*c0c93480Slin wang - Sun Microsystems - Beijing China if ((in == NULL) || (frm == NULL) || (ic = in->in_ic) == NULL) {
260*c0c93480Slin wang - Sun Microsystems - Beijing China ARN_DBG((ARN_DBG_FATAL,
261*c0c93480Slin wang - Sun Microsystems - Beijing China "Unknown AMPDU action or NULL node index\n"));
262*c0c93480Slin wang - Sun Microsystems - Beijing China return;
263*c0c93480Slin wang - Sun Microsystems - Beijing China }
264*c0c93480Slin wang - Sun Microsystems - Beijing China
265*c0c93480Slin wang - Sun Microsystems - Beijing China sc = (struct arn_softc *)ic;
266*c0c93480Slin wang - Sun Microsystems - Beijing China
267*c0c93480Slin wang - Sun Microsystems - Beijing China if (!(sc->sc_flags & SC_OP_RXAGGR))
268*c0c93480Slin wang - Sun Microsystems - Beijing China return;
269*c0c93480Slin wang - Sun Microsystems - Beijing China else
270*c0c93480Slin wang - Sun Microsystems - Beijing China sc->sc_recv_action(in, frm, efrm);
271*c0c93480Slin wang - Sun Microsystems - Beijing China }
272*c0c93480Slin wang - Sun Microsystems - Beijing China
273dd1de374Slin wang - Sun Microsystems - Beijing China int
arn_startrecv(struct arn_softc * sc)274dd1de374Slin wang - Sun Microsystems - Beijing China arn_startrecv(struct arn_softc *sc)
275dd1de374Slin wang - Sun Microsystems - Beijing China {
276dd1de374Slin wang - Sun Microsystems - Beijing China struct ath_hal *ah = sc->sc_ah;
277dd1de374Slin wang - Sun Microsystems - Beijing China struct ath_buf *bf;
278dd1de374Slin wang - Sun Microsystems - Beijing China
279*c0c93480Slin wang - Sun Microsystems - Beijing China /* rx descriptor link set up */
280*c0c93480Slin wang - Sun Microsystems - Beijing China mutex_enter(&sc->sc_rxbuflock);
281*c0c93480Slin wang - Sun Microsystems - Beijing China if (list_empty(&sc->sc_rxbuf_list))
282*c0c93480Slin wang - Sun Microsystems - Beijing China goto start_recv;
283*c0c93480Slin wang - Sun Microsystems - Beijing China
284dd1de374Slin wang - Sun Microsystems - Beijing China /* clean up rx link firstly */
285dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_rxlink = NULL;
286dd1de374Slin wang - Sun Microsystems - Beijing China
287dd1de374Slin wang - Sun Microsystems - Beijing China bf = list_head(&sc->sc_rxbuf_list);
288dd1de374Slin wang - Sun Microsystems - Beijing China while (bf != NULL) {
289dd1de374Slin wang - Sun Microsystems - Beijing China arn_rx_buf_link(sc, bf);
290dd1de374Slin wang - Sun Microsystems - Beijing China bf = list_next(&sc->sc_rxbuf_list, bf);
291dd1de374Slin wang - Sun Microsystems - Beijing China }
292dd1de374Slin wang - Sun Microsystems - Beijing China
293*c0c93480Slin wang - Sun Microsystems - Beijing China
294*c0c93480Slin wang - Sun Microsystems - Beijing China /* We could have deleted elements so the list may be empty now */
295*c0c93480Slin wang - Sun Microsystems - Beijing China if (list_empty(&sc->sc_rxbuf_list))
296*c0c93480Slin wang - Sun Microsystems - Beijing China goto start_recv;
297*c0c93480Slin wang - Sun Microsystems - Beijing China
298dd1de374Slin wang - Sun Microsystems - Beijing China bf = list_head(&sc->sc_rxbuf_list);
299dd1de374Slin wang - Sun Microsystems - Beijing China
300dd1de374Slin wang - Sun Microsystems - Beijing China ath9k_hw_putrxbuf(ah, bf->bf_daddr);
301dd1de374Slin wang - Sun Microsystems - Beijing China ath9k_hw_rxena(ah);
302dd1de374Slin wang - Sun Microsystems - Beijing China
303*c0c93480Slin wang - Sun Microsystems - Beijing China start_recv:
304*c0c93480Slin wang - Sun Microsystems - Beijing China mutex_exit(&sc->sc_rxbuflock);
305dd1de374Slin wang - Sun Microsystems - Beijing China arn_opmode_init(sc);
306dd1de374Slin wang - Sun Microsystems - Beijing China ath9k_hw_startpcureceive(ah);
307dd1de374Slin wang - Sun Microsystems - Beijing China
308dd1de374Slin wang - Sun Microsystems - Beijing China return (0);
309dd1de374Slin wang - Sun Microsystems - Beijing China }
310dd1de374Slin wang - Sun Microsystems - Beijing China
311dd1de374Slin wang - Sun Microsystems - Beijing China boolean_t
arn_stoprecv(struct arn_softc * sc)312dd1de374Slin wang - Sun Microsystems - Beijing China arn_stoprecv(struct arn_softc *sc)
313dd1de374Slin wang - Sun Microsystems - Beijing China {
314dd1de374Slin wang - Sun Microsystems - Beijing China struct ath_hal *ah = sc->sc_ah;
315dd1de374Slin wang - Sun Microsystems - Beijing China boolean_t stopped;
316dd1de374Slin wang - Sun Microsystems - Beijing China
317dd1de374Slin wang - Sun Microsystems - Beijing China ath9k_hw_stoppcurecv(ah);
318dd1de374Slin wang - Sun Microsystems - Beijing China ath9k_hw_setrxfilter(ah, 0);
319dd1de374Slin wang - Sun Microsystems - Beijing China stopped = ath9k_hw_stopdmarecv(ah);
320dd1de374Slin wang - Sun Microsystems - Beijing China
321dd1de374Slin wang - Sun Microsystems - Beijing China /* 3ms is long enough for 1 frame ??? */
322dd1de374Slin wang - Sun Microsystems - Beijing China drv_usecwait(3000);
323dd1de374Slin wang - Sun Microsystems - Beijing China
324dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_rxlink = NULL;
325dd1de374Slin wang - Sun Microsystems - Beijing China
326dd1de374Slin wang - Sun Microsystems - Beijing China return (stopped);
327dd1de374Slin wang - Sun Microsystems - Beijing China }
328dd1de374Slin wang - Sun Microsystems - Beijing China
329dd1de374Slin wang - Sun Microsystems - Beijing China /*
330dd1de374Slin wang - Sun Microsystems - Beijing China * Intercept management frames to collect beacon rssi data
331dd1de374Slin wang - Sun Microsystems - Beijing China * and to do ibss merges.
332dd1de374Slin wang - Sun Microsystems - Beijing China */
333dd1de374Slin wang - Sun Microsystems - Beijing China
334dd1de374Slin wang - Sun Microsystems - Beijing China void
arn_recv_mgmt(struct ieee80211com * ic,mblk_t * mp,struct ieee80211_node * in,int subtype,int rssi,uint32_t rstamp)335dd1de374Slin wang - Sun Microsystems - Beijing China arn_recv_mgmt(struct ieee80211com *ic, mblk_t *mp, struct ieee80211_node *in,
336dd1de374Slin wang - Sun Microsystems - Beijing China int subtype, int rssi, uint32_t rstamp)
337dd1de374Slin wang - Sun Microsystems - Beijing China {
338dd1de374Slin wang - Sun Microsystems - Beijing China struct arn_softc *sc = (struct arn_softc *)ic;
339dd1de374Slin wang - Sun Microsystems - Beijing China
340dd1de374Slin wang - Sun Microsystems - Beijing China /*
341dd1de374Slin wang - Sun Microsystems - Beijing China * Call up first so subsequent work can use information
342dd1de374Slin wang - Sun Microsystems - Beijing China * potentially stored in the node (e.g. for ibss merge).
343dd1de374Slin wang - Sun Microsystems - Beijing China */
344dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_recv_mgmt(ic, mp, in, subtype, rssi, rstamp);
345dd1de374Slin wang - Sun Microsystems - Beijing China
346dd1de374Slin wang - Sun Microsystems - Beijing China ARN_LOCK(sc);
347dd1de374Slin wang - Sun Microsystems - Beijing China switch (subtype) {
348dd1de374Slin wang - Sun Microsystems - Beijing China case IEEE80211_FC0_SUBTYPE_BEACON:
349dd1de374Slin wang - Sun Microsystems - Beijing China /* update rssi statistics */
350dd1de374Slin wang - Sun Microsystems - Beijing China if (sc->sc_bsync && in == ic->ic_bss &&
351dd1de374Slin wang - Sun Microsystems - Beijing China ic->ic_state == IEEE80211_S_RUN) {
352dd1de374Slin wang - Sun Microsystems - Beijing China /*
353dd1de374Slin wang - Sun Microsystems - Beijing China * Resync beacon timers using the tsf of the beacon
354dd1de374Slin wang - Sun Microsystems - Beijing China * frame we just received.
355dd1de374Slin wang - Sun Microsystems - Beijing China */
356dd1de374Slin wang - Sun Microsystems - Beijing China arn_beacon_config(sc);
357dd1de374Slin wang - Sun Microsystems - Beijing China }
358dd1de374Slin wang - Sun Microsystems - Beijing China /* FALLTHRU */
359dd1de374Slin wang - Sun Microsystems - Beijing China case IEEE80211_FC0_SUBTYPE_PROBE_RESP:
360dd1de374Slin wang - Sun Microsystems - Beijing China if (ic->ic_opmode == IEEE80211_M_IBSS &&
361dd1de374Slin wang - Sun Microsystems - Beijing China ic->ic_state == IEEE80211_S_RUN &&
362dd1de374Slin wang - Sun Microsystems - Beijing China (in->in_capinfo & IEEE80211_CAPINFO_IBSS)) {
363dd1de374Slin wang - Sun Microsystems - Beijing China uint64_t tsf = arn_extend_tsf(sc, rstamp);
364dd1de374Slin wang - Sun Microsystems - Beijing China /*
365dd1de374Slin wang - Sun Microsystems - Beijing China * Handle ibss merge as needed; check the tsf on the
366dd1de374Slin wang - Sun Microsystems - Beijing China * frame before attempting the merge. The 802.11 spec
367dd1de374Slin wang - Sun Microsystems - Beijing China * says the station should change it's bssid to match
368dd1de374Slin wang - Sun Microsystems - Beijing China * the oldest station with the same ssid, where oldest
369dd1de374Slin wang - Sun Microsystems - Beijing China * is determined by the tsf. Note that hardware
370dd1de374Slin wang - Sun Microsystems - Beijing China * reconfiguration happens through callback to
371dd1de374Slin wang - Sun Microsystems - Beijing China * ath_newstate as the state machine will go from
372dd1de374Slin wang - Sun Microsystems - Beijing China * RUN -> RUN when this happens.
373dd1de374Slin wang - Sun Microsystems - Beijing China */
374dd1de374Slin wang - Sun Microsystems - Beijing China if (LE_64(in->in_tstamp.tsf) >= tsf) {
375dd1de374Slin wang - Sun Microsystems - Beijing China ARN_DBG((ARN_DBG_BEACON, "arn: arn_recv_mgmt:"
376dd1de374Slin wang - Sun Microsystems - Beijing China "ibss merge, rstamp %u tsf %lu "
377dd1de374Slin wang - Sun Microsystems - Beijing China "tstamp %lu\n", rstamp, tsf,
378dd1de374Slin wang - Sun Microsystems - Beijing China in->in_tstamp.tsf));
379dd1de374Slin wang - Sun Microsystems - Beijing China ARN_UNLOCK(sc);
380dd1de374Slin wang - Sun Microsystems - Beijing China ARN_DBG((ARN_DBG_BEACON, "arn_recv_mgmt():"
381dd1de374Slin wang - Sun Microsystems - Beijing China "ibss_merge: rstamp=%d in_tstamp=%02x %02x"
382dd1de374Slin wang - Sun Microsystems - Beijing China " %02x %02x %02x %02x %02x %02x\n",
383dd1de374Slin wang - Sun Microsystems - Beijing China rstamp, in->in_tstamp.data[0],
384dd1de374Slin wang - Sun Microsystems - Beijing China in->in_tstamp.data[1],
385dd1de374Slin wang - Sun Microsystems - Beijing China in->in_tstamp.data[2],
386dd1de374Slin wang - Sun Microsystems - Beijing China in->in_tstamp.data[3],
387dd1de374Slin wang - Sun Microsystems - Beijing China in->in_tstamp.data[4],
388dd1de374Slin wang - Sun Microsystems - Beijing China in->in_tstamp.data[5],
389dd1de374Slin wang - Sun Microsystems - Beijing China in->in_tstamp.data[6],
390dd1de374Slin wang - Sun Microsystems - Beijing China in->in_tstamp.data[7]));
391dd1de374Slin wang - Sun Microsystems - Beijing China (void) ieee80211_ibss_merge(in);
392dd1de374Slin wang - Sun Microsystems - Beijing China return;
393dd1de374Slin wang - Sun Microsystems - Beijing China }
394dd1de374Slin wang - Sun Microsystems - Beijing China }
395dd1de374Slin wang - Sun Microsystems - Beijing China break;
396dd1de374Slin wang - Sun Microsystems - Beijing China }
397dd1de374Slin wang - Sun Microsystems - Beijing China ARN_UNLOCK(sc);
398dd1de374Slin wang - Sun Microsystems - Beijing China }
399dd1de374Slin wang - Sun Microsystems - Beijing China
400dd1de374Slin wang - Sun Microsystems - Beijing China static void
arn_printrxbuf(struct ath_buf * bf,int32_t done)401dd1de374Slin wang - Sun Microsystems - Beijing China arn_printrxbuf(struct ath_buf *bf, int32_t done)
402dd1de374Slin wang - Sun Microsystems - Beijing China {
403dd1de374Slin wang - Sun Microsystems - Beijing China struct ath_desc *ds = bf->bf_desc;
404dd1de374Slin wang - Sun Microsystems - Beijing China const struct ath_rx_status *rs = &ds->ds_rxstat;
405dd1de374Slin wang - Sun Microsystems - Beijing China
406dd1de374Slin wang - Sun Microsystems - Beijing China ARN_DBG((ARN_DBG_RECV, "arn: R (%p %p) %08x %08x %08x "
407dd1de374Slin wang - Sun Microsystems - Beijing China "%08x %08x %08x %c\n",
408dd1de374Slin wang - Sun Microsystems - Beijing China ds, bf->bf_daddr,
409dd1de374Slin wang - Sun Microsystems - Beijing China ds->ds_link, ds->ds_data,
410dd1de374Slin wang - Sun Microsystems - Beijing China ds->ds_ctl0, ds->ds_ctl1,
411dd1de374Slin wang - Sun Microsystems - Beijing China ds->ds_hw[0], ds->ds_hw[1],
412dd1de374Slin wang - Sun Microsystems - Beijing China !done ? ' ' : (rs->rs_status == 0) ? '*' : '!'));
413dd1de374Slin wang - Sun Microsystems - Beijing China }
414dd1de374Slin wang - Sun Microsystems - Beijing China
415dd1de374Slin wang - Sun Microsystems - Beijing China static void
arn_rx_handler(struct arn_softc * sc)416dd1de374Slin wang - Sun Microsystems - Beijing China arn_rx_handler(struct arn_softc *sc)
417dd1de374Slin wang - Sun Microsystems - Beijing China {
418dd1de374Slin wang - Sun Microsystems - Beijing China #define PA2DESC(_sc, _pa) \
419dd1de374Slin wang - Sun Microsystems - Beijing China ((struct ath_desc *)((caddr_t)(_sc)->sc_desc + \
420dd1de374Slin wang - Sun Microsystems - Beijing China ((_pa) - (_sc)->sc_desc_dma.cookie.dmac_address)))
421dd1de374Slin wang - Sun Microsystems - Beijing China
422dd1de374Slin wang - Sun Microsystems - Beijing China ieee80211com_t *ic = (ieee80211com_t *)sc;
423dd1de374Slin wang - Sun Microsystems - Beijing China struct ath_buf *bf;
424dd1de374Slin wang - Sun Microsystems - Beijing China struct ath_hal *ah = sc->sc_ah;
425dd1de374Slin wang - Sun Microsystems - Beijing China struct ath_desc *ds;
426dd1de374Slin wang - Sun Microsystems - Beijing China struct ath_rx_status *rs;
427dd1de374Slin wang - Sun Microsystems - Beijing China mblk_t *rx_mp;
428dd1de374Slin wang - Sun Microsystems - Beijing China struct ieee80211_frame *wh;
429*c0c93480Slin wang - Sun Microsystems - Beijing China int32_t len, ngood = 0, loop = 1;
430*c0c93480Slin wang - Sun Microsystems - Beijing China uint32_t subtype;
431dd1de374Slin wang - Sun Microsystems - Beijing China int status;
432*c0c93480Slin wang - Sun Microsystems - Beijing China int last_rssi = ATH_RSSI_DUMMY_MARKER;
433*c0c93480Slin wang - Sun Microsystems - Beijing China struct ath_node *an;
434dd1de374Slin wang - Sun Microsystems - Beijing China struct ieee80211_node *in;
4353ae945c3Slin wang - Sun Microsystems - Beijing China uint32_t cur_signal;
436*c0c93480Slin wang - Sun Microsystems - Beijing China #ifdef ARN_DBG_AMSDU
437*c0c93480Slin wang - Sun Microsystems - Beijing China uint8_t qos;
438*c0c93480Slin wang - Sun Microsystems - Beijing China #endif
439dd1de374Slin wang - Sun Microsystems - Beijing China
440dd1de374Slin wang - Sun Microsystems - Beijing China do {
441dd1de374Slin wang - Sun Microsystems - Beijing China mutex_enter(&sc->sc_rxbuflock);
442dd1de374Slin wang - Sun Microsystems - Beijing China bf = list_head(&sc->sc_rxbuf_list);
443dd1de374Slin wang - Sun Microsystems - Beijing China if (bf == NULL) {
444dd1de374Slin wang - Sun Microsystems - Beijing China ARN_DBG((ARN_DBG_RECV, "arn: arn_rx_handler(): "
445dd1de374Slin wang - Sun Microsystems - Beijing China "no buffer\n"));
446*c0c93480Slin wang - Sun Microsystems - Beijing China sc->sc_rxlink = NULL;
447dd1de374Slin wang - Sun Microsystems - Beijing China mutex_exit(&sc->sc_rxbuflock);
448dd1de374Slin wang - Sun Microsystems - Beijing China break;
449dd1de374Slin wang - Sun Microsystems - Beijing China }
450dd1de374Slin wang - Sun Microsystems - Beijing China ASSERT(bf->bf_dma.cookie.dmac_address != NULL);
451dd1de374Slin wang - Sun Microsystems - Beijing China ds = bf->bf_desc;
452dd1de374Slin wang - Sun Microsystems - Beijing China
453dd1de374Slin wang - Sun Microsystems - Beijing China /*
454dd1de374Slin wang - Sun Microsystems - Beijing China * Must provide the virtual address of the current
455dd1de374Slin wang - Sun Microsystems - Beijing China * descriptor, the physical address, and the virtual
456dd1de374Slin wang - Sun Microsystems - Beijing China * address of the next descriptor in the h/w chain.
457dd1de374Slin wang - Sun Microsystems - Beijing China * This allows the HAL to look ahead to see if the
458dd1de374Slin wang - Sun Microsystems - Beijing China * hardware is done with a descriptor by checking the
459dd1de374Slin wang - Sun Microsystems - Beijing China * done bit in the following descriptor and the address
460dd1de374Slin wang - Sun Microsystems - Beijing China * of the current descriptor the DMA engine is working
461dd1de374Slin wang - Sun Microsystems - Beijing China * on. All this is necessary because of our use of
462dd1de374Slin wang - Sun Microsystems - Beijing China * a self-linked list to avoid rx overruns.
463dd1de374Slin wang - Sun Microsystems - Beijing China */
464dd1de374Slin wang - Sun Microsystems - Beijing China status = ath9k_hw_rxprocdesc(ah, ds,
465dd1de374Slin wang - Sun Microsystems - Beijing China bf->bf_daddr,
466dd1de374Slin wang - Sun Microsystems - Beijing China PA2DESC(sc, ds->ds_link), 0);
467dd1de374Slin wang - Sun Microsystems - Beijing China if (status == EINPROGRESS) {
468*c0c93480Slin wang - Sun Microsystems - Beijing China struct ath_buf *tbf;
469*c0c93480Slin wang - Sun Microsystems - Beijing China struct ath_desc *tds;
470*c0c93480Slin wang - Sun Microsystems - Beijing China
471*c0c93480Slin wang - Sun Microsystems - Beijing China if (list_is_last(&bf->bf_node, &sc->sc_rxbuf_list)) {
472*c0c93480Slin wang - Sun Microsystems - Beijing China ARN_DBG((ARN_DBG_RECV, "arn: arn_rx_handler(): "
473*c0c93480Slin wang - Sun Microsystems - Beijing China "List is in last! \n"));
474*c0c93480Slin wang - Sun Microsystems - Beijing China sc->sc_rxlink = NULL;
475*c0c93480Slin wang - Sun Microsystems - Beijing China break;
476*c0c93480Slin wang - Sun Microsystems - Beijing China }
477*c0c93480Slin wang - Sun Microsystems - Beijing China
478*c0c93480Slin wang - Sun Microsystems - Beijing China tbf = list_object(&sc->sc_rxbuf_list,
479*c0c93480Slin wang - Sun Microsystems - Beijing China bf->bf_node.list_next);
480*c0c93480Slin wang - Sun Microsystems - Beijing China
481*c0c93480Slin wang - Sun Microsystems - Beijing China /*
482*c0c93480Slin wang - Sun Microsystems - Beijing China * On some hardware the descriptor status words could
483*c0c93480Slin wang - Sun Microsystems - Beijing China * get corrupted, including the done bit. Because of
484*c0c93480Slin wang - Sun Microsystems - Beijing China * this, check if the next descriptor's done bit is
485*c0c93480Slin wang - Sun Microsystems - Beijing China * set or not.
486*c0c93480Slin wang - Sun Microsystems - Beijing China *
487*c0c93480Slin wang - Sun Microsystems - Beijing China * If the next descriptor's done bit is set, the current
488*c0c93480Slin wang - Sun Microsystems - Beijing China * descriptor has been corrupted. Force s/w to discard
489*c0c93480Slin wang - Sun Microsystems - Beijing China * this descriptor and continue...
490*c0c93480Slin wang - Sun Microsystems - Beijing China */
491*c0c93480Slin wang - Sun Microsystems - Beijing China
492*c0c93480Slin wang - Sun Microsystems - Beijing China tds = tbf->bf_desc;
493*c0c93480Slin wang - Sun Microsystems - Beijing China status = ath9k_hw_rxprocdesc(ah, tds, tbf->bf_daddr,
494*c0c93480Slin wang - Sun Microsystems - Beijing China PA2DESC(sc, tds->ds_link), 0);
495*c0c93480Slin wang - Sun Microsystems - Beijing China if (status == EINPROGRESS) {
496dd1de374Slin wang - Sun Microsystems - Beijing China mutex_exit(&sc->sc_rxbuflock);
497dd1de374Slin wang - Sun Microsystems - Beijing China break;
498dd1de374Slin wang - Sun Microsystems - Beijing China }
499*c0c93480Slin wang - Sun Microsystems - Beijing China }
500dd1de374Slin wang - Sun Microsystems - Beijing China list_remove(&sc->sc_rxbuf_list, bf);
501dd1de374Slin wang - Sun Microsystems - Beijing China mutex_exit(&sc->sc_rxbuflock);
502dd1de374Slin wang - Sun Microsystems - Beijing China
503dd1de374Slin wang - Sun Microsystems - Beijing China rs = &ds->ds_rxstat;
504dd1de374Slin wang - Sun Microsystems - Beijing China len = rs->rs_datalen;
505dd1de374Slin wang - Sun Microsystems - Beijing China
506dd1de374Slin wang - Sun Microsystems - Beijing China /* less than sizeof(struct ieee80211_frame) */
507dd1de374Slin wang - Sun Microsystems - Beijing China if (len < 20) {
508dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_stats.ast_rx_tooshort++;
509*c0c93480Slin wang - Sun Microsystems - Beijing China goto requeue;
510dd1de374Slin wang - Sun Microsystems - Beijing China }
511dd1de374Slin wang - Sun Microsystems - Beijing China
512*c0c93480Slin wang - Sun Microsystems - Beijing China /* The status portion of the descriptor could get corrupted. */
513*c0c93480Slin wang - Sun Microsystems - Beijing China if (sc->rx_dmabuf_size < rs->rs_datalen) {
514*c0c93480Slin wang - Sun Microsystems - Beijing China arn_problem("Requeued because of wrong rs_datalen\n");
515*c0c93480Slin wang - Sun Microsystems - Beijing China goto requeue;
516*c0c93480Slin wang - Sun Microsystems - Beijing China }
517*c0c93480Slin wang - Sun Microsystems - Beijing China
518*c0c93480Slin wang - Sun Microsystems - Beijing China if (!arn_rx_prepare(ds, sc))
519*c0c93480Slin wang - Sun Microsystems - Beijing China goto requeue;
520*c0c93480Slin wang - Sun Microsystems - Beijing China
521*c0c93480Slin wang - Sun Microsystems - Beijing China if ((rx_mp = allocb(sc->rx_dmabuf_size, BPRI_MED)) == NULL) {
522dd1de374Slin wang - Sun Microsystems - Beijing China arn_problem("arn: arn_rx_handler(): "
523dd1de374Slin wang - Sun Microsystems - Beijing China "allocing mblk buffer failed.\n");
524dd1de374Slin wang - Sun Microsystems - Beijing China return;
525dd1de374Slin wang - Sun Microsystems - Beijing China }
526dd1de374Slin wang - Sun Microsystems - Beijing China
527dd1de374Slin wang - Sun Microsystems - Beijing China ARN_DMA_SYNC(bf->bf_dma, DDI_DMA_SYNC_FORCPU);
528dd1de374Slin wang - Sun Microsystems - Beijing China bcopy(bf->bf_dma.mem_va, rx_mp->b_rptr, len);
529dd1de374Slin wang - Sun Microsystems - Beijing China
530dd1de374Slin wang - Sun Microsystems - Beijing China rx_mp->b_wptr += len;
531dd1de374Slin wang - Sun Microsystems - Beijing China wh = (struct ieee80211_frame *)rx_mp->b_rptr;
532dd1de374Slin wang - Sun Microsystems - Beijing China
533dd1de374Slin wang - Sun Microsystems - Beijing China if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) ==
534dd1de374Slin wang - Sun Microsystems - Beijing China IEEE80211_FC0_TYPE_CTL) {
535dd1de374Slin wang - Sun Microsystems - Beijing China /*
536dd1de374Slin wang - Sun Microsystems - Beijing China * Ignore control frame received in promisc mode.
537dd1de374Slin wang - Sun Microsystems - Beijing China */
538dd1de374Slin wang - Sun Microsystems - Beijing China freemsg(rx_mp);
539*c0c93480Slin wang - Sun Microsystems - Beijing China goto requeue;
540dd1de374Slin wang - Sun Microsystems - Beijing China }
541dd1de374Slin wang - Sun Microsystems - Beijing China /* Remove the CRC at the end of IEEE80211 frame */
542dd1de374Slin wang - Sun Microsystems - Beijing China rx_mp->b_wptr -= IEEE80211_CRC_LEN;
543dd1de374Slin wang - Sun Microsystems - Beijing China
544*c0c93480Slin wang - Sun Microsystems - Beijing China #ifdef DEBUG
545*c0c93480Slin wang - Sun Microsystems - Beijing China arn_printrxbuf(bf, status == 0);
546*c0c93480Slin wang - Sun Microsystems - Beijing China #endif
547*c0c93480Slin wang - Sun Microsystems - Beijing China
548*c0c93480Slin wang - Sun Microsystems - Beijing China #ifdef ARN_DBG_AMSDU
549*c0c93480Slin wang - Sun Microsystems - Beijing China if (IEEE80211_IS_DATA_QOS(wh)) {
550*c0c93480Slin wang - Sun Microsystems - Beijing China if ((wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) ==
551*c0c93480Slin wang - Sun Microsystems - Beijing China IEEE80211_FC1_DIR_DSTODS)
552*c0c93480Slin wang - Sun Microsystems - Beijing China qos = ((struct ieee80211_qosframe_addr4 *)
553*c0c93480Slin wang - Sun Microsystems - Beijing China wh)->i_qos[0];
554*c0c93480Slin wang - Sun Microsystems - Beijing China else
555*c0c93480Slin wang - Sun Microsystems - Beijing China qos =
556*c0c93480Slin wang - Sun Microsystems - Beijing China ((struct ieee80211_qosframe *)wh)->i_qos[0];
557*c0c93480Slin wang - Sun Microsystems - Beijing China
558*c0c93480Slin wang - Sun Microsystems - Beijing China if (qos & IEEE80211_QOS_AMSDU)
559*c0c93480Slin wang - Sun Microsystems - Beijing China arn_dump_pkg((unsigned char *)bf->bf_dma.mem_va,
560*c0c93480Slin wang - Sun Microsystems - Beijing China len, 1, 1);
561*c0c93480Slin wang - Sun Microsystems - Beijing China }
562*c0c93480Slin wang - Sun Microsystems - Beijing China #endif /* ARN_DBG_AMSDU */
563*c0c93480Slin wang - Sun Microsystems - Beijing China
564dd1de374Slin wang - Sun Microsystems - Beijing China /*
565dd1de374Slin wang - Sun Microsystems - Beijing China * Locate the node for sender, track state, and then
566dd1de374Slin wang - Sun Microsystems - Beijing China * pass the (referenced) node up to the 802.11 layer
567dd1de374Slin wang - Sun Microsystems - Beijing China * for its use.
568dd1de374Slin wang - Sun Microsystems - Beijing China */
569dd1de374Slin wang - Sun Microsystems - Beijing China in = ieee80211_find_rxnode(ic, wh);
570*c0c93480Slin wang - Sun Microsystems - Beijing China an = ATH_NODE(in);
571*c0c93480Slin wang - Sun Microsystems - Beijing China
572*c0c93480Slin wang - Sun Microsystems - Beijing China /*
573*c0c93480Slin wang - Sun Microsystems - Beijing China * Theory for reporting quality:
574*c0c93480Slin wang - Sun Microsystems - Beijing China *
575*c0c93480Slin wang - Sun Microsystems - Beijing China * At a hardware RSSI of 45 you will be able to use
576*c0c93480Slin wang - Sun Microsystems - Beijing China * MCS 7 reliably.
577*c0c93480Slin wang - Sun Microsystems - Beijing China * At a hardware RSSI of 45 you will be able to use
578*c0c93480Slin wang - Sun Microsystems - Beijing China * MCS 15 reliably.
579*c0c93480Slin wang - Sun Microsystems - Beijing China * At a hardware RSSI of 35 you should be able use
580*c0c93480Slin wang - Sun Microsystems - Beijing China * 54 Mbps reliably.
581*c0c93480Slin wang - Sun Microsystems - Beijing China *
582*c0c93480Slin wang - Sun Microsystems - Beijing China * MCS 7 is the highets MCS index usable by a 1-stream device.
583*c0c93480Slin wang - Sun Microsystems - Beijing China * MCS 15 is the highest MCS index usable by a 2-stream device.
584*c0c93480Slin wang - Sun Microsystems - Beijing China *
585*c0c93480Slin wang - Sun Microsystems - Beijing China * All ath9k devices are either 1-stream or 2-stream.
586*c0c93480Slin wang - Sun Microsystems - Beijing China *
587*c0c93480Slin wang - Sun Microsystems - Beijing China * How many bars you see is derived from the qual reporting.
588*c0c93480Slin wang - Sun Microsystems - Beijing China *
589*c0c93480Slin wang - Sun Microsystems - Beijing China * A more elaborate scheme can be used here but it requires
590*c0c93480Slin wang - Sun Microsystems - Beijing China * tables of SNR/throughput for each possible mode used. For
591*c0c93480Slin wang - Sun Microsystems - Beijing China * the MCS table you can refer to the wireless wiki:
592*c0c93480Slin wang - Sun Microsystems - Beijing China *
593*c0c93480Slin wang - Sun Microsystems - Beijing China * http://wireless.kernel.org/en/developers/Documentation/
594*c0c93480Slin wang - Sun Microsystems - Beijing China * ieee80211/802.11n
595*c0c93480Slin wang - Sun Microsystems - Beijing China */
596*c0c93480Slin wang - Sun Microsystems - Beijing China if (ds->ds_rxstat.rs_rssi != ATH9K_RSSI_BAD &&
597*c0c93480Slin wang - Sun Microsystems - Beijing China !ds->ds_rxstat.rs_moreaggr) {
598*c0c93480Slin wang - Sun Microsystems - Beijing China /* LINTED: E_CONSTANT_CONDITION */
599*c0c93480Slin wang - Sun Microsystems - Beijing China ATH_RSSI_LPF(an->last_rssi, ds->ds_rxstat.rs_rssi);
600*c0c93480Slin wang - Sun Microsystems - Beijing China }
601*c0c93480Slin wang - Sun Microsystems - Beijing China last_rssi = an->last_rssi;
602*c0c93480Slin wang - Sun Microsystems - Beijing China
603*c0c93480Slin wang - Sun Microsystems - Beijing China if (last_rssi != ATH_RSSI_DUMMY_MARKER)
604*c0c93480Slin wang - Sun Microsystems - Beijing China ds->ds_rxstat.rs_rssi = ATH_EP_RND(last_rssi,
605*c0c93480Slin wang - Sun Microsystems - Beijing China ATH_RSSI_EP_MULTIPLIER);
606dd1de374Slin wang - Sun Microsystems - Beijing China
6073ae945c3Slin wang - Sun Microsystems - Beijing China if (ds->ds_rxstat.rs_rssi < 0)
6083ae945c3Slin wang - Sun Microsystems - Beijing China ds->ds_rxstat.rs_rssi = 0;
6093ae945c3Slin wang - Sun Microsystems - Beijing China
6103ae945c3Slin wang - Sun Microsystems - Beijing China if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) ==
6113ae945c3Slin wang - Sun Microsystems - Beijing China IEEE80211_FC0_TYPE_MGT) {
6123ae945c3Slin wang - Sun Microsystems - Beijing China subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
6133ae945c3Slin wang - Sun Microsystems - Beijing China if (subtype == IEEE80211_FC0_SUBTYPE_BEACON)
6143ae945c3Slin wang - Sun Microsystems - Beijing China sc->sc_halstats.ns_avgbrssi =
6153ae945c3Slin wang - Sun Microsystems - Beijing China ds->ds_rxstat.rs_rssi;
6163ae945c3Slin wang - Sun Microsystems - Beijing China }
6173ae945c3Slin wang - Sun Microsystems - Beijing China
6183ae945c3Slin wang - Sun Microsystems - Beijing China /*
619*c0c93480Slin wang - Sun Microsystems - Beijing China * signal (13-15) DLADM_WLAN_STRENGTH_EXCELLENT
620*c0c93480Slin wang - Sun Microsystems - Beijing China * signal (10-12) DLADM_WLAN_STRENGTH_VERY_GOOD
621*c0c93480Slin wang - Sun Microsystems - Beijing China * signal (6-9) DLADM_WLAN_STRENGTH_GOOD
622*c0c93480Slin wang - Sun Microsystems - Beijing China * signal (3-5) DLADM_WLAN_STRENGTH_WEAK
623*c0c93480Slin wang - Sun Microsystems - Beijing China * signal (0-2) DLADM_WLAN_STRENGTH_VERY_WEAK
6243ae945c3Slin wang - Sun Microsystems - Beijing China */
6253ae945c3Slin wang - Sun Microsystems - Beijing China if (rs->rs_rssi == 0)
6263ae945c3Slin wang - Sun Microsystems - Beijing China cur_signal = 0;
6273ae945c3Slin wang - Sun Microsystems - Beijing China else if (rs->rs_rssi >= 45)
6283ae945c3Slin wang - Sun Microsystems - Beijing China cur_signal = MAX_RSSI;
6293ae945c3Slin wang - Sun Microsystems - Beijing China else
6303ae945c3Slin wang - Sun Microsystems - Beijing China cur_signal = rs->rs_rssi * MAX_RSSI / 45 + 1;
6313ae945c3Slin wang - Sun Microsystems - Beijing China
632dd1de374Slin wang - Sun Microsystems - Beijing China /*
633dd1de374Slin wang - Sun Microsystems - Beijing China * Send the frame to net80211 for processing
634dd1de374Slin wang - Sun Microsystems - Beijing China */
635*c0c93480Slin wang - Sun Microsystems - Beijing China if (cur_signal <= 2 && ic->ic_state == IEEE80211_S_RUN) {
6363ae945c3Slin wang - Sun Microsystems - Beijing China (void) ieee80211_input(ic, rx_mp, in,
6373ae945c3Slin wang - Sun Microsystems - Beijing China (rs->rs_rssi + 10), rs->rs_tstamp);
638*c0c93480Slin wang - Sun Microsystems - Beijing China }
6393ae945c3Slin wang - Sun Microsystems - Beijing China else
640*c0c93480Slin wang - Sun Microsystems - Beijing China (void) ieee80211_input(ic, rx_mp, in, rs->rs_rssi,
641*c0c93480Slin wang - Sun Microsystems - Beijing China rs->rs_tstamp);
642dd1de374Slin wang - Sun Microsystems - Beijing China
643dd1de374Slin wang - Sun Microsystems - Beijing China /* release node */
644dd1de374Slin wang - Sun Microsystems - Beijing China ieee80211_free_node(in);
645dd1de374Slin wang - Sun Microsystems - Beijing China
646dd1de374Slin wang - Sun Microsystems - Beijing China /*
647dd1de374Slin wang - Sun Microsystems - Beijing China * Arrange to update the last rx timestamp only for
648dd1de374Slin wang - Sun Microsystems - Beijing China * frames from our ap when operating in station mode.
649dd1de374Slin wang - Sun Microsystems - Beijing China * This assumes the rx key is always setup when associated.
650dd1de374Slin wang - Sun Microsystems - Beijing China */
651dd1de374Slin wang - Sun Microsystems - Beijing China if (ic->ic_opmode == IEEE80211_M_STA &&
652dd1de374Slin wang - Sun Microsystems - Beijing China rs->rs_keyix != ATH9K_RXKEYIX_INVALID) {
653dd1de374Slin wang - Sun Microsystems - Beijing China ngood++;
654dd1de374Slin wang - Sun Microsystems - Beijing China }
655dd1de374Slin wang - Sun Microsystems - Beijing China
656dd1de374Slin wang - Sun Microsystems - Beijing China /*
657dd1de374Slin wang - Sun Microsystems - Beijing China * change the default rx antenna if rx diversity chooses the
658dd1de374Slin wang - Sun Microsystems - Beijing China * other antenna 3 times in a row.
659dd1de374Slin wang - Sun Microsystems - Beijing China */
660dd1de374Slin wang - Sun Microsystems - Beijing China if (sc->sc_defant != ds->ds_rxstat.rs_antenna) {
661dd1de374Slin wang - Sun Microsystems - Beijing China if (++sc->sc_rxotherant >= 3) {
662dd1de374Slin wang - Sun Microsystems - Beijing China ath9k_hw_setantenna(sc->sc_ah,
663dd1de374Slin wang - Sun Microsystems - Beijing China ds->ds_rxstat.rs_antenna);
664dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_defant = ds->ds_rxstat.rs_antenna;
665dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_rxotherant = 0;
666dd1de374Slin wang - Sun Microsystems - Beijing China }
667dd1de374Slin wang - Sun Microsystems - Beijing China } else {
668dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_rxotherant = 0;
669dd1de374Slin wang - Sun Microsystems - Beijing China }
670dd1de374Slin wang - Sun Microsystems - Beijing China
671*c0c93480Slin wang - Sun Microsystems - Beijing China requeue:
672dd1de374Slin wang - Sun Microsystems - Beijing China mutex_enter(&sc->sc_rxbuflock);
673dd1de374Slin wang - Sun Microsystems - Beijing China list_insert_tail(&sc->sc_rxbuf_list, bf);
674dd1de374Slin wang - Sun Microsystems - Beijing China mutex_exit(&sc->sc_rxbuflock);
675dd1de374Slin wang - Sun Microsystems - Beijing China arn_rx_buf_link(sc, bf);
676dd1de374Slin wang - Sun Microsystems - Beijing China } while (loop);
677dd1de374Slin wang - Sun Microsystems - Beijing China
678dd1de374Slin wang - Sun Microsystems - Beijing China if (ngood)
679dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_lastrx = ath9k_hw_gettsf64(ah);
680dd1de374Slin wang - Sun Microsystems - Beijing China
681dd1de374Slin wang - Sun Microsystems - Beijing China #undef PA2DESC
682dd1de374Slin wang - Sun Microsystems - Beijing China }
683dd1de374Slin wang - Sun Microsystems - Beijing China
684dd1de374Slin wang - Sun Microsystems - Beijing China uint_t
arn_softint_handler(caddr_t data)685dd1de374Slin wang - Sun Microsystems - Beijing China arn_softint_handler(caddr_t data)
686dd1de374Slin wang - Sun Microsystems - Beijing China {
687dd1de374Slin wang - Sun Microsystems - Beijing China struct arn_softc *sc = (struct arn_softc *)data;
688dd1de374Slin wang - Sun Microsystems - Beijing China
689dd1de374Slin wang - Sun Microsystems - Beijing China ARN_LOCK(sc);
690dd1de374Slin wang - Sun Microsystems - Beijing China
691dd1de374Slin wang - Sun Microsystems - Beijing China if (sc->sc_rx_pend) {
692dd1de374Slin wang - Sun Microsystems - Beijing China /* Soft interrupt for this driver */
693dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_rx_pend = 0;
694dd1de374Slin wang - Sun Microsystems - Beijing China ARN_UNLOCK(sc);
695dd1de374Slin wang - Sun Microsystems - Beijing China arn_rx_handler(sc);
696dd1de374Slin wang - Sun Microsystems - Beijing China return (DDI_INTR_CLAIMED);
697dd1de374Slin wang - Sun Microsystems - Beijing China }
698dd1de374Slin wang - Sun Microsystems - Beijing China
699dd1de374Slin wang - Sun Microsystems - Beijing China ARN_UNLOCK(sc);
700dd1de374Slin wang - Sun Microsystems - Beijing China
701dd1de374Slin wang - Sun Microsystems - Beijing China return (DDI_INTR_UNCLAIMED);
702dd1de374Slin wang - Sun Microsystems - Beijing China }
703