Date: Mon, 14 Apr 2008 17:27:45 GMT From: Sam Leffler <sam@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 140035 for review Message-ID: <200804141727.m3EHRjiY041252@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=140035 Change 140035 by sam@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) <<<
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200804141727.m3EHRjiY041252>