summaryrefslogtreecommitdiffstats
path: root/freebsd/sys/dev/usb/wlan/if_urtw.c
diff options
context:
space:
mode:
Diffstat (limited to 'freebsd/sys/dev/usb/wlan/if_urtw.c')
-rw-r--r--freebsd/sys/dev/usb/wlan/if_urtw.c142
1 files changed, 90 insertions, 52 deletions
diff --git a/freebsd/sys/dev/usb/wlan/if_urtw.c b/freebsd/sys/dev/usb/wlan/if_urtw.c
index 309375f0..aba334af 100644
--- a/freebsd/sys/dev/usb/wlan/if_urtw.c
+++ b/freebsd/sys/dev/usb/wlan/if_urtw.c
@@ -36,10 +36,6 @@ __FBSDID("$FreeBSD$");
#include <sys/endian.h>
#include <sys/kdb.h>
-#include <machine/bus.h>
-#include <machine/resource.h>
-#include <sys/rman.h>
-
#include <net/if.h>
#include <net/if_var.h>
#include <net/if_arp.h>
@@ -217,9 +213,6 @@ static uint8_t urtw_8225z2_agc[] = {
0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31
};
-static const uint8_t urtw_chan_2ghz[] =
- { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 };
-
static uint32_t urtw_8225_channel[] = {
0x0000, /* dummy channel 0 */
0x085c, /* 1 */
@@ -679,6 +672,7 @@ static void urtw_scan_end(struct ieee80211com *);
static void urtw_getradiocaps(struct ieee80211com *, int, int *,
struct ieee80211_channel[]);
static void urtw_set_channel(struct ieee80211com *);
+static void urtw_update_promisc(struct ieee80211com *);
static void urtw_update_mcast(struct ieee80211com *);
static int urtw_tx_start(struct urtw_softc *,
struct ieee80211_node *, struct mbuf *,
@@ -760,6 +754,7 @@ static void urtw_free_tx_data_list(struct urtw_softc *);
static void urtw_free_rx_data_list(struct urtw_softc *);
static void urtw_free_data_list(struct urtw_softc *,
struct urtw_data data[], int, int);
+static usb_error_t urtw_set_macaddr(struct urtw_softc *, const uint8_t *);
static usb_error_t urtw_adapter_start(struct urtw_softc *);
static usb_error_t urtw_adapter_start_b(struct urtw_softc *);
static usb_error_t urtw_set_mode(struct urtw_softc *, uint32_t);
@@ -905,6 +900,7 @@ urtw_attach(device_t dev)
ic->ic_updateslot = urtw_updateslot;
ic->ic_vap_create = urtw_vap_create;
ic->ic_vap_delete = urtw_vap_delete;
+ ic->ic_update_promisc = urtw_update_promisc;
ic->ic_update_mcast = urtw_update_mcast;
ic->ic_parent = urtw_parent;
ic->ic_transmit = urtw_transmit;
@@ -1194,9 +1190,23 @@ fail:
}
static usb_error_t
+urtw_set_macaddr(struct urtw_softc *sc, const uint8_t *macaddr)
+{
+ usb_error_t error;
+
+ urtw_write32_m(sc, URTW_MAC0, ((const uint32_t *)macaddr)[0]);
+ urtw_write16_m(sc, URTW_MAC4, ((const uint32_t *)macaddr)[1] & 0xffff);
+
+fail:
+ return (error);
+}
+
+static usb_error_t
urtw_adapter_start(struct urtw_softc *sc)
{
struct ieee80211com *ic = &sc->sc_ic;
+ struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
+ const uint8_t *macaddr;
usb_error_t error;
error = urtw_reset(sc);
@@ -1216,8 +1226,11 @@ urtw_adapter_start(struct urtw_softc *sc)
if (error)
goto fail;
/* applying MAC address again. */
- urtw_write32_m(sc, URTW_MAC0, ((uint32_t *)ic->ic_macaddr)[0]);
- urtw_write16_m(sc, URTW_MAC4, ((uint32_t *)ic->ic_macaddr)[1] & 0xffff);
+ macaddr = vap ? vap->iv_myaddr : ic->ic_macaddr;
+ urtw_set_macaddr(sc, macaddr);
+ if (error)
+ goto fail;
+
error = urtw_set_mode(sc, URTW_EPROM_CMD_NORMAL);
if (error)
goto fail;
@@ -1587,8 +1600,7 @@ urtw_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,
- urtw_chan_2ghz, nitems(urtw_chan_2ghz), bands, 0);
+ ieee80211_add_channels_default_2ghz(chans, maxchans, nchans, bands, 0);
}
static void
@@ -1641,6 +1653,17 @@ fail:
}
static void
+urtw_update_promisc(struct ieee80211com *ic)
+{
+ struct urtw_softc *sc = ic->ic_softc;
+
+ URTW_LOCK(sc);
+ if (sc->sc_flags & URTW_RUNNING)
+ urtw_rx_setconf(sc);
+ URTW_UNLOCK(sc);
+}
+
+static void
urtw_update_mcast(struct ieee80211com *ic)
{
@@ -1694,11 +1717,7 @@ urtw_tx_start(struct urtw_softc *sc, struct ieee80211_node *ni, struct mbuf *m0,
if (ieee80211_radiotap_active_vap(vap)) {
struct urtw_tx_radiotap_header *tap = &sc->sc_txtap;
- /* XXX Are variables correct? */
tap->wt_flags = 0;
- tap->wt_chan_freq = htole16(ic->ic_curchan->ic_freq);
- tap->wt_chan_flags = htole16(ic->ic_curchan->ic_flags);
-
ieee80211_radiotap_tx(vap, m0);
}
@@ -1892,11 +1911,13 @@ static void
urtw_watchdog(void *arg)
{
struct urtw_softc *sc = arg;
+ struct ieee80211com *ic = &sc->sc_ic;
if (sc->sc_txtimer > 0) {
if (--sc->sc_txtimer == 0) {
device_printf(sc->sc_dev, "device timeout\n");
- counter_u64_add(sc->sc_ic.ic_oerrors, 1);
+ counter_u64_add(ic->ic_oerrors, 1);
+ ieee80211_restart_all(ic);
return;
}
callout_reset(&sc->sc_watchdog_ch, hz, urtw_watchdog, sc);
@@ -3179,6 +3200,8 @@ static usb_error_t
urtw_8225v2b_rf_init(struct urtw_softc *sc)
{
struct ieee80211com *ic = &sc->sc_ic;
+ struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
+ const uint8_t *macaddr;
unsigned int i;
uint8_t data8;
usb_error_t error;
@@ -3226,8 +3249,10 @@ urtw_8225v2b_rf_init(struct urtw_softc *sc)
urtw_write8_m(sc, URTW_CONFIG1, data8);
/* applying MAC address again. */
- urtw_write32_m(sc, URTW_MAC0, ((uint32_t *)ic->ic_macaddr)[0]);
- urtw_write16_m(sc, URTW_MAC4, ((uint32_t *)ic->ic_macaddr)[1] & 0xffff);
+ macaddr = vap ? vap->iv_myaddr : ic->ic_macaddr;
+ error = urtw_set_macaddr(sc, macaddr);
+ if (error)
+ goto fail;
error = urtw_set_mode(sc, URTW_EPROM_CMD_NORMAL);
if (error)
@@ -3887,7 +3912,6 @@ urtw_rx_setconf(struct urtw_softc *sc)
if (sc->sc_flags & URTW_RTL8187B) {
data = data | URTW_RX_FILTER_MNG | URTW_RX_FILTER_DATA |
URTW_RX_FILTER_MCAST | URTW_RX_FILTER_BCAST |
- URTW_RX_FILTER_NICMAC | URTW_RX_CHECK_BSSID |
URTW_RX_FIFO_THRESHOLD_NONE |
URTW_MAX_RX_DMA_2048 |
URTW_RX_AUTORESETPHY | URTW_RCR_ONLYERLPKT;
@@ -3902,14 +3926,6 @@ urtw_rx_setconf(struct urtw_softc *sc)
if (sc->sc_crcmon == 1 && ic->ic_opmode == IEEE80211_M_MONITOR)
data = data | URTW_RX_FILTER_CRCERR;
- if (ic->ic_opmode == IEEE80211_M_MONITOR ||
- ic->ic_promisc > 0 || ic->ic_allmulti > 0) {
- data = data | URTW_RX_FILTER_ALLMAC;
- } else {
- data = data | URTW_RX_FILTER_NICMAC;
- data = data | URTW_RX_CHECK_BSSID;
- }
-
data = data &~ URTW_RX_FIFO_THRESHOLD_MASK;
data = data | URTW_RX_FIFO_THRESHOLD_NONE |
URTW_RX_AUTORESETPHY;
@@ -3917,6 +3933,16 @@ urtw_rx_setconf(struct urtw_softc *sc)
data = data | URTW_MAX_RX_DMA_2048 | URTW_RCR_ONLYERLPKT;
}
+ /* XXX allmulti should not be checked here... */
+ if (ic->ic_opmode == IEEE80211_M_MONITOR ||
+ ic->ic_promisc > 0 || ic->ic_allmulti > 0) {
+ data = data | URTW_RX_FILTER_CTL;
+ data = data | URTW_RX_FILTER_ALLMAC;
+ } else {
+ data = data | URTW_RX_FILTER_NICMAC;
+ data = data | URTW_RX_CHECK_BSSID;
+ }
+
urtw_write32_m(sc, URTW_RX, data);
fail:
return (error);
@@ -3932,50 +3958,56 @@ urtw_rxeof(struct usb_xfer *xfer, struct urtw_data *data, int *rssi_p,
struct urtw_softc *sc = data->sc;
struct ieee80211com *ic = &sc->sc_ic;
uint8_t noise = 0, rate;
+ uint64_t mactime;
usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL);
- if (actlen < (int)URTW_MIN_RXBUFSZ) {
- counter_u64_add(ic->ic_ierrors, 1);
- return (NULL);
- }
-
if (sc->sc_flags & URTW_RTL8187B) {
struct urtw_8187b_rxhdr *rx;
+ if (actlen < sizeof(*rx) + IEEE80211_ACK_LEN)
+ goto fail;
+
rx = (struct urtw_8187b_rxhdr *)(data->buf +
(actlen - (sizeof(struct urtw_8187b_rxhdr))));
flen = le32toh(rx->flag) & 0xfff;
- if (flen > actlen) {
- counter_u64_add(ic->ic_ierrors, 1);
- return (NULL);
- }
+ if (flen > actlen - sizeof(*rx))
+ goto fail;
+
rate = (le32toh(rx->flag) >> URTW_RX_FLAG_RXRATE_SHIFT) & 0xf;
/* XXX correct? */
rssi = rx->rssi & URTW_RX_RSSI_MASK;
noise = rx->noise;
+
+ if (ieee80211_radiotap_active(ic))
+ mactime = rx->mactime;
} else {
struct urtw_8187l_rxhdr *rx;
+ if (actlen < sizeof(*rx) + IEEE80211_ACK_LEN)
+ goto fail;
+
rx = (struct urtw_8187l_rxhdr *)(data->buf +
(actlen - (sizeof(struct urtw_8187l_rxhdr))));
flen = le32toh(rx->flag) & 0xfff;
- if (flen > actlen) {
- counter_u64_add(ic->ic_ierrors, 1);
- return (NULL);
- }
+ if (flen > actlen - sizeof(*rx))
+ goto fail;
rate = (le32toh(rx->flag) >> URTW_RX_FLAG_RXRATE_SHIFT) & 0xf;
/* XXX correct? */
rssi = rx->rssi & URTW_RX_8187L_RSSI_MASK;
noise = rx->noise;
+
+ if (ieee80211_radiotap_active(ic))
+ mactime = rx->mactime;
}
+ if (flen < IEEE80211_ACK_LEN)
+ goto fail;
+
mnew = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
- if (mnew == NULL) {
- counter_u64_add(ic->ic_ierrors, 1);
- return (NULL);
- }
+ if (mnew == NULL)
+ goto fail;
m = data->m;
data->m = mnew;
@@ -3987,20 +4019,23 @@ urtw_rxeof(struct usb_xfer *xfer, struct urtw_data *data, int *rssi_p,
if (ieee80211_radiotap_active(ic)) {
struct urtw_rx_radiotap_header *tap = &sc->sc_rxtap;
- /* XXX Are variables correct? */
- tap->wr_chan_freq = htole16(ic->ic_curchan->ic_freq);
- tap->wr_chan_flags = htole16(ic->ic_curchan->ic_flags);
+ tap->wr_tsf = mactime;
+ tap->wr_flags = 0;
tap->wr_dbm_antsignal = (int8_t)rssi;
}
wh = mtod(m, struct ieee80211_frame *);
- if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == IEEE80211_FC0_TYPE_DATA)
+ if (IEEE80211_IS_DATA(wh))
sc->sc_currate = (rate > 0) ? rate : sc->sc_currate;
*rssi_p = rssi;
*nf_p = noise; /* XXX correct? */
return (m);
+
+fail:
+ counter_u64_add(ic->ic_ierrors, 1);
+ return (NULL);
}
static void
@@ -4008,7 +4043,6 @@ urtw_bulk_rx_callback(struct usb_xfer *xfer, usb_error_t error)
{
struct urtw_softc *sc = usbd_xfer_softc(xfer);
struct ieee80211com *ic = &sc->sc_ic;
- struct ieee80211_frame *wh;
struct ieee80211_node *ni;
struct mbuf *m = NULL;
struct urtw_data *data;
@@ -4046,9 +4080,13 @@ setup:
*/
URTW_UNLOCK(sc);
if (m != NULL) {
- wh = mtod(m, struct ieee80211_frame *);
- ni = ieee80211_find_rxnode(ic,
- (struct ieee80211_frame_min *)wh);
+ if (m->m_pkthdr.len >=
+ sizeof(struct ieee80211_frame_min)) {
+ ni = ieee80211_find_rxnode(ic,
+ mtod(m, struct ieee80211_frame_min *));
+ } else
+ ni = NULL;
+
if (ni != NULL) {
(void) ieee80211_input(ni, m, rssi, nf);
/* node is no longer needed */