--- dwc2.c Wed Mar 31 07:42:18 2021 +++ /usr/src/sys/dev/usb/dwc2/dwc2.c Mon Jul 19 19:42:08 2021 @@ -1,4 +1,5 @@ -/* $NetBSD: dwc2.c,v 1.76 2021/01/07 13:25:51 skrll Exp $ */ +/* $OpenBSD: dwc2.c,v 1.53 2021/01/28 01:48:54 kurt Exp $ */ +/* $NetBSD: dwc2.c,v 1.32 2014/09/02 23:26:20 macallan Exp $ */ /*- * Copyright (c) 2013 The NetBSD Foundation, Inc. @@ -29,36 +30,28 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#include -__KERNEL_RCSID(0, "$NetBSD: dwc2.c,v 1.76 2021/01/07 13:25:51 skrll Exp $"); - -#include "opt_usb.h" - #include - -#include -#include +#include +#include #include -#include +#include +#include #include #include -#include -#include -#include +#include -#include +#include #include #include #include #include -#include -#include -#include +#include +#include -#include "dwc2_core.h" -#include "dwc2_hcd.h" +#include +#include #ifdef DWC2_COUNTERS #define DWC2_EVCNT_ADD(a,b) ((void)((a).ev_count += (b))) @@ -76,90 +69,69 @@ __KERNEL_RCSID(0, "$NetBSD: dwc2.c,v 1.76 2021/01/07 1 } while (0) #define DPRINTF(...) DPRINTFN(1, __VA_ARGS__) int dwc2debug = 0; - -SYSCTL_SETUP(sysctl_hw_dwc2_setup, "sysctl hw.dwc2 setup") -{ - int err; - const struct sysctlnode *rnode; - const struct sysctlnode *cnode; - - err = sysctl_createv(clog, 0, NULL, &rnode, - CTLFLAG_PERMANENT, CTLTYPE_NODE, "dwc2", - SYSCTL_DESCR("dwc2 global controls"), - NULL, 0, NULL, 0, CTL_HW, CTL_CREATE, CTL_EOL); - - if (err) - goto fail; - - /* control debugging printfs */ - err = sysctl_createv(clog, 0, &rnode, &cnode, - CTLFLAG_PERMANENT|CTLFLAG_READWRITE, CTLTYPE_INT, - "debug", SYSCTL_DESCR("Enable debugging output"), - NULL, 0, &dwc2debug, sizeof(dwc2debug), CTL_CREATE, CTL_EOL); - if (err) - goto fail; - - return; -fail: - aprint_error("%s: sysctl_createv failed (err = %d)\n", __func__, err); -} #else #define DPRINTF(...) do { } while (0) #define DPRINTFN(...) do { } while (0) #endif -Static usbd_status dwc2_open(struct usbd_pipe *); -Static void dwc2_poll(struct usbd_bus *); -Static void dwc2_softintr(void *); +STATIC usbd_status dwc2_open(struct usbd_pipe *); +STATIC int dwc2_setaddr(struct usbd_device *, int); +STATIC void dwc2_poll(struct usbd_bus *); +STATIC void dwc2_softintr(void *); -Static struct usbd_xfer * - dwc2_allocx(struct usbd_bus *, unsigned int); -Static void dwc2_freex(struct usbd_bus *, struct usbd_xfer *); -Static void dwc2_get_lock(struct usbd_bus *, kmutex_t **); -Static bool dwc2_dying(struct usbd_bus *); -Static int dwc2_roothub_ctrl(struct usbd_bus *, usb_device_request_t *, - void *, int); +STATIC struct usbd_xfer *dwc2_allocx(struct usbd_bus *); +STATIC void dwc2_freex(struct usbd_bus *, struct usbd_xfer *); -Static usbd_status dwc2_root_intr_transfer(struct usbd_xfer *); -Static usbd_status dwc2_root_intr_start(struct usbd_xfer *); -Static void dwc2_root_intr_abort(struct usbd_xfer *); -Static void dwc2_root_intr_close(struct usbd_pipe *); -Static void dwc2_root_intr_done(struct usbd_xfer *); +STATIC usbd_status dwc2_root_ctrl_transfer(struct usbd_xfer *); +STATIC usbd_status dwc2_root_ctrl_start(struct usbd_xfer *); +STATIC void dwc2_root_ctrl_abort(struct usbd_xfer *); +STATIC void dwc2_root_ctrl_close(struct usbd_pipe *); +STATIC void dwc2_root_ctrl_done(struct usbd_xfer *); -Static usbd_status dwc2_device_ctrl_transfer(struct usbd_xfer *); -Static usbd_status dwc2_device_ctrl_start(struct usbd_xfer *); -Static void dwc2_device_ctrl_abort(struct usbd_xfer *); -Static void dwc2_device_ctrl_close(struct usbd_pipe *); -Static void dwc2_device_ctrl_done(struct usbd_xfer *); +STATIC usbd_status dwc2_root_intr_transfer(struct usbd_xfer *); +STATIC usbd_status dwc2_root_intr_start(struct usbd_xfer *); +STATIC void dwc2_root_intr_abort(struct usbd_xfer *); +STATIC void dwc2_root_intr_close(struct usbd_pipe *); +STATIC void dwc2_root_intr_done(struct usbd_xfer *); -Static usbd_status dwc2_device_bulk_transfer(struct usbd_xfer *); -Static void dwc2_device_bulk_abort(struct usbd_xfer *); -Static void dwc2_device_bulk_close(struct usbd_pipe *); -Static void dwc2_device_bulk_done(struct usbd_xfer *); +STATIC usbd_status dwc2_device_ctrl_transfer(struct usbd_xfer *); +STATIC usbd_status dwc2_device_ctrl_start(struct usbd_xfer *); +STATIC void dwc2_device_ctrl_abort(struct usbd_xfer *); +STATIC void dwc2_device_ctrl_close(struct usbd_pipe *); +STATIC void dwc2_device_ctrl_done(struct usbd_xfer *); -Static usbd_status dwc2_device_intr_transfer(struct usbd_xfer *); -Static usbd_status dwc2_device_intr_start(struct usbd_xfer *); -Static void dwc2_device_intr_abort(struct usbd_xfer *); -Static void dwc2_device_intr_close(struct usbd_pipe *); -Static void dwc2_device_intr_done(struct usbd_xfer *); +STATIC usbd_status dwc2_device_bulk_transfer(struct usbd_xfer *); +STATIC usbd_status dwc2_device_bulk_start(struct usbd_xfer *); +STATIC void dwc2_device_bulk_abort(struct usbd_xfer *); +STATIC void dwc2_device_bulk_close(struct usbd_pipe *); +STATIC void dwc2_device_bulk_done(struct usbd_xfer *); -Static usbd_status dwc2_device_isoc_transfer(struct usbd_xfer *); -Static void dwc2_device_isoc_abort(struct usbd_xfer *); -Static void dwc2_device_isoc_close(struct usbd_pipe *); -Static void dwc2_device_isoc_done(struct usbd_xfer *); +STATIC usbd_status dwc2_device_intr_transfer(struct usbd_xfer *); +STATIC usbd_status dwc2_device_intr_start(struct usbd_xfer *); +STATIC void dwc2_device_intr_abort(struct usbd_xfer *); +STATIC void dwc2_device_intr_close(struct usbd_pipe *); +STATIC void dwc2_device_intr_done(struct usbd_xfer *); -Static usbd_status dwc2_device_start(struct usbd_xfer *); +STATIC usbd_status dwc2_device_isoc_transfer(struct usbd_xfer *); +STATIC usbd_status dwc2_device_isoc_start(struct usbd_xfer *); +STATIC void dwc2_device_isoc_abort(struct usbd_xfer *); +STATIC void dwc2_device_isoc_close(struct usbd_pipe *); +STATIC void dwc2_device_isoc_done(struct usbd_xfer *); -Static void dwc2_close_pipe(struct usbd_pipe *); -Static void dwc2_abortx(struct usbd_xfer *); +STATIC usbd_status dwc2_device_start(struct usbd_xfer *); -Static void dwc2_device_clear_toggle(struct usbd_pipe *); -Static void dwc2_noop(struct usbd_pipe *pipe); +STATIC void dwc2_close_pipe(struct usbd_pipe *); +STATIC void dwc2_abort_xfer(struct usbd_xfer *, usbd_status); -Static int dwc2_interrupt(struct dwc2_softc *); -Static void dwc2_rhc(void *); +STATIC void dwc2_device_clear_toggle(struct usbd_pipe *); +STATIC void dwc2_noop(struct usbd_pipe *pipe); +STATIC int dwc2_interrupt(struct dwc2_softc *); +STATIC void dwc2_rhc(void *); +STATIC void dwc2_timeout(void *); +STATIC void dwc2_timeout_task(void *); + static inline void dwc2_allocate_bus_bandwidth(struct dwc2_hsotg *hsotg, u16 bw, struct usbd_xfer *xfer) @@ -172,63 +144,96 @@ dwc2_free_bus_bandwidth(struct dwc2_hsotg *hsotg, u16 { } -Static const struct usbd_bus_methods dwc2_bus_methods = { - .ubm_open = dwc2_open, - .ubm_softint = dwc2_softintr, - .ubm_dopoll = dwc2_poll, - .ubm_allocx = dwc2_allocx, - .ubm_freex = dwc2_freex, - .ubm_abortx = dwc2_abortx, - .ubm_dying = dwc2_dying, - .ubm_getlock = dwc2_get_lock, - .ubm_rhctrl = dwc2_roothub_ctrl, +#define DWC2_INTR_ENDPT 1 + +STATIC struct usbd_bus_methods dwc2_bus_methods = { + .open_pipe = dwc2_open, + .dev_setaddr = dwc2_setaddr, + .soft_intr = dwc2_softintr, + .do_poll = dwc2_poll, + .allocx = dwc2_allocx, + .freex = dwc2_freex, }; -Static const struct usbd_pipe_methods dwc2_root_intr_methods = { - .upm_transfer = dwc2_root_intr_transfer, - .upm_start = dwc2_root_intr_start, - .upm_abort = dwc2_root_intr_abort, - .upm_close = dwc2_root_intr_close, - .upm_cleartoggle = dwc2_noop, - .upm_done = dwc2_root_intr_done, +STATIC struct usbd_pipe_methods dwc2_root_ctrl_methods = { + .transfer = dwc2_root_ctrl_transfer, + .start = dwc2_root_ctrl_start, + .abort = dwc2_root_ctrl_abort, + .close = dwc2_root_ctrl_close, + .cleartoggle = dwc2_noop, + .done = dwc2_root_ctrl_done, }; -Static const struct usbd_pipe_methods dwc2_device_ctrl_methods = { - .upm_transfer = dwc2_device_ctrl_transfer, - .upm_start = dwc2_device_ctrl_start, - .upm_abort = dwc2_device_ctrl_abort, - .upm_close = dwc2_device_ctrl_close, - .upm_cleartoggle = dwc2_noop, - .upm_done = dwc2_device_ctrl_done, +STATIC struct usbd_pipe_methods dwc2_root_intr_methods = { + .transfer = dwc2_root_intr_transfer, + .start = dwc2_root_intr_start, + .abort = dwc2_root_intr_abort, + .close = dwc2_root_intr_close, + .cleartoggle = dwc2_noop, + .done = dwc2_root_intr_done, }; -Static const struct usbd_pipe_methods dwc2_device_intr_methods = { - .upm_transfer = dwc2_device_intr_transfer, - .upm_start = dwc2_device_intr_start, - .upm_abort = dwc2_device_intr_abort, - .upm_close = dwc2_device_intr_close, - .upm_cleartoggle = dwc2_device_clear_toggle, - .upm_done = dwc2_device_intr_done, +STATIC struct usbd_pipe_methods dwc2_device_ctrl_methods = { + .transfer = dwc2_device_ctrl_transfer, + .start = dwc2_device_ctrl_start, + .abort = dwc2_device_ctrl_abort, + .close = dwc2_device_ctrl_close, + .cleartoggle = dwc2_noop, + .done = dwc2_device_ctrl_done, }; -Static const struct usbd_pipe_methods dwc2_device_bulk_methods = { - .upm_transfer = dwc2_device_bulk_transfer, - .upm_abort = dwc2_device_bulk_abort, - .upm_close = dwc2_device_bulk_close, - .upm_cleartoggle = dwc2_device_clear_toggle, - .upm_done = dwc2_device_bulk_done, +STATIC struct usbd_pipe_methods dwc2_device_intr_methods = { + .transfer = dwc2_device_intr_transfer, + .start = dwc2_device_intr_start, + .abort = dwc2_device_intr_abort, + .close = dwc2_device_intr_close, + .cleartoggle = dwc2_device_clear_toggle, + .done = dwc2_device_intr_done, }; -Static const struct usbd_pipe_methods dwc2_device_isoc_methods = { - .upm_transfer = dwc2_device_isoc_transfer, - .upm_abort = dwc2_device_isoc_abort, - .upm_close = dwc2_device_isoc_close, - .upm_cleartoggle = dwc2_noop, - .upm_done = dwc2_device_isoc_done, +STATIC struct usbd_pipe_methods dwc2_device_bulk_methods = { + .transfer = dwc2_device_bulk_transfer, + .start = dwc2_device_bulk_start, + .abort = dwc2_device_bulk_abort, + .close = dwc2_device_bulk_close, + .cleartoggle = dwc2_device_clear_toggle, + .done = dwc2_device_bulk_done, }; +STATIC struct usbd_pipe_methods dwc2_device_isoc_methods = { + .transfer = dwc2_device_isoc_transfer, + .start = dwc2_device_isoc_start, + .abort = dwc2_device_isoc_abort, + .close = dwc2_device_isoc_close, + .cleartoggle = dwc2_noop, + .done = dwc2_device_isoc_done, +}; + +/* + * Work around the half configured control (default) pipe when setting + * the address of a device. + */ +STATIC int +dwc2_setaddr(struct usbd_device *dev, int addr) +{ + if (usbd_set_address(dev, addr)) + return (1); + + dev->address = addr; + + /* + * Re-establish the default pipe with the new address and the + * new max packet size. + */ + dwc2_close_pipe(dev->default_pipe); + if (dwc2_open(dev->default_pipe)) + return (EINVAL); + + return (0); +} + struct usbd_xfer * -dwc2_allocx(struct usbd_bus *bus, unsigned int nframes) +dwc2_allocx(struct usbd_bus *bus) { struct dwc2_softc *sc = DWC2_BUS2SC(bus); struct dwc2_xfer *dxfer; @@ -236,13 +241,13 @@ dwc2_allocx(struct usbd_bus *bus, unsigned int nframes DPRINTFN(10, "\n"); DWC2_EVCNT_INCR(sc->sc_ev_xferpoolget); - dxfer = pool_cache_get(sc->sc_xferpool, PR_WAITOK); + dxfer = pool_get(&sc->sc_xferpool, PR_WAITOK); if (dxfer != NULL) { memset(dxfer, 0, sizeof(*dxfer)); dxfer->urb = dwc2_hcd_urb_alloc(sc->sc_hsotg, - nframes, GFP_KERNEL); + DWC2_MAXISOCPACKETS, M_NOWAIT); #ifdef DIAGNOSTIC - dxfer->xfer.ux_state = XFER_BUSY; + dxfer->xfer.busy_free = XFER_ONQU; #endif } return (struct usbd_xfer *)dxfer; @@ -257,34 +262,18 @@ dwc2_freex(struct usbd_bus *bus, struct usbd_xfer *xfe DPRINTFN(10, "\n"); #ifdef DIAGNOSTIC - if (xfer->ux_state != XFER_BUSY && - xfer->ux_status != USBD_NOT_STARTED) { - DPRINTF("xfer=%p not busy, 0x%08x\n", xfer, xfer->ux_state); + if (xfer->busy_free != XFER_ONQU && + xfer->status != USBD_NOT_STARTED) { + DPRINTF("xfer=%p not busy, 0x%08x\n", xfer, xfer->busy_free); } - xfer->ux_state = XFER_FREE; + xfer->busy_free = XFER_FREE; #endif DWC2_EVCNT_INCR(sc->sc_ev_xferpoolput); - dwc2_hcd_urb_free(sc->sc_hsotg, dxfer->urb, dxfer->urb->packet_count); - pool_cache_put(sc->sc_xferpool, xfer); + dwc2_hcd_urb_free(sc->sc_hsotg, dxfer->urb, DWC2_MAXISOCPACKETS); + pool_put(&sc->sc_xferpool, xfer); } -Static bool -dwc2_dying(struct usbd_bus *bus) -{ - struct dwc2_softc *sc = DWC2_BUS2SC(bus); - - return sc->sc_dying; -} - -Static void -dwc2_get_lock(struct usbd_bus *bus, kmutex_t **lock) -{ - struct dwc2_softc *sc = DWC2_BUS2SC(bus); - - *lock = &sc->sc_lock; -} - -Static void +STATIC void dwc2_rhc(void *addr) { struct dwc2_softc *sc = addr; @@ -292,30 +281,29 @@ dwc2_rhc(void *addr) u_char *p; DPRINTF("\n"); - mutex_enter(&sc->sc_lock); + mtx_enter(&sc->sc_lock); xfer = sc->sc_intrxfer; if (xfer == NULL) { /* Just ignore the change. */ - mutex_exit(&sc->sc_lock); + mtx_leave(&sc->sc_lock); return; } - KASSERT(xfer->ux_status == USBD_IN_PROGRESS); /* set port bit */ - p = KERNADDR(&xfer->ux_dmabuf, 0); + p = KERNADDR(&xfer->dmabuf, 0); p[0] = 0x02; /* we only have one port (1 << 1) */ - xfer->ux_actlen = xfer->ux_length; - xfer->ux_status = USBD_NORMAL_COMPLETION; + xfer->actlen = xfer->length; + xfer->status = USBD_NORMAL_COMPLETION; usb_transfer_complete(xfer); - mutex_exit(&sc->sc_lock); + mtx_leave(&sc->sc_lock); } -Static void +STATIC void dwc2_softintr(void *v) { struct usbd_bus *bus = v; @@ -324,8 +312,6 @@ dwc2_softintr(void *v) struct dwc2_xfer *dxfer, *next; TAILQ_HEAD(, dwc2_xfer) claimed = TAILQ_HEAD_INITIALIZER(claimed); - KASSERT(sc->sc_bus.ub_usepolling || mutex_owned(&sc->sc_lock)); - /* * Grab all the xfers that have not been aborted or timed out. * Do so under a single lock -- without dropping it to run @@ -333,63 +319,86 @@ dwc2_softintr(void *v) * remove next out from under us during iteration when we've * dropped the lock. */ - mutex_spin_enter(&hsotg->lock); + mtx_enter(&hsotg->lock); TAILQ_FOREACH_SAFE(dxfer, &sc->sc_complete, xnext, next) { - if (!usbd_xfer_trycomplete(&dxfer->xfer)) - /* - * The hard interrput handler decided to - * complete the xfer, and put it on sc_complete - * to pass it to us in the soft interrupt - * handler, but in the time between hard - * interrupt and soft interrupt, the xfer was - * aborted or timed out and we lost the race. - */ - continue; - KASSERT(dxfer->xfer.ux_status == USBD_IN_PROGRESS); + KASSERT(dxfer->xfer.status == USBD_IN_PROGRESS); KASSERT(dxfer->intr_status != USBD_CANCELLED); KASSERT(dxfer->intr_status != USBD_TIMEOUT); TAILQ_REMOVE(&sc->sc_complete, dxfer, xnext); TAILQ_INSERT_TAIL(&claimed, dxfer, xnext); } - mutex_spin_exit(&hsotg->lock); + mtx_leave(&hsotg->lock); /* Now complete them. */ while (!TAILQ_EMPTY(&claimed)) { dxfer = TAILQ_FIRST(&claimed); - KASSERT(dxfer->xfer.ux_status == USBD_IN_PROGRESS); + KASSERT(dxfer->xfer.status == USBD_IN_PROGRESS); KASSERT(dxfer->intr_status != USBD_CANCELLED); KASSERT(dxfer->intr_status != USBD_TIMEOUT); TAILQ_REMOVE(&claimed, dxfer, xnext); - dxfer->xfer.ux_status = dxfer->intr_status; + dxfer->xfer.status = dxfer->intr_status; usb_transfer_complete(&dxfer->xfer); } } +STATIC void +dwc2_timeout(void *addr) +{ + struct usbd_xfer *xfer = addr; + struct dwc2_softc *sc = DWC2_XFER2SC(xfer); + + DPRINTF("xfer=%p\n", xfer); + + if (sc->sc_bus.dying) { + dwc2_timeout_task(addr); + return; + } + + /* Execute the abort in a process context. */ + usb_init_task(&xfer->abort_task, dwc2_timeout_task, addr, + USB_TASK_TYPE_ABORT); + usb_add_task(xfer->device, &xfer->abort_task); +} + +STATIC void +dwc2_timeout_task(void *addr) +{ + struct usbd_xfer *xfer = addr; + int s; + + DPRINTF("xfer=%p\n", xfer); + + s = splusb(); + dwc2_abort_xfer(xfer, USBD_TIMEOUT); + splx(s); +} + usbd_status dwc2_open(struct usbd_pipe *pipe) { - struct usbd_device *dev = pipe->up_dev; + struct usbd_device *dev = pipe->device; struct dwc2_softc *sc = DWC2_PIPE2SC(pipe); struct dwc2_pipe *dpipe = DWC2_PIPE2DPIPE(pipe); - usb_endpoint_descriptor_t *ed = pipe->up_endpoint->ue_edesc; - uint8_t addr = dev->ud_addr; + usb_endpoint_descriptor_t *ed = pipe->endpoint->edesc; + uint8_t addr = dev->address; uint8_t xfertype = UE_GET_XFERTYPE(ed->bmAttributes); + usbd_status err; DPRINTF("pipe %p addr %d xfertype %d dir %s\n", pipe, addr, xfertype, UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN ? "in" : "out"); - if (sc->sc_dying) { + if (sc->sc_bus.dying) { return USBD_IOERROR; } - if (addr == dev->ud_bus->ub_rhaddr) { + if (addr == sc->sc_addr) { switch (ed->bEndpointAddress) { case USB_CONTROL_ENDPOINT: - pipe->up_methods = &roothub_ctrl_methods; + pipe->methods = &dwc2_root_ctrl_methods; break; - case UE_DIR_IN | USBROOTHUB_INTR_ENDPT: - pipe->up_methods = &dwc2_root_intr_methods; + case UE_DIR_IN | DWC2_INTR_ENDPT: + pipe->methods = &dwc2_root_intr_methods; break; default: DPRINTF("bad bEndpointAddress 0x%02x\n", @@ -402,22 +411,20 @@ dwc2_open(struct usbd_pipe *pipe) switch (xfertype) { case UE_CONTROL: - pipe->up_methods = &dwc2_device_ctrl_methods; - int err = usb_allocmem(&sc->sc_bus, sizeof(usb_device_request_t), - 0, USBMALLOC_COHERENT, &dpipe->req_dma); + pipe->methods = &dwc2_device_ctrl_methods; + err = usb_allocmem(&sc->sc_bus, sizeof(usb_device_request_t), + 0, USB_DMA_COHERENT, &dpipe->req_dma); if (err) return USBD_NOMEM; break; case UE_INTERRUPT: - pipe->up_methods = &dwc2_device_intr_methods; + pipe->methods = &dwc2_device_intr_methods; break; case UE_ISOCHRONOUS: - pipe->up_serialise = false; - pipe->up_methods = &dwc2_device_isoc_methods; + pipe->methods = &dwc2_device_isoc_methods; break; case UE_BULK: - pipe->up_serialise = false; - pipe->up_methods = &dwc2_device_bulk_methods; + pipe->methods = &dwc2_device_bulk_methods; break; default: DPRINTF("bad xfer type %d\n", xfertype); @@ -430,135 +437,206 @@ dwc2_open(struct usbd_pipe *pipe) return USBD_NORMAL_COMPLETION; } -Static void +STATIC void dwc2_poll(struct usbd_bus *bus) { struct dwc2_softc *sc = DWC2_BUS2SC(bus); struct dwc2_hsotg *hsotg = sc->sc_hsotg; - mutex_spin_enter(&hsotg->lock); + mtx_enter(&hsotg->lock); dwc2_interrupt(sc); - mutex_spin_exit(&hsotg->lock); + mtx_leave(&hsotg->lock); } /* * Close a reqular pipe. * Assumes that there are no pending transactions. */ -Static void +STATIC void dwc2_close_pipe(struct usbd_pipe *pipe) { - struct dwc2_softc *sc __diagused = pipe->up_dev->ud_bus->ub_hcpriv; - - KASSERT(mutex_owned(&sc->sc_lock)); + /* nothing */ } /* * Abort a device request. */ -Static void -dwc2_abortx(struct usbd_xfer *xfer) +STATIC void +dwc2_abort_xfer(struct usbd_xfer *xfer, usbd_status status) { struct dwc2_xfer *dxfer = DWC2_XFER2DXFER(xfer); struct dwc2_softc *sc = DWC2_XFER2SC(xfer); struct dwc2_hsotg *hsotg = sc->sc_hsotg; - struct dwc2_xfer *d; + struct dwc2_xfer *d, *tmp; + bool wake; int err; - DPRINTF("xfer %p pipe %p status 0x%08x", xfer, xfer->ux_pipe, - xfer->ux_status); + splsoftassert(IPL_SOFTUSB); - KASSERT(mutex_owned(&sc->sc_lock)); - ASSERT_SLEEPABLE(); + DPRINTF("xfer=%p\n", xfer); - KASSERTMSG((xfer->ux_status == USBD_CANCELLED || - xfer->ux_status == USBD_TIMEOUT), - "bad abort status: %d", xfer->ux_status); + if (sc->sc_bus.dying) { + xfer->status = status; + timeout_del(&xfer->timeout_handle); + usb_rem_task(xfer->device, &xfer->abort_task); + usb_transfer_complete(xfer); + return; + } - mutex_spin_enter(&hsotg->lock); - /* - * Check whether we aborted or timed out after the hardware - * completion interrupt determined that it's done but before - * the soft interrupt could actually complete it. If so, it's - * too late for the soft interrupt -- at this point we've - * already committed to abort it or time it out, so we need to - * take it off the softint's list of work in case the caller, - * say, frees the xfer before the softint runs. - * - * This logic is unusual among host controller drivers, and - * happens because dwc2 decides to complete xfers in the hard - * interrupt handler rather than in the soft interrupt handler, - * but usb_transfer_complete must be deferred to softint -- and - * we happened to swoop in between the hard interrupt and the - * soft interrupt. Other host controller drivers do almost all - * processing in the softint so there's no intermediate stage. - * - * Fortunately, this linear search to discern the intermediate - * stage is not likely to be a serious performance impact - * because it happens only on abort or timeout. + * If an abort is already in progress then just wait for it to + * complete and return. */ - TAILQ_FOREACH(d, &sc->sc_complete, xnext) { - if (d == dxfer) { - TAILQ_REMOVE(&sc->sc_complete, dxfer, xnext); - break; - } + if (dxfer->flags & DWC2_XFER_ABORTING) { + xfer->status = status; + dxfer->flags |= DWC2_XFER_ABORTWAIT; + while (dxfer->flags & DWC2_XFER_ABORTING) + tsleep_nsec(&dxfer->flags, PZERO, "dwc2xfer", INFSLP); + return; } - /* - * If we're dying, skip the hardware action and just notify the - * software that we're done. - */ - if (sc->sc_dying) { - DPRINTFN(4, "xfer %p dying 0x%08x", xfer, xfer->ux_status); - goto dying; + mtx_enter(&hsotg->lock); + + /* The transfer might have been completed already. */ + if (xfer->status != USBD_IN_PROGRESS) { + DPRINTF("xfer=%p already completed\n", xfer); + mtx_leave(&hsotg->lock); + return; } /* - * HC Step 1: Handle the hardware. + * Step 1: Make the stack ignore it and stop the timeout. */ + dxfer->flags |= DWC2_XFER_ABORTING; + + xfer->status = status; /* make software ignore it */ + timeout_del(&xfer->timeout_handle); + usb_rem_task(xfer->device, &xfer->abort_task); + + /* XXXNH suboptimal */ + TAILQ_FOREACH_SAFE(d, &sc->sc_complete, xnext, tmp) { + if (d == dxfer) { + TAILQ_REMOVE(&sc->sc_complete, dxfer, xnext); + } + } + err = dwc2_hcd_urb_dequeue(hsotg, dxfer->urb); if (err) { DPRINTF("dwc2_hcd_urb_dequeue failed\n"); } -dying: - mutex_spin_exit(&hsotg->lock); + mtx_leave(&hsotg->lock); /* - * Final Step: Notify completion to waiting xfers. + * Step 2: Execute callback. */ + wake = dxfer->flags & DWC2_XFER_ABORTWAIT; + dxfer->flags &= ~(DWC2_XFER_ABORTING | DWC2_XFER_ABORTWAIT); + usb_transfer_complete(xfer); - KASSERT(mutex_owned(&sc->sc_lock)); + if (wake) { + wakeup(&dxfer->flags); + } } -Static void +STATIC void dwc2_noop(struct usbd_pipe *pipe) { } -Static void +STATIC void dwc2_device_clear_toggle(struct usbd_pipe *pipe) { - DPRINTF("toggle %d -> 0", pipe->up_endpoint->ue_toggle); + DPRINTF("toggle %d -> 0", pipe->endpoint->savedtoggle); } /***********************************************************************/ -Static int -dwc2_roothub_ctrl(struct usbd_bus *bus, usb_device_request_t *req, - void *buf, int buflen) +/* + * Data structures and routines to emulate the root hub. + */ + +STATIC const usb_device_descriptor_t dwc2_devd = { + .bLength = sizeof(usb_device_descriptor_t), + .bDescriptorType = UDESC_DEVICE, + .bcdUSB = {0x00, 0x02}, + .bDeviceClass = UDCLASS_HUB, + .bDeviceSubClass = UDSUBCLASS_HUB, + .bDeviceProtocol = UDPROTO_HSHUBSTT, + .bMaxPacketSize = 64, + .bcdDevice = {0x00, 0x01}, + .iManufacturer = 1, + .iProduct = 2, + .bNumConfigurations = 1, +}; + +struct dwc2_config_desc { + usb_config_descriptor_t confd; + usb_interface_descriptor_t ifcd; + usb_endpoint_descriptor_t endpd; +} __packed; + +STATIC const struct dwc2_config_desc dwc2_confd = { + .confd = { + .bLength = USB_CONFIG_DESCRIPTOR_SIZE, + .bDescriptorType = UDESC_CONFIG, + .wTotalLength[0] = sizeof(dwc2_confd), + .bNumInterfaces = 1, + .bConfigurationValue = 1, + .iConfiguration = 0, + .bmAttributes = UC_BUS_POWERED | UC_SELF_POWERED, + .bMaxPower = 0, + }, + .ifcd = { + .bLength = USB_INTERFACE_DESCRIPTOR_SIZE, + .bDescriptorType = UDESC_INTERFACE, + .bInterfaceNumber = 0, + .bAlternateSetting = 0, + .bNumEndpoints = 1, + .bInterfaceClass = UICLASS_HUB, + .bInterfaceSubClass = UISUBCLASS_HUB, + .bInterfaceProtocol = UIPROTO_HSHUBSTT, + .iInterface = 0 + }, + .endpd = { + .bLength = USB_ENDPOINT_DESCRIPTOR_SIZE, + .bDescriptorType = UDESC_ENDPOINT, + .bEndpointAddress = UE_DIR_IN | DWC2_INTR_ENDPT, + .bmAttributes = UE_INTERRUPT, + .wMaxPacketSize = {8, 0}, /* max packet */ + .bInterval = 255, + }, +}; + +STATIC usbd_status +dwc2_root_ctrl_transfer(struct usbd_xfer *xfer) { - struct dwc2_softc *sc = bus->ub_hcpriv; + usbd_status err; + + err = usb_insert_transfer(xfer); + if (err) + return err; + + return dwc2_root_ctrl_start(SIMPLEQ_FIRST(&xfer->pipe->queue)); +} + +STATIC usbd_status +dwc2_root_ctrl_start(struct usbd_xfer *xfer) +{ + struct dwc2_softc *sc = DWC2_XFER2SC(xfer); + usb_device_request_t *req; + uint8_t *buf; + uint16_t len; + int value, index, l, s, totlen; usbd_status err = USBD_IOERROR; - uint16_t len, value, index; - int totlen = 0; - if (sc->sc_dying) - return -1; + if (sc->sc_bus.dying) + return USBD_IOERROR; + req = &xfer->request; + DPRINTFN(4, "type=0x%02x request=%02x\n", req->bmRequestType, req->bRequest); @@ -566,52 +644,156 @@ dwc2_roothub_ctrl(struct usbd_bus *bus, usb_device_req value = UGETW(req->wValue); index = UGETW(req->wIndex); + buf = len ? KERNADDR(&xfer->dmabuf, 0) : NULL; + + totlen = 0; + #define C(x,y) ((x) | ((y) << 8)) switch (C(req->bRequest, req->bmRequestType)) { + case C(UR_CLEAR_FEATURE, UT_WRITE_DEVICE): + case C(UR_CLEAR_FEATURE, UT_WRITE_INTERFACE): + case C(UR_CLEAR_FEATURE, UT_WRITE_ENDPOINT): + /* + * DEVICE_REMOTE_WAKEUP and ENDPOINT_HALT are no-ops + * for the integrated root hub. + */ + break; + case C(UR_GET_CONFIG, UT_READ_DEVICE): + if (len > 0) { + *buf = sc->sc_conf; + totlen = 1; + } + break; case C(UR_GET_DESCRIPTOR, UT_READ_DEVICE): DPRINTFN(8, "wValue=0x%04x\n", value); if (len == 0) break; switch (value) { + case C(0, UDESC_DEVICE): + l = min(len, USB_DEVICE_DESCRIPTOR_SIZE); +// USETW(dwc2_devd.idVendor, sc->sc_id_vendor); + memcpy(buf, &dwc2_devd, l); + buf += l; + len -= l; + totlen += l; + + break; + case C(0, UDESC_CONFIG): + l = min(len, sizeof(dwc2_confd)); + memcpy(buf, &dwc2_confd, l); + buf += l; + len -= l; + totlen += l; + + break; #define sd ((usb_string_descriptor_t *)buf) + case C(0, UDESC_STRING): + totlen = usbd_str(sd, len, "\001"); + break; + case C(1, UDESC_STRING): + totlen = usbd_str(sd, len, sc->sc_vendor); + break; case C(2, UDESC_STRING): - /* Product */ - totlen = usb_makestrdesc(sd, len, "DWC2 root hub"); + totlen = usbd_str(sd, len, "DWC2 root hub"); break; #undef sd default: - /* default from usbroothub */ - return buflen; + goto fail; } break; - - case C(UR_GET_CONFIG, UT_READ_DEVICE): case C(UR_GET_INTERFACE, UT_READ_INTERFACE): + if (len > 0) { + *buf = 0; + totlen = 1; + } + break; + case C(UR_GET_STATUS, UT_READ_DEVICE): + if (len > 1) { + USETW(((usb_status_t *)buf)->wStatus,UDS_SELF_POWERED); + totlen = 2; + } + break; case C(UR_GET_STATUS, UT_READ_INTERFACE): case C(UR_GET_STATUS, UT_READ_ENDPOINT): + if (len > 1) { + USETW(((usb_status_t *)buf)->wStatus, 0); + totlen = 2; + } + break; case C(UR_SET_ADDRESS, UT_WRITE_DEVICE): + DPRINTF("UR_SET_ADDRESS, UT_WRITE_DEVICE: addr %d\n", + value); + if (value >= USB_MAX_DEVICES) + goto fail; + + sc->sc_addr = value; + break; case C(UR_SET_CONFIG, UT_WRITE_DEVICE): - /* default from usbroothub */ - DPRINTFN(4, "returning %d (usbroothub default)", buflen); + if (value != 0 && value != 1) + goto fail; - return buflen; - + sc->sc_conf = value; + break; + case C(UR_SET_DESCRIPTOR, UT_WRITE_DEVICE): + break; + case C(UR_SET_FEATURE, UT_WRITE_DEVICE): + case C(UR_SET_FEATURE, UT_WRITE_INTERFACE): + case C(UR_SET_FEATURE, UT_WRITE_ENDPOINT): + err = USBD_IOERROR; + goto fail; + case C(UR_SET_INTERFACE, UT_WRITE_INTERFACE): + break; + case C(UR_SYNCH_FRAME, UT_WRITE_ENDPOINT): + break; default: - /* Hub requests */ + /* Hub requests - XXXNH len check? */ err = dwc2_hcd_hub_control(sc->sc_hsotg, C(req->bRequest, req->bmRequestType), value, index, buf, len); if (err) { - return -1; + err = USBD_IOERROR; + goto fail; } totlen = len; } + xfer->actlen = totlen; + err = USBD_NORMAL_COMPLETION; - return totlen; +fail: + s = splusb(); + xfer->status = err; + usb_transfer_complete(xfer); + splx(s); + + return err; } -Static usbd_status +STATIC void +dwc2_root_ctrl_abort(struct usbd_xfer *xfer) +{ + DPRINTFN(10, "\n"); + + /* Nothing to do, all transfers are synchronous. */ +} + +STATIC void +dwc2_root_ctrl_close(struct usbd_pipe *pipe) +{ + DPRINTFN(10, "\n"); + + /* Nothing to do. */ +} + +STATIC void +dwc2_root_ctrl_done(struct usbd_xfer *xfer) +{ + DPRINTFN(10, "\n"); + + /* Nothing to do. */ +} + +STATIC usbd_status dwc2_root_intr_transfer(struct usbd_xfer *xfer) { struct dwc2_softc *sc = DWC2_XFER2SC(xfer); @@ -620,49 +802,46 @@ dwc2_root_intr_transfer(struct usbd_xfer *xfer) DPRINTF("\n"); /* Insert last in queue. */ - mutex_enter(&sc->sc_lock); + mtx_enter(&sc->sc_lock); err = usb_insert_transfer(xfer); - mutex_exit(&sc->sc_lock); + mtx_leave(&sc->sc_lock); if (err) return err; /* Pipe isn't running, start first */ - return dwc2_root_intr_start(SIMPLEQ_FIRST(&xfer->ux_pipe->up_queue)); + return dwc2_root_intr_start(SIMPLEQ_FIRST(&xfer->pipe->queue)); } -Static usbd_status +STATIC usbd_status dwc2_root_intr_start(struct usbd_xfer *xfer) { struct dwc2_softc *sc = DWC2_XFER2SC(xfer); - const bool polling = sc->sc_bus.ub_usepolling; + const bool polling = sc->sc_bus.use_polling; DPRINTF("\n"); - if (sc->sc_dying) + if (sc->sc_bus.dying) return USBD_IOERROR; if (!polling) - mutex_enter(&sc->sc_lock); + mtx_enter(&sc->sc_lock); KASSERT(sc->sc_intrxfer == NULL); sc->sc_intrxfer = xfer; - xfer->ux_status = USBD_IN_PROGRESS; + xfer->status = USBD_IN_PROGRESS; if (!polling) - mutex_exit(&sc->sc_lock); + mtx_leave(&sc->sc_lock); return USBD_IN_PROGRESS; } /* Abort a root interrupt request. */ -Static void +STATIC void dwc2_root_intr_abort(struct usbd_xfer *xfer) { - struct dwc2_softc *sc __diagused = DWC2_XFER2SC(xfer); + struct dwc2_softc *sc = DWC2_XFER2SC(xfer); DPRINTF("xfer=%p\n", xfer); - KASSERT(mutex_owned(&sc->sc_lock)); - KASSERT(xfer->ux_pipe->up_intrxfer == xfer); - /* If xfer has already completed, nothing to do here. */ if (sc->sc_intrxfer == NULL) return; @@ -672,20 +851,18 @@ dwc2_root_intr_abort(struct usbd_xfer *xfer) * Cancel it. */ KASSERT(sc->sc_intrxfer == xfer); - KASSERT(xfer->ux_status == USBD_IN_PROGRESS); - xfer->ux_status = USBD_CANCELLED; + KASSERT(xfer->status == USBD_IN_PROGRESS); + xfer->status = USBD_CANCELLED; usb_transfer_complete(xfer); } -Static void +STATIC void dwc2_root_intr_close(struct usbd_pipe *pipe) { - struct dwc2_softc *sc __diagused = DWC2_PIPE2SC(pipe); + struct dwc2_softc *sc = DWC2_PIPE2SC(pipe); DPRINTF("\n"); - KASSERT(mutex_owned(&sc->sc_lock)); - /* * Caller must guarantee the xfer has completed first, by * closing the pipe only after normal completion or an abort. @@ -693,7 +870,7 @@ dwc2_root_intr_close(struct usbd_pipe *pipe) KASSERT(sc->sc_intrxfer == NULL); } -Static void +STATIC void dwc2_root_intr_done(struct usbd_xfer *xfer) { struct dwc2_softc *sc = DWC2_XFER2SC(xfer); @@ -702,13 +879,13 @@ dwc2_root_intr_done(struct usbd_xfer *xfer) /* Claim the xfer so it doesn't get completed again. */ KASSERT(sc->sc_intrxfer == xfer); - KASSERT(xfer->ux_status != USBD_IN_PROGRESS); + KASSERT(xfer->status != USBD_IN_PROGRESS); sc->sc_intrxfer = NULL; } /***********************************************************************/ -Static usbd_status +STATIC usbd_status dwc2_device_ctrl_transfer(struct usbd_xfer *xfer) { struct dwc2_softc *sc = DWC2_XFER2SC(xfer); @@ -717,31 +894,31 @@ dwc2_device_ctrl_transfer(struct usbd_xfer *xfer) DPRINTF("\n"); /* Insert last in queue. */ - mutex_enter(&sc->sc_lock); + mtx_enter(&sc->sc_lock); err = usb_insert_transfer(xfer); - mutex_exit(&sc->sc_lock); + mtx_leave(&sc->sc_lock); if (err) return err; /* Pipe isn't running, start first */ - return dwc2_device_ctrl_start(SIMPLEQ_FIRST(&xfer->ux_pipe->up_queue)); + return dwc2_device_ctrl_start(SIMPLEQ_FIRST(&xfer->pipe->queue)); } -Static usbd_status +STATIC usbd_status dwc2_device_ctrl_start(struct usbd_xfer *xfer) { struct dwc2_softc *sc = DWC2_XFER2SC(xfer); usbd_status err; - const bool polling = sc->sc_bus.ub_usepolling; + const bool polling = sc->sc_bus.use_polling; DPRINTF("\n"); if (!polling) - mutex_enter(&sc->sc_lock); - xfer->ux_status = USBD_IN_PROGRESS; + mtx_enter(&sc->sc_lock); + xfer->status = USBD_IN_PROGRESS; err = dwc2_device_start(xfer); if (!polling) - mutex_exit(&sc->sc_lock); + mtx_leave(&sc->sc_lock); if (err) return err; @@ -749,18 +926,14 @@ dwc2_device_ctrl_start(struct usbd_xfer *xfer) return USBD_IN_PROGRESS; } -Static void +STATIC void dwc2_device_ctrl_abort(struct usbd_xfer *xfer) { - struct dwc2_softc *sc __diagused = DWC2_XFER2SC(xfer); - - KASSERT(mutex_owned(&sc->sc_lock)); - DPRINTF("xfer=%p\n", xfer); - usbd_xfer_abort(xfer); + dwc2_abort_xfer(xfer, USBD_CANCELLED); } -Static void +STATIC void dwc2_device_ctrl_close(struct usbd_pipe *pipe) { struct dwc2_softc * const sc = DWC2_PIPE2SC(pipe); @@ -772,7 +945,7 @@ dwc2_device_ctrl_close(struct usbd_pipe *pipe) usb_freemem(&sc->sc_bus, &dpipe->req_dma); } -Static void +STATIC void dwc2_device_ctrl_done(struct usbd_xfer *xfer) { @@ -781,39 +954,44 @@ dwc2_device_ctrl_done(struct usbd_xfer *xfer) /***********************************************************************/ -Static usbd_status +STATIC usbd_status dwc2_device_bulk_transfer(struct usbd_xfer *xfer) { - struct dwc2_softc *sc = DWC2_XFER2SC(xfer); usbd_status err; DPRINTF("xfer=%p\n", xfer); /* Insert last in queue. */ - mutex_enter(&sc->sc_lock); err = usb_insert_transfer(xfer); + if (err) + return err; - KASSERT(err == USBD_NORMAL_COMPLETION); + /* Pipe isn't running, start first */ + return dwc2_device_bulk_start(SIMPLEQ_FIRST(&xfer->pipe->queue)); +} - xfer->ux_status = USBD_IN_PROGRESS; +STATIC usbd_status +dwc2_device_bulk_start(struct usbd_xfer *xfer) +{ + usbd_status err; + + DPRINTF("xfer=%p\n", xfer); + + xfer->status = USBD_IN_PROGRESS; err = dwc2_device_start(xfer); - mutex_exit(&sc->sc_lock); return err; } -Static void +STATIC void dwc2_device_bulk_abort(struct usbd_xfer *xfer) { - struct dwc2_softc *sc __diagused = DWC2_XFER2SC(xfer); - - KASSERT(mutex_owned(&sc->sc_lock)); - DPRINTF("xfer=%p\n", xfer); - usbd_xfer_abort(xfer); + + dwc2_abort_xfer(xfer, USBD_CANCELLED); } -Static void +STATIC void dwc2_device_bulk_close(struct usbd_pipe *pipe) { @@ -822,7 +1000,7 @@ dwc2_device_bulk_close(struct usbd_pipe *pipe) dwc2_close_pipe(pipe); } -Static void +STATIC void dwc2_device_bulk_done(struct usbd_xfer *xfer) { @@ -831,7 +1009,7 @@ dwc2_device_bulk_done(struct usbd_xfer *xfer) /***********************************************************************/ -Static usbd_status +STATIC usbd_status dwc2_device_intr_transfer(struct usbd_xfer *xfer) { struct dwc2_softc *sc = DWC2_XFER2SC(xfer); @@ -840,31 +1018,29 @@ dwc2_device_intr_transfer(struct usbd_xfer *xfer) DPRINTF("xfer=%p\n", xfer); /* Insert last in queue. */ - mutex_enter(&sc->sc_lock); + mtx_enter(&sc->sc_lock); err = usb_insert_transfer(xfer); - mutex_exit(&sc->sc_lock); + mtx_leave(&sc->sc_lock); if (err) return err; /* Pipe isn't running, start first */ - return dwc2_device_intr_start(SIMPLEQ_FIRST(&xfer->ux_pipe->up_queue)); + return dwc2_device_intr_start(SIMPLEQ_FIRST(&xfer->pipe->queue)); } -Static usbd_status +STATIC usbd_status dwc2_device_intr_start(struct usbd_xfer *xfer) { - struct dwc2_pipe *dpipe = DWC2_XFER2DPIPE(xfer) - struct usbd_device *dev = dpipe->pipe.up_dev; - struct dwc2_softc *sc = dev->ud_bus->ub_hcpriv; + struct dwc2_softc *sc = DWC2_XFER2SC(xfer); usbd_status err; - const bool polling = sc->sc_bus.ub_usepolling; + const bool polling = sc->sc_bus.use_polling; if (!polling) - mutex_enter(&sc->sc_lock); - xfer->ux_status = USBD_IN_PROGRESS; + mtx_enter(&sc->sc_lock); + xfer->status = USBD_IN_PROGRESS; err = dwc2_device_start(xfer); if (!polling) - mutex_exit(&sc->sc_lock); + mtx_leave(&sc->sc_lock); if (err) return err; @@ -873,18 +1049,17 @@ dwc2_device_intr_start(struct usbd_xfer *xfer) } /* Abort a device interrupt request. */ -Static void +STATIC void dwc2_device_intr_abort(struct usbd_xfer *xfer) { - struct dwc2_softc *sc __diagused = DWC2_XFER2SC(xfer); + KASSERT(xfer->pipe->intrxfer == xfer); - KASSERT(mutex_owned(&sc->sc_lock)); - DPRINTF("xfer=%p\n", xfer); - usbd_xfer_abort(xfer); + + dwc2_abort_xfer(xfer, USBD_CANCELLED); } -Static void +STATIC void dwc2_device_intr_close(struct usbd_pipe *pipe) { @@ -893,11 +1068,16 @@ dwc2_device_intr_close(struct usbd_pipe *pipe) dwc2_close_pipe(pipe); } -Static void +STATIC void dwc2_device_intr_done(struct usbd_xfer *xfer) { DPRINTF("\n"); + + if (xfer->pipe->repeat) { + xfer->status = USBD_IN_PROGRESS; + dwc2_device_start(xfer); + } } /***********************************************************************/ @@ -905,20 +1085,32 @@ dwc2_device_intr_done(struct usbd_xfer *xfer) usbd_status dwc2_device_isoc_transfer(struct usbd_xfer *xfer) { - struct dwc2_softc *sc = DWC2_XFER2SC(xfer); usbd_status err; DPRINTF("xfer=%p\n", xfer); /* Insert last in queue. */ - mutex_enter(&sc->sc_lock); err = usb_insert_transfer(xfer); + if (err) + return err; - KASSERT(err == USBD_NORMAL_COMPLETION); + /* Pipe isn't running, start first */ + return dwc2_device_isoc_start(SIMPLEQ_FIRST(&xfer->pipe->queue)); +} - xfer->ux_status = USBD_IN_PROGRESS; +usbd_status +dwc2_device_isoc_start(struct usbd_xfer *xfer) +{ + struct dwc2_pipe *dpipe = DWC2_XFER2DPIPE(xfer); + struct dwc2_softc *sc = DWC2_DPIPE2SC(dpipe); + usbd_status err; + + /* Why would you do that anyway? */ + if (sc->sc_bus.use_polling) + return (USBD_INVAL); + + xfer->status = USBD_IN_PROGRESS; err = dwc2_device_start(xfer); - mutex_exit(&sc->sc_lock); return err; } @@ -926,11 +1118,9 @@ dwc2_device_isoc_transfer(struct usbd_xfer *xfer) void dwc2_device_isoc_abort(struct usbd_xfer *xfer) { - struct dwc2_softc *sc __diagused = DWC2_XFER2SC(xfer); - KASSERT(mutex_owned(&sc->sc_lock)); - DPRINTF("xfer=%p\n", xfer); - usbd_xfer_abort(xfer); + + dwc2_abort_xfer(xfer, USBD_CANCELLED); } void @@ -958,9 +1148,9 @@ dwc2_device_start(struct usbd_xfer *xfer) struct dwc2_hsotg *hsotg = sc->sc_hsotg; struct dwc2_hcd_urb *dwc2_urb; - struct usbd_device *dev = xfer->ux_pipe->up_dev; - usb_endpoint_descriptor_t *ed = xfer->ux_pipe->up_endpoint->ue_edesc; - uint8_t addr = dev->ud_addr; + struct usbd_device *dev = xfer->pipe->device; + usb_endpoint_descriptor_t *ed = xfer->pipe->endpoint->edesc; + uint8_t addr = dev->address; uint8_t xfertype = UE_GET_XFERTYPE(ed->bmAttributes); uint8_t epnum = UE_GET_ADDR(ed->bEndpointAddress); uint8_t dir = UE_GET_DIR(ed->bEndpointAddress); @@ -972,14 +1162,14 @@ dwc2_device_start(struct usbd_xfer *xfer) int retval, err; int alloc_bandwidth = 0; - DPRINTFN(1, "xfer=%p pipe=%p\n", xfer, xfer->ux_pipe); + DPRINTFN(1, "xfer=%p pipe=%p\n", xfer, xfer->pipe); if (xfertype == UE_ISOCHRONOUS || xfertype == UE_INTERRUPT) { - mutex_spin_enter(&hsotg->lock); + mtx_enter(&hsotg->lock); if (!dwc2_hcd_is_bandwidth_allocated(hsotg, xfer)) alloc_bandwidth = 1; - mutex_spin_exit(&hsotg->lock); + mtx_leave(&hsotg->lock); } /* @@ -987,14 +1177,14 @@ dwc2_device_start(struct usbd_xfer *xfer) * transfers have been set correctly at pipe open time. */ if (xfertype == UE_CONTROL) { - usb_device_request_t *req = &xfer->ux_request; + usb_device_request_t *req = &xfer->request; DPRINTFN(3, "xfer=%p type=0x%02x request=0x%02x wValue=0x%04x " "wIndex=0x%04x len=%d addr=%d endpt=%d dir=%s speed=%d " "mps=%d\n", xfer, req->bmRequestType, req->bRequest, UGETW(req->wValue), - UGETW(req->wIndex), UGETW(req->wLength), dev->ud_addr, - epnum, dir == UT_READ ? "in" :"out", dev->ud_speed, mps); + UGETW(req->wIndex), UGETW(req->wLength), dev->address, + epnum, dir == UT_READ ? "in" :"out", dev->speed, mps); /* Copy request packet to our DMA buffer */ memcpy(KERNADDR(&dpipe->req_dma, 0), req, sizeof(*req)); @@ -1007,41 +1197,42 @@ dwc2_device_start(struct usbd_xfer *xfer) dir = UE_DIR_OUT; } - DPRINTFN(3, "req = %p dma = %" PRIxBUSADDR " len %d dir %s\n", - KERNADDR(&dpipe->req_dma, 0), DMAADDR(&dpipe->req_dma, 0), + DPRINTFN(3, "req = %p dma = %llx len %d dir %s\n", + KERNADDR(&dpipe->req_dma, 0), + (long long)DMAADDR(&dpipe->req_dma, 0), len, dir == UE_DIR_IN ? "in" : "out"); } else if (xfertype == UE_ISOCHRONOUS) { DPRINTFN(3, "xfer=%p nframes=%d flags=%d addr=%d endpt=%d," - " mps=%d dir %s\n", xfer, xfer->ux_nframes, xfer->ux_flags, addr, + " mps=%d dir %s\n", xfer, xfer->nframes, xfer->flags, addr, epnum, mps, dir == UT_READ ? "in" :"out"); #ifdef DIAGNOSTIC len = 0; - for (size_t i = 0; i < xfer->ux_nframes; i++) - len += xfer->ux_frlengths[i]; - if (len != xfer->ux_length) - panic("len (%d) != xfer->ux_length (%d)", len, - xfer->ux_length); + for (size_t i = 0; i < xfer->nframes; i++) + len += xfer->frlengths[i]; + if (len != xfer->length) + panic("len (%d) != xfer->length (%d)", len, + xfer->length); #endif - len = xfer->ux_length; - } else { - DPRINTFN(3, "xfer=%p len=%d flags=%d addr=%d endpt=%d," - " mps=%d dir %s\n", xfer, xfer->ux_length, xfer->ux_flags, addr, - epnum, mps, dir == UT_READ ? "in" :"out"); + len = xfer->length; + } else { + DPRINTFN(3, "xfer=%p len=%d flags=%d addr=%d endpt=%d," + " mps=%d dir %s\n", xfer, xfer->length, xfer->flags, addr, + epnum, mps, dir == UT_READ ? "in" :"out"); - len = xfer->ux_length; + len = xfer->length; } dwc2_urb = dxfer->urb; if (!dwc2_urb) return USBD_NOMEM; - KASSERT(dwc2_urb->packet_count == xfer->ux_nframes); +// KASSERT(dwc2_urb->packet_count == xfer->nframes); memset(dwc2_urb, 0, sizeof(*dwc2_urb) + - sizeof(dwc2_urb->iso_descs[0]) * dwc2_urb->packet_count); + sizeof(dwc2_urb->iso_descs[0]) * DWC2_MAXISOCPACKETS); dwc2_urb->priv = xfer; - dwc2_urb->packet_count = xfer->ux_nframes; + dwc2_urb->packet_count = xfer->nframes; dwc2_hcd_urb_set_pipeinfo(hsotg, dwc2_urb, addr, epnum, xfertype, dir, mps); @@ -1052,7 +1243,7 @@ dwc2_device_start(struct usbd_xfer *xfer) dwc2_urb->setup_dma = DMAADDR(&dpipe->req_dma, 0); } else { /* XXXNH - % mps required? */ - if ((xfer->ux_flags & USBD_FORCE_SHORT_XFER) && (len % mps) == 0) + if ((xfer->flags & USBD_FORCE_SHORT_XFER) && (len % mps) == 0) flags |= URB_SEND_ZERO_PACKET; } flags |= URB_GIVEBACK_ASAP; @@ -1062,11 +1253,11 @@ dwc2_device_start(struct usbd_xfer *xfer) * everything else does. */ if (!(xfertype == UE_CONTROL && len == 0)) { - dwc2_urb->usbdma = &xfer->ux_dmabuf; + dwc2_urb->usbdma = &xfer->dmabuf; dwc2_urb->buf = KERNADDR(dwc2_urb->usbdma, 0); dwc2_urb->dma = DMAADDR(dwc2_urb->usbdma, 0); - usb_syncmem(&xfer->ux_dmabuf, 0, len, + usb_syncmem(&xfer->dmabuf, 0, len, dir == UE_DIR_IN ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE); } @@ -1079,8 +1270,8 @@ dwc2_device_start(struct usbd_xfer *xfer) uint16_t ival; if (xfertype == UE_INTERRUPT && - dpipe->pipe.up_interval != USBD_DEFAULT_INTERVAL) { - ival = dpipe->pipe.up_interval; + dpipe->pipe.interval != USBD_DEFAULT_INTERVAL) { + ival = dpipe->pipe.interval; } else { ival = ed->bInterval; } @@ -1089,8 +1280,8 @@ dwc2_device_start(struct usbd_xfer *xfer) retval = -ENODEV; goto fail; } - if (dev->ud_speed == USB_SPEED_HIGH || - (dev->ud_speed == USB_SPEED_FULL && xfertype == UE_ISOCHRONOUS)) { + if (dev->speed == USB_SPEED_HIGH || + (dev->speed == USB_SPEED_FULL && xfertype == UE_ISOCHRONOUS)) { if (ival > 16) { /* * illegal with HS/FS, but there were @@ -1108,23 +1299,23 @@ dwc2_device_start(struct usbd_xfer *xfer) } /* XXXNH bring down from callers?? */ -// mutex_enter(&sc->sc_lock); +// mtx_enter(&sc->sc_lock); - xfer->ux_actlen = 0; + xfer->actlen = 0; KASSERT(xfertype != UE_ISOCHRONOUS || - xfer->ux_nframes <= dwc2_urb->packet_count); - KASSERTMSG(xfer->ux_nframes == 0 || xfertype == UE_ISOCHRONOUS, - "nframes %d xfertype %d\n", xfer->ux_nframes, xfertype); + xfer->nframes <= DWC2_MAXISOCPACKETS); + KASSERTMSG(xfer->nframes == 0 || xfertype == UE_ISOCHRONOUS, + "nframes %d xfertype %d\n", xfer->nframes, xfertype); off = 0; - for (size_t i = 0; i < xfer->ux_nframes; ++i) { - DPRINTFN(3, "xfer=%p frame=%zd offset=%d length=%d\n", xfer, i, - off, xfer->ux_frlengths[i]); + for (size_t i = 0; i < xfer->nframes; ++i) { + DPRINTFN(3, "xfer=%p frame=%zu offset=%d length=%d\n", xfer, i, + off, xfer->frlengths[i]); dwc2_hcd_urb_set_iso_desc_params(dwc2_urb, i, off, - xfer->ux_frlengths[i]); - off += xfer->ux_frlengths[i]; + xfer->frlengths[i]); + off += xfer->frlengths[i]; } struct dwc2_qh *qh = dpipe->priv; @@ -1133,7 +1324,7 @@ dwc2_device_start(struct usbd_xfer *xfer) /* Create QH for the endpoint if it doesn't exist */ if (!qh) { - qh = dwc2_hcd_qh_create(hsotg, dwc2_urb, GFP_ATOMIC); + qh = dwc2_hcd_qh_create(hsotg, dwc2_urb, M_NOWAIT); if (!qh) { retval = -ENOMEM; goto fail; @@ -1142,7 +1333,7 @@ dwc2_device_start(struct usbd_xfer *xfer) qh_allocated = true; } - qtd = pool_cache_get(sc->sc_qtdpool, PR_NOWAIT); + qtd = pool_get(&sc->sc_qtdpool, PR_NOWAIT); if (!qtd) { retval = -ENOMEM; goto fail1; @@ -1150,12 +1341,15 @@ dwc2_device_start(struct usbd_xfer *xfer) memset(qtd, 0, sizeof(*qtd)); /* might need to check cpu_intr_p */ - mutex_spin_enter(&hsotg->lock); + mtx_enter(&hsotg->lock); retval = dwc2_hcd_urb_enqueue(hsotg, dwc2_urb, qh, qtd); if (retval) goto fail2; - usbd_xfer_schedule_timeout(xfer); - xfer->ux_status = USBD_IN_PROGRESS; + if (xfer->timeout && !sc->sc_bus.use_polling) { + timeout_set(&xfer->timeout_handle, dwc2_timeout, xfer); + timeout_add_msec(&xfer->timeout_handle, xfer->timeout); + } + xfer->status = USBD_IN_PROGRESS; if (alloc_bandwidth) { dwc2_allocate_bus_bandwidth(hsotg, @@ -1163,15 +1357,15 @@ dwc2_device_start(struct usbd_xfer *xfer) xfer); } - mutex_spin_exit(&hsotg->lock); -// mutex_exit(&sc->sc_lock); + mtx_leave(&hsotg->lock); +// mtx_exit(&sc->sc_lock); return USBD_IN_PROGRESS; fail2: dwc2_urb->priv = NULL; - mutex_spin_exit(&hsotg->lock); - pool_cache_put(sc->sc_qtdpool, qtd); + mtx_leave(&hsotg->lock); + pool_put(&sc->sc_qtdpool, qtd); fail1: if (qh_allocated) { @@ -1206,12 +1400,12 @@ int dwc2_intr(void *p) return 0; hsotg = sc->sc_hsotg; - mutex_spin_enter(&hsotg->lock); + mtx_enter(&hsotg->lock); - if (sc->sc_dying || !device_has_power(sc->sc_dev)) + if (sc->sc_bus.dying) goto done; - if (sc->sc_bus.ub_usepolling) { + if (sc->sc_bus.use_polling) { uint32_t intrs; intrs = dwc2_read_core_intr(hsotg); @@ -1221,7 +1415,7 @@ int dwc2_intr(void *p) } done: - mutex_spin_exit(&hsotg->lock); + mtx_leave(&hsotg->lock); return ret; } @@ -1253,88 +1447,34 @@ dwc2_detach(struct dwc2_softc *sc, int flags) return rv; } -bool -dwc2_shutdown(device_t self, int flags) -{ - struct dwc2_softc *sc = device_private(self); - - sc = sc; - - return true; -} - -void -dwc2_childdet(device_t self, device_t child) -{ - struct dwc2_softc *sc = device_private(self); - - sc = sc; -} - -int -dwc2_activate(device_t self, enum devact act) -{ - struct dwc2_softc *sc = device_private(self); - - sc = sc; - - return 0; -} - -bool -dwc2_resume(device_t dv, const pmf_qual_t *qual) -{ - struct dwc2_softc *sc = device_private(dv); - - sc = sc; - - return true; -} - -bool -dwc2_suspend(device_t dv, const pmf_qual_t *qual) -{ - struct dwc2_softc *sc = device_private(dv); - - sc = sc; - - return true; -} - /***********************************************************************/ int dwc2_init(struct dwc2_softc *sc) { int err = 0; - err = linux_workqueue_init(); - if (err) - return err; - - sc->sc_bus.ub_hcpriv = sc; - sc->sc_bus.ub_revision = USBREV_2_0; - sc->sc_bus.ub_methods = &dwc2_bus_methods; - sc->sc_bus.ub_pipesize = sizeof(struct dwc2_pipe); - sc->sc_bus.ub_usedma = true; + sc->sc_bus.usbrev = USBREV_2_0; + sc->sc_bus.methods = &dwc2_bus_methods; + sc->sc_bus.pipe_size = sizeof(struct dwc2_pipe); sc->sc_hcdenabled = false; - mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_SOFTUSB); + mtx_init(&sc->sc_lock, IPL_SOFTUSB); TAILQ_INIT(&sc->sc_complete); - sc->sc_rhc_si = softint_establish(SOFTINT_USB | SOFTINT_MPSAFE, - dwc2_rhc, sc); + sc->sc_rhc_si = softintr_establish(IPL_SOFTUSB, dwc2_rhc, sc); - sc->sc_xferpool = pool_cache_init(sizeof(struct dwc2_xfer), 0, 0, 0, - "dwc2xfer", NULL, IPL_USB, NULL, NULL, NULL); - sc->sc_qhpool = pool_cache_init(sizeof(struct dwc2_qh), 0, 0, 0, - "dwc2qh", NULL, IPL_USB, NULL, NULL, NULL); - sc->sc_qtdpool = pool_cache_init(sizeof(struct dwc2_qtd), 0, 0, 0, - "dwc2qtd", NULL, IPL_USB, NULL, NULL, NULL); + pool_init(&sc->sc_xferpool, sizeof(struct dwc2_xfer), 0, IPL_USB, 0, + "dwc2xfer", NULL); + pool_init(&sc->sc_qhpool, sizeof(struct dwc2_qh), 0, IPL_USB, 0, + "dwc2qh", NULL); + pool_init(&sc->sc_qtdpool, sizeof(struct dwc2_qtd), 0, IPL_USB, 0, + "dwc2qtd", NULL); - sc->sc_hsotg = kmem_zalloc(sizeof(struct dwc2_hsotg), KM_SLEEP); + sc->sc_hsotg = malloc(sizeof(struct dwc2_hsotg), M_DEVBUF, + M_ZERO | M_WAITOK); sc->sc_hsotg->hsotg_sc = sc; - sc->sc_hsotg->dev = sc->sc_dev; + sc->sc_hsotg->dev = &sc->sc_bus.bdev; sc->sc_hcdenabled = true; struct dwc2_hsotg *hsotg = sc->sc_hsotg; @@ -1354,13 +1494,21 @@ dwc2_init(struct dwc2_softc *sc) } hsotg->dr_mode = USB_DR_MODE_HOST; + /* + * Reset before dwc2_get_hwparams() then it could get power-on real + * reset value form registers. + */ + dwc2_core_reset(hsotg); + usb_delay_ms(&sc->sc_bus, 500); + /* Detect config values from hardware */ retval = dwc2_get_hwparams(hsotg); if (retval) { goto fail2; } - hsotg->core_params = kmem_zalloc(sizeof(*hsotg->core_params), KM_SLEEP); + hsotg->core_params = malloc(sizeof(*hsotg->core_params), M_DEVBUF, + M_ZERO | M_WAITOK); dwc2_set_all_params(hsotg->core_params, -1); /* Validate parameter values */ @@ -1388,17 +1536,19 @@ dwc2_init(struct dwc2_softc *sc) } #endif +#ifdef DWC2_DEBUG uint32_t snpsid = hsotg->hw_params.snpsid; - aprint_verbose_dev(sc->sc_dev, "Core Release: %x.%x%x%x (snpsid=%x)\n", + dev_dbg(hsotg->dev, "Core Release: %x.%x%x%x (snpsid=%x)\n", snpsid >> 12 & 0xf, snpsid >> 8 & 0xf, snpsid >> 4 & 0xf, snpsid & 0xf, snpsid); +#endif return 0; fail2: err = -retval; - kmem_free(sc->sc_hsotg, sizeof(struct dwc2_hsotg)); - softint_disestablish(sc->sc_rhc_si); + free(sc->sc_hsotg, M_DEVBUF, sizeof(struct dwc2_hsotg)); + softintr_disestablish(sc->sc_rhc_si); return err; } @@ -1407,7 +1557,7 @@ fail2: /* * curmode is a mode indication bit 0 = device, 1 = host */ -static const char * const intnames[32] = { +STATIC const char * const intnames[32] = { "curmode", "modemis", "otgint", "sof", "rxflvl", "nptxfemp", "ginnakeff", "goutnakeff", "ulpickint", "i2cint", "erlysusp", "usbsusp", @@ -1423,24 +1573,34 @@ static const char * const intnames[32] = { #endif + +void +dw_timeout(void *arg) +{ + struct delayed_work *dw = arg; + + task_set(&dw->work, dw->dw_fn, dw->dw_arg); + task_add(dw->dw_wq, &dw->work); +} + void dwc2_host_hub_info(struct dwc2_hsotg *hsotg, void *context, int *hub_addr, int *hub_port) { struct usbd_xfer *xfer = context; struct dwc2_pipe *dpipe = DWC2_XFER2DPIPE(xfer); - struct usbd_device *dev = dpipe->pipe.up_dev; + struct usbd_device *dev = dpipe->pipe.device; - *hub_addr = dev->ud_myhsport->up_parent->ud_addr; - *hub_port = dev->ud_myhsport->up_portno; + *hub_addr = dev->myhsport->parent->address; + *hub_port = dev->myhsport->portno; } int dwc2_host_get_speed(struct dwc2_hsotg *hsotg, void *context) { struct usbd_xfer *xfer = context; struct dwc2_pipe *dpipe = DWC2_XFER2DPIPE(xfer); - struct usbd_device *dev = dpipe->pipe.up_dev; + struct usbd_device *dev = dpipe->pipe.device; - return dev->ud_speed; + return dev->speed; } /* @@ -1458,8 +1618,6 @@ void dwc2_host_complete(struct dwc2_hsotg *hsotg, stru usb_endpoint_descriptor_t *ed; uint8_t xfertype; - KASSERT(mutex_owned(&hsotg->lock)); - if (!qtd) { dev_dbg(hsotg->dev, "## %s: qtd is NULL ##\n", __func__); return; @@ -1478,36 +1636,36 @@ void dwc2_host_complete(struct dwc2_hsotg *hsotg, stru dxfer = DWC2_XFER2DXFER(xfer); sc = DWC2_XFER2SC(xfer); - ed = xfer->ux_pipe->up_endpoint->ue_edesc; + ed = xfer->pipe->endpoint->edesc; xfertype = UE_GET_XFERTYPE(ed->bmAttributes); struct dwc2_hcd_urb *urb = qtd->urb; - xfer->ux_actlen = dwc2_hcd_urb_get_actual_length(urb); + xfer->actlen = dwc2_hcd_urb_get_actual_length(urb); - DPRINTFN(3, "xfer=%p actlen=%d\n", xfer, xfer->ux_actlen); + DPRINTFN(3, "xfer=%p actlen=%d\n", xfer, xfer->actlen); if (xfertype == UE_ISOCHRONOUS) { - xfer->ux_actlen = 0; - for (size_t i = 0; i < xfer->ux_nframes; ++i) { - xfer->ux_frlengths[i] = + xfer->actlen = 0; + for (size_t i = 0; i < xfer->nframes; ++i) { + xfer->frlengths[i] = dwc2_hcd_urb_get_iso_desc_actual_length( urb, i); DPRINTFN(1, "xfer=%p frame=%zu length=%d\n", xfer, i, - xfer->ux_frlengths[i]); - xfer->ux_actlen += xfer->ux_frlengths[i]; + xfer->frlengths[i]); + xfer->actlen += xfer->frlengths[i]; } - DPRINTFN(1, "xfer=%p actlen=%d (isoc)\n", xfer, xfer->ux_actlen); + DPRINTFN(1, "xfer=%p actlen=%d (isoc)\n", xfer, xfer->actlen); } if (xfertype == UE_ISOCHRONOUS && dbg_perio()) { - for (size_t i = 0; i < xfer->ux_nframes; i++) + for (size_t i = 0; i < xfer->nframes; i++) dev_vdbg(hsotg->dev, " ISO Desc %zu status %d\n", i, urb->iso_descs[i].status); } if (!status) { - if (!(xfer->ux_flags & USBD_SHORT_XFER_OK) && - xfer->ux_actlen < xfer->ux_length) + if (!(xfer->flags & USBD_SHORT_XFER_OK) && + xfer->actlen < xfer->length) status = -EIO; } @@ -1538,12 +1696,12 @@ void dwc2_host_complete(struct dwc2_hsotg *hsotg, stru * everything else does. */ if (!(xfertype == UE_CONTROL && - UGETW(xfer->ux_request.wLength) == 0) && - xfer->ux_actlen > 0 /* XXX PR/53503 */ + xfer->length == 0) && + xfer->actlen > 0 /* XXX PR/53503 */ ) { int rd = usbd_xfer_isread(xfer); - usb_syncmem(&xfer->ux_dmabuf, 0, xfer->ux_actlen, + usb_syncmem(&xfer->dmabuf, 0, xfer->actlen, rd ? BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE); } } @@ -1558,13 +1716,15 @@ void dwc2_host_complete(struct dwc2_hsotg *hsotg, stru } qtd->urb = NULL; - KASSERT(mutex_owned(&hsotg->lock)); + timeout_del(&xfer->timeout_handle); + usb_rem_task(xfer->device, &xfer->abort_task); + MUTEX_ASSERT_LOCKED(&hsotg->lock); TAILQ_INSERT_TAIL(&sc->sc_complete, dxfer, xnext); - mutex_spin_exit(&hsotg->lock); + mtx_leave(&hsotg->lock); usb_schedsoftintr(&sc->sc_bus); - mutex_spin_enter(&hsotg->lock); + mtx_enter(&hsotg->lock); } @@ -1573,18 +1733,18 @@ _dwc2_hcd_start(struct dwc2_hsotg *hsotg) { dev_dbg(hsotg->dev, "DWC OTG HCD START\n"); - mutex_spin_enter(&hsotg->lock); + mtx_enter(&hsotg->lock); hsotg->lx_state = DWC2_L0; if (dwc2_is_device_mode(hsotg)) { - mutex_spin_exit(&hsotg->lock); + mtx_leave(&hsotg->lock); return 0; /* why 0 ?? */ } dwc2_hcd_reinit(hsotg); - mutex_spin_exit(&hsotg->lock); + mtx_leave(&hsotg->lock); return 0; } --- dwc2.h Wed Mar 31 07:42:17 2021 +++ /usr/src/sys/dev/usb/dwc2/dwc2.h Mon Jul 19 19:25:53 2021 @@ -1,4 +1,5 @@ -/* $NetBSD: dwc2.h,v 1.10 2018/08/27 17:13:07 riastradh Exp $ */ +/* $OpenBSD: dwc2.h,v 1.14 2017/02/15 14:49:13 visa Exp $ */ +/* $NetBSD: dwc2.h,v 1.4 2014/12/23 16:20:06 macallan Exp $ */ /*- * Copyright (c) 2013 The NetBSD Foundation, Inc. @@ -33,16 +34,14 @@ #define _EXTERNAL_BSD_DWC2_DWC2_H_ #include - -#include #include -#include -#include -#include -#include +#include -#include "opt_usb.h" +#include + +#define STATIC + // #define VERBOSE_DEBUG // #define DWC2_DUMP_FRREM // #define CONFIG_USB_DWC2_TRACK_MISSED_SOFS @@ -105,9 +104,6 @@ extern int dwc2debug; #define dev_vdbg(...) do { } while (0) #endif -#define jiffies hardclock_ticks -#define msecs_to_jiffies mstohz - enum usb_otg_state { OTG_STATE_RESERVED = 0, @@ -120,16 +116,16 @@ enum usb_otg_state { #define usleep_range(l, u) do { DELAY(u); } while (0) -#define spinlock_t kmutex_t -#define spin_lock_init(lock) mutex_init(lock, MUTEX_DEFAULT, IPL_VM) -#define spin_lock(l) do { mutex_spin_enter(l); } while (0) -#define spin_unlock(l) do { mutex_spin_exit(l); } while (0) +#define spinlock_t struct mutex +#define spin_lock_init(lock) mtx_init(lock, IPL_USB) +#define spin_lock(l) do { mtx_enter(l); } while (0) +#define spin_unlock(l) do { mtx_leave(l); } while (0) #define spin_lock_irqsave(l, f) \ - do { mutex_spin_enter(l); (void)(f); } while (0) + do { mtx_enter(l); (void)(f); } while (0) #define spin_unlock_irqrestore(l, f) \ - do { mutex_spin_exit(l); (void)(f); } while (0) + do { mtx_leave(l); (void)(f); } while (0) #define IRQ_RETVAL(r) (r) @@ -256,21 +252,37 @@ ndelay(unsigned long nsecs) DELAY(nsecs / 1000); } -static inline void -msleep(unsigned int msec) -{ - if (cold || - ((hz < 1000) && (msec < (1000/hz)))) - udelay(msec * 1000); - else - (void)kpause("mdelay", false, mstohz(msec), NULL); -} - #define EREMOTEIO EIO #define ECOMM EIO #define ENOTSUPP ENOTSUP #define NS_TO_US(ns) ((ns + 500L) / 1000L) + +void dw_timeout(void *); + +struct delayed_work { + struct task work; + struct timeout dw_timer; + + struct taskq *dw_wq; + void (*dw_fn)(void *); + void *dw_arg; +}; + +static inline void +INIT_DELAYED_WORK(struct delayed_work *dw, void (*fn)(void *), void *arg) +{ + dw->dw_fn = fn; + dw->dw_arg = arg; + timeout_set(&dw->dw_timer, dw_timeout, dw); +} + +static inline void +queue_delayed_work(struct taskq *wq, struct delayed_work *dw, int j) +{ + dw->dw_wq = wq; + timeout_add(&dw->dw_timer, j); +} #define USB_RESUME_TIMEOUT 40 /* ms */ --- dwc2_core.c Wed Mar 31 07:42:18 2021 +++ /usr/src/sys/dev/usb/dwc2/dwc2_core.c Mon Jul 19 19:27:21 2021 @@ -1,4 +1,5 @@ -/* $NetBSD: dwc2_core.c,v 1.13 2016/02/24 22:17:54 skrll Exp $ */ +/* $OpenBSD: dwc2_core.c,v 1.9 2017/09/08 05:36:52 deraadt Exp $ */ +/* $NetBSD: dwc2_core.c,v 1.6 2014/04/03 06:34:58 skrll Exp $ */ /* * core.c - DesignWare HS OTG Controller common routines @@ -42,30 +43,28 @@ * Driver and the Peripheral Controller Driver. */ -#include -__KERNEL_RCSID(0, "$NetBSD: dwc2_core.c,v 1.13 2016/02/24 22:17:54 skrll Exp $"); - -#include -#include +#include +#include +#include #include -#include +#include #include #include +#include +#include + #include #include #include #include -#include -#include +#include +#include -#include -#include +#include +#include -#include "dwc2_core.h" -#include "dwc2_hcd.h" - #if IS_ENABLED(CONFIG_USB_DWC2_HOST) || IS_ENABLED(CONFIG_USB_DWC2_DUAL_ROLE) /** * dwc2_backup_host_registers() - Backup controller host registers. @@ -74,7 +73,7 @@ __KERNEL_RCSID(0, "$NetBSD: dwc2_core.c,v 1.13 2016/02 * * @hsotg: Programming view of the DWC_otg controller */ -static int dwc2_backup_host_registers(struct dwc2_hsotg *hsotg) +STATIC int dwc2_backup_host_registers(struct dwc2_hsotg *hsotg) { struct dwc2_hregs_backup *hr; int i; @@ -102,7 +101,7 @@ static int dwc2_backup_host_registers(struct dwc2_hsot * * @hsotg: Programming view of the DWC_otg controller */ -static int dwc2_restore_host_registers(struct dwc2_hsotg *hsotg) +STATIC int dwc2_restore_host_registers(struct dwc2_hsotg *hsotg) { struct dwc2_hregs_backup *hr; int i; @@ -147,7 +146,7 @@ static inline int dwc2_restore_host_registers(struct d * * @hsotg: Programming view of the DWC_otg controller */ -static int dwc2_backup_device_registers(struct dwc2_hsotg *hsotg) +STATIC int dwc2_backup_device_registers(struct dwc2_hsotg *hsotg) { struct dwc2_dregs_backup *dr; int i; @@ -199,7 +198,7 @@ static int dwc2_backup_device_registers(struct dwc2_hs * * @hsotg: Programming view of the DWC_otg controller */ -static int dwc2_restore_device_registers(struct dwc2_hsotg *hsotg) +STATIC int dwc2_restore_device_registers(struct dwc2_hsotg *hsotg) { struct dwc2_dregs_backup *dr; u32 dctl; @@ -256,7 +255,7 @@ static inline int dwc2_restore_device_registers(struct * * @hsotg: Programming view of the DWC_otg controller */ -static int dwc2_backup_global_registers(struct dwc2_hsotg *hsotg) +STATIC int dwc2_backup_global_registers(struct dwc2_hsotg *hsotg) { struct dwc2_gregs_backup *gr; int i; @@ -286,7 +285,7 @@ static int dwc2_backup_global_registers(struct dwc2_hs * * @hsotg: Programming view of the DWC_otg controller */ -static int dwc2_restore_global_registers(struct dwc2_hsotg *hsotg) +STATIC int dwc2_restore_global_registers(struct dwc2_hsotg *hsotg) { struct dwc2_gregs_backup *gr; int i; @@ -329,7 +328,7 @@ int dwc2_exit_hibernation(struct dwc2_hsotg *hsotg, bo int ret = 0; if (!hsotg->core_params->hibernation) - return -ENOTSUPP; + return -ENOTSUP; pcgcctl = DWC2_READ_4(hsotg, PCGCTL); pcgcctl &= ~PCGCTL_STOPPCLK; @@ -382,7 +381,7 @@ int dwc2_enter_hibernation(struct dwc2_hsotg *hsotg) int ret = 0; if (!hsotg->core_params->hibernation) - return -ENOTSUPP; + return -ENOTSUP; /* Backup all registers */ ret = dwc2_backup_global_registers(hsotg); @@ -437,7 +436,7 @@ int dwc2_enter_hibernation(struct dwc2_hsotg *hsotg) * * @hsotg: Programming view of the DWC_otg controller */ -static void dwc2_enable_common_interrupts(struct dwc2_hsotg *hsotg) +STATIC void dwc2_enable_common_interrupts(struct dwc2_hsotg *hsotg) { u32 intmsk; @@ -465,7 +464,7 @@ static void dwc2_enable_common_interrupts(struct dwc2_ * Initializes the FSLSPClkSel field of the HCFG register depending on the * PHY type */ -static void dwc2_init_fs_ls_pclk_sel(struct dwc2_hsotg *hsotg) +STATIC void dwc2_init_fs_ls_pclk_sel(struct dwc2_hsotg *hsotg) { u32 hcfg, val; @@ -553,8 +552,9 @@ int dwc2_core_reset(struct dwc2_hsotg *hsotg) * * Returns true if the mode was forced. */ -static bool dwc2_force_mode(struct dwc2_hsotg *hsotg, bool host) +STATIC bool dwc2_force_mode(struct dwc2_hsotg *hsotg, bool host) { + struct dwc2_softc *sc = hsotg->hsotg_sc; u32 gusbcfg; u32 set; u32 clear; @@ -590,15 +590,16 @@ static bool dwc2_force_mode(struct dwc2_hsotg *hsotg, gusbcfg |= set; DWC2_WRITE_4(hsotg, GUSBCFG, gusbcfg); - msleep(25); + usb_delay_ms(&sc->sc_bus, 25); return true; } /* * Clears the force mode bits. */ -static void dwc2_clear_force_mode(struct dwc2_hsotg *hsotg) +STATIC void dwc2_clear_force_mode(struct dwc2_hsotg *hsotg) { + struct dwc2_softc *sc = hsotg->hsotg_sc; u32 gusbcfg; gusbcfg = DWC2_READ_4(hsotg, GUSBCFG); @@ -610,7 +611,7 @@ static void dwc2_clear_force_mode(struct dwc2_hsotg *h * NOTE: This long sleep is _very_ important, otherwise the core will * not stay in host mode after a connector ID change! */ - msleep(25); + usb_delay_ms(&sc->sc_bus, 25); } /* @@ -654,7 +655,7 @@ int dwc2_core_reset_and_force_dr_mode(struct dwc2_hsot return 0; } -static int dwc2_fs_phy_init(struct dwc2_hsotg *hsotg, bool select_phy) +STATIC int dwc2_fs_phy_init(struct dwc2_hsotg *hsotg, bool select_phy) { u32 usbcfg, i2cctl; int retval = 0; @@ -711,7 +712,7 @@ static int dwc2_fs_phy_init(struct dwc2_hsotg *hsotg, return retval; } -static int dwc2_hs_phy_init(struct dwc2_hsotg *hsotg, bool select_phy) +STATIC int dwc2_hs_phy_init(struct dwc2_hsotg *hsotg, bool select_phy) { u32 usbcfg, usbcfg_old; int retval = 0; @@ -762,7 +763,7 @@ static int dwc2_hs_phy_init(struct dwc2_hsotg *hsotg, return retval; } -static int dwc2_phy_init(struct dwc2_hsotg *hsotg, bool select_phy) +STATIC int dwc2_phy_init(struct dwc2_hsotg *hsotg, bool select_phy) { u32 usbcfg; int retval = 0; @@ -798,7 +799,7 @@ static int dwc2_phy_init(struct dwc2_hsotg *hsotg, boo return retval; } -static int dwc2_gahbcfg_init(struct dwc2_hsotg *hsotg) +STATIC int dwc2_gahbcfg_init(struct dwc2_hsotg *hsotg) { struct dwc2_softc *sc = hsotg->hsotg_sc; u32 ahbcfg = DWC2_READ_4(hsotg, GAHBCFG); @@ -854,7 +855,7 @@ static int dwc2_gahbcfg_init(struct dwc2_hsotg *hsotg) return 0; } -static void dwc2_gusbcfg_init(struct dwc2_hsotg *hsotg) +STATIC void dwc2_gusbcfg_init(struct dwc2_hsotg *hsotg) { u32 usbcfg; @@ -1024,7 +1025,7 @@ void dwc2_disable_host_interrupts(struct dwc2_hsotg *h * * @hsotg: Programming view of DWC_otg controller */ -static void dwc2_calculate_dynamic_fifo(struct dwc2_hsotg *hsotg) +STATIC void dwc2_calculate_dynamic_fifo(struct dwc2_hsotg *hsotg) { struct dwc2_core_params *params = hsotg->core_params; struct dwc2_hw_params *hw = &hsotg->hw_params; @@ -1079,11 +1080,11 @@ static void dwc2_calculate_dynamic_fifo(struct dwc2_hs * * FIXME improve this FIFO allocation algorithm. */ - if (unlikely(total_fifo_size < (rxfsiz + nptxfsiz + ptxfsiz))) + if (total_fifo_size < (rxfsiz + nptxfsiz + ptxfsiz)) dev_err(hsotg->dev, "invalid fifo sizes\n"); } -static void dwc2_config_fifos(struct dwc2_hsotg *hsotg) +STATIC void dwc2_config_fifos(struct dwc2_hsotg *hsotg) { struct dwc2_core_params *params = hsotg->core_params; u32 nptxfsiz, hptxfsiz, dfifocfg, grxfsiz; @@ -1271,7 +1272,7 @@ void dwc2_core_host_init(struct dwc2_hsotg *hsotg) dwc2_enable_host_interrupts(hsotg); } -static void dwc2_hc_enable_slave_ints(struct dwc2_hsotg *hsotg, +STATIC void dwc2_hc_enable_slave_ints(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan) { u32 hcintmsk = HCINTMSK_CHHLTD; @@ -1349,7 +1350,7 @@ static void dwc2_hc_enable_slave_ints(struct dwc2_hsot dev_vdbg(hsotg->dev, "set HCINTMSK to %08x\n", hcintmsk); } -static void dwc2_hc_enable_dma_ints(struct dwc2_hsotg *hsotg, +STATIC void dwc2_hc_enable_dma_ints(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan) { u32 hcintmsk = HCINTMSK_CHHLTD; @@ -1386,7 +1387,7 @@ static void dwc2_hc_enable_dma_ints(struct dwc2_hsotg dev_vdbg(hsotg->dev, "set HCINTMSK to %08x\n", hcintmsk); } -static void dwc2_hc_enable_ints(struct dwc2_hsotg *hsotg, +STATIC void dwc2_hc_enable_ints(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan) { u32 intmsk; @@ -1714,7 +1715,7 @@ void dwc2_hc_cleanup(struct dwc2_hsotg *hsotg, struct * * This function has no effect on non-periodic transfers */ -static void dwc2_hc_set_even_odd_frame(struct dwc2_hsotg *hsotg, +STATIC void dwc2_hc_set_even_odd_frame(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan, u32 *hcchar) { if (chan->ep_type == USB_ENDPOINT_XFER_INT || @@ -1725,7 +1726,7 @@ static void dwc2_hc_set_even_odd_frame(struct dwc2_hso } } -static void dwc2_set_pid_isoc(struct dwc2_host_chan *chan) +STATIC void dwc2_set_pid_isoc(struct dwc2_host_chan *chan) { /* Set up the initial PID for the transfer */ if (chan->speed == USB_SPEED_HIGH) { @@ -1761,7 +1762,7 @@ static void dwc2_set_pid_isoc(struct dwc2_host_chan *c * Upon return the xfer_buf and xfer_count fields in chan are incremented by * the number of bytes written to the Tx FIFO. */ -static void dwc2_hc_write_packet(struct dwc2_hsotg *hsotg, +STATIC void dwc2_hc_write_packet(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan) { u32 i; @@ -2869,7 +2870,7 @@ void dwc2_set_param_phy_type(struct dwc2_hsotg *hsotg, hsotg->core_params->phy_type = val; } -static int dwc2_get_param_phy_type(struct dwc2_hsotg *hsotg) +STATIC int dwc2_get_param_phy_type(struct dwc2_hsotg *hsotg) { return hsotg->core_params->phy_type; } @@ -3135,7 +3136,7 @@ void dwc2_set_param_otg_ver(struct dwc2_hsotg *hsotg, hsotg->core_params->otg_ver = val; } -static void dwc2_set_param_uframe_sched(struct dwc2_hsotg *hsotg, int val) +STATIC void dwc2_set_param_uframe_sched(struct dwc2_hsotg *hsotg, int val) { if (DWC2_OUT_OF_BOUNDS(val, 0, 1)) { if (val >= 0) { @@ -3151,7 +3152,7 @@ static void dwc2_set_param_uframe_sched(struct dwc2_hs hsotg->core_params->uframe_sched = val; } -static void dwc2_set_param_external_id_pin_ctl(struct dwc2_hsotg *hsotg, +STATIC void dwc2_set_param_external_id_pin_ctl(struct dwc2_hsotg *hsotg, int val) { if (DWC2_OUT_OF_BOUNDS(val, 0, 1)) { @@ -3168,7 +3169,7 @@ static void dwc2_set_param_external_id_pin_ctl(struct hsotg->core_params->external_id_pin_ctl = val; } -static void dwc2_set_param_hibernation(struct dwc2_hsotg *hsotg, +STATIC void dwc2_set_param_hibernation(struct dwc2_hsotg *hsotg, int val) { if (DWC2_OUT_OF_BOUNDS(val, 0, 1)) { @@ -3240,7 +3241,7 @@ void dwc2_set_parameters(struct dwc2_hsotg *hsotg, * * Returns true if the mode was forced. */ -static bool dwc2_force_mode_if_needed(struct dwc2_hsotg *hsotg, bool host) +STATIC bool dwc2_force_mode_if_needed(struct dwc2_hsotg *hsotg, bool host) { if (host && dwc2_is_host_mode(hsotg)) return false; @@ -3255,7 +3256,7 @@ static bool dwc2_force_mode_if_needed(struct dwc2_hsot * host mode. Should be called immediately after a core soft reset in * order to get the reset values. */ -static void dwc2_get_host_hwparams(struct dwc2_hsotg *hsotg) +STATIC void dwc2_get_host_hwparams(struct dwc2_hsotg *hsotg) { struct dwc2_hw_params *hw = &hsotg->hw_params; u32 gnptxfsiz; @@ -3286,7 +3287,7 @@ static void dwc2_get_host_hwparams(struct dwc2_hsotg * * currently in device mode. Should be called immediately after a core * soft reset in order to get the reset values. */ -static void dwc2_get_dev_hwparams(struct dwc2_hsotg *hsotg) +STATIC void dwc2_get_dev_hwparams(struct dwc2_hsotg *hsotg) { struct dwc2_hw_params *hw = &hsotg->hw_params; bool forced; --- dwc2_core.h Wed Mar 31 07:42:18 2021 +++ /usr/src/sys/dev/usb/dwc2/dwc2_core.h Mon Jul 19 19:26:23 2021 @@ -1,4 +1,5 @@ -/* $NetBSD: dwc2_core.h,v 1.9 2018/08/08 07:20:44 simonb Exp $ */ +/* $OpenBSD: dwc2_core.h,v 1.9 2015/06/28 11:48:18 jmatthew Exp $ */ +/* $NetBSD: dwc2_core.h,v 1.5 2014/04/03 06:34:58 skrll Exp $ */ /* * core.h - DesignWare HS OTG Controller common declarations @@ -40,22 +41,25 @@ #define __DWC2_CORE_H__ #include +#include #include #include #include #include -#include +#include -#include "dwc2_hw.h" +#include +#include + /* Maximum number of Endpoints/HostChannels */ #define MAX_EPS_CHANNELS 16 #if IS_ENABLED(CONFIG_USB_DWC2_PERIPHERAL) || IS_ENABLED(CONFIG_USB_DWC2_DUAL_ROLE) /* dwc2-hsotg declarations */ -static const char * const dwc2_hsotg_supply_names[] = { +STATIC const char * const dwc2_hsotg_supply_names[] = { "vusb_d", /* digital USB supply, 1.2V */ "vusb_a", /* analog USB supply, 1.1V */ }; @@ -693,7 +697,7 @@ struct dwc2_hregs_backup { * @g_tx_fifo_sz: Contains tx fifo size value per endpoints */ struct dwc2_hsotg { - device_t dev; + struct device *dev; struct dwc2_softc *hsotg_sc; /** Params detected from hardware */ struct dwc2_hw_params hw_params; @@ -722,9 +726,9 @@ struct dwc2_hsotg { unsigned int queuing_high_bandwidth:1; unsigned int srp_success:1; - struct workqueue_struct *wq_otg; - struct work_struct wf_otg; - struct callout wkp_timer; + struct taskq *wq_otg; + struct task wf_otg; + struct timeout wkp_timer; enum dwc2_lx_state lx_state; struct dwc2_gregs_backup gr_backup; struct dwc2_dregs_backup dr_backup; @@ -784,7 +788,7 @@ struct dwc2_hsotg { int non_periodic_channels; int available_host_channels; struct dwc2_host_chan *hc_ptr_array[MAX_EPS_CHANNELS]; - usb_dma_t status_buf_usbdma; + struct usb_dma status_buf_usbdma; u8 *status_buf; dma_addr_t status_buf_dma; #define DWC2_HCD_STATUS_BUF_SIZE 64 @@ -792,7 +796,7 @@ struct dwc2_hsotg { struct delayed_work start_work; struct delayed_work reset_work; u8 otg_port; - usb_dma_t frame_list_usbdma; + struct usb_dma frame_list_usbdma; u32 *frame_list; dma_addr_t frame_list_dma; u32 frame_list_sz; --- dwc2_coreintr.c Wed Mar 31 07:42:18 2021 +++ /usr/src/sys/dev/usb/dwc2/dwc2_coreintr.c Wed Jul 14 17:24:28 2021 @@ -1,4 +1,5 @@ -/* $NetBSD: dwc2_coreintr.c,v 1.11 2016/02/24 22:17:54 skrll Exp $ */ +/* $OpenBSD: dwc2_coreintr.c,v 1.10 2017/06/29 17:36:16 deraadt Exp $ */ +/* $NetBSD: dwc2_coreintr.c,v 1.8 2014/04/04 05:40:57 skrll Exp $ */ /* * core_intr.c - DesignWare HS OTG Controller common interrupt handling @@ -40,33 +41,30 @@ * This file contains the common interrupt handlers */ -#include -__KERNEL_RCSID(0, "$NetBSD: dwc2_coreintr.c,v 1.11 2016/02/24 22:17:54 skrll Exp $"); - #include +#include #include #include #include -#include -#include +#include +#include + +#include + #include #include #include #include -#include -#include -#include +#include +#include -#include -#include +#include +#include -#include "dwc2_core.h" -#include "dwc2_hcd.h" - #ifdef DWC2_DEBUG -static const char *dwc2_op_state_str(struct dwc2_hsotg *hsotg) +STATIC const char *dwc2_op_state_str(struct dwc2_hsotg *hsotg) { switch (hsotg->op_state) { case OTG_STATE_A_HOST: @@ -92,7 +90,7 @@ static const char *dwc2_op_state_str(struct dwc2_hsotg * * @hsotg: Programming view of DWC_otg controller */ -static void dwc2_handle_usb_port_intr(struct dwc2_hsotg *hsotg) +STATIC void dwc2_handle_usb_port_intr(struct dwc2_hsotg *hsotg) { u32 hprt0 = DWC2_READ_4(hsotg, HPRT0); @@ -107,7 +105,7 @@ static void dwc2_handle_usb_port_intr(struct dwc2_hsot * * @hsotg: Programming view of DWC_otg controller */ -static void dwc2_handle_mode_mismatch_intr(struct dwc2_hsotg *hsotg) +STATIC void dwc2_handle_mode_mismatch_intr(struct dwc2_hsotg *hsotg) { /* Clear interrupt */ DWC2_WRITE_4(hsotg, GINTSTS, GINTSTS_MODEMIS); @@ -122,7 +120,7 @@ static void dwc2_handle_mode_mismatch_intr(struct dwc2 * * @hsotg: Programming view of DWC_otg controller */ -static void dwc2_handle_otg_intr(struct dwc2_hsotg *hsotg) +STATIC void dwc2_handle_otg_intr(struct dwc2_hsotg *hsotg) { u32 gotgint; u32 gotgctl; @@ -285,7 +283,7 @@ static void dwc2_handle_otg_intr(struct dwc2_hsotg *hs * Device to Host Mode transition or a Host to Device Mode transition. This only * occurs when the cable is connected/removed from the PHY connector. */ -static void dwc2_handle_conn_id_status_change_intr(struct dwc2_hsotg *hsotg) +STATIC void dwc2_handle_conn_id_status_change_intr(struct dwc2_hsotg *hsotg) { u32 gintmsk; @@ -307,7 +305,7 @@ static void dwc2_handle_conn_id_status_change_intr(str */ if (hsotg->wq_otg) { spin_unlock(&hsotg->lock); - queue_work(hsotg->wq_otg, &hsotg->wf_otg); + task_add(hsotg->wq_otg, &hsotg->wf_otg); spin_lock(&hsotg->lock); } } @@ -323,7 +321,7 @@ static void dwc2_handle_conn_id_status_change_intr(str * in low power mode, this handler brings the controller out of low power mode * before turning on bus power. */ -static void dwc2_handle_session_req_intr(struct dwc2_hsotg *hsotg) +STATIC void dwc2_handle_session_req_intr(struct dwc2_hsotg *hsotg) { int ret; @@ -336,7 +334,7 @@ static void dwc2_handle_session_req_intr(struct dwc2_h if (dwc2_is_device_mode(hsotg)) { if (hsotg->lx_state == DWC2_L2) { ret = dwc2_exit_hibernation(hsotg, true); - if (ret && (ret != -ENOTSUPP)) + if (ret && (ret != -ENOTSUP)) dev_err(hsotg->dev, "exit hibernation failed\n"); } @@ -356,7 +354,7 @@ static void dwc2_handle_session_req_intr(struct dwc2_h * power mode. The controller automatically begins resume signaling. * The handler schedules a time to stop resume signaling. */ -static void dwc2_handle_wakeup_detected_intr(struct dwc2_hsotg *hsotg) +STATIC void dwc2_handle_wakeup_detected_intr(struct dwc2_hsotg *hsotg) { int ret; @@ -375,7 +373,7 @@ static void dwc2_handle_wakeup_detected_intr(struct dw dctl &= ~DCTL_RMTWKUPSIG; DWC2_WRITE_4(hsotg, DCTL, dctl); ret = dwc2_exit_hibernation(hsotg, true); - if (ret && (ret != -ENOTSUPP)) + if (ret && (ret != -ENOTSUP)) dev_err(hsotg->dev, "exit hibernation failed\n"); call_gadget(hsotg, resume); @@ -392,8 +390,9 @@ static void dwc2_handle_wakeup_detected_intr(struct dw /* Restart the Phy Clock */ pcgcctl &= ~PCGCTL_STOPPCLK; DWC2_WRITE_4(hsotg, PCGCTL, pcgcctl); - callout_reset(&hsotg->wkp_timer, mstohz(71), - dwc2_wakeup_detected, hsotg); + timeout_set(&hsotg->wkp_timer, dwc2_wakeup_detected, + hsotg); + timeout_add_msec(&hsotg->wkp_timer, 71); } else { /* Change to L0 state */ hsotg->lx_state = DWC2_L0; @@ -405,7 +404,7 @@ static void dwc2_handle_wakeup_detected_intr(struct dw * This interrupt indicates that a device has been disconnected from the * root port */ -static void dwc2_handle_disconnect_intr(struct dwc2_hsotg *hsotg) +STATIC void dwc2_handle_disconnect_intr(struct dwc2_hsotg *hsotg) { DWC2_WRITE_4(hsotg, GINTSTS, GINTSTS_DISCONNINT); @@ -425,7 +424,7 @@ static void dwc2_handle_disconnect_intr(struct dwc2_hs * * When power management is enabled the core will be put in low power mode. */ -static void dwc2_handle_usb_suspend_intr(struct dwc2_hsotg *hsotg) +STATIC void dwc2_handle_usb_suspend_intr(struct dwc2_hsotg *hsotg) { u32 dsts; int ret; @@ -456,7 +455,7 @@ static void dwc2_handle_usb_suspend_intr(struct dwc2_h ret = dwc2_enter_hibernation(hsotg); if (ret) { - if (ret != -ENOTSUPP) + if (ret != -ENOTSUP) dev_err(hsotg->dev, "enter hibernation failed\n"); goto skip_power_saving; @@ -465,7 +464,7 @@ static void dwc2_handle_usb_suspend_intr(struct dwc2_h udelay(100); /* Ask phy to be suspended */ - if (!IS_ERR_OR_NULL(hsotg->uphy)) + if (hsotg->uphy != NULL) usb_phy_set_suspend(hsotg->uphy, true); skip_power_saving: /* @@ -500,7 +499,7 @@ skip_power_saving: /* * This function returns the Core Interrupt register */ -static u32 dwc2_read_common_intr(struct dwc2_hsotg *hsotg) +STATIC u32 dwc2_read_common_intr(struct dwc2_hsotg *hsotg) { u32 gintsts; u32 gintmsk; @@ -546,7 +545,7 @@ irqreturn_t dwc2_handle_common_intr(void *dev) goto out; } - KASSERT(mutex_owned(&hsotg->lock)); + MUTEX_ASSERT_LOCKED(&hsotg->lock); gintsts = dwc2_read_common_intr(hsotg); if (gintsts & ~GINTSTS_PRTINT) --- dwc2_hcd.c Wed Mar 31 07:42:18 2021 +++ /usr/src/sys/dev/usb/dwc2/dwc2_hcd.c Wed Jul 14 17:25:18 2021 @@ -1,4 +1,5 @@ -/* $NetBSD: dwc2_hcd.c,v 1.25 2021/01/11 17:00:18 skrll Exp $ */ +/* $OpenBSD: dwc2_hcd.c,v 1.22 2020/03/21 12:08:31 patrick Exp $ */ +/* $NetBSD: dwc2_hcd.c,v 1.15 2014/11/24 10:14:14 skrll Exp $ */ /* * hcd.c - DesignWare HS OTG Controller host-mode routines @@ -41,30 +42,27 @@ * API */ -#include -__KERNEL_RCSID(0, "$NetBSD: dwc2_hcd.c,v 1.25 2021/01/11 17:00:18 skrll Exp $"); - -#include -#include +#include +#include +#include +#include #include #include +#include +#include + #include #include #include #include -#include -#include -#include -#include +#include +#include -#include -#include +#include +#include -#include "dwc2_core.h" -#include "dwc2_hcd.h" - /** * dwc2_dump_channel_info() - Prints the state of a host channel * @@ -77,7 +75,7 @@ __KERNEL_RCSID(0, "$NetBSD: dwc2_hcd.c,v 1.25 2021/01/ * is integrated and the driver is stable */ #ifdef VERBOSE_DEBUG -static void dwc2_dump_channel_info(struct dwc2_hsotg *hsotg, +STATIC void dwc2_dump_channel_info(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan) { int num_channels = hsotg->core_params->host_channels; @@ -140,7 +138,7 @@ static void dwc2_dump_channel_info(struct dwc2_hsotg * * * Must be called with interrupt disabled and spinlock held */ -static void dwc2_kill_urbs_in_qh_list(struct dwc2_hsotg *hsotg, +STATIC void dwc2_kill_urbs_in_qh_list(struct dwc2_hsotg *hsotg, struct list_head *qh_list) { struct dwc2_qh *qh, *qh_tmp; @@ -155,7 +153,7 @@ static void dwc2_kill_urbs_in_qh_list(struct dwc2_hsot } } -static void dwc2_qh_list_free(struct dwc2_hsotg *hsotg, +STATIC void dwc2_qh_list_free(struct dwc2_hsotg *hsotg, struct list_head *qh_list) { struct dwc2_qtd *qtd, *qtd_tmp; @@ -195,7 +193,7 @@ static void dwc2_qh_list_free(struct dwc2_hsotg *hsotg * * Must be called with interrupt disabled and spinlock held */ -static void dwc2_kill_all_urbs(struct dwc2_hsotg *hsotg) +STATIC void dwc2_kill_all_urbs(struct dwc2_hsotg *hsotg) { dwc2_kill_urbs_in_qh_list(hsotg, &hsotg->non_periodic_sched_inactive); dwc2_kill_urbs_in_qh_list(hsotg, &hsotg->non_periodic_sched_waiting); @@ -231,7 +229,7 @@ void dwc2_hcd_start(struct dwc2_hsotg *hsotg) } /* Must be called with interrupt disabled and spinlock held */ -static void dwc2_hcd_cleanup_channels(struct dwc2_hsotg *hsotg) +STATIC void dwc2_hcd_cleanup_channels(struct dwc2_hsotg *hsotg) { int num_channels = hsotg->core_params->host_channels; struct dwc2_host_chan *channel; @@ -376,7 +374,7 @@ void dwc2_hcd_disconnect(struct dwc2_hsotg *hsotg, boo * * @hsotg: Pointer to struct dwc2_hsotg */ -static void dwc2_hcd_rem_wakeup(struct dwc2_hsotg *hsotg) +STATIC void dwc2_hcd_rem_wakeup(struct dwc2_hsotg *hsotg) { if (hsotg->bus_suspended) { hsotg->flags.b.port_suspend_change = 1; @@ -582,7 +580,7 @@ dwc2_hcd_reinit(struct dwc2_hsotg *hsotg) dwc2_core_host_init(hsotg); } -static void dwc2_hc_init_split(struct dwc2_hsotg *hsotg, +STATIC void dwc2_hc_init_split(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan, struct dwc2_qtd *qtd, struct dwc2_hcd_urb *urb) { @@ -596,7 +594,7 @@ static void dwc2_hc_init_split(struct dwc2_hsotg *hsot chan->hub_port = (u8)hub_port; } -static void *dwc2_hc_init_xfer_data(struct dwc2_hsotg *hsotg, +STATIC void *dwc2_hc_init_xfer_data(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan, struct dwc2_qtd *qtd, struct dwc2_hcd_urb *urb) { @@ -614,7 +612,7 @@ static void *dwc2_hc_init_xfer_data(struct dwc2_hsotg return NULL; } -static void *dwc2_hc_init_xfer(struct dwc2_hsotg *hsotg, +STATIC void *dwc2_hc_init_xfer(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan, struct dwc2_qtd *qtd, struct dwc2_hcd_urb *urb) { @@ -715,7 +713,7 @@ static void *dwc2_hc_init_xfer(struct dwc2_hsotg *hsot return bufptr; } -static int dwc2_hc_setup_align_buf(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh, +STATIC int dwc2_hc_setup_align_buf(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh, struct dwc2_host_chan *chan, struct dwc2_hcd_urb *urb, void *bufptr) { @@ -733,9 +731,9 @@ static int dwc2_hc_setup_align_buf(struct dwc2_hsotg * qh->dw_align_buf = NULL; qh->dw_align_buf_dma = 0; err = usb_allocmem(&hsotg->hsotg_sc->sc_bus, buf_size, 0, - USBMALLOC_COHERENT, &qh->dw_align_buf_usbdma); + USB_DMA_COHERENT, &qh->dw_align_buf_usbdma); if (!err) { - usb_dma_t *ud = &qh->dw_align_buf_usbdma; + struct usb_dma *ud = &qh->dw_align_buf_usbdma; qh->dw_align_buf = KERNADDR(ud, 0); qh->dw_align_buf_dma = DMAADDR(ud, 0); @@ -775,7 +773,7 @@ static int dwc2_hc_setup_align_buf(struct dwc2_hsotg * * @qh: Transactions from the first QTD for this QH are selected and assigned * to a free host channel */ -static int dwc2_assign_and_init_hc(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh) +STATIC int dwc2_assign_and_init_hc(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh) { struct dwc2_host_chan *chan; struct dwc2_hcd_urb *urb; @@ -1019,7 +1017,7 @@ enum dwc2_transaction_type dwc2_hcd_select_transaction * * Must be called with interrupt disabled and spinlock held */ -static int dwc2_queue_transaction(struct dwc2_hsotg *hsotg, +STATIC int dwc2_queue_transaction(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan, u16 fifo_dwords_avail) { @@ -1076,7 +1074,7 @@ static int dwc2_queue_transaction(struct dwc2_hsotg *h * * Must be called with interrupt disabled and spinlock held */ -static void dwc2_process_periodic_channels(struct dwc2_hsotg *hsotg) +STATIC void dwc2_process_periodic_channels(struct dwc2_hsotg *hsotg) { struct list_head *qh_ptr; struct dwc2_qh *qh; @@ -1216,7 +1214,7 @@ static void dwc2_process_periodic_channels(struct dwc2 * * Must be called with interrupt disabled and spinlock held */ -static void dwc2_process_non_periodic_channels(struct dwc2_hsotg *hsotg) +STATIC void dwc2_process_non_periodic_channels(struct dwc2_hsotg *hsotg) { struct list_head *orig_qh_ptr; struct dwc2_qh *qh; @@ -1370,10 +1368,10 @@ void dwc2_hcd_queue_transactions(struct dwc2_hsotg *hs } } -static void dwc2_conn_id_status_change(struct work_struct *work) + +STATIC void dwc2_conn_id_status_change(void *data) { - struct dwc2_hsotg *hsotg = container_of(work, struct dwc2_hsotg, - wf_otg); + struct dwc2_hsotg *hsotg = data; u32 count = 0; u32 gotgctl; unsigned long flags; @@ -1457,7 +1455,7 @@ void dwc2_wakeup_detected(void *data) } /* Must NOT be called with interrupt disabled or spinlock held */ -static void dwc2_port_suspend(struct dwc2_hsotg *hsotg, u16 windex) +STATIC void dwc2_port_suspend(struct dwc2_hsotg *hsotg, u16 windex) { unsigned long flags; u32 hprt0; @@ -1508,8 +1506,9 @@ static void dwc2_port_suspend(struct dwc2_hsotg *hsotg } /* Must NOT be called with interrupt disabled or spinlock held */ -static void dwc2_port_resume(struct dwc2_hsotg *hsotg) +STATIC void dwc2_port_resume(struct dwc2_hsotg *hsotg) { + struct dwc2_softc *sc = hsotg->hsotg_sc; unsigned long flags; u32 hprt0; u32 pcgctl; @@ -1535,7 +1534,7 @@ static void dwc2_port_resume(struct dwc2_hsotg *hsotg) DWC2_WRITE_4(hsotg, HPRT0, hprt0); spin_unlock_irqrestore(&hsotg->lock, flags); - msleep(USB_RESUME_TIMEOUT); + usb_delay_ms(&sc->sc_bus, USB_RESUME_TIMEOUT); spin_lock_irqsave(&hsotg->lock, flags); hprt0 = dwc2_read_hprt0(hsotg); @@ -1907,14 +1906,8 @@ dwc2_hcd_urb_alloc(struct dwc2_hsotg *hsotg, int iso_d struct dwc2_hcd_urb *urb; u32 size = sizeof(*urb) + iso_desc_count * sizeof(struct dwc2_hcd_iso_packet_desc); - int kmem_flag; - if ((mem_flags & __GFP_WAIT) == __GFP_WAIT) - kmem_flag = KM_SLEEP; - else - kmem_flag = KM_NOSLEEP; - - urb = kmem_zalloc(size, kmem_flag); + urb = malloc(size, M_DEVBUF, M_ZERO | mem_flags); if (urb) urb->packet_count = iso_desc_count; return urb; @@ -1928,7 +1921,7 @@ dwc2_hcd_urb_free(struct dwc2_hsotg *hsotg, struct dwc u32 size = sizeof(*urb) + iso_desc_count * sizeof(struct dwc2_hcd_iso_packet_desc); - kmem_free(urb, size); + free(urb, M_DEVBUF, size); } void @@ -2167,10 +2160,9 @@ void dwc2_host_disconnect(struct dwc2_hsotg *hsotg) /* * Work queue function for starting the HCD when A-Cable is connected */ -static void dwc2_hcd_start_func(struct work_struct *work) +STATIC void dwc2_hcd_start_func(void *data) { - struct dwc2_hsotg *hsotg = container_of(work, struct dwc2_hsotg, - start_work.work); + struct dwc2_hsotg *hsotg = data; dev_dbg(hsotg->dev, "%s() %p\n", __func__, hsotg); dwc2_host_start(hsotg); @@ -2179,10 +2171,9 @@ static void dwc2_hcd_start_func(struct work_struct *wo /* * Reset work queue function */ -static void dwc2_hcd_reset_func(struct work_struct *work) +STATIC void dwc2_hcd_reset_func(void *data) { - struct dwc2_hsotg *hsotg = container_of(work, struct dwc2_hsotg, - reset_work.work); + struct dwc2_hsotg *hsotg = data; unsigned long flags; u32 hprt0; @@ -2216,7 +2207,7 @@ static void dwc2_hcd_reset_func(struct work_struct *wo * Frees secondary storage associated with the dwc2_hsotg structure contained * in the struct usb_hcd field */ -static void dwc2_hcd_free(struct dwc2_hsotg *hsotg) +STATIC void dwc2_hcd_free(struct dwc2_hsotg *hsotg) { u32 ahbcfg; u32 dctl; @@ -2241,7 +2232,7 @@ static void dwc2_hcd_free(struct dwc2_hsotg *hsotg) dev_dbg(hsotg->dev, "HCD Free channel #%i, chan=%p\n", i, chan); hsotg->hc_ptr_array[i] = NULL; - kmem_free(chan, sizeof(*chan)); + free(chan, M_DEVBUF, sizeof(*chan)); } } @@ -2252,7 +2243,7 @@ static void dwc2_hcd_free(struct dwc2_hsotg *hsotg) hsotg->status_buf = NULL; } } else { - kmem_free(hsotg->status_buf,DWC2_HCD_STATUS_BUF_SIZE); + free(hsotg->status_buf, M_DEVBUF, DWC2_HCD_STATUS_BUF_SIZE); hsotg->status_buf = NULL; } @@ -2270,17 +2261,15 @@ static void dwc2_hcd_free(struct dwc2_hsotg *hsotg) } if (hsotg->wq_otg) { - if (!cancel_work_sync(&hsotg->wf_otg)) - flush_workqueue(hsotg->wq_otg); - destroy_workqueue(hsotg->wq_otg); + taskq_destroy(hsotg->wq_otg); } - kmem_free(hsotg->core_params, sizeof(*hsotg->core_params)); + free(hsotg->core_params, M_DEVBUF, sizeof(*hsotg->core_params)); hsotg->core_params = NULL; - callout_destroy(&hsotg->wkp_timer); + timeout_del(&hsotg->wkp_timer); } -static void dwc2_hcd_release(struct dwc2_hsotg *hsotg) +STATIC void dwc2_hcd_release(struct dwc2_hsotg *hsotg) { /* Turn off all host-specific interrupts */ dwc2_disable_host_interrupts(hsotg); @@ -2310,13 +2299,14 @@ int dwc2_hcd_init(struct dwc2_hsotg *hsotg) dev_dbg(hsotg->dev, "hcfg=%08x\n", DWC2_READ_4(hsotg, HCFG)); #ifdef CONFIG_USB_DWC2_TRACK_MISSED_SOFS - hsotg->frame_num_array = kmem_zalloc(sizeof(*hsotg->frame_num_array) * - FRAME_NUM_ARRAY_SIZE, KM_SLEEP); + hsotg->frame_num_array = malloc(sizeof(*hsotg->frame_num_array) * + FRAME_NUM_ARRAY_SIZE, M_DEVBUF, + M_ZERO | M_WAITOK); if (!hsotg->frame_num_array) goto error1; - hsotg->last_frame_num_array = kmem_zalloc( + hsotg->last_frame_num_array = malloc( sizeof(*hsotg->last_frame_num_array) * - FRAME_NUM_ARRAY_SIZE, KM_SLEEP); + FRAME_NUM_ARRAY_SIZE, M_DEVBUF, M_ZERO | M_WAITOK); if (!hsotg->last_frame_num_array) goto error1; hsotg->last_frame_num = HFNUM_MAX_FRNUM; @@ -2337,15 +2327,14 @@ int dwc2_hcd_init(struct dwc2_hsotg *hsotg) /* Create new workqueue and init work */ retval = -ENOMEM; - hsotg->wq_otg = create_singlethread_workqueue("dwc2"); + hsotg->wq_otg = taskq_create("dwc2", 1, IPL_USB, 0); if (!hsotg->wq_otg) { dev_err(hsotg->dev, "Failed to create workqueue\n"); goto error2; } - INIT_WORK(&hsotg->wf_otg, dwc2_conn_id_status_change); + task_set(&hsotg->wf_otg, dwc2_conn_id_status_change, hsotg); - callout_init(&hsotg->wkp_timer, CALLOUT_MPSAFE); - callout_setfunc(&hsotg->wkp_timer, dwc2_wakeup_detected, hsotg); + timeout_set(&hsotg->wkp_timer, dwc2_wakeup_detected, hsotg); /* Initialize the non-periodic schedule */ INIT_LIST_HEAD(&hsotg->non_periodic_sched_inactive); @@ -2367,7 +2356,7 @@ int dwc2_hcd_init(struct dwc2_hsotg *hsotg) memset(&hsotg->hc_ptr_array[0], 0, sizeof(hsotg->hc_ptr_array)); for (i = 0; i < num_channels; i++) { - channel = kmem_zalloc(sizeof(*channel), KM_SLEEP); + channel = malloc(sizeof(*channel), M_DEVBUF, M_ZERO | M_WAITOK); if (channel == NULL) goto error3; channel->hc_num = i; @@ -2378,10 +2367,10 @@ int dwc2_hcd_init(struct dwc2_hsotg *hsotg) dwc2_hcd_init_usecs(hsotg); /* Initialize hsotg start work */ - INIT_DELAYED_WORK(&hsotg->start_work, dwc2_hcd_start_func); + INIT_DELAYED_WORK(&hsotg->start_work, dwc2_hcd_start_func, hsotg); /* Initialize port reset work */ - INIT_DELAYED_WORK(&hsotg->reset_work, dwc2_hcd_reset_func); + INIT_DELAYED_WORK(&hsotg->reset_work, dwc2_hcd_reset_func, hsotg); /* * Allocate space for storing data on status transactions. Normally no @@ -2392,15 +2381,15 @@ int dwc2_hcd_init(struct dwc2_hsotg *hsotg) hsotg->status_buf = NULL; if (hsotg->core_params->dma_enable > 0) { int error = usb_allocmem(&hsotg->hsotg_sc->sc_bus, - DWC2_HCD_STATUS_BUF_SIZE, 0, USBMALLOC_COHERENT, + DWC2_HCD_STATUS_BUF_SIZE, 0, USB_DMA_COHERENT, &hsotg->status_buf_usbdma); if (!error) { hsotg->status_buf = KERNADDR(&hsotg->status_buf_usbdma, 0); hsotg->status_buf_dma = DMAADDR(&hsotg->status_buf_usbdma, 0); } } else - hsotg->status_buf = kmem_zalloc(DWC2_HCD_STATUS_BUF_SIZE, - KM_SLEEP); + hsotg->status_buf = malloc(DWC2_HCD_STATUS_BUF_SIZE, M_DEVBUF, + M_ZERO | M_WAITOK); /* retval is already -ENOMEM */ if (!hsotg->status_buf) @@ -2426,15 +2415,15 @@ error3: dwc2_hcd_release(hsotg); error2: if (hsotg->core_params != NULL) - kmem_free(hsotg->core_params, sizeof(*hsotg->core_params)); + free(hsotg->core_params, M_DEVBUF, sizeof(*hsotg->core_params)); #ifdef CONFIG_USB_DWC2_TRACK_MISSED_SOFS if (hsotg->last_frame_num_array != NULL) - kmem_free(hsotg->last_frame_num_array, - sizeof(*hsotg->last_frame_num_array) * FRAME_NUM_ARRAY_SIZE); + free(hsotg->last_frame_num_array, M_DEVBUF, + sizeof(*hsotg->last_frame_num_array) * FRAME_NUM_ARRAY_SIZE); if (hsotg->frame_num_array != NULL) - kmem_free(hsotg->frame_num_array, - sizeof(*hsotg->frame_num_array) * FRAME_NUM_ARRAY_SIZE); + free(hsotg->frame_num_array, M_DEVBUF, + sizeof(*hsotg->frame_num_array) * FRAME_NUM_ARRAY_SIZE); #endif dev_err(hsotg->dev, "%s() FAILED, returning %d\n", __func__, retval); @@ -2464,7 +2453,7 @@ void dwc2_hcd_remove(struct dwc2_hsotg *hsotg) dwc2_hcd_release(hsotg); #ifdef CONFIG_USB_DWC2_TRACK_MISSED_SOFS - kmem_free(hsotg->last_frame_num_array, sizeof(*hsotg->last_frame_num_array) * FRAME_NUM_ARRAY_SIZE); - kmem_free(hsotg->frame_num_array, sizeof(*hsotg->frame_num_array) * FRAME_NUM_ARRAY_SIZE); + free(hsotg->last_frame_num_array, M_DEVBUF, sizeof(*hsotg->last_frame_num_array) * FRAME_NUM_ARRAY_SIZE); + free(hsotg->frame_num_array, M_DEVBUF, sizeof(*hsotg->frame_num_array) * FRAME_NUM_ARRAY_SIZE); #endif } --- dwc2_hcd.h Wed Mar 31 07:42:18 2021 +++ /usr/src/sys/dev/usb/dwc2/dwc2_hcd.h Mon Jul 19 19:26:37 2021 @@ -1,4 +1,5 @@ -/* $NetBSD: dwc2_hcd.h,v 1.15 2018/08/08 07:20:44 simonb Exp $ */ +/* $OpenBSD: dwc2_hcd.h,v 1.13 2015/06/28 11:48:18 jmatthew Exp $ */ +/* $NetBSD: dwc2_hcd.h,v 1.9 2014/09/03 10:00:08 skrll Exp $ */ /* * hcd.h - DesignWare HS OTG Controller host-mode declarations @@ -133,7 +134,7 @@ struct dwc2_host_chan { unsigned multi_count:2; - usb_dma_t *xfer_usbdma; + struct usb_dma *xfer_usbdma; u8 *xfer_buf; dma_addr_t xfer_dma; dma_addr_t align_buf; @@ -162,7 +163,7 @@ struct dwc2_host_chan { u32 hcint; struct dwc2_qh *qh; struct list_head hc_list_entry; - usb_dma_t desc_list_usbdma; + struct usb_dma desc_list_usbdma; dma_addr_t desc_list_addr; u32 desc_list_sz; }; @@ -187,10 +188,10 @@ struct dwc2_qtd; struct dwc2_hcd_urb { void *priv; /* the xfer handle */ struct dwc2_qtd *qtd; - usb_dma_t *usbdma; + struct usb_dma *usbdma; u8 *buf; dma_addr_t dma; - usb_dma_t *setup_usbdma; + struct usb_dma *setup_usbdma; void *setup_packet; dma_addr_t setup_dma; u32 length; @@ -293,20 +294,20 @@ struct dwc2_qh { u16 frame_usecs[8]; u16 start_split_frame; u16 ntd; - usb_dma_t dw_align_buf_usbdma; + struct usb_dma dw_align_buf_usbdma; u8 *dw_align_buf; int dw_align_buf_size; dma_addr_t dw_align_buf_dma; struct list_head qtd_list; struct dwc2_host_chan *channel; struct list_head qh_list_entry; - usb_dma_t desc_list_usbdma; + struct usb_dma desc_list_usbdma; struct dwc2_hcd_dma_desc *desc_list; dma_addr_t desc_list_dma; u32 desc_list_sz; u32 *n_bytes; /* XXX struct timer_list wait_timer; */ - callout_t wait_timer; + struct timeout wait_timer; unsigned tt_buffer_dirty:1; unsigned want_wait:1; unsigned wait_timer_cancel:1; --- dwc2_hcdddma.c Wed Mar 31 07:42:18 2021 +++ /usr/src/sys/dev/usb/dwc2/dwc2_hcdddma.c Wed Jul 14 17:26:43 2021 @@ -1,4 +1,5 @@ -/* $NetBSD: dwc2_hcdddma.c,v 1.9 2020/04/05 20:59:38 skrll Exp $ */ +/* $OpenBSD: dwc2_hcdddma.c,v 1.16 2020/03/21 12:08:31 patrick Exp $ */ +/* $NetBSD: dwc2_hcdddma.c,v 1.6 2014/04/03 06:34:58 skrll Exp $ */ /* * hcd_ddma.c - DesignWare HS OTG Controller descriptor DMA routines @@ -39,74 +40,68 @@ /* * This file contains the Descriptor DMA implementation for Host mode */ -#include -__KERNEL_RCSID(0, "$NetBSD: dwc2_hcdddma.c,v 1.9 2020/04/05 20:59:38 skrll Exp $"); #include -#include +#include #include -#include -#include +#include +#include + #include #include #include #include -#include -#include +#include +#include -#include -#include +#include +#include -#include "dwc2_core.h" -#include "dwc2_hcd.h" - -static u16 dwc2_frame_list_idx(u16 frame) +STATIC u16 dwc2_frame_list_idx(u16 frame) { return frame & (FRLISTEN_64_SIZE - 1); } -static u16 dwc2_desclist_idx_inc(u16 idx, u16 inc, u8 speed) +STATIC u16 dwc2_desclist_idx_inc(u16 idx, u16 inc, u8 speed) { return (idx + inc) & ((speed == USB_SPEED_HIGH ? MAX_DMA_DESC_NUM_HS_ISOC : MAX_DMA_DESC_NUM_GENERIC) - 1); } -static u16 dwc2_desclist_idx_dec(u16 idx, u16 inc, u8 speed) +STATIC u16 dwc2_desclist_idx_dec(u16 idx, u16 inc, u8 speed) { return (idx - inc) & ((speed == USB_SPEED_HIGH ? MAX_DMA_DESC_NUM_HS_ISOC : MAX_DMA_DESC_NUM_GENERIC) - 1); } -static u16 dwc2_max_desc_num(struct dwc2_qh *qh) +STATIC u16 dwc2_max_desc_num(struct dwc2_qh *qh) { return (qh->ep_type == USB_ENDPOINT_XFER_ISOC && qh->dev_speed == USB_SPEED_HIGH) ? MAX_DMA_DESC_NUM_HS_ISOC : MAX_DMA_DESC_NUM_GENERIC; } -static u16 dwc2_frame_incr_val(struct dwc2_qh *qh) +STATIC u16 dwc2_frame_incr_val(struct dwc2_qh *qh) { return qh->dev_speed == USB_SPEED_HIGH ? (qh->interval + 8 - 1) / 8 : qh->interval; } -static int dwc2_desc_list_alloc(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh, +STATIC int dwc2_desc_list_alloc(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh, gfp_t flags) { int err; - KASSERT(!cpu_intr_p() && !cpu_softintr_p()); - qh->desc_list = NULL; qh->desc_list_sz = sizeof(struct dwc2_hcd_dma_desc) * dwc2_max_desc_num(qh); err = usb_allocmem(&hsotg->hsotg_sc->sc_bus, qh->desc_list_sz, 0, - USBMALLOC_COHERENT, &qh->desc_list_usbdma); + USB_DMA_COHERENT, &qh->desc_list_usbdma); if (err) return -ENOMEM; @@ -114,7 +109,9 @@ static int dwc2_desc_list_alloc(struct dwc2_hsotg *hso qh->desc_list = KERNADDR(&qh->desc_list_usbdma, 0); qh->desc_list_dma = DMAADDR(&qh->desc_list_usbdma, 0); - qh->n_bytes = kmem_zalloc(sizeof(u32) * dwc2_max_desc_num(qh), KM_SLEEP); + qh->n_bytes = malloc(sizeof(u32) * dwc2_max_desc_num(qh), M_DEVBUF, + M_ZERO | M_WAITOK); + if (!qh->n_bytes) { usb_freemem(&hsotg->hsotg_sc->sc_bus, &qh->desc_list_usbdma); qh->desc_list = NULL; @@ -124,7 +121,7 @@ static int dwc2_desc_list_alloc(struct dwc2_hsotg *hso return 0; } -static void dwc2_desc_list_free(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh) +STATIC void dwc2_desc_list_free(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh) { if (qh->desc_list) { @@ -132,11 +129,11 @@ static void dwc2_desc_list_free(struct dwc2_hsotg *hso qh->desc_list = NULL; } - kmem_free(qh->n_bytes, sizeof(u32) * dwc2_max_desc_num(qh)); + free(qh->n_bytes, M_DEVBUF, sizeof(u32) * dwc2_max_desc_num(qh)); qh->n_bytes = NULL; } -static int dwc2_frame_list_alloc(struct dwc2_hsotg *hsotg, gfp_t mem_flags) +STATIC int dwc2_frame_list_alloc(struct dwc2_hsotg *hsotg, gfp_t mem_flags) { int err; @@ -147,7 +144,7 @@ static int dwc2_frame_list_alloc(struct dwc2_hsotg *hs hsotg->frame_list_sz = 4 * FRLISTEN_64_SIZE; hsotg->frame_list = NULL; err = usb_allocmem(&hsotg->hsotg_sc->sc_bus, hsotg->frame_list_sz, - 0, USBMALLOC_COHERENT, &hsotg->frame_list_usbdma); + 0, USB_DMA_COHERENT, &hsotg->frame_list_usbdma); if (!err) { hsotg->frame_list = KERNADDR(&hsotg->frame_list_usbdma, 0); @@ -160,9 +157,9 @@ static int dwc2_frame_list_alloc(struct dwc2_hsotg *hs return 0; } -static void dwc2_frame_list_free(struct dwc2_hsotg *hsotg) +STATIC void dwc2_frame_list_free(struct dwc2_hsotg *hsotg) { - usb_dma_t frame_list_usbdma; + struct usb_dma frame_list_usbdma; unsigned long flags; spin_lock_irqsave(&hsotg->lock, flags); @@ -180,7 +177,7 @@ static void dwc2_frame_list_free(struct dwc2_hsotg *hs usb_freemem(&hsotg->hsotg_sc->sc_bus, &frame_list_usbdma); } -static void dwc2_per_sched_enable(struct dwc2_hsotg *hsotg, u32 fr_list_en) +STATIC void dwc2_per_sched_enable(struct dwc2_hsotg *hsotg, u32 fr_list_en) { u32 hcfg; unsigned long flags; @@ -204,7 +201,7 @@ static void dwc2_per_sched_enable(struct dwc2_hsotg *h spin_unlock_irqrestore(&hsotg->lock, flags); } -static void dwc2_per_sched_disable(struct dwc2_hsotg *hsotg) +STATIC void dwc2_per_sched_disable(struct dwc2_hsotg *hsotg) { u32 hcfg; unsigned long flags; @@ -229,7 +226,7 @@ static void dwc2_per_sched_disable(struct dwc2_hsotg * * Activates/Deactivates FrameList entries for the channel based on endpoint * servicing period */ -static void dwc2_update_frame_list(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh, +STATIC void dwc2_update_frame_list(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh, int enable) { struct dwc2_host_chan *chan; @@ -291,7 +288,7 @@ static void dwc2_update_frame_list(struct dwc2_hsotg * } } -static void dwc2_release_channel_ddma(struct dwc2_hsotg *hsotg, +STATIC void dwc2_release_channel_ddma(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh) { struct dwc2_host_chan *chan = qh->channel; @@ -411,7 +408,7 @@ void dwc2_hcd_qh_free_ddma(struct dwc2_hsotg *hsotg, s } } -static u8 dwc2_frame_to_desc_idx(struct dwc2_qh *qh, u16 frame_idx) +STATIC u8 dwc2_frame_to_desc_idx(struct dwc2_qh *qh, u16 frame_idx) { if (qh->dev_speed == USB_SPEED_HIGH) /* Descriptor set (8 descriptors) index which is 8-aligned */ @@ -424,7 +421,7 @@ static u8 dwc2_frame_to_desc_idx(struct dwc2_qh *qh, u * Determine starting frame for Isochronous transfer. * Few frames skipped to prevent race condition with HC. */ -static u16 dwc2_calc_starting_frame(struct dwc2_hsotg *hsotg, +STATIC u16 dwc2_calc_starting_frame(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh, u16 *skip_frames) { u16 frame; @@ -483,7 +480,7 @@ static u16 dwc2_calc_starting_frame(struct dwc2_hsotg * Calculate initial descriptor index for isochronous transfer based on * scheduled frame */ -static u16 dwc2_recalc_initial_desc_idx(struct dwc2_hsotg *hsotg, +STATIC u16 dwc2_recalc_initial_desc_idx(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh) { u16 frame, fr_idx, fr_idx_tmp, skip_frames; @@ -534,7 +531,7 @@ static u16 dwc2_recalc_initial_desc_idx(struct dwc2_hs #define MAX_ISOC_XFER_SIZE_HS 3072 #define DESCNUM_THRESHOLD 4 -static void dwc2_fill_host_isoc_dma_desc(struct dwc2_hsotg *hsotg, +STATIC void dwc2_fill_host_isoc_dma_desc(struct dwc2_hsotg *hsotg, struct dwc2_qtd *qtd, struct dwc2_qh *qh, u32 max_xfer_size, u16 idx) @@ -572,7 +569,7 @@ static void dwc2_fill_host_isoc_dma_desc(struct dwc2_h BUS_DMASYNC_PREWRITE); } -static void dwc2_init_isoc_dma_desc(struct dwc2_hsotg *hsotg, +STATIC void dwc2_init_isoc_dma_desc(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh, u16 skip_frames) { struct dwc2_qtd *qtd; @@ -680,7 +677,7 @@ static void dwc2_init_isoc_dma_desc(struct dwc2_hsotg #endif } -static void dwc2_fill_host_dma_desc(struct dwc2_hsotg *hsotg, +STATIC void dwc2_fill_host_dma_desc(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan, struct dwc2_qtd *qtd, struct dwc2_qh *qh, int n_desc) @@ -731,7 +728,7 @@ static void dwc2_fill_host_dma_desc(struct dwc2_hsotg } } -static void dwc2_init_non_isoc_dma_desc(struct dwc2_hsotg *hsotg, +STATIC void dwc2_init_non_isoc_dma_desc(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh) { struct dwc2_qtd *qtd; @@ -879,7 +876,7 @@ void dwc2_hcd_start_xfer_ddma(struct dwc2_hsotg *hsotg #define DWC2_CMPL_DONE 1 #define DWC2_CMPL_STOP 2 -static int dwc2_cmpl_host_isoc_dma_desc(struct dwc2_hsotg *hsotg, +STATIC int dwc2_cmpl_host_isoc_dma_desc(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan, struct dwc2_qtd *qtd, struct dwc2_qh *qh, u16 idx) @@ -948,7 +945,7 @@ static int dwc2_cmpl_host_isoc_dma_desc(struct dwc2_hs return rc; } -static void dwc2_complete_isoc_xfer_ddma(struct dwc2_hsotg *hsotg, +STATIC void dwc2_complete_isoc_xfer_ddma(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan, enum dwc2_halt_status halt_status) { @@ -1054,7 +1051,7 @@ stop_scan: qh->td_first = idx; } -static int dwc2_update_non_isoc_urb_state_ddma(struct dwc2_hsotg *hsotg, +STATIC int dwc2_update_non_isoc_urb_state_ddma(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan, struct dwc2_qtd *qtd, struct dwc2_hcd_dma_desc *dma_desc, @@ -1136,7 +1133,7 @@ static int dwc2_update_non_isoc_urb_state_ddma(struct return 0; } -static int dwc2_process_non_isoc_desc(struct dwc2_hsotg *hsotg, +STATIC int dwc2_process_non_isoc_desc(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan, int chnum, struct dwc2_qtd *qtd, int desc_num, @@ -1210,7 +1207,7 @@ static int dwc2_process_non_isoc_desc(struct dwc2_hsot return 0; } -static void dwc2_complete_non_isoc_xfer_ddma(struct dwc2_hsotg *hsotg, +STATIC void dwc2_complete_non_isoc_xfer_ddma(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan, int chnum, enum dwc2_halt_status halt_status) --- dwc2_hcdintr.c Wed Mar 31 07:42:18 2021 +++ /usr/src/sys/dev/usb/dwc2/dwc2_hcdintr.c Wed Jul 14 17:26:57 2021 @@ -1,4 +1,5 @@ -/* $NetBSD: dwc2_hcdintr.c,v 1.15 2018/08/12 09:59:30 skrll Exp $ */ +/* $OpenBSD: dwc2_hcdintr.c,v 1.10 2017/09/08 05:36:53 deraadt Exp $ */ +/* $NetBSD: dwc2_hcdintr.c,v 1.11 2014/11/24 10:14:14 skrll Exp $ */ /* * hcd_intr.c - DesignWare HS OTG Controller host-mode interrupt handling @@ -39,27 +40,24 @@ /* * This file contains the interrupt handlers for Host mode */ -#include -__KERNEL_RCSID(0, "$NetBSD: dwc2_hcdintr.c,v 1.15 2018/08/12 09:59:30 skrll Exp $"); -#include +#include +#include #include +#include + #include #include #include #include -#include +#include +#include -#include +#include +#include -#include -#include - -#include "dwc2_core.h" -#include "dwc2_hcd.h" - /* * If we get this many NAKs on a split transaction we'll slow down * retransmission. A 1 here means delay after the first NAK. @@ -71,7 +69,7 @@ int dwc2_naks_before_delay = DWC2_NAKS_BEFORE_DELAY; int dwc2_out_naks_before_delay = DWC2_OUT_NAKS_BEFORE_DELAY; /* This function is for debug only */ -static void dwc2_track_missed_sofs(struct dwc2_hsotg *hsotg) +STATIC void dwc2_track_missed_sofs(struct dwc2_hsotg *hsotg) { #ifdef CONFIG_USB_DWC2_TRACK_MISSED_SOFS u16 curr_frame_number = hsotg->frame_number; @@ -101,7 +99,7 @@ static void dwc2_track_missed_sofs(struct dwc2_hsotg * #endif } -static void dwc2_hc_handle_tt_clear(struct dwc2_hsotg *hsotg, +STATIC void dwc2_hc_handle_tt_clear(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan, struct dwc2_qtd *qtd) { @@ -129,7 +127,7 @@ static void dwc2_hc_handle_tt_clear(struct dwc2_hsotg * (micro)frame. Periodic transactions may be queued to the controller * for the next (micro)frame. */ -static void dwc2_sof_intr(struct dwc2_hsotg *hsotg) +STATIC void dwc2_sof_intr(struct dwc2_hsotg *hsotg) { struct list_head *qh_entry; struct dwc2_qh *qh; @@ -169,7 +167,7 @@ static void dwc2_sof_intr(struct dwc2_hsotg *hsotg) * at least one packet in the Rx FIFO. The packets are moved from the FIFO to * memory if the DWC_otg controller is operating in Slave mode. */ -static void dwc2_rx_fifo_level_intr(struct dwc2_hsotg *hsotg) +STATIC void dwc2_rx_fifo_level_intr(struct dwc2_hsotg *hsotg) { u32 grxsts, chnum, bcnt, pktsts; struct dwc2_host_chan *chan; @@ -227,7 +225,7 @@ static void dwc2_rx_fifo_level_intr(struct dwc2_hsotg * may be written to the non-periodic request queue for IN transfers. This * interrupt is enabled only in Slave mode. */ -static void dwc2_np_tx_fifo_empty_intr(struct dwc2_hsotg *hsotg) +STATIC void dwc2_np_tx_fifo_empty_intr(struct dwc2_hsotg *hsotg) { dev_vdbg(hsotg->dev, "--Non-Periodic TxFIFO Empty Interrupt--\n"); dwc2_hcd_queue_transactions(hsotg, DWC2_TRANSACTION_NON_PERIODIC); @@ -239,14 +237,14 @@ static void dwc2_np_tx_fifo_empty_intr(struct dwc2_hso * written to the periodic request queue for IN transfers. This interrupt is * enabled only in Slave mode. */ -static void dwc2_perio_tx_fifo_empty_intr(struct dwc2_hsotg *hsotg) +STATIC void dwc2_perio_tx_fifo_empty_intr(struct dwc2_hsotg *hsotg) { if (dbg_perio()) dev_vdbg(hsotg->dev, "--Periodic TxFIFO Empty Interrupt--\n"); dwc2_hcd_queue_transactions(hsotg, DWC2_TRANSACTION_PERIODIC); } -static void dwc2_hprt0_enable(struct dwc2_hsotg *hsotg, u32 hprt0, +STATIC void dwc2_hprt0_enable(struct dwc2_hsotg *hsotg, u32 hprt0, u32 *hprt0_modify) { struct dwc2_core_params *params = hsotg->core_params; @@ -343,7 +341,7 @@ static void dwc2_hprt0_enable(struct dwc2_hsotg *hsotg * determines which interrupt conditions have occurred and handles them * appropriately. */ -static void dwc2_port_intr(struct dwc2_hsotg *hsotg) +STATIC void dwc2_port_intr(struct dwc2_hsotg *hsotg) { u32 hprt0; u32 hprt0_modify; @@ -428,7 +426,7 @@ static void dwc2_port_intr(struct dwc2_hsotg *hsotg) * transferred. short_read may also be NULL on entry, in which case it remains * unchanged. */ -static u32 dwc2_get_actual_xfer_length(struct dwc2_hsotg *hsotg, +STATIC u32 dwc2_get_actual_xfer_length(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan, int chnum, struct dwc2_qtd *qtd, enum dwc2_halt_status halt_status, @@ -476,7 +474,7 @@ static u32 dwc2_get_actual_xfer_length(struct dwc2_hso * Return: 1 if the data transfer specified by the URB is completely finished, * 0 otherwise */ -static int dwc2_update_urb_state(struct dwc2_hsotg *hsotg, +STATIC int dwc2_update_urb_state(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan, int chnum, struct dwc2_hcd_urb *urb, struct dwc2_qtd *qtd) @@ -568,7 +566,7 @@ void dwc2_hcd_save_data_toggle(struct dwc2_hsotg *hsot * Return: DWC2_HC_XFER_COMPLETE if there are more frames remaining to be * transferred in the URB. Otherwise return DWC2_HC_XFER_URB_COMPLETE. */ -static enum dwc2_halt_status dwc2_update_isoc_urb_state( +STATIC enum dwc2_halt_status dwc2_update_isoc_urb_state( struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan, int chnum, struct dwc2_qtd *qtd, enum dwc2_halt_status halt_status) @@ -591,7 +589,7 @@ static enum dwc2_halt_status dwc2_update_isoc_urb_stat if (chan->align_buf && frame_desc->actual_length) { dev_vdbg(hsotg->dev, "%s(): non-aligned buffer\n", __func__); - usb_dma_t *ud = &chan->qh->dw_align_buf_usbdma; + struct usb_dma *ud = &chan->qh->dw_align_buf_usbdma; usb_syncmem(ud, 0, chan->qh->dw_align_buf_size, chan->ep_is_in ? @@ -629,7 +627,7 @@ static enum dwc2_halt_status dwc2_update_isoc_urb_stat if (chan->align_buf && frame_desc->actual_length) { dev_vdbg(hsotg->dev, "%s(): non-aligned buffer\n", __func__); - usb_dma_t *ud = &chan->qh->dw_align_buf_usbdma; + struct usb_dma *ud = &chan->qh->dw_align_buf_usbdma; usb_syncmem(ud, 0, chan->qh->dw_align_buf_size, chan->ep_is_in ? @@ -680,7 +678,7 @@ static enum dwc2_halt_status dwc2_update_isoc_urb_stat * non-periodic schedule. For periodic QHs, removes the QH from the periodic * schedule if no more QTDs are linked to the QH. */ -static void dwc2_deactivate_qh(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh, +STATIC void dwc2_deactivate_qh(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh, int free_qtd) { int continue_split = 0; @@ -728,7 +726,7 @@ no_qtd: * Also attempts to select and queue more transactions since at least one host * channel is available. */ -static void dwc2_release_channel(struct dwc2_hsotg *hsotg, +STATIC void dwc2_release_channel(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan, struct dwc2_qtd *qtd, enum dwc2_halt_status halt_status) @@ -827,7 +825,7 @@ cleanup: * simply released since the core always halts the channel automatically in * DMA mode. */ -static void dwc2_halt_channel(struct dwc2_hsotg *hsotg, +STATIC void dwc2_halt_channel(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan, struct dwc2_qtd *qtd, enum dwc2_halt_status halt_status) { @@ -887,7 +885,7 @@ static void dwc2_halt_channel(struct dwc2_hsotg *hsotg * Complete interrupt. This function should be called after any endpoint type * specific handling is finished to release the host channel. */ -static void dwc2_complete_non_periodic_xfer(struct dwc2_hsotg *hsotg, +STATIC void dwc2_complete_non_periodic_xfer(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan, int chnum, struct dwc2_qtd *qtd, enum dwc2_halt_status halt_status) @@ -937,7 +935,7 @@ static void dwc2_complete_non_periodic_xfer(struct dwc * interrupt. This function should be called after any endpoint type specific * handling is finished to release the host channel. */ -static void dwc2_complete_periodic_xfer(struct dwc2_hsotg *hsotg, +STATIC void dwc2_complete_periodic_xfer(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan, int chnum, struct dwc2_qtd *qtd, enum dwc2_halt_status halt_status) @@ -954,7 +952,7 @@ static void dwc2_complete_periodic_xfer(struct dwc2_hs dwc2_halt_channel(hsotg, chan, qtd, halt_status); } -static int dwc2_xfercomp_isoc_split_in(struct dwc2_hsotg *hsotg, +STATIC int dwc2_xfercomp_isoc_split_in(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan, int chnum, struct dwc2_qtd *qtd) { @@ -1010,7 +1008,7 @@ static int dwc2_xfercomp_isoc_split_in(struct dwc2_hso * Handles a host channel Transfer Complete interrupt. This handler may be * called in either DMA mode or Slave mode. */ -static void dwc2_hc_xfercomp_intr(struct dwc2_hsotg *hsotg, +STATIC void dwc2_hc_xfercomp_intr(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan, int chnum, struct dwc2_qtd *qtd) { @@ -1142,7 +1140,7 @@ handle_xfercomp_done: * Handles a host channel STALL interrupt. This handler may be called in * either DMA mode or Slave mode. */ -static void dwc2_hc_stall_intr(struct dwc2_hsotg *hsotg, +STATIC void dwc2_hc_stall_intr(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan, int chnum, struct dwc2_qtd *qtd) { @@ -1192,7 +1190,7 @@ handle_stall_done: * actual_length field of the URB to reflect the number of bytes that have * actually been transferred via the host channel. */ -static void dwc2_update_urb_state_abn(struct dwc2_hsotg *hsotg, +STATIC void dwc2_update_urb_state_abn(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan, int chnum, struct dwc2_hcd_urb *urb, struct dwc2_qtd *qtd, @@ -1210,7 +1208,7 @@ static void dwc2_update_urb_state_abn(struct dwc2_hsot if (chan->align_buf && xfer_length && chan->ep_is_in) { dev_vdbg(hsotg->dev, "%s(): non-aligned buffer\n", __func__); - usb_dma_t *ud = &chan->qh->dw_align_buf_usbdma; + struct usb_dma *ud = &chan->qh->dw_align_buf_usbdma; usb_syncmem(ud, 0, chan->qh->dw_align_buf_size, chan->ep_is_in ? @@ -1245,7 +1243,7 @@ static void dwc2_update_urb_state_abn(struct dwc2_hsot * Handles a host channel NAK interrupt. This handler may be called in either * DMA mode or Slave mode. */ -static void dwc2_hc_nak_intr(struct dwc2_hsotg *hsotg, +STATIC void dwc2_hc_nak_intr(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan, int chnum, struct dwc2_qtd *qtd) { @@ -1361,7 +1359,7 @@ handle_nak_done: * performing the PING protocol in Slave mode, when errors occur during * either Slave mode or DMA mode, and during Start Split transactions. */ -static void dwc2_hc_ack_intr(struct dwc2_hsotg *hsotg, +STATIC void dwc2_hc_ack_intr(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan, int chnum, struct dwc2_qtd *qtd) { @@ -1440,7 +1438,7 @@ static void dwc2_hc_ack_intr(struct dwc2_hsotg *hsotg, * handled in the xfercomp interrupt handler, not here. This handler may be * called in either DMA mode or Slave mode. */ -static void dwc2_hc_nyet_intr(struct dwc2_hsotg *hsotg, +STATIC void dwc2_hc_nyet_intr(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan, int chnum, struct dwc2_qtd *qtd) { @@ -1523,7 +1521,7 @@ handle_nyet_done: * Handles a host channel babble interrupt. This handler may be called in * either DMA mode or Slave mode. */ -static void dwc2_hc_babble_intr(struct dwc2_hsotg *hsotg, +STATIC void dwc2_hc_babble_intr(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan, int chnum, struct dwc2_qtd *qtd) { @@ -1557,7 +1555,7 @@ disable_int: * Handles a host channel AHB error interrupt. This handler is only called in * DMA mode. */ -static void dwc2_hc_ahberr_intr(struct dwc2_hsotg *hsotg, +STATIC void dwc2_hc_ahberr_intr(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan, int chnum, struct dwc2_qtd *qtd) { @@ -1659,7 +1657,7 @@ handle_ahberr_done: * Handles a host channel transaction error interrupt. This handler may be * called in either DMA mode or Slave mode. */ -static void dwc2_hc_xacterr_intr(struct dwc2_hsotg *hsotg, +STATIC void dwc2_hc_xacterr_intr(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan, int chnum, struct dwc2_qtd *qtd) { @@ -1718,7 +1716,7 @@ handle_xacterr_done: * Handles a host channel frame overrun interrupt. This handler may be called * in either DMA mode or Slave mode. */ -static void dwc2_hc_frmovrun_intr(struct dwc2_hsotg *hsotg, +STATIC void dwc2_hc_frmovrun_intr(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan, int chnum, struct dwc2_qtd *qtd) { @@ -1751,7 +1749,7 @@ static void dwc2_hc_frmovrun_intr(struct dwc2_hsotg *h * Handles a host channel data toggle error interrupt. This handler may be * called in either DMA mode or Slave mode. */ -static void dwc2_hc_datatglerr_intr(struct dwc2_hsotg *hsotg, +STATIC void dwc2_hc_datatglerr_intr(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan, int chnum, struct dwc2_qtd *qtd) { @@ -1776,7 +1774,7 @@ static void dwc2_hc_datatglerr_intr(struct dwc2_hsotg * * Return: true if halt status is ok, false otherwise */ -static bool dwc2_halt_status_ok(struct dwc2_hsotg *hsotg, +STATIC bool dwc2_halt_status_ok(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan, int chnum, struct dwc2_qtd *qtd) { @@ -1836,7 +1834,7 @@ static bool dwc2_halt_status_ok(struct dwc2_hsotg *hso * Handles a host Channel Halted interrupt in DMA mode. This handler * determines the reason the channel halted and proceeds accordingly. */ -static void dwc2_hc_chhltd_intr_dma(struct dwc2_hsotg *hsotg, +STATIC void dwc2_hc_chhltd_intr_dma(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan, int chnum, struct dwc2_qtd *qtd) { @@ -2002,7 +2000,7 @@ error: * processing a transfer on a channel. Other host channel interrupts (except * ahberr) are disabled in DMA mode. */ -static void dwc2_hc_chhltd_intr(struct dwc2_hsotg *hsotg, +STATIC void dwc2_hc_chhltd_intr(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan, int chnum, struct dwc2_qtd *qtd) { @@ -2025,7 +2023,7 @@ static void dwc2_hc_chhltd_intr(struct dwc2_hsotg *hso * If dwc2_hcd_qtd_unlink_and_free() has been called since we grabbed * the qtd from the top of the list, this will return false (otherwise true). */ -static bool dwc2_check_qtd_still_ok(struct dwc2_qtd *qtd, struct dwc2_qh *qh) +STATIC bool dwc2_check_qtd_still_ok(struct dwc2_qtd *qtd, struct dwc2_qh *qh) { struct dwc2_qtd *cur_head; @@ -2038,7 +2036,7 @@ static bool dwc2_check_qtd_still_ok(struct dwc2_qtd *q } /* Handles interrupt for a specific Host Channel */ -static void dwc2_hc_n_intr(struct dwc2_hsotg *hsotg, int chnum) +STATIC void dwc2_hc_n_intr(struct dwc2_hsotg *hsotg, int chnum) { struct dwc2_qtd *qtd; struct dwc2_host_chan *chan; @@ -2181,7 +2179,7 @@ exit: * interrupt. This function determines which conditions have occurred for each * host channel interrupt and handles them appropriately. */ -static void dwc2_hc_intr(struct dwc2_hsotg *hsotg) +STATIC void dwc2_hc_intr(struct dwc2_hsotg *hsotg) { u32 haint; int i; @@ -2210,7 +2208,7 @@ irqreturn_t dwc2_handle_hcd_intr(struct dwc2_hsotg *hs return retval; } - KASSERT(mutex_owned(&hsotg->lock)); + MUTEX_ASSERT_LOCKED(&hsotg->lock); /* Check if HOST Mode */ if (dwc2_is_host_mode(hsotg)) { --- dwc2_hcdqueue.c Wed Mar 31 07:42:18 2021 +++ /usr/src/sys/dev/usb/dwc2/dwc2_hcdqueue.c Wed Jul 14 17:27:11 2021 @@ -1,4 +1,5 @@ -/* $NetBSD: dwc2_hcdqueue.c,v 1.15 2018/08/08 07:20:44 simonb Exp $ */ +/* $OpenBSD: dwc2_hcdqueue.c,v 1.9 2017/09/08 05:36:53 deraadt Exp $ */ +/* $NetBSD: dwc2_hcdqueue.c,v 1.11 2014/09/03 10:00:08 skrll Exp $ */ /* * hcd_queue.c - DesignWare HS OTG Controller host queuing routines @@ -41,31 +42,27 @@ * Transfer Descriptors for Host mode */ -#include -__KERNEL_RCSID(0, "$NetBSD: dwc2_hcdqueue.c,v 1.15 2018/08/08 07:20:44 simonb Exp $"); - -#include -#include +#include +#include +#include #include +#include + #include #include #include #include -#include +#include +#include -#include +#include +#include -#include -#include +STATIC u32 dwc2_calc_bus_time(struct dwc2_hsotg *, int, int, int, int); +STATIC void dwc2_wait_timer_fn(void *); -#include "dwc2_core.h" -#include "dwc2_hcd.h" - -static u32 dwc2_calc_bus_time(struct dwc2_hsotg *, int, int, int, int); -static void dwc2_wait_timer_fn(void *); - /* If we get a NAK, wait this long before retrying */ #define DWC2_RETRY_WAIT_DELAY 1 /* msec */ @@ -78,7 +75,7 @@ static void dwc2_wait_timer_fn(void *); * the QH */ #define SCHEDULE_SLOP 10 -static void dwc2_qh_init(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh, +STATIC void dwc2_qh_init(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh, struct dwc2_hcd_urb *urb) { int dev_speed, hub_addr, hub_port; @@ -88,8 +85,7 @@ static void dwc2_qh_init(struct dwc2_hsotg *hsotg, str /* Initialize QH */ qh->hsotg = hsotg; /* XXX timer_setup(&qh->wait_timer, dwc2_wait_timer_fn, 0); */ - callout_init(&qh->wait_timer, 0); - callout_setfunc(&qh->wait_timer, dwc2_wait_timer_fn, qh); + timeout_set(&qh->wait_timer, dwc2_wait_timer_fn, qh); qh->ep_type = dwc2_hcd_get_pipe_type(&urb->pipe_info); qh->ep_is_in = dwc2_hcd_is_pipe_in(&urb->pipe_info) ? 1 : 0; @@ -228,7 +224,7 @@ struct dwc2_qh *dwc2_hcd_qh_create(struct dwc2_hsotg * return NULL; /* Allocate memory */ - qh = pool_cache_get(sc->sc_qhpool, PR_NOWAIT); + qh = pool_get(&sc->sc_qhpool, PR_NOWAIT); if (!qh) return NULL; @@ -267,8 +263,8 @@ void dwc2_hcd_qh_free(struct dwc2_hsotg *hsotg, struct * memory. */ /* XXX del_timer_sync(&qh->wait_timer); */ - callout_destroy(&qh->wait_timer); /* XXX need to callout_halt() first? */ + timeout_del(&qh->wait_timer); if (qh->desc_list) { dwc2_hcd_qh_free_ddma(hsotg, qh); } else if (qh->dw_align_buf) { @@ -276,7 +272,7 @@ void dwc2_hcd_qh_free(struct dwc2_hsotg *hsotg, struct qh->dw_align_buf_dma = (dma_addr_t)0; } - pool_cache_put(sc->sc_qhpool, qh); + pool_put(&sc->sc_qhpool, qh); } /** @@ -287,7 +283,7 @@ void dwc2_hcd_qh_free(struct dwc2_hsotg *hsotg, struct * * Return: 0 if successful, negative error code otherwise */ -static int dwc2_periodic_channel_available(struct dwc2_hsotg *hsotg) +STATIC int dwc2_periodic_channel_available(struct dwc2_hsotg *hsotg) { /* * Currently assuming that there is a dedicated host channel for @@ -325,7 +321,7 @@ static int dwc2_periodic_channel_available(struct dwc2 * For simplicity, this calculation assumes that all the transfers in the * periodic schedule may occur in the same (micro)frame */ -static int dwc2_check_periodic_bandwidth(struct dwc2_hsotg *hsotg, +STATIC int dwc2_check_periodic_bandwidth(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh) { int status; @@ -363,7 +359,7 @@ static int dwc2_check_periodic_bandwidth(struct dwc2_h * keep each qh use in qh->frame_usecs * when surrendering the qh then donate the time back */ -static const unsigned short max_uframe_usecs[] = { +STATIC const unsigned short max_uframe_usecs[] = { 100, 100, 100, 100, 100, 100, 30, 0 }; @@ -375,7 +371,7 @@ void dwc2_hcd_init_usecs(struct dwc2_hsotg *hsotg) hsotg->frame_usecs[i] = max_uframe_usecs[i]; } -static int dwc2_find_single_uframe(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh) +STATIC int dwc2_find_single_uframe(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh) { unsigned short utime = qh->usecs; int i; @@ -394,7 +390,7 @@ static int dwc2_find_single_uframe(struct dwc2_hsotg * /* * use this for FS apps that can span multiple uframes */ -static int dwc2_find_multi_uframe(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh) +STATIC int dwc2_find_multi_uframe(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh) { unsigned short utime = qh->usecs; unsigned short xtime; @@ -450,7 +446,7 @@ static int dwc2_find_multi_uframe(struct dwc2_hsotg *h return -ENOSPC; } -static int dwc2_find_uframe(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh) +STATIC int dwc2_find_uframe(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh) { int ret; @@ -477,7 +473,7 @@ static int dwc2_find_uframe(struct dwc2_hsotg *hsotg, * * Return: 0 if successful, negative error code otherwise */ -static int dwc2_check_max_xfer_size(struct dwc2_hsotg *hsotg, +STATIC int dwc2_check_max_xfer_size(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh) { u32 max_xfer_size; @@ -507,7 +503,7 @@ static int dwc2_check_max_xfer_size(struct dwc2_hsotg * * Return: 0 if successful, negative error code otherwise */ -static int dwc2_schedule_periodic(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh) +STATIC int dwc2_schedule_periodic(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh) { int status; @@ -580,7 +576,7 @@ static int dwc2_schedule_periodic(struct dwc2_hsotg *h * @hsotg: The HCD state structure for the DWC OTG controller * @qh: QH for the periodic transfer */ -static void dwc2_deschedule_periodic(struct dwc2_hsotg *hsotg, +STATIC void dwc2_deschedule_periodic(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh) { int i; @@ -622,7 +618,7 @@ static void dwc2_deschedule_periodic(struct dwc2_hsotg * * @t: Pointer to wait_timer in a qh. */ -static void dwc2_wait_timer_fn(void *arg) +STATIC void dwc2_wait_timer_fn(void *arg) { struct dwc2_qh *qh = arg; struct dwc2_hsotg *hsotg = qh->hsotg; @@ -688,8 +684,8 @@ int dwc2_hcd_qh_add(struct dwc2_hsotg *hsotg, struct d qh->wait_timer_cancel = false; /* XXX mod_timer(&qh->wait_timer, jiffies + DWC2_RETRY_WAIT_DELAY + 1); */ - callout_schedule(&qh->wait_timer, - mstohz(DWC2_RETRY_WAIT_DELAY)); + timeout_add_msec(&qh->wait_timer, + DWC2_RETRY_WAIT_DELAY); } else { list_add_tail(&qh->qh_list_entry, &hsotg->non_periodic_sched_inactive); @@ -750,7 +746,7 @@ void dwc2_hcd_qh_unlink(struct dwc2_hsotg *hsotg, stru /* * Schedule the next continuing periodic split transfer */ -static void dwc2_sched_periodic_split(struct dwc2_hsotg *hsotg, +STATIC void dwc2_sched_periodic_split(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh, u16 frame_number, int sched_next_periodic_split) { @@ -887,10 +883,10 @@ int dwc2_hcd_qtd_add(struct dwc2_hsotg *hsotg, struct struct dwc2_qh *qh) { - KASSERT(mutex_owned(&hsotg->lock)); + MUTEX_ASSERT_LOCKED(&hsotg->lock); int retval; - if (unlikely(!qh)) { + if (!qh) { dev_err(hsotg->dev, "%s: Invalid QH\n", __func__); retval = -EINVAL; goto fail; @@ -915,7 +911,7 @@ void dwc2_hcd_qtd_unlink_and_free(struct dwc2_hsotg *h struct dwc2_softc *sc = hsotg->hsotg_sc; list_del_init(&qtd->qtd_list_entry); - pool_cache_put(sc->sc_qtdpool, qtd); + pool_put(&sc->sc_qtdpool, qtd); } #define BITSTUFFTIME(bytecount) ((8 * 7 * (bytecount)) / 6) @@ -923,7 +919,7 @@ void dwc2_hcd_qtd_unlink_and_free(struct dwc2_hsotg *h #define FS_LS_HOST_DELAY 1000 /* nanoseconds */ #define HUB_LS_SETUP 333 /* nanoseconds */ -static u32 dwc2_calc_bus_time(struct dwc2_hsotg *hsotg, int speed, int is_in, +STATIC u32 dwc2_calc_bus_time(struct dwc2_hsotg *hsotg, int speed, int is_in, int is_isoc, int bytecount) { unsigned long retval; --- dwc2_hw.h Wed Mar 31 07:42:18 2021 +++ /usr/src/sys/dev/usb/dwc2/dwc2_hw.h Wed Jul 14 13:32:06 2021 @@ -1,4 +1,5 @@ -/* $NetBSD: dwc2_hw.h,v 1.4 2016/02/14 10:53:30 skrll Exp $ */ +/* $OpenBSD: dwc2_hw.h,v 1.2 2015/02/10 12:58:47 uebayasi Exp $ */ +/* $NetBSD: dwc2_hw.h,v 1.2 2013/09/25 06:19:22 skrll Exp $ */ /* * hw.h - DesignWare HS OTG Controller hardware definitions --- dwc2var.h Wed Mar 31 07:42:17 2021 +++ /usr/src/sys/dev/usb/dwc2/dwc2var.h Wed Jul 14 17:31:05 2021 @@ -1,4 +1,5 @@ -/* $NetBSD: dwc2var.h,v 1.7 2020/02/12 16:01:00 riastradh Exp $ */ +/* $OpenBSD: dwc2var.h,v 1.19 2017/09/05 14:01:03 otto Exp $ */ +/* $NetBSD: dwc2var.h,v 1.3 2013/10/22 12:57:40 skrll Exp $ */ /*- * Copyright (c) 2013 The NetBSD Foundation, Inc. @@ -33,6 +34,7 @@ #define _DWC2VAR_H_ #include +#include struct dwc2_hsotg; struct dwc2_qtd; @@ -44,6 +46,9 @@ struct dwc2_xfer { TAILQ_ENTRY(dwc2_xfer) xnext; /* list of complete xfers */ usbd_status intr_status; + u_int32_t flags; +#define DWC2_XFER_ABORTING 0x0001 /* xfer is aborting. */ +#define DWC2_XFER_ABORTWAIT 0x0002 /* abort completion is being awaited. */ }; struct dwc2_pipe { @@ -53,65 +58,62 @@ struct dwc2_pipe { void *priv; /* QH */ /* DMA buffer for control endpoint requests */ - usb_dma_t req_dma; + struct usb_dma req_dma; }; -#define DWC2_BUS2SC(bus) ((bus)->ub_hcpriv) -#define DWC2_PIPE2SC(pipe) DWC2_BUS2SC((pipe)->up_dev->ud_bus) -#define DWC2_XFER2SC(xfer) DWC2_BUS2SC((xfer)->ux_bus) -#define DWC2_DPIPE2SC(d) DWC2_BUS2SC((d)->pipe.up_dev->ud_bus) +#define DWC2_BUS2SC(bus) ((void *)(bus)) +#define DWC2_PIPE2SC(pipe) DWC2_BUS2SC((pipe)->device->bus) +#define DWC2_XFER2SC(xfer) DWC2_PIPE2SC((xfer)->pipe) +#define DWC2_DPIPE2SC(d) DWC2_BUS2SC((d)->pipe.device->bus) #define DWC2_XFER2DXFER(x) (struct dwc2_xfer *)(x) -#define DWC2_XFER2DPIPE(x) (struct dwc2_pipe *)(x)->ux_pipe; +#define DWC2_XFER2DPIPE(x) (struct dwc2_pipe *)(x)->pipe; #define DWC2_PIPE2DPIPE(p) (struct dwc2_pipe *)(p) typedef struct dwc2_softc { - device_t sc_dev; + struct usbd_bus sc_bus; bus_space_tag_t sc_iot; bus_space_handle_t sc_ioh; - bus_dma_tag_t sc_dmat; struct dwc2_core_params *sc_params; - int (*sc_set_dma_addr)(device_t, bus_addr_t, int); + int (*sc_set_dma_addr)(struct device *, bus_addr_t, int); /* * Private */ - struct usbd_bus sc_bus; struct dwc2_hsotg *sc_hsotg; - kmutex_t sc_lock; + struct mutex sc_lock; bool sc_hcdenabled; void *sc_rhc_si; struct usbd_xfer *sc_intrxfer; - device_t sc_child; /* /dev/usb# device */ - char sc_dying; + struct device *sc_child; /* /dev/usb# device */ + char sc_vendor[32]; /* vendor string for root hub */ + TAILQ_HEAD(, dwc2_xfer) sc_complete; /* complete transfers */ - pool_cache_t sc_xferpool; - pool_cache_t sc_qhpool; - pool_cache_t sc_qtdpool; + struct pool sc_xferpool; + struct pool sc_qhpool; + struct pool sc_qtdpool; + uint8_t sc_addr; /* device address */ + uint8_t sc_conf; /* device configuration */ + } dwc2_softc_t; int dwc2_init(struct dwc2_softc *); int dwc2_intr(void *); int dwc2_detach(dwc2_softc_t *, int); -bool dwc2_shutdown(device_t, int); -void dwc2_childdet(device_t, device_t); -int dwc2_activate(device_t, enum devact); -bool dwc2_resume(device_t, const pmf_qual_t *); -bool dwc2_suspend(device_t, const pmf_qual_t *); -void dwc2_worker(struct work *, void *); +void dwc2_worker(struct task *, void *); void dwc2_host_complete(struct dwc2_hsotg *, struct dwc2_qtd *, int); @@ -120,7 +122,21 @@ static inline void dwc2_root_intr(dwc2_softc_t *sc) { - softint_schedule(sc->sc_rhc_si); + softintr_schedule(sc->sc_rhc_si); } + +/* + * XXX Compat + */ +#define DWC2_MAXISOCPACKETS 16 /* XXX: Fix nframes handling */ +#define ENOSR 90 +#define device_xname(d) ((d)->dv_xname) +#define jiffies hardclock_ticks +#define mstohz(ms) \ + (__predict_false((ms) >= 0x20000) ? \ + ((ms +0u) / 1000u) * hz : \ + ((ms +0u) * hz) / 1000u) +#define msecs_to_jiffies mstohz +#define IS_ENABLED(option) (option) #endif /* _DWC_OTGVAR_H_ */