Date: Thu, 13 Aug 2009 07:21:24 +0000 (UTC) From: Nick Hibma <n_hibma@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-7@freebsd.org Subject: svn commit: r196167 - stable/7/sys/dev/usb Message-ID: <200908130721.n7D7LOWd090861@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: n_hibma Date: Thu Aug 13 07:21:24 2009 New Revision: 196167 URL: http://svn.freebsd.org/changeset/base/196167 Log: Restart the controller if it has halted. Restarting it makes the USB tree functional again (without reconnecting the devices, mind you). On my laptop there is probably a short somewhere on the motherboard and once in a while the host controller halts. Modified: stable/7/sys/dev/usb/uhci.c Modified: stable/7/sys/dev/usb/uhci.c ============================================================================== --- stable/7/sys/dev/usb/uhci.c Thu Aug 13 07:19:43 2009 (r196166) +++ stable/7/sys/dev/usb/uhci.c Thu Aug 13 07:21:24 2009 (r196167) @@ -1205,20 +1205,55 @@ uhci_intr1(uhci_softc_t *sc) device_get_nameunit(sc->sc_bus.bdev)); } if (status & UHCI_STS_HCH) { - /* no acknowledge needed */ if (!sc->sc_dying) { + ack |= UHCI_STS_HCH; printf("%s: host controller halted\n", - device_get_nameunit(sc->sc_bus.bdev)); -#ifdef USB_DEBUG - uhci_dump_all(sc); -#endif + device_get_nameunit(sc->sc_bus.bdev)); } - sc->sc_dying = 1; } if (!ack) return (0); /* nothing to acknowledge */ - UWRITE2(sc, UHCI_STS, ack); /* acknowledge the ints */ + + UWRITE2(sc, UHCI_STS, ack & ~UHCI_STS_HCH); /* acknowledge the ints */ + + if (ack & UHCI_STS_HCH) { + /* Restart the controller, by Manuel Bouyer */ + sc->sc_saved_frnum = UREAD2(sc, UHCI_FRNUM); + sc->sc_saved_sof = UREAD1(sc, UHCI_SOF); + + sc->sc_bus.use_polling++; + uhci_run(sc, 0); /* stop the controller */ + UWRITE2(sc, UHCI_INTR, 0); /* disable intrs */ + + uhci_globalreset(sc); + uhci_reset(sc); + + /* restore saved state */ + UWRITE4(sc, UHCI_FLBASEADDR, DMAADDR(&sc->sc_dma, 0)); + UWRITE2(sc, UHCI_FRNUM, sc->sc_saved_frnum); + UWRITE1(sc, UHCI_SOF, sc->sc_saved_sof); + + UWRITE2(sc, UHCI_INTR, UHCI_INTR_TOCRCIE | UHCI_INTR_RIE | + UHCI_INTR_IOCE | UHCI_INTR_SPIE); /* re-enable intrs */ + UHCICMD(sc, UHCI_CMD_MAXP); + + uhci_run(sc, 1); /* and start traffic again */ + sc->sc_bus.use_polling--; + + if (UREAD2(sc, UHCI_STS) & UHCI_STS_HCH) { + printf("%s: host controller couldn't be restarted\n", + device_get_nameunit(sc->sc_bus.bdev)); +#ifdef USB_DEBUG + uhci_dump_all(sc); +#endif + sc->sc_dying = 1; + return (0); + } + + printf("%s: host controller restarted\n", + device_get_nameunit(sc->sc_bus.bdev)); + } sc->sc_bus.no_intrs++; usb_schedsoftintr(&sc->sc_bus);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200908130721.n7D7LOWd090861>