summaryrefslogtreecommitdiffstats
path: root/sys/dev/sk
diff options
context:
space:
mode:
authoryongari <yongari@FreeBSD.org>2006-06-07 09:05:20 +0000
committeryongari <yongari@FreeBSD.org>2006-06-07 09:05:20 +0000
commit5a9f20b064c183c0627c8138e9776fde6dafdc9c (patch)
treec14faa3d7951f6bd37a6f42b32c105fdb4c91de0 /sys/dev/sk
parent21150f79c206e3b5de5dc56228941bdfa93096c6 (diff)
downloadFreeBSD-src-5a9f20b064c183c0627c8138e9776fde6dafdc9c.zip
FreeBSD-src-5a9f20b064c183c0627c8138e9776fde6dafdc9c.tar.gz
Fix watchdog timeout errors seen on a few systems.
SK-NET GENESIS document says reading SK_ISSR should stop generating further interrupts(Since we drop a driver lock before invoking ifp->if_input handler we should disable interrupts in ISR in order to protect integrity of softc from subsequent interrupts). But it seems that there is possibility of loosing interrupts between reading SK_ISSR and determining which interrupts are reported. To cope with the situation we continuously read SK_ISSR register until there are no interrupts. However, it seems that the above work around doesn't fix all cases. To protect watchdog handler from triggering false alarm add a work around code which try to reclaim pending Tx descriptors before resetting hardware. This should fix occasional watchdog timeout errors seen on this driver. Reported by: Frank Behrens <frank AT pinky dot sax dot de > Tested by: Frank Behrens <frank AT pinky dot sax dot de >
Diffstat (limited to 'sys/dev/sk')
-rw-r--r--sys/dev/sk/if_sk.c19
1 files changed, 13 insertions, 6 deletions
diff --git a/sys/dev/sk/if_sk.c b/sys/dev/sk/if_sk.c
index d15efe8..2c3d76d 100644
--- a/sys/dev/sk/if_sk.c
+++ b/sys/dev/sk/if_sk.c
@@ -2870,10 +2870,17 @@ sk_watchdog(ifp)
sc_if = ifp->if_softc;
SK_IF_LOCK(sc_if);
- if_printf(sc_if->sk_ifp, "watchdog timeout\n");
- ifp->if_oerrors++;
- ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
- sk_init_locked(sc_if);
+ /*
+ * Reclaim first as there is a possibility of loosing Tx completion
+ * interrupt.
+ */
+ sk_txeof(sc_if);
+ if (sc_if->sk_cdata.sk_tx_cnt != 0) {
+ if_printf(sc_if->sk_ifp, "watchdog timeout\n");
+ ifp->if_oerrors++;
+ ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
+ sk_init_locked(sc_if);
+ }
SK_IF_UNLOCK(sc_if);
return;
@@ -3425,8 +3432,7 @@ sk_intr(xsc)
if (sc_if1 != NULL)
ifp1 = sc_if1->sk_ifp;
- status &= sc->sk_intrmask;
- if ((status & sc->sk_intrmask) != 0) {
+ for (; (status &= sc->sk_intrmask) != 0;) {
/* Handle receive interrupts first. */
if (status & SK_ISR_RX1_EOF) {
if (ifp0->if_mtu > SK_MAX_FRAMELEN)
@@ -3480,6 +3486,7 @@ sk_intr(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);
OpenPOWER on IntegriCloud