summaryrefslogtreecommitdiffstats
path: root/sys/dev/wi/if_wi.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/wi/if_wi.c')
-rw-r--r--sys/dev/wi/if_wi.c382
1 files changed, 146 insertions, 236 deletions
diff --git a/sys/dev/wi/if_wi.c b/sys/dev/wi/if_wi.c
index b316d46..f8af231 100644
--- a/sys/dev/wi/if_wi.c
+++ b/sys/dev/wi/if_wi.c
@@ -116,11 +116,9 @@ static struct ieee80211vap *wi_vap_create(struct ieee80211com *,
const uint8_t [IEEE80211_ADDR_LEN],
const uint8_t [IEEE80211_ADDR_LEN]);
static void wi_vap_delete(struct ieee80211vap *vap);
-static void wi_stop_locked(struct wi_softc *sc, int disable);
-static void wi_start_locked(struct ifnet *);
-static void wi_start(struct ifnet *);
-static int wi_start_tx(struct ifnet *ifp, struct wi_frame *frmhdr,
- struct mbuf *m0);
+static int wi_transmit(struct ieee80211com *, struct mbuf *);
+static void wi_start(struct wi_softc *);
+static int wi_start_tx(struct wi_softc *, struct wi_frame *, struct mbuf *);
static int wi_raw_xmit(struct ieee80211_node *, struct mbuf *,
const struct ieee80211_bpf_params *);
static int wi_newstate_sta(struct ieee80211vap *, enum ieee80211_state, int);
@@ -131,10 +129,8 @@ static void wi_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m,
int rssi, int nf);
static int wi_reset(struct wi_softc *);
static void wi_watchdog(void *);
-static int wi_ioctl(struct ifnet *, u_long, caddr_t);
+static void wi_parent(struct ieee80211com *);
static void wi_media_status(struct ifnet *, struct ifmediareq *);
-static uint64_t wi_get_counter(struct ifnet *, ift_counter);
-
static void wi_rx_intr(struct wi_softc *);
static void wi_tx_intr(struct wi_softc *);
static void wi_tx_ex_intr(struct wi_softc *);
@@ -153,10 +149,10 @@ static int wi_write_ssid(struct wi_softc *, int, u_int8_t *, int);
static int wi_cmd(struct wi_softc *, int, int, int, int);
static int wi_seek_bap(struct wi_softc *, int, int);
static int wi_read_bap(struct wi_softc *, int, int, void *, int);
-static int wi_write_bap(struct wi_softc *, int, int, void *, int);
+static int wi_write_bap(struct wi_softc *, int, int, const void *, int);
static int wi_mwrite_bap(struct wi_softc *, int, int, struct mbuf *, int);
static int wi_read_rid(struct wi_softc *, int, void *, int *);
-static int wi_write_rid(struct wi_softc *, int, void *, int);
+static int wi_write_rid(struct wi_softc *, int, const void *, int);
static int wi_write_appie(struct wi_softc *, int, const struct ieee80211_appie *);
static void wi_scan_start(struct ieee80211com *);
@@ -237,8 +233,7 @@ int
wi_attach(device_t dev)
{
struct wi_softc *sc = device_get_softc(dev);
- struct ieee80211com *ic;
- struct ifnet *ifp;
+ struct ieee80211com *ic = &sc->sc_ic;
int i, nrates, buflen;
u_int16_t val;
u_int8_t ratebuf[2 + IEEE80211_RATE_SIZE];
@@ -249,15 +244,6 @@ wi_attach(device_t dev)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
int error;
- uint8_t macaddr[IEEE80211_ADDR_LEN];
-
- ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
- if (ifp == NULL) {
- device_printf(dev, "can not if_alloc\n");
- wi_free(dev);
- return ENOSPC;
- }
- ic = ifp->if_l2com;
sc->sc_firmware_type = WI_NOTYPE;
sc->wi_cmd_count = 500;
@@ -309,6 +295,7 @@ wi_attach(device_t dev)
mtx_init(&sc->sc_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK,
MTX_DEF | MTX_RECURSE);
callout_init_mtx(&sc->sc_watchdog, &sc->sc_mtx, 0);
+ mbufq_init(&sc->sc_snd, ifqmaxlen);
/*
* Read the station address.
@@ -317,12 +304,13 @@ wi_attach(device_t dev)
* the probe to fail.
*/
buflen = IEEE80211_ADDR_LEN;
- error = wi_read_rid(sc, WI_RID_MAC_NODE, macaddr, &buflen);
+ error = wi_read_rid(sc, WI_RID_MAC_NODE, &ic->ic_macaddr, &buflen);
if (error != 0) {
buflen = IEEE80211_ADDR_LEN;
- error = wi_read_rid(sc, WI_RID_MAC_NODE, macaddr, &buflen);
+ error = wi_read_rid(sc, WI_RID_MAC_NODE, &ic->ic_macaddr,
+ &buflen);
}
- if (error || IEEE80211_ADDR_EQ(macaddr, empty_macaddr)) {
+ if (error || IEEE80211_ADDR_EQ(&ic->ic_macaddr, empty_macaddr)) {
if (error != 0)
device_printf(dev, "mac read failed %d\n", error);
else {
@@ -333,18 +321,6 @@ wi_attach(device_t dev)
return (error);
}
- ifp->if_softc = sc;
- if_initname(ifp, device_get_name(dev), device_get_unit(dev));
- ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
- ifp->if_ioctl = wi_ioctl;
- ifp->if_start = wi_start;
- ifp->if_init = wi_init;
- ifp->if_get_counter = wi_get_counter;
- IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
- ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
- IFQ_SET_READY(&ifp->if_snd);
-
- ic->ic_ifp = ifp;
ic->ic_softc = sc;
ic->ic_name = device_get_nameunit(dev);
ic->ic_phytype = IEEE80211_T_DS;
@@ -458,16 +434,17 @@ wi_attach(device_t dev)
sc->sc_portnum = WI_DEFAULT_PORT;
- ieee80211_ifattach(ic, macaddr);
+ ieee80211_ifattach(ic);
ic->ic_raw_xmit = wi_raw_xmit;
ic->ic_scan_start = wi_scan_start;
ic->ic_scan_end = wi_scan_end;
ic->ic_set_channel = wi_set_channel;
-
ic->ic_vap_create = wi_vap_create;
ic->ic_vap_delete = wi_vap_delete;
ic->ic_update_mcast = wi_update_mcast;
ic->ic_update_promisc = wi_update_promisc;
+ ic->ic_transmit = wi_transmit;
+ ic->ic_parent = wi_parent;
ieee80211_radiotap_attach(ic,
&sc->sc_tx_th.wt_ihdr, sizeof(sc->sc_tx_th),
@@ -483,7 +460,6 @@ wi_attach(device_t dev)
if (error) {
device_printf(dev, "bus_setup_intr() failed! (%d)\n", error);
ieee80211_ifdetach(ic);
- if_free(sc->sc_ifp);
wi_free(dev);
return error;
}
@@ -495,21 +471,20 @@ int
wi_detach(device_t dev)
{
struct wi_softc *sc = device_get_softc(dev);
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
WI_LOCK(sc);
/* check if device was removed */
sc->wi_gone |= !bus_child_present(dev);
- wi_stop_locked(sc, 0);
+ wi_stop(sc, 0);
WI_UNLOCK(sc);
ieee80211_ifdetach(ic);
bus_teardown_intr(dev, sc->irq, sc->wi_intrhand);
- if_free(sc->sc_ifp);
wi_free(dev);
+ mbufq_drain(&sc->sc_snd);
mtx_destroy(&sc->sc_mtx);
return (0);
}
@@ -520,19 +495,16 @@ wi_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
const uint8_t bssid[IEEE80211_ADDR_LEN],
const uint8_t mac[IEEE80211_ADDR_LEN])
{
- struct wi_softc *sc = ic->ic_ifp->if_softc;
+ struct wi_softc *sc = ic->ic_softc;
struct wi_vap *wvp;
struct ieee80211vap *vap;
if (!TAILQ_EMPTY(&ic->ic_vaps)) /* only one at a time */
return NULL;
- wvp = (struct wi_vap *) malloc(sizeof(struct wi_vap),
- M_80211_VAP, M_NOWAIT | M_ZERO);
- if (wvp == NULL)
- return NULL;
+ wvp = malloc(sizeof(struct wi_vap), M_80211_VAP, M_WAITOK | M_ZERO);
vap = &wvp->wv_vap;
- ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid, mac);
+ ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid);
vap->iv_max_aid = WI_MAX_AID;
@@ -566,7 +538,7 @@ wi_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
}
/* complete setup */
- ieee80211_vap_attach(vap, ieee80211_media_change, wi_media_status);
+ ieee80211_vap_attach(vap, ieee80211_media_change, wi_media_status, mac);
ic->ic_opmode = opmode;
return vap;
}
@@ -585,7 +557,9 @@ wi_shutdown(device_t dev)
{
struct wi_softc *sc = device_get_softc(dev);
+ WI_LOCK(sc);
wi_stop(sc, 1);
+ WI_UNLOCK(sc);
return (0);
}
@@ -593,12 +567,12 @@ void
wi_intr(void *arg)
{
struct wi_softc *sc = arg;
- struct ifnet *ifp = sc->sc_ifp;
u_int16_t status;
WI_LOCK(sc);
- if (sc->wi_gone || !sc->sc_enabled || (ifp->if_flags & IFF_UP) == 0) {
+ if (sc->wi_gone || !sc->sc_enabled ||
+ (sc->sc_flags & WI_FLAGS_RUNNING) == 0) {
CSR_WRITE_2(sc, WI_INT_EN, 0);
CSR_WRITE_2(sc, WI_EVENT_ACK, 0xFFFF);
WI_UNLOCK(sc);
@@ -617,9 +591,8 @@ wi_intr(void *arg)
wi_tx_ex_intr(sc);
if (status & WI_EV_INFO)
wi_info_intr(sc);
- if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0 &&
- !IFQ_DRV_IS_EMPTY(&ifp->if_snd))
- wi_start_locked(ifp);
+ if (mbufq_first(&sc->sc_snd) != NULL)
+ wi_start(sc);
/* Re-enable interrupts. */
CSR_WRITE_2(sc, WI_INT_EN, WI_INTRS);
@@ -642,7 +615,7 @@ wi_enable(struct wi_softc *sc)
static int
wi_setup_locked(struct wi_softc *sc, int porttype, int mode,
- uint8_t mac[IEEE80211_ADDR_LEN])
+ const uint8_t mac[IEEE80211_ADDR_LEN])
{
int i;
@@ -676,26 +649,25 @@ wi_setup_locked(struct wi_softc *sc, int porttype, int mode,
return 0;
}
-static void
-wi_init_locked(struct wi_softc *sc)
+void
+wi_init(struct wi_softc *sc)
{
- struct ifnet *ifp = sc->sc_ifp;
int wasenabled;
WI_LOCK_ASSERT(sc);
wasenabled = sc->sc_enabled;
if (wasenabled)
- wi_stop_locked(sc, 1);
+ wi_stop(sc, 1);
- if (wi_setup_locked(sc, sc->sc_porttype, 3, IF_LLADDR(ifp)) != 0) {
- if_printf(ifp, "interface not running\n");
- wi_stop_locked(sc, 1);
+ if (wi_setup_locked(sc, sc->sc_porttype, 3,
+ sc->sc_ic.ic_macaddr) != 0) {
+ device_printf(sc->sc_dev, "interface not running\n");
+ wi_stop(sc, 1);
return;
}
- ifp->if_drv_flags |= IFF_DRV_RUNNING;
- ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
+ sc->sc_flags |= WI_FLAGS_RUNNING;
callout_reset(&sc->sc_watchdog, hz, wi_watchdog, sc);
@@ -703,24 +675,8 @@ wi_init_locked(struct wi_softc *sc)
}
void
-wi_init(void *arg)
-{
- struct wi_softc *sc = arg;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
-
- WI_LOCK(sc);
- wi_init_locked(sc);
- WI_UNLOCK(sc);
-
- if (ifp->if_drv_flags & IFF_DRV_RUNNING)
- ieee80211_start_all(ic); /* start all vap's */
-}
-
-static void
-wi_stop_locked(struct wi_softc *sc, int disable)
+wi_stop(struct wi_softc *sc, int disable)
{
- struct ifnet *ifp = sc->sc_ifp;
WI_LOCK_ASSERT(sc);
@@ -736,22 +692,13 @@ wi_stop_locked(struct wi_softc *sc, int disable)
sc->sc_tx_timer = 0;
sc->sc_false_syns = 0;
- ifp->if_drv_flags &= ~(IFF_DRV_OACTIVE | IFF_DRV_RUNNING);
-}
-
-void
-wi_stop(struct wi_softc *sc, int disable)
-{
- WI_LOCK(sc);
- wi_stop_locked(sc, disable);
- WI_UNLOCK(sc);
+ sc->sc_flags &= ~WI_FLAGS_RUNNING;
}
static void
wi_set_channel(struct ieee80211com *ic)
{
- struct ifnet *ifp = ic->ic_ifp;
- struct wi_softc *sc = ifp->if_softc;
+ struct wi_softc *sc = ic->ic_softc;
DPRINTF(("%s: channel %d, %sscanning\n", __func__,
ieee80211_chan2ieee(ic, ic->ic_curchan),
@@ -766,8 +713,7 @@ wi_set_channel(struct ieee80211com *ic)
static void
wi_scan_start(struct ieee80211com *ic)
{
- struct ifnet *ifp = ic->ic_ifp;
- struct wi_softc *sc = ifp->if_softc;
+ struct wi_softc *sc = ic->ic_softc;
struct ieee80211_scan_state *ss = ic->ic_scan;
DPRINTF(("%s\n", __func__));
@@ -790,8 +736,7 @@ wi_scan_start(struct ieee80211com *ic)
static void
wi_scan_end(struct ieee80211com *ic)
{
- struct ifnet *ifp = ic->ic_ifp;
- struct wi_softc *sc = ifp->if_softc;
+ struct wi_softc *sc = ic->ic_softc;
DPRINTF(("%s: restore port type %d\n", __func__, sc->sc_porttype));
@@ -824,9 +769,8 @@ static int
wi_newstate_sta(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
{
struct ieee80211com *ic = vap->iv_ic;
- struct ifnet *ifp = ic->ic_ifp;
struct ieee80211_node *bss;
- struct wi_softc *sc = ifp->if_softc;
+ struct wi_softc *sc = ic->ic_softc;
DPRINTF(("%s: %s -> %s\n", __func__,
ieee80211_state_name[vap->iv_state],
@@ -894,9 +838,8 @@ static int
wi_newstate_hostap(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
{
struct ieee80211com *ic = vap->iv_ic;
- struct ifnet *ifp = ic->ic_ifp;
struct ieee80211_node *bss;
- struct wi_softc *sc = ifp->if_softc;
+ struct wi_softc *sc = ic->ic_softc;
int error;
DPRINTF(("%s: %s -> %s\n", __func__,
@@ -953,10 +896,30 @@ wi_newstate_hostap(struct ieee80211vap *vap, enum ieee80211_state nstate, int ar
return error;
}
+static int
+wi_transmit(struct ieee80211com *ic, struct mbuf *m)
+{
+ struct wi_softc *sc = ic->ic_softc;
+ int error;
+
+ WI_LOCK(sc);
+ if ((sc->sc_flags & WI_FLAGS_RUNNING) == 0) {
+ WI_UNLOCK(sc);
+ return (ENXIO);
+ }
+ error = mbufq_enqueue(&sc->sc_snd, m);
+ if (error) {
+ WI_UNLOCK(sc);
+ return (error);
+ }
+ wi_start(sc);
+ WI_UNLOCK(sc);
+ return (0);
+}
+
static void
-wi_start_locked(struct ifnet *ifp)
+wi_start(struct wi_softc *sc)
{
- struct wi_softc *sc = ifp->if_softc;
struct ieee80211_node *ni;
struct ieee80211_frame *wh;
struct mbuf *m0;
@@ -972,15 +935,8 @@ wi_start_locked(struct ifnet *ifp)
memset(&frmhdr, 0, sizeof(frmhdr));
cur = sc->sc_txnext;
- for (;;) {
- IFQ_DRV_DEQUEUE(&ifp->if_snd, m0);
- if (m0 == NULL)
- break;
- if (sc->sc_txd[cur].d_len != 0) {
- IFQ_DRV_PREPEND(&ifp->if_snd, m0);
- ifp->if_drv_flags |= IFF_DRV_OACTIVE;
- break;
- }
+ while (sc->sc_txd[cur].d_len == 0 &&
+ (m0 = mbufq_dequeue(&sc->sc_snd)) != NULL) {
ni = (struct ieee80211_node *) m0->m_pkthdr.rcvif;
/* reconstruct 802.3 header */
@@ -1029,28 +985,16 @@ wi_start_locked(struct ifnet *ifp)
m_adj(m0, sizeof(struct ieee80211_frame));
frmhdr.wi_dat_len = htole16(m0->m_pkthdr.len);
ieee80211_free_node(ni);
- if (wi_start_tx(ifp, &frmhdr, m0))
+ if (wi_start_tx(sc, &frmhdr, m0))
continue;
sc->sc_txnext = cur = (cur + 1) % sc->sc_ntxbuf;
- if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
}
}
-static void
-wi_start(struct ifnet *ifp)
-{
- struct wi_softc *sc = ifp->if_softc;
-
- WI_LOCK(sc);
- wi_start_locked(ifp);
- WI_UNLOCK(sc);
-}
-
static int
-wi_start_tx(struct ifnet *ifp, struct wi_frame *frmhdr, struct mbuf *m0)
+wi_start_tx(struct wi_softc *sc, struct wi_frame *frmhdr, struct mbuf *m0)
{
- struct wi_softc *sc = ifp->if_softc;
int cur = sc->sc_txnext;
int fid, off, error;
@@ -1060,13 +1004,13 @@ wi_start_tx(struct ifnet *ifp, struct wi_frame *frmhdr, struct mbuf *m0)
|| wi_mwrite_bap(sc, fid, off, m0, m0->m_pkthdr.len) != 0;
m_freem(m0);
if (error) {
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
+ counter_u64_add(sc->sc_ic.ic_oerrors, 1);
return -1;
}
sc->sc_txd[cur].d_len = off;
if (sc->sc_txcur == cur) {
if (wi_cmd(sc, WI_CMD_TX | WI_RECLAIM, fid, 0, 0)) {
- if_printf(ifp, "xmit failed\n");
+ device_printf(sc->sc_dev, "xmit failed\n");
sc->sc_txd[cur].d_len = 0;
return -1;
}
@@ -1080,9 +1024,8 @@ wi_raw_xmit(struct ieee80211_node *ni, struct mbuf *m0,
const struct ieee80211_bpf_params *params)
{
struct ieee80211com *ic = ni->ni_ic;
- struct ifnet *ifp = ic->ic_ifp;
struct ieee80211vap *vap = ni->ni_vap;
- struct wi_softc *sc = ifp->if_softc;
+ struct wi_softc *sc = ic->ic_softc;
struct ieee80211_key *k;
struct ieee80211_frame *wh;
struct wi_frame frmhdr;
@@ -1098,7 +1041,6 @@ wi_raw_xmit(struct ieee80211_node *ni, struct mbuf *m0,
memset(&frmhdr, 0, sizeof(frmhdr));
cur = sc->sc_txnext;
if (sc->sc_txd[cur].d_len != 0) {
- ifp->if_drv_flags |= IFF_DRV_OACTIVE;
rc = ENOBUFS;
goto out;
}
@@ -1129,7 +1071,7 @@ wi_raw_xmit(struct ieee80211_node *ni, struct mbuf *m0,
(caddr_t)&frmhdr.wi_whdr);
m_adj(m0, sizeof(struct ieee80211_frame));
frmhdr.wi_dat_len = htole16(m0->m_pkthdr.len);
- if (wi_start_tx(ifp, &frmhdr, m0) < 0) {
+ if (wi_start_tx(sc, &frmhdr, m0) < 0) {
m0 = NULL;
rc = EIO;
goto out;
@@ -1160,7 +1102,7 @@ wi_reset(struct wi_softc *sc)
}
sc->sc_reset = 1;
if (i == WI_INIT_TRIES) {
- if_printf(sc->sc_ifp, "reset failed\n");
+ device_printf(sc->sc_dev, "reset failed\n");
return error;
}
@@ -1178,7 +1120,6 @@ static void
wi_watchdog(void *arg)
{
struct wi_softc *sc = arg;
- struct ifnet *ifp = sc->sc_ifp;
WI_LOCK_ASSERT(sc);
@@ -1186,65 +1127,52 @@ wi_watchdog(void *arg)
return;
if (sc->sc_tx_timer && --sc->sc_tx_timer == 0) {
- if_printf(ifp, "device timeout\n");
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
- wi_init_locked(ifp->if_softc);
+ device_printf(sc->sc_dev, "device timeout\n");
+ counter_u64_add(sc->sc_ic.ic_oerrors, 1);
+ wi_init(sc);
return;
}
callout_reset(&sc->sc_watchdog, hz, wi_watchdog, sc);
}
-static int
-wi_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
+static void
+wi_parent(struct ieee80211com *ic)
{
- struct wi_softc *sc = ifp->if_softc;
- struct ieee80211com *ic = ifp->if_l2com;
- struct ifreq *ifr = (struct ifreq *) data;
- int error = 0, startall = 0;
+ struct wi_softc *sc = ic->ic_softc;
+ int startall = 0;
- switch (cmd) {
- case SIOCSIFFLAGS:
- WI_LOCK(sc);
- /*
- * Can't do promisc and hostap at the same time. If all that's
- * changing is the promisc flag, try to short-circuit a call to
- * wi_init() by just setting PROMISC in the hardware.
- */
- if (ifp->if_flags & IFF_UP) {
- if (ic->ic_opmode != IEEE80211_M_HOSTAP &&
- ifp->if_drv_flags & IFF_DRV_RUNNING) {
- if ((ifp->if_flags ^ sc->sc_if_flags) & IFF_PROMISC) {
- wi_write_val(sc, WI_RID_PROMISC,
- (ifp->if_flags & IFF_PROMISC) != 0);
- } else {
- wi_init_locked(sc);
- startall = 1;
- }
+ WI_LOCK(sc);
+ /*
+ * Can't do promisc and hostap at the same time. If all that's
+ * changing is the promisc flag, try to short-circuit a call to
+ * wi_init() by just setting PROMISC in the hardware.
+ */
+ if (ic->ic_nrunning > 0) {
+ if (ic->ic_opmode != IEEE80211_M_HOSTAP &&
+ sc->sc_flags & WI_FLAGS_RUNNING) {
+ if (ic->ic_promisc > 0 &&
+ (sc->sc_flags & WI_FLAGS_PROMISC) == 0) {
+ wi_write_val(sc, WI_RID_PROMISC, 1);
+ sc->sc_flags |= WI_FLAGS_PROMISC;
+ } else if (ic->ic_promisc == 0 &&
+ (sc->sc_flags & WI_FLAGS_PROMISC) != 0) {
+ wi_write_val(sc, WI_RID_PROMISC, 0);
+ sc->sc_flags &= ~WI_FLAGS_PROMISC;
} else {
- wi_init_locked(sc);
+ wi_init(sc);
startall = 1;
}
} else {
- if (ifp->if_drv_flags & IFF_DRV_RUNNING)
- wi_stop_locked(sc, 1);
- sc->wi_gone = 0;
+ wi_init(sc);
+ startall = 1;
}
- sc->sc_if_flags = ifp->if_flags;
- WI_UNLOCK(sc);
- if (startall)
- ieee80211_start_all(ic);
- break;
- case SIOCGIFMEDIA:
- error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);
- break;
- case SIOCGIFADDR:
- error = ether_ioctl(ifp, cmd, data);
- break;
- default:
- error = EINVAL;
- break;
+ } else if (sc->sc_flags & WI_FLAGS_RUNNING) {
+ wi_stop(sc, 1);
+ sc->wi_gone = 0;
}
- return error;
+ WI_UNLOCK(sc);
+ if (startall)
+ ieee80211_start_all(ic);
}
static void
@@ -1252,7 +1180,7 @@ wi_media_status(struct ifnet *ifp, struct ifmediareq *imr)
{
struct ieee80211vap *vap = ifp->if_softc;
struct ieee80211com *ic = vap->iv_ic;
- struct wi_softc *sc = ic->ic_ifp->if_softc;
+ struct wi_softc *sc = ic->ic_softc;
u_int16_t val;
int rate, len;
@@ -1280,8 +1208,7 @@ wi_media_status(struct ifnet *ifp, struct ifmediareq *imr)
static void
wi_sync_bssid(struct wi_softc *sc, u_int8_t new_bssid[IEEE80211_ADDR_LEN])
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
struct ieee80211_node *ni = vap->iv_bss;
@@ -1295,7 +1222,7 @@ wi_sync_bssid(struct wi_softc *sc, u_int8_t new_bssid[IEEE80211_ADDR_LEN])
* indicator of the firmware's BSSID. Damp spurious
* change-of-BSSID indications.
*/
- if ((ifp->if_flags & IFF_PROMISC) != 0 &&
+ if (ic->ic_promisc > 0 &&
!ppsratecheck(&sc->sc_last_syn, &sc->sc_false_syns,
WI_MAX_FALSE_SYNS))
return;
@@ -1316,8 +1243,7 @@ wi_sync_bssid(struct wi_softc *sc, u_int8_t new_bssid[IEEE80211_ADDR_LEN])
static __noinline void
wi_rx_intr(struct wi_softc *sc)
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct wi_frame frmhdr;
struct mbuf *m;
struct ieee80211_frame *wh;
@@ -1332,7 +1258,7 @@ wi_rx_intr(struct wi_softc *sc)
/* First read in the frame header */
if (wi_read_bap(sc, fid, 0, &frmhdr, sizeof(frmhdr))) {
CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX);
- if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
+ counter_u64_add(ic->ic_ierrors, 1);
DPRINTF(("wi_rx_intr: read fid %x failed\n", fid));
return;
}
@@ -1343,7 +1269,7 @@ wi_rx_intr(struct wi_softc *sc)
status = le16toh(frmhdr.wi_status);
if (status & WI_STAT_ERRSTAT) {
CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX);
- if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
+ counter_u64_add(ic->ic_ierrors, 1);
DPRINTF(("wi_rx_intr: fid %x error status %x\n", fid, status));
return;
}
@@ -1358,7 +1284,7 @@ wi_rx_intr(struct wi_softc *sc)
if (off + len > MCLBYTES) {
if (ic->ic_opmode != IEEE80211_M_MONITOR) {
CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX);
- if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
+ counter_u64_add(ic->ic_ierrors, 1);
DPRINTF(("wi_rx_intr: oversized packet\n"));
return;
} else
@@ -1371,7 +1297,7 @@ wi_rx_intr(struct wi_softc *sc)
m = m_gethdr(M_NOWAIT, MT_DATA);
if (m == NULL) {
CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX);
- if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
+ counter_u64_add(ic->ic_ierrors, 1);
DPRINTF(("wi_rx_intr: MGET failed\n"));
return;
}
@@ -1380,7 +1306,6 @@ wi_rx_intr(struct wi_softc *sc)
wi_read_bap(sc, fid, sizeof(frmhdr),
m->m_data + sizeof(struct ieee80211_frame), len);
m->m_pkthdr.len = m->m_len = sizeof(struct ieee80211_frame) + len;
- m->m_pkthdr.rcvif = ifp;
CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX);
@@ -1425,7 +1350,6 @@ wi_rx_intr(struct wi_softc *sc)
static __noinline void
wi_tx_ex_intr(struct wi_softc *sc)
{
- struct ifnet *ifp = sc->sc_ifp;
struct wi_frame frmhdr;
int fid;
@@ -1440,7 +1364,7 @@ wi_tx_ex_intr(struct wi_softc *sc)
*/
if ((status & WI_TXSTAT_DISCONNECT) == 0) {
if (ppsratecheck(&lasttxerror, &curtxeps, wi_txerate)) {
- if_printf(ifp, "tx failed");
+ device_printf(sc->sc_dev, "tx failed");
if (status & WI_TXSTAT_RET_ERR)
printf(", retry limit exceeded");
if (status & WI_TXSTAT_AGED_ERR)
@@ -1455,7 +1379,7 @@ wi_tx_ex_intr(struct wi_softc *sc)
printf(", status=0x%x", status);
printf("\n");
}
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
+ counter_u64_add(sc->sc_ic.ic_oerrors, 1);
} else
DPRINTF(("port disconnected\n"));
} else
@@ -1466,7 +1390,6 @@ wi_tx_ex_intr(struct wi_softc *sc)
static __noinline void
wi_tx_intr(struct wi_softc *sc)
{
- struct ifnet *ifp = sc->sc_ifp;
int fid, cur;
if (sc->wi_gone)
@@ -1477,19 +1400,17 @@ wi_tx_intr(struct wi_softc *sc)
cur = sc->sc_txcur;
if (sc->sc_txd[cur].d_fid != fid) {
- if_printf(ifp, "bad alloc %x != %x, cur %d nxt %d\n",
+ device_printf(sc->sc_dev, "bad alloc %x != %x, cur %d nxt %d\n",
fid, sc->sc_txd[cur].d_fid, cur, sc->sc_txnext);
return;
}
sc->sc_tx_timer = 0;
sc->sc_txd[cur].d_len = 0;
sc->sc_txcur = cur = (cur + 1) % sc->sc_ntxbuf;
- if (sc->sc_txd[cur].d_len == 0)
- ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
- else {
+ if (sc->sc_txd[cur].d_len != 0) {
if (wi_cmd(sc, WI_CMD_TX | WI_RECLAIM, sc->sc_txd[cur].d_fid,
0, 0)) {
- if_printf(ifp, "xmit failed\n");
+ device_printf(sc->sc_dev, "xmit failed\n");
sc->sc_txd[cur].d_len = 0;
} else {
sc->sc_tx_timer = 5;
@@ -1500,7 +1421,7 @@ wi_tx_intr(struct wi_softc *sc)
static __noinline void
wi_info_intr(struct wi_softc *sc)
{
- struct ieee80211com *ic = sc->sc_ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
int i, fid, len, off;
u_int16_t ltbuf[2];
@@ -1574,32 +1495,15 @@ finish:
CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_INFO);
}
-static uint64_t
-wi_get_counter(struct ifnet *ifp, ift_counter cnt)
-{
- struct wi_softc *sc;
-
- sc = if_getsoftc(ifp);
-
- switch (cnt) {
- case IFCOUNTER_COLLISIONS:
- return (sc->sc_stats.wi_tx_single_retries +
- sc->sc_stats.wi_tx_multi_retries +
- sc->sc_stats.wi_tx_retry_limit);
- default:
- return (if_get_counter_default(ifp, cnt));
- }
-}
-
static int
wi_write_multi(struct wi_softc *sc)
{
- struct ifnet *ifp = sc->sc_ifp;
- int n;
- struct ifmultiaddr *ifma;
+ struct ieee80211com *ic = &sc->sc_ic;
+ struct ieee80211vap *vap;
struct wi_mcast mlist;
+ int n;
- if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) {
+ if (ic->ic_allmulti > 0 || ic->ic_promisc > 0) {
allmulti:
memset(&mlist, 0, sizeof(mlist));
return wi_write_rid(sc, WI_RID_MCAST_LIST, &mlist,
@@ -1607,17 +1511,23 @@ allmulti:
}
n = 0;
- if_maddr_rlock(ifp);
- TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
- if (ifma->ifma_addr->sa_family != AF_LINK)
- continue;
- if (n >= 16)
- goto allmulti;
- IEEE80211_ADDR_COPY(&mlist.wi_mcast[n],
- (LLADDR((struct sockaddr_dl *)ifma->ifma_addr)));
- n++;
+ TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) {
+ struct ifnet *ifp;
+ struct ifmultiaddr *ifma;
+
+ ifp = vap->iv_ifp;
+ if_maddr_rlock(ifp);
+ TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
+ if (ifma->ifma_addr->sa_family != AF_LINK)
+ continue;
+ if (n >= 16)
+ goto allmulti;
+ IEEE80211_ADDR_COPY(&mlist.wi_mcast[n],
+ (LLADDR((struct sockaddr_dl *)ifma->ifma_addr)));
+ n++;
+ }
+ if_maddr_runlock(ifp);
}
- if_maddr_runlock(ifp);
return wi_write_rid(sc, WI_RID_MCAST_LIST, &mlist,
IEEE80211_ADDR_LEN * n);
}
@@ -1638,7 +1548,7 @@ wi_update_promisc(struct ieee80211com *ic)
/* XXX handle WEP special case handling? */
wi_write_val(sc, WI_RID_PROMISC,
(ic->ic_opmode == IEEE80211_M_MONITOR ||
- (ic->ic_ifp->if_flags & IFF_PROMISC)));
+ (ic->ic_promisc > 0)));
WI_UNLOCK(sc);
}
@@ -1937,7 +1847,7 @@ wi_read_bap(struct wi_softc *sc, int id, int off, void *buf, int buflen)
}
static int
-wi_write_bap(struct wi_softc *sc, int id, int off, void *buf, int buflen)
+wi_write_bap(struct wi_softc *sc, int id, int off, const void *buf, int buflen)
{
int error, cnt;
@@ -1949,7 +1859,7 @@ wi_write_bap(struct wi_softc *sc, int id, int off, void *buf, int buflen)
return error;
}
cnt = (buflen + 1) / 2;
- CSR_WRITE_MULTI_STREAM_2(sc, WI_DATA0, (u_int16_t *)buf, cnt);
+ CSR_WRITE_MULTI_STREAM_2(sc, WI_DATA0, (const uint16_t *)buf, cnt);
sc->sc_bap_off += cnt * 2;
return 0;
@@ -2039,7 +1949,7 @@ wi_read_rid(struct wi_softc *sc, int rid, void *buf, int *buflenp)
}
static int
-wi_write_rid(struct wi_softc *sc, int rid, void *buf, int buflen)
+wi_write_rid(struct wi_softc *sc, int rid, const void *buf, int buflen)
{
int error;
u_int16_t ltbuf[2];
OpenPOWER on IntegriCloud