aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/wi
diff options
context:
space:
mode:
authorAdrian Chadd <adrian@FreeBSD.org>2015-08-08 01:10:17 +0000
committerAdrian Chadd <adrian@FreeBSD.org>2015-08-08 01:10:17 +0000
commitba2c1fbc03f312b978f76f7b6c67eec6afa80bf8 (patch)
tree5973a9059f73ed5abf84d6d98e44f1953e764064 /sys/dev/wi
parent721b581722c3a383f02036d009db4473590e3f88 (diff)
downloadsrc-ba2c1fbc03f312b978f76f7b6c67eec6afa80bf8.tar.gz
src-ba2c1fbc03f312b978f76f7b6c67eec6afa80bf8.zip
Revert the wifi ifnet changes until things are more baked and tested.
* 286410 * 286413 * 286416 The initial commit broke a variety of debug and features that aren't in the GENERIC kernels but are enabled in other platforms.
Notes
Notes: svn path=/head/; revision=286437
Diffstat (limited to 'sys/dev/wi')
-rw-r--r--sys/dev/wi/if_wi.c382
-rw-r--r--sys/dev/wi/if_wi_pccard.c1
-rw-r--r--sys/dev/wi/if_wi_pci.c17
-rw-r--r--sys/dev/wi/if_wivar.h8
4 files changed, 247 insertions, 161 deletions
diff --git a/sys/dev/wi/if_wi.c b/sys/dev/wi/if_wi.c
index f8af23138340..b316d46dae74 100644
--- a/sys/dev/wi/if_wi.c
+++ b/sys/dev/wi/if_wi.c
@@ -116,9 +116,11 @@ 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 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 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_raw_xmit(struct ieee80211_node *, struct mbuf *,
const struct ieee80211_bpf_params *);
static int wi_newstate_sta(struct ieee80211vap *, enum ieee80211_state, int);
@@ -129,8 +131,10 @@ 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 void wi_parent(struct ieee80211com *);
+static int wi_ioctl(struct ifnet *, u_long, caddr_t);
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 *);
@@ -149,10 +153,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, const void *, int);
+static int wi_write_bap(struct wi_softc *, int, int, 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, const void *, int);
+static int wi_write_rid(struct wi_softc *, int, void *, int);
static int wi_write_appie(struct wi_softc *, int, const struct ieee80211_appie *);
static void wi_scan_start(struct ieee80211com *);
@@ -233,7 +237,8 @@ int
wi_attach(device_t dev)
{
struct wi_softc *sc = device_get_softc(dev);
- struct ieee80211com *ic = &sc->sc_ic;
+ struct ieee80211com *ic;
+ struct ifnet *ifp;
int i, nrates, buflen;
u_int16_t val;
u_int8_t ratebuf[2 + IEEE80211_RATE_SIZE];
@@ -244,6 +249,15 @@ 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;
@@ -295,7 +309,6 @@ 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.
@@ -304,13 +317,12 @@ wi_attach(device_t dev)
* the probe to fail.
*/
buflen = IEEE80211_ADDR_LEN;
- error = wi_read_rid(sc, WI_RID_MAC_NODE, &ic->ic_macaddr, &buflen);
+ error = wi_read_rid(sc, WI_RID_MAC_NODE, macaddr, &buflen);
if (error != 0) {
buflen = IEEE80211_ADDR_LEN;
- error = wi_read_rid(sc, WI_RID_MAC_NODE, &ic->ic_macaddr,
- &buflen);
+ error = wi_read_rid(sc, WI_RID_MAC_NODE, macaddr, &buflen);
}
- if (error || IEEE80211_ADDR_EQ(&ic->ic_macaddr, empty_macaddr)) {
+ if (error || IEEE80211_ADDR_EQ(macaddr, empty_macaddr)) {
if (error != 0)
device_printf(dev, "mac read failed %d\n", error);
else {
@@ -321,6 +333,18 @@ 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;
@@ -434,17 +458,16 @@ wi_attach(device_t dev)
sc->sc_portnum = WI_DEFAULT_PORT;
- ieee80211_ifattach(ic);
+ ieee80211_ifattach(ic, macaddr);
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),
@@ -460,6 +483,7 @@ 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;
}
@@ -471,20 +495,21 @@ int
wi_detach(device_t dev)
{
struct wi_softc *sc = device_get_softc(dev);
- struct ieee80211com *ic = &sc->sc_ic;
+ struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = ifp->if_l2com;
WI_LOCK(sc);
/* check if device was removed */
sc->wi_gone |= !bus_child_present(dev);
- wi_stop(sc, 0);
+ wi_stop_locked(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);
}
@@ -495,16 +520,19 @@ 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_softc;
+ struct wi_softc *sc = ic->ic_ifp->if_softc;
struct wi_vap *wvp;
struct ieee80211vap *vap;
if (!TAILQ_EMPTY(&ic->ic_vaps)) /* only one at a time */
return NULL;
- wvp = malloc(sizeof(struct wi_vap), M_80211_VAP, M_WAITOK | M_ZERO);
+ wvp = (struct wi_vap *) malloc(sizeof(struct wi_vap),
+ M_80211_VAP, M_NOWAIT | M_ZERO);
+ if (wvp == NULL)
+ return NULL;
vap = &wvp->wv_vap;
- ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid);
+ ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid, mac);
vap->iv_max_aid = WI_MAX_AID;
@@ -538,7 +566,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, mac);
+ ieee80211_vap_attach(vap, ieee80211_media_change, wi_media_status);
ic->ic_opmode = opmode;
return vap;
}
@@ -557,9 +585,7 @@ 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);
}
@@ -567,12 +593,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 ||
- (sc->sc_flags & WI_FLAGS_RUNNING) == 0) {
+ if (sc->wi_gone || !sc->sc_enabled || (ifp->if_flags & IFF_UP) == 0) {
CSR_WRITE_2(sc, WI_INT_EN, 0);
CSR_WRITE_2(sc, WI_EVENT_ACK, 0xFFFF);
WI_UNLOCK(sc);
@@ -591,8 +617,9 @@ wi_intr(void *arg)
wi_tx_ex_intr(sc);
if (status & WI_EV_INFO)
wi_info_intr(sc);
- if (mbufq_first(&sc->sc_snd) != NULL)
- wi_start(sc);
+ if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0 &&
+ !IFQ_DRV_IS_EMPTY(&ifp->if_snd))
+ wi_start_locked(ifp);
/* Re-enable interrupts. */
CSR_WRITE_2(sc, WI_INT_EN, WI_INTRS);
@@ -615,7 +642,7 @@ wi_enable(struct wi_softc *sc)
static int
wi_setup_locked(struct wi_softc *sc, int porttype, int mode,
- const uint8_t mac[IEEE80211_ADDR_LEN])
+ uint8_t mac[IEEE80211_ADDR_LEN])
{
int i;
@@ -649,25 +676,26 @@ wi_setup_locked(struct wi_softc *sc, int porttype, int mode,
return 0;
}
-void
-wi_init(struct wi_softc *sc)
+static void
+wi_init_locked(struct wi_softc *sc)
{
+ struct ifnet *ifp = sc->sc_ifp;
int wasenabled;
WI_LOCK_ASSERT(sc);
wasenabled = sc->sc_enabled;
if (wasenabled)
- wi_stop(sc, 1);
+ 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);
+ 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);
return;
}
- sc->sc_flags |= WI_FLAGS_RUNNING;
+ ifp->if_drv_flags |= IFF_DRV_RUNNING;
+ ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
callout_reset(&sc->sc_watchdog, hz, wi_watchdog, sc);
@@ -675,8 +703,24 @@ wi_init(struct wi_softc *sc)
}
void
-wi_stop(struct wi_softc *sc, int disable)
+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)
{
+ struct ifnet *ifp = sc->sc_ifp;
WI_LOCK_ASSERT(sc);
@@ -692,13 +736,22 @@ wi_stop(struct wi_softc *sc, int disable)
sc->sc_tx_timer = 0;
sc->sc_false_syns = 0;
- sc->sc_flags &= ~WI_FLAGS_RUNNING;
+ 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);
}
static void
wi_set_channel(struct ieee80211com *ic)
{
- struct wi_softc *sc = ic->ic_softc;
+ struct ifnet *ifp = ic->ic_ifp;
+ struct wi_softc *sc = ifp->if_softc;
DPRINTF(("%s: channel %d, %sscanning\n", __func__,
ieee80211_chan2ieee(ic, ic->ic_curchan),
@@ -713,7 +766,8 @@ wi_set_channel(struct ieee80211com *ic)
static void
wi_scan_start(struct ieee80211com *ic)
{
- struct wi_softc *sc = ic->ic_softc;
+ struct ifnet *ifp = ic->ic_ifp;
+ struct wi_softc *sc = ifp->if_softc;
struct ieee80211_scan_state *ss = ic->ic_scan;
DPRINTF(("%s\n", __func__));
@@ -736,7 +790,8 @@ wi_scan_start(struct ieee80211com *ic)
static void
wi_scan_end(struct ieee80211com *ic)
{
- struct wi_softc *sc = ic->ic_softc;
+ struct ifnet *ifp = ic->ic_ifp;
+ struct wi_softc *sc = ifp->if_softc;
DPRINTF(("%s: restore port type %d\n", __func__, sc->sc_porttype));
@@ -769,8 +824,9 @@ 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 = ic->ic_softc;
+ struct wi_softc *sc = ifp->if_softc;
DPRINTF(("%s: %s -> %s\n", __func__,
ieee80211_state_name[vap->iv_state],
@@ -838,8 +894,9 @@ 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 = ic->ic_softc;
+ struct wi_softc *sc = ifp->if_softc;
int error;
DPRINTF(("%s: %s -> %s\n", __func__,
@@ -896,30 +953,10 @@ 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(struct wi_softc *sc)
+wi_start_locked(struct ifnet *ifp)
{
+ struct wi_softc *sc = ifp->if_softc;
struct ieee80211_node *ni;
struct ieee80211_frame *wh;
struct mbuf *m0;
@@ -935,8 +972,15 @@ wi_start(struct wi_softc *sc)
memset(&frmhdr, 0, sizeof(frmhdr));
cur = sc->sc_txnext;
- while (sc->sc_txd[cur].d_len == 0 &&
- (m0 = mbufq_dequeue(&sc->sc_snd)) != NULL) {
+ 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;
+ }
ni = (struct ieee80211_node *) m0->m_pkthdr.rcvif;
/* reconstruct 802.3 header */
@@ -985,16 +1029,28 @@ wi_start(struct wi_softc *sc)
m_adj(m0, sizeof(struct ieee80211_frame));
frmhdr.wi_dat_len = htole16(m0->m_pkthdr.len);
ieee80211_free_node(ni);
- if (wi_start_tx(sc, &frmhdr, m0))
+ if (wi_start_tx(ifp, &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 wi_softc *sc, struct wi_frame *frmhdr, struct mbuf *m0)
+wi_start_tx(struct ifnet *ifp, struct wi_frame *frmhdr, struct mbuf *m0)
{
+ struct wi_softc *sc = ifp->if_softc;
int cur = sc->sc_txnext;
int fid, off, error;
@@ -1004,13 +1060,13 @@ wi_start_tx(struct wi_softc *sc, struct wi_frame *frmhdr, struct mbuf *m0)
|| wi_mwrite_bap(sc, fid, off, m0, m0->m_pkthdr.len) != 0;
m_freem(m0);
if (error) {
- counter_u64_add(sc->sc_ic.ic_oerrors, 1);
+ if_inc_counter(ifp, IFCOUNTER_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)) {
- device_printf(sc->sc_dev, "xmit failed\n");
+ if_printf(ifp, "xmit failed\n");
sc->sc_txd[cur].d_len = 0;
return -1;
}
@@ -1024,8 +1080,9 @@ 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 = ic->ic_softc;
+ struct wi_softc *sc = ifp->if_softc;
struct ieee80211_key *k;
struct ieee80211_frame *wh;
struct wi_frame frmhdr;
@@ -1041,6 +1098,7 @@ 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;
}
@@ -1071,7 +1129,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(sc, &frmhdr, m0) < 0) {
+ if (wi_start_tx(ifp, &frmhdr, m0) < 0) {
m0 = NULL;
rc = EIO;
goto out;
@@ -1102,7 +1160,7 @@ wi_reset(struct wi_softc *sc)
}
sc->sc_reset = 1;
if (i == WI_INIT_TRIES) {
- device_printf(sc->sc_dev, "reset failed\n");
+ if_printf(sc->sc_ifp, "reset failed\n");
return error;
}
@@ -1120,6 +1178,7 @@ static void
wi_watchdog(void *arg)
{
struct wi_softc *sc = arg;
+ struct ifnet *ifp = sc->sc_ifp;
WI_LOCK_ASSERT(sc);
@@ -1127,52 +1186,65 @@ wi_watchdog(void *arg)
return;
if (sc->sc_tx_timer && --sc->sc_tx_timer == 0) {
- device_printf(sc->sc_dev, "device timeout\n");
- counter_u64_add(sc->sc_ic.ic_oerrors, 1);
- wi_init(sc);
+ if_printf(ifp, "device timeout\n");
+ if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
+ wi_init_locked(ifp->if_softc);
return;
}
callout_reset(&sc->sc_watchdog, hz, wi_watchdog, sc);
}
-static void
-wi_parent(struct ieee80211com *ic)
+static int
+wi_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
{
- struct wi_softc *sc = ic->ic_softc;
- int startall = 0;
+ struct wi_softc *sc = ifp->if_softc;
+ struct ieee80211com *ic = ifp->if_l2com;
+ struct ifreq *ifr = (struct ifreq *) data;
+ int error = 0, startall = 0;
- 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;
+ 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;
+ }
} else {
- wi_init(sc);
+ wi_init_locked(sc);
startall = 1;
}
} else {
- wi_init(sc);
- startall = 1;
+ if (ifp->if_drv_flags & IFF_DRV_RUNNING)
+ wi_stop_locked(sc, 1);
+ sc->wi_gone = 0;
}
- } else if (sc->sc_flags & WI_FLAGS_RUNNING) {
- wi_stop(sc, 1);
- sc->wi_gone = 0;
+ 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;
}
- WI_UNLOCK(sc);
- if (startall)
- ieee80211_start_all(ic);
+ return error;
}
static void
@@ -1180,7 +1252,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_softc;
+ struct wi_softc *sc = ic->ic_ifp->if_softc;
u_int16_t val;
int rate, len;
@@ -1208,7 +1280,8 @@ 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 ieee80211com *ic = &sc->sc_ic;
+ struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
struct ieee80211_node *ni = vap->iv_bss;
@@ -1222,7 +1295,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 (ic->ic_promisc > 0 &&
+ if ((ifp->if_flags & IFF_PROMISC) != 0 &&
!ppsratecheck(&sc->sc_last_syn, &sc->sc_false_syns,
WI_MAX_FALSE_SYNS))
return;
@@ -1243,7 +1316,8 @@ 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 ieee80211com *ic = &sc->sc_ic;
+ struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = ifp->if_l2com;
struct wi_frame frmhdr;
struct mbuf *m;
struct ieee80211_frame *wh;
@@ -1258,7 +1332,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);
- counter_u64_add(ic->ic_ierrors, 1);
+ if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
DPRINTF(("wi_rx_intr: read fid %x failed\n", fid));
return;
}
@@ -1269,7 +1343,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);
- counter_u64_add(ic->ic_ierrors, 1);
+ if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
DPRINTF(("wi_rx_intr: fid %x error status %x\n", fid, status));
return;
}
@@ -1284,7 +1358,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);
- counter_u64_add(ic->ic_ierrors, 1);
+ if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
DPRINTF(("wi_rx_intr: oversized packet\n"));
return;
} else
@@ -1297,7 +1371,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);
- counter_u64_add(ic->ic_ierrors, 1);
+ if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
DPRINTF(("wi_rx_intr: MGET failed\n"));
return;
}
@@ -1306,6 +1380,7 @@ 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);
@@ -1350,6 +1425,7 @@ 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;
@@ -1364,7 +1440,7 @@ wi_tx_ex_intr(struct wi_softc *sc)
*/
if ((status & WI_TXSTAT_DISCONNECT) == 0) {
if (ppsratecheck(&lasttxerror, &curtxeps, wi_txerate)) {
- device_printf(sc->sc_dev, "tx failed");
+ if_printf(ifp, "tx failed");
if (status & WI_TXSTAT_RET_ERR)
printf(", retry limit exceeded");
if (status & WI_TXSTAT_AGED_ERR)
@@ -1379,7 +1455,7 @@ wi_tx_ex_intr(struct wi_softc *sc)
printf(", status=0x%x", status);
printf("\n");
}
- counter_u64_add(sc->sc_ic.ic_oerrors, 1);
+ if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
} else
DPRINTF(("port disconnected\n"));
} else
@@ -1390,6 +1466,7 @@ 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)
@@ -1400,17 +1477,19 @@ wi_tx_intr(struct wi_softc *sc)
cur = sc->sc_txcur;
if (sc->sc_txd[cur].d_fid != fid) {
- device_printf(sc->sc_dev, "bad alloc %x != %x, cur %d nxt %d\n",
+ if_printf(ifp, "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) {
+ if (sc->sc_txd[cur].d_len == 0)
+ ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
+ else {
if (wi_cmd(sc, WI_CMD_TX | WI_RECLAIM, sc->sc_txd[cur].d_fid,
0, 0)) {
- device_printf(sc->sc_dev, "xmit failed\n");
+ if_printf(ifp, "xmit failed\n");
sc->sc_txd[cur].d_len = 0;
} else {
sc->sc_tx_timer = 5;
@@ -1421,7 +1500,7 @@ wi_tx_intr(struct wi_softc *sc)
static __noinline void
wi_info_intr(struct wi_softc *sc)
{
- struct ieee80211com *ic = &sc->sc_ic;
+ struct ieee80211com *ic = sc->sc_ifp->if_l2com;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
int i, fid, len, off;
u_int16_t ltbuf[2];
@@ -1495,15 +1574,32 @@ 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 ieee80211com *ic = &sc->sc_ic;
- struct ieee80211vap *vap;
- struct wi_mcast mlist;
+ struct ifnet *ifp = sc->sc_ifp;
int n;
+ struct ifmultiaddr *ifma;
+ struct wi_mcast mlist;
- if (ic->ic_allmulti > 0 || ic->ic_promisc > 0) {
+ if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) {
allmulti:
memset(&mlist, 0, sizeof(mlist));
return wi_write_rid(sc, WI_RID_MCAST_LIST, &mlist,
@@ -1511,23 +1607,17 @@ allmulti:
}
n = 0;
- 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_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);
return wi_write_rid(sc, WI_RID_MCAST_LIST, &mlist,
IEEE80211_ADDR_LEN * n);
}
@@ -1548,7 +1638,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_promisc > 0)));
+ (ic->ic_ifp->if_flags & IFF_PROMISC)));
WI_UNLOCK(sc);
}
@@ -1847,7 +1937,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, const void *buf, int buflen)
+wi_write_bap(struct wi_softc *sc, int id, int off, void *buf, int buflen)
{
int error, cnt;
@@ -1859,7 +1949,7 @@ wi_write_bap(struct wi_softc *sc, int id, int off, const void *buf, int buflen)
return error;
}
cnt = (buflen + 1) / 2;
- CSR_WRITE_MULTI_STREAM_2(sc, WI_DATA0, (const uint16_t *)buf, cnt);
+ CSR_WRITE_MULTI_STREAM_2(sc, WI_DATA0, (u_int16_t *)buf, cnt);
sc->sc_bap_off += cnt * 2;
return 0;
@@ -1949,7 +2039,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, const void *buf, int buflen)
+wi_write_rid(struct wi_softc *sc, int rid, void *buf, int buflen)
{
int error;
u_int16_t ltbuf[2];
diff --git a/sys/dev/wi/if_wi_pccard.c b/sys/dev/wi/if_wi_pccard.c
index 414dc20dba1b..fd70e77074a7 100644
--- a/sys/dev/wi/if_wi_pccard.c
+++ b/sys/dev/wi/if_wi_pccard.c
@@ -46,7 +46,6 @@ __FBSDID("$FreeBSD$");
#include <sys/malloc.h>
#include <sys/socket.h>
#include <sys/systm.h>
-#include <sys/mbuf.h>
#include <sys/module.h>
#include <sys/bus.h>
diff --git a/sys/dev/wi/if_wi_pci.c b/sys/dev/wi/if_wi_pci.c
index b218c2479a69..198c599ef54a 100644
--- a/sys/dev/wi/if_wi_pci.c
+++ b/sys/dev/wi/if_wi_pci.c
@@ -238,9 +238,7 @@ wi_pci_suspend(device_t dev)
{
struct wi_softc *sc = device_get_softc(dev);
- WI_LOCK(sc);
wi_stop(sc, 1);
- WI_UNLOCK(sc);
return (0);
}
@@ -249,15 +247,16 @@ static int
wi_pci_resume(device_t dev)
{
struct wi_softc *sc = device_get_softc(dev);
- struct ieee80211com *ic = &sc->sc_ic;
+ struct ifnet *ifp = sc->sc_ifp;
- WI_LOCK(sc);
- if (sc->wi_bus_type != WI_BUS_PCI_NATIVE) {
+ if (sc->wi_bus_type != WI_BUS_PCI_NATIVE)
return (0);
- WI_UNLOCK(sc);
+
+ if (ifp->if_flags & IFF_UP) {
+ ifp->if_init(ifp->if_softc);
+ if (ifp->if_drv_flags & IFF_DRV_RUNNING)
+ ifp->if_start(ifp);
}
- if (ic->ic_nrunning > 0)
- wi_init(sc);
- WI_UNLOCK(sc);
+
return (0);
}
diff --git a/sys/dev/wi/if_wivar.h b/sys/dev/wi/if_wivar.h
index 9b668cc0e114..f163744ef834 100644
--- a/sys/dev/wi/if_wivar.h
+++ b/sys/dev/wi/if_wivar.h
@@ -68,8 +68,7 @@ struct wi_vap {
#define WI_VAP(vap) ((struct wi_vap *)(vap))
struct wi_softc {
- struct ieee80211com sc_ic;
- struct mbufq sc_snd;
+ struct ifnet *sc_ifp;
device_t sc_dev;
struct mtx sc_mtx;
struct callout sc_watchdog;
@@ -108,6 +107,7 @@ struct wi_softc {
int wi_cmd_count;
int sc_flags;
+ int sc_if_flags;
int sc_bap_id;
int sc_bap_off;
@@ -152,8 +152,6 @@ struct wi_softc {
#define WI_FLAGS_HAS_ROAMING 0x0020
#define WI_FLAGS_HAS_FRAGTHR 0x0200
#define WI_FLAGS_HAS_DBMADJUST 0x0400
-#define WI_FLAGS_RUNNING 0x0800
-#define WI_FLAGS_PROMISC 0x1000
struct wi_card_ident {
u_int16_t card_id;
@@ -182,7 +180,7 @@ int wi_shutdown(device_t);
int wi_alloc(device_t, int);
void wi_free(device_t);
extern devclass_t wi_devclass;
+void wi_init(void *);
void wi_intr(void *);
int wi_mgmt_xmit(struct wi_softc *, caddr_t, int);
void wi_stop(struct wi_softc *, int);
-void wi_init(struct wi_softc *);