xref: /freebsd/sys/dev/rtwn/if_rtwn_rx.c (revision 3a56015a2f5d630910177fa79a522bb95511ccf7)
1 /*	$OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $	*/
2 
3 /*-
4  * Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
5  * Copyright (c) 2014 Kevin Lo <kevlo@FreeBSD.org>
6  * Copyright (c) 2015-2016 Andriy Voskoboinyk <avos@FreeBSD.org>
7  *
8  * Permission to use, copy, modify, and distribute this software for any
9  * purpose with or without fee is hereby granted, provided that the above
10  * copyright notice and this permission notice appear in all copies.
11  *
12  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19  */
20 
21 #include <sys/cdefs.h>
22 #include "opt_wlan.h"
23 
24 #include <sys/param.h>
25 #include <sys/lock.h>
26 #include <sys/mutex.h>
27 #include <sys/mbuf.h>
28 #include <sys/kernel.h>
29 #include <sys/socket.h>
30 #include <sys/systm.h>
31 #include <sys/malloc.h>
32 #include <sys/queue.h>
33 #include <sys/taskqueue.h>
34 #include <sys/bus.h>
35 #include <sys/endian.h>
36 
37 #include <net/if.h>
38 #include <net/if_var.h>
39 #include <net/ethernet.h>
40 #include <net/if_dl.h>
41 #include <net/if_media.h>
42 
43 #include <net80211/ieee80211_var.h>
44 #include <net80211/ieee80211_radiotap.h>
45 
46 #include <dev/rtwn/if_rtwnreg.h>
47 #include <dev/rtwn/if_rtwnvar.h>
48 
49 #include <dev/rtwn/if_rtwn_debug.h>
50 #include <dev/rtwn/if_rtwn_ridx.h>
51 #include <dev/rtwn/if_rtwn_rx.h>
52 
53 #include <dev/rtwn/rtl8192c/r92c_reg.h>
54 
55 /*
56  * Get the driver rate set for the current operating rateset(s).
57  *
58  * rates_p is set to a mask of 11abg ridx values (not HW rate values.)
59  * htrates_p is set to a mask of 11n ridx values (not HW rate values),
60  *  starting at MCS0 == bit 0.
61  *
62  * maxrate_p is set to the ridx value.
63  *
64  * If basic_rates is 1 then only the 11abg basic rate logic will
65  * be applied; the HT rateset will be applied to 11n rates.
66  */
67 void
68 rtwn_get_rates(struct rtwn_softc *sc, const struct ieee80211_rateset *rs,
69     const struct ieee80211_htrateset *rs_ht, uint32_t *rates_p,
70     uint32_t *htrates_p, int *maxrate_p, int basic_rates)
71 {
72 	uint32_t rates = 0, htrates = 0;
73 	uint8_t ridx;
74 	int i, maxrate;
75 
76 	/* Get rates mask. */
77 	rates = 0;
78 	maxrate = 0;
79 
80 	/* This is for 11abg */
81 	for (i = 0; i < rs->rs_nrates; i++) {
82 		/* Convert 802.11 rate to HW rate index. */
83 		ridx = rate2ridx(IEEE80211_RV(rs->rs_rates[i]));
84 		if (ridx == RTWN_RIDX_UNKNOWN)	/* Unknown rate, skip. */
85 			continue;
86 		if (((rs->rs_rates[i] & IEEE80211_RATE_BASIC) != 0) ||
87 		    !basic_rates) {
88 			rates |= 1 << ridx;
89 			if (ridx > maxrate)
90 				maxrate = ridx;
91 		}
92 	}
93 
94 	/* If we're doing 11n, enable 11n rates */
95 	if (rs_ht != NULL) {
96 		for (i = 0; i < rs_ht->rs_nrates; i++) {
97 			uint8_t rate = rs_ht->rs_rates[i] & 0x7f;
98 			bool is_basic = rs_ht->rs_rates[i] &
99 			    IEEE80211_RATE_BASIC;
100 			/* Only do up to 2-stream rates for now */
101 			if ((rate) > 0xf)
102 				continue;
103 
104 			if (basic_rates && is_basic == false)
105 				continue;
106 
107 			ridx = rate & 0xf;
108 			htrates |= (1 << ridx);
109 
110 			/* Guard against the rate table being oddly ordered */
111 			if (RTWN_RIDX_HT_MCS(ridx) > maxrate)
112 				maxrate = RTWN_RIDX_HT_MCS(ridx);
113 		}
114 	}
115 
116 	RTWN_DPRINTF(sc, RTWN_DEBUG_RA,
117 	    "%s: rates 0x%08X htrates 0x%08X, maxrate %d\n",
118 	    __func__, rates, htrates, maxrate);
119 
120 	if (rates_p != NULL)
121 		*rates_p = rates;
122 	if (htrates_p != NULL)
123 		*htrates_p = htrates;
124 	if (maxrate_p != NULL)
125 		*maxrate_p = maxrate;
126 }
127 
128 void
129 rtwn_set_basicrates(struct rtwn_softc *sc, uint32_t rates)
130 {
131 
132 	RTWN_DPRINTF(sc, RTWN_DEBUG_RA, "%s: rates 0x%08X\n", __func__, rates);
133 
134 	rtwn_setbits_4(sc, R92C_RRSR, R92C_RRSR_RATE_BITMAP_M, rates);
135 }
136 
137 static void
138 rtwn_update_avgrssi(struct rtwn_softc *sc, struct rtwn_node *un, int8_t rssi,
139     int is_cck)
140 {
141 	int pwdb;
142 
143 	/* Convert antenna signal to percentage. */
144 	if (rssi <= -100 || rssi >= 20)
145 		pwdb = 0;
146 	else if (rssi >= 0)
147 		pwdb = 100;
148 	else
149 		pwdb = 100 + rssi;
150 	if (is_cck) {
151 		/* CCK gain is smaller than OFDM/MCS gain. */
152 		pwdb += 6;
153 		if (pwdb > 100)
154 			pwdb = 100;
155 		if (pwdb <= 14)
156 			pwdb -= 4;
157 		else if (pwdb <= 26)
158 			pwdb -= 8;
159 		else if (pwdb <= 34)
160 			pwdb -= 6;
161 		else if (pwdb <= 42)
162 			pwdb -= 2;
163 	}
164 
165 	if (un->avg_pwdb == -1)	/* Init. */
166 		un->avg_pwdb = pwdb;
167 	else if (un->avg_pwdb < pwdb)
168 		un->avg_pwdb = ((un->avg_pwdb * 19 + pwdb) / 20) + 1;
169 	else
170 		un->avg_pwdb = ((un->avg_pwdb * 19 + pwdb) / 20);
171 
172 	RTWN_DPRINTF(sc, RTWN_DEBUG_RSSI,
173 	    "MACID %d, PWDB %d, EMA %d\n", un->id, pwdb, un->avg_pwdb);
174 }
175 
176 static int8_t
177 rtwn_get_rssi(struct rtwn_softc *sc, void *physt, int is_cck)
178 {
179 	int8_t rssi;
180 
181 	if (is_cck)
182 		rssi = rtwn_get_rssi_cck(sc, physt);
183 	else	/* OFDM/HT. */
184 		rssi = rtwn_get_rssi_ofdm(sc, physt);
185 
186 	return (rssi);
187 }
188 
189 static uint32_t
190 rtwn_get_tsf_low(struct rtwn_softc *sc, int id)
191 {
192 	return (rtwn_read_4(sc, R92C_TSFTR(id)));
193 }
194 
195 static uint32_t
196 rtwn_get_tsf_high(struct rtwn_softc *sc, int id)
197 {
198 	return (rtwn_read_4(sc, R92C_TSFTR(id) + 4));
199 }
200 
201 static void
202 rtwn_get_tsf(struct rtwn_softc *sc, uint64_t *buf, int id)
203 {
204 	/* NB: we cannot read it at once. */
205 	*buf = rtwn_get_tsf_high(sc, id);
206 	*buf <<= 32;
207 	*buf += rtwn_get_tsf_low(sc, id);
208 }
209 
210 static uint64_t
211 rtwn_extend_rx_tsf(struct rtwn_softc *sc,
212     const struct rtwn_rx_stat_common *stat)
213 {
214 	uint64_t tsft;
215 	uint32_t rxdw3, tsfl, tsfl_curr;
216 	int id;
217 
218 	rxdw3 = le32toh(stat->rxdw3);
219 	tsfl = le32toh(stat->tsf_low);
220 	id = MS(rxdw3, RTWN_RXDW3_BSSID01_FIT);
221 
222 	switch (id) {
223 	case 1:
224 	case 2:
225 		id >>= 1;
226 		tsfl_curr = rtwn_get_tsf_low(sc, id);
227 		break;
228 	default:
229 	{
230 		uint32_t tsfl0, tsfl1;
231 
232 		tsfl0 = rtwn_get_tsf_low(sc, 0);
233 		tsfl1 = rtwn_get_tsf_low(sc, 1);
234 
235 		if (abs(tsfl0 - tsfl) < abs(tsfl1 - tsfl)) {
236 			id = 0;
237 			tsfl_curr = tsfl0;
238 		} else {
239 			id = 1;
240 			tsfl_curr = tsfl1;
241 		}
242 		break;
243 	}
244 	}
245 
246 	tsft = rtwn_get_tsf_high(sc, id);
247 	if (tsfl > tsfl_curr && tsfl > 0xffff0000)
248 		tsft--;
249 	tsft <<= 32;
250 	tsft += tsfl;
251 
252 	return (tsft);
253 }
254 
255 struct ieee80211_node *
256 rtwn_rx_common(struct rtwn_softc *sc, struct mbuf *m, void *desc)
257 {
258 	struct ieee80211com *ic = &sc->sc_ic;
259 	struct ieee80211_node *ni;
260 	struct ieee80211_frame_min *wh;
261 	struct ieee80211_rx_stats rxs;
262 	struct rtwn_node *un;
263 	struct rtwn_rx_stat_common *stat;
264 	void *physt;
265 	uint32_t rxdw0;
266 	int8_t rssi;
267 	int cipher, infosz, is_cck, pktlen, shift;
268 
269 	stat = desc;
270 	rxdw0 = le32toh(stat->rxdw0);
271 
272 	cipher = MS(rxdw0, RTWN_RXDW0_CIPHER);
273 	infosz = MS(rxdw0, RTWN_RXDW0_INFOSZ) * 8;
274 	pktlen = MS(rxdw0, RTWN_RXDW0_PKTLEN);
275 	shift = MS(rxdw0, RTWN_RXDW0_SHIFT);
276 
277 	wh = (struct ieee80211_frame_min *)(mtodo(m, shift + infosz));
278 	if ((wh->i_fc[1] & IEEE80211_FC1_PROTECTED) &&
279 	    cipher != R92C_CAM_ALGO_NONE)
280 		m->m_flags |= M_WEP;
281 
282 	if (pktlen >= sizeof(*wh)) {
283 		ni = ieee80211_find_rxnode(ic, wh);
284 		if (ni != NULL && (ni->ni_flags & IEEE80211_NODE_HT))
285 			m->m_flags |= M_AMPDU;
286 	} else
287 		ni = NULL;
288 	un = RTWN_NODE(ni);
289 
290 	if (infosz != 0 && (rxdw0 & RTWN_RXDW0_PHYST))
291 		physt = (void *)mtodo(m, shift);
292 	else
293 		physt = (un != NULL) ? &un->last_physt : &sc->last_physt;
294 
295 	bzero(&rxs, sizeof(rxs));
296 	rtwn_get_rx_stats(sc, &rxs, desc, physt);
297 	if (rxs.c_pktflags & IEEE80211_RX_F_AMPDU) {
298 		/* Next MPDU will come without PHY info. */
299 		memcpy(&sc->last_physt, physt, sizeof(sc->last_physt));
300 		if (un != NULL)
301 			memcpy(&un->last_physt, physt, sizeof(sc->last_physt));
302 	}
303 
304 	/* Add some common bits. */
305 	/* NB: should not happen. */
306 	if (rxdw0 & RTWN_RXDW0_CRCERR)
307 		rxs.c_pktflags |= IEEE80211_RX_F_FAIL_FCSCRC;
308 
309 	rxs.r_flags |= IEEE80211_R_TSF_START;	/* XXX undocumented */
310 
311 	/*
312 	 * Doing the TSF64 extension on USB is expensive, especially
313 	 * if it's being done on every MPDU in an AMPDU burst.
314 	 */
315 	if (sc->sc_ena_tsf64) {
316 		rxs.r_flags |= IEEE80211_R_TSF64;
317 		rxs.c_rx_tsf = rtwn_extend_rx_tsf(sc, stat);
318 	} else {
319 		rxs.r_flags |= IEEE80211_R_TSF32;
320 		rxs.c_rx_tsf = le32toh(stat->tsf_low);
321 	}
322 
323 	/* Get RSSI from PHY status descriptor. */
324 	is_cck = (rxs.c_pktflags & IEEE80211_RX_F_CCK) != 0;
325 	rssi = rtwn_get_rssi(sc, physt, is_cck);
326 
327 	/* XXX TODO: we really need a rate-to-string method */
328 	RTWN_DPRINTF(sc, RTWN_DEBUG_RSSI, "%s: rssi %d, rate %d\n",
329 	    __func__, rssi, rxs.c_rate);
330 	if (un != NULL && infosz != 0 && (rxdw0 & RTWN_RXDW0_PHYST)) {
331 		/* Update our average RSSI. */
332 		rtwn_update_avgrssi(sc, un, rssi, is_cck);
333 	}
334 
335 	rxs.r_flags |= IEEE80211_R_NF | IEEE80211_R_RSSI;
336 	rxs.c_nf = RTWN_NOISE_FLOOR;
337 	rxs.c_rssi = rssi - rxs.c_nf;
338 	(void) ieee80211_add_rx_params(m, &rxs);
339 
340 	if (ieee80211_radiotap_active(ic)) {
341 		struct rtwn_rx_radiotap_header *tap = &sc->sc_rxtap;
342 
343 		tap->wr_flags = rtwn_rx_radiotap_flags(sc, desc);
344 		tap->wr_tsft = htole64(rxs.c_rx_tsf);
345 		tap->wr_rate = rxs.c_rate;
346 		tap->wr_dbm_antsignal = rssi;
347 		tap->wr_dbm_antnoise = rxs.c_nf;
348 	}
349 
350 	/* Drop PHY descriptor. */
351 	m_adj(m, infosz + shift);
352 
353 	/* If APPFCS, drop FCS */
354 	if (sc->rcr & R92C_RCR_APPFCS)
355 		m_adj(m, -IEEE80211_CRC_LEN);
356 
357 	return (ni);
358 }
359 
360 void
361 rtwn_adhoc_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m, int subtype,
362     const struct ieee80211_rx_stats *rxs,
363     int rssi, int nf)
364 {
365 	struct ieee80211vap *vap = ni->ni_vap;
366 	struct rtwn_softc *sc = vap->iv_ic->ic_softc;
367 	struct rtwn_vap *uvp = RTWN_VAP(vap);
368 	uint64_t ni_tstamp, curr_tstamp;
369 
370 	uvp->recv_mgmt(ni, m, subtype, rxs, rssi, nf);
371 
372 	if (vap->iv_state == IEEE80211_S_RUN &&
373 	    (subtype == IEEE80211_FC0_SUBTYPE_BEACON ||
374 	    subtype == IEEE80211_FC0_SUBTYPE_PROBE_RESP)) {
375 		ni_tstamp = le64toh(ni->ni_tstamp.tsf);
376 		RTWN_LOCK(sc);
377 		rtwn_get_tsf(sc, &curr_tstamp, uvp->id);
378 		RTWN_UNLOCK(sc);
379 
380 		if (ni_tstamp >= curr_tstamp)
381 			(void) ieee80211_ibss_merge(ni);
382 	}
383 }
384 
385 static uint8_t
386 rtwn_get_multi_pos(const uint8_t maddr[])
387 {
388 	uint64_t mask = 0x00004d101df481b4;
389 	uint8_t pos = 0x27;	/* initial value */
390 	int i, j;
391 
392 	for (i = 0; i < IEEE80211_ADDR_LEN; i++)
393 		for (j = (i == 0) ? 1 : 0; j < 8; j++)
394 			if ((maddr[i] >> j) & 1)
395 				pos ^= (mask >> (i * 8 + j - 1));
396 
397 	pos &= 0x3f;
398 
399 	return (pos);
400 }
401 
402 static u_int
403 rtwm_hash_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt)
404 {
405 	uint32_t *mfilt = arg;
406 	uint8_t pos;
407 
408 	pos = rtwn_get_multi_pos(LLADDR(sdl));
409 	mfilt[pos / 32] |= (1 << (pos % 32));
410 
411 	return (1);
412 }
413 
414 void
415 rtwn_set_multi(struct rtwn_softc *sc)
416 {
417 	struct ieee80211com *ic = &sc->sc_ic;
418 	uint32_t mfilt[2];
419 
420 	RTWN_ASSERT_LOCKED(sc);
421 
422 	/* general structure was copied from ath(4). */
423 	if (ic->ic_allmulti == 0) {
424 		struct ieee80211vap *vap;
425 
426 		/*
427 		 * Merge multicast addresses to form the hardware filter.
428 		 */
429 		mfilt[0] = mfilt[1] = 0;
430 		TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next)
431 			if_foreach_llmaddr(vap->iv_ifp, rtwm_hash_maddr, mfilt);
432 	} else
433 		mfilt[0] = mfilt[1] = ~0;
434 
435 	rtwn_write_4(sc, R92C_MAR + 0, mfilt[0]);
436 	rtwn_write_4(sc, R92C_MAR + 4, mfilt[1]);
437 
438 	RTWN_DPRINTF(sc, RTWN_DEBUG_STATE, "%s: MC filter %08x:%08x\n",
439 	    __func__, mfilt[0], mfilt[1]);
440 }
441 
442 static void
443 rtwn_rxfilter_update_mgt(struct rtwn_softc *sc)
444 {
445 	uint16_t filter;
446 
447 	filter = 0x7f7f;
448 	if (sc->bcn_vaps == 0) {	/* STA and/or MONITOR mode vaps */
449 		filter &= ~(
450 		    R92C_RXFLTMAP_SUBTYPE(IEEE80211_FC0_SUBTYPE_ASSOC_REQ) |
451 		    R92C_RXFLTMAP_SUBTYPE(IEEE80211_FC0_SUBTYPE_REASSOC_REQ) |
452 		    R92C_RXFLTMAP_SUBTYPE(IEEE80211_FC0_SUBTYPE_PROBE_REQ));
453 	}
454 	if (sc->ap_vaps == sc->nvaps - sc->mon_vaps) {	/* AP vaps only */
455 		filter &= ~(
456 		    R92C_RXFLTMAP_SUBTYPE(IEEE80211_FC0_SUBTYPE_ASSOC_RESP) |
457 		    R92C_RXFLTMAP_SUBTYPE(IEEE80211_FC0_SUBTYPE_REASSOC_RESP));
458 	}
459 	rtwn_write_2(sc, R92C_RXFLTMAP0, filter);
460 }
461 
462 void
463 rtwn_rxfilter_update(struct rtwn_softc *sc)
464 {
465 
466 	RTWN_ASSERT_LOCKED(sc);
467 
468 	/* Filter for management frames. */
469 	rtwn_rxfilter_update_mgt(sc);
470 
471 	/* Update Rx filter. */
472 	rtwn_set_promisc(sc);
473 }
474 
475 void
476 rtwn_rxfilter_init(struct rtwn_softc *sc)
477 {
478 
479 	RTWN_ASSERT_LOCKED(sc);
480 
481 	/* Setup multicast filter. */
482 	rtwn_set_multi(sc);
483 
484 	/* Reject all control frames. */
485 	rtwn_write_2(sc, R92C_RXFLTMAP1, 0x0000);
486 
487 	/* Reject all data frames. */
488 	rtwn_write_2(sc, R92C_RXFLTMAP2, 0x0000);
489 
490 	/* Append generic Rx filter bits. */
491 	sc->rcr |= R92C_RCR_AM | R92C_RCR_AB | R92C_RCR_APM |
492 	    R92C_RCR_HTC_LOC_CTRL | R92C_RCR_APP_PHYSTS |
493 	    R92C_RCR_APP_ICV | R92C_RCR_APP_MIC;
494 
495 	/*
496 	 * Add FCS, to work around occasional 4 byte truncation
497 	 * with some frames.  This is more problematic on RTL8812/
498 	 * RTL8821 because they're also doing L3/L4 checksum offload
499 	 * and hardware encryption, so both are tagged as "passed"
500 	 * before the frame is truncated.
501 	 */
502 	sc->rcr |= R92C_RCR_APPFCS;
503 
504 	/* Update dynamic Rx filter parts. */
505 	rtwn_rxfilter_update(sc);
506 }
507 
508 void
509 rtwn_rxfilter_set(struct rtwn_softc *sc)
510 {
511 	if (!(sc->sc_flags & RTWN_RCR_LOCKED))
512 		rtwn_write_4(sc, R92C_RCR, sc->rcr);
513 }
514 
515 void
516 rtwn_set_rx_bssid_all(struct rtwn_softc *sc, int enable)
517 {
518 
519 	if (enable)
520 		sc->rcr &= ~R92C_RCR_CBSSID_BCN;
521 	else
522 		sc->rcr |= R92C_RCR_CBSSID_BCN;
523 	rtwn_rxfilter_set(sc);
524 }
525 
526 void
527 rtwn_set_promisc(struct rtwn_softc *sc)
528 {
529 	struct ieee80211com *ic = &sc->sc_ic;
530 	uint32_t mask_all, mask_min;
531 
532 	RTWN_ASSERT_LOCKED(sc);
533 
534 	mask_all = R92C_RCR_ACF | R92C_RCR_ADF | R92C_RCR_AMF | R92C_RCR_AAP;
535 	mask_min = R92C_RCR_APM | R92C_RCR_APPFCS;
536 
537 	if (sc->bcn_vaps == 0)
538 		mask_min |= R92C_RCR_CBSSID_BCN;
539 	if (sc->ap_vaps == 0)
540 		mask_min |= R92C_RCR_CBSSID_DATA;
541 
542 	if (ic->ic_promisc == 0 && sc->mon_vaps == 0) {
543 		if (sc->bcn_vaps != 0)
544 			mask_all |= R92C_RCR_CBSSID_BCN;
545 		if (sc->ap_vaps != 0)	/* for Null data frames */
546 			mask_all |= R92C_RCR_CBSSID_DATA;
547 
548 		sc->rcr &= ~mask_all;
549 		sc->rcr |= mask_min;
550 	} else {
551 		sc->rcr &= ~mask_min;
552 		sc->rcr |= mask_all;
553 	}
554 	rtwn_rxfilter_set(sc);
555 }
556