aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/ed
diff options
context:
space:
mode:
authorWarner Losh <imp@FreeBSD.org>2001-11-24 16:15:18 +0000
committerWarner Losh <imp@FreeBSD.org>2001-11-24 16:15:18 +0000
commit5c8fcbc8667c0fbc75a8fc88ced42098ea2da746 (patch)
treedbd8cf8ecadcdde2c6a23463b1607228bdec5a4e /sys/dev/ed
parent2d37e7d3ef2bfd55e5a2019ff3d99c6477dcb6d8 (diff)
downloadsrc-5c8fcbc8667c0fbc75a8fc88ced42098ea2da746.tar.gz
src-5c8fcbc8667c0fbc75a8fc88ced42098ea2da746.zip
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
Notes
Notes: svn path=/head/; revision=86865
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 43099ef366a7..8fb2dc8343d2 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;
}
/*