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.
This commit is contained in:
parent
572ab50c54
commit
0e630ee24b
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=112363
@ -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;
|
||||
/* Disable interrupts. */
|
||||
CSR_WRITE_2(sc, WI_INT_EN, 0);
|
||||
|
||||
if (status & WI_EV_RX)
|
||||
wi_rx_intr(sc);
|
||||
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);
|
||||
|
||||
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 {
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user