summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorBrad Smith <brad@cvs.openbsd.org>2006-06-15 20:12:41 +0000
committerBrad Smith <brad@cvs.openbsd.org>2006-06-15 20:12:41 +0000
commit7b21556daf0a60db3098be08138be972cfec1429 (patch)
treeb032f30deff00bcb7f62ea3d32f55fc75f4bf3cb /sys/dev
parent3c18738eebc3ab152ffb51145446e53abd3236d3 (diff)
Fix watchdog timeout errors seen on a few systems.
The SK-NET GENESIS document says reading the SK_ISSR register should stop generating further interrupts, but it seems there is the possibility of losing interrupts between reading the SK_ISSR register and determining which interrupts have been reported. To cope with this situation we continuously read the SK_ISSR register until there are no interrupts. However, it seems that the above workaround does not fix all cases. Add workaround code that tries to protect against false alarms from the watchdog handler by trying to reclaim pending Tx descriptors before resetting the hardware. This should fix occasional watchdog timeouts seen with this driver. From FreeBSD
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/pci/if_sk.c19
1 files changed, 13 insertions, 6 deletions
diff --git a/sys/dev/pci/if_sk.c b/sys/dev/pci/if_sk.c
index d3aad1102b4..921086a9212 100644
--- a/sys/dev/pci/if_sk.c
+++ b/sys/dev/pci/if_sk.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_sk.c,v 1.111 2006/05/28 00:20:21 brad Exp $ */
+/* $OpenBSD: if_sk.c,v 1.112 2006/06/15 20:12:40 brad Exp $ */
/*
* Copyright (c) 1997, 1998, 1999, 2000
@@ -1821,11 +1821,18 @@ sk_watchdog(struct ifnet *ifp)
{
struct sk_if_softc *sc_if = ifp->if_softc;
- printf("%s: watchdog timeout\n", sc_if->sk_dev.dv_xname);
+ /*
+ * Reclaim first as there is a possibility of losing Tx completion
+ * interrupts.
+ */
+ sk_txeof(sc_if);
+ if (sc_if->sk_cdata.sk_tx_cnt != 0) {
+ printf("%s: watchdog timeout\n", sc_if->sk_dev.dv_xname);
- ifp->if_oerrors++;
+ ifp->if_oerrors++;
- sk_init(sc_if);
+ sk_init(sc_if);
+ }
}
void
@@ -2247,8 +2254,7 @@ sk_intr(void *xsc)
if (sc_if1 != NULL)
ifp1 = &sc_if1->arpcom.ac_if;
- status &= sc->sk_intrmask;
- if ((status & sc->sk_intrmask) != 0) {
+ for (; (status &= sc->sk_intrmask) != 0;) {
claimed = 1;
/* Handle receive interrupts first. */
@@ -2302,6 +2308,7 @@ sk_intr(void *xsc)
sc_if1->sk_phytype == SK_PHYTYPE_BCOM)
sk_intr_bcom(sc_if1);
}
+ status = CSR_READ_4(sc, SK_ISSR);
}
CSR_WRITE_4(sc, SK_IMR, sc->sk_intrmask);