PERFORCE change 138681 for review
Sam Leffler
sam at FreeBSD.org
Wed Mar 26 23:08:13 UTC 2008
http://perforce.freebsd.org/chv.cgi?CH=138681
Change 138681 by sam at 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);
More information about the p4-projects
mailing list