diff --git a/sys/dev/rtwn/if_rtwn_cam.c b/sys/dev/rtwn/if_rtwn_cam.c index 6ee630533675..febb93fa97fd 100644 --- a/sys/dev/rtwn/if_rtwn_cam.c +++ b/sys/dev/rtwn/if_rtwn_cam.c @@ -1,363 +1,344 @@ /* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */ /*- * Copyright (c) 2010 Damien Bergamini * Copyright (c) 2014 Kevin Lo * Copyright (c) 2015-2016 Andriy Voskoboinyk * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include __FBSDID("$FreeBSD$"); #include "opt_wlan.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include void rtwn_init_cam(struct rtwn_softc *sc) { /* Invalidate all CAM entries. */ rtwn_write_4(sc, R92C_CAMCMD, R92C_CAMCMD_POLLING | R92C_CAMCMD_CLR); } static int rtwn_cam_write(struct rtwn_softc *sc, uint32_t addr, uint32_t data) { int error; error = rtwn_write_4(sc, R92C_CAMWRITE, data); if (error != 0) return (error); error = rtwn_write_4(sc, R92C_CAMCMD, R92C_CAMCMD_POLLING | R92C_CAMCMD_WRITE | SM(R92C_CAMCMD_ADDR, addr)); return (error); } void rtwn_init_seccfg(struct rtwn_softc *sc) { uint16_t seccfg; /* Select decryption / encryption flags. */ seccfg = 0; switch (sc->sc_hwcrypto) { case RTWN_CRYPTO_SW: break; /* nothing to do */ case RTWN_CRYPTO_PAIR: /* NB: TXUCKEY_DEF / RXUCKEY_DEF are required for RTL8192C */ seccfg = R92C_SECCFG_TXUCKEY_DEF | R92C_SECCFG_RXUCKEY_DEF | R92C_SECCFG_TXENC_ENA | R92C_SECCFG_RXDEC_ENA | R92C_SECCFG_MC_SRCH_DIS; break; case RTWN_CRYPTO_FULL: seccfg = R92C_SECCFG_TXUCKEY_DEF | R92C_SECCFG_RXUCKEY_DEF | R92C_SECCFG_TXENC_ENA | R92C_SECCFG_RXDEC_ENA | R92C_SECCFG_TXBCKEY_DEF | R92C_SECCFG_RXBCKEY_DEF; break; default: KASSERT(0, ("%s: case %d was not handled\n", __func__, sc->sc_hwcrypto)); break; } RTWN_DPRINTF(sc, RTWN_DEBUG_KEY, "%s: seccfg %04X, hwcrypto %d\n", __func__, seccfg, sc->sc_hwcrypto); rtwn_write_2(sc, R92C_SECCFG, seccfg); } int rtwn_key_alloc(struct ieee80211vap *vap, struct ieee80211_key *k, ieee80211_keyix *keyix, ieee80211_keyix *rxkeyix) { struct rtwn_softc *sc = vap->iv_ic->ic_softc; int i, start; if (&vap->iv_nw_keys[0] <= k && k < &vap->iv_nw_keys[IEEE80211_WEP_NKID]) { -#if __FreeBSD_version > 1200018 *keyix = ieee80211_crypto_get_key_wepidx(vap, k); -#else - *keyix = k - vap->iv_nw_keys; -#endif if (sc->sc_hwcrypto != RTWN_CRYPTO_FULL) k->wk_flags |= IEEE80211_KEY_SWCRYPT; else { RTWN_LOCK(sc); if (isset(sc->keys_bmap, *keyix)) { device_printf(sc->sc_dev, "%s: group key slot %d is already used!\n", __func__, *keyix); /* XXX recover? */ RTWN_UNLOCK(sc); return (0); } setbit(sc->keys_bmap, *keyix); RTWN_UNLOCK(sc); } goto end; } start = sc->cam_entry_limit; switch (sc->sc_hwcrypto) { case RTWN_CRYPTO_SW: k->wk_flags |= IEEE80211_KEY_SWCRYPT; *keyix = 0; goto end; case RTWN_CRYPTO_PAIR: /* all slots for pairwise keys. */ start = 0; RTWN_LOCK(sc); if (sc->sc_flags & RTWN_FLAG_CAM_FIXED) start = 4; RTWN_UNLOCK(sc); break; case RTWN_CRYPTO_FULL: /* first 4 - for group keys, others for pairwise. */ start = 4; break; default: KASSERT(0, ("%s: case %d was not handled!\n", __func__, sc->sc_hwcrypto)); break; } RTWN_LOCK(sc); for (i = start; i < sc->cam_entry_limit; i++) { if (isclr(sc->keys_bmap, i)) { setbit(sc->keys_bmap, i); *keyix = i; break; } } RTWN_UNLOCK(sc); if (i == sc->cam_entry_limit) { -#if __FreeBSD_version > 1200008 /* XXX check and remove keys with the same MAC address */ k->wk_flags |= IEEE80211_KEY_SWCRYPT; *keyix = 0; -#else - device_printf(sc->sc_dev, - "%s: no free space in the key table\n", __func__); - return (0); -#endif } end: *rxkeyix = *keyix; return (1); } static int rtwn_key_set_cb0(struct rtwn_softc *sc, const struct ieee80211_key *k) { uint8_t algo, keyid; int i, error; if (sc->sc_hwcrypto == RTWN_CRYPTO_FULL && k->wk_keyix < IEEE80211_WEP_NKID) keyid = k->wk_keyix; else keyid = 0; /* Map net80211 cipher to HW crypto algorithm. */ switch (k->wk_cipher->ic_cipher) { case IEEE80211_CIPHER_WEP: if (k->wk_keylen < 8) algo = R92C_CAM_ALGO_WEP40; else algo = R92C_CAM_ALGO_WEP104; break; case IEEE80211_CIPHER_TKIP: algo = R92C_CAM_ALGO_TKIP; break; case IEEE80211_CIPHER_AES_CCM: algo = R92C_CAM_ALGO_AES; break; default: device_printf(sc->sc_dev, "%s: unknown cipher %u\n", __func__, k->wk_cipher->ic_cipher); return (EINVAL); } RTWN_DPRINTF(sc, RTWN_DEBUG_KEY, "%s: keyix %u, keyid %u, algo %u/%u, flags %04X, len %u, " "macaddr %s\n", __func__, k->wk_keyix, keyid, k->wk_cipher->ic_cipher, algo, k->wk_flags, k->wk_keylen, ether_sprintf(k->wk_macaddr)); /* Clear high bits. */ rtwn_cam_write(sc, R92C_CAM_CTL6(k->wk_keyix), 0); rtwn_cam_write(sc, R92C_CAM_CTL7(k->wk_keyix), 0); /* Write key. */ for (i = 0; i < 4; i++) { error = rtwn_cam_write(sc, R92C_CAM_KEY(k->wk_keyix, i), le32dec(&k->wk_key[i * 4])); if (error != 0) goto fail; } /* Write CTL0 last since that will validate the CAM entry. */ error = rtwn_cam_write(sc, R92C_CAM_CTL1(k->wk_keyix), le32dec(&k->wk_macaddr[2])); if (error != 0) goto fail; error = rtwn_cam_write(sc, R92C_CAM_CTL0(k->wk_keyix), SM(R92C_CAM_ALGO, algo) | SM(R92C_CAM_KEYID, keyid) | SM(R92C_CAM_MACLO, le16dec(&k->wk_macaddr[0])) | R92C_CAM_VALID); if (error != 0) goto fail; return (0); fail: device_printf(sc->sc_dev, "%s fails, error %d\n", __func__, error); return (error); } static void rtwn_key_set_cb(struct rtwn_softc *sc, union sec_param *data) { const struct ieee80211_key *k = &data->key; (void) rtwn_key_set_cb0(sc, k); } int rtwn_init_static_keys(struct rtwn_softc *sc, struct rtwn_vap *rvp) { int i, error; if (sc->sc_hwcrypto != RTWN_CRYPTO_FULL) return (0); /* nothing to do */ for (i = 0; i < IEEE80211_WEP_NKID; i++) { const struct ieee80211_key *k = rvp->keys[i]; if (k != NULL) { error = rtwn_key_set_cb0(sc, k); if (error != 0) return (error); } } return (0); } static void rtwn_key_del_cb(struct rtwn_softc *sc, union sec_param *data) { struct ieee80211_key *k = &data->key; int i; RTWN_DPRINTF(sc, RTWN_DEBUG_KEY, "%s: keyix %u, flags %04X, macaddr %s\n", __func__, k->wk_keyix, k->wk_flags, ether_sprintf(k->wk_macaddr)); rtwn_cam_write(sc, R92C_CAM_CTL0(k->wk_keyix), 0); rtwn_cam_write(sc, R92C_CAM_CTL1(k->wk_keyix), 0); /* Clear key. */ for (i = 0; i < 4; i++) rtwn_cam_write(sc, R92C_CAM_KEY(k->wk_keyix, i), 0); clrbit(sc->keys_bmap, k->wk_keyix); } static int rtwn_process_key(struct ieee80211vap *vap, const struct ieee80211_key *k, int set) { struct rtwn_softc *sc = vap->iv_ic->ic_softc; if (k->wk_flags & IEEE80211_KEY_SWCRYPT) { /* Not for us. */ return (1); } if (&vap->iv_nw_keys[0] <= k && k < &vap->iv_nw_keys[IEEE80211_WEP_NKID]) { -#if __FreeBSD_version <= 1200008 - struct ieee80211_key *k1 = &vap->iv_nw_keys[k->wk_keyix]; - - if (sc->sc_hwcrypto != RTWN_CRYPTO_FULL) { - k1->wk_flags |= IEEE80211_KEY_SWCRYPT; - return (k->wk_cipher->ic_setkey(k1)); - } else { -#else if (sc->sc_hwcrypto == RTWN_CRYPTO_FULL) { -#endif struct rtwn_vap *rvp = RTWN_VAP(vap); RTWN_LOCK(sc); rvp->keys[k->wk_keyix] = (set ? k : NULL); if ((sc->sc_flags & RTWN_RUNNING) == 0) { if (!set) clrbit(sc->keys_bmap, k->wk_keyix); RTWN_UNLOCK(sc); return (1); } RTWN_UNLOCK(sc); } } return (!rtwn_cmd_sleepable(sc, k, sizeof(*k), set ? rtwn_key_set_cb : rtwn_key_del_cb)); } int rtwn_key_set(struct ieee80211vap *vap, const struct ieee80211_key *k) { return (rtwn_process_key(vap, k, 1)); } int rtwn_key_delete(struct ieee80211vap *vap, const struct ieee80211_key *k) { return (rtwn_process_key(vap, k, 0)); } diff --git a/sys/dev/rtwn/rtl8188e/r88e_rx.c b/sys/dev/rtwn/rtl8188e/r88e_rx.c index 16510839bd44..ec6174e3df00 100644 --- a/sys/dev/rtwn/rtl8188e/r88e_rx.c +++ b/sys/dev/rtwn/rtl8188e/r88e_rx.c @@ -1,249 +1,236 @@ /* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */ /*- * Copyright (c) 2010 Damien Bergamini * Copyright (c) 2014 Kevin Lo * Copyright (c) 2015-2016 Andriy Voskoboinyk * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include __FBSDID("$FreeBSD$"); #include "opt_wlan.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include int r88e_classify_intr(struct rtwn_softc *sc, void *buf, int len) { struct r92c_rx_stat *stat = buf; int report_sel = MS(le32toh(stat->rxdw3), R88E_RXDW3_RPT); switch (report_sel) { case R88E_RXDW3_RPT_RX: return (RTWN_RX_DATA); case R88E_RXDW3_RPT_TX1: /* per-packet Tx report */ case R88E_RXDW3_RPT_TX2: /* periodical Tx report */ return (RTWN_RX_TX_REPORT); case R88E_RXDW3_RPT_HIS: return (RTWN_RX_OTHER); default: /* shut up the compiler */ return (RTWN_RX_DATA); } } void r88e_ratectl_tx_complete(struct rtwn_softc *sc, uint8_t *buf, int len) { -#if __FreeBSD_version >= 1200012 struct ieee80211_ratectl_tx_status txs; -#endif struct r88e_tx_rpt_ccx *rpt; struct ieee80211_node *ni; uint8_t macid; int ntries; /* Skip Rx descriptor. */ buf += sizeof(struct r92c_rx_stat); len -= sizeof(struct r92c_rx_stat); rpt = (struct r88e_tx_rpt_ccx *)buf; if (len != sizeof(*rpt)) { RTWN_DPRINTF(sc, RTWN_DEBUG_INTR, "%s: wrong report size (%d, must be %zu)\n", __func__, len, sizeof(*rpt)); return; } RTWN_DPRINTF(sc, RTWN_DEBUG_INTR, "%s: ccx report dump: 0: %02X, 1: %02X, 2: %02X, queue time: " "low %02X, high %02X, final ridx: %02X, 6: %02X, 7: %02X\n", __func__, rpt->rptb0, rpt->rptb1, rpt->rptb2, rpt->queue_time_low, rpt->queue_time_high, rpt->final_rate, rpt->rptb6, rpt->rptb7); macid = MS(rpt->rptb1, R88E_RPTB1_MACID); if (macid > sc->macid_limit) { device_printf(sc->sc_dev, "macid %u is too big; increase MACID_MAX limit\n", macid); return; } ntries = MS(rpt->rptb2, R88E_RPTB2_RETRY_CNT); ni = sc->node_list[macid]; if (ni != NULL) { RTWN_DPRINTF(sc, RTWN_DEBUG_INTR, "%s: frame for macid %u was" "%s sent (%d retries)\n", __func__, macid, (rpt->rptb1 & R88E_RPTB1_PKT_OK) ? "" : " not", ntries); -#if __FreeBSD_version >= 1200012 txs.flags = IEEE80211_RATECTL_STATUS_LONG_RETRY | IEEE80211_RATECTL_STATUS_FINAL_RATE; txs.long_retries = ntries; if (rpt->final_rate > RTWN_RIDX_OFDM54) { /* MCS */ txs.final_rate = rpt->final_rate - RTWN_RIDX_HT_MCS_SHIFT; txs.final_rate |= IEEE80211_RATE_MCS; } else txs.final_rate = ridx2rate[rpt->final_rate]; if (rpt->rptb1 & R88E_RPTB1_PKT_OK) txs.status = IEEE80211_RATECTL_TX_SUCCESS; else if (rpt->rptb2 & R88E_RPTB2_RETRY_OVER) txs.status = IEEE80211_RATECTL_TX_FAIL_LONG; else if (rpt->rptb2 & R88E_RPTB2_LIFE_EXPIRE) txs.status = IEEE80211_RATECTL_TX_FAIL_EXPIRED; else txs.status = IEEE80211_RATECTL_TX_FAIL_UNSPECIFIED; ieee80211_ratectl_tx_complete(ni, &txs); -#else - struct ieee80211vap *vap = ni->ni_vap; - if (rpt->rptb1 & R88E_RPTB1_PKT_OK) { - ieee80211_ratectl_tx_complete(vap, ni, - IEEE80211_RATECTL_TX_SUCCESS, &ntries, NULL); - } else { - ieee80211_ratectl_tx_complete(vap, ni, - IEEE80211_RATECTL_TX_FAILURE, &ntries, NULL); - } -#endif } else { RTWN_DPRINTF(sc, RTWN_DEBUG_INTR, "%s: macid %u, ni is NULL\n", __func__, macid); } } void r88e_handle_c2h_report(struct rtwn_softc *sc, uint8_t *buf, int len) { /* Skip Rx descriptor. */ buf += sizeof(struct r92c_rx_stat); len -= sizeof(struct r92c_rx_stat); if (len != R88E_INTR_MSG_LEN) { RTWN_DPRINTF(sc, RTWN_DEBUG_INTR, "%s: wrong interrupt message size (%d, must be %d)\n", __func__, len, R88E_INTR_MSG_LEN); return; } /* XXX TODO */ } int8_t r88e_get_rssi_cck(struct rtwn_softc *sc, void *physt) { struct r88e_rx_phystat *phy = (struct r88e_rx_phystat *)physt; int8_t lna_idx, vga_idx, rssi; lna_idx = (phy->agc_rpt & 0xe0) >> 5; vga_idx = (phy->agc_rpt & 0x1f); rssi = 6 - 2 * vga_idx; switch (lna_idx) { case 7: if (vga_idx > 27) rssi = -100 + 6; else rssi += -100 + 2 * 27; break; case 6: rssi += -48 + 2 * 2; break; case 5: rssi += -42 + 2 * 7; break; case 4: rssi += -36 + 2 * 7; break; case 3: rssi += -24 + 2 * 7; break; case 2: rssi += -6 + 2 * 5; if (sc->sc_flags & RTWN_FLAG_CCK_HIPWR) rssi -= 6; break; case 1: rssi += 8; break; case 0: rssi += 14; break; } return (rssi); } int8_t r88e_get_rssi_ofdm(struct rtwn_softc *sc, void *physt) { struct r88e_rx_phystat *phy = (struct r88e_rx_phystat *)physt; int rssi; /* Get average RSSI. */ rssi = ((phy->sig_qual >> 1) & 0x7f) - 110; return (rssi); } void r88e_get_rx_stats(struct rtwn_softc *sc, struct ieee80211_rx_stats *rxs, const void *desc, const void *physt_ptr) { const struct r88e_rx_phystat *physt = physt_ptr; r92c_get_rx_stats(sc, rxs, desc, physt_ptr); if (!sc->sc_ht40) { /* XXX center channel */ rxs->r_flags |= IEEE80211_R_IEEE | IEEE80211_R_FREQ; rxs->r_flags |= IEEE80211_R_BAND; rxs->c_ieee = physt->chan; rxs->c_freq = ieee80211_ieee2mhz(rxs->c_ieee, IEEE80211_CHAN_2GHZ); rxs->c_band = IEEE80211_CHAN_2GHZ; } } diff --git a/sys/dev/rtwn/rtl8192c/r92c_fw.c b/sys/dev/rtwn/rtl8192c/r92c_fw.c index 7ad6d7d2dfe6..be284ff91c61 100644 --- a/sys/dev/rtwn/rtl8192c/r92c_fw.c +++ b/sys/dev/rtwn/rtl8192c/r92c_fw.c @@ -1,519 +1,506 @@ /* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */ /*- * Copyright (c) 2010 Damien Bergamini * Copyright (c) 2014 Kevin Lo * Copyright (c) 2015-2016 Andriy Voskoboinyk * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include __FBSDID("$FreeBSD$"); #include "opt_wlan.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifndef RTWN_WITHOUT_UCODE static int r92c_fw_cmd(struct rtwn_softc *sc, uint8_t id, const void *buf, int len) { struct r92c_fw_cmd cmd; int ntries, error; KASSERT(len <= sizeof(cmd.msg), ("%s: firmware command too long (%d > %zu)\n", __func__, len, sizeof(cmd.msg))); if (!(sc->sc_flags & RTWN_FW_LOADED)) { RTWN_DPRINTF(sc, RTWN_DEBUG_FIRMWARE, "%s: firmware " "was not loaded; command (id %u) will be discarded\n", __func__, id); return (0); } /* Wait for current FW box to be empty. */ for (ntries = 0; ntries < 100; ntries++) { if (!(rtwn_read_1(sc, R92C_HMETFR) & (1 << sc->fwcur))) break; rtwn_delay(sc, 2000); } if (ntries == 100) { device_printf(sc->sc_dev, "could not send firmware command\n"); return (ETIMEDOUT); } memset(&cmd, 0, sizeof(cmd)); cmd.id = id; if (len > 3) { /* Ext command: [id : byte2 : byte3 : byte4 : byte0 : byte1] */ cmd.id |= R92C_CMD_FLAG_EXT; memcpy(cmd.msg, (const uint8_t *)buf + 2, len - 2); memcpy(cmd.msg + 3, buf, 2); } else memcpy(cmd.msg, buf, len); /* Write the first word last since that will trigger the FW. */ if (len > 3) { error = rtwn_write_2(sc, R92C_HMEBOX_EXT(sc->fwcur), *(uint16_t *)((uint8_t *)&cmd + 4)); if (error != 0) return (error); } error = rtwn_write_4(sc, R92C_HMEBOX(sc->fwcur), *(uint32_t *)&cmd); if (error != 0) return (error); sc->fwcur = (sc->fwcur + 1) % R92C_H2C_NBOX; return (0); } void r92c_fw_reset(struct rtwn_softc *sc, int reason) { int ntries; if (reason == RTWN_FW_RESET_CHECKSUM) return; /* Tell 8051 to reset itself. */ rtwn_write_1(sc, R92C_HMETFR + 3, 0x20); /* Wait until 8051 resets by itself. */ for (ntries = 0; ntries < 100; ntries++) { if ((rtwn_read_2(sc, R92C_SYS_FUNC_EN) & R92C_SYS_FUNC_EN_CPUEN) == 0) return; rtwn_delay(sc, 50); } /* Force 8051 reset. */ rtwn_setbits_1_shift(sc, R92C_SYS_FUNC_EN, R92C_SYS_FUNC_EN_CPUEN, 0, 1); } void r92c_fw_download_enable(struct rtwn_softc *sc, int enable) { if (enable) { /* 8051 enable. */ rtwn_setbits_1_shift(sc, R92C_SYS_FUNC_EN, 0, R92C_SYS_FUNC_EN_CPUEN, 1); /* MCU firmware download enable. */ rtwn_setbits_1(sc, R92C_MCUFWDL, 0, R92C_MCUFWDL_EN); /* 8051 reset. */ rtwn_setbits_1_shift(sc, R92C_MCUFWDL, R92C_MCUFWDL_ROM_DLEN, 0, 2); } else { /* MCU download disable. */ rtwn_setbits_1(sc, R92C_MCUFWDL, R92C_MCUFWDL_EN, 0); /* Reserved for f/w extension. */ rtwn_write_1(sc, R92C_MCUFWDL + 1, 0); } } #endif /* * Initialize firmware rate adaptation. */ #ifndef RTWN_WITHOUT_UCODE static int r92c_send_ra_cmd(struct rtwn_softc *sc, int macid, uint32_t rates, int maxrate) { struct r92c_fw_cmd_macid_cfg cmd; uint8_t mode; int error = 0; /* XXX should be called directly from iv_newstate() for MACID_BC */ /* XXX joinbss, not send_ra_cmd() */ #ifdef RTWN_TODO /* NB: group addressed frames are done at 11bg rates for now */ if (ic->ic_curmode == IEEE80211_MODE_11B) mode = R92C_RAID_11B; else mode = R92C_RAID_11BG; /* XXX misleading 'mode' value here for unicast frames */ RTWN_DPRINTF(sc, RTWN_DEBUG_RA, "%s: mode 0x%x, rates 0x%08x, basicrates 0x%08x\n", __func__, mode, rates, basicrates); /* Set rates mask for group addressed frames. */ cmd.macid = RTWN_MACID_BC | R92C_CMD_MACID_VALID; cmd.mask = htole32(mode << 28 | basicrates); error = rtwn_fw_cmd(sc, R92C_CMD_MACID_CONFIG, &cmd, sizeof(cmd)); if (error != 0) { device_printf(sc->sc_dev, "could not set RA mask for broadcast station\n"); return (error); } #endif /* Set rates mask for unicast frames. */ if (maxrate >= RTWN_RIDX_HT_MCS(0)) mode = R92C_RAID_11GN; else if (maxrate >= RTWN_RIDX_OFDM6) mode = R92C_RAID_11BG; else mode = R92C_RAID_11B; cmd.macid = macid | R92C_CMD_MACID_VALID; cmd.mask = htole32(mode << 28 | rates); error = r92c_fw_cmd(sc, R92C_CMD_MACID_CONFIG, &cmd, sizeof(cmd)); if (error != 0) { device_printf(sc->sc_dev, "%s: could not set RA mask for %d station\n", __func__, macid); return (error); } return (0); } #endif static void r92c_init_ra(struct rtwn_softc *sc, int macid) { struct ieee80211_htrateset *rs_ht; struct ieee80211_node *ni; uint32_t rates; int maxrate; RTWN_NT_LOCK(sc); if (sc->node_list[macid] == NULL) { RTWN_DPRINTF(sc, RTWN_DEBUG_RA, "%s: macid %d, ni is NULL\n", __func__, macid); RTWN_NT_UNLOCK(sc); return; } ni = ieee80211_ref_node(sc->node_list[macid]); if (ni->ni_flags & IEEE80211_NODE_HT) rs_ht = &ni->ni_htrates; else rs_ht = NULL; /* XXX MACID_BC */ rtwn_get_rates(sc, &ni->ni_rates, rs_ht, &rates, &maxrate, 0); RTWN_NT_UNLOCK(sc); #ifndef RTWN_WITHOUT_UCODE if (sc->sc_ratectl == RTWN_RATECTL_FW) { r92c_send_ra_cmd(sc, macid, rates, maxrate); } #endif rtwn_write_1(sc, R92C_INIDATA_RATE_SEL(macid), maxrate); ieee80211_free_node(ni); } void r92c_joinbss_rpt(struct rtwn_softc *sc, int macid) { #ifndef RTWN_WITHOUT_UCODE struct r92c_softc *rs = sc->sc_priv; struct ieee80211vap *vap; struct r92c_fw_cmd_joinbss_rpt cmd; if (sc->vaps[0] == NULL) /* XXX fix */ goto end; vap = &sc->vaps[0]->vap; if ((vap->iv_state == IEEE80211_S_RUN) ^ !(rs->rs_flags & R92C_FLAG_ASSOCIATED)) goto end; if (rs->rs_flags & R92C_FLAG_ASSOCIATED) { cmd.mstatus = R92C_MSTATUS_DISASSOC; rs->rs_flags &= ~R92C_FLAG_ASSOCIATED; } else { cmd.mstatus = R92C_MSTATUS_ASSOC; rs->rs_flags |= R92C_FLAG_ASSOCIATED; } if (r92c_fw_cmd(sc, R92C_CMD_JOINBSS_RPT, &cmd, sizeof(cmd)) != 0) { device_printf(sc->sc_dev, "%s: cannot change media status!\n", __func__); } end: #endif /* TODO: init rates for RTWN_MACID_BC. */ if (macid & RTWN_MACID_VALID) r92c_init_ra(sc, macid & ~RTWN_MACID_VALID); } #ifndef RTWN_WITHOUT_UCODE int r92c_set_rsvd_page(struct rtwn_softc *sc, int probe_resp, int null, int qos_null) { struct r92c_fw_cmd_rsvdpage rsvd; rsvd.probe_resp = probe_resp; rsvd.ps_poll = 0; rsvd.null_data = null; return (r92c_fw_cmd(sc, R92C_CMD_RSVD_PAGE, &rsvd, sizeof(rsvd))); } int r92c_set_pwrmode(struct rtwn_softc *sc, struct ieee80211vap *vap, int off) { struct r92c_fw_cmd_pwrmode mode; int error; /* XXX dm_RF_saving */ if (off && vap->iv_state == IEEE80211_S_RUN && (vap->iv_flags & IEEE80211_F_PMGTON)) mode.mode = R92C_PWRMODE_MIN; else mode.mode = R92C_PWRMODE_CAM; mode.smart_ps = R92C_PWRMODE_SMARTPS_NULLDATA; mode.bcn_pass = 1; /* XXX */ error = r92c_fw_cmd(sc, R92C_CMD_SET_PWRMODE, &mode, sizeof(mode)); if (error != 0) { device_printf(sc->sc_dev, "%s: CMD_SET_PWRMODE was not sent, error %d\n", __func__, error); } return (error); } void r92c_set_rssi(struct rtwn_softc *sc) { struct ieee80211_node *ni; struct rtwn_node *rn; struct r92c_fw_cmd_rssi cmd; int i; cmd.reserved = 0; RTWN_NT_LOCK(sc); for (i = 0; i < sc->macid_limit; i++) { /* XXX optimize? */ ni = sc->node_list[i]; if (ni == NULL) continue; rn = RTWN_NODE(ni); cmd.macid = i; cmd.pwdb = rn->avg_pwdb; RTWN_DPRINTF(sc, RTWN_DEBUG_RSSI, "%s: sending RSSI command (macid %d, rssi %d)\n", __func__, i, rn->avg_pwdb); RTWN_NT_UNLOCK(sc); r92c_fw_cmd(sc, R92C_CMD_RSSI_SETTING, &cmd, sizeof(cmd)); RTWN_NT_LOCK(sc); } RTWN_NT_UNLOCK(sc); } static void r92c_ratectl_tx_complete(struct rtwn_softc *sc, uint8_t *buf, int len) { -#if __FreeBSD_version >= 1200012 struct ieee80211_ratectl_tx_status txs; -#endif struct r92c_c2h_tx_rpt *rpt; struct ieee80211_node *ni; uint8_t macid; int ntries; if (sc->sc_ratectl != RTWN_RATECTL_NET80211) { /* shouldn't happen */ device_printf(sc->sc_dev, "%s called while ratectl = %d!\n", __func__, sc->sc_ratectl); return; } rpt = (struct r92c_c2h_tx_rpt *)buf; if (len != sizeof(*rpt)) { device_printf(sc->sc_dev, "%s: wrong report size (%d, must be %zu)\n", __func__, len, sizeof(*rpt)); return; } RTWN_DPRINTF(sc, RTWN_DEBUG_INTR, "%s: ccx report dump: 0: %02X, 1: %02X, queue time: " "low %02X, high %02X, 4: %02X, 5: %02X, 6: %02X, 7: %02X\n", __func__, rpt->rptb0, rpt->rptb1, rpt->queue_time_low, rpt->queue_time_high, rpt->rptb4, rpt->rptb5, rpt->rptb6, rpt->rptb7); macid = MS(rpt->rptb5, R92C_RPTB5_MACID); if (macid > sc->macid_limit) { device_printf(sc->sc_dev, "macid %u is too big; increase MACID_MAX limit\n", macid); return; } ntries = MS(rpt->rptb0, R92C_RPTB0_RETRY_CNT); RTWN_NT_LOCK(sc); ni = sc->node_list[macid]; if (ni != NULL) { RTWN_DPRINTF(sc, RTWN_DEBUG_INTR, "%s: frame for macid %u was" "%s sent (%d retries)\n", __func__, macid, (rpt->rptb7 & R92C_RPTB7_PKT_OK) ? "" : " not", ntries); -#if __FreeBSD_version >= 1200012 txs.flags = IEEE80211_RATECTL_STATUS_LONG_RETRY; txs.long_retries = ntries; if (rpt->rptb7 & R92C_RPTB7_PKT_OK) txs.status = IEEE80211_RATECTL_TX_SUCCESS; else if (rpt->rptb6 & R92C_RPTB6_RETRY_OVER) txs.status = IEEE80211_RATECTL_TX_FAIL_LONG; /* XXX */ else if (rpt->rptb6 & R92C_RPTB6_LIFE_EXPIRE) txs.status = IEEE80211_RATECTL_TX_FAIL_EXPIRED; else txs.status = IEEE80211_RATECTL_TX_FAIL_UNSPECIFIED; ieee80211_ratectl_tx_complete(ni, &txs); -#else - struct ieee80211vap *vap = ni->ni_vap; - if (rpt->rptb7 & R92C_RPTB7_PKT_OK) { - ieee80211_ratectl_tx_complete(vap, ni, - IEEE80211_RATECTL_TX_SUCCESS, &ntries, NULL); - } else { - ieee80211_ratectl_tx_complete(vap, ni, - IEEE80211_RATECTL_TX_FAILURE, &ntries, NULL); - } -#endif } else { RTWN_DPRINTF(sc, RTWN_DEBUG_INTR, "%s: macid %u, ni is NULL\n", __func__, macid); } RTWN_NT_UNLOCK(sc); #ifdef IEEE80211_SUPPORT_SUPERG if (sc->sc_tx_n_active > 0 && --sc->sc_tx_n_active <= 1) rtwn_cmd_sleepable(sc, NULL, 0, rtwn_ff_flush_all); #endif } static void r92c_handle_c2h_task(struct rtwn_softc *sc, union sec_param *data) { const uint16_t off = R92C_C2H_EVT_MSG + sizeof(struct r92c_c2h_evt); struct r92c_softc *rs = sc->sc_priv; uint16_t buf[R92C_C2H_MSG_MAX_LEN / 2 + 1]; uint8_t id, len, status; int i; /* Do not reschedule the task if device is not running. */ if (!(sc->sc_flags & RTWN_RUNNING)) return; /* Read current status. */ status = rtwn_read_1(sc, R92C_C2H_EVT_CLEAR); if (status == R92C_C2H_EVT_HOST_CLOSE) goto end; /* nothing to do */ else if (status == R92C_C2H_EVT_FW_CLOSE) { len = rtwn_read_1(sc, R92C_C2H_EVT_MSG); id = MS(len, R92C_C2H_EVTB0_ID); len = MS(len, R92C_C2H_EVTB0_LEN); memset(buf, 0, sizeof(buf)); /* Try to optimize event reads. */ for (i = 0; i < len; i += 2) buf[i / 2] = rtwn_read_2(sc, off + i); KASSERT(i < sizeof(buf), ("%s: buffer overrun (%d >= %zu)!", __func__, i, sizeof(buf))); switch (id) { case R92C_C2H_EVT_TX_REPORT: r92c_ratectl_tx_complete(sc, (uint8_t *)buf, len); break; default: device_printf(sc->sc_dev, "%s: C2H report %u (len %u) was not handled\n", __func__, id, len); break; } } /* Prepare for next event. */ rtwn_write_1(sc, R92C_C2H_EVT_CLEAR, R92C_C2H_EVT_HOST_CLOSE); end: /* Adjust timeout for next call. */ if (rs->rs_c2h_pending != 0) { rs->rs_c2h_pending = 0; rs->rs_c2h_paused = 0; } else rs->rs_c2h_paused++; if (rs->rs_c2h_paused > R92C_TX_PAUSED_THRESHOLD) rs->rs_c2h_timeout = hz; else rs->rs_c2h_timeout = MAX(hz / 100, 1); /* Reschedule the task. */ callout_reset(&rs->rs_c2h_report, rs->rs_c2h_timeout, r92c_handle_c2h_report, sc); } void r92c_handle_c2h_report(void *arg) { struct rtwn_softc *sc = arg; rtwn_cmd_sleepable(sc, NULL, 0, r92c_handle_c2h_task); } #endif /* RTWN_WITHOUT_UCODE */ diff --git a/sys/dev/rtwn/rtl8812a/r12a_rx.c b/sys/dev/rtwn/rtl8812a/r12a_rx.c index 98e0cabdff7c..ebe299214e98 100644 --- a/sys/dev/rtwn/rtl8812a/r12a_rx.c +++ b/sys/dev/rtwn/rtl8812a/r12a_rx.c @@ -1,330 +1,317 @@ /*- * Copyright (c) 2016 Andriy Voskoboinyk * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include "opt_wlan.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifndef RTWN_WITHOUT_UCODE void r12a_ratectl_tx_complete(struct rtwn_softc *sc, uint8_t *buf, int len) { -#if __FreeBSD_version >= 1200012 struct ieee80211_ratectl_tx_status txs; -#endif struct r12a_c2h_tx_rpt *rpt; struct ieee80211_node *ni; int ntries; /* Skip Rx descriptor / report id / sequence fields. */ buf += sizeof(struct r92c_rx_stat) + 2; len -= sizeof(struct r92c_rx_stat) + 2; rpt = (struct r12a_c2h_tx_rpt *)buf; if (len != sizeof(*rpt)) { device_printf(sc->sc_dev, "%s: wrong report size (%d, must be %zu)\n", __func__, len, sizeof(*rpt)); return; } RTWN_DPRINTF(sc, RTWN_DEBUG_INTR, "%s: ccx report dump: 0: %02X, id: %02X, 2: %02X, queue time: " "low %02X, high %02X, final ridx: %02X, rsvd: %04X\n", __func__, rpt->txrptb0, rpt->macid, rpt->txrptb2, rpt->queue_time_low, rpt->queue_time_high, rpt->final_rate, rpt->reserved); if (rpt->macid > sc->macid_limit) { device_printf(sc->sc_dev, "macid %u is too big; increase MACID_MAX limit\n", rpt->macid); return; } ntries = MS(rpt->txrptb2, R12A_TXRPTB2_RETRY_CNT); ni = sc->node_list[rpt->macid]; if (ni != NULL) { RTWN_DPRINTF(sc, RTWN_DEBUG_INTR, "%s: frame for macid %u was" "%s sent (%d retries)\n", __func__, rpt->macid, (rpt->txrptb0 & (R12A_TXRPTB0_RETRY_OVER | R12A_TXRPTB0_LIFE_EXPIRE)) ? " not" : "", ntries); -#if __FreeBSD_version >= 1200012 txs.flags = IEEE80211_RATECTL_STATUS_LONG_RETRY | IEEE80211_RATECTL_STATUS_FINAL_RATE; txs.long_retries = ntries; if (rpt->final_rate > RTWN_RIDX_OFDM54) { /* MCS */ txs.final_rate = rpt->final_rate - RTWN_RIDX_HT_MCS_SHIFT; txs.final_rate |= IEEE80211_RATE_MCS; } else txs.final_rate = ridx2rate[rpt->final_rate]; if (rpt->txrptb0 & R12A_TXRPTB0_RETRY_OVER) txs.status = IEEE80211_RATECTL_TX_FAIL_LONG; else if (rpt->txrptb0 & R12A_TXRPTB0_LIFE_EXPIRE) txs.status = IEEE80211_RATECTL_TX_FAIL_EXPIRED; else txs.status = IEEE80211_RATECTL_TX_SUCCESS; ieee80211_ratectl_tx_complete(ni, &txs); -#else - struct ieee80211vap *vap = ni->ni_vap; - if (rpt->txrptb0 & R12A_TXRPTB0_RETRY_OVER) { - ieee80211_ratectl_tx_complete(vap, ni, - IEEE80211_RATECTL_TX_FAILURE, &ntries, NULL); - } else { - ieee80211_ratectl_tx_complete(vap, ni, - IEEE80211_RATECTL_TX_SUCCESS, &ntries, NULL); - } -#endif } else { RTWN_DPRINTF(sc, RTWN_DEBUG_INTR, "%s: macid %u, ni is NULL\n", __func__, rpt->macid); } } void r12a_handle_c2h_report(struct rtwn_softc *sc, uint8_t *buf, int len) { struct r12a_softc *rs = sc->sc_priv; /* Skip Rx descriptor. */ buf += sizeof(struct r92c_rx_stat); len -= sizeof(struct r92c_rx_stat); if (len < 2) { device_printf(sc->sc_dev, "C2H report too short (len %d)\n", len); return; } len -= 2; switch (buf[0]) { /* command id */ case R12A_C2H_TX_REPORT: /* NOTREACHED */ KASSERT(0, ("use handle_tx_report() instead of %s\n", __func__)); break; case R12A_C2H_IQK_FINISHED: RTWN_DPRINTF(sc, RTWN_DEBUG_CALIB, "FW IQ calibration finished\n"); rs->rs_flags &= ~R12A_IQK_RUNNING; break; default: device_printf(sc->sc_dev, "%s: C2H report %u was not handled\n", __func__, buf[0]); } } #else void r12a_ratectl_tx_complete(struct rtwn_softc *sc, uint8_t *buf, int len) { /* Should not happen. */ device_printf(sc->sc_dev, "%s: called\n", __func__); } void r12a_handle_c2h_report(struct rtwn_softc *sc, uint8_t *buf, int len) { /* Should not happen. */ device_printf(sc->sc_dev, "%s: called\n", __func__); } #endif int r12a_check_frame_checksum(struct rtwn_softc *sc, struct mbuf *m) { struct r12a_softc *rs = sc->sc_priv; struct r92c_rx_stat *stat; uint32_t rxdw1; stat = mtod(m, struct r92c_rx_stat *); rxdw1 = le32toh(stat->rxdw1); if (rxdw1 & R12A_RXDW1_CKSUM) { RTWN_DPRINTF(sc, RTWN_DEBUG_RECV, "%s: %s/%s checksum is %s\n", __func__, (rxdw1 & R12A_RXDW1_UDP) ? "UDP" : "TCP", (rxdw1 & R12A_RXDW1_IPV6) ? "IPv6" : "IP", (rxdw1 & R12A_RXDW1_CKSUM_ERR) ? "invalid" : "valid"); if (rxdw1 & R12A_RXDW1_CKSUM_ERR) return (-1); if ((rxdw1 & R12A_RXDW1_IPV6) ? (rs->rs_flags & R12A_RXCKSUM6_EN) : (rs->rs_flags & R12A_RXCKSUM_EN)) { m->m_pkthdr.csum_flags = CSUM_IP_CHECKED | CSUM_IP_VALID | CSUM_DATA_VALID | CSUM_PSEUDO_HDR; m->m_pkthdr.csum_data = 0xffff; } } return (0); } uint8_t r12a_rx_radiotap_flags(const void *buf) { const struct r92c_rx_stat *stat = buf; uint8_t flags, rate; if (!(stat->rxdw4 & htole32(R12A_RXDW4_SPLCP))) return (0); rate = MS(le32toh(stat->rxdw3), R12A_RXDW3_RATE); if (RTWN_RATE_IS_CCK(rate)) flags = IEEE80211_RADIOTAP_F_SHORTPRE; else flags = IEEE80211_RADIOTAP_F_SHORTGI; return (flags); } void r12a_get_rx_stats(struct rtwn_softc *sc, struct ieee80211_rx_stats *rxs, const void *desc, const void *physt_ptr) { const struct r92c_rx_stat *stat = desc; const struct r12a_rx_phystat *physt = physt_ptr; uint32_t rxdw0, rxdw1, rxdw3, rxdw4; uint8_t rate; rxdw0 = le32toh(stat->rxdw0); rxdw1 = le32toh(stat->rxdw1); rxdw3 = le32toh(stat->rxdw3); rxdw4 = le32toh(stat->rxdw4); rate = MS(rxdw3, R12A_RXDW3_RATE); /* TODO: STBC */ if (rxdw4 & R12A_RXDW4_LDPC) rxs->c_pktflags |= IEEE80211_RX_F_LDPC; if (rxdw1 & R12A_RXDW1_AMPDU) { if (rxdw0 & R92C_RXDW0_PHYST) rxs->c_pktflags |= IEEE80211_RX_F_AMPDU; else rxs->c_pktflags |= IEEE80211_RX_F_AMPDU_MORE; } if ((rxdw4 & R12A_RXDW4_SPLCP) && rate >= RTWN_RIDX_HT_MCS(0)) rxs->c_pktflags |= IEEE80211_RX_F_SHORTGI; switch (MS(rxdw4, R12A_RXDW4_BW)) { case R12A_RXDW4_BW20: rxs->c_width = IEEE80211_RX_FW_20MHZ; break; case R12A_RXDW4_BW40: rxs->c_width = IEEE80211_RX_FW_40MHZ; break; case R12A_RXDW4_BW80: rxs->c_width = IEEE80211_RX_FW_80MHZ; break; default: break; } if (RTWN_RATE_IS_CCK(rate)) rxs->c_phytype = IEEE80211_RX_FP_11B; else { int is5ghz; /* XXX magic */ /* XXX check with RTL8812AU */ is5ghz = (physt->cfosho[2] != 0x01); if (rate < RTWN_RIDX_HT_MCS(0)) { if (is5ghz) rxs->c_phytype = IEEE80211_RX_FP_11A; else rxs->c_phytype = IEEE80211_RX_FP_11G; } else { if (is5ghz) rxs->c_phytype = IEEE80211_RX_FP_11NA; else rxs->c_phytype = IEEE80211_RX_FP_11NG; } } /* Map HW rate index to 802.11 rate. */ if (rate < RTWN_RIDX_HT_MCS(0)) { rxs->c_rate = ridx2rate[rate]; if (RTWN_RATE_IS_CCK(rate)) rxs->c_pktflags |= IEEE80211_RX_F_CCK; else rxs->c_pktflags |= IEEE80211_RX_F_OFDM; } else { /* MCS0~15. */ /* TODO: VHT rates */ rxs->c_rate = IEEE80211_RATE_MCS | (rate - RTWN_RIDX_HT_MCS_SHIFT); rxs->c_pktflags |= IEEE80211_RX_F_HT; } /* * XXX always zero for RTL8821AU * (vendor driver does not check this field) */ #if 0 rxs->r_flags |= IEEE80211_R_IEEE | IEEE80211_R_FREQ; rxs->r_flags |= IEEE80211_R_BAND; rxs->c_ieee = MS(le16toh(physt->phyw1), R12A_PHYW1_CHAN); rxs->c_freq = ieee80211_ieee2mhz(rxs->c_ieee, (rxs->c_ieee < 36) ? IEEE80211_CHAN_2GHZ : IEEE80211_CHAN_5GHZ); rxs->c_band = (rxs->c_ieee < 36) ? IEEE80211_CHAN_2GHZ : IEEE80211_CHAN_5GHZ; #endif }