From 5a9f20b064c183c0627c8138e9776fde6dafdc9c Mon Sep 17 00:00:00 2001 From: yongari Date: Wed, 7 Jun 2006 09:05:20 +0000 Subject: 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 Tested by: Frank Behrens --- sys/dev/sk/if_sk.c | 19 +++++++++++++------ 1 file 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); -- cgit v1.1