From owner-svn-src-all@FreeBSD.ORG Thu May 29 10:06:19 2014 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 82D23D72; Thu, 29 May 2014 10:06:19 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 6EF6D269B; Thu, 29 May 2014 10:06:19 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.8/8.14.8) with ESMTP id s4TA6JAt013609; Thu, 29 May 2014 10:06:19 GMT (envelope-from hselasky@svn.freebsd.org) Received: (from hselasky@localhost) by svn.freebsd.org (8.14.8/8.14.8/Submit) id s4TA6IBj013604; Thu, 29 May 2014 10:06:18 GMT (envelope-from hselasky@svn.freebsd.org) Message-Id: <201405291006.s4TA6IBj013604@svn.freebsd.org> From: Hans Petter Selasky Date: Thu, 29 May 2014 10:06:18 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r266831 - head/sys/dev/usb/controller X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 29 May 2014 10:06:19 -0000 Author: hselasky Date: Thu May 29 10:06:18 2014 New Revision: 266831 URL: http://svnweb.freebsd.org/changeset/base/266831 Log: Optimise the ISP/SAF1761 driver: - Use an interrupt filter for handling the data path interrupts. This increases the throughput significantly. - Implement support for USB suspend and resume in USB host mode. Sponsored by: DARPA, AFRL Modified: head/sys/dev/usb/controller/saf1761_otg.c head/sys/dev/usb/controller/saf1761_otg.h head/sys/dev/usb/controller/saf1761_otg_fdt.c Modified: head/sys/dev/usb/controller/saf1761_otg.c ============================================================================== --- head/sys/dev/usb/controller/saf1761_otg.c Thu May 29 07:45:45 2014 (r266830) +++ head/sys/dev/usb/controller/saf1761_otg.c Thu May 29 10:06:18 2014 (r266831) @@ -84,6 +84,13 @@ ((struct saf1761_otg_softc *)(((uint8_t *)(bus)) - \ ((uint8_t *)&(((struct saf1761_otg_softc *)0)->sc_bus)))) +#define SAF1761_OTG_PC2UDEV(pc) \ + (USB_DMATAG_TO_XROOT((pc)->tag_parent)->udev) + +#define SAF1761_DCINTERRUPT_THREAD_IRQ \ + (SOTG_DCINTERRUPT_IEVBUS | SOTG_DCINTERRUPT_IEBRST | \ + SOTG_DCINTERRUPT_IERESM | SOTG_DCINTERRUPT_IESUSP) + #ifdef USB_DEBUG static int saf1761_otg_debug = 0; static int saf1761_otg_forcefs = 0; @@ -201,7 +208,6 @@ saf1761_otg_wakeup_peer(struct saf1761_o /* Wait 8ms for remote wakeup to complete. */ usb_pause_mtx(&sc->sc_bus.bus_mtx, hz / 125); - } static uint8_t @@ -212,6 +218,10 @@ saf1761_host_channel_alloc(struct saf176 if (td->channel < SOTG_HOST_CHANNEL_MAX) return (0); + /* check if device is suspended */ + if (SAF1761_OTG_PC2UDEV(td->pc)->flags.self_suspended != 0) + return (1); /* busy - cannot transfer data */ + switch (td->ep_type) { case UE_INTERRUPT: for (x = 0; x != 32; x++) { @@ -257,19 +267,25 @@ saf1761_host_channel_free(struct saf1761 x = td->channel - 32; td->channel = SOTG_HOST_CHANNEL_MAX; sc->sc_host_intr_map &= ~(1 << x); - SAF1761_WRITE_LE_4(sc, SOTG_INT_PTD_SKIP_PTD, ~sc->sc_host_intr_map); + sc->sc_host_intr_suspend_map &= ~(1 << x); + SAF1761_WRITE_LE_4(sc, SOTG_INT_PTD_SKIP_PTD, + (~sc->sc_host_intr_map) | sc->sc_host_intr_suspend_map); break; case UE_ISOCHRONOUS: x = td->channel; td->channel = SOTG_HOST_CHANNEL_MAX; sc->sc_host_isoc_map &= ~(1 << x); - SAF1761_WRITE_LE_4(sc, SOTG_ISO_PTD_SKIP_PTD, ~sc->sc_host_isoc_map); + sc->sc_host_isoc_suspend_map &= ~(1 << x); + SAF1761_WRITE_LE_4(sc, SOTG_ISO_PTD_SKIP_PTD, + (~sc->sc_host_isoc_map) | sc->sc_host_isoc_suspend_map); break; default: x = td->channel - 64; td->channel = SOTG_HOST_CHANNEL_MAX; sc->sc_host_async_map &= ~(1 << x); - SAF1761_WRITE_LE_4(sc, SOTG_ATL_PTD_SKIP_PTD, ~sc->sc_host_async_map); + sc->sc_host_async_suspend_map &= ~(1 << x); + SAF1761_WRITE_LE_4(sc, SOTG_ATL_PTD_SKIP_PTD, + (~sc->sc_host_async_map) | sc->sc_host_async_suspend_map); break; } } @@ -447,7 +463,8 @@ saf1761_host_setup_tx(struct saf1761_otg SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW0, temp); /* activate PTD */ - SAF1761_WRITE_LE_4(sc, SOTG_ATL_PTD_SKIP_PTD, ~sc->sc_host_async_map); + SAF1761_WRITE_LE_4(sc, SOTG_ATL_PTD_SKIP_PTD, + (~sc->sc_host_async_map) | sc->sc_host_async_suspend_map); td->toggle = 1; busy: @@ -553,7 +570,8 @@ saf1761_host_bulk_data_rx(struct saf1761 SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW0, temp); /* activate PTD */ - SAF1761_WRITE_LE_4(sc, SOTG_ATL_PTD_SKIP_PTD, ~sc->sc_host_async_map); + SAF1761_WRITE_LE_4(sc, SOTG_ATL_PTD_SKIP_PTD, + (~sc->sc_host_async_map) | sc->sc_host_async_suspend_map); busy: return (1); /* busy */ complete: @@ -639,7 +657,8 @@ saf1761_host_bulk_data_tx(struct saf1761 SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW0, temp); /* activate PTD */ - SAF1761_WRITE_LE_4(sc, SOTG_ATL_PTD_SKIP_PTD, ~sc->sc_host_async_map); + SAF1761_WRITE_LE_4(sc, SOTG_ATL_PTD_SKIP_PTD, + (~sc->sc_host_async_map) | sc->sc_host_async_suspend_map); td->toggle ^= 1; busy: @@ -748,7 +767,8 @@ saf1761_host_intr_data_rx(struct saf1761 SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW0, temp); /* activate PTD */ - SAF1761_WRITE_LE_4(sc, SOTG_INT_PTD_SKIP_PTD, ~sc->sc_host_intr_map); + SAF1761_WRITE_LE_4(sc, SOTG_INT_PTD_SKIP_PTD, + (~sc->sc_host_intr_map) | sc->sc_host_intr_suspend_map); busy: return (1); /* busy */ complete: @@ -838,7 +858,8 @@ saf1761_host_intr_data_tx(struct saf1761 SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW0, temp); /* activate PTD */ - SAF1761_WRITE_LE_4(sc, SOTG_INT_PTD_SKIP_PTD, ~sc->sc_host_intr_map); + SAF1761_WRITE_LE_4(sc, SOTG_INT_PTD_SKIP_PTD, + (~sc->sc_host_intr_map) | sc->sc_host_intr_suspend_map); td->toggle ^= 1; busy: @@ -852,7 +873,8 @@ static uint8_t saf1761_host_isoc_data_rx(struct saf1761_otg_softc *sc, struct saf1761_otg_td *td) { /* activate PTD */ - SAF1761_WRITE_LE_4(sc, SOTG_ISO_PTD_SKIP_PTD, ~sc->sc_host_isoc_map); + SAF1761_WRITE_LE_4(sc, SOTG_ISO_PTD_SKIP_PTD, + (~sc->sc_host_isoc_map) | sc->sc_host_isoc_suspend_map); return (1); /* busy */ } @@ -861,7 +883,8 @@ static uint8_t saf1761_host_isoc_data_tx(struct saf1761_otg_softc *sc, struct saf1761_otg_td *td) { /* activate PTD */ - SAF1761_WRITE_LE_4(sc, SOTG_ISO_PTD_SKIP_PTD, ~sc->sc_host_isoc_map); + SAF1761_WRITE_LE_4(sc, SOTG_ISO_PTD_SKIP_PTD, + (~sc->sc_host_isoc_map) | sc->sc_host_isoc_suspend_map); return (1); /* busy */ } @@ -1222,7 +1245,7 @@ saf1761_device_data_tx_sync(struct saf17 return (0); /* complete */ } -static uint8_t +static void saf1761_otg_xfer_do_fifo(struct saf1761_otg_softc *sc, struct usb_xfer *xfer) { struct saf1761_otg_td *td; @@ -1231,6 +1254,9 @@ saf1761_otg_xfer_do_fifo(struct saf1761_ DPRINTFN(9, "\n"); td = xfer->td_transfer_cache; + if (td == NULL) + return; + while (1) { if ((td->func) (sc, td)) { /* operation in progress */ @@ -1258,28 +1284,37 @@ saf1761_otg_xfer_do_fifo(struct saf1761_ td->toggle = toggle; xfer->td_transfer_cache = td; } - return (1); /* not complete */ + return; done: /* compute all actual lengths */ + xfer->td_transfer_cache = NULL; + sc->sc_xfer_complete = 1; +} + +static uint8_t +saf1761_otg_xfer_do_complete(struct saf1761_otg_softc *sc, struct usb_xfer *xfer) +{ + struct saf1761_otg_td *td; - saf1761_otg_standard_done(xfer); + DPRINTFN(9, "\n"); - return (0); /* complete */ + td = xfer->td_transfer_cache; + if (td == NULL) { + /* compute all actual lengths */ + saf1761_otg_standard_done(xfer); + return (1); + } + return (0); } static void -saf1761_otg_interrupt_poll(struct saf1761_otg_softc *sc) +saf1761_otg_interrupt_poll_locked(struct saf1761_otg_softc *sc) { struct usb_xfer *xfer; -repeat: - TAILQ_FOREACH(xfer, &sc->sc_bus.intr_q.head, wait_entry) { - if (!saf1761_otg_xfer_do_fifo(sc, xfer)) { - /* queue has been modified */ - goto repeat; - } - } + TAILQ_FOREACH(xfer, &sc->sc_bus.intr_q.head, wait_entry) + saf1761_otg_xfer_do_fifo(sc, xfer); } static void @@ -1329,13 +1364,27 @@ saf1761_otg_update_vbus(struct saf1761_o } } -void -saf1761_otg_interrupt(struct saf1761_otg_softc *sc) +static void +saf1761_otg_interrupt_complete_locked(struct saf1761_otg_softc *sc) { - uint32_t status; + struct usb_xfer *xfer; +repeat: + /* scan for completion events */ + TAILQ_FOREACH(xfer, &sc->sc_bus.intr_q.head, wait_entry) { + if (saf1761_otg_xfer_do_complete(sc, xfer)) + goto repeat; + } +} + +int +saf1761_otg_filter_interrupt(void *arg) +{ + struct saf1761_otg_softc *sc = arg; + int retval = FILTER_HANDLED; uint32_t hcstat; + uint32_t status; - USB_BUS_LOCK(&sc->sc_bus); + USB_BUS_SPIN_LOCK(&sc->sc_bus); hcstat = SAF1761_READ_LE_4(sc, SOTG_HCINTERRUPT); /* acknowledge all host controller interrupts */ @@ -1343,17 +1392,47 @@ saf1761_otg_interrupt(struct saf1761_otg status = SAF1761_READ_LE_4(sc, SOTG_DCINTERRUPT); /* acknowledge all device controller interrupts */ - SAF1761_WRITE_LE_4(sc, SOTG_DCINTERRUPT, status); - - DPRINTF("DCINTERRUPT=0x%08x HCINTERRUPT=0x%08x SOF=0x%08x " - "FRINDEX=0x%08x\n", status, hcstat, - SAF1761_READ_LE_4(sc, SOTG_FRAME_NUM), - SAF1761_READ_LE_4(sc, SOTG_FRINDEX)); + SAF1761_WRITE_LE_4(sc, SOTG_DCINTERRUPT, + status & ~SAF1761_DCINTERRUPT_THREAD_IRQ); (void) SAF1761_READ_LE_4(sc, SOTG_ATL_PTD_DONE_PTD); (void) SAF1761_READ_LE_4(sc, SOTG_INT_PTD_DONE_PTD); (void) SAF1761_READ_LE_4(sc, SOTG_ISO_PTD_DONE_PTD); + if (status & SAF1761_DCINTERRUPT_THREAD_IRQ) + retval = FILTER_SCHEDULE_THREAD; + + /* poll FIFOs, if any */ + saf1761_otg_interrupt_poll_locked(sc); + + if (sc->sc_xfer_complete != 0) + retval = FILTER_SCHEDULE_THREAD; + + USB_BUS_SPIN_UNLOCK(&sc->sc_bus); + + return (retval); +} + +void +saf1761_otg_interrupt(void *arg) +{ + struct saf1761_otg_softc *sc = arg; + uint32_t status; + + USB_BUS_LOCK(&sc->sc_bus); + USB_BUS_SPIN_LOCK(&sc->sc_bus); + + status = SAF1761_READ_LE_4(sc, SOTG_DCINTERRUPT) & + SAF1761_DCINTERRUPT_THREAD_IRQ; + + /* acknowledge all device controller interrupts */ + SAF1761_WRITE_LE_4(sc, SOTG_DCINTERRUPT, status); + + DPRINTF("DCINTERRUPT=0x%08x SOF=0x%08x " + "FRINDEX=0x%08x\n", status, + SAF1761_READ_LE_4(sc, SOTG_FRAME_NUM), + SAF1761_READ_LE_4(sc, SOTG_FRINDEX)); + /* update VBUS and ID bits, if any */ if (status & SOTG_DCINTERRUPT_IEVBUS) saf1761_otg_update_vbus(sc); @@ -1405,9 +1484,14 @@ saf1761_otg_interrupt(struct saf1761_otg saf1761_otg_root_intr(sc); } } - /* poll all active transfers */ - saf1761_otg_interrupt_poll(sc); + if (sc->sc_xfer_complete != 0) { + sc->sc_xfer_complete = 0; + + /* complete FIFOs, if any */ + saf1761_otg_interrupt_complete_locked(sc); + } + USB_BUS_SPIN_UNLOCK(&sc->sc_bus); USB_BUS_UNLOCK(&sc->sc_bus); } @@ -1694,9 +1778,12 @@ saf1761_otg_start_standard_chain(struct DPRINTFN(9, "\n"); + USB_BUS_SPIN_LOCK(&sc->sc_bus); + /* poll one time */ - if (saf1761_otg_xfer_do_fifo(sc, xfer)) { + saf1761_otg_xfer_do_fifo(sc, xfer); + if (xfer->td_transfer_cache != NULL) { /* * Only enable the endpoint interrupt when we are * actually waiting for data, hence we are dealing @@ -1712,7 +1799,11 @@ saf1761_otg_start_standard_chain(struct usbd_transfer_timeout_ms(xfer, &saf1761_otg_timeout, xfer->timeout); } + } else { + /* catch completion, if any */ + saf1761_otg_interrupt_complete_locked(sc); } + USB_BUS_SPIN_UNLOCK(&sc->sc_bus); } static void @@ -1856,6 +1947,8 @@ saf1761_otg_device_done(struct usb_xfer DPRINTFN(2, "xfer=%p, endpoint=%p, error=%d\n", xfer, xfer->endpoint, error); + USB_BUS_SPIN_LOCK(&sc->sc_bus); + if (xfer->flags_int.usb_mode == USB_MODE_DEVICE) { saf1761_otg_intr_set(xfer, 0); } else { @@ -1869,6 +1962,8 @@ saf1761_otg_device_done(struct usb_xfer /* dequeue transfer and start next transfer */ usbd_transfer_done(xfer, error); + + USB_BUS_SPIN_UNLOCK(&sc->sc_bus); } static void @@ -1896,8 +1991,9 @@ saf1761_otg_set_stall(struct usb_device DPRINTFN(5, "endpoint=%p\n", ep); - /* set FORCESTALL */ + /* set STALL bit */ sc = SAF1761_OTG_BUS2SC(udev->bus); + ep_no = (ep->edesc->bEndpointAddress & UE_ADDR); ep_dir = (ep->edesc->bEndpointAddress & (UE_DIR_IN | UE_DIR_OUT)); ep_type = (ep->edesc->bmAttributes & UE_XFERTYPE); @@ -1906,6 +2002,8 @@ saf1761_otg_set_stall(struct usb_device /* should not happen */ return; } + USB_BUS_SPIN_LOCK(&sc->sc_bus); + /* select the correct endpoint */ SAF1761_WRITE_LE_4(sc, SOTG_EP_INDEX, (ep_no << SOTG_EP_INDEX_ENDP_INDEX_SHIFT) | @@ -1914,10 +2012,12 @@ saf1761_otg_set_stall(struct usb_device /* set stall */ SAF1761_WRITE_LE_4(sc, SOTG_CTRL_FUNC, SOTG_CTRL_FUNC_STALL); + + USB_BUS_SPIN_UNLOCK(&sc->sc_bus); } static void -saf1761_otg_clear_stall_sub(struct saf1761_otg_softc *sc, +saf1761_otg_clear_stall_sub_locked(struct saf1761_otg_softc *sc, uint8_t ep_no, uint8_t ep_type, uint8_t ep_dir) { if (ep_type == UE_CONTROL) { @@ -1959,14 +2059,18 @@ saf1761_otg_clear_stall(struct usb_devic /* get softc */ sc = SAF1761_OTG_BUS2SC(udev->bus); + USB_BUS_SPIN_LOCK(&sc->sc_bus); + /* get endpoint descriptor */ ed = ep->edesc; /* reset endpoint */ - saf1761_otg_clear_stall_sub(sc, + saf1761_otg_clear_stall_sub_locked(sc, (ed->bEndpointAddress & UE_ADDR), (ed->bmAttributes & UE_XFERTYPE), (ed->bEndpointAddress & (UE_DIR_IN | UE_DIR_OUT))); + + USB_BUS_SPIN_UNLOCK(&sc->sc_bus); } usb_error_t @@ -2218,7 +2322,10 @@ saf1761_otg_do_poll(struct usb_bus *bus) struct saf1761_otg_softc *sc = SAF1761_OTG_BUS2SC(bus); USB_BUS_LOCK(&sc->sc_bus); - saf1761_otg_interrupt_poll(sc); + USB_BUS_SPIN_LOCK(&sc->sc_bus); + saf1761_otg_interrupt_poll_locked(sc); + saf1761_otg_interrupt_complete_locked(sc); + USB_BUS_SPIN_UNLOCK(&sc->sc_bus); USB_BUS_UNLOCK(&sc->sc_bus); } @@ -3150,6 +3257,115 @@ saf1761_otg_set_hw_power_sleep(struct us } } +static void +saf1761_otg_device_resume(struct usb_device *udev) +{ + struct saf1761_otg_softc *sc; + struct saf1761_otg_td *td; + struct usb_xfer *xfer; + uint8_t x; + + DPRINTF("\n"); + + if (udev->flags.usb_mode != USB_MODE_HOST) + return; + + sc = SAF1761_OTG_BUS2SC(udev->bus); + + USB_BUS_LOCK(&sc->sc_bus); + USB_BUS_SPIN_LOCK(&sc->sc_bus); + + TAILQ_FOREACH(xfer, &sc->sc_bus.intr_q.head, wait_entry) { + + if (xfer->xroot->udev != udev) + continue; + + td = xfer->td_transfer_cache; + if (td == NULL || td->channel >= SOTG_HOST_CHANNEL_MAX) + continue; + + switch (td->ep_type) { + case UE_INTERRUPT: + x = td->channel - 32; + sc->sc_host_intr_suspend_map &= ~(1 << x); + SAF1761_WRITE_LE_4(sc, SOTG_INT_PTD_SKIP_PTD, + (~sc->sc_host_intr_map) | sc->sc_host_intr_suspend_map); + break; + case UE_ISOCHRONOUS: + x = td->channel; + sc->sc_host_isoc_suspend_map &= ~(1 << x); + SAF1761_WRITE_LE_4(sc, SOTG_ISO_PTD_SKIP_PTD, + (~sc->sc_host_isoc_map) | sc->sc_host_isoc_suspend_map); + break; + default: + x = td->channel - 64; + sc->sc_host_async_suspend_map &= ~(1 << x); + SAF1761_WRITE_LE_4(sc, SOTG_ATL_PTD_SKIP_PTD, + (~sc->sc_host_async_map) | sc->sc_host_async_suspend_map); + break; + } + } + + USB_BUS_SPIN_UNLOCK(&sc->sc_bus); + USB_BUS_UNLOCK(&sc->sc_bus); + + /* poll all transfers again to restart resumed ones */ + saf1761_otg_do_poll(&sc->sc_bus); +} + +static void +saf1761_otg_device_suspend(struct usb_device *udev) +{ + struct saf1761_otg_softc *sc; + struct saf1761_otg_td *td; + struct usb_xfer *xfer; + uint8_t x; + + DPRINTF("\n"); + + if (udev->flags.usb_mode != USB_MODE_HOST) + return; + + sc = SAF1761_OTG_BUS2SC(udev->bus); + + USB_BUS_LOCK(&sc->sc_bus); + USB_BUS_SPIN_LOCK(&sc->sc_bus); + + TAILQ_FOREACH(xfer, &sc->sc_bus.intr_q.head, wait_entry) { + + if (xfer->xroot->udev != udev) + continue; + + td = xfer->td_transfer_cache; + if (td == NULL || td->channel >= SOTG_HOST_CHANNEL_MAX) + continue; + + switch (td->ep_type) { + case UE_INTERRUPT: + x = td->channel - 32; + sc->sc_host_intr_suspend_map |= (1 << x); + SAF1761_WRITE_LE_4(sc, SOTG_INT_PTD_SKIP_PTD, + (~sc->sc_host_intr_map) | sc->sc_host_intr_suspend_map); + break; + case UE_ISOCHRONOUS: + x = td->channel; + sc->sc_host_isoc_suspend_map |= (1 << x); + SAF1761_WRITE_LE_4(sc, SOTG_ISO_PTD_SKIP_PTD, + (~sc->sc_host_isoc_map) | sc->sc_host_isoc_suspend_map); + break; + default: + x = td->channel - 64; + sc->sc_host_async_suspend_map |= (1 << x); + SAF1761_WRITE_LE_4(sc, SOTG_ATL_PTD_SKIP_PTD, + (~sc->sc_host_async_map) | sc->sc_host_async_suspend_map); + break; + } + } + + USB_BUS_SPIN_UNLOCK(&sc->sc_bus); + USB_BUS_UNLOCK(&sc->sc_bus); +} + static const struct usb_bus_methods saf1761_otg_bus_methods = { .endpoint_init = &saf1761_otg_ep_init, @@ -3162,4 +3378,6 @@ static const struct usb_bus_methods saf1 .roothub_exec = &saf1761_otg_roothub_exec, .xfer_poll = &saf1761_otg_do_poll, .set_hw_power_sleep = saf1761_otg_set_hw_power_sleep, + .device_resume = &saf1761_otg_device_resume, + .device_suspend = &saf1761_otg_device_suspend, }; Modified: head/sys/dev/usb/controller/saf1761_otg.h ============================================================================== --- head/sys/dev/usb/controller/saf1761_otg.h Thu May 29 07:45:45 2014 (r266830) +++ head/sys/dev/usb/controller/saf1761_otg.h Thu May 29 10:06:18 2014 (r266831) @@ -140,11 +140,15 @@ struct saf1761_otg_softc { bus_space_handle_t sc_io_hdl; uint32_t sc_host_async_map; + uint32_t sc_host_async_suspend_map; uint32_t sc_host_intr_map; + uint32_t sc_host_intr_suspend_map; uint32_t sc_host_isoc_map; + uint32_t sc_host_isoc_suspend_map; uint32_t sc_intr_enable; /* enabled interrupts */ uint32_t sc_hw_mode; /* hardware mode */ uint32_t sc_interrupt_cfg; /* interrupt configuration */ + uint32_t sc_xfer_complete; uint32_t sc_bounce_buffer[1024 / 4]; @@ -162,6 +166,7 @@ struct saf1761_otg_softc { usb_error_t saf1761_otg_init(struct saf1761_otg_softc *sc); void saf1761_otg_uninit(struct saf1761_otg_softc *sc); -void saf1761_otg_interrupt(struct saf1761_otg_softc *sc); +driver_filter_t saf1761_otg_filter_interrupt; +driver_intr_t saf1761_otg_interrupt; #endif /* _SAF1761_OTG_H_ */ Modified: head/sys/dev/usb/controller/saf1761_otg_fdt.c ============================================================================== --- head/sys/dev/usb/controller/saf1761_otg_fdt.c Thu May 29 07:45:45 2014 (r266830) +++ head/sys/dev/usb/controller/saf1761_otg_fdt.c Thu May 29 10:06:18 2014 (r266831) @@ -210,8 +210,8 @@ saf1761_otg_fdt_attach(device_t dev) device_set_ivars(sc->sc_bus.bdev, &sc->sc_bus); - err = bus_setup_intr(dev, sc->sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE, - NULL, (driver_intr_t *)saf1761_otg_interrupt, sc, &sc->sc_intr_hdl); + err = bus_setup_intr(dev, sc->sc_irq_res, INTR_TYPE_TTY | INTR_MPSAFE, + &saf1761_otg_filter_interrupt, &saf1761_otg_interrupt, sc, &sc->sc_intr_hdl); if (err) { sc->sc_intr_hdl = NULL; goto error;