summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorimp <imp@FreeBSD.org>2003-12-02 04:59:59 +0000
committerimp <imp@FreeBSD.org>2003-12-02 04:59:59 +0000
commit9d12741630d0b87d30301063746bdd84e5e075e3 (patch)
tree3c247e51097d7e8305d82977ab3fc41f064cdf1a
parentb2c171d63c85f931a59d4e994ce51792ca2ba695 (diff)
downloadFreeBSD-src-9d12741630d0b87d30301063746bdd84e5e075e3.zip
FreeBSD-src-9d12741630d0b87d30301063746bdd84e5e075e3.tar.gz
Fix Lucent cards.
o Back out workaround for not resetting lucent cards more than once. With these fixes, it appaers they are no longer necessary. o Set wi_gone when the card goes awol: typically when we get 0xffff back from the card. Also, don't interact with a card that's gone, so we fail in seconds rather than minutes. Also reduce amount of time we wait to .5s in wi_cmd. o clear wi_gone on ifconfig down to give some cards a chance after they wedge (this appears to unwedge one of my prism cards with old firmware). ifconfig up will fail quickly enough if the card really is out to lunch. o Add delay in wi_init of 100ms. o wi_stop(ifp, 0->1) changes so that we clear sc_enabled so that we exit out of the interrupt routine by just acking the interrupt Submitted by: iedowse Approved by: re@ (scottl) # after the freeze I'll fix some of the minor style issues that reviewers # of this patch have told me about.
-rw-r--r--sys/dev/wi/if_wi.c35
1 files changed, 25 insertions, 10 deletions
diff --git a/sys/dev/wi/if_wi.c b/sys/dev/wi/if_wi.c
index 8313a89..6281a1d 100644
--- a/sys/dev/wi/if_wi.c
+++ b/sys/dev/wi/if_wi.c
@@ -501,7 +501,7 @@ wi_detach(device_t dev)
WI_LOCK(sc);
/* check if device was removed */
- sc->wi_gone = !bus_child_present(dev);
+ sc->wi_gone |= !bus_child_present(dev);
wi_stop(ifp, 0);
@@ -584,9 +584,9 @@ wi_intr(void *arg)
WI_LOCK(sc);
- if (sc->wi_gone || (ifp->if_flags & IFF_UP) == 0) {
+ if (sc->wi_gone || !sc->sc_enabled || (ifp->if_flags & IFF_UP) == 0) {
CSR_WRITE_2(sc, WI_INT_EN, 0);
- CSR_WRITE_2(sc, WI_EVENT_ACK, ~0);
+ CSR_WRITE_2(sc, WI_EVENT_ACK, 0xFFFF);
WI_UNLOCK(sc);
return;
}
@@ -637,7 +637,7 @@ wi_init(void *arg)
}
if ((wasenabled = sc->sc_enabled))
- wi_stop(ifp, 0);
+ wi_stop(ifp, 1);
wi_reset(sc);
/* common 802.11 configuration */
@@ -800,7 +800,7 @@ wi_init(void *arg)
out:
if (error) {
if_printf(ifp, "interface not running\n");
- wi_stop(ifp, 0);
+ wi_stop(ifp, 1);
}
WI_UNLOCK(sc);
DPRINTF(("wi_init: return %d\n", error));
@@ -816,6 +816,8 @@ wi_stop(struct ifnet *ifp, int disable)
WI_LOCK(sc);
+ DELAY(100000);
+
ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
if (sc->sc_enabled && !sc->wi_gone) {
CSR_WRITE_2(sc, WI_INT_EN, 0);
@@ -827,7 +829,8 @@ wi_stop(struct ifnet *ifp, int disable)
#endif
sc->sc_enabled = 0;
}
- }
+ } else if (sc->wi_gone && disable) /* gone --> not enabled */
+ sc->sc_enabled = 0;
sc->sc_tx_timer = 0;
sc->sc_scan_timer = 0;
@@ -991,7 +994,7 @@ wi_reset(struct wi_softc *sc)
int tries;
/* Symbol firmware cannot be initialized more than once */
- if (sc->sc_firmware_type != WI_INTERSIL && sc->sc_reset)
+ if (sc->sc_firmware_type == WI_SYMBOL && sc->sc_reset)
return (0);
if (sc->sc_firmware_type == WI_SYMBOL)
tries = 1;
@@ -1113,8 +1116,9 @@ wi_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
}
} else {
if (ifp->if_flags & IFF_RUNNING) {
- wi_stop(ifp, 0);
+ wi_stop(ifp, 1);
}
+ sc->wi_gone = 0;
}
sc->sc_if_flags = ifp->if_flags;
error = 0;
@@ -1605,6 +1609,9 @@ wi_tx_intr(struct wi_softc *sc)
struct ifnet *ifp = &ic->ic_if;
int fid, cur;
+ if (sc->wi_gone)
+ return;
+
fid = CSR_READ_2(sc, WI_ALLOC_FID);
CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_ALLOC);
@@ -2375,18 +2382,22 @@ wi_cmd(struct wi_softc *sc, int cmd, int val0, int val1, int val2)
int i, s = 0;
static volatile int count = 0;
+ if (sc->wi_gone)
+ return (ENODEV);
+
if (count > 0)
panic("Hey partner, hold on there!");
count++;
/* wait for the busy bit to clear */
- for (i = 500; i > 0; i--) { /* 5s */
+ for (i = 500; i > 0; i--) { /* 500ms */
if (!(CSR_READ_2(sc, WI_COMMAND) & WI_CMD_BUSY))
break;
- DELAY(10*1000); /* 10 m sec */
+ DELAY(1*1000); /* 1ms */
}
if (i == 0) {
device_printf(sc->sc_dev, "wi_cmd: busy bit won't clear.\n" );
+ sc->wi_gone = 1;
count--;
return(ETIMEDOUT);
}
@@ -2423,6 +2434,8 @@ wi_cmd(struct wi_softc *sc, int cmd, int val0, int val1, int val2)
if (i == WI_TIMEOUT) {
device_printf(sc->sc_dev,
"timeout in wi_cmd 0x%04x; event status 0x%04x\n", cmd, s);
+ if (s == 0xffff)
+ sc->wi_gone = 1;
return(ETIMEDOUT);
}
return (0);
@@ -2444,6 +2457,8 @@ wi_seek_bap(struct wi_softc *sc, int id, int off)
device_printf(sc->sc_dev, "timeout in wi_seek to %x/%x\n",
id, off);
sc->sc_bap_off = WI_OFF_ERR; /* invalidate */
+ if (status == 0xffff)
+ sc->wi_gone = 1;
return ETIMEDOUT;
}
DELAY(1);
OpenPOWER on IntegriCloud