rtwn: export more stats to net80211
Setup more ieee80211_rx_stats fields for received frames: - pktflags: * IEEE80211_RX_F_FAIL_FCSCRC; * IEEE80211_RX_F_AMPDU; * IEEE80211_RX_F_AMPDU_MORE; * IEEE80211_RX_F_SHORTGI; - rate flags (CCK, OFDM, HT); - width; - phytype; - rate; - rx_tsf; - rssi; - nf; - ieee, freq (RTL8188EU only, when ht40 support is disabled). Tested with: - RTL8188CE, RTL8188EU, RTL8821AU (STA / AP modes, i386) - (by kevlo) RTL8188EU and RTL8812AU (amd64) Reviewed by: adrian (previous version), kevlo Differential Revision: https://reviews.freebsd.org/D9021
This commit is contained in:
parent
fdb9150ea4
commit
09606165a0
@ -1999,6 +1999,7 @@ rtwn_stop(struct rtwn_softc *sc)
|
||||
sc->fwver = 0;
|
||||
sc->thcal_temp = 0;
|
||||
sc->cur_bcnq_id = RTWN_VAP_ID_INVALID;
|
||||
bzero(&sc->last_physt, sizeof(sc->last_physt));
|
||||
|
||||
#ifdef D4054
|
||||
ieee80211_tx_watchdog_stop(&sc->sc_ic);
|
||||
|
@ -117,18 +117,19 @@ rtwn_set_basicrates(struct rtwn_softc *sc, uint32_t rates)
|
||||
}
|
||||
|
||||
static void
|
||||
rtwn_update_avgrssi(struct rtwn_softc *sc, struct rtwn_node *un, int rate)
|
||||
rtwn_update_avgrssi(struct rtwn_softc *sc, struct rtwn_node *un, int8_t rssi,
|
||||
int is_cck)
|
||||
{
|
||||
int pwdb;
|
||||
|
||||
/* Convert antenna signal to percentage. */
|
||||
if (un->last_rssi <= -100 || un->last_rssi >= 20)
|
||||
if (rssi <= -100 || rssi >= 20)
|
||||
pwdb = 0;
|
||||
else if (un->last_rssi >= 0)
|
||||
else if (rssi >= 0)
|
||||
pwdb = 100;
|
||||
else
|
||||
pwdb = 100 + un->last_rssi;
|
||||
if (RTWN_RATE_IS_CCK(rate)) {
|
||||
pwdb = 100 + rssi;
|
||||
if (is_cck) {
|
||||
/* CCK gain is smaller than OFDM/MCS gain. */
|
||||
pwdb += 6;
|
||||
if (pwdb > 100)
|
||||
@ -155,11 +156,11 @@ rtwn_update_avgrssi(struct rtwn_softc *sc, struct rtwn_node *un, int rate)
|
||||
}
|
||||
|
||||
static int8_t
|
||||
rtwn_get_rssi(struct rtwn_softc *sc, int rate, void *physt)
|
||||
rtwn_get_rssi(struct rtwn_softc *sc, void *physt, int is_cck)
|
||||
{
|
||||
int8_t rssi;
|
||||
|
||||
if (RTWN_RATE_IS_CCK(rate))
|
||||
if (is_cck)
|
||||
rssi = rtwn_get_rssi_cck(sc, physt);
|
||||
else /* OFDM/HT. */
|
||||
rssi = rtwn_get_rssi_ofdm(sc, physt);
|
||||
@ -188,81 +189,133 @@ rtwn_get_tsf(struct rtwn_softc *sc, uint64_t *buf, int id)
|
||||
*buf += rtwn_get_tsf_low(sc, id);
|
||||
}
|
||||
|
||||
static uint64_t
|
||||
rtwn_extend_rx_tsf(struct rtwn_softc *sc, const struct r92c_rx_stat *stat)
|
||||
{
|
||||
uint64_t tsft;
|
||||
uint32_t rxdw3, tsfl, tsfl_curr;
|
||||
int id;
|
||||
|
||||
rxdw3 = le32toh(stat->rxdw3);
|
||||
tsfl = le32toh(stat->tsf_low);
|
||||
id = MS(rxdw3, R92C_RXDW3_BSSID_FIT);
|
||||
|
||||
switch (id) {
|
||||
case 1:
|
||||
case 2:
|
||||
id >>= 1;
|
||||
tsfl_curr = rtwn_get_tsf_low(sc, id);
|
||||
break;
|
||||
default:
|
||||
{
|
||||
uint32_t tsfl0, tsfl1;
|
||||
|
||||
tsfl0 = rtwn_get_tsf_low(sc, 0);
|
||||
tsfl1 = rtwn_get_tsf_low(sc, 1);
|
||||
|
||||
if (abs(tsfl0 - tsfl) < abs(tsfl1 - tsfl)) {
|
||||
id = 0;
|
||||
tsfl_curr = tsfl0;
|
||||
} else {
|
||||
id = 1;
|
||||
tsfl_curr = tsfl1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
tsft = rtwn_get_tsf_high(sc, id);
|
||||
if (tsfl > tsfl_curr && tsfl > 0xffff0000)
|
||||
tsft--;
|
||||
tsft <<= 32;
|
||||
tsft += tsfl;
|
||||
|
||||
return (tsft);
|
||||
}
|
||||
|
||||
struct ieee80211_node *
|
||||
rtwn_rx_common(struct rtwn_softc *sc, struct mbuf *m, void *desc,
|
||||
int8_t *rssi)
|
||||
rtwn_rx_common(struct rtwn_softc *sc, struct mbuf *m, void *desc)
|
||||
{
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ieee80211_node *ni;
|
||||
struct ieee80211_frame_min *wh;
|
||||
struct ieee80211_rx_stats rxs;
|
||||
struct rtwn_node *un;
|
||||
struct r92c_rx_stat *stat;
|
||||
uint32_t rxdw0, rxdw3;
|
||||
int cipher, infosz, pktlen, rate, shift;
|
||||
void *physt;
|
||||
uint32_t rxdw0;
|
||||
int8_t rssi;
|
||||
int cipher, infosz, is_cck, pktlen, shift;
|
||||
|
||||
stat = desc;
|
||||
rxdw0 = le32toh(stat->rxdw0);
|
||||
rxdw3 = le32toh(stat->rxdw3);
|
||||
|
||||
cipher = MS(rxdw0, R92C_RXDW0_CIPHER);
|
||||
infosz = MS(rxdw0, R92C_RXDW0_INFOSZ) * 8;
|
||||
pktlen = MS(rxdw0, R92C_RXDW0_PKTLEN);
|
||||
shift = MS(rxdw0, R92C_RXDW0_SHIFT);
|
||||
rate = MS(rxdw3, R92C_RXDW3_RATE);
|
||||
|
||||
wh = (struct ieee80211_frame_min *)(mtodo(m, shift + infosz));
|
||||
if ((wh->i_fc[1] & IEEE80211_FC1_PROTECTED) &&
|
||||
cipher != R92C_CAM_ALGO_NONE)
|
||||
m->m_flags |= M_WEP;
|
||||
|
||||
if (pktlen >= sizeof(*wh))
|
||||
if (pktlen >= sizeof(*wh)) {
|
||||
ni = ieee80211_find_rxnode(ic, wh);
|
||||
else
|
||||
if (ni != NULL && (ni->ni_flags & IEEE80211_NODE_HT))
|
||||
m->m_flags |= M_AMPDU;
|
||||
} else
|
||||
ni = NULL;
|
||||
un = RTWN_NODE(ni);
|
||||
|
||||
/* Get RSSI from PHY status descriptor if present. */
|
||||
if (infosz != 0 && (rxdw0 & R92C_RXDW0_PHYST)) {
|
||||
*rssi = rtwn_get_rssi(sc, rate, mtod(m, void *));
|
||||
RTWN_DPRINTF(sc, RTWN_DEBUG_RSSI, "%s: rssi %d, ridx %d\n",
|
||||
__func__, *rssi, rate);
|
||||
if (infosz != 0 && (rxdw0 & R92C_RXDW0_PHYST))
|
||||
physt = (void *)mtodo(m, shift);
|
||||
else
|
||||
physt = (un != NULL) ? &un->last_physt : &sc->last_physt;
|
||||
|
||||
sc->last_rssi = *rssi;
|
||||
if (un != NULL) {
|
||||
un->last_rssi = *rssi;
|
||||
bzero(&rxs, sizeof(rxs));
|
||||
rtwn_get_rx_stats(sc, &rxs, desc, physt);
|
||||
if (rxs.c_pktflags & IEEE80211_RX_F_AMPDU) {
|
||||
/* Next MPDU will come without PHY info. */
|
||||
memcpy(&sc->last_physt, physt, sizeof(sc->last_physt));
|
||||
if (un != NULL)
|
||||
memcpy(&un->last_physt, physt, sizeof(sc->last_physt));
|
||||
}
|
||||
|
||||
/* Update our average RSSI. */
|
||||
rtwn_update_avgrssi(sc, un, rate);
|
||||
}
|
||||
} else
|
||||
*rssi = (un != NULL) ? un->last_rssi : sc->last_rssi;
|
||||
/* Add some common bits. */
|
||||
/* NB: should not happen. */
|
||||
if (rxdw0 & R92C_RXDW0_CRCERR)
|
||||
rxs.c_pktflags |= IEEE80211_RX_F_FAIL_FCSCRC;
|
||||
|
||||
rxs.r_flags |= IEEE80211_R_TSF_START; /* XXX undocumented */
|
||||
rxs.r_flags |= IEEE80211_R_TSF64;
|
||||
rxs.c_rx_tsf = rtwn_extend_rx_tsf(sc, stat);
|
||||
|
||||
/* Get RSSI from PHY status descriptor. */
|
||||
is_cck = (rxs.c_pktflags & IEEE80211_RX_F_CCK) != 0;
|
||||
rssi = rtwn_get_rssi(sc, physt, is_cck);
|
||||
|
||||
/* XXX TODO: we really need a rate-to-string method */
|
||||
RTWN_DPRINTF(sc, RTWN_DEBUG_RSSI, "%s: rssi %d, rate %d\n",
|
||||
__func__, rssi, rxs.c_rate);
|
||||
if (un != NULL && infosz != 0 && (rxdw0 & R92C_RXDW0_PHYST)) {
|
||||
/* Update our average RSSI. */
|
||||
rtwn_update_avgrssi(sc, un, rssi, is_cck);
|
||||
}
|
||||
|
||||
rxs.r_flags |= IEEE80211_R_NF | IEEE80211_R_RSSI;
|
||||
rxs.c_nf = RTWN_NOISE_FLOOR;
|
||||
rxs.c_rssi = rssi - rxs.c_nf;
|
||||
(void) ieee80211_add_rx_params(m, &rxs);
|
||||
|
||||
if (ieee80211_radiotap_active(ic)) {
|
||||
struct rtwn_rx_radiotap_header *tap = &sc->sc_rxtap;
|
||||
int id = RTWN_VAP_ID_INVALID;
|
||||
|
||||
if (ni != NULL)
|
||||
id = RTWN_VAP(ni->ni_vap)->id;
|
||||
if (id == RTWN_VAP_ID_INVALID)
|
||||
id = 0;
|
||||
|
||||
tap->wr_flags = rtwn_rx_radiotap_flags(sc, desc);
|
||||
tap->wr_tsft = rtwn_get_tsf_high(sc, id);
|
||||
if (le32toh(stat->tsf_low) > rtwn_get_tsf_low(sc, id))
|
||||
tap->wr_tsft--;
|
||||
tap->wr_tsft = (uint64_t)htole32(tap->wr_tsft) << 32;
|
||||
tap->wr_tsft += stat->tsf_low;
|
||||
|
||||
/* XXX 20/40? */
|
||||
|
||||
/* Map HW rate index to 802.11 rate. */
|
||||
if (rate < RTWN_RIDX_MCS(0))
|
||||
tap->wr_rate = ridx2rate[rate];
|
||||
else /* MCS0~15. */
|
||||
tap->wr_rate = IEEE80211_RATE_MCS | (rate - 12);
|
||||
|
||||
tap->wr_dbm_antsignal = *rssi;
|
||||
tap->wr_dbm_antnoise = RTWN_NOISE_FLOOR;
|
||||
tap->wr_tsft = htole64(rxs.c_rx_tsf);
|
||||
tap->wr_rate = rxs.c_rate;
|
||||
tap->wr_dbm_antsignal = rssi;
|
||||
tap->wr_dbm_antnoise = rxs.c_nf;
|
||||
}
|
||||
|
||||
/* Drop PHY descriptor. */
|
||||
|
@ -26,7 +26,7 @@ void rtwn_get_rates(struct rtwn_softc *, const struct ieee80211_rateset *,
|
||||
const struct ieee80211_htrateset *, uint32_t *, int *, int);
|
||||
void rtwn_set_basicrates(struct rtwn_softc *, uint32_t);
|
||||
struct ieee80211_node * rtwn_rx_common(struct rtwn_softc *, struct mbuf *,
|
||||
void *, int8_t *);
|
||||
void *);
|
||||
void rtwn_adhoc_recv_mgmt(struct ieee80211_node *, struct mbuf *, int,
|
||||
const struct ieee80211_rx_stats *, int, int);
|
||||
void rtwn_set_multi(struct rtwn_softc *);
|
||||
|
@ -76,6 +76,12 @@ struct rtwn_tx_buf {
|
||||
uint8_t txd[RTWN_TX_DESC_SIZE];
|
||||
} __attribute__((aligned(4)));
|
||||
|
||||
#define RTWN_PHY_STATUS_SIZE 32
|
||||
struct rtwn_tx_phystat {
|
||||
uint32_t phydw[RTWN_PHY_STATUS_SIZE / sizeof(uint32_t)];
|
||||
};
|
||||
|
||||
|
||||
struct rtwn_softc;
|
||||
|
||||
union sec_param {
|
||||
@ -95,7 +101,8 @@ struct rtwn_cmdq {
|
||||
struct rtwn_node {
|
||||
struct ieee80211_node ni; /* must be the first */
|
||||
int id;
|
||||
int8_t last_rssi;
|
||||
|
||||
struct rtwn_tx_phystat last_physt;
|
||||
int avg_pwdb;
|
||||
};
|
||||
#define RTWN_NODE(ni) ((struct rtwn_node *)(ni))
|
||||
@ -195,7 +202,7 @@ struct rtwn_softc {
|
||||
const char *name;
|
||||
int sc_ant;
|
||||
|
||||
int8_t last_rssi;
|
||||
struct rtwn_tx_phystat last_physt;
|
||||
uint8_t thcal_temp;
|
||||
int cur_bcnq_id;
|
||||
|
||||
@ -336,6 +343,9 @@ struct rtwn_softc {
|
||||
struct ieee80211vap *, int);
|
||||
void (*sc_set_rssi)(struct rtwn_softc *);
|
||||
#endif
|
||||
void (*sc_get_rx_stats)(struct rtwn_softc *,
|
||||
struct ieee80211_rx_stats *, const void *,
|
||||
const void *);
|
||||
int8_t (*sc_get_rssi_cck)(struct rtwn_softc *, void *);
|
||||
int8_t (*sc_get_rssi_ofdm)(struct rtwn_softc *, void *);
|
||||
int (*sc_classify_intr)(struct rtwn_softc *, void *, int);
|
||||
@ -478,6 +488,8 @@ void rtwn_suspend(struct rtwn_softc *);
|
||||
(((_sc)->sc_parse_rom)((_sc), (_rom)))
|
||||
#define rtwn_set_led(_sc, _led, _on) \
|
||||
(((_sc)->sc_set_led)((_sc), (_led), (_on)))
|
||||
#define rtwn_get_rx_stats(_sc, _rxs, _desc, _physt) \
|
||||
(((_sc)->sc_get_rx_stats((_sc), (_rxs), (_desc), (_physt))))
|
||||
#define rtwn_get_rssi_cck(_sc, _physt) \
|
||||
(((_sc)->sc_get_rssi_cck)((_sc), (_physt)))
|
||||
#define rtwn_get_rssi_ofdm(_sc, _physt) \
|
||||
|
@ -95,7 +95,6 @@ rtwn_pci_rx_frame(struct rtwn_softc *sc, struct r92ce_rx_stat *rx_desc,
|
||||
struct ieee80211_node *ni;
|
||||
uint32_t rxdw0;
|
||||
struct mbuf *m, *m1;
|
||||
int8_t rssi = 0, nf;
|
||||
int infosz, pktlen, shift, error;
|
||||
|
||||
/* Dump Rx descriptor. */
|
||||
@ -162,12 +161,11 @@ rtwn_pci_rx_frame(struct rtwn_softc *sc, struct r92ce_rx_stat *rx_desc,
|
||||
rx_data->m = m1;
|
||||
m->m_pkthdr.len = m->m_len = pktlen + infosz + shift;
|
||||
|
||||
nf = RTWN_NOISE_FLOOR;
|
||||
ni = rtwn_rx_common(sc, m, rx_desc, &rssi);
|
||||
ni = rtwn_rx_common(sc, m, rx_desc);
|
||||
|
||||
RTWN_DPRINTF(sc, RTWN_DEBUG_RECV,
|
||||
"%s: Rx frame len %d, infosz %d, shift %d, rssi %d\n",
|
||||
__func__, pktlen, infosz, shift, rssi);
|
||||
"%s: Rx frame len %d, infosz %d, shift %d\n",
|
||||
__func__, pktlen, infosz, shift);
|
||||
|
||||
/* Update RX descriptor. */
|
||||
rtwn_pci_setup_rx_desc(pc, rx_desc, rx_data->paddr, MJUMPAGESIZE,
|
||||
@ -176,11 +174,11 @@ rtwn_pci_rx_frame(struct rtwn_softc *sc, struct r92ce_rx_stat *rx_desc,
|
||||
/* Send the frame to the 802.11 layer. */
|
||||
RTWN_UNLOCK(sc);
|
||||
if (ni != NULL) {
|
||||
(void)ieee80211_input(ni, m, rssi - nf, nf);
|
||||
(void)ieee80211_input_mimo(ni, m);
|
||||
/* Node is no longer needed. */
|
||||
ieee80211_free_node(ni);
|
||||
} else
|
||||
(void)ieee80211_input_all(ic, m, rssi - nf, nf);
|
||||
(void)ieee80211_input_mimo_all(ic, m);
|
||||
|
||||
RTWN_LOCK(sc);
|
||||
|
||||
|
@ -85,6 +85,8 @@ void r88e_ratectl_tx_complete(struct rtwn_softc *, uint8_t *, int);
|
||||
void r88e_handle_c2h_report(struct rtwn_softc *, uint8_t *, int);
|
||||
int8_t r88e_get_rssi_cck(struct rtwn_softc *, void *);
|
||||
int8_t r88e_get_rssi_ofdm(struct rtwn_softc *, void *);
|
||||
void r88e_get_rx_stats(struct rtwn_softc *, struct ieee80211_rx_stats *,
|
||||
const void *, const void *);
|
||||
|
||||
/* r88e_tx.c */
|
||||
void r88e_tx_enable_ampdu(void *, int);
|
||||
|
@ -51,6 +51,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <dev/rtwn/if_rtwn_debug.h>
|
||||
#include <dev/rtwn/if_rtwn_ridx.h>
|
||||
|
||||
#include <dev/rtwn/rtl8192c/r92c.h>
|
||||
#include <dev/rtwn/rtl8188e/r88e.h>
|
||||
#include <dev/rtwn/rtl8188e/r88e_rx_desc.h>
|
||||
|
||||
@ -209,3 +210,19 @@ r88e_get_rssi_ofdm(struct rtwn_softc *sc, void *physt)
|
||||
|
||||
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->c_ieee = le16toh(physt->chan);
|
||||
rxs->c_freq = ieee80211_ieee2mhz(rxs->c_ieee,
|
||||
IEEE80211_CHAN_2GHZ);
|
||||
}
|
||||
}
|
||||
|
@ -127,6 +127,7 @@ r88eu_attach(struct rtwn_usb_softc *uc)
|
||||
sc->sc_dump_tx_desc = r92cu_dump_tx_desc;
|
||||
sc->sc_tx_radiotap_flags = r92c_tx_radiotap_flags;
|
||||
sc->sc_rx_radiotap_flags = r92c_rx_radiotap_flags;
|
||||
sc->sc_get_rx_stats = r88e_get_rx_stats;
|
||||
sc->sc_get_rssi_cck = r88e_get_rssi_cck;
|
||||
sc->sc_get_rssi_ofdm = r88e_get_rssi_ofdm;
|
||||
sc->sc_classify_intr = r88eu_classify_intr;
|
||||
|
@ -172,6 +172,7 @@ r92ce_attach(struct rtwn_pci_softc *pc)
|
||||
sc->sc_dump_tx_desc = r92ce_dump_tx_desc;
|
||||
sc->sc_tx_radiotap_flags = r92c_tx_radiotap_flags;
|
||||
sc->sc_rx_radiotap_flags = r92c_rx_radiotap_flags;
|
||||
sc->sc_get_rx_stats = r92c_get_rx_stats;
|
||||
sc->sc_get_rssi_cck = r92c_get_rssi_cck;
|
||||
sc->sc_get_rssi_ofdm = r92c_get_rssi_ofdm;
|
||||
sc->sc_classify_intr = r92ce_classify_intr;
|
||||
|
@ -99,6 +99,8 @@ void r92c_parse_rom(struct rtwn_softc *, uint8_t *);
|
||||
int8_t r92c_get_rssi_cck(struct rtwn_softc *, void *);
|
||||
int8_t r92c_get_rssi_ofdm(struct rtwn_softc *, void *);
|
||||
uint8_t r92c_rx_radiotap_flags(const void *);
|
||||
void r92c_get_rx_stats(struct rtwn_softc *, struct ieee80211_rx_stats *,
|
||||
const void *, const void *);
|
||||
|
||||
/* r92c_tx.c */
|
||||
void r92c_tx_enable_ampdu(void *, int);
|
||||
|
@ -420,6 +420,7 @@
|
||||
#define R92C_PBP_1024 4
|
||||
|
||||
/* Bits for R92C_TRXDMA_CTRL. */
|
||||
#define R92C_TRXDMA_CTRL_RX_SHIFT_EN 0x0002
|
||||
#define R92C_TRXDMA_CTRL_RXDMA_AGG_EN 0x0004
|
||||
#define R92C_TRXDMA_CTRL_TXDMA_VOQ_MAP_M 0x0030
|
||||
#define R92C_TRXDMA_CTRL_TXDMA_VOQ_MAP_S 4
|
||||
@ -593,7 +594,8 @@
|
||||
#define R92C_RCR_APPFCS 0x80000000
|
||||
|
||||
/* Bits for R92C_RX_DRVINFO_SZ. */
|
||||
#define R92C_RX_DRVINFO_SZ_DEF 4 /* XXX other values will not work */
|
||||
/* XXX other values will not work */
|
||||
#define R92C_RX_DRVINFO_SZ_DEF ((RTWN_PHY_STATUS_SIZE) / 8)
|
||||
|
||||
/* Bits for R92C_WMAC_TRXPTCL_CTL. */
|
||||
#define R92C_WMAC_TRXPTCL_SHPRE 0x00020000
|
||||
|
@ -100,3 +100,47 @@ r92c_rx_radiotap_flags(const void *buf)
|
||||
flags = IEEE80211_RADIOTAP_F_SHORTGI;
|
||||
return (flags);
|
||||
}
|
||||
|
||||
void
|
||||
r92c_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;
|
||||
uint32_t rxdw1, rxdw3;
|
||||
uint8_t rate;
|
||||
|
||||
rxdw1 = le32toh(stat->rxdw1);
|
||||
rxdw3 = le32toh(stat->rxdw3);
|
||||
rate = MS(rxdw3, R92C_RXDW3_RATE);
|
||||
|
||||
if (rxdw1 & R92C_RXDW1_AMPDU)
|
||||
rxs->c_pktflags |= IEEE80211_RX_F_AMPDU;
|
||||
else if (rxdw1 & R92C_RXDW1_AMPDU_MORE)
|
||||
rxs->c_pktflags |= IEEE80211_RX_F_AMPDU_MORE;
|
||||
if ((rxdw3 & R92C_RXDW3_SPLCP) && rate >= RTWN_RIDX_MCS(0))
|
||||
rxs->c_pktflags |= IEEE80211_RX_F_SHORTGI;
|
||||
|
||||
if (rxdw3 & R92C_RXDW3_HT40)
|
||||
rxs->c_width = IEEE80211_RX_FW_40MHZ;
|
||||
else
|
||||
rxs->c_width = IEEE80211_RX_FW_20MHZ;
|
||||
|
||||
if (RTWN_RATE_IS_CCK(rate))
|
||||
rxs->c_phytype = IEEE80211_RX_FP_11B;
|
||||
else if (rate < RTWN_RIDX_MCS(0))
|
||||
rxs->c_phytype = IEEE80211_RX_FP_11G;
|
||||
else
|
||||
rxs->c_phytype = IEEE80211_RX_FP_11NG;
|
||||
|
||||
/* Map HW rate index to 802.11 rate. */
|
||||
if (rate < RTWN_RIDX_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. */
|
||||
rxs->c_rate = IEEE80211_RATE_MCS | (rate - 12);
|
||||
rxs->c_pktflags |= IEEE80211_RX_F_HT;
|
||||
}
|
||||
}
|
||||
|
@ -45,6 +45,9 @@ struct r92c_rx_stat {
|
||||
uint32_t rxdw1;
|
||||
#define R92C_RXDW1_MACID_M 0x0000001f
|
||||
#define R92C_RXDW1_MACID_S 0
|
||||
#define R92C_RXDW1_AMSDU 0x00002000
|
||||
#define R92C_RXDW1_AMPDU_MORE 0x00004000
|
||||
#define R92C_RXDW1_AMPDU 0x00008000
|
||||
#define R92C_RXDW1_MC 0x40000000
|
||||
#define R92C_RXDW1_BC 0x80000000
|
||||
|
||||
@ -56,6 +59,8 @@ struct r92c_rx_stat {
|
||||
#define R92C_RXDW3_SPLCP 0x00000100
|
||||
#define R92C_RXDW3_HT40 0x00000200
|
||||
#define R92C_RXDW3_HTC 0x00000400
|
||||
#define R92C_RXDW3_BSSID_FIT_M 0x00003000
|
||||
#define R92C_RXDW3_BSSID_FIT_S 12
|
||||
|
||||
uint32_t rxdw4;
|
||||
uint32_t tsf_low;
|
||||
|
@ -165,6 +165,7 @@ r92cu_attach(struct rtwn_usb_softc *uc)
|
||||
sc->sc_dump_tx_desc = r92cu_dump_tx_desc;
|
||||
sc->sc_tx_radiotap_flags = r92c_tx_radiotap_flags;
|
||||
sc->sc_rx_radiotap_flags = r92c_rx_radiotap_flags;
|
||||
sc->sc_get_rx_stats = r92c_get_rx_stats;
|
||||
sc->sc_get_rssi_cck = r92c_get_rssi_cck;
|
||||
sc->sc_get_rssi_ofdm = r92c_get_rssi_ofdm;
|
||||
sc->sc_classify_intr = r92cu_classify_intr;
|
||||
|
@ -128,6 +128,8 @@ void r12a_ratectl_tx_complete(struct rtwn_softc *, uint8_t *, int);
|
||||
void r12a_handle_c2h_report(struct rtwn_softc *, uint8_t *, int);
|
||||
int r12a_check_frame_checksum(struct rtwn_softc *, struct mbuf *);
|
||||
uint8_t r12a_rx_radiotap_flags(const void *);
|
||||
void r12a_get_rx_stats(struct rtwn_softc *, struct ieee80211_rx_stats *,
|
||||
const void *, const void *);
|
||||
|
||||
/* r12a_tx.c */
|
||||
void r12a_fill_tx_desc(struct rtwn_softc *, struct ieee80211_node *,
|
||||
|
@ -229,10 +229,97 @@ r12a_rx_radiotap_flags(const void *buf)
|
||||
|
||||
if (!(stat->rxdw4 & htole32(R12A_RXDW4_SPLCP)))
|
||||
return (0);
|
||||
rate = MS(le32toh(stat->rxdw3), R92C_RXDW3_RATE);
|
||||
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, 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_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_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_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 - 12);
|
||||
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->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);
|
||||
#endif
|
||||
}
|
||||
|
@ -34,18 +34,26 @@
|
||||
/* Rx MAC descriptor defines (chip-specific). */
|
||||
/* Rx dword 1 */
|
||||
#define R12A_RXDW1_AMSDU 0x00002000
|
||||
#define R12A_RXDW1_AMPDU 0x00008000
|
||||
#define R12A_RXDW1_CKSUM_ERR 0x00100000
|
||||
#define R12A_RXDW1_IPV6 0x00200000
|
||||
#define R12A_RXDW1_UDP 0x00400000
|
||||
#define R12A_RXDW1_CKSUM 0x00800000
|
||||
/* Rx dword 2 */
|
||||
#define R12A_RXDW2_RPT_C2H 0x10000000
|
||||
/* Rx dword 3 */
|
||||
#define R12A_RXDW3_RATE_M 0x0000007f
|
||||
#define R12A_RXDW3_RATE_S 0
|
||||
/* Rx dword 4 */
|
||||
#define R12A_RXDW4_SPLCP 0x00000001
|
||||
#define R12A_RXDW4_LDPC 0x00000002
|
||||
#define R12A_RXDW4_STBC 0x00000004
|
||||
#define R12A_RXDW4_BW_M 0x00000030
|
||||
#define R12A_RXDW4_BW_S 4
|
||||
#define R12A_RXDW4_BW20 0
|
||||
#define R12A_RXDW4_BW40 1
|
||||
#define R12A_RXDW4_BW80 2
|
||||
#define R12A_RXDW4_BW160 3
|
||||
|
||||
/* Rx PHY descriptor. */
|
||||
struct r12a_rx_phystat {
|
||||
|
@ -190,6 +190,7 @@ r12au_attach(struct rtwn_usb_softc *uc)
|
||||
sc->sc_dump_tx_desc = r12au_dump_tx_desc;
|
||||
sc->sc_tx_radiotap_flags = r12a_tx_radiotap_flags;
|
||||
sc->sc_rx_radiotap_flags = r12a_rx_radiotap_flags;
|
||||
sc->sc_get_rx_stats = r12a_get_rx_stats;
|
||||
sc->sc_get_rssi_cck = r88e_get_rssi_cck;
|
||||
sc->sc_get_rssi_ofdm = r88e_get_rssi_ofdm;
|
||||
sc->sc_classify_intr = r12au_classify_intr;
|
||||
|
@ -182,6 +182,7 @@ r21au_attach(struct rtwn_usb_softc *uc)
|
||||
sc->sc_dump_tx_desc = r12au_dump_tx_desc;
|
||||
sc->sc_tx_radiotap_flags = r12a_tx_radiotap_flags;
|
||||
sc->sc_rx_radiotap_flags = r12a_rx_radiotap_flags;
|
||||
sc->sc_get_rx_stats = r12a_get_rx_stats;
|
||||
sc->sc_get_rssi_cck = r21a_get_rssi_cck;
|
||||
sc->sc_get_rssi_ofdm = r88e_get_rssi_ofdm;
|
||||
sc->sc_classify_intr = r12au_classify_intr;
|
||||
|
@ -236,7 +236,7 @@ rtwn_report_intr(struct rtwn_usb_softc *uc, struct usb_xfer *xfer,
|
||||
}
|
||||
|
||||
static struct ieee80211_node *
|
||||
rtwn_rx_frame(struct rtwn_softc *sc, struct mbuf *m, int8_t *rssi)
|
||||
rtwn_rx_frame(struct rtwn_softc *sc, struct mbuf *m)
|
||||
{
|
||||
struct r92c_rx_stat stat;
|
||||
|
||||
@ -244,7 +244,7 @@ rtwn_rx_frame(struct rtwn_softc *sc, struct mbuf *m, int8_t *rssi)
|
||||
m_copydata(m, 0, sizeof(struct r92c_rx_stat), (caddr_t)&stat);
|
||||
m_adj(m, sizeof(struct r92c_rx_stat));
|
||||
|
||||
return (rtwn_rx_common(sc, m, &stat, rssi));
|
||||
return (rtwn_rx_common(sc, m, &stat));
|
||||
}
|
||||
|
||||
void
|
||||
@ -256,7 +256,6 @@ rtwn_bulk_rx_callback(struct usb_xfer *xfer, usb_error_t error)
|
||||
struct ieee80211_node *ni;
|
||||
struct mbuf *m = NULL, *next;
|
||||
struct rtwn_data *data;
|
||||
int8_t nf, rssi;
|
||||
|
||||
RTWN_ASSERT_LOCKED(sc);
|
||||
|
||||
@ -291,19 +290,15 @@ rtwn_bulk_rx_callback(struct usb_xfer *xfer, usb_error_t error)
|
||||
next = m->m_next;
|
||||
m->m_next = NULL;
|
||||
|
||||
ni = rtwn_rx_frame(sc, m, &rssi);
|
||||
ni = rtwn_rx_frame(sc, m);
|
||||
|
||||
RTWN_UNLOCK(sc);
|
||||
|
||||
nf = RTWN_NOISE_FLOOR;
|
||||
if (ni != NULL) {
|
||||
if (ni->ni_flags & IEEE80211_NODE_HT)
|
||||
m->m_flags |= M_AMPDU;
|
||||
(void)ieee80211_input(ni, m, rssi - nf, nf);
|
||||
(void)ieee80211_input_mimo(ni, m);
|
||||
ieee80211_free_node(ni);
|
||||
} else {
|
||||
(void)ieee80211_input_all(ic, m,
|
||||
rssi - nf, nf);
|
||||
(void)ieee80211_input_mimo_all(ic, m);
|
||||
}
|
||||
RTWN_LOCK(sc);
|
||||
m = next;
|
||||
|
Loading…
Reference in New Issue
Block a user