summaryrefslogtreecommitdiffstats
path: root/freebsd/sys/dev/usb/wlan/if_run.c
diff options
context:
space:
mode:
Diffstat (limited to 'freebsd/sys/dev/usb/wlan/if_run.c')
-rw-r--r--freebsd/sys/dev/usb/wlan/if_run.c145
1 files changed, 83 insertions, 62 deletions
diff --git a/freebsd/sys/dev/usb/wlan/if_run.c b/freebsd/sys/dev/usb/wlan/if_run.c
index 3bd247e3..9f11a3a3 100644
--- a/freebsd/sys/dev/usb/wlan/if_run.c
+++ b/freebsd/sys/dev/usb/wlan/if_run.c
@@ -30,6 +30,7 @@ __FBSDID("$FreeBSD$");
#include <rtems/bsd/local/opt_wlan.h>
#include <sys/param.h>
+#include <sys/eventhandler.h>
#include <sys/sockio.h>
#include <sys/sysctl.h>
#include <sys/lock.h>
@@ -46,10 +47,6 @@ __FBSDID("$FreeBSD$");
#include <sys/firmware.h>
#include <sys/kdb.h>
-#include <machine/bus.h>
-#include <machine/resource.h>
-#include <sys/rman.h>
-
#include <net/bpf.h>
#include <net/if.h>
#include <net/if_var.h>
@@ -470,6 +467,7 @@ static void run_usb_timeout_cb(void *);
static void run_reset_livelock(struct run_softc *);
static void run_enable_tsf_sync(struct run_softc *);
static void run_enable_tsf(struct run_softc *);
+static void run_disable_tsf(struct run_softc *);
static void run_get_tsf(struct run_softc *, uint64_t *);
static void run_enable_mrr(struct run_softc *);
static void run_set_txpreamble(struct run_softc *);
@@ -2035,7 +2033,8 @@ run_read_eeprom(struct run_softc *sc)
static struct ieee80211_node *
run_node_alloc(struct ieee80211vap *vap, const uint8_t mac[IEEE80211_ADDR_LEN])
{
- return malloc(sizeof (struct run_node), M_DEVBUF, M_NOWAIT | M_ZERO);
+ return malloc(sizeof (struct run_node), M_80211_NODE,
+ M_NOWAIT | M_ZERO);
}
static int
@@ -2095,7 +2094,6 @@ run_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
struct run_vap *rvp = RUN_VAP(vap);
enum ieee80211_state ostate;
uint32_t sta[3];
- uint32_t tmp;
uint8_t ratectl;
uint8_t restart_ratectl = 0;
uint8_t bid = 1 << rvp->rvp_id;
@@ -2128,12 +2126,8 @@ run_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
sc->runbmap &= ~bid;
/* abort TSF synchronization if there is no vap running */
- if (--sc->running == 0) {
- run_read(sc, RT2860_BCN_TIME_CFG, &tmp);
- run_write(sc, RT2860_BCN_TIME_CFG,
- tmp & ~(RT2860_BCN_TX_EN | RT2860_TSF_TIMER_EN |
- RT2860_TBTT_TIMER_EN));
- }
+ if (--sc->running == 0)
+ run_disable_tsf(sc);
break;
case IEEE80211_S_RUN:
@@ -2826,76 +2820,83 @@ run_rx_frame(struct run_softc *sc, struct mbuf *m, uint32_t dmalen)
uint8_t ant, rssi;
int8_t nf;
- rxwi = mtod(m, struct rt2860_rxwi *);
- len = le16toh(rxwi->len) & 0xfff;
rxwisize = sizeof(struct rt2860_rxwi);
if (sc->mac_ver == 0x5592)
rxwisize += sizeof(uint64_t);
else if (sc->mac_ver == 0x3593)
rxwisize += sizeof(uint32_t);
- if (__predict_false(len > dmalen)) {
- m_freem(m);
- counter_u64_add(ic->ic_ierrors, 1);
+
+ if (__predict_false(dmalen <
+ rxwisize + sizeof(struct ieee80211_frame_ack))) {
+ RUN_DPRINTF(sc, RUN_DEBUG_RECV,
+ "payload is too short: dma length %u < %zu\n",
+ dmalen, rxwisize + sizeof(struct ieee80211_frame_ack));
+ goto fail;
+ }
+
+ rxwi = mtod(m, struct rt2860_rxwi *);
+ len = le16toh(rxwi->len) & 0xfff;
+
+ if (__predict_false(len > dmalen - rxwisize)) {
RUN_DPRINTF(sc, RUN_DEBUG_RECV,
"bad RXWI length %u > %u\n", len, dmalen);
- return;
+ goto fail;
}
+
/* Rx descriptor is located at the end */
rxd = (struct rt2870_rxd *)(mtod(m, caddr_t) + dmalen);
flags = le32toh(rxd->flags);
if (__predict_false(flags & (RT2860_RX_CRCERR | RT2860_RX_ICVERR))) {
- m_freem(m);
- counter_u64_add(ic->ic_ierrors, 1);
RUN_DPRINTF(sc, RUN_DEBUG_RECV, "%s error.\n",
(flags & RT2860_RX_CRCERR)?"CRC":"ICV");
- return;
+ goto fail;
+ }
+
+ if (flags & RT2860_RX_L2PAD) {
+ RUN_DPRINTF(sc, RUN_DEBUG_RECV,
+ "received RT2860_RX_L2PAD frame\n");
+ len += 2;
}
m->m_data += rxwisize;
- m->m_pkthdr.len = m->m_len -= rxwisize;
+ m->m_pkthdr.len = m->m_len = len;
wh = mtod(m, struct ieee80211_frame *);
- if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) {
+ if ((wh->i_fc[1] & IEEE80211_FC1_PROTECTED) != 0 &&
+ (flags & RT2860_RX_DEC) != 0) {
wh->i_fc[1] &= ~IEEE80211_FC1_PROTECTED;
m->m_flags |= M_WEP;
}
- if (flags & RT2860_RX_L2PAD) {
- RUN_DPRINTF(sc, RUN_DEBUG_RECV,
- "received RT2860_RX_L2PAD frame\n");
- len += 2;
- }
-
- ni = ieee80211_find_rxnode(ic,
- mtod(m, struct ieee80211_frame_min *));
+ if (len >= sizeof(struct ieee80211_frame_min)) {
+ ni = ieee80211_find_rxnode(ic,
+ mtod(m, struct ieee80211_frame_min *));
+ } else
+ ni = NULL;
if (__predict_false(flags & RT2860_RX_MICERR)) {
/* report MIC failures to net80211 for TKIP */
if (ni != NULL)
ieee80211_notify_michael_failure(ni->ni_vap, wh,
rxwi->keyidx);
- m_freem(m);
- counter_u64_add(ic->ic_ierrors, 1);
RUN_DPRINTF(sc, RUN_DEBUG_RECV,
"MIC error. Someone is lying.\n");
- return;
+ goto fail;
}
ant = run_maxrssi_chain(sc, rxwi);
rssi = rxwi->rssi[ant];
nf = run_rssi2dbm(sc, rssi, ant);
- m->m_pkthdr.len = m->m_len = len;
-
if (__predict_false(ieee80211_radiotap_active(ic))) {
struct run_rx_radiotap_header *tap = &sc->sc_rxtap;
uint16_t phy;
tap->wr_flags = 0;
- tap->wr_chan_freq = htole16(ic->ic_curchan->ic_freq);
- tap->wr_chan_flags = htole16(ic->ic_curchan->ic_flags);
+ if (flags & RT2860_RX_L2PAD)
+ tap->wr_flags |= IEEE80211_RADIOTAP_F_DATAPAD;
tap->wr_antsignal = rssi;
tap->wr_antenna = ant;
tap->wr_dbm_antsignal = run_rssi2dbm(sc, rssi, ant);
@@ -2936,6 +2937,12 @@ run_rx_frame(struct run_softc *sc, struct mbuf *m, uint32_t dmalen)
} else {
(void)ieee80211_input_all(ic, m, rssi, nf);
}
+
+ return;
+
+fail:
+ m_freem(m);
+ counter_u64_add(ic->ic_ierrors, 1);
}
static void
@@ -2945,7 +2952,7 @@ run_bulk_rx_callback(struct usb_xfer *xfer, usb_error_t error)
struct ieee80211com *ic = &sc->sc_ic;
struct mbuf *m = NULL;
struct mbuf *m0;
- uint32_t dmalen;
+ uint32_t dmalen, mbuf_len;
uint16_t rxwisize;
int xferlen;
@@ -3051,6 +3058,14 @@ tr_setup:
break;
}
+ mbuf_len = dmalen + sizeof(struct rt2870_rxd);
+ if (__predict_false(mbuf_len > MCLBYTES)) {
+ RUN_DPRINTF(sc, RUN_DEBUG_RECV_DESC | RUN_DEBUG_USB,
+ "payload is too big: mbuf_len %u\n", mbuf_len);
+ counter_u64_add(ic->ic_ierrors, 1);
+ break;
+ }
+
/* copy aggregated frames to another mbuf */
m0 = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
if (__predict_false(m0 == NULL)) {
@@ -3060,14 +3075,13 @@ tr_setup:
break;
}
m_copydata(m, 4 /* skip 32-bit DMA-len header */,
- dmalen + sizeof(struct rt2870_rxd), mtod(m0, caddr_t));
- m0->m_pkthdr.len = m0->m_len =
- dmalen + sizeof(struct rt2870_rxd);
+ mbuf_len, mtod(m0, caddr_t));
+ m0->m_pkthdr.len = m0->m_len = mbuf_len;
run_rx_frame(sc, m0, dmalen);
/* update data ptr */
- m->m_data += dmalen + 8;
- m->m_pkthdr.len = m->m_len -= dmalen + 8;
+ m->m_data += mbuf_len + 4;
+ m->m_pkthdr.len = m->m_len -= mbuf_len + 4;
}
/* make sure we free the source buffer, if any */
@@ -3149,16 +3163,23 @@ tr_setup:
vap = data->ni->ni_vap;
if (ieee80211_radiotap_active_vap(vap)) {
+ const struct ieee80211_frame *wh;
struct run_tx_radiotap_header *tap = &sc->sc_txtap;
struct rt2860_txwi *txwi =
(struct rt2860_txwi *)(&data->desc + sizeof(struct rt2870_txd));
+ int has_l2pad;
+
+ wh = mtod(m, struct ieee80211_frame *);
+ has_l2pad = IEEE80211_HAS_ADDR4(wh) !=
+ IEEE80211_QOS_HAS_SEQ(wh);
+
tap->wt_flags = 0;
tap->wt_rate = rt2860_rates[data->ridx].rate;
- tap->wt_chan_freq = htole16(ic->ic_curchan->ic_freq);
- tap->wt_chan_flags = htole16(ic->ic_curchan->ic_flags);
tap->wt_hwqueue = index;
if (le16toh(txwi->phy) & RT2860_PHY_SHPRE)
tap->wt_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
+ if (has_l2pad)
+ tap->wt_flags |= IEEE80211_RADIOTAP_F_DATAPAD;
ieee80211_radiotap_tx(vap, m);
}
@@ -3350,11 +3371,7 @@ run_tx(struct run_softc *sc, struct mbuf *m, struct ieee80211_node *ni)
if ((hasqos = IEEE80211_QOS_HAS_SEQ(wh))) {
uint8_t *frm;
- if(IEEE80211_HAS_ADDR4(wh))
- frm = ((struct ieee80211_qosframe_addr4 *)wh)->i_qos;
- else
- frm =((struct ieee80211_qosframe *)wh)->i_qos;
-
+ frm = ieee80211_getqos(wh);
qos = le16toh(*(const uint16_t *)frm);
tid = qos & IEEE80211_QOS_TID;
qid = TID_TO_WME_AC(tid);
@@ -4837,8 +4854,7 @@ run_getradiocaps(struct ieee80211com *ic,
memset(bands, 0, sizeof(bands));
setbit(bands, IEEE80211_MODE_11B);
setbit(bands, IEEE80211_MODE_11G);
- ieee80211_add_channel_list_2ghz(chans, maxchans, nchans,
- run_chan_2ghz, nitems(run_chan_2ghz), bands, 0);
+ ieee80211_add_channels_default_2ghz(chans, maxchans, nchans, bands, 0);
if (sc->rf_rev == RT2860_RF_2750 || sc->rf_rev == RT2860_RF_2850 ||
sc->rf_rev == RT3070_RF_3052 || sc->rf_rev == RT3593_RF_3053 ||
@@ -4853,15 +4869,11 @@ static void
run_scan_start(struct ieee80211com *ic)
{
struct run_softc *sc = ic->ic_softc;
- uint32_t tmp;
RUN_LOCK(sc);
/* abort TSF synchronization */
- run_read(sc, RT2860_BCN_TIME_CFG, &tmp);
- run_write(sc, RT2860_BCN_TIME_CFG,
- tmp & ~(RT2860_BCN_TX_EN | RT2860_TSF_TIMER_EN |
- RT2860_TBTT_TIMER_EN));
+ run_disable_tsf(sc);
run_set_bssid(sc, ieee80211broadcastaddr);
RUN_UNLOCK(sc);
@@ -5148,6 +5160,18 @@ run_enable_tsf(struct run_softc *sc)
}
static void
+run_disable_tsf(struct run_softc *sc)
+{
+ uint32_t tmp;
+
+ if (run_read(sc, RT2860_BCN_TIME_CFG, &tmp) == 0) {
+ tmp &= ~(RT2860_BCN_TX_EN | RT2860_TSF_TIMER_EN |
+ RT2860_TBTT_TIMER_EN);
+ run_write(sc, RT2860_BCN_TIME_CFG, tmp);
+ }
+}
+
+static void
run_get_tsf(struct run_softc *sc, uint64_t *buf)
{
run_read_region_1(sc, RT2860_TSF_TIMER_DW0, (uint8_t *)buf,
@@ -6098,10 +6122,7 @@ run_init_locked(struct run_softc *sc)
}
/* abort TSF synchronization */
- run_read(sc, RT2860_BCN_TIME_CFG, &tmp);
- tmp &= ~(RT2860_BCN_TX_EN | RT2860_TSF_TIMER_EN |
- RT2860_TBTT_TIMER_EN);
- run_write(sc, RT2860_BCN_TIME_CFG, tmp);
+ run_disable_tsf(sc);
/* clear RX WCID search table */
run_set_region_4(sc, RT2860_WCID_ENTRY(0), 0, 512);