PERFORCE change 140035 for review
Sam Leffler
sam at FreeBSD.org
Mon Apr 14 17:27:46 UTC 2008
http://perforce.freebsd.org/chv.cgi?CH=140035
Change 140035 by sam at sam_ebb on 2008/04/14 17:27:22
checkpoint; associates
Affected files ...
.. //depot/projects/vap/sys/dev/ipw/if_ipw.c#12 edit
.. //depot/projects/vap/sys/dev/ipw/if_ipwvar.h#9 edit
Differences ...
==== //depot/projects/vap/sys/dev/ipw/if_ipw.c#12 (text+ko) ====
@@ -118,6 +118,10 @@
static int ipw_newstate(struct ieee80211vap *, enum ieee80211_state, int);
static uint16_t ipw_read_prom_word(struct ipw_softc *, uint8_t);
static void ipw_rx_cmd_intr(struct ipw_softc *, struct ipw_soft_buf *);
+static void ipw_assocsuccess(void *, int);
+static void ipw_assocfailed(void *, int);
+static void ipw_scandone(void *, int);
+static void ipw_bmiss(void *, int);
static void ipw_rx_newstate_intr(struct ipw_softc *, struct ipw_soft_buf *);
static void ipw_rx_data_intr(struct ipw_softc *, struct ipw_status *,
struct ipw_soft_bd *, struct ipw_soft_buf *);
@@ -130,6 +134,8 @@
static int ipw_cmd(struct ipw_softc *, uint32_t, void *, uint32_t);
static int ipw_tx_start(struct ifnet *, struct mbuf *,
struct ieee80211_node *);
+static int ipw_raw_xmit(struct ieee80211_node *, struct mbuf *,
+ const struct ieee80211_bpf_params *);
static void ipw_start(struct ifnet *);
static void ipw_start_locked(struct ifnet *);
static void ipw_watchdog(void *);
@@ -142,12 +148,10 @@
static int ipw_load_firmware(struct ipw_softc *, const char *, int);
static int ipw_config(struct ipw_softc *);
static void ipw_assoc_task(void *, int);
-static int ipw_auth_and_assoc(struct ipw_softc *);
static void ipw_disassoc_task(void *, int);
-static int ipw_disassociate(struct ipw_softc *);
static void ipw_init_task(void *, int);
static void ipw_init(void *);
-static void ipw_init_locked(struct ipw_softc *, int);
+static void ipw_init_locked(struct ipw_softc *);
static void ipw_stop(void *);
static void ipw_stop_locked(struct ipw_softc *);
static int ipw_sysctl_stats(SYSCTL_HANDLER_ARGS);
@@ -236,8 +240,7 @@
TASK_INIT(&sc->sc_init_task, 0, ipw_init_task, sc);
TASK_INIT(&sc->sc_scan_task, 0, ipw_scan_task, sc);
- TASK_INIT(&sc->sc_assoc_task, 0, ipw_assoc_task, sc);
- TASK_INIT(&sc->sc_disassoc_task, 0, ipw_disassoc_task, sc);
+ TASK_INIT(&sc->sc_bmiss_task, 0, ipw_bmiss, sc);
callout_init_mtx(&sc->sc_wdtimer, &sc->sc_mtx, 0);
if (pci_get_powerstate(dev) != PCI_POWERSTATE_D0) {
@@ -267,23 +270,23 @@
RF_ACTIVE | RF_SHAREABLE);
if (sc->irq == NULL) {
device_printf(dev, "could not allocate interrupt resource\n");
- goto fail;
+ goto fail1;
}
if (ipw_reset(sc) != 0) {
device_printf(dev, "could not reset adapter\n");
- goto fail;
+ goto fail2;
}
if (ipw_dma_alloc(sc) != 0) {
device_printf(dev, "could not allocate DMA resources\n");
- goto fail;
+ goto fail2;
}
ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
if (ifp == NULL) {
device_printf(dev, "can not if_alloc()\n");
- goto fail;
+ goto fail3;
}
ic = ifp->if_l2com;
@@ -298,6 +301,7 @@
IFQ_SET_READY(&ifp->if_snd);
ic->ic_ifp = ifp;
+ ic->ic_opmode = IEEE80211_M_STA;
ic->ic_phytype = IEEE80211_T_DS;
/* set device capabilities */
@@ -342,6 +346,7 @@
ic->ic_set_channel = ipw_set_channel;
ic->ic_scan_curchan = ipw_scan_curchan;
ic->ic_scan_mindwell = ipw_scan_mindwell;
+ ic->ic_raw_xmit = ipw_raw_xmit;
ic->ic_vap_create = ipw_vap_create;
ic->ic_vap_delete = ipw_vap_delete;
@@ -377,15 +382,23 @@
NULL, ipw_intr, sc, &sc->sc_ih);
if (error != 0) {
device_printf(dev, "could not set up interrupt\n");
- goto fail;
+ goto fail4;
}
if (bootverbose)
ieee80211_announce(ic);
return 0;
-
-fail: ipw_detach(dev);
+fail4:
+ if_free(ifp);
+fail3:
+ ipw_release(sc);
+fail2:
+ bus_release_resource(dev, SYS_RES_IRQ, sc->irq_rid, sc->irq);
+fail1:
+ bus_release_resource(dev, SYS_RES_MEMORY, sc->mem_rid, sc->mem);
+fail:
+ mtx_destroy(&sc->sc_mtx);
return ENXIO;
}
@@ -397,29 +410,23 @@
struct ieee80211com *ic = ifp->if_l2com;
ipw_stop(sc);
+
+ bpfdetach(ifp);
+ ieee80211_ifdetach(ic);
+
callout_drain(&sc->sc_wdtimer);
taskqueue_drain(taskqueue_fast, &sc->sc_init_task);
taskqueue_drain(taskqueue_fast, &sc->sc_scan_task);
- taskqueue_drain(taskqueue_fast, &sc->sc_assoc_task);
- taskqueue_drain(taskqueue_fast, &sc->sc_disassoc_task);
+ taskqueue_drain(taskqueue_fast, &sc->sc_bmiss_task);
- if (ifp != NULL) {
- bpfdetach(ifp);
- ieee80211_ifdetach(ic);
- }
-
ipw_release(sc);
- if (sc->irq != NULL) {
- bus_teardown_intr(dev, sc->irq, sc->sc_ih);
- bus_release_resource(dev, SYS_RES_IRQ, sc->irq_rid, sc->irq);
- }
+ bus_teardown_intr(dev, sc->irq, sc->sc_ih);
+ bus_release_resource(dev, SYS_RES_IRQ, sc->irq_rid, sc->irq);
- if (sc->mem != NULL)
- bus_release_resource(dev, SYS_RES_MEMORY, sc->mem_rid, sc->mem);
+ bus_release_resource(dev, SYS_RES_MEMORY, sc->mem_rid, sc->mem);
- if (ifp != NULL)
- if_free(ifp);
+ if_free(ifp);
if (sc->sc_firmware != NULL) {
firmware_put(sc->sc_firmware, FIRMWARE_UNLOAD);
@@ -437,16 +444,77 @@
const uint8_t bssid[IEEE80211_ADDR_LEN],
const uint8_t mac[IEEE80211_ADDR_LEN])
{
+ struct ifnet *ifp = ic->ic_ifp;
+ struct ipw_softc *sc = ifp->if_softc;
struct ipw_vap *ivp;
struct ieee80211vap *vap;
+ const struct firmware *fp;
+ const struct ipw_firmware_hdr *hdr;
+ const char *imagename;
if (!TAILQ_EMPTY(&ic->ic_vaps)) /* only one at a time */
return NULL;
+
+ switch (opmode) {
+ case IEEE80211_M_STA:
+ imagename = "ipw_bss";
+ break;
+ case IEEE80211_M_IBSS:
+ imagename = "ipw_ibss";
+ break;
+ case IEEE80211_M_MONITOR:
+ imagename = "ipw_monitor";
+ break;
+ default:
+ return NULL;
+ }
+
+ /*
+ * Load firmware image using the firmware(9) subsystem. Doing
+ * this unlocked is ok since we're single-threaded by the
+ * 802.11 layer.
+ */
+ if (sc->sc_firmware == NULL ||
+ strcmp(sc->sc_firmware->name, imagename) != 0) {
+ if (sc->sc_firmware != NULL)
+ firmware_put(sc->sc_firmware, FIRMWARE_UNLOAD);
+ sc->sc_firmware = firmware_get(imagename);
+ }
+ if (sc->sc_firmware == NULL) {
+ device_printf(sc->sc_dev,
+ "could not load firmware image '%s'\n", imagename);
+ return NULL;
+ }
+ fp = sc->sc_firmware;
+ if (fp->datasize < sizeof *hdr) {
+ device_printf(sc->sc_dev,
+ "firmware image too short %zu\n", fp->datasize);
+ firmware_put(sc->sc_firmware, FIRMWARE_UNLOAD);
+ sc->sc_firmware = NULL;
+ return NULL;
+ }
+ hdr = (const struct ipw_firmware_hdr *)fp->data;
+ if (fp->datasize < sizeof *hdr + le32toh(hdr->mainsz) +
+ le32toh(hdr->ucodesz)) {
+ device_printf(sc->sc_dev,
+ "firmware image too short %zu\n", fp->datasize);
+ firmware_put(sc->sc_firmware, FIRMWARE_UNLOAD);
+ sc->sc_firmware = NULL;
+ return NULL;
+ }
+
ivp = (struct ipw_vap *) malloc(sizeof(struct ipw_vap),
M_80211_VAP, M_NOWAIT | M_ZERO);
if (ivp == NULL)
return NULL;
vap = &ivp->vap;
+
+ TASK_INIT(&ivp->assoc_task, 0, ipw_assoc_task, vap);
+ TASK_INIT(&ivp->disassoc_task, 0, ipw_disassoc_task, vap);
+ TASK_INIT(&ivp->assoc_success_task, 0, ipw_assocsuccess, vap);
+ TASK_INIT(&ivp->assoc_failed_task, 0, ipw_assocfailed, vap);
+ TASK_INIT(&ivp->scandone_task, 0, ipw_scandone, vap);
+
ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid, mac);
/* override with driver methods */
ivp->newstate = vap->iv_newstate;
@@ -786,7 +854,7 @@
pci_write_config(dev, 0x41, 0, 1);
if (ifp->if_flags & IFF_UP) {
- ipw_init_locked(sc, 0);
+ ipw_init_locked(sc);
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
ipw_start_locked(ifp);
}
@@ -848,30 +916,34 @@
* AUTH -> RUN transition and we want to do nothing.
* This is all totally bogus and needs to be redone.
*/
- if (vap->iv_state == IEEE80211_S_SCAN)
- taskqueue_enqueue_fast(taskqueue_fast,
- &sc->sc_assoc_task);
+ if (vap->iv_state == IEEE80211_S_SCAN) {
+ taskqueue_enqueue(taskqueue_swi,
+ &IPW_VAP(vap)->assoc_task);
+ return EINPROGRESS;
+ }
}
break;
case IEEE80211_S_INIT:
if (sc->flags & IPW_FLAG_ASSOCIATED)
- taskqueue_enqueue_fast(taskqueue_fast,
- &sc->sc_disassoc_task);
+ taskqueue_enqueue(taskqueue_swi,
+ &IPW_VAP(vap)->disassoc_task);
break;
case IEEE80211_S_AUTH:
- taskqueue_enqueue_fast(taskqueue_fast, &sc->sc_assoc_task);
- break;
+ taskqueue_enqueue(taskqueue_swi, &IPW_VAP(vap)->assoc_task);
+ return EINPROGRESS;
case IEEE80211_S_ASSOC:
/*
* If we are not transitioning from AUTH the resend the
* association request.
*/
- if (vap->iv_state != IEEE80211_S_AUTH)
- taskqueue_enqueue_fast(taskqueue_fast,
- &sc->sc_assoc_task);
+ if (vap->iv_state != IEEE80211_S_AUTH) {
+ taskqueue_enqueue(taskqueue_swi,
+ &IPW_VAP(vap)->assoc_task);
+ return EINPROGRESS;
+ }
break;
default:
@@ -954,6 +1026,38 @@
}
static void
+ipw_assocsuccess(void *arg, int npending)
+{
+ struct ieee80211vap *vap = arg;
+
+ ieee80211_new_state(vap, IEEE80211_S_RUN, -1);
+}
+
+static void
+ipw_assocfailed(void *arg, int npending)
+{
+ struct ieee80211vap *vap = arg;
+
+ ieee80211_new_state(vap, IEEE80211_S_SCAN, -1);
+}
+
+static void
+ipw_scandone(void *arg, int npending)
+{
+ struct ieee80211vap *vap = arg;
+
+ ieee80211_scan_done(vap);
+}
+
+static void
+ipw_bmiss(void *arg, int npending)
+{
+ struct ieee80211com *ic = arg;
+
+ ieee80211_beacon_miss(ic);
+}
+
+static void
ipw_rx_newstate_intr(struct ipw_softc *sc, struct ipw_soft_buf *sbuf)
{
#define IEEESTATE(vap) ieee80211_state_name[vap->iv_state]
@@ -970,13 +1074,16 @@
case IPW_STATE_ASSOCIATED:
DPRINTFN(2, ("Association succeeded (%s flags 0x%x)\n",
IEEESTATE(vap), sc->flags));
+ /* XXX suppress state change in case the fw auto-associates */
+ if ((sc->flags & IPW_FLAG_ASSOCIATING) == 0) {
+ DPRINTF(("Unexpected association (%s, flags 0x%x)\n",
+ IEEESTATE(vap), sc->flags));
+ break;
+ }
+ sc->flags &= ~IPW_FLAG_ASSOCIATING;
sc->flags |= IPW_FLAG_ASSOCIATED;
- /* XXX suppress state change in case the fw auto-associates */
- if (vap->iv_state != IEEE80211_S_ASSOC) {
- DPRINTF(("Unexpected association (state %u)\n",
- vap->iv_state));
- } else
- ieee80211_new_state(vap, IEEE80211_S_RUN, -1);
+ taskqueue_enqueue(taskqueue_swi,
+ &IPW_VAP(vap)->assoc_success_task);
break;
case IPW_STATE_SCANNING:
@@ -988,8 +1095,10 @@
* scan and we would treat it as a beacon miss if
* we checked the 802.11 layer state.
*/
- if (sc->flags & IPW_FLAG_ASSOCIATED)
- ieee80211_beacon_miss(ic);
+ if (sc->flags & IPW_FLAG_ASSOCIATED) {
+ /* XXX probably need to issue disassoc to fw */
+ taskqueue_enqueue(taskqueue_swi, &sc->sc_bmiss_task);
+ }
break;
case IPW_STATE_SCAN_COMPLETE:
@@ -1000,14 +1109,15 @@
* around this by marking the HACK flag and skipping
* the first scan complete event.
*/
+ DPRINTFN(3, ("Scan complete (%s flags 0x%x)\n",
+ IEEESTATE(vap), sc->flags));
if (sc->flags & IPW_FLAG_HACK) {
sc->flags &= ~IPW_FLAG_HACK;
break;
}
- DPRINTFN(3, ("Scan complete (%s flags 0x%x)\n",
- IEEESTATE(vap), sc->flags));
if (sc->flags & IPW_FLAG_SCANNING) {
- ieee80211_scan_done(vap);
+ taskqueue_enqueue(taskqueue_swi,
+ &IPW_VAP(vap)->scandone_task);
sc->flags &= ~IPW_FLAG_SCANNING;
sc->sc_scan_timer = 0;
}
@@ -1016,21 +1126,25 @@
case IPW_STATE_ASSOCIATION_LOST:
DPRINTFN(2, ("Association lost (%s flags 0x%x)\n",
IEEESTATE(vap), sc->flags));
- sc->flags &= ~IPW_FLAG_ASSOCIATED;
+ sc->flags &= ~(IPW_FLAG_ASSOCIATING | IPW_FLAG_ASSOCIATED);
if (vap->iv_state == IEEE80211_S_RUN)
- ieee80211_new_state(vap, IEEE80211_S_SCAN, -1);
+ taskqueue_enqueue(taskqueue_swi,
+ &IPW_VAP(vap)->assoc_failed_task);
break;
case IPW_STATE_DISABLED:
+ /* XXX? is this right? */
+ sc->flags &= ~(IPW_FLAG_HACK | IPW_FLAG_SCANNING |
+ IPW_FLAG_ASSOCIATING | IPW_FLAG_ASSOCIATED);
DPRINTFN(2, ("Firmware disabled (%s flags 0x%x)\n",
IEEESTATE(vap), sc->flags));
break;
case IPW_STATE_RADIO_DISABLED:
- DPRINTFN(2, ("Radio off (%s flags 0x%x)\n",
- IEEESTATE(vap), sc->flags));
- vap->iv_ifp->if_flags &= ~IFF_UP; /* XXX */
+ device_printf(sc->sc_dev, "radio turned off\n");
+ ieee80211_notify_radio(ic, 0);
ipw_stop_locked(sc);
+ /* XXX start polling thread to detect radio on */
break;
default:
@@ -1199,9 +1313,6 @@
static void
ipw_rx_intr(struct ipw_softc *sc)
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
- struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
struct ipw_status *status;
struct ipw_soft_bd *sbd;
struct ipw_soft_buf *sbuf;
@@ -1236,11 +1347,7 @@
case IPW_STATUS_CODE_NOTIFICATION:
DPRINTFN(2, ("notification status, len %u flags 0x%x\n",
le32toh(status->len), status->flags));
- if (vap->iv_state == IEEE80211_S_AUTH) {
- /* XXX assume auth notification */
- ieee80211_node_authorize(vap->iv_bss);
- ieee80211_new_state(vap, IEEE80211_S_ASSOC, -1);
- }
+ /* XXX maybe drive state machine AUTH->ASSOC? */
break;
default:
@@ -1352,7 +1459,7 @@
if (r & (IPW_INTR_FATAL_ERROR | IPW_INTR_PARITY_ERROR)) {
device_printf(sc->sc_dev, "firmware error\n");
- taskqueue_enqueue_fast(taskqueue_fast, &sc->sc_init_task);
+ taskqueue_enqueue(taskqueue_swi, &sc->sc_init_task);
r = 0; /* don't process more interrupts */
}
@@ -1440,6 +1547,8 @@
bus_addr_t physaddr;
int error;
+ IPW_LOCK_ASSERT(sc);
+
if (sc->flags & IPW_FLAG_BUSY) {
device_printf(sc->sc_dev, "%s: %s not sent, busy\n",
__func__, ipw_cmdname(type));
@@ -1652,6 +1761,16 @@
return 0;
}
+static int
+ipw_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
+ const struct ieee80211_bpf_params *params)
+{
+ /* no support; just discard */
+ m_freem(m);
+ ieee80211_free_node(ni);
+ return 0;
+}
+
static void
ipw_start(struct ifnet *ifp)
{
@@ -1710,8 +1829,7 @@
if (--sc->sc_tx_timer == 0) {
if_printf(ifp, "device timeout\n");
ifp->if_oerrors++;
- taskqueue_enqueue_fast(taskqueue_fast,
- &sc->sc_init_task);
+ taskqueue_enqueue(taskqueue_swi, &sc->sc_init_task);
}
}
if (sc->sc_scan_timer > 0) {
@@ -1737,17 +1855,17 @@
int error = 0;
IPW_LOCK_DECL;
- IPW_LOCK(sc);
-
switch (cmd) {
case SIOCSIFFLAGS:
+ IPW_LOCK(sc);
if (ifp->if_flags & IFF_UP) {
if (!(ifp->if_drv_flags & IFF_DRV_RUNNING))
- ipw_init_locked(sc, 0);
+ ipw_init_locked(sc);
} else {
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
ipw_stop_locked(sc);
}
+ IPW_UNLOCK(sc);
break;
case SIOCGIFMEDIA:
case SIOCSIFMEDIA:
@@ -1756,9 +1874,6 @@
default:
error = ether_ioctl(ifp, cmd, data);
}
-
- IPW_UNLOCK(sc);
-
return error;
}
@@ -2146,146 +2261,50 @@
return error;
}
-static int
-ipw_config(struct ipw_softc *sc)
+static void
+ipw_assoc_task(void *context, int pending)
{
- struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211vap *vap = context;
+ struct ifnet *ifp = vap->iv_ic->ic_ifp;
struct ieee80211com *ic = ifp->if_l2com;
- struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
+ struct ipw_softc *sc = ifp->if_softc;
+ struct ieee80211_node *ni = vap->iv_bss;
struct ipw_security security;
- struct ipw_configuration config;
uint32_t data;
int error;
+ IPW_LOCK_DECL;
+ IPW_LOCK(sc);
error = ipw_disable(sc);
if (error != 0)
- return error;
+ goto done;
- switch (ic->ic_opmode) {
- case IEEE80211_M_STA:
- case IEEE80211_M_HOSTAP:
- case IEEE80211_M_WDS: /* XXX */
- data = htole32(IPW_MODE_BSS);
- break;
- case IEEE80211_M_IBSS:
- case IEEE80211_M_AHDEMO:
- data = htole32(IPW_MODE_IBSS);
- break;
- case IEEE80211_M_MONITOR:
- data = htole32(IPW_MODE_MONITOR);
- break;
- }
- DPRINTF(("Setting mode to %u\n", le32toh(data)));
- error = ipw_cmd(sc, IPW_CMD_SET_MODE, &data, sizeof data);
+ memset(&security, 0, sizeof security);
+ security.authmode = (ni->ni_authmode == IEEE80211_AUTH_SHARED) ?
+ IPW_AUTH_SHARED : IPW_AUTH_OPEN;
+ security.ciphers = htole32(IPW_CIPHER_NONE);
+ DPRINTF(("Setting authmode to %u\n", security.authmode));
+ error = ipw_cmd(sc, IPW_CMD_SET_SECURITY_INFO, &security,
+ sizeof security);
if (error != 0)
- return error;
-
- if (ic->ic_opmode == IEEE80211_M_IBSS ||
- ic->ic_opmode == IEEE80211_M_MONITOR) {
- error = ipw_setchannel(sc, ic->ic_curchan);
- if (error != 0)
- return error;
- }
-
- if (ic->ic_opmode == IEEE80211_M_MONITOR)
- return ipw_enable(sc);
-
- IEEE80211_ADDR_COPY(vap->iv_myaddr, IF_LLADDR(ifp));
- DPRINTF(("Setting MAC address to %6D\n", vap->iv_myaddr, ":"));
- error = ipw_cmd(sc, IPW_CMD_SET_MAC_ADDRESS, vap->iv_myaddr,
- IEEE80211_ADDR_LEN);
- if (error != 0)
- return error;
-
- config.flags = htole32(IPW_CFG_BSS_MASK | IPW_CFG_IBSS_MASK |
- IPW_CFG_PREAMBLE_AUTO | IPW_CFG_802_1x_ENABLE);
- if (ic->ic_opmode == IEEE80211_M_IBSS)
- config.flags |= htole32(IPW_CFG_IBSS_AUTO_START);
- if (ifp->if_flags & IFF_PROMISC)
- config.flags |= htole32(IPW_CFG_PROMISCUOUS);
- config.bss_chan = htole32(0x3fff); /* channels 1-14 */
- config.ibss_chan = htole32(0x7ff); /* channels 1-11 */
- DPRINTF(("Setting configuration to 0x%x\n", le32toh(config.flags)));
- error = ipw_cmd(sc, IPW_CMD_SET_CONFIGURATION, &config, sizeof config);
- if (error != 0)
- return error;
-
- data = htole32(0x3); /* 1, 2 */
- DPRINTF(("Setting basic tx rates to 0x%x\n", le32toh(data)));
- error = ipw_cmd(sc, IPW_CMD_SET_BASIC_TX_RATES, &data, sizeof data);
- if (error != 0)
- return error;
-
- /* NB: use the same rate set */
- DPRINTF(("Setting msdu tx rates to 0x%x\n", le32toh(data)));
- error = ipw_cmd(sc, IPW_CMD_SET_MSDU_TX_RATES, &data, sizeof data);
- if (error != 0)
- return error;
-
- data = htole32(0xf); /* 1, 2, 5.5, 11 */
- DPRINTF(("Setting tx rates to 0x%x\n", le32toh(data)));
- error = ipw_cmd(sc, IPW_CMD_SET_TX_RATES, &data, sizeof data);
- if (error != 0)
- return error;
-
- data = htole32(IPW_POWER_MODE_CAM);
- DPRINTF(("Setting power mode to %u\n", le32toh(data)));
- error = ipw_cmd(sc, IPW_CMD_SET_POWER_MODE, &data, sizeof data);
- if (error != 0)
- return error;
-
- if (ic->ic_opmode == IEEE80211_M_IBSS) {
- data = htole32(32); /* default value */
- DPRINTF(("Setting tx power index to %u\n", le32toh(data)));
- error = ipw_cmd(sc, IPW_CMD_SET_TX_POWER_INDEX, &data,
- sizeof data);
- if (error != 0)
- return error;
- }
+ goto done;
data = htole32(vap->iv_rtsthreshold);
DPRINTF(("Setting RTS threshold to %u\n", le32toh(data)));
error = ipw_cmd(sc, IPW_CMD_SET_RTS_THRESHOLD, &data, sizeof data);
if (error != 0)
- return error;
+ goto done;
data = htole32(vap->iv_fragthreshold);
DPRINTF(("Setting frag threshold to %u\n", le32toh(data)));
error = ipw_cmd(sc, IPW_CMD_SET_FRAG_THRESHOLD, &data, sizeof data);
if (error != 0)
- return error;
-
- error = ipw_setssid(sc, vap->iv_des_ssid[0].ssid, vap->iv_des_ssid[0].len);
- if (error != 0)
- return error;
-
- error = ipw_setbssid(sc, NULL);
- if (error != 0)
- return error;
-
- if (vap->iv_flags & IEEE80211_F_DESBSSID) {
- DPRINTF(("Setting desired BSSID to %6D\n", vap->iv_des_bssid,
- ":"));
- error = ipw_cmd(sc, IPW_CMD_SET_DESIRED_BSSID,
- vap->iv_des_bssid, IEEE80211_ADDR_LEN);
- if (error != 0)
- return error;
- }
-
- memset(&security, 0, sizeof security);
- security.authmode = (vap->iv_bss->ni_authmode == IEEE80211_AUTH_SHARED) ?
- IPW_AUTH_SHARED : IPW_AUTH_OPEN;
- security.ciphers = htole32(IPW_CIPHER_NONE);
- DPRINTF(("Setting authmode to %u\n", security.authmode));
- error = ipw_cmd(sc, IPW_CMD_SET_SECURITY_INFO, &security,
- sizeof security);
- if (error != 0)
- return error;
+ goto done;
if (vap->iv_flags & IEEE80211_F_PRIVACY) {
error = ipw_setwepkeys(sc);
if (error != 0)
- return error;
+ goto done;
if (vap->iv_def_txkey != IEEE80211_KEYIX_NONE) {
data = htole32(vap->iv_def_txkey);
@@ -2294,7 +2313,7 @@
error = ipw_cmd(sc, IPW_CMD_SET_WEP_KEY_INDEX, &data,
sizeof data);
if (error != 0)
- return error;
+ goto done;
}
}
@@ -2302,159 +2321,66 @@
DPRINTF(("Setting wep flags to 0x%x\n", le32toh(data)));
error = ipw_cmd(sc, IPW_CMD_SET_WEP_FLAGS, &data, sizeof data);
if (error != 0)
- return error;
-
- if (vap->iv_appie_assocreq != NULL) {
- struct ieee80211_appie *ie = vap->iv_appie_assocreq;
- error = ipw_setwpaie(sc, ie->ie_data, ie->ie_len);
- if (error != 0)
- return error;
- }
-
- if (ic->ic_opmode == IEEE80211_M_IBSS) {
- data = htole32(ic->ic_bintval);
- DPRINTF(("Setting beacon interval to %u\n", le32toh(data)));
- error = ipw_cmd(sc, IPW_CMD_SET_BEACON_INTERVAL, &data,
- sizeof data);
- if (error != 0)
- return error;
- }
-
- error = ipw_setscanopts(sc, 0x3fff, 0);
- if (error != 0)
- return error;
-
- return (ipw_enable(sc));
-}
-
-/*
- * Handler for sc_assoc_task. This is a simple wrapper around
- * ipw_auth_and_assoc().
- */
-static void
-ipw_assoc_task(void *context, int pending)
-{
- struct ipw_softc *sc = context;
- IPW_LOCK_DECL;
-
- IPW_LOCK(sc);
- ipw_auth_and_assoc(sc);
- IPW_UNLOCK(sc);
-}
-
-static int
-ipw_auth_and_assoc(struct ipw_softc *sc)
-{
- 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;
- struct ipw_security security;
- uint32_t data;
- int error;
-
- error = ipw_disable(sc);
- if (error != 0)
- return (error);
-
- memset(&security, 0, sizeof security);
- security.authmode = (ni->ni_authmode == IEEE80211_AUTH_SHARED) ?
- IPW_AUTH_SHARED : IPW_AUTH_OPEN;
- security.ciphers = htole32(IPW_CIPHER_NONE);
- DPRINTF(("Setting authmode to %u\n", security.authmode));
- error = ipw_cmd(sc, IPW_CMD_SET_SECURITY_INFO, &security,
- sizeof security);
- if (error != 0)
- return (error);
-
- if (vap->iv_flags & IEEE80211_F_PRIVACY) {
- error = ipw_setwepkeys(sc);
- if (error != 0)
- return error;
-
- if (vap->iv_def_txkey != IEEE80211_KEYIX_NONE) {
- data = htole32(vap->iv_def_txkey);
- DPRINTF(("Setting wep tx key index to %u\n",
- le32toh(data)));
- error = ipw_cmd(sc, IPW_CMD_SET_WEP_KEY_INDEX, &data,
- sizeof data);
- if (error != 0)
- return error;
- }
- }
+ goto done;
- data = htole32((vap->iv_flags & IEEE80211_F_PRIVACY) ? IPW_WEPON : 0);
- DPRINTF(("Setting wep flags to 0x%x\n", le32toh(data)));
- error = ipw_cmd(sc, IPW_CMD_SET_WEP_FLAGS, &data, sizeof data);
- if (error != 0)
- return error;
-
error = ipw_setssid(sc, ni->ni_essid, ni->ni_esslen);
if (error != 0)
- return (error);
+ goto done;
error = ipw_setbssid(sc, ni->ni_bssid);
if (error != 0)
- return (error);
+ goto done;
if (vap->iv_appie_assocreq != NULL) {
struct ieee80211_appie *ie = vap->iv_appie_assocreq;
error = ipw_setwpaie(sc, ie->ie_data, ie->ie_len);
if (error != 0)
- return error;
+ goto done;
}
if (ic->ic_opmode == IEEE80211_M_IBSS) {
error = ipw_setchannel(sc, ni->ni_chan);
if (error != 0)
- return (error);
+ goto done;
}
/* lock scan to ap's channel and enable associate */
error = ipw_setscanopts(sc,
- 1<<(ieee80211_chan2ieee(ic, ni->ni_chan)-1), 0);
+ 1<<(ieee80211_chan2ieee(ic, ni->ni_chan)-1), 0);
+ if (error != 0)
+ goto done;
- return ipw_enable(sc); /* finally, enable adapter */
+ error = ipw_enable(sc); /* finally, enable adapter */
+ if (error == 0)
+ sc->flags |= IPW_FLAG_ASSOCIATING;
+done:
+ IPW_UNLOCK(sc);
}
-/*
- * Handler for sc_disassoc_task. This is a simple wrapper around
- * ipw_disassociate().
- */
static void
ipw_disassoc_task(void *context, int pending)
{
- struct ipw_softc *sc = context;
+ struct ieee80211vap *vap = context;
+ struct ifnet *ifp = vap->iv_ic->ic_ifp;
+ struct ieee80211_node *ni = vap->iv_bss;
+ struct ipw_softc *sc = ifp->if_softc;
IPW_LOCK_DECL;
IPW_LOCK(sc);
- ipw_disassociate(sc);
- IPW_UNLOCK(sc);
-}
-
-static int
-ipw_disassociate(struct ipw_softc *sc)
-{
- 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;
-
DPRINTF(("Disassociate from %6D\n", ni->ni_bssid, ":"));
-
/*
* NB: don't try to do this if ipw_stop_master has
* shutdown the firmware and disabled interrupts.
*/
- if (!(sc->flags & IPW_FLAG_FW_INITED))
- return (0);
-
- sc->flags &= ~IPW_FLAG_ASSOCIATED;
- /*
- * NB: firmware currently ignores bssid parameter, but
- * supply it in case this changes (follow linux driver).
- */
- return ipw_cmd(sc, IPW_CMD_DISASSOCIATE,
- ni->ni_bssid, IEEE80211_ADDR_LEN);
+ if (sc->flags & IPW_FLAG_FW_INITED) {
+ sc->flags &= ~IPW_FLAG_ASSOCIATED;
+ /*
+ * NB: firmware currently ignores bssid parameter, but
+ * supply it in case this changes (follow linux driver).
+ */
+ (void) ipw_cmd(sc, IPW_CMD_DISASSOCIATE,
+ ni->ni_bssid, IEEE80211_ADDR_LEN);
+ }
+ IPW_UNLOCK(sc);
}
/*
@@ -2474,20 +2400,19 @@
IPW_LOCK_DECL;
IPW_LOCK(sc);
- ipw_init_locked(sc, 0);
+ ipw_init_locked(sc);
IPW_UNLOCK(sc);
}
static void
-ipw_init_locked(struct ipw_softc *sc, int force)
+ipw_init_locked(struct ipw_softc *sc)
{
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
const struct firmware *fp;
const struct ipw_firmware_hdr *hdr;
- const char *imagename, *fw;
- IPW_LOCK_DECL;
+ const char *fw;
IPW_LOCK_ASSERT(sc);
@@ -2507,63 +2432,22 @@
if (ipw_reset(sc) != 0) {
device_printf(sc->sc_dev, "could not reset adapter\n");
- goto fail1;
- }
-
- switch (ic->ic_opmode) {
- case IEEE80211_M_STA:
- imagename = "ipw_bss";
- break;
- case IEEE80211_M_IBSS:
- imagename = "ipw_ibss";
- break;
- case IEEE80211_M_MONITOR:
- imagename = "ipw_monitor";
- break;
- default:
- imagename = NULL; /* should not get there */
- }
-
- /*
- * Load firmware image using the firmware(9) subsystem. We need to
- * release the driver's lock first.
- */
- if (sc->sc_firmware == NULL || strcmp(sc->sc_firmware->name,
- imagename) != 0) {
- IPW_UNLOCK(sc);
- if (sc->sc_firmware != NULL)
- firmware_put(sc->sc_firmware, FIRMWARE_UNLOAD);
- sc->sc_firmware = firmware_get(imagename);
- IPW_LOCK(sc);
+ goto fail;
}
if (sc->sc_firmware == NULL) {
- device_printf(sc->sc_dev,
- "could not load firmware image '%s'\n", imagename);
- goto fail1;
+ device_printf(sc->sc_dev, "no firmware\n");
+ goto fail;
}
-
+ /* NB: consistency already checked on load */
fp = sc->sc_firmware;
- if (fp->datasize < sizeof *hdr) {
- device_printf(sc->sc_dev,
- "firmware image too short %zu\n", fp->datasize);
- goto fail2;
- }
-
hdr = (const struct ipw_firmware_hdr *)fp->data;
- if (fp->datasize < sizeof *hdr + le32toh(hdr->mainsz) +
- le32toh(hdr->ucodesz)) {
- device_printf(sc->sc_dev,
- "firmware image too short %zu\n", fp->datasize);
- goto fail2;
- }
-
- DPRINTF(("Loading firmware image '%s'\n", imagename));
+ DPRINTF(("Loading firmware image '%s'\n", fp->name));
fw = (const char *)fp->data + sizeof *hdr + le32toh(hdr->mainsz);
if (ipw_load_ucode(sc, fw, le32toh(hdr->ucodesz)) != 0) {
device_printf(sc->sc_dev, "could not load microcode\n");
- goto fail2;
+ goto fail;
}
ipw_stop_master(sc);
@@ -2591,7 +2475,7 @@
fw = (const char *)fp->data + sizeof *hdr;
if (ipw_load_firmware(sc, fw, le32toh(hdr->mainsz)) != 0) {
device_printf(sc->sc_dev, "could not load firmware\n");
- goto fail2;
+ goto fail;
}
sc->flags |= IPW_FLAG_FW_INITED;
@@ -2604,26 +2488,114 @@
if (ipw_config(sc) != 0) {
device_printf(sc->sc_dev, "device configuration failed\n");
- goto fail1;
+ goto fail;
}
callout_reset(&sc->sc_wdtimer, hz, ipw_watchdog, sc);
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
ifp->if_drv_flags |= IFF_DRV_RUNNING;
>>> TRUNCATED FOR MAIL (1000 lines) <<<
More information about the p4-projects
mailing list