xref: /freebsd/sys/dev/rtwn/if_rtwn_rx.c (revision 63d1fd5970ec814904aa0f4580b10a0d302d08b2)
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 __FBSDID("$FreeBSD$");
23 
24 #include "opt_wlan.h"
25 
26 #include <sys/param.h>
27 #include <sys/lock.h>
28 #include <sys/mutex.h>
29 #include <sys/mbuf.h>
30 #include <sys/kernel.h>
31 #include <sys/socket.h>
32 #include <sys/systm.h>
33 #include <sys/malloc.h>
34 #include <sys/queue.h>
35 #include <sys/taskqueue.h>
36 #include <sys/bus.h>
37 #include <sys/endian.h>
38 
39 #include <net/if.h>
40 #include <net/if_var.h>
41 #include <net/ethernet.h>
42 #include <net/if_dl.h>
43 #include <net/if_media.h>
44 
45 #include <net80211/ieee80211_var.h>
46 #include <net80211/ieee80211_radiotap.h>
47 
48 #include <dev/rtwn/if_rtwnreg.h>
49 #include <dev/rtwn/if_rtwnvar.h>
50 
51 #include <dev/rtwn/if_rtwn_debug.h>
52 #include <dev/rtwn/if_rtwn_ridx.h>
53 #include <dev/rtwn/if_rtwn_rx.h>
54 
55 #include <dev/rtwn/rtl8192c/r92c_reg.h>
56 #include <dev/rtwn/rtl8192c/r92c_rx_desc.h>
57 
58 
59 void
60 rtwn_get_rates(struct rtwn_softc *sc, const struct ieee80211_rateset *rs,
61     const struct ieee80211_htrateset *rs_ht, uint32_t *rates_p,
62     int *maxrate_p, int basic_rates)
63 {
64 	uint32_t rates;
65 	uint8_t ridx;
66 	int i, maxrate;
67 
68 	/* Get rates mask. */
69 	rates = 0;
70 	maxrate = 0;
71 
72 	/* This is for 11bg */
73 	for (i = 0; i < rs->rs_nrates; i++) {
74 		/* Convert 802.11 rate to HW rate index. */
75 		ridx = rate2ridx(IEEE80211_RV(rs->rs_rates[i]));
76 		if (ridx == RTWN_RIDX_UNKNOWN)	/* Unknown rate, skip. */
77 			continue;
78 		if (((rs->rs_rates[i] & IEEE80211_RATE_BASIC) != 0) ||
79 		    !basic_rates) {
80 			rates |= 1 << ridx;
81 			if (ridx > maxrate)
82 				maxrate = ridx;
83 		}
84 	}
85 
86 	/* If we're doing 11n, enable 11n rates */
87 	if (rs_ht != NULL && !basic_rates) {
88 		for (i = 0; i < rs_ht->rs_nrates; i++) {
89 			if ((rs_ht->rs_rates[i] & 0x7f) > 0xf)
90 				continue;
91 			/* 11n rates start at index 12 */
92 			ridx = RTWN_RIDX_MCS((rs_ht->rs_rates[i]) & 0xf);
93 			rates |= (1 << ridx);
94 
95 			/* Guard against the rate table being oddly ordered */
96 			if (ridx > maxrate)
97 				maxrate = ridx;
98 		}
99 	}
100 
101 	RTWN_DPRINTF(sc, RTWN_DEBUG_RA,
102 	    "%s: rates 0x%08X, maxrate %d\n", __func__, rates, maxrate);
103 
104 	if (rates_p != NULL)
105 		*rates_p = rates;
106 	if (maxrate_p != NULL)
107 		*maxrate_p = maxrate;
108 }
109 
110 void
111 rtwn_set_basicrates(struct rtwn_softc *sc, uint32_t rates)
112 {
113 
114 	RTWN_DPRINTF(sc, RTWN_DEBUG_RA, "%s: rates 0x%08X\n", __func__, rates);
115 
116 	rtwn_setbits_4(sc, R92C_RRSR, R92C_RRSR_RATE_BITMAP_M, rates);
117 }
118 
119 static void
120 rtwn_update_avgrssi(struct rtwn_softc *sc, struct rtwn_node *un, int rate)
121 {
122 	int pwdb;
123 
124 	/* Convert antenna signal to percentage. */
125 	if (un->last_rssi <= -100 || un->last_rssi >= 20)
126 		pwdb = 0;
127 	else if (un->last_rssi >= 0)
128 		pwdb = 100;
129 	else
130 		pwdb = 100 + un->last_rssi;
131 	if (RTWN_RATE_IS_CCK(rate)) {
132 		/* CCK gain is smaller than OFDM/MCS gain. */
133 		pwdb += 6;
134 		if (pwdb > 100)
135 			pwdb = 100;
136 		if (pwdb <= 14)
137 			pwdb -= 4;
138 		else if (pwdb <= 26)
139 			pwdb -= 8;
140 		else if (pwdb <= 34)
141 			pwdb -= 6;
142 		else if (pwdb <= 42)
143 			pwdb -= 2;
144 	}
145 
146 	if (un->avg_pwdb == -1)	/* Init. */
147 		un->avg_pwdb = pwdb;
148 	else if (un->avg_pwdb < pwdb)
149 		un->avg_pwdb = ((un->avg_pwdb * 19 + pwdb) / 20) + 1;
150 	else
151 		un->avg_pwdb = ((un->avg_pwdb * 19 + pwdb) / 20);
152 
153 	RTWN_DPRINTF(sc, RTWN_DEBUG_RSSI,
154 	    "MACID %d, PWDB %d, EMA %d\n", un->id, pwdb, un->avg_pwdb);
155 }
156 
157 static int8_t
158 rtwn_get_rssi(struct rtwn_softc *sc, int rate, void *physt)
159 {
160 	int8_t rssi;
161 
162 	if (RTWN_RATE_IS_CCK(rate))
163 		rssi = rtwn_get_rssi_cck(sc, physt);
164 	else	/* OFDM/HT. */
165 		rssi = rtwn_get_rssi_ofdm(sc, physt);
166 
167 	return (rssi);
168 }
169 
170 static uint32_t
171 rtwn_get_tsf_low(struct rtwn_softc *sc, int id)
172 {
173 	return (rtwn_read_4(sc, R92C_TSFTR(id)));
174 }
175 
176 static uint32_t
177 rtwn_get_tsf_high(struct rtwn_softc *sc, int id)
178 {
179 	return (rtwn_read_4(sc, R92C_TSFTR(id) + 4));
180 }
181 
182 static void
183 rtwn_get_tsf(struct rtwn_softc *sc, uint64_t *buf, int id)
184 {
185 	/* NB: we cannot read it at once. */
186 	*buf = rtwn_get_tsf_high(sc, id);
187 	*buf <<= 32;
188 	*buf += rtwn_get_tsf_low(sc, id);
189 }
190 
191 struct ieee80211_node *
192 rtwn_rx_common(struct rtwn_softc *sc, struct mbuf *m, void *desc,
193     int8_t *rssi)
194 {
195 	struct ieee80211com *ic = &sc->sc_ic;
196 	struct ieee80211_node *ni;
197 	struct ieee80211_frame_min *wh;
198 	struct rtwn_node *un;
199 	struct r92c_rx_stat *stat;
200 	uint32_t rxdw0, rxdw3;
201 	int cipher, infosz, pktlen, rate, shift;
202 
203 	stat = desc;
204 	rxdw0 = le32toh(stat->rxdw0);
205 	rxdw3 = le32toh(stat->rxdw3);
206 
207 	cipher = MS(rxdw0, R92C_RXDW0_CIPHER);
208 	infosz = MS(rxdw0, R92C_RXDW0_INFOSZ) * 8;
209 	pktlen = MS(rxdw0, R92C_RXDW0_PKTLEN);
210 	shift = MS(rxdw0, R92C_RXDW0_SHIFT);
211 	rate = MS(rxdw3, R92C_RXDW3_RATE);
212 
213 	wh = (struct ieee80211_frame_min *)(mtodo(m, shift + infosz));
214 	if ((wh->i_fc[1] & IEEE80211_FC1_PROTECTED) &&
215 	    cipher != R92C_CAM_ALGO_NONE)
216 		m->m_flags |= M_WEP;
217 
218 	if (pktlen >= sizeof(*wh))
219 		ni = ieee80211_find_rxnode(ic, wh);
220 	else
221 		ni = NULL;
222 	un = RTWN_NODE(ni);
223 
224 	/* Get RSSI from PHY status descriptor if present. */
225 	if (infosz != 0 && (rxdw0 & R92C_RXDW0_PHYST)) {
226 		*rssi = rtwn_get_rssi(sc, rate, mtod(m, void *));
227 		RTWN_DPRINTF(sc, RTWN_DEBUG_RSSI, "%s: rssi %d, ridx %d\n",
228 		    __func__, *rssi, rate);
229 
230 		sc->last_rssi = *rssi;
231 		if (un != NULL) {
232 			un->last_rssi = *rssi;
233 
234 			/* Update our average RSSI. */
235 			rtwn_update_avgrssi(sc, un, rate);
236 		}
237 	} else
238 		*rssi = (un != NULL) ? un->last_rssi : sc->last_rssi;
239 
240 	if (ieee80211_radiotap_active(ic)) {
241 		struct rtwn_rx_radiotap_header *tap = &sc->sc_rxtap;
242 		int id = RTWN_VAP_ID_INVALID;
243 
244 		if (ni != NULL)
245 			id = RTWN_VAP(ni->ni_vap)->id;
246 		if (id == RTWN_VAP_ID_INVALID)
247 			id = 0;
248 
249 		tap->wr_flags = rtwn_rx_radiotap_flags(sc, desc);
250 		tap->wr_tsft = rtwn_get_tsf_high(sc, id);
251 		if (le32toh(stat->tsf_low) > rtwn_get_tsf_low(sc, id))
252 			tap->wr_tsft--;
253 		tap->wr_tsft = (uint64_t)htole32(tap->wr_tsft) << 32;
254 		tap->wr_tsft += stat->tsf_low;
255 
256 		/* XXX 20/40? */
257 
258 		/* Map HW rate index to 802.11 rate. */
259 		if (rate < RTWN_RIDX_MCS(0))
260 			tap->wr_rate = ridx2rate[rate];
261 		else	/* MCS0~15. */
262 			tap->wr_rate = IEEE80211_RATE_MCS | (rate - 12);
263 
264 		tap->wr_dbm_antsignal = *rssi;
265 		tap->wr_dbm_antnoise = RTWN_NOISE_FLOOR;
266 	}
267 
268 	/* Drop PHY descriptor. */
269 	m_adj(m, infosz + shift);
270 
271 	return (ni);
272 }
273 
274 void
275 rtwn_adhoc_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m, int subtype,
276     const struct ieee80211_rx_stats *rxs,
277     int rssi, int nf)
278 {
279 	struct ieee80211vap *vap = ni->ni_vap;
280 	struct rtwn_softc *sc = vap->iv_ic->ic_softc;
281 	struct rtwn_vap *uvp = RTWN_VAP(vap);
282 	uint64_t ni_tstamp, curr_tstamp;
283 
284 	uvp->recv_mgmt(ni, m, subtype, rxs, rssi, nf);
285 
286 	if (vap->iv_state == IEEE80211_S_RUN &&
287 	    (subtype == IEEE80211_FC0_SUBTYPE_BEACON ||
288 	    subtype == IEEE80211_FC0_SUBTYPE_PROBE_RESP)) {
289 		ni_tstamp = le64toh(ni->ni_tstamp.tsf);
290 		RTWN_LOCK(sc);
291 		rtwn_get_tsf(sc, &curr_tstamp, uvp->id);
292 		RTWN_UNLOCK(sc);
293 
294 		if (ni_tstamp >= curr_tstamp)
295 			(void) ieee80211_ibss_merge(ni);
296 	}
297 }
298 
299 static uint8_t
300 rtwn_get_multi_pos(const uint8_t maddr[])
301 {
302 	uint64_t mask = 0x00004d101df481b4;
303 	uint8_t pos = 0x27;	/* initial value */
304 	int i, j;
305 
306 	for (i = 0; i < IEEE80211_ADDR_LEN; i++)
307 		for (j = (i == 0) ? 1 : 0; j < 8; j++)
308 			if ((maddr[i] >> j) & 1)
309 				pos ^= (mask >> (i * 8 + j - 1));
310 
311 	pos &= 0x3f;
312 
313 	return (pos);
314 }
315 
316 void
317 rtwn_set_multi(struct rtwn_softc *sc)
318 {
319 	struct ieee80211com *ic = &sc->sc_ic;
320 	uint32_t mfilt[2];
321 
322 	RTWN_ASSERT_LOCKED(sc);
323 
324 	/* general structure was copied from ath(4). */
325 	if (ic->ic_allmulti == 0) {
326 		struct ieee80211vap *vap;
327 		struct ifnet *ifp;
328 		struct ifmultiaddr *ifma;
329 
330 		/*
331 		 * Merge multicast addresses to form the hardware filter.
332 		 */
333 		mfilt[0] = mfilt[1] = 0;
334 		TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) {
335 			ifp = vap->iv_ifp;
336 			if_maddr_rlock(ifp);
337 			TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
338 				caddr_t dl;
339 				uint8_t pos;
340 
341 				dl = LLADDR((struct sockaddr_dl *)
342 				    ifma->ifma_addr);
343 				pos = rtwn_get_multi_pos(dl);
344 
345 				mfilt[pos / 32] |= (1 << (pos % 32));
346 			}
347 			if_maddr_runlock(ifp);
348 		}
349 	} else
350 		mfilt[0] = mfilt[1] = ~0;
351 
352 
353 	rtwn_write_4(sc, R92C_MAR + 0, mfilt[0]);
354 	rtwn_write_4(sc, R92C_MAR + 4, mfilt[1]);
355 
356 	RTWN_DPRINTF(sc, RTWN_DEBUG_STATE, "%s: MC filter %08x:%08x\n",
357 	    __func__, mfilt[0], mfilt[1]);
358 }
359 
360 static void
361 rtwn_rxfilter_update_mgt(struct rtwn_softc *sc)
362 {
363 	uint16_t filter;
364 
365 	filter = 0x7f7f;
366 	if (sc->bcn_vaps == 0) {	/* STA and/or MONITOR mode vaps */
367 		filter &= ~(
368 		    R92C_RXFLTMAP_SUBTYPE(IEEE80211_FC0_SUBTYPE_ASSOC_REQ) |
369 		    R92C_RXFLTMAP_SUBTYPE(IEEE80211_FC0_SUBTYPE_REASSOC_REQ) |
370 		    R92C_RXFLTMAP_SUBTYPE(IEEE80211_FC0_SUBTYPE_PROBE_REQ));
371 	}
372 	if (sc->ap_vaps == sc->nvaps - sc->mon_vaps) {	/* AP vaps only */
373 		filter &= ~(
374 		    R92C_RXFLTMAP_SUBTYPE(IEEE80211_FC0_SUBTYPE_ASSOC_RESP) |
375 		    R92C_RXFLTMAP_SUBTYPE(IEEE80211_FC0_SUBTYPE_REASSOC_RESP));
376 	}
377 	rtwn_write_2(sc, R92C_RXFLTMAP0, filter);
378 }
379 
380 void
381 rtwn_rxfilter_update(struct rtwn_softc *sc)
382 {
383 
384 	RTWN_ASSERT_LOCKED(sc);
385 
386 	/* Filter for management frames. */
387 	rtwn_rxfilter_update_mgt(sc);
388 
389 	/* Update Rx filter. */
390 	rtwn_set_promisc(sc);
391 }
392 
393 void
394 rtwn_rxfilter_init(struct rtwn_softc *sc)
395 {
396 
397 	RTWN_ASSERT_LOCKED(sc);
398 
399 	/* Setup multicast filter. */
400 	rtwn_set_multi(sc);
401 
402 	/* Reject all control frames. */
403 	rtwn_write_2(sc, R92C_RXFLTMAP1, 0x0000);
404 
405 	/* Reject all data frames. */
406 	rtwn_write_2(sc, R92C_RXFLTMAP2, 0x0000);
407 
408 	/* Append generic Rx filter bits. */
409 	sc->rcr |= R92C_RCR_AM | R92C_RCR_AB | R92C_RCR_APM |
410 	    R92C_RCR_HTC_LOC_CTRL | R92C_RCR_APP_PHYSTS |
411 	    R92C_RCR_APP_ICV | R92C_RCR_APP_MIC;
412 
413 	/* Update dynamic Rx filter parts. */
414 	rtwn_rxfilter_update(sc);
415 }
416 
417 void
418 rtwn_rxfilter_set(struct rtwn_softc *sc)
419 {
420 	if (!(sc->sc_flags & RTWN_RCR_LOCKED))
421 		rtwn_write_4(sc, R92C_RCR, sc->rcr);
422 }
423 
424 void
425 rtwn_set_rx_bssid_all(struct rtwn_softc *sc, int enable)
426 {
427 
428 	if (enable)
429 		sc->rcr &= ~R92C_RCR_CBSSID_BCN;
430 	else
431 		sc->rcr |= R92C_RCR_CBSSID_BCN;
432 	rtwn_rxfilter_set(sc);
433 }
434 
435 void
436 rtwn_set_promisc(struct rtwn_softc *sc)
437 {
438 	struct ieee80211com *ic = &sc->sc_ic;
439 	uint32_t mask_all, mask_min;
440 
441 	RTWN_ASSERT_LOCKED(sc);
442 
443 	mask_all = R92C_RCR_ACF | R92C_RCR_ADF | R92C_RCR_AMF | R92C_RCR_AAP;
444 	mask_min = R92C_RCR_APM;
445 
446 	if (sc->bcn_vaps == 0)
447 		mask_min |= R92C_RCR_CBSSID_BCN;
448 	if (sc->ap_vaps == 0)
449 		mask_min |= R92C_RCR_CBSSID_DATA;
450 
451 	if (ic->ic_promisc == 0 && sc->mon_vaps == 0) {
452 		if (sc->bcn_vaps != 0)
453 			mask_all |= R92C_RCR_CBSSID_BCN;
454 		if (sc->ap_vaps != 0)	/* for Null data frames */
455 			mask_all |= R92C_RCR_CBSSID_DATA;
456 
457 		sc->rcr &= ~mask_all;
458 		sc->rcr |= mask_min;
459 	} else {
460 		sc->rcr &= ~mask_min;
461 		sc->rcr |= mask_all;
462 	}
463 	rtwn_rxfilter_set(sc);
464 }
465