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