From owner-svn-src-head@FreeBSD.ORG Thu Jan 8 13:32:09 2009 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 0648E10656DB; Thu, 8 Jan 2009 13:32:09 +0000 (UTC) (envelope-from raj@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 8A74C8FC13; Thu, 8 Jan 2009 13:32:08 +0000 (UTC) (envelope-from raj@FreeBSD.org) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id n08DW8K1023798; Thu, 8 Jan 2009 13:32:08 GMT (envelope-from raj@svn.freebsd.org) Received: (from raj@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id n08DW8Is023797; Thu, 8 Jan 2009 13:32:08 GMT (envelope-from raj@svn.freebsd.org) Message-Id: <200901081332.n08DW8Is023797@svn.freebsd.org> From: Rafal Jaworowski Date: Thu, 8 Jan 2009 13:32:08 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r186902 - head/sys/dev/usb X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 08 Jan 2009 13:32:10 -0000 Author: raj Date: Thu Jan 8 13:32:08 2009 New Revision: 186902 URL: http://svn.freebsd.org/changeset/base/186902 Log: Provide handler for USB controller error interrupts for Marvell EHCI device. Obtained from: Semihalf Modified: head/sys/dev/usb/ehci_mbus.c Modified: head/sys/dev/usb/ehci_mbus.c ============================================================================== --- head/sys/dev/usb/ehci_mbus.c Thu Jan 8 13:25:22 2009 (r186901) +++ head/sys/dev/usb/ehci_mbus.c Thu Jan 8 13:32:08 2009 (r186902) @@ -73,6 +73,19 @@ static device_shutdown_t ehci_mbus_shutd static device_suspend_t ehci_mbus_suspend; static device_resume_t ehci_mbus_resume; +static int err_intr(void *arg); + +struct resource *irq_err; +void *ih_err; + +#define USB_BRIDGE_INTR_CAUSE 0x210 +#define USB_BRIDGE_INTR_MASK 0x214 + +#define MV_USB_ADDR_DECODE_ERR (1 << 0) +#define MV_USB_HOST_UNDERFLOW (1 << 1) +#define MV_USB_HOST_OVERFLOW (1 << 2) +#define MV_USB_DEVICE_UNDERFLOW (1 << 3) + static int ehci_mbus_suspend(device_t self) { @@ -157,6 +170,15 @@ ehci_mbus_attach(device_t self) device_get_name(self)); sc->sc_size = MV_USB_SIZE - MV_USB_HOST_OFST; + rid = 0; + irq_err = bus_alloc_resource_any(self, SYS_RES_IRQ, &rid, + RF_SHAREABLE | RF_ACTIVE); + if (irq_err == NULL) { + device_printf(self, "Could not allocate error irq\n"); + ehci_mbus_detach(self); + return (ENXIO); + } + /* * Notice: Marvell EHCI controller has TWO interrupt lines, so make sure to * use the correct rid for the main one (controller interrupt) -- @@ -181,6 +203,19 @@ ehci_mbus_attach(device_t self) sprintf(sc->sc_vendor, "Marvell"); sc->sc_id_vendor = EHCI_VENDORID_MRVL; + err = bus_setup_intr(self, irq_err, INTR_FAST | INTR_TYPE_BIO, + err_intr, NULL, sc, &ih_err); + if (err) { + device_printf(self, "Could not setup error irq, %d\n", err); + ih_err = NULL; + ehci_mbus_detach(self); + return (ENXIO); + } + + EWRITE4(sc, USB_BRIDGE_INTR_MASK, MV_USB_ADDR_DECODE_ERR | + MV_USB_HOST_UNDERFLOW | MV_USB_HOST_OVERFLOW | + MV_USB_DEVICE_UNDERFLOW); + err = bus_setup_intr(self, sc->irq_res, INTR_TYPE_BIO, NULL, (driver_intr_t*)ehci_intr, sc, &sc->ih); if (err) { @@ -277,6 +312,17 @@ ehci_mbus_detach(device_t self) err); sc->ih = NULL; } + EWRITE4(sc, USB_BRIDGE_INTR_MASK, 0); + + if (irq_err && ih_err) { + err = bus_teardown_intr(self, irq_err, ih_err); + + if (err) + device_printf(self, "Could not tear down irq, %d\n", + err); + ih_err = NULL; + } + if (sc->sc_bus.bdev) { device_delete_child(self, sc->sc_bus.bdev); sc->sc_bus.bdev = NULL; @@ -285,6 +331,10 @@ ehci_mbus_detach(device_t self) bus_release_resource(self, SYS_RES_IRQ, 0, sc->irq_res); sc->irq_res = NULL; } + if (irq_err) { + bus_release_resource(self, SYS_RES_IRQ, 1, irq_err); + irq_err = NULL; + } if (sc->io_res) { bus_release_resource(self, SYS_RES_MEMORY, 0, sc->io_res); sc->io_res = NULL; @@ -294,6 +344,32 @@ ehci_mbus_detach(device_t self) return (0); } +static int +err_intr(void *arg) +{ + ehci_softc_t *sc = arg; + unsigned int cause; + + cause = EREAD4(sc, USB_BRIDGE_INTR_CAUSE); + if (cause) { + printf("IRQ ERR: cause: 0x%08x\n", cause); + if (cause & MV_USB_ADDR_DECODE_ERR) + printf("IRQ ERR: Address decoding error\n"); + if (cause & MV_USB_HOST_UNDERFLOW) + printf("IRQ ERR: USB Host Underflow\n"); + if (cause & MV_USB_HOST_OVERFLOW) + printf("IRQ ERR: USB Host Overflow\n"); + if (cause & MV_USB_DEVICE_UNDERFLOW) + printf("IRQ ERR: USB Device Underflow\n"); + if (cause & ~(MV_USB_ADDR_DECODE_ERR | MV_USB_HOST_UNDERFLOW | + MV_USB_HOST_OVERFLOW | MV_USB_DEVICE_UNDERFLOW)) + printf("IRQ ERR: Unknown error\n"); + + EWRITE4(sc, USB_BRIDGE_INTR_CAUSE, 0); + } + return (FILTER_HANDLED); +} + static device_method_t ehci_methods[] = { /* Device interface */ DEVMETHOD(device_probe, ehci_mbus_probe),