summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorimp <imp@FreeBSD.org>2003-03-18 04:22:42 +0000
committerimp <imp@FreeBSD.org>2003-03-18 04:22:42 +0000
commitc67f918d581b524182a91b083f5649439eaa0815 (patch)
tree392c4a2b1c15326b4a3126fe8b6be04b61029112
parent78371158c8a40f9bc2f40c86692e1e8b2a6c6725 (diff)
downloadFreeBSD-src-c67f918d581b524182a91b083f5649439eaa0815.zip
FreeBSD-src-c67f918d581b524182a91b083f5649439eaa0815.tar.gz
o Lucent cards don't seem to like multiple buffers for tx. Use only
one tx buffer for these cards. The old driver only used one. We use 1 for symbol, and 3 for prism cards. o Don't do the maximum loops thing in the ISR. In fact, revert to the old interrupt handler. Lucent cards don't seem to work too well if you don't disable/enable interrupts from the card in the ISR. Between these two changes, Lucent cards suck less. They work in autoselect mode only. And seem to get 1Mbps or 2Mbps only. Setting a specific media speed doesn't work, and I've had a few issues even with these patches. They turn a former brick into a nearly useful card. These patches work on the prism 2 and 2.5 PC Card cards that I have. I've not tested this on PCI cards. I suspect, but couldn't find proof, that they were the reason that the ISR was changed so radically from its FreeBSD roots in NetBSD. We might need to have a variant ISR if so.
-rw-r--r--sys/dev/wi/if_wi.c62
-rw-r--r--sys/dev/wi/if_wivar.h1
2 files changed, 26 insertions, 37 deletions
diff --git a/sys/dev/wi/if_wi.c b/sys/dev/wi/if_wi.c
index 6d2b10b..64d68d2 100644
--- a/sys/dev/wi/if_wi.c
+++ b/sys/dev/wi/if_wi.c
@@ -345,6 +345,7 @@ wi_attach(device_t dev)
*/
switch (sc->sc_firmware_type) {
case WI_LUCENT:
+ sc->sc_ntxbuf = 1;
sc->sc_flags |= WI_FLAGS_HAS_SYSSCALE;
#ifdef WI_HERMES_AUTOINC_WAR
/* XXX: not confirmed, but never seen for recent firmware */
@@ -360,6 +361,7 @@ wi_attach(device_t dev)
break;
case WI_INTERSIL:
+ sc->sc_ntxbuf = WI_NTXBUF;
sc->sc_flags |= WI_FLAGS_HAS_FRAGTHR;
sc->sc_flags |= WI_FLAGS_HAS_ROAMING;
sc->sc_flags |= WI_FLAGS_HAS_SYSSCALE;
@@ -378,6 +380,7 @@ wi_attach(device_t dev)
break;
case WI_SYMBOL:
+ sc->sc_ntxbuf = 1;
sc->sc_flags |= WI_FLAGS_HAS_DIVERSITY;
if (sc->sc_sta_firmware_ver >= 25000)
ic->ic_flags |= IEEE80211_F_HASIBSS;
@@ -553,10 +556,9 @@ wi_shutdown(device_t dev)
void
wi_intr(void *arg)
{
- int i;
struct wi_softc *sc = arg;
struct ifnet *ifp = &sc->sc_ic.ic_if;
- u_int16_t status, raw_status, last_status;
+ u_int16_t status;
WI_LOCK_DECL();
WI_LOCK(sc);
@@ -568,39 +570,25 @@ wi_intr(void *arg)
return;
}
- /* maximum 10 loops per interrupt */
- last_status = 0;
- for (i = 0; i < 10; i++) {
- /*
- * Only believe a status bit when we enter wi_intr, or when
- * the bit was "off" the last time through the loop. This is
- * my strategy to avoid racing the hardware/firmware if I
- * can re-read the event status register more quickly than
- * it is updated.
- */
- raw_status = CSR_READ_2(sc, WI_EVENT_STAT);
- status = raw_status & ~last_status;
- if ((status & WI_INTRS) == 0)
- break;
- last_status = raw_status;
-
- if (status & WI_EV_RX)
- wi_rx_intr(sc);
-
- if (status & WI_EV_ALLOC)
- wi_tx_intr(sc);
-
- if (status & WI_EV_TX_EXC)
- wi_tx_ex_intr(sc);
-
- if (status & WI_EV_INFO)
- wi_info_intr(sc);
+ /* Disable interrupts. */
+ CSR_WRITE_2(sc, WI_INT_EN, 0);
- if ((ifp->if_flags & IFF_OACTIVE) == 0 &&
- (sc->sc_flags & WI_FLAGS_OUTRANGE) == 0 &&
- _IF_QLEN(&ifp->if_snd) != 0)
- wi_start(ifp);
- }
+ status = CSR_READ_2(sc, WI_EVENT_STAT);
+ if (status & WI_EV_RX)
+ wi_rx_intr(sc);
+ if (status & WI_EV_ALLOC)
+ wi_tx_intr(sc);
+ if (status & WI_EV_TX_EXC)
+ wi_tx_ex_intr(sc);
+ if (status & WI_EV_INFO)
+ wi_info_intr(sc);
+ if ((ifp->if_flags & IFF_OACTIVE) == 0 &&
+ (sc->sc_flags & WI_FLAGS_OUTRANGE) == 0 &&
+ _IF_QLEN(&ifp->if_snd) != 0)
+ wi_start(ifp);
+
+ /* Re-enable interrupts. */
+ CSR_WRITE_2(sc, WI_INT_EN, WI_INTRS);
WI_UNLOCK(sc);
@@ -722,7 +710,7 @@ wi_init(void *arg)
sc->sc_buflen = IEEE80211_MAX_LEN + sizeof(struct wi_frame);
if (sc->sc_firmware_type == WI_SYMBOL)
sc->sc_buflen = 1585; /* XXX */
- for (i = 0; i < WI_NTXBUF; i++) {
+ for (i = 0; i < sc->sc_ntxbuf; i++) {
error = wi_alloc_fid(sc, sc->sc_buflen,
&sc->sc_txd[i].d_fid);
if (error) {
@@ -941,7 +929,7 @@ wi_start(struct ifnet *ifp)
sc->sc_tx_timer = 5;
ifp->if_timer = 1;
}
- sc->sc_txnext = cur = (cur + 1) % WI_NTXBUF;
+ sc->sc_txnext = cur = (cur + 1) % sc->sc_ntxbuf;
}
WI_UNLOCK(sc);
@@ -1465,7 +1453,7 @@ wi_tx_intr(struct wi_softc *sc)
}
sc->sc_tx_timer = 0;
sc->sc_txd[cur].d_len = 0;
- sc->sc_txcur = cur = (cur + 1) % WI_NTXBUF;
+ sc->sc_txcur = cur = (cur + 1) % sc->sc_ntxbuf;
if (sc->sc_txd[cur].d_len == 0)
ifp->if_flags &= ~IFF_OACTIVE;
else {
diff --git a/sys/dev/wi/if_wivar.h b/sys/dev/wi/if_wivar.h
index 6b6200f..11ee69f 100644
--- a/sys/dev/wi/if_wivar.h
+++ b/sys/dev/wi/if_wivar.h
@@ -120,6 +120,7 @@ struct wi_softc {
char sc_net_name[IEEE80211_NWID_LEN];
int sc_buflen; /* TX buffer size */
+ int sc_ntxbuf;
#define WI_NTXBUF 3
struct {
int d_fid;
OpenPOWER on IntegriCloud