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