Subject: Re: Proxim wi(4) not quite working, crashes
To: None <current-users@NetBSD.org>
From: David Young <dyoung@pobox.com>
List: current-users
Date: 10/13/2005 21:05:51
--+Z7/5fzWRHDJ0o7Q
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
On Thu, Oct 13, 2005 at 09:05:28PM -0400, Greg Troxel wrote:
> I don't know the wi code, but it would seem nice to ignore gracefully
> a stray interrupt if that's doable, just returning from wi_cmd_intr in
> that case.
Greg,
Here are wi patches, derived from FreeBSD, that disregard stray
interrupts. I haven't touched these patches in a long time.
Dave
--
David Young OJC Technologies
dyoung@ojctech.com Urbana, IL * (217) 278-3933
--+Z7/5fzWRHDJ0o7Q
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename=wi-invalid
Index: wi.c
===================================================================
RCS file: /cvsroot/src/sys/dev/ic/wi.c,v
retrieving revision 1.201
diff -u -u -r1.201 wi.c
--- wi.c 26 Jun 2005 21:51:37 -0000 1.201
+++ wi.c 6 Jul 2005 06:42:25 -0000
@@ -515,6 +515,7 @@
sc->sc_attached = 1;
splx(s);
+ ieee80211_announce(ic);
return 0;
}
@@ -603,7 +604,7 @@
struct ifnet *ifp = &sc->sc_if;
u_int16_t status;
- if (sc->sc_enabled == 0 ||
+ if (sc->sc_invalid || !sc->sc_enabled ||
(sc->sc_dev.dv_flags & DVF_ACTIVE) == 0 ||
(ifp->if_flags & IFF_RUNNING) == 0)
return 0;
@@ -621,6 +622,8 @@
/* maximum 10 loops per interrupt */
for (i = 0; i < 10; i++) {
+ if (sc->sc_invalid)
+ return 1;
status = CSR_READ_2(sc, WI_EVENT_STAT);
#ifdef WI_DEBUG
if (wi_debug > 1) {
@@ -710,6 +713,9 @@
int i;
int error = 0, wasenabled;
+ if (sc->sc_invalid)
+ return ENXIO;
+
DPRINTF(("wi_init: enabled %d\n", sc->sc_enabled));
wasenabled = sc->sc_enabled;
if (!sc->sc_enabled) {
@@ -924,7 +930,10 @@
STATIC void
wi_txcmd_wait(struct wi_softc *sc)
{
- KASSERT(sc->sc_txcmds == 1);
+#ifdef DIAGNOSTIC
+ if (sc->sc_txcmds < 1)
+ printf("%s: no txcmds outstanding!\n", __func__);
+#endif /* DIAGNOSTIC */
if (sc->sc_status & WI_EV_CMD) {
sc->sc_status &= ~WI_EV_CMD;
CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_CMD);
@@ -949,7 +958,7 @@
ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
/* wait for tx command completion (deassoc, deauth) */
- while (sc->sc_txcmds > 0) {
+ while (!sc->sc_invalid && sc->sc_txcmds > 0) {
wi_txcmd_wait(sc);
wi_cmd_intr(sc);
}
@@ -1229,8 +1238,6 @@
error = 0;
for (i = 0; i < 5; i++) {
- if (sc->sc_invalid)
- return ENXIO;
DELAY(20*1000); /* XXX: way too long! */
if ((error = wi_cmd(sc, WI_CMD_INI, 0, 0, 0)) == 0)
break;
@@ -1288,6 +1295,9 @@
struct ifreq *ifr = (struct ifreq *)data;
int s, error = 0;
+ if (sc->sc_invalid)
+ return ENXIO;
+
if ((sc->sc_dev.dv_flags & DVF_ACTIVE) == 0)
return ENXIO;
@@ -1309,8 +1319,15 @@
wi_write_val(sc, WI_RID_PROMISC, 0);
} else
error = wi_init(ifp);
- } else if (sc->sc_enabled)
+ } else if (sc->sc_enabled) {
wi_stop(ifp, 1);
+ /* Sometimes the device will come back to
+ * life after DOWN/UP. If not, that's ok,
+ * sc_invalid will be set back to 1 soon
+ * enough.
+ */
+ sc->sc_invalid = 0;
+ }
break;
case SIOCSIFMEDIA:
case SIOCGIFMEDIA:
@@ -1394,7 +1411,7 @@
u_int16_t val;
int rate;
- if (sc->sc_enabled == 0) {
+ if (!sc->sc_enabled || sc->sc_invalid) {
imr->ifm_active = IFM_IEEE80211 | IFM_NONE;
imr->ifm_status = 0;
return;
@@ -1749,7 +1766,10 @@
if (wi_debug)
printf("%s: %d txcmds outstanding\n", __func__, sc->sc_txcmds);
#endif
- KASSERT(sc->sc_txcmds > 0);
+#ifdef DIAGNOSTIC
+ if (sc->sc_txcmds <= 0)
+ printf("%s: no txcmds outstanding, getting out\n", __func__);
+#endif /* DIAGNOSTIC */
--sc->sc_txcmds;
@@ -1775,8 +1795,6 @@
cur = sc->sc_txstart;
fid = sc->sc_txd[cur].d_fid;
- KASSERT(sc->sc_txcmds == 0);
-
if (wi_cmd_start(sc, WI_CMD_TX | WI_RECLAIM, fid, 0, 0)) {
printf("%s: xmit failed\n", sc->sc_dev.dv_xname);
/* XXX ring might have a hole */
@@ -2619,17 +2638,19 @@
#endif
int i;
+ if (sc->sc_invalid)
+ return ENXIO;
+
/* wait for the busy bit to clear */
for (i = 500; i > 0; i--) { /* 5s */
if ((CSR_READ_2(sc, WI_COMMAND) & WI_CMD_BUSY) == 0)
break;
- if (sc->sc_invalid)
- return ENXIO;
DELAY(1000); /* 1 m sec */
}
if (i == 0) {
printf("%s: wi_cmd: busy bit won't clear.\n",
sc->sc_dev.dv_xname);
+ sc->sc_invalid = 1;
return(ETIMEDOUT);
}
#ifdef WI_HISTOGRAM
@@ -2665,6 +2686,9 @@
sc->sc_txcmds);
}
#endif
+ if (sc->sc_invalid)
+ return ENXIO;
+
if (sc->sc_txcmds > 0)
wi_txcmd_wait(sc);
@@ -2673,8 +2697,6 @@
if (cmd == WI_CMD_INI) {
/* XXX: should sleep here. */
- if (sc->sc_invalid)
- return ENXIO;
DELAY(100*1000);
}
rc = wi_cmd_wait(sc, cmd, val0);
@@ -2710,12 +2732,13 @@
printf("%s: cmd=%#x, arg=%#x\n", __func__, cmd, val0);
#endif /* WI_DEBUG */
+ if (sc->sc_invalid)
+ return ENXIO;
+
/* wait for the cmd completed bit */
for (i = 0; i < WI_TIMEOUT; i++) {
if (CSR_READ_2(sc, WI_EVENT_STAT) & WI_EV_CMD)
break;
- if (sc->sc_invalid)
- return ENXIO;
DELAY(WI_DELAY);
}
@@ -2739,6 +2762,8 @@
if (i == WI_TIMEOUT) {
printf("%s: command timed out, cmd=0x%x, arg=0x%x\n",
sc->sc_dev.dv_xname, cmd, val0);
+ if (status == 0xffff)
+ sc->sc_invalid = 1;
return ETIMEDOUT;
}
@@ -2772,10 +2797,10 @@
printf("%s: timeout in wi_seek to %x/%x\n",
sc->sc_dev.dv_xname, id, off);
sc->sc_bap_off = WI_OFF_ERR; /* invalidate */
+ if (status == 0xffff)
+ sc->sc_invalid = 1;
return ETIMEDOUT;
}
- if (sc->sc_invalid)
- return ENXIO;
DELAY(2);
}
#ifdef WI_HISTOGRAM
--+Z7/5fzWRHDJ0o7Q--