From ad25ff2b433846ae8f2c92ca6cbb4ca88c1aea89 Mon Sep 17 00:00:00 2001 From: Pyun YongHyeon 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(-) (limited to 'sys/dev') diff --git a/sys/dev/sk/if_sk.c b/sys/dev/sk/if_sk.c index d15efe89db54..2c3d76da697f 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.3