summaryrefslogtreecommitdiffstats
path: root/sys/dev/ed
diff options
context:
space:
mode:
authorimp <imp@FreeBSD.org>2001-11-24 16:15:18 +0000
committerimp <imp@FreeBSD.org>2001-11-24 16:15:18 +0000
commit55262e3b08db9fbbce5c1b2e4d8622e44a7e9bbe (patch)
treedbd8cf8ecadcdde2c6a23463b1607228bdec5a4e /sys/dev/ed
parentbd8e2fa8eb0aecc989fbcb9a365735f5f935a1ee (diff)
downloadFreeBSD-src-55262e3b08db9fbbce5c1b2e4d8622e44a7e9bbe.zip
FreeBSD-src-55262e3b08db9fbbce5c1b2e4d8622e44a7e9bbe.tar.gz
Patch to allow the ed driver interrupt routine to terminate if the
card is ejected while we're in this routine. yamamoto-san's original patch had a small race window for AX88190 chips, which I corrected by limiting the number of iterations we'd try to reset the bits to be about 15ms rather than forever. This seems to work for me, but I don't have a large collections of cards based on this chipset. Submitted by: YAMAMOTO Shigeru
Diffstat (limited to 'sys/dev/ed')
-rw-r--r--sys/dev/ed/if_ed.c21
1 files changed, 17 insertions, 4 deletions
diff --git a/sys/dev/ed/if_ed.c b/sys/dev/ed/if_ed.c
index 43099ef..8fb2dc8 100644
--- a/sys/dev/ed/if_ed.c
+++ b/sys/dev/ed/if_ed.c
@@ -2285,6 +2285,7 @@ edintr(arg)
struct ed_softc *sc = (struct ed_softc*) arg;
struct ifnet *ifp = (struct ifnet *)sc;
u_char isr;
+ int count;
if (sc->gone)
return;
@@ -2294,9 +2295,12 @@ edintr(arg)
ed_nic_outb(sc, ED_P0_CR, sc->cr_proto | ED_CR_STA);
/*
- * loop until there are no more new interrupts
+ * loop until there are no more new interrupts. When the card
+ * goes away, the hardware will read back 0xff. Looking at
+ * the interrupts, it would appear that 0xff is impossible,
+ * or at least extremely unlikely.
*/
- while ((isr = ed_nic_inb(sc, ED_P0_ISR)) != 0) {
+ while ((isr = ed_nic_inb(sc, ED_P0_ISR)) != 0 && isr != 0xff) {
/*
* reset all the bits that we are 'acknowledging' by writing a
@@ -2305,12 +2309,21 @@ edintr(arg)
*/
ed_nic_outb(sc, ED_P0_ISR, isr);
- /* XXX workaround for AX88190 */
+ /*
+ * XXX workaround for AX88190
+ * We limit this to 5000 iterations. At 1us per inb/outb,
+ * this translates to about 15ms, which should be plenty
+ * of time, and also gives protection in the card eject
+ * case.
+ */
if (sc->chip_type == ED_CHIP_TYPE_AX88190) {
- while (ed_nic_inb(sc, ED_P0_ISR) & isr) {
+ count = 5000; /* 15ms */
+ while (count-- && (ed_nic_inb(sc, ED_P0_ISR) & isr)) {
ed_nic_outb(sc, ED_P0_ISR,0);
ed_nic_outb(sc, ED_P0_ISR,isr);
}
+ if (count == 0)
+ break;
}
/*
OpenPOWER on IntegriCloud