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 /* 138 * Configure the initial RTS rate to use. 139 */ 140 void 141 rtwn_set_rts_rate(struct rtwn_softc *sc, uint32_t rates) 142 { 143 uint8_t ridx; 144 145 /* 146 * We shouldn't set the initial RTS/CTS generation rate 147 * as the highest available rate - that may end up 148 * with trying to configure something like MCS1 RTS/CTS. 149 * 150 * Instead, choose a suitable low OFDM/CCK rate based 151 * on the basic rate bitmask. Assume the caller 152 * has filtered out CCK modes in 5GHz. 153 */ 154 rates &= (1 << RTWN_RIDX_CCK1) | (1 << RTWN_RIDX_CCK55) | 155 (1 << RTWN_RIDX_CCK11) | (1 << RTWN_RIDX_OFDM6) | 156 (1 << RTWN_RIDX_OFDM9) | (1 << RTWN_RIDX_OFDM12) | 157 (1 << RTWN_RIDX_OFDM18) | (1 << RTWN_RIDX_OFDM24); 158 if (rates == 0) { 159 device_printf(sc->sc_dev, 160 "WARNING: no configured basic RTS rate!\n"); 161 return; 162 } 163 ridx = fls(rates) - 1; 164 165 RTWN_DPRINTF(sc, RTWN_DEBUG_RA, 166 "%s: mask=0x%08x, ridx=%d\n", 167 __func__, rates, ridx); 168 169 rtwn_write_1(sc, R92C_INIRTS_RATE_SEL, ridx); 170 } 171 172 static void 173 rtwn_update_avgrssi(struct rtwn_softc *sc, struct rtwn_node *un, int8_t rssi, 174 int is_cck) 175 { 176 int pwdb; 177 178 /* Convert antenna signal to percentage. */ 179 if (rssi <= -100 || rssi >= 20) 180 pwdb = 0; 181 else if (rssi >= 0) 182 pwdb = 100; 183 else 184 pwdb = 100 + rssi; 185 if (is_cck) { 186 /* CCK gain is smaller than OFDM/MCS gain. */ 187 pwdb += 6; 188 if (pwdb > 100) 189 pwdb = 100; 190 if (pwdb <= 14) 191 pwdb -= 4; 192 else if (pwdb <= 26) 193 pwdb -= 8; 194 else if (pwdb <= 34) 195 pwdb -= 6; 196 else if (pwdb <= 42) 197 pwdb -= 2; 198 } 199 200 if (un->avg_pwdb == -1) /* Init. */ 201 un->avg_pwdb = pwdb; 202 else if (un->avg_pwdb < pwdb) 203 un->avg_pwdb = ((un->avg_pwdb * 19 + pwdb) / 20) + 1; 204 else 205 un->avg_pwdb = ((un->avg_pwdb * 19 + pwdb) / 20); 206 207 RTWN_DPRINTF(sc, RTWN_DEBUG_RSSI, 208 "MACID %d, PWDB %d, EMA %d\n", un->id, pwdb, un->avg_pwdb); 209 } 210 211 static int8_t 212 rtwn_get_rssi(struct rtwn_softc *sc, void *physt, int is_cck) 213 { 214 int8_t rssi; 215 216 if (is_cck) 217 rssi = rtwn_get_rssi_cck(sc, physt); 218 else /* OFDM/HT. */ 219 rssi = rtwn_get_rssi_ofdm(sc, physt); 220 221 return (rssi); 222 } 223 224 static uint32_t 225 rtwn_get_tsf_low(struct rtwn_softc *sc, int id) 226 { 227 return (rtwn_read_4(sc, R92C_TSFTR(id))); 228 } 229 230 static uint32_t 231 rtwn_get_tsf_high(struct rtwn_softc *sc, int id) 232 { 233 return (rtwn_read_4(sc, R92C_TSFTR(id) + 4)); 234 } 235 236 static void 237 rtwn_get_tsf(struct rtwn_softc *sc, uint64_t *buf, int id) 238 { 239 /* NB: we cannot read it at once. */ 240 *buf = rtwn_get_tsf_high(sc, id); 241 *buf <<= 32; 242 *buf += rtwn_get_tsf_low(sc, id); 243 } 244 245 static uint64_t 246 rtwn_extend_rx_tsf(struct rtwn_softc *sc, 247 const struct rtwn_rx_stat_common *stat) 248 { 249 uint64_t tsft; 250 uint32_t rxdw3, tsfl, tsfl_curr; 251 int id; 252 253 rxdw3 = le32toh(stat->rxdw3); 254 tsfl = le32toh(stat->tsf_low); 255 id = MS(rxdw3, RTWN_RXDW3_BSSID01_FIT); 256 257 switch (id) { 258 case 1: 259 case 2: 260 id >>= 1; 261 tsfl_curr = rtwn_get_tsf_low(sc, id); 262 break; 263 default: 264 { 265 uint32_t tsfl0, tsfl1; 266 267 tsfl0 = rtwn_get_tsf_low(sc, 0); 268 tsfl1 = rtwn_get_tsf_low(sc, 1); 269 270 if (abs(tsfl0 - tsfl) < abs(tsfl1 - tsfl)) { 271 id = 0; 272 tsfl_curr = tsfl0; 273 } else { 274 id = 1; 275 tsfl_curr = tsfl1; 276 } 277 break; 278 } 279 } 280 281 tsft = rtwn_get_tsf_high(sc, id); 282 if (tsfl > tsfl_curr && tsfl > 0xffff0000) 283 tsft--; 284 tsft <<= 32; 285 tsft += tsfl; 286 287 return (tsft); 288 } 289 290 struct ieee80211_node * 291 rtwn_rx_common(struct rtwn_softc *sc, struct mbuf *m, void *desc) 292 { 293 struct ieee80211com *ic = &sc->sc_ic; 294 struct ieee80211_node *ni; 295 struct ieee80211_frame_min *wh; 296 struct ieee80211_rx_stats rxs; 297 struct rtwn_node *un; 298 struct rtwn_rx_stat_common *stat; 299 void *physt; 300 uint32_t rxdw0; 301 int8_t rssi; 302 int cipher, infosz, is_cck, pktlen, shift; 303 304 stat = desc; 305 rxdw0 = le32toh(stat->rxdw0); 306 307 cipher = MS(rxdw0, RTWN_RXDW0_CIPHER); 308 infosz = MS(rxdw0, RTWN_RXDW0_INFOSZ) * 8; 309 pktlen = MS(rxdw0, RTWN_RXDW0_PKTLEN); 310 shift = MS(rxdw0, RTWN_RXDW0_SHIFT); 311 312 wh = (struct ieee80211_frame_min *)(mtodo(m, shift + infosz)); 313 if ((wh->i_fc[1] & IEEE80211_FC1_PROTECTED) && 314 cipher != R92C_CAM_ALGO_NONE) 315 m->m_flags |= M_WEP; 316 317 if (pktlen >= sizeof(*wh)) { 318 ni = ieee80211_find_rxnode(ic, wh); 319 if (ni != NULL && (ni->ni_flags & IEEE80211_NODE_HT)) 320 m->m_flags |= M_AMPDU; 321 } else 322 ni = NULL; 323 un = RTWN_NODE(ni); 324 325 if (infosz != 0 && (rxdw0 & RTWN_RXDW0_PHYST)) 326 physt = (void *)mtodo(m, shift); 327 else 328 physt = (un != NULL) ? &un->last_physt : &sc->last_physt; 329 330 bzero(&rxs, sizeof(rxs)); 331 rtwn_get_rx_stats(sc, &rxs, desc, physt); 332 if (rxs.c_pktflags & IEEE80211_RX_F_AMPDU) { 333 /* Next MPDU will come without PHY info. */ 334 memcpy(&sc->last_physt, physt, sizeof(sc->last_physt)); 335 if (un != NULL) 336 memcpy(&un->last_physt, physt, sizeof(sc->last_physt)); 337 } 338 339 /* Add some common bits. */ 340 /* NB: should not happen. */ 341 if (rxdw0 & RTWN_RXDW0_CRCERR) 342 rxs.c_pktflags |= IEEE80211_RX_F_FAIL_FCSCRC; 343 344 rxs.r_flags |= IEEE80211_R_TSF_START; /* XXX undocumented */ 345 346 /* 347 * Doing the TSF64 extension on USB is expensive, especially 348 * if it's being done on every MPDU in an AMPDU burst. 349 */ 350 if (sc->sc_ena_tsf64) { 351 rxs.r_flags |= IEEE80211_R_TSF64; 352 rxs.c_rx_tsf = rtwn_extend_rx_tsf(sc, stat); 353 } else { 354 rxs.r_flags |= IEEE80211_R_TSF32; 355 rxs.c_rx_tsf = le32toh(stat->tsf_low); 356 } 357 358 /* Get RSSI from PHY status descriptor. */ 359 is_cck = (rxs.c_pktflags & IEEE80211_RX_F_CCK) != 0; 360 rssi = rtwn_get_rssi(sc, physt, is_cck); 361 362 /* XXX TODO: we really need a rate-to-string method */ 363 RTWN_DPRINTF(sc, RTWN_DEBUG_RSSI, "%s: rssi %d, rate %d\n", 364 __func__, rssi, rxs.c_rate); 365 if (un != NULL && infosz != 0 && (rxdw0 & RTWN_RXDW0_PHYST)) { 366 /* Update our average RSSI. */ 367 rtwn_update_avgrssi(sc, un, rssi, is_cck); 368 } 369 370 rxs.r_flags |= IEEE80211_R_NF | IEEE80211_R_RSSI; 371 rxs.c_nf = RTWN_NOISE_FLOOR; 372 rxs.c_rssi = rssi - rxs.c_nf; 373 (void) ieee80211_add_rx_params(m, &rxs); 374 375 if (ieee80211_radiotap_active(ic)) { 376 struct rtwn_rx_radiotap_header *tap = &sc->sc_rxtap; 377 378 tap->wr_flags = rtwn_rx_radiotap_flags(sc, desc); 379 tap->wr_tsft = htole64(rxs.c_rx_tsf); 380 tap->wr_rate = rxs.c_rate; 381 tap->wr_dbm_antsignal = rssi; 382 tap->wr_dbm_antnoise = rxs.c_nf; 383 } 384 385 /* Drop PHY descriptor. */ 386 m_adj(m, infosz + shift); 387 388 /* If APPFCS, drop FCS */ 389 if (sc->rcr & R92C_RCR_APPFCS) 390 m_adj(m, -IEEE80211_CRC_LEN); 391 392 return (ni); 393 } 394 395 void 396 rtwn_adhoc_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m, int subtype, 397 const struct ieee80211_rx_stats *rxs, 398 int rssi, int nf) 399 { 400 struct ieee80211vap *vap = ni->ni_vap; 401 struct rtwn_softc *sc = vap->iv_ic->ic_softc; 402 struct rtwn_vap *uvp = RTWN_VAP(vap); 403 uint64_t ni_tstamp, curr_tstamp; 404 405 uvp->recv_mgmt(ni, m, subtype, rxs, rssi, nf); 406 407 if (vap->iv_state == IEEE80211_S_RUN && 408 (subtype == IEEE80211_FC0_SUBTYPE_BEACON || 409 subtype == IEEE80211_FC0_SUBTYPE_PROBE_RESP)) { 410 ni_tstamp = le64toh(ni->ni_tstamp.tsf); 411 RTWN_LOCK(sc); 412 rtwn_get_tsf(sc, &curr_tstamp, uvp->id); 413 RTWN_UNLOCK(sc); 414 415 if (ni_tstamp >= curr_tstamp) 416 (void) ieee80211_ibss_merge(ni); 417 } 418 } 419 420 static uint8_t 421 rtwn_get_multi_pos(const uint8_t maddr[]) 422 { 423 uint64_t mask = 0x00004d101df481b4; 424 uint8_t pos = 0x27; /* initial value */ 425 int i, j; 426 427 for (i = 0; i < IEEE80211_ADDR_LEN; i++) 428 for (j = (i == 0) ? 1 : 0; j < 8; j++) 429 if ((maddr[i] >> j) & 1) 430 pos ^= (mask >> (i * 8 + j - 1)); 431 432 pos &= 0x3f; 433 434 return (pos); 435 } 436 437 static u_int 438 rtwm_hash_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt) 439 { 440 uint32_t *mfilt = arg; 441 uint8_t pos; 442 443 pos = rtwn_get_multi_pos(LLADDR(sdl)); 444 mfilt[pos / 32] |= (1 << (pos % 32)); 445 446 return (1); 447 } 448 449 void 450 rtwn_set_multi(struct rtwn_softc *sc) 451 { 452 struct ieee80211com *ic = &sc->sc_ic; 453 uint32_t mfilt[2]; 454 455 RTWN_ASSERT_LOCKED(sc); 456 457 /* general structure was copied from ath(4). */ 458 if (ic->ic_allmulti == 0) { 459 struct ieee80211vap *vap; 460 461 /* 462 * Merge multicast addresses to form the hardware filter. 463 */ 464 mfilt[0] = mfilt[1] = 0; 465 TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) 466 if_foreach_llmaddr(vap->iv_ifp, rtwm_hash_maddr, mfilt); 467 } else 468 mfilt[0] = mfilt[1] = ~0; 469 470 rtwn_write_4(sc, R92C_MAR + 0, mfilt[0]); 471 rtwn_write_4(sc, R92C_MAR + 4, mfilt[1]); 472 473 RTWN_DPRINTF(sc, RTWN_DEBUG_STATE, "%s: MC filter %08x:%08x\n", 474 __func__, mfilt[0], mfilt[1]); 475 } 476 477 static void 478 rtwn_rxfilter_update_mgt(struct rtwn_softc *sc) 479 { 480 uint16_t filter; 481 482 filter = 0x7f7f; 483 if (sc->bcn_vaps == 0) { /* STA and/or MONITOR mode vaps */ 484 filter &= ~( 485 R92C_RXFLTMAP_SUBTYPE(IEEE80211_FC0_SUBTYPE_ASSOC_REQ) | 486 R92C_RXFLTMAP_SUBTYPE(IEEE80211_FC0_SUBTYPE_REASSOC_REQ) | 487 R92C_RXFLTMAP_SUBTYPE(IEEE80211_FC0_SUBTYPE_PROBE_REQ)); 488 } 489 if (sc->ap_vaps == sc->nvaps - sc->mon_vaps) { /* AP vaps only */ 490 filter &= ~( 491 R92C_RXFLTMAP_SUBTYPE(IEEE80211_FC0_SUBTYPE_ASSOC_RESP) | 492 R92C_RXFLTMAP_SUBTYPE(IEEE80211_FC0_SUBTYPE_REASSOC_RESP)); 493 } 494 rtwn_write_2(sc, R92C_RXFLTMAP0, filter); 495 } 496 497 void 498 rtwn_rxfilter_update(struct rtwn_softc *sc) 499 { 500 501 RTWN_ASSERT_LOCKED(sc); 502 503 /* Filter for management frames. */ 504 rtwn_rxfilter_update_mgt(sc); 505 506 /* Update Rx filter. */ 507 rtwn_set_promisc(sc); 508 } 509 510 void 511 rtwn_rxfilter_init(struct rtwn_softc *sc) 512 { 513 514 RTWN_ASSERT_LOCKED(sc); 515 516 /* Setup multicast filter. */ 517 rtwn_set_multi(sc); 518 519 /* Reject all control frames. */ 520 rtwn_write_2(sc, R92C_RXFLTMAP1, 0x0000); 521 522 /* Reject all data frames. */ 523 rtwn_write_2(sc, R92C_RXFLTMAP2, 0x0000); 524 525 /* Append generic Rx filter bits. */ 526 sc->rcr |= R92C_RCR_AM | R92C_RCR_AB | R92C_RCR_APM | 527 R92C_RCR_HTC_LOC_CTRL | R92C_RCR_APP_PHYSTS | 528 R92C_RCR_APP_ICV | R92C_RCR_APP_MIC; 529 530 /* 531 * Add FCS, to work around occasional 4 byte truncation 532 * with some frames. This is more problematic on RTL8812/ 533 * RTL8821 because they're also doing L3/L4 checksum offload 534 * and hardware encryption, so both are tagged as "passed" 535 * before the frame is truncated. 536 */ 537 sc->rcr |= R92C_RCR_APPFCS; 538 539 /* Update dynamic Rx filter parts. */ 540 rtwn_rxfilter_update(sc); 541 } 542 543 void 544 rtwn_rxfilter_set(struct rtwn_softc *sc) 545 { 546 if (!(sc->sc_flags & RTWN_RCR_LOCKED)) 547 rtwn_write_4(sc, R92C_RCR, sc->rcr); 548 } 549 550 void 551 rtwn_set_rx_bssid_all(struct rtwn_softc *sc, int enable) 552 { 553 554 if (enable) 555 sc->rcr &= ~R92C_RCR_CBSSID_BCN; 556 else 557 sc->rcr |= R92C_RCR_CBSSID_BCN; 558 rtwn_rxfilter_set(sc); 559 } 560 561 void 562 rtwn_set_promisc(struct rtwn_softc *sc) 563 { 564 struct ieee80211com *ic = &sc->sc_ic; 565 uint32_t mask_all, mask_min; 566 567 RTWN_ASSERT_LOCKED(sc); 568 569 mask_all = R92C_RCR_ACF | R92C_RCR_ADF | R92C_RCR_AMF | R92C_RCR_AAP; 570 mask_min = R92C_RCR_APM; 571 572 if (sc->bcn_vaps == 0) 573 mask_min |= R92C_RCR_CBSSID_BCN; 574 if (sc->ap_vaps == 0) 575 mask_min |= R92C_RCR_CBSSID_DATA; 576 577 if (ic->ic_promisc == 0 && sc->mon_vaps == 0) { 578 if (sc->bcn_vaps != 0) 579 mask_all |= R92C_RCR_CBSSID_BCN; 580 if (sc->ap_vaps != 0) /* for Null data frames */ 581 mask_all |= R92C_RCR_CBSSID_DATA; 582 583 sc->rcr &= ~mask_all; 584 sc->rcr |= mask_min; 585 } else { 586 sc->rcr &= ~mask_min; 587 sc->rcr |= mask_all; 588 } 589 590 /* 591 * Add FCS, to work around occasional 4 byte truncation. 592 * See the previous comment above R92C_RCR_APPFCS. 593 */ 594 sc->rcr |= R92C_RCR_APPFCS; 595 596 rtwn_rxfilter_set(sc); 597 } 598