Date: Wed, 26 Mar 2008 23:08:12 GMT From: Sam Leffler <sam@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 138681 for review Message-ID: <200803262308.m2QN8CIn006648@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=138681 Change 138681 by sam@sam_ebb on 2008/03/26 23:07:56 checkpoint; can associate and pass traffic with a netgear ma401 but my intersil cards lock up after sending auth Affected files ... .. //depot/projects/vap/sys/dev/wi/if_wi.c#13 edit .. //depot/projects/vap/sys/dev/wi/if_wi_pci.c#6 edit .. //depot/projects/vap/sys/dev/wi/if_wivar.h#10 edit Differences ... ==== //depot/projects/vap/sys/dev/wi/if_wi.c#13 (text+ko) ==== @@ -114,6 +114,7 @@ const uint8_t bssid[IEEE80211_ADDR_LEN], const uint8_t mac[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, @@ -122,7 +123,7 @@ const struct ieee80211_bpf_params *); static void wi_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m, int subtype, int rssi, int noise, u_int32_t rstamp); -static int wi_reset(struct ifnet *); +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_media_status(struct ifnet *, struct ifmediareq *); @@ -271,7 +272,7 @@ sc->sc_firmware_type = WI_NOTYPE; sc->wi_cmd_count = 500; /* Reset the NIC. */ - if (wi_reset(ifp) != 0) { + if (wi_reset(sc) != 0) { wi_free(dev); return ENXIO; /* XXX */ } @@ -436,8 +437,7 @@ sc->sc_max_datalen = 2304; sc->sc_system_scale = 1; - sc->sc_cnfauthmode = IEEE80211_AUTH_OPEN; - sc->sc_roaming_mode = 1; + sc->sc_roaming_mode = 2; /* NB: host decides */ sc->sc_portnum = WI_DEFAULT_PORT; sc->sc_authtype = WI_DEFAULT_AUTHTYPE; @@ -489,7 +489,7 @@ /* check if device was removed */ sc->wi_gone |= !bus_child_present(dev); - wi_stop(ifp, 0); + wi_stop_locked(sc, 0); WI_UNLOCK(sc); #if NBPFILTER > 0 bpfdetach(ifp); @@ -577,7 +577,7 @@ { struct wi_softc *sc = device_get_softc(dev); - wi_stop(sc->sc_ifp, 1); + wi_stop(sc, 1); } void @@ -620,31 +620,26 @@ return; } -void -wi_init(void *arg) +static void +wi_enable(struct wi_softc *sc) +{ + /* enable port */ + wi_cmd(sc, WI_CMD_ENABLE | sc->sc_portnum, 0, 0, 0); + sc->sc_enabled = 1; +} + +static int +wi_init_locked(struct wi_softc *sc, uint8_t mac[IEEE80211_ADDR_LEN]) { - struct wi_softc *sc = arg; - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = &sc->sc_ic; int i; - int error = 0, wasenabled; - if (sc->wi_gone) - return; - - if ((wasenabled = sc->sc_enabled)) - wi_stop(ifp, 1); + wi_reset(sc); - WI_LOCK(sc); - wi_reset(ifp); - wi_write_val(sc, WI_RID_PORTTYPE, sc->sc_porttype); - wi_write_val(sc, WI_RID_CREATE_IBSS, 0); + wi_write_val(sc, WI_RID_CREATE_IBSS, 3); /* join only, don't create */ wi_write_val(sc, WI_RID_MAX_DATALEN, sc->sc_max_datalen); -#if 0 /* NB: for IEEE80211_BPF_NOACK */ wi_write_val(sc, WI_RID_ALT_RETRY_CNT, 0); -#endif if (sc->sc_flags & WI_FLAGS_HAS_SYSSCALE) wi_write_val(sc, WI_RID_SYSTEM_SCALE, sc->sc_system_scale); if (sc->sc_flags & WI_FLAGS_HAS_ROAMING) @@ -652,30 +647,52 @@ if (sc->sc_flags & WI_FLAGS_HAS_MOR) wi_write_val(sc, WI_RID_MICROWAVE_OVEN, sc->sc_microwave_oven); - IEEE80211_ADDR_COPY(ic->ic_myaddr, IF_LLADDR(ifp)); - wi_write_rid(sc, WI_RID_MAC_NODE, ic->ic_myaddr, IEEE80211_ADDR_LEN); + wi_write_rid(sc, WI_RID_MAC_NODE, mac, IEEE80211_ADDR_LEN); /* Allocate fids for the card */ - if (!wasenabled) { - sc->sc_buflen = IEEE80211_MAX_LEN + sizeof(struct wi_frame); - for (i = 0; i < sc->sc_ntxbuf; i++) { - error = wi_alloc_fid(sc, sc->sc_buflen, - &sc->sc_txd[i].d_fid); - if (error) { - device_printf(sc->sc_dev, - "tx buffer allocation failed (error %u)\n", - error); - goto out; - } - sc->sc_txd[i].d_len = 0; + sc->sc_buflen = IEEE80211_MAX_LEN + sizeof(struct wi_frame); + for (i = 0; i < sc->sc_ntxbuf; i++) { + int error = wi_alloc_fid(sc, sc->sc_buflen, + &sc->sc_txd[i].d_fid); + if (error) { + device_printf(sc->sc_dev, + "tx buffer allocation failed (error %u)\n", + error); + return error; } + sc->sc_txd[i].d_len = 0; } sc->sc_txcur = sc->sc_txnext = 0; - /* Enable desired port */ - wi_cmd(sc, WI_CMD_ENABLE | sc->sc_portnum, 0, 0, 0); + return 0; +} + +void +wi_init(void *arg) +{ + struct wi_softc *sc = arg; + struct ifnet *ifp = sc->sc_ifp; + struct ieee80211com *ic = &sc->sc_ic; + int wasenabled; + + WI_LOCK(sc); + if (sc->wi_gone) { + WI_UNLOCK(sc); + return; + } + wasenabled = sc->sc_enabled; + if (wasenabled) + wi_stop_locked(sc, 1); + + IEEE80211_ADDR_COPY(ic->ic_myaddr, IF_LLADDR(ifp)); + if (wi_init_locked(sc, ic->ic_myaddr) != 0) { + if_printf(ifp, "interface not running\n"); + wi_stop_locked(sc, 1); + WI_UNLOCK(sc); + return; + } + wi_enable(sc); /* Enable desired port */ - sc->sc_enabled = 1; ifp->if_drv_flags |= IFF_DRV_RUNNING; ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; @@ -686,23 +703,15 @@ ieee80211_start_all(ic); callout_reset(&sc->sc_watchdog, hz, wi_watchdog, sc); - return; -out: - if (error) { - if_printf(ifp, "interface not running\n"); - wi_stop(ifp, 1); - } - WI_UNLOCK(sc); - DPRINTF(("wi_init: return %d\n", error)); - return; } -void -wi_stop(struct ifnet *ifp, int disable) +static void +wi_stop_locked(struct wi_softc *sc, int disable) { - struct wi_softc *sc = ifp->if_softc; + struct ifnet *ifp = sc->sc_ifp; + + WI_LOCK_ASSERT(sc); - WI_LOCK(sc); if (sc->sc_enabled && !sc->wi_gone) { CSR_WRITE_2(sc, WI_INT_EN, 0); wi_cmd(sc, WI_CMD_DISABLE | sc->sc_portnum, 0, 0, 0); @@ -716,7 +725,13 @@ 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); } @@ -726,24 +741,25 @@ 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), + ic->ic_flags & IEEE80211_F_SCAN ? "" : "!")); + WI_LOCK(sc); + /* + * Don't force the channel if we're not scanning; we may + * be called back on entering the AUTH and/or RUN state + * but the firmware gets unhappy as it's join primitive + * handles the channel change. + */ wi_write_val(sc, WI_RID_OWN_CHNL, ieee80211_chan2ieee(ic, ic->ic_curchan)); - #if NBPFILTER > 0 sc->sc_tx_th.wt_chan_freq = sc->sc_rx_th.wr_chan_freq = htole16(ic->ic_curchan->ic_freq); sc->sc_tx_th.wt_chan_flags = sc->sc_rx_th.wr_chan_flags = htole16(ic->ic_curchan->ic_flags); #endif - - if ((ic->ic_flags & IEEE80211_F_SCAN) == 0 && - ic->ic_opmode == IEEE80211_M_HOSTAP && - sc->sc_firmware_type == WI_INTERSIL) { - /* XXX: some cards need to be re-enabled */ - wi_cmd(sc, WI_CMD_DISABLE | WI_PORT0, 0, 0, 0); - wi_cmd(sc, WI_CMD_ENABLE | WI_PORT0, 0, 0, 0); - } WI_UNLOCK(sc); } @@ -754,6 +770,8 @@ struct wi_softc *sc = ifp->if_softc; struct ieee80211_scan_state *ss = ic->ic_scan; + DPRINTF(("%s\n", __func__)); + WI_LOCK(sc); /* * Switch device to monitor mode. @@ -766,9 +784,12 @@ wi_write_val(sc, WI_RID_PORTTYPE, WI_PORTTYPE_APSILENT); break; } - wi_cmd(sc, WI_CMD_DEBUG | (WI_TEST_MONITOR << 8), 0, 0, 0); - - ss->ss_mindwell = ss->ss_maxdwell = msecs_to_ticks(400); /* 400ms */ + if (sc->sc_firmware_type == WI_INTERSIL) { + wi_cmd(sc, WI_CMD_DISABLE | WI_PORT0, 0, 0, 0); + wi_cmd(sc, WI_CMD_ENABLE | WI_PORT0, 0, 0, 0); + } + /* force full dwell time to compensate for firmware overhead */ + ss->ss_mindwell = ss->ss_maxdwell = msecs_to_ticks(400); WI_UNLOCK(sc); } @@ -779,9 +800,14 @@ struct ifnet *ifp = ic->ic_ifp; struct wi_softc *sc = ifp->if_softc; + DPRINTF(("%s: restore port type %d\n", __func__, sc->sc_porttype)); + WI_LOCK(sc); - wi_cmd(sc, WI_CMD_DEBUG, 0, 0, 0); wi_write_val(sc, WI_RID_PORTTYPE, sc->sc_porttype); + if (sc->sc_firmware_type == WI_INTERSIL) { + wi_cmd(sc, WI_CMD_DISABLE | WI_PORT0, 0, 0, 0); + wi_cmd(sc, WI_CMD_ENABLE | WI_PORT0, 0, 0, 0); + } WI_UNLOCK(sc); } @@ -816,8 +842,30 @@ if (nstate == IEEE80211_S_AUTH) { struct ieee80211_node *bss = vap->iv_bss; - wi_write_ssid(sc, WI_RID_DESIRED_SSID, - bss->ni_essid, bss->ni_esslen); + wi_init_locked(sc, vap->iv_myaddr); + + if (vap->iv_flags & IEEE80211_F_PMGTON) { + wi_write_val(sc, WI_RID_MAX_SLEEP, ic->ic_lintval); + wi_write_val(sc, WI_RID_PM_ENABLED, 1); + } + wi_write_val(sc, WI_RID_RTS_THRESH, vap->iv_rtsthreshold); + if (sc->sc_flags & WI_FLAGS_HAS_FRAGTHR) + wi_write_val(sc, WI_RID_FRAG_THRESH, + vap->iv_fragthreshold); + wi_write_txrate(sc, vap); + + /* Configure WEP. */ + if (ic->ic_caps & IEEE80211_C_WEP) + wi_write_wep(sc, vap); + else + sc->sc_encryption = 0; + + wi_write_ssid(sc, WI_RID_DESIRED_SSID, bss->ni_essid, bss->ni_esslen); + wi_write_val(sc, WI_RID_OWN_CHNL, + ieee80211_chan2ieee(ic, bss->ni_chan)); + + wi_enable(sc); /* enable port */ + /* Lucent firmware does not support the JOIN RID. */ if (sc->sc_firmware_type == WI_INTERSIL) { struct wi_joinreq join; @@ -827,8 +875,6 @@ join.wi_chan = htole16( ieee80211_chan2ieee(ic, bss->ni_chan)); wi_write_rid(sc, WI_RID_JOIN_REQ, &join, sizeof(join)); - } else { - wi_write_val(sc, WI_RID_CREATE_IBSS, 0); } /* NB: don't go through 802.11 layer, it'll send auth frame */ vap->iv_state = nstate; @@ -840,32 +886,29 @@ if (nstate == IEEE80211_S_RUN && vap->iv_state != IEEE80211_S_RUN) { if (vap->iv_opmode == IEEE80211_M_MONITOR) wi_cmd(sc, WI_CMD_DEBUG | (WI_TEST_MONITOR << 8), 0, 0, 0); - wi_write_val(sc, WI_RID_MAX_SLEEP, ic->ic_lintval); - if (ic->ic_caps & IEEE80211_C_PMGT) - wi_write_val(sc, WI_RID_PM_ENABLED, - (vap->iv_flags & IEEE80211_F_PMGTON) ? 1 : 0); - wi_write_val(sc, WI_RID_RTS_THRESH, vap->iv_rtsthreshold); - if (sc->sc_flags & WI_FLAGS_HAS_FRAGTHR) - wi_write_val(sc, WI_RID_FRAG_THRESH, - vap->iv_fragthreshold); - wi_write_txrate(sc, vap); + if (vap->iv_opmode == IEEE80211_M_HOSTAP) { + wi_write_val(sc, WI_RID_RTS_THRESH, vap->iv_rtsthreshold); + if (sc->sc_flags & WI_FLAGS_HAS_FRAGTHR) + wi_write_val(sc, WI_RID_FRAG_THRESH, + vap->iv_fragthreshold); + wi_write_txrate(sc, vap); - /* Configure WEP. */ - if (ic->ic_caps & IEEE80211_C_WEP) { - sc->sc_cnfauthmode = vap->iv_bss->ni_authmode; - wi_write_wep(sc, vap); - } else - sc->sc_encryption = 0; + /* Configure WEP. */ + if (ic->ic_caps & IEEE80211_C_WEP) { + sc->sc_cnfauthmode = vap->iv_bss->ni_authmode; + wi_write_wep(sc, vap); + } else + sc->sc_encryption = 0; - if (vap->iv_opmode == IEEE80211_M_HOSTAP && - sc->sc_firmware_type == WI_INTERSIL) { + /* NB: only Intersil supports HOSTAP so this works for now */ wi_write_ssid(sc, WI_RID_OWN_SSID, vap->iv_des_ssid[0].ssid, vap->iv_des_ssid[0].len); wi_write_val(sc, WI_RID_OWN_BEACON_INT, ic->ic_bintval); wi_write_val(sc, WI_RID_BASIC_RATE, 0x03); /* 1, 2 */ wi_write_val(sc, WI_RID_SUPPORT_RATE, 0x0f); /* 1, 2, 5.5, 11 */ wi_write_val(sc, WI_RID_DTIM_PERIOD, vap->iv_dtim_period); - /* XXX: some card need to be re-enabled for hostap */ + + /* XXX: some cards need to be re-enabled for hostap */ wi_cmd(sc, WI_CMD_DISABLE | WI_PORT0, 0, 0, 0); wi_cmd(sc, WI_CMD_ENABLE | WI_PORT0, 0, 0, 0); } @@ -1066,21 +1109,20 @@ } static int -wi_reset(struct ifnet *ifp) +wi_reset(struct wi_softc *sc) { #define WI_INIT_TRIES 3 - struct wi_softc *sc = ifp->if_softc; - int i; - int error = 0; + int i, error = 0; for (i = 0; i < WI_INIT_TRIES; i++) { - if ((error = wi_cmd(sc, WI_CMD_INI, 0, 0, 0)) == 0) + error = wi_cmd(sc, WI_CMD_INI, 0, 0, 0); + if (error == 0) break; DELAY(WI_DELAY * 1000); } sc->sc_reset = 1; if (i == WI_INIT_TRIES) { - if_printf(ifp, "init failed\n"); + if_printf(sc->sc_ifp, "reset failed\n"); return error; } @@ -1142,7 +1184,7 @@ wi_init(sc); } else { if (ifp->if_drv_flags & IFF_DRV_RUNNING) - wi_stop(ifp, 1); + wi_stop_locked(sc, 1); sc->wi_gone = 0; } sc->sc_if_flags = ifp->if_flags; @@ -1462,11 +1504,11 @@ IEEE80211_UNLOCK(ic); break; case WI_INFO_LINK_STAT_AP_INR: + case WI_INFO_LINK_STAT_DISCONNECTED: break; case WI_INFO_LINK_STAT_AP_OOR: ieee80211_beacon_miss(ic); break; - case WI_INFO_LINK_STAT_DISCONNECTED: case WI_INFO_LINK_STAT_ASSOC_FAILED: if (vap->iv_opmode == IEEE80211_M_STA) ieee80211_new_state(vap, IEEE80211_S_SCAN, @@ -1748,7 +1790,7 @@ wi_write_val(sc, WI_RID_PROMISC, 1); } wi_write_val(sc, WI_RID_CNFAUTHMODE, - sc->sc_cnfauthmode); + vap->iv_bss->ni_authmode); /* XXX should honor IEEE80211_F_DROPUNENC */ val = PRIVACY_INVOKED | EXCLUDE_UNENCRYPTED; /* ==== //depot/projects/vap/sys/dev/wi/if_wi_pci.c#6 (text+ko) ==== @@ -246,10 +246,8 @@ wi_pci_suspend(device_t dev) { struct wi_softc *sc = device_get_softc(dev); - struct ieee80211com *ic = &sc->sc_ic; - struct ifnet *ifp = ic->ic_ifp; - wi_stop(ifp, 1); + wi_stop(sc, 1); return (0); } ==== //depot/projects/vap/sys/dev/wi/if_wivar.h#10 (text+ko) ==== @@ -194,4 +194,4 @@ void wi_init(void *); void wi_intr(void *); int wi_mgmt_xmit(struct wi_softc *, caddr_t, int); -void wi_stop(struct ifnet *, int); +void wi_stop(struct wi_softc *, int);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200803262308.m2QN8CIn006648>