diff --git a/sys/dev/sound/usb/uaudio.c b/sys/dev/sound/usb/uaudio.c --- a/sys/dev/sound/usb/uaudio.c +++ b/sys/dev/sound/usb/uaudio.c @@ -207,11 +207,6 @@ struct uaudio_mixer_node *next; }; -struct uaudio_configure_msg { - struct usb_proc_msg hdr; - struct uaudio_softc *sc; -}; - #define CHAN_MAX_ALT 24 struct uaudio_chan_alt { @@ -373,7 +368,7 @@ struct uaudio_hid sc_hid; struct uaudio_search_result sc_mixer_clocks; struct uaudio_mixer_node sc_mixer_node; - struct uaudio_configure_msg sc_config_msg[2]; + struct usb_proc_msg sc_config_msg; struct uaudio_softc_child sc_child[UAUDIO_MAX_CHILD]; struct usb_device *sc_udev; @@ -981,10 +976,7 @@ sc->sc_udev = uaa->device; sc->sc_mixer_iface_index = uaa->info.bIfaceIndex; sc->sc_mixer_iface_no = uaa->info.bIfaceNum; - sc->sc_config_msg[0].hdr.pm_callback = &uaudio_configure_msg; - sc->sc_config_msg[0].sc = sc; - sc->sc_config_msg[1].hdr.pm_callback = &uaudio_configure_msg; - sc->sc_config_msg[1].sc = sc; + USB_PROC_MSG_INIT(&sc->sc_config_msg, 0, uaudio_configure_msg, sc); if (usb_test_quirk(uaa, UQ_AUDIO_SWAP_LR)) sc->sc_uq_audio_swap_lr = 1; @@ -1274,9 +1266,8 @@ sc->sc_play_chan[i].operation = CHAN_OP_DRAIN; sc->sc_rec_chan[i].operation = CHAN_OP_DRAIN; } - usb_proc_explore_mwait(sc->sc_udev, - &sc->sc_config_msg[0], &sc->sc_config_msg[1]); usb_proc_explore_unlock(sc->sc_udev); + usb_proc_explore_mwait(sc->sc_udev, &sc->sc_config_msg); for (i = 0; i != UAUDIO_MAX_CHILD; i++) { usbd_transfer_unsetup(sc->sc_play_chan[i].xfer, UAUDIO_NCHANBUFS + 1); @@ -1545,17 +1536,15 @@ } static void -uaudio_configure_msg(struct usb_proc_msg *pm) +uaudio_configure_msg(void *ctx) { - struct uaudio_softc *sc = ((struct uaudio_configure_msg *)pm)->sc; + struct uaudio_softc *sc = ctx; unsigned i; - usb_proc_explore_unlock(sc->sc_udev); for (i = 0; i != UAUDIO_MAX_CHILD; i++) { uaudio_configure_msg_sub(sc, &sc->sc_play_chan[i], PCMDIR_PLAY); uaudio_configure_msg_sub(sc, &sc->sc_rec_chan[i], PCMDIR_REC); } - usb_proc_explore_lock(sc->sc_udev); } /*========================================================================* @@ -2834,8 +2823,7 @@ * configuration, this part must be executed from the USB * explore process. */ - (void)usb_proc_explore_msignal(sc->sc_udev, - &sc->sc_config_msg[0], &sc->sc_config_msg[1]); + (void)usb_proc_explore_msignal(sc->sc_udev, &sc->sc_config_msg); } static int diff --git a/sys/dev/usb/controller/usb_controller.c b/sys/dev/usb/controller/usb_controller.c --- a/sys/dev/usb/controller/usb_controller.c +++ b/sys/dev/usb/controller/usb_controller.c @@ -208,22 +208,16 @@ usb_root_mount_rel(bus); #endif - USB_BUS_LOCK(bus); - /* Queue detach job */ - usb_proc_msignal(USB_BUS_EXPLORE_PROC(bus), - &bus->detach_msg[0], &bus->detach_msg[1]); + usb_proc_msignal(USB_BUS_EXPLORE_PROC(bus), &bus->detach_msg); /* Wait for detach to complete */ - usb_proc_mwait(USB_BUS_EXPLORE_PROC(bus), - &bus->detach_msg[0], &bus->detach_msg[1]); + usb_proc_mwait(USB_BUS_EXPLORE_PROC(bus), &bus->detach_msg); #if USB_HAVE_UGEN /* Wait for cleanup to complete */ - usb_proc_mwait(USB_BUS_EXPLORE_PROC(bus), - &bus->cleanup_msg[0], &bus->cleanup_msg[1]); + usb_proc_mwait(USB_BUS_EXPLORE_PROC(bus), &bus->cleanup_msg); #endif - USB_BUS_UNLOCK(bus); #if USB_HAVE_PER_BUS_PROCESS /* Get rid of USB callback processes */ @@ -262,15 +256,11 @@ return (0); } - USB_BUS_LOCK(bus); - usb_proc_msignal(USB_BUS_EXPLORE_PROC(bus), - &bus->suspend_msg[0], &bus->suspend_msg[1]); + usb_proc_msignal(USB_BUS_EXPLORE_PROC(bus), &bus->suspend_msg); if (usb_no_suspend_wait == 0) { /* wait for suspend callback to be executed */ - usb_proc_mwait(USB_BUS_EXPLORE_PROC(bus), - &bus->suspend_msg[0], &bus->suspend_msg[1]); + usb_proc_mwait(USB_BUS_EXPLORE_PROC(bus), &bus->suspend_msg); } - USB_BUS_UNLOCK(bus); return (0); } @@ -290,10 +280,7 @@ return (0); } - USB_BUS_LOCK(bus); - usb_proc_msignal(USB_BUS_EXPLORE_PROC(bus), - &bus->resume_msg[0], &bus->resume_msg[1]); - USB_BUS_UNLOCK(bus); + usb_proc_msignal(USB_BUS_EXPLORE_PROC(bus), &bus->resume_msg); return (0); } @@ -308,16 +295,13 @@ DPRINTF("\n"); - if (bus->reset_msg[0].hdr.pm_qentry.tqe_prev != NULL || - bus->reset_msg[1].hdr.pm_qentry.tqe_prev != NULL) { + if (usb_proc_msignal_pending(USB_BUS_EXPLORE_PROC(bus), + &bus->reset_msg)) { DPRINTF("Reset already pending\n"); return; } device_printf(bus->parent, "Resetting controller\n"); - - usb_proc_msignal(USB_BUS_EXPLORE_PROC(bus), - &bus->reset_msg[0], &bus->reset_msg[1]); } /*------------------------------------------------------------------------* @@ -337,15 +321,11 @@ DPRINTF("%s: Controller shutdown\n", device_get_nameunit(bus->bdev)); - USB_BUS_LOCK(bus); - usb_proc_msignal(USB_BUS_EXPLORE_PROC(bus), - &bus->shutdown_msg[0], &bus->shutdown_msg[1]); + usb_proc_msignal(USB_BUS_EXPLORE_PROC(bus), &bus->shutdown_msg); if (usb_no_shutdown_wait == 0) { /* wait for shutdown callback to be executed */ - usb_proc_mwait(USB_BUS_EXPLORE_PROC(bus), - &bus->shutdown_msg[0], &bus->shutdown_msg[1]); + usb_proc_mwait(USB_BUS_EXPLORE_PROC(bus), &bus->shutdown_msg); } - USB_BUS_UNLOCK(bus); DPRINTF("%s: Controller shutdown complete\n", device_get_nameunit(bus->bdev)); @@ -359,17 +339,19 @@ * This function is used to explore the device tree from the root. *------------------------------------------------------------------------*/ static void -usb_bus_explore(struct usb_proc_msg *pm) +usb_bus_explore(void *ctx) { struct usb_bus *bus; struct usb_device *udev; - bus = ((struct usb_bus_msg *)pm)->bus; + bus = ctx; + USB_BUS_LOCK(bus); udev = bus->devices[USB_ROOT_HUB_ADDR]; - if (bus->no_explore != 0) + if (bus->no_explore != 0) { + USB_BUS_UNLOCK(bus); return; - + } if (udev != NULL) { USB_BUS_UNLOCK(bus); uhub_explore_handle_re_enumerate(udev); @@ -415,6 +397,7 @@ /* Nice the enumeration a bit, to avoid looping too fast. */ usb_pause_mtx(&bus->bus_mtx, USB_MS_TO_TICKS(usb_enum_nice_time)); + USB_BUS_UNLOCK(bus); } /*------------------------------------------------------------------------* @@ -423,13 +406,14 @@ * This function is used to detach the device tree from the root. *------------------------------------------------------------------------*/ static void -usb_bus_detach(struct usb_proc_msg *pm) +usb_bus_detach(void *ctx) { struct usb_bus *bus; struct usb_device *udev; device_t dev; - bus = ((struct usb_bus_msg *)pm)->bus; + bus = ctx; + USB_BUS_LOCK(bus); udev = bus->devices[USB_ROOT_HUB_ADDR]; dev = bus->bdev; /* clear the softc */ @@ -449,6 +433,7 @@ USB_BUS_LOCK(bus); /* clear bdev variable last */ bus->bdev = NULL; + USB_BUS_UNLOCK(bus); } /*------------------------------------------------------------------------* @@ -457,7 +442,7 @@ * This function is used to suspend the USB controller. *------------------------------------------------------------------------*/ static void -usb_bus_suspend(struct usb_proc_msg *pm) +usb_bus_suspend(void *ctx) { struct usb_bus *bus; struct usb_device *udev; @@ -466,25 +451,16 @@ DPRINTF("\n"); - bus = ((struct usb_bus_msg *)pm)->bus; + bus = ctx; + USB_BUS_LOCK(bus); udev = bus->devices[USB_ROOT_HUB_ADDR]; - if (udev == NULL || bus->bdev == NULL) + if (udev == NULL || bus->bdev == NULL) { + USB_BUS_UNLOCK(bus); return; - + } USB_BUS_UNLOCK(bus); - /* - * We use the shutdown event here because the suspend and - * resume events are reserved for the USB port suspend and - * resume. The USB system suspend is implemented like full - * shutdown and all connected USB devices will be disconnected - * subsequently. At resume all USB devices will be - * re-connected again. - */ - - bus_generic_shutdown(bus->bdev); - do_unlock = usbd_enum_lock(udev); err = usbd_set_config_index(udev, USB_UNCONFIG_INDEX); @@ -504,8 +480,6 @@ if (do_unlock) usbd_enum_unlock(udev); - - USB_BUS_LOCK(bus); } /*------------------------------------------------------------------------* @@ -514,7 +488,7 @@ * This function is used to resume the USB controller. *------------------------------------------------------------------------*/ static void -usb_bus_resume(struct usb_proc_msg *pm) +usb_bus_resume(void *ctx) { struct usb_bus *bus; struct usb_device *udev; @@ -523,12 +497,14 @@ DPRINTF("\n"); - bus = ((struct usb_bus_msg *)pm)->bus; + bus = ctx; + USB_BUS_LOCK(bus); udev = bus->devices[USB_ROOT_HUB_ADDR]; - if (udev == NULL || bus->bdev == NULL) + if (udev == NULL || bus->bdev == NULL) { + USB_BUS_UNLOCK(bus); return; - + } USB_BUS_UNLOCK(bus); do_unlock = usbd_enum_lock(udev); @@ -567,8 +543,6 @@ if (do_unlock) usbd_enum_unlock(udev); - - USB_BUS_LOCK(bus); } /*------------------------------------------------------------------------* @@ -577,20 +551,23 @@ * This function is used to reset the USB controller. *------------------------------------------------------------------------*/ static void -usb_bus_reset(struct usb_proc_msg *pm) +usb_bus_reset(void *ctx) { struct usb_bus *bus; DPRINTF("\n"); - bus = ((struct usb_bus_msg *)pm)->bus; - - if (bus->bdev == NULL || bus->no_explore != 0) + bus = ctx; + USB_BUS_LOCK(bus); + if (bus->bdev == NULL || bus->no_explore != 0) { + USB_BUS_UNLOCK(bus); return; + } /* a suspend and resume will reset the USB controller */ - usb_bus_suspend(pm); - usb_bus_resume(pm); + usb_bus_suspend(ctx); + usb_bus_resume(ctx); + USB_BUS_UNLOCK(bus); } /*------------------------------------------------------------------------* @@ -599,19 +576,21 @@ * This function is used to shutdown the USB controller. *------------------------------------------------------------------------*/ static void -usb_bus_shutdown(struct usb_proc_msg *pm) +usb_bus_shutdown(void *ctx) { struct usb_bus *bus; struct usb_device *udev; usb_error_t err; uint8_t do_unlock; - bus = ((struct usb_bus_msg *)pm)->bus; + bus = ctx; + USB_BUS_LOCK(bus); udev = bus->devices[USB_ROOT_HUB_ADDR]; - if (udev == NULL || bus->bdev == NULL) + if (udev == NULL || bus->bdev == NULL) { + USB_BUS_UNLOCK(bus); return; - + } USB_BUS_UNLOCK(bus); bus_generic_shutdown(bus->bdev); @@ -635,8 +614,6 @@ if (do_unlock) usbd_enum_unlock(udev); - - USB_BUS_LOCK(bus); } /*------------------------------------------------------------------------* @@ -646,13 +623,14 @@ *------------------------------------------------------------------------*/ #if USB_HAVE_UGEN static void -usb_bus_cleanup(struct usb_proc_msg *pm) +usb_bus_cleanup(void *ctx) { struct usb_bus *bus; struct usb_fs_privdata *pd; - bus = ((struct usb_bus_msg *)pm)->bus; + bus = ctx; + USB_BUS_LOCK(bus); while ((pd = SLIST_FIRST(&bus->pd_cleanup_list)) != NULL) { SLIST_REMOVE(&bus->pd_cleanup_list, pd, usb_fs_privdata, pd_next); USB_BUS_UNLOCK(bus); @@ -661,6 +639,7 @@ USB_BUS_LOCK(bus); } + USB_BUS_UNLOCK(bus); } #endif @@ -697,7 +676,7 @@ * This function attaches USB in context of the explore thread. *------------------------------------------------------------------------*/ static void -usb_bus_attach(struct usb_proc_msg *pm) +usb_bus_attach(void *ctx) { struct usb_bus *bus; struct usb_device *child; @@ -705,7 +684,8 @@ usb_error_t err; enum usb_dev_speed speed; - bus = ((struct usb_bus_msg *)pm)->bus; + bus = ctx; + USB_BUS_LOCK(bus); dev = bus->bdev; DPRINTF("\n"); @@ -741,6 +721,7 @@ #if USB_HAVE_ROOT_MOUNT_HOLD usb_root_mount_rel(bus); #endif + USB_BUS_UNLOCK(bus); return; } @@ -792,6 +773,7 @@ /* start watchdog */ usb_power_wdog(bus); + USB_BUS_UNLOCK(bus); } /*------------------------------------------------------------------------* @@ -811,47 +793,17 @@ usbpf_attach(bus); #endif /* Initialise USB process messages */ - bus->explore_msg[0].hdr.pm_callback = &usb_bus_explore; - bus->explore_msg[0].bus = bus; - bus->explore_msg[1].hdr.pm_callback = &usb_bus_explore; - bus->explore_msg[1].bus = bus; - - bus->detach_msg[0].hdr.pm_callback = &usb_bus_detach; - bus->detach_msg[0].bus = bus; - bus->detach_msg[1].hdr.pm_callback = &usb_bus_detach; - bus->detach_msg[1].bus = bus; - - bus->attach_msg[0].hdr.pm_callback = &usb_bus_attach; - bus->attach_msg[0].bus = bus; - bus->attach_msg[1].hdr.pm_callback = &usb_bus_attach; - bus->attach_msg[1].bus = bus; - - bus->suspend_msg[0].hdr.pm_callback = &usb_bus_suspend; - bus->suspend_msg[0].bus = bus; - bus->suspend_msg[1].hdr.pm_callback = &usb_bus_suspend; - bus->suspend_msg[1].bus = bus; - - bus->resume_msg[0].hdr.pm_callback = &usb_bus_resume; - bus->resume_msg[0].bus = bus; - bus->resume_msg[1].hdr.pm_callback = &usb_bus_resume; - bus->resume_msg[1].bus = bus; - - bus->reset_msg[0].hdr.pm_callback = &usb_bus_reset; - bus->reset_msg[0].bus = bus; - bus->reset_msg[1].hdr.pm_callback = &usb_bus_reset; - bus->reset_msg[1].bus = bus; - - bus->shutdown_msg[0].hdr.pm_callback = &usb_bus_shutdown; - bus->shutdown_msg[0].bus = bus; - bus->shutdown_msg[1].hdr.pm_callback = &usb_bus_shutdown; - bus->shutdown_msg[1].bus = bus; + USB_PROC_MSG_INIT(&bus->explore_msg, 0, usb_bus_explore, bus); + USB_PROC_MSG_INIT(&bus->detach_msg, 0, usb_bus_detach, bus); + USB_PROC_MSG_INIT(&bus->attach_msg, 0, usb_bus_attach, bus); + USB_PROC_MSG_INIT(&bus->suspend_msg, 0, usb_bus_suspend, bus); + USB_PROC_MSG_INIT(&bus->resume_msg, 0, usb_bus_resume, bus); + USB_PROC_MSG_INIT(&bus->reset_msg, 0, usb_bus_reset, bus); + USB_PROC_MSG_INIT(&bus->shutdown_msg, 0, usb_bus_shutdown, bus); #if USB_HAVE_UGEN SLIST_INIT(&bus->pd_cleanup_list); - bus->cleanup_msg[0].hdr.pm_callback = &usb_bus_cleanup; - bus->cleanup_msg[0].bus = bus; - bus->cleanup_msg[1].hdr.pm_callback = &usb_bus_cleanup; - bus->cleanup_msg[1].bus = bus; + USB_PROC_MSG_INIT(&bus->cleanup_msg, 0, usb_bus_cleanup, bus); #endif #if USB_HAVE_PER_BUS_PROCESS @@ -881,10 +833,7 @@ #endif { /* Get final attach going */ - USB_BUS_LOCK(bus); - usb_proc_msignal(USB_BUS_EXPLORE_PROC(bus), - &bus->attach_msg[0], &bus->attach_msg[1]); - USB_BUS_UNLOCK(bus); + usb_proc_msignal(USB_BUS_EXPLORE_PROC(bus), &bus->attach_msg); /* Do initial explore */ usb_needs_explore(bus, 1); @@ -1011,15 +960,15 @@ /* convenience wrappers */ void -usb_proc_explore_mwait(struct usb_device *udev, void *pm1, void *pm2) +usb_proc_explore_mwait(struct usb_device *udev, struct usb_proc_msg *msg) { - usb_proc_mwait(USB_BUS_EXPLORE_PROC(udev->bus), pm1, pm2); + usb_proc_mwait(USB_BUS_EXPLORE_PROC(udev->bus), msg); } -void * -usb_proc_explore_msignal(struct usb_device *udev, void *pm1, void *pm2) +void +usb_proc_explore_msignal(struct usb_device *udev, struct usb_proc_msg *msg) { - return (usb_proc_msignal(USB_BUS_EXPLORE_PROC(udev->bus), pm1, pm2)); + return (usb_proc_msignal(USB_BUS_EXPLORE_PROC(udev->bus), msg)); } void diff --git a/sys/dev/usb/controller/xhci.h b/sys/dev/usb/controller/xhci.h --- a/sys/dev/usb/controller/xhci.h +++ b/sys/dev/usb/controller/xhci.h @@ -496,7 +496,7 @@ /* base device */ struct usb_bus sc_bus; /* configure message */ - struct usb_bus_msg sc_config_msg[2]; + struct usb_proc_msg sc_config_msg; struct usb_callout sc_callout; diff --git a/sys/dev/usb/controller/xhci.c b/sys/dev/usb/controller/xhci.c --- a/sys/dev/usb/controller/xhci.c +++ b/sys/dev/usb/controller/xhci.c @@ -633,10 +633,8 @@ cv_init(&sc->sc_cmd_cv, "CMDQ"); sx_init(&sc->sc_cmd_sx, "CMDQ lock"); - sc->sc_config_msg[0].hdr.pm_callback = &xhci_configure_msg; - sc->sc_config_msg[0].bus = &sc->sc_bus; - sc->sc_config_msg[1].hdr.pm_callback = &xhci_configure_msg; - sc->sc_config_msg[1].bus = &sc->sc_bus; + USB_PROC_MSG_INIT(&sc->sc_config_msg, 0, xhci_configure_msg, + &sc->sc_bus); return (0); } @@ -2977,8 +2975,8 @@ DPRINTFN(8, "Not running\n"); /* start configuration */ - (void)usb_proc_msignal(USB_BUS_CONTROL_XFER_PROC(&sc->sc_bus), - &sc->sc_config_msg[0], &sc->sc_config_msg[1]); + usb_proc_msignal(USB_BUS_CONTROL_XFER_PROC(&sc->sc_bus), + &sc->sc_config_msg); return (0); } @@ -3993,18 +3991,19 @@ usbd_transfer_enqueue(&sc->sc_bus.intr_q, xfer); (void)usb_proc_msignal(USB_BUS_CONTROL_XFER_PROC(&sc->sc_bus), - &sc->sc_config_msg[0], &sc->sc_config_msg[1]); + &sc->sc_config_msg); } static void -xhci_configure_msg(struct usb_proc_msg *pm) +xhci_configure_msg(void *ctx) { struct xhci_softc *sc; struct xhci_endpoint_ext *pepext; struct usb_xfer *xfer; - sc = XHCI_BUS2SC(((struct usb_bus_msg *)pm)->bus); + sc = XHCI_BUS2SC(ctx); + USB_BUS_LOCK(&sc->sc_bus); restart: TAILQ_FOREACH(xfer, &sc->sc_bus.intr_q.head, wait_entry) { pepext = xhci_get_endpoint_ext(xfer->xroot->udev, @@ -4074,6 +4073,7 @@ xhci_device_generic_multi_enter(xfer->endpoint, xfer->stream_id, NULL); } + USB_BUS_UNLOCK(&sc->sc_bus); } static void diff --git a/sys/dev/usb/misc/ugold.c b/sys/dev/usb/misc/ugold.c --- a/sys/dev/usb/misc/ugold.c +++ b/sys/dev/usb/misc/ugold.c @@ -87,19 +87,13 @@ #endif -struct ugold_softc; -struct ugold_readout_msg { - struct usb_proc_msg hdr; - struct ugold_softc *sc; -}; - struct ugold_softc { struct usb_device *sc_udev; struct usb_xfer *sc_xfer[UGOLD_N_TRANSFER]; struct callout sc_callout; struct mtx sc_mtx; - struct ugold_readout_msg sc_readout_msg[2]; + struct usb_proc_msg sc_readout_msg; int sc_num_sensors; int sc_sensor[UGOLD_MAX_SENSORS]; @@ -160,10 +154,7 @@ { struct ugold_softc *sc = arg; - usb_proc_explore_lock(sc->sc_udev); - (void)usb_proc_explore_msignal(sc->sc_udev, - &sc->sc_readout_msg[0], &sc->sc_readout_msg[1]); - usb_proc_explore_unlock(sc->sc_udev); + usb_proc_explore_msignal(sc->sc_udev, &sc->sc_readout_msg); callout_reset(&sc->sc_callout, 6 * hz, &ugold_timeout, sc); } @@ -196,10 +187,7 @@ int i; sc->sc_udev = uaa->device; - sc->sc_readout_msg[0].hdr.pm_callback = &ugold_readout_msg; - sc->sc_readout_msg[0].sc = sc; - sc->sc_readout_msg[1].hdr.pm_callback = &ugold_readout_msg; - sc->sc_readout_msg[1].sc = sc; + USB_PROC_MSG_INIT(&sc->sc_readout_msg, 0, ugold_readout_msg, sc); sc->sc_iface_index[0] = uaa->info.bIfaceIndex; sc->sc_iface_index[1] = uaa->info.bIfaceIndex + 1; @@ -292,10 +280,7 @@ callout_drain(&sc->sc_callout); - usb_proc_explore_lock(sc->sc_udev); - usb_proc_explore_mwait(sc->sc_udev, - &sc->sc_readout_msg[0], &sc->sc_readout_msg[1]); - usb_proc_explore_unlock(sc->sc_udev); + usb_proc_explore_mwait(sc->sc_udev, &sc->sc_readout_msg); usbd_transfer_unsetup(sc->sc_xfer, UGOLD_N_TRANSFER); @@ -385,11 +370,9 @@ } static void -ugold_readout_msg(struct usb_proc_msg *pm) +ugold_readout_msg(void *ctx) { - struct ugold_softc *sc = ((struct ugold_readout_msg *)pm)->sc; - - usb_proc_explore_unlock(sc->sc_udev); + struct ugold_softc *sc = ctx; mtx_lock(&sc->sc_mtx); if (sc->sc_num_sensors == 0) @@ -397,6 +380,4 @@ ugold_issue_cmd(sc, cmd_data, sizeof(cmd_data)); mtx_unlock(&sc->sc_mtx); - - usb_proc_explore_lock(sc->sc_udev); } diff --git a/sys/dev/usb/net/if_umb.c b/sys/dev/usb/net/if_umb.c --- a/sys/dev/usb/net/if_umb.c +++ b/sys/dev/usb/net/if_umb.c @@ -170,7 +170,7 @@ static device_detach_t umb_detach; static device_suspend_t umb_suspend; static device_resume_t umb_resume; -static void umb_attach_task(struct usb_proc_msg *); +static void umb_attach_task(void *); static usb_handle_request_t umb_handle_request; static int umb_deactivate(device_t); static void umb_ncm_setup(struct umb_softc *, struct usb_config *); @@ -181,7 +181,7 @@ static int umb_output(if_t , struct mbuf *, const struct sockaddr *, struct route *); static void umb_start(if_t ); -static void umb_start_task(struct usb_proc_msg *); +static void umb_start_task(void *); #if 0 static void umb_watchdog(if_t ); #endif @@ -190,14 +190,13 @@ static int umb_mediachange(if_t ); static void umb_mediastatus(if_t , struct ifmediareq *); -static void umb_add_task(struct umb_softc *sc, usb_proc_callback_t, - struct usb_proc_msg *, struct usb_proc_msg *, int); +static void umb_add_task(struct umb_softc *sc, struct usb_proc_msg *, int); static void umb_newstate(struct umb_softc *, enum umb_state, int); -static void umb_state_task(struct usb_proc_msg *); +static void umb_state_task(void *); static void umb_up(struct umb_softc *); static void umb_down(struct umb_softc *, int); -static void umb_get_response_task(struct usb_proc_msg *); +static void umb_get_response_task(void *); static void umb_decode_response(struct umb_softc *, void *, int); static void umb_handle_indicate_status_msg(struct umb_softc *, void *, @@ -513,6 +512,11 @@ device_get_nameunit(sc->sc_dev), USB_PRI_MED) != 0) goto fail; + USB_PROC_MSG_INIT(&sc->sc_proc_attach_task, 0, umb_attach_task, sc); + USB_PROC_MSG_INIT(&sc->sc_proc_start_task, 0, umb_start_task, sc); + USB_PROC_MSG_INIT(&sc->sc_proc_state_task, 0, umb_state_task, sc); + USB_PROC_MSG_INIT(&sc->sc_proc_get_response_task, 0, + umb_get_response_task, sc); DPRINTFN(2, "ctrl-ifno#%d: data-ifno#%d\n", sc->sc_ctrl_ifaceno, data_ifaceno); @@ -552,11 +556,7 @@ sc->sc_info.ber = UMB_VALUE_UNKNOWN; /* defer attaching the interface */ - mtx_lock(&sc->sc_mutex); - umb_add_task(sc, umb_attach_task, - &sc->sc_proc_attach_task[0].hdr, - &sc->sc_proc_attach_task[1].hdr, 0); - mtx_unlock(&sc->sc_mutex); + umb_add_task(sc, &sc->sc_proc_attach_task, 0); return (0); @@ -566,14 +566,11 @@ } static void -umb_attach_task(struct usb_proc_msg *msg) +umb_attach_task(void *ctx) { - struct umb_task *task = (struct umb_task *)msg; - struct umb_softc *sc = task->sc; + struct umb_softc *sc = ctx; if_t ifp; - mtx_unlock(&sc->sc_mutex); - CURVNET_SET_QUIET(vnet0); /* initialize the interface */ @@ -611,7 +608,6 @@ CURVNET_RESTORE(); umb_init(sc); - mtx_lock(&sc->sc_mutex); } static int @@ -758,11 +754,9 @@ } break; case SIOCSIFFLAGS: - mtx_lock(&sc->sc_mutex); - umb_add_task(sc, umb_state_task, - &sc->sc_proc_state_task[0].hdr, - &sc->sc_proc_state_task[1].hdr, 1); mtx_unlock(&sc->sc_mutex); + umb_add_task(sc, &sc->sc_proc_state_task, 1); + mtx_lock(&sc->sc_mutex); break; case SIOCGUMBINFO: error = copyout(&sc->sc_info, ifr->ifr_ifru.ifru_data, @@ -833,11 +827,7 @@ { struct umb_softc *sc = arg; - mtx_lock(&sc->sc_mutex); - umb_add_task(sc, umb_start_task, - &sc->sc_proc_start_task[0].hdr, - &sc->sc_proc_start_task[1].hdr, 0); - mtx_unlock(&sc->sc_mutex); + umb_add_task(sc, &sc->sc_proc_start_task, 0); } static void @@ -917,15 +907,14 @@ } static void -umb_start_task(struct usb_proc_msg *msg) +umb_start_task(void *ctx) { - struct umb_task *task = (struct umb_task *)msg; - struct umb_softc *sc = task->sc; + struct umb_softc *sc = ctx; if_t ifp = GET_IFP(sc); DPRINTF("%s()\n", __func__); - mtx_assert(&sc->sc_mutex, MA_OWNED); + mtx_lock(&sc->sc_mutex); if_setdrvflagbits(ifp, IFF_DRV_RUNNING, 0); @@ -933,6 +922,7 @@ usbd_transfer_start(sc->sc_xfer[UMB_INTR_RX]); umb_open(sc); + mtx_unlock(&sc->sc_mutex); } #if 0 @@ -964,9 +954,7 @@ log(LOG_DEBUG, "%s: state change timeout\n", DEVNAM(sc)); - umb_add_task(sc, umb_state_task, - &sc->sc_proc_state_task[0].hdr, - &sc->sc_proc_state_task[1].hdr, 0); + umb_add_task(sc, &sc->sc_proc_state_task, 0); } static int @@ -992,24 +980,16 @@ } static void -umb_add_task(struct umb_softc *sc, usb_proc_callback_t callback, - struct usb_proc_msg *t0, struct usb_proc_msg *t1, int sync) +umb_add_task(struct umb_softc *sc, struct usb_proc_msg *msg, int sync) { - struct umb_task * task; - - mtx_assert(&sc->sc_mutex, MA_OWNED); - if (usb_proc_is_gone(&sc->sc_taskqueue)) { return; } - task = usb_proc_msignal(&sc->sc_taskqueue, t0, t1); - - task->hdr.pm_callback = callback; - task->sc = sc; + usb_proc_msignal(&sc->sc_taskqueue, msg); if (sync) { - usb_proc_mwait(&sc->sc_taskqueue, t0, t1); + usb_proc_mwait(&sc->sc_taskqueue, msg); } } @@ -1028,28 +1008,27 @@ DEVNAM(sc), newstate > sc->sc_state ? "up" : "down", umb_istate(sc->sc_state), umb_istate(newstate)); sc->sc_state = newstate; - umb_add_task(sc, umb_state_task, - &sc->sc_proc_state_task[0].hdr, - &sc->sc_proc_state_task[1].hdr, 0); + umb_add_task(sc, &sc->sc_proc_state_task, 0); } static void -umb_state_task(struct usb_proc_msg *msg) +umb_state_task(void *ctx) { - struct umb_task *task = (struct umb_task *)msg; - struct umb_softc *sc = task->sc; + struct umb_softc *sc = ctx; if_t ifp = GET_IFP(sc); struct ifreq ifr; int state; DPRINTF("%s()\n", __func__); + mtx_lock(&sc->sc_mutex); if (sc->sc_info.regstate == MBIM_REGSTATE_ROAMING && !sc->sc_roaming) { /* * Query the registration state until we're with the home * network again. */ umb_cmd(sc, MBIM_CID_REGISTER_STATE, MBIM_CMDOP_QRY, NULL, 0); + mtx_unlock(&sc->sc_mutex); return; } @@ -1087,6 +1066,7 @@ } if_link_state_change(ifp, state); } + mtx_unlock(&sc->sc_mutex); } static void @@ -1197,13 +1177,13 @@ } static void -umb_get_response_task(struct usb_proc_msg *msg) +umb_get_response_task(void *ctx) { - struct umb_task *task = (struct umb_task *)msg; - struct umb_softc *sc = task->sc; + struct umb_softc *sc = ctx; int len; DPRINTF("%s()\n", __func__); + mtx_lock(&sc->sc_mutex); /* * Function is required to send on RESPONSE_AVAILABLE notification for * each encapsulated response that is to be processed by the host. @@ -1216,6 +1196,7 @@ if (umb_get_encap_response(sc, sc->sc_resp_buf, &len)) umb_decode_response(sc, sc->sc_resp_buf, len); } + mtx_unlock(&sc->sc_mutex); } static void @@ -1587,9 +1568,7 @@ /* * In case the PIN was set after IFF_UP, retrigger the state machine */ - umb_add_task(sc, umb_state_task, - &sc->sc_proc_state_task[0].hdr, - &sc->sc_proc_state_task[1].hdr, 0); + umb_add_task(sc, &sc->sc_proc_state_task, 0); return 1; } @@ -2825,10 +2804,7 @@ case UCDC_N_RESPONSE_AVAILABLE: DPRINTFN(2, "umb_intr: response available\n"); ++sc->sc_nresp; - umb_add_task(sc, umb_get_response_task, - &sc->sc_proc_get_response_task[0].hdr, - &sc->sc_proc_get_response_task[1].hdr, - 0); + umb_add_task(sc, &sc->sc_proc_get_response_task, 0); break; case UCDC_N_CONNECTION_SPEED_CHANGE: DPRINTFN(2, "umb_intr: connection speed changed\n"); diff --git a/sys/dev/usb/net/if_umbreg.h b/sys/dev/usb/net/if_umbreg.h --- a/sys/dev/usb/net/if_umbreg.h +++ b/sys/dev/usb/net/if_umbreg.h @@ -381,11 +381,6 @@ UMB_N_TRANSFER, }; -struct umb_task { - struct usb_proc_msg hdr; - struct umb_softc *sc; -}; - struct umb_softc { device_t sc_dev; struct ifnet *sc_if; @@ -407,10 +402,10 @@ int sc_cid; struct usb_process sc_taskqueue; - struct umb_task sc_proc_attach_task[2]; - struct umb_task sc_proc_start_task[2]; - struct umb_task sc_proc_state_task[2]; - struct umb_task sc_proc_get_response_task[2]; + struct usb_proc_msg sc_proc_attach_task; + struct usb_proc_msg sc_proc_start_task; + struct usb_proc_msg sc_proc_state_task; + struct usb_proc_msg sc_proc_get_response_task; int sc_nresp; struct mtx sc_mutex; diff --git a/sys/dev/usb/net/usb_ethernet.h b/sys/dev/usb/net/usb_ethernet.h --- a/sys/dev/usb/net/usb_ethernet.h +++ b/sys/dev/usb/net/usb_ethernet.h @@ -66,11 +66,6 @@ int (*ue_attach_post_sub)(struct usb_ether *); }; -struct usb_ether_cfg_task { - struct usb_proc_msg hdr; - struct usb_ether *ue; -}; - struct usb_ether { /* NOTE: the "ue_ifp" pointer must be first --hps */ if_t ue_ifp; @@ -86,11 +81,13 @@ struct sysctl_ctx_list ue_sysctl_ctx; struct mbufq ue_rxq; struct usb_callout ue_watchdog; - struct usb_ether_cfg_task ue_sync_task[2]; - struct usb_ether_cfg_task ue_media_task[2]; - struct usb_ether_cfg_task ue_multi_task[2]; - struct usb_ether_cfg_task ue_promisc_task[2]; - struct usb_ether_cfg_task ue_tick_task[2]; + struct usb_proc_msg ue_sync_task; + struct usb_proc_msg ue_start_msg; + struct usb_proc_msg ue_stop_msg; + struct usb_proc_msg ue_media_task; + struct usb_proc_msg ue_multi_task; + struct usb_proc_msg ue_promisc_task; + struct usb_proc_msg ue_tick_task; int ue_unit; diff --git a/sys/dev/usb/net/usb_ethernet.c b/sys/dev/usb/net/usb_ethernet.c --- a/sys/dev/usb/net/usb_ethernet.c +++ b/sys/dev/usb/net/usb_ethernet.c @@ -98,14 +98,8 @@ } static void -ue_queue_command(struct usb_ether *ue, - usb_proc_callback_t *fn, - struct usb_proc_msg *t0, struct usb_proc_msg *t1) +ue_queue_command(struct usb_ether *ue, struct usb_proc_msg *msg, bool wait) { - struct usb_ether_cfg_task *task; - - UE_LOCK_ASSERT(ue, MA_OWNED); - if (usb_proc_is_gone(&ue->ue_tq)) { return; /* nothing to do */ } @@ -114,18 +108,13 @@ * "sc_mtx" mutex. It is safe to update fields in the message * structure after that the message got queued. */ - task = (struct usb_ether_cfg_task *) - usb_proc_msignal(&ue->ue_tq, t0, t1); - - /* Setup callback and self pointers */ - task->hdr.pm_callback = fn; - task->ue = ue; + usb_proc_msignal(&ue->ue_tq, msg); /* * Start and stop must be synchronous! */ - if ((fn == ue_start_task) || (fn == ue_stop_task)) - usb_proc_mwait(&ue->ue_tq, t0, t1); + if (wait) + usb_proc_mwait(&ue->ue_tq, msg); } if_t @@ -170,17 +159,20 @@ error = usb_proc_create(&ue->ue_tq, ue->ue_mtx, device_get_nameunit(ue->ue_dev), USB_PRI_MED); + USB_PROC_MSG_INIT(&ue->ue_sync_task, 0, ue_attach_post_task, ue); + USB_PROC_MSG_INIT(&ue->ue_start_msg, 0, ue_start_task, ue); + USB_PROC_MSG_INIT(&ue->ue_stop_msg, 0, ue_stop_task, ue); + USB_PROC_MSG_INIT(&ue->ue_media_task, 0, ue_ifmedia_task, ue); + USB_PROC_MSG_INIT(&ue->ue_multi_task, 0, ue_setmulti_task, ue); + USB_PROC_MSG_INIT(&ue->ue_promisc_task, 0, ue_promisc_task, ue); + USB_PROC_MSG_INIT(&ue->ue_tick_task, 0, ue_tick_task, ue); if (error) { device_printf(ue->ue_dev, "could not setup taskqueue\n"); goto error; } /* fork rest of the attach code */ - UE_LOCK(ue); - ue_queue_command(ue, ue_attach_post_task, - &ue->ue_sync_task[0].hdr, - &ue->ue_sync_task[1].hdr); - UE_UNLOCK(ue); + ue_queue_command(ue, &ue->ue_sync_task, false); error: return (error); @@ -189,27 +181,20 @@ void uether_ifattach_wait(struct usb_ether *ue) { - - UE_LOCK(ue); - usb_proc_mwait(&ue->ue_tq, - &ue->ue_sync_task[0].hdr, - &ue->ue_sync_task[1].hdr); - UE_UNLOCK(ue); + usb_proc_mwait(&ue->ue_tq, &ue->ue_sync_task); } static void -ue_attach_post_task(struct usb_proc_msg *_task) +ue_attach_post_task(void *ctx) { - struct usb_ether_cfg_task *task = - (struct usb_ether_cfg_task *)_task; - struct usb_ether *ue = task->ue; + struct usb_ether *ue = ctx; if_t ifp; int error; char num[14]; /* sufficient for 32 bits */ + UE_LOCK(ue); /* first call driver's post attach routine */ ue->ue_methods->ue_attach_post(ue); - UE_UNLOCK(ue); ue->ue_unit = alloc_unr(ueunit); @@ -269,7 +254,6 @@ CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE, ue, 0, ue_sysctl_parent, "A", "parent device"); - UE_LOCK(ue); return; fail: @@ -284,7 +268,6 @@ if_free(ue->ue_ifp); ue->ue_ifp = NULL; } - UE_LOCK(ue); return; } @@ -293,9 +276,6 @@ { if_t ifp; - /* wait for any post attach or other command to complete */ - usb_proc_drain(&ue->ue_tq); - /* read "ifnet" pointer after taskqueue drain */ ifp = ue->ue_ifp; @@ -354,44 +334,42 @@ { struct usb_ether *ue = arg; - UE_LOCK(ue); - ue_queue_command(ue, ue_start_task, - &ue->ue_sync_task[0].hdr, - &ue->ue_sync_task[1].hdr); - UE_UNLOCK(ue); + ue_queue_command(ue, &ue->ue_start_msg, true); } static void -ue_start_task(struct usb_proc_msg *_task) +ue_start_task(void *ctx) { - struct usb_ether_cfg_task *task = - (struct usb_ether_cfg_task *)_task; - struct usb_ether *ue = task->ue; + struct usb_ether *ue = ctx; if_t ifp = ue->ue_ifp; - UE_LOCK_ASSERT(ue, MA_OWNED); + UE_LOCK_ASSERT(ue, MA_NOTOWNED); + UE_LOCK(ue); ue->ue_methods->ue_init(ue); - if ((if_getdrvflags(ifp) & IFF_DRV_RUNNING) == 0) + if ((if_getdrvflags(ifp) & IFF_DRV_RUNNING) == 0) { + UE_UNLOCK(ue); return; + } if (ue->ue_methods->ue_tick != NULL) usb_callout_reset(&ue->ue_watchdog, hz, ue_watchdog, ue); + UE_UNLOCK(ue); } static void -ue_stop_task(struct usb_proc_msg *_task) +ue_stop_task(void *ctx) { - struct usb_ether_cfg_task *task = - (struct usb_ether_cfg_task *)_task; - struct usb_ether *ue = task->ue; + struct usb_ether *ue = ctx; - UE_LOCK_ASSERT(ue, MA_OWNED); + UE_LOCK_ASSERT(ue, MA_NOTOWNED); + UE_LOCK(ue); usb_callout_stop(&ue->ue_watchdog); ue->ue_methods->ue_stop(ue); + UE_UNLOCK(ue); } void @@ -415,23 +393,23 @@ } static void -ue_promisc_task(struct usb_proc_msg *_task) +ue_promisc_task(void *ctx) { - struct usb_ether_cfg_task *task = - (struct usb_ether_cfg_task *)_task; - struct usb_ether *ue = task->ue; + struct usb_ether *ue = ctx; + UE_LOCK(ue); ue->ue_methods->ue_setpromisc(ue); + UE_UNLOCK(ue); } static void -ue_setmulti_task(struct usb_proc_msg *_task) +ue_setmulti_task(void *ctx) { - struct usb_ether_cfg_task *task = - (struct usb_ether_cfg_task *)_task; - struct usb_ether *ue = task->ue; + struct usb_ether *ue = ctx; + UE_LOCK(ue); ue->ue_methods->ue_setmulti(ue); + UE_UNLOCK(ue); } int @@ -447,24 +425,20 @@ struct usb_ether *ue = if_getsoftc(ifp); /* Defer to process context */ - UE_LOCK(ue); - ue_queue_command(ue, ue_ifmedia_task, - &ue->ue_media_task[0].hdr, - &ue->ue_media_task[1].hdr); - UE_UNLOCK(ue); + ue_queue_command(ue, &ue->ue_media_task, false); return (0); } static void -ue_ifmedia_task(struct usb_proc_msg *_task) +ue_ifmedia_task(void *ctx) { - struct usb_ether_cfg_task *task = - (struct usb_ether_cfg_task *)_task; - struct usb_ether *ue = task->ue; + struct usb_ether *ue = ctx; if_t ifp = ue->ue_ifp; + UE_LOCK(ue); ue->ue_methods->ue_mii_upd(ifp); + UE_UNLOCK(ue); } static void @@ -476,25 +450,22 @@ if ((if_getdrvflags(ifp) & IFF_DRV_RUNNING) == 0) return; - ue_queue_command(ue, ue_tick_task, - &ue->ue_tick_task[0].hdr, - &ue->ue_tick_task[1].hdr); + ue_queue_command(ue, &ue->ue_tick_task, false); usb_callout_reset(&ue->ue_watchdog, hz, ue_watchdog, ue); } static void -ue_tick_task(struct usb_proc_msg *_task) +ue_tick_task(void *ctx) { - struct usb_ether_cfg_task *task = - (struct usb_ether_cfg_task *)_task; - struct usb_ether *ue = task->ue; + struct usb_ether *ue = ctx; if_t ifp = ue->ue_ifp; if ((if_getdrvflags(ifp) & IFF_DRV_RUNNING) == 0) return; - + UE_LOCK(ue); ue->ue_methods->ue_tick(ue); + UE_UNLOCK(ue); } int @@ -507,30 +478,19 @@ switch (command) { case SIOCSIFFLAGS: - UE_LOCK(ue); if (if_getflags(ifp) & IFF_UP) { if (if_getdrvflags(ifp) & IFF_DRV_RUNNING) - ue_queue_command(ue, ue_promisc_task, - &ue->ue_promisc_task[0].hdr, - &ue->ue_promisc_task[1].hdr); + ue_queue_command(ue, &ue->ue_promisc_task, + false); else - ue_queue_command(ue, ue_start_task, - &ue->ue_sync_task[0].hdr, - &ue->ue_sync_task[1].hdr); + ue_queue_command(ue, &ue->ue_start_msg, true); } else { - ue_queue_command(ue, ue_stop_task, - &ue->ue_sync_task[0].hdr, - &ue->ue_sync_task[1].hdr); + ue_queue_command(ue, &ue->ue_stop_msg, true); } - UE_UNLOCK(ue); break; case SIOCADDMULTI: case SIOCDELMULTI: - UE_LOCK(ue); - ue_queue_command(ue, ue_setmulti_task, - &ue->ue_multi_task[0].hdr, - &ue->ue_multi_task[1].hdr); - UE_UNLOCK(ue); + ue_queue_command(ue, &ue->ue_multi_task, false); break; case SIOCGIFMEDIA: case SIOCSIFMEDIA: diff --git a/sys/dev/usb/serial/usb_serial.h b/sys/dev/usb/serial/usb_serial.h --- a/sys/dev/usb/serial/usb_serial.h +++ b/sys/dev/usb/serial/usb_serial.h @@ -117,17 +117,6 @@ #define ULSR_RXRDY 0x01 /* Byte ready in Receive Buffer */ #define ULSR_RCV_MASK 0x1f /* Mask for incoming data or error */ -struct ucom_cfg_task { - struct usb_proc_msg hdr; - struct ucom_softc *sc; -}; - -struct ucom_param_task { - struct usb_proc_msg hdr; - struct ucom_softc *sc; - struct termios termios_copy; -}; - struct ucom_super_softc { struct usb_process sc_tq; int sc_unit; @@ -151,12 +140,13 @@ * OPEN->CLOSE * CLOSE->OPEN */ - struct ucom_cfg_task sc_start_task[2]; - struct ucom_cfg_task sc_open_task[2]; - struct ucom_cfg_task sc_close_task[2]; - struct ucom_cfg_task sc_line_state_task[2]; - struct ucom_cfg_task sc_status_task[2]; - struct ucom_param_task sc_param_task[2]; + struct termios t; + struct usb_proc_msg sc_start_task; + struct usb_proc_msg sc_open_task; + struct usb_proc_msg sc_close_task; + struct usb_proc_msg sc_line_state_task; + struct usb_proc_msg sc_status_task; + struct usb_proc_msg sc_param_task; /* pulse capturing support, PPS */ struct pps_state sc_pps; /* Used to set "UCOM_FLAG_GP_DATA" flag: */ diff --git a/sys/dev/usb/serial/usb_serial.c b/sys/dev/usb/serial/usb_serial.c --- a/sys/dev/usb/serial/usb_serial.c +++ b/sys/dev/usb/serial/usb_serial.c @@ -151,8 +151,7 @@ static int ucom_attach_tty(struct ucom_super_softc *, struct ucom_softc *); static void ucom_detach_tty(struct ucom_super_softc *, struct ucom_softc *); static int ucom_queue_command(struct ucom_softc *, - usb_proc_callback_t *, struct termios *pt, - struct usb_proc_msg *t0, struct usb_proc_msg *t1, bool wait); + struct usb_proc_msg *msg, bool wait); static void ucom_shutdown(struct ucom_softc *); static void ucom_ring(struct ucom_softc *, uint8_t); static void ucom_break(struct ucom_softc *, uint8_t); @@ -290,6 +289,12 @@ ucom_unit_free(ssc->sc_unit); return (error); } + USB_PROC_MSG_INIT(&sc->sc_start_task, 0, ucom_cfg_start_transfers, sc); + USB_PROC_MSG_INIT(&sc->sc_open_task, 0, ucom_cfg_open, sc); + USB_PROC_MSG_INIT(&sc->sc_close_task, 0, ucom_cfg_close, sc); + USB_PROC_MSG_INIT(&sc->sc_line_state_task, 0, ucom_cfg_line_state, sc); + USB_PROC_MSG_INIT(&sc->sc_status_task, 0, ucom_cfg_status_change, sc); + USB_PROC_MSG_INIT(&sc->sc_param_task, 0, ucom_cfg_param, sc); ssc->sc_subunits = subunits; ssc->sc_flag = UCOM_FLAG_ATTACHED | UCOM_FLAG_FREE_UNIT | (ssc->sc_flag & UCOM_FLAG_DEVICE_MODE); @@ -592,7 +597,7 @@ } static void -ucom_command_barrier_cb(struct usb_proc_msg *msg __unused) +ucom_command_barrier_cb(void *ctx) { /* NOP */ } @@ -606,32 +611,31 @@ ucom_command_barrier(struct ucom_softc *sc) { struct ucom_super_softc *ssc = sc->sc_super; - struct usb_proc_msg dummy = { .pm_callback = ucom_command_barrier_cb }; - struct usb_proc_msg *task; - int error; + struct usb_proc_msg dummy; UCOM_MTX_ASSERT(sc, MA_OWNED); + USB_PROC_MSG_INIT(&dummy, 0, &ucom_command_barrier_cb, sc); + if (usb_proc_is_gone(&ssc->sc_tq)) { DPRINTF("proc is gone\n"); return (ENXIO); /* nothing to do */ } - task = usb_proc_msignal(&ssc->sc_tq, &dummy, &dummy); - error = usb_proc_mwait_sig(&ssc->sc_tq, task, task); - if (error == 0 && sc->sc_tty != NULL && tty_gone(sc->sc_tty)) - error = ENXIO; - return (error); + UCOM_MTX_UNLOCK(sc); + usb_proc_msignal(&ssc->sc_tq, &dummy); + usb_proc_mwait(&ssc->sc_tq, &dummy); + UCOM_MTX_LOCK(sc); + if (sc->sc_tty != NULL && tty_gone(sc->sc_tty)) + return (ENXIO); + return (0); } static int -ucom_queue_command(struct ucom_softc *sc, - usb_proc_callback_t *fn, struct termios *pt, - struct usb_proc_msg *t0, struct usb_proc_msg *t1, bool wait) +ucom_queue_command(struct ucom_softc *sc, struct usb_proc_msg *msg, bool wait) { struct ucom_super_softc *ssc = sc->sc_super; - struct ucom_param_task *task; - int error; + int error = 0; UCOM_MTX_ASSERT(sc, MA_OWNED); @@ -644,40 +648,23 @@ * "sc_mtx" mutex. It is safe to update fields in the message * structure after that the message got queued. */ - task = (struct ucom_param_task *) - usb_proc_msignal(&ssc->sc_tq, t0, t1); - - /* Setup callback and softc pointers */ - task->hdr.pm_callback = fn; - task->sc = sc; - - /* - * Make a copy of the termios. This field is only present if - * the "pt" field is not NULL. - */ - if (pt != NULL) - task->termios_copy = *pt; + usb_proc_msignal(&ssc->sc_tq, msg); /* * Closing or opening the device should be synchronous. */ if (wait) { - error = usb_proc_mwait_sig(&ssc->sc_tq, t0, t1); + usb_proc_mwait(&ssc->sc_tq, msg); /* usb_proc_mwait_sig may have dropped the tty lock. */ - if (error == 0 && sc->sc_tty != NULL && tty_gone(sc->sc_tty)) + UCOM_MTX_LOCK(sc); + if (sc->sc_tty != NULL && tty_gone(sc->sc_tty)) error = ENXIO; + UCOM_MTX_UNLOCK(sc); } else { error = 0; } - /* - * In case of multiple configure requests, - * keep track of the last one! - */ - if (fn == ucom_cfg_start_transfers) - sc->sc_last_start_xfer = &task->hdr; - return (error); } @@ -712,22 +699,19 @@ } static void -ucom_cfg_start_transfers(struct usb_proc_msg *_task) +ucom_cfg_start_transfers(void *ctx) { - struct ucom_cfg_task *task = - (struct ucom_cfg_task *)_task; - struct ucom_softc *sc = task->sc; + struct ucom_softc *sc = ctx; + UCOM_MTX_LOCK(sc); if (!(sc->sc_flag & UCOM_FLAG_LL_READY)) { - return; + goto end; } if (!(sc->sc_flag & UCOM_FLAG_HL_READY)) { /* TTY device closed */ - return; + goto end; } - - if (_task == sc->sc_last_start_xfer) - sc->sc_flag |= UCOM_FLAG_GP_DATA; + sc->sc_flag |= UCOM_FLAG_GP_DATA; if (sc->sc_callback->ucom_start_read) { (sc->sc_callback->ucom_start_read) (sc); @@ -735,6 +719,8 @@ if (sc->sc_callback->ucom_start_write) { (sc->sc_callback->ucom_start_write) (sc); } +end: + UCOM_MTX_UNLOCK(sc); } static void @@ -756,14 +742,13 @@ } static void -ucom_cfg_open(struct usb_proc_msg *_task) +ucom_cfg_open(void *ctx) { - struct ucom_cfg_task *task = - (struct ucom_cfg_task *)_task; - struct ucom_softc *sc = task->sc; + struct ucom_softc *sc = ctx; DPRINTF("\n"); + UCOM_MTX_LOCK(sc); if (sc->sc_flag & UCOM_FLAG_LL_READY) { /* already opened */ @@ -777,6 +762,7 @@ usb_pause_mtx(sc->sc_mtx, hz / 10); } } + UCOM_MTX_UNLOCK(sc); } static int @@ -823,21 +809,23 @@ sc->sc_jitterbuf_in = 0; sc->sc_jitterbuf_out = 0; - error = ucom_queue_command(sc, ucom_cfg_open, NULL, - &sc->sc_open_task[0].hdr, - &sc->sc_open_task[1].hdr, true); - if (error != 0) + UCOM_MTX_UNLOCK(sc); + error = ucom_queue_command(sc, &sc->sc_open_task, true); + if (error != 0) { + UCOM_MTX_LOCK(sc); goto out; + } /* * Queue transfer enable command last, we'll have a barrier later so we * don't need to wait on this to complete specifically. */ - error = ucom_queue_command(sc, ucom_cfg_start_transfers, NULL, - &sc->sc_start_task[0].hdr, - &sc->sc_start_task[1].hdr, true); - if (error != 0) + error = ucom_queue_command(sc, &sc->sc_start_task, true); + if (error != 0) { + UCOM_MTX_LOCK(sc); goto out; + } + UCOM_MTX_LOCK(sc); if (sc->sc_tty == NULL || (sc->sc_tty->t_termios.c_cflag & CNO_RTSDTR) == 0) ucom_modem(tp, SER_DTR | SER_RTS, 0); @@ -854,14 +842,13 @@ } static void -ucom_cfg_close(struct usb_proc_msg *_task) +ucom_cfg_close(void *ctx) { - struct ucom_cfg_task *task = - (struct ucom_cfg_task *)_task; - struct ucom_softc *sc = task->sc; + struct ucom_softc *sc = ctx; DPRINTF("\n"); + UCOM_MTX_LOCK(sc); if (sc->sc_flag & UCOM_FLAG_LL_READY) { sc->sc_flag &= ~UCOM_FLAG_LL_READY; if (sc->sc_callback->ucom_cfg_close) @@ -869,6 +856,7 @@ } else { /* already closed */ } + UCOM_MTX_UNLOCK(sc); } static void @@ -886,9 +874,9 @@ } ucom_shutdown(sc); - (void)ucom_queue_command(sc, ucom_cfg_close, NULL, - &sc->sc_close_task[0].hdr, - &sc->sc_close_task[1].hdr, true); + UCOM_MTX_UNLOCK(sc); + ucom_queue_command(sc, &sc->sc_close_task, true); + UCOM_MTX_LOCK(sc); sc->sc_flag &= ~(UCOM_FLAG_HL_READY | UCOM_FLAG_RTS_IFLOW); @@ -1047,18 +1035,18 @@ } static void -ucom_cfg_line_state(struct usb_proc_msg *_task) +ucom_cfg_line_state(void *ctx) { - struct ucom_cfg_task *task = - (struct ucom_cfg_task *)_task; - struct ucom_softc *sc = task->sc; + struct ucom_softc *sc = ctx; uint8_t notch_bits; uint8_t any_bits; uint8_t prev_value; uint8_t last_value; uint8_t mask; + UCOM_MTX_LOCK(sc); if (!(sc->sc_flag & UCOM_FLAG_LL_READY)) { + UCOM_MTX_UNLOCK(sc); return; } @@ -1111,6 +1099,7 @@ if (any_bits & UCOM_LS_RING) sc->sc_callback->ucom_cfg_set_ring(sc, (last_value & UCOM_LS_RING) ? 1 : 0); + UCOM_MTX_UNLOCK(sc); } static void @@ -1135,9 +1124,7 @@ * defer driver programming - we don't propagate any error from * this call because we'll catch such errors further up the call stack. */ - (void)ucom_queue_command(sc, ucom_cfg_line_state, NULL, - &sc->sc_line_state_task[0].hdr, - &sc->sc_line_state_task[1].hdr, false); + (void)ucom_queue_command(sc, &sc->sc_line_state_task, false); } static void @@ -1185,11 +1172,9 @@ } static void -ucom_cfg_status_change(struct usb_proc_msg *_task) +ucom_cfg_status_change(void *ctx) { - struct ucom_cfg_task *task = - (struct ucom_cfg_task *)_task; - struct ucom_softc *sc = task->sc; + struct ucom_softc *sc = ctx; struct tty *tp; int onoff; uint8_t new_msr; @@ -1200,14 +1185,14 @@ tp = sc->sc_tty; - UCOM_MTX_ASSERT(sc, MA_OWNED); + UCOM_MTX_ASSERT(sc, MA_NOTOWNED); + UCOM_MTX_LOCK(sc); if (!(sc->sc_flag & UCOM_FLAG_LL_READY)) { - return; - } - if (sc->sc_callback->ucom_cfg_get_status == NULL) { - return; + goto end; } + if (sc->sc_callback->ucom_cfg_get_status == NULL) + goto end; /* get status */ new_msr = 0; @@ -1215,10 +1200,9 @@ (sc->sc_callback->ucom_cfg_get_status) (sc, &new_lsr, &new_msr); - if (!(sc->sc_flag & UCOM_FLAG_HL_READY)) { - /* TTY device closed */ - return; - } + if (!(sc->sc_flag & UCOM_FLAG_HL_READY)) + goto end; + msr_delta = (sc->sc_msr ^ new_msr); lsr_delta = (sc->sc_lsr ^ new_lsr); @@ -1278,6 +1262,8 @@ ttydisc_rint(tp, 0, TRE_PARITY); ttydisc_rint_done(tp); } +end: + UCOM_MTX_UNLOCK(sc); } void @@ -1293,29 +1279,30 @@ } DPRINTF("\n"); - (void)ucom_queue_command(sc, ucom_cfg_status_change, NULL, - &sc->sc_status_task[0].hdr, - &sc->sc_status_task[1].hdr, true); + UCOM_MTX_UNLOCK(sc); + (void)ucom_queue_command(sc, &sc->sc_status_task, true); + UCOM_MTX_LOCK(sc); } static void -ucom_cfg_param(struct usb_proc_msg *_task) +ucom_cfg_param(void *ctx) { - struct ucom_param_task *task = - (struct ucom_param_task *)_task; - struct ucom_softc *sc = task->sc; + struct ucom_softc *sc = ctx; + UCOM_MTX_LOCK(sc); if (!(sc->sc_flag & UCOM_FLAG_LL_READY)) { - return; + goto end; } if (sc->sc_callback->ucom_cfg_param == NULL) { - return; + goto end; } - (sc->sc_callback->ucom_cfg_param) (sc, &task->termios_copy); + (sc->sc_callback->ucom_cfg_param)(sc, &sc->t); /* wait a little */ usb_pause_mtx(sc->sc_mtx, hz / 10); +end: + UCOM_MTX_UNLOCK(sc); } static int @@ -1367,18 +1354,21 @@ sc->sc_flag &= ~UCOM_FLAG_GP_DATA; /* Queue baud rate programming command first */ - error = ucom_queue_command(sc, ucom_cfg_param, t, - &sc->sc_param_task[0].hdr, - &sc->sc_param_task[1].hdr, true); - if (error != 0) + sc->t = *t; + UCOM_MTX_UNLOCK(sc); + error = ucom_queue_command(sc, &sc->sc_param_task, true); + if (error != 0) { + UCOM_MTX_LOCK(sc); goto done; + } /* Queue transfer enable command last */ - error = ucom_queue_command(sc, ucom_cfg_start_transfers, NULL, - &sc->sc_start_task[0].hdr, - &sc->sc_start_task[1].hdr, true); - if (error != 0) + error = ucom_queue_command(sc, &sc->sc_start_task, true); + if (error != 0) { + UCOM_MTX_LOCK(sc); goto done; + } + UCOM_MTX_LOCK(sc); if (t->c_cflag & CRTS_IFLOW) { sc->sc_flag |= UCOM_FLAG_RTS_IFLOW; diff --git a/sys/dev/usb/usb_bus.h b/sys/dev/usb/usb_bus.h --- a/sys/dev/usb/usb_bus.h +++ b/sys/dev/usb/usb_bus.h @@ -30,16 +30,6 @@ struct usb_fs_privdata; -/* - * The following structure defines the USB explore message sent to the USB - * explore process. - */ - -struct usb_bus_msg { - struct usb_proc_msg hdr; - struct usb_bus *bus; -}; - /* * The following structure defines an USB BUS. There is one USB BUS * for every Host or Device controller. @@ -77,15 +67,15 @@ struct usb_process control_xfer_proc; #endif - struct usb_bus_msg explore_msg[2]; - struct usb_bus_msg detach_msg[2]; - struct usb_bus_msg attach_msg[2]; - struct usb_bus_msg suspend_msg[2]; - struct usb_bus_msg resume_msg[2]; - struct usb_bus_msg reset_msg[2]; - struct usb_bus_msg shutdown_msg[2]; + struct usb_proc_msg explore_msg; + struct usb_proc_msg detach_msg; + struct usb_proc_msg attach_msg; + struct usb_proc_msg suspend_msg; + struct usb_proc_msg resume_msg; + struct usb_proc_msg reset_msg; + struct usb_proc_msg shutdown_msg; #if USB_HAVE_UGEN - struct usb_bus_msg cleanup_msg[2]; + struct usb_proc_msg cleanup_msg; SLIST_HEAD(,usb_fs_privdata) pd_cleanup_list; #endif /* diff --git a/sys/dev/usb/usb_device.h b/sys/dev/usb/usb_device.h --- a/sys/dev/usb/usb_device.h +++ b/sys/dev/usb/usb_device.h @@ -54,11 +54,6 @@ #define USB_UNCFG_FLAG_NONE 0x00 #define USB_UNCFG_FLAG_FREE_EP0 0x02 /* endpoint zero is freed */ -struct usb_udev_msg { - struct usb_proc_msg hdr; - struct usb_device *udev; -}; - /* The following four structures makes up a tree, where we have the * leaf structure, "usb_host_endpoint", first, and the root structure, * "usb_device", last. The four structures below mirror the structure @@ -193,7 +188,7 @@ struct usb_device_statistics stats_cancelled; /* generic clear stall message */ - struct usb_udev_msg cs_msg[2]; + struct usb_proc_msg cs_msg; struct sx enum_sx; struct sx sr_sx; struct sx ctrl_sx; diff --git a/sys/dev/usb/usb_device.c b/sys/dev/usb/usb_device.c --- a/sys/dev/usb/usb_device.c +++ b/sys/dev/usb/usb_device.c @@ -1640,13 +1640,11 @@ * This function performs generic USB clear stall operations. *------------------------------------------------------------------------*/ static void -usbd_clear_stall_proc(struct usb_proc_msg *_pm) +usbd_clear_stall_proc(void *ctx) { - struct usb_udev_msg *pm = (void *)_pm; - struct usb_device *udev = pm->udev; + struct usb_device *udev = ctx; /* Change lock */ - USB_BUS_UNLOCK(udev->bus); USB_MTX_LOCK(&udev->device_mtx); /* Start clear stall callback */ @@ -1654,7 +1652,6 @@ /* Change lock */ USB_MTX_UNLOCK(&udev->device_mtx); - USB_BUS_LOCK(udev->bus); } /*------------------------------------------------------------------------* @@ -1809,10 +1806,7 @@ mtx_init(&udev->device_mtx, "USB device mutex", NULL, MTX_DEF); /* initialise generic clear stall */ - udev->cs_msg[0].hdr.pm_callback = &usbd_clear_stall_proc; - udev->cs_msg[0].udev = udev; - udev->cs_msg[1].hdr.pm_callback = &usbd_clear_stall_proc; - udev->cs_msg[1].udev = udev; + USB_PROC_MSG_INIT(&udev->cs_msg, 0, usbd_clear_stall_proc, udev); /* initialise some USB device fields */ udev->parent_hub = parent_hub; @@ -2194,8 +2188,7 @@ USB_BUS_LOCK(bus); SLIST_INSERT_HEAD(&bus->pd_cleanup_list, pd, pd_next); /* get cleanup going */ - usb_proc_msignal(USB_BUS_EXPLORE_PROC(bus), - &bus->cleanup_msg[0], &bus->cleanup_msg[1]); + usb_proc_msignal(USB_BUS_EXPLORE_PROC(bus), &bus->cleanup_msg); USB_BUS_UNLOCK(bus); } @@ -2339,14 +2332,11 @@ /* template unsetup, if any */ (usb_temp_unsetup_p) (udev); - /* + /* * Make sure that our clear-stall messages are not queued * anywhere: */ - USB_BUS_LOCK(udev->bus); - usb_proc_mwait(USB_BUS_CS_PROC(udev->bus), - &udev->cs_msg[0], &udev->cs_msg[1]); - USB_BUS_UNLOCK(udev->bus); + usb_proc_mwait(USB_BUS_CS_PROC(udev->bus), &udev->cs_msg); /* wait for all references to go away */ usb_wait_pending_refs(udev); diff --git a/sys/dev/usb/usb_hub.h b/sys/dev/usb/usb_hub.h --- a/sys/dev/usb/usb_hub.h +++ b/sys/dev/usb/usb_hub.h @@ -49,7 +49,7 @@ usb_error_t (*explore) (struct usb_device *hub); void *hubsoftc; #if USB_HAVE_TT_SUPPORT - struct usb_udev_msg tt_msg[2]; + struct usb_proc_msg tt_msg; #endif usb_size_t uframe_usage[USB_HS_MICRO_FRAMES_MAX]; uint16_t portpower; /* mA per USB port */ diff --git a/sys/dev/usb/usb_hub.c b/sys/dev/usb/usb_hub.c --- a/sys/dev/usb/usb_hub.c +++ b/sys/dev/usb/usb_hub.c @@ -224,10 +224,9 @@ *------------------------------------------------------------------------*/ #if USB_HAVE_TT_SUPPORT static void -uhub_reset_tt_proc(struct usb_proc_msg *_pm) +uhub_reset_tt_proc(void *ctx) { - struct usb_udev_msg *pm = (void *)_pm; - struct usb_device *udev = pm->udev; + struct usb_device *udev = ctx; struct usb_hub *hub; struct uhub_softc *sc; @@ -239,13 +238,11 @@ return; /* Change lock */ - USB_BUS_UNLOCK(udev->bus); USB_MTX_LOCK(&sc->sc_mtx); /* Start transfer */ usbd_transfer_start(sc->sc_xfer[UHUB_RESET_TT_TRANSFER]); /* Change lock */ USB_MTX_UNLOCK(&sc->sc_mtx); - USB_BUS_LOCK(udev->bus); } #endif @@ -316,8 +313,7 @@ } up->req_reset_tt = req; /* get reset transfer started */ - usb_proc_msignal(USB_BUS_TT_PROC(udev->bus), - &hub->tt_msg[0], &hub->tt_msg[1]); + usb_proc_msignal(USB_BUS_TT_PROC(udev->bus), &hub->tt_msg); } #endif @@ -1380,10 +1376,7 @@ hub->nports = nports; hub->hubudev = udev; #if USB_HAVE_TT_SUPPORT - hub->tt_msg[0].hdr.pm_callback = &uhub_reset_tt_proc; - hub->tt_msg[0].udev = udev; - hub->tt_msg[1].hdr.pm_callback = &uhub_reset_tt_proc; - hub->tt_msg[1].udev = udev; + USB_PROC_MSG_INIT(&hub->tt_msg, 0, uhub_reset_tt_proc, udev); #endif /* if self powered hub, give ports maximum current */ if (udev->flags.self_powered) { @@ -1576,10 +1569,7 @@ #if USB_HAVE_TT_SUPPORT /* Make sure our TT messages are not queued anywhere */ - USB_BUS_LOCK(bus); - usb_proc_mwait(USB_BUS_TT_PROC(bus), - &hub->tt_msg[0], &hub->tt_msg[1]); - USB_BUS_UNLOCK(bus); + usb_proc_mwait(USB_BUS_TT_PROC(bus), &hub->tt_msg); #endif #if (USB_HAVE_FIXED_PORT == 0) @@ -2267,8 +2257,6 @@ void usb_needs_explore(struct usb_bus *bus, uint8_t do_probe) { - uint8_t do_unlock; - DPRINTF("\n"); if (cold != 0) { @@ -2285,22 +2273,11 @@ DPRINTF("No root HUB\n"); return; } - if (mtx_owned(&bus->bus_mtx)) { - do_unlock = 0; - } else { - USB_BUS_LOCK(bus); - do_unlock = 1; - } + if (do_probe) { bus->do_probe = 1; } - if (usb_proc_msignal(USB_BUS_EXPLORE_PROC(bus), - &bus->explore_msg[0], &bus->explore_msg[1])) { - /* ignore */ - } - if (do_unlock) { - USB_BUS_UNLOCK(bus); - } + usb_proc_msignal(USB_BUS_EXPLORE_PROC(bus), &bus->explore_msg); } /*------------------------------------------------------------------------* diff --git a/sys/dev/usb/usb_process.h b/sys/dev/usb/usb_process.h --- a/sys/dev/usb/usb_process.h +++ b/sys/dev/usb/usb_process.h @@ -29,8 +29,10 @@ #define _USB_PROCESS_H_ #ifndef USB_GLOBAL_INCLUDE_FILE +#include #include #include +#include #endif /* defines */ @@ -51,21 +53,8 @@ * The following structure defines the USB process. */ struct usb_process { - TAILQ_HEAD(, usb_proc_msg) up_qhead; - struct cv up_cv; - struct cv up_drain; - - struct thread *up_ptr; - struct thread *up_curtd; + struct taskqueue *tq; struct mtx *up_mtx; - - usb_size_t up_msg_num; - - uint8_t up_prio; - uint8_t up_gone; - uint8_t up_msleep; - uint8_t up_csleep; - uint8_t up_dsleep; }; /* prototypes */ @@ -74,15 +63,14 @@ int usb_proc_create(struct usb_process *up, struct mtx *p_mtx, const char *pmesg, uint8_t prio); void usb_proc_drain(struct usb_process *up); -void usb_proc_mwait(struct usb_process *up, void *pm0, void *pm1); -int usb_proc_mwait_sig(struct usb_process *up, void *pm0, void *pm1); +void usb_proc_mwait(struct usb_process *up, struct usb_proc_msg *msg); void usb_proc_free(struct usb_process *up); -void *usb_proc_msignal(struct usb_process *up, void *pm0, void *pm1); +void usb_proc_msignal(struct usb_process *up, struct usb_proc_msg *msg); +int usb_proc_msignal_pending(struct usb_process *up, struct usb_proc_msg *msg); void usb_proc_rewakeup(struct usb_process *up); -int usb_proc_is_called_from(struct usb_process *up); -void usb_proc_explore_mwait(struct usb_device *, void *, void *); -void *usb_proc_explore_msignal(struct usb_device *, void *, void *); +void usb_proc_explore_mwait(struct usb_device *, struct usb_proc_msg *); +void usb_proc_explore_msignal(struct usb_device *, struct usb_proc_msg *); void usb_proc_explore_lock(struct usb_device *); void usb_proc_explore_unlock(struct usb_device *); diff --git a/sys/dev/usb/usb_process.c b/sys/dev/usb/usb_process.c --- a/sys/dev/usb/usb_process.c +++ b/sys/dev/usb/usb_process.c @@ -42,6 +42,7 @@ #include #include #include +#include #include #include #include @@ -61,11 +62,8 @@ #include #endif /* USB_GLOBAL_INCLUDE_FILE */ -static struct proc *usbproc; static int usb_pcount; -#define USB_THREAD_CREATE(f, s, p, ...) \ - kproc_kthread_add((f), (s), &usbproc, (p), RFHIGHPID, \ - 0, "usb", __VA_ARGS__) + #define USB_THREAD_SUSPEND_CHECK() kthread_suspend_check() #define USB_THREAD_SUSPEND(p) kthread_suspend(p,0) #define USB_THREAD_EXIT(err) kthread_exit() @@ -79,114 +77,6 @@ "Debug level"); #endif -/*------------------------------------------------------------------------* - * usb_process - * - * This function is the USB process dispatcher. - *------------------------------------------------------------------------*/ -static void -usb_process(void *arg) -{ - struct usb_process *up = arg; - struct usb_proc_msg *pm; - struct thread *td; - - /* in case of attach error, check for suspended */ - USB_THREAD_SUSPEND_CHECK(); - - /* adjust priority */ - td = curthread; - thread_lock(td); - sched_prio(td, up->up_prio); - thread_unlock(td); - - USB_MTX_LOCK(up->up_mtx); - - up->up_curtd = td; - - while (1) { - if (up->up_gone) - break; - - /* - * NOTE to reimplementors: dequeueing a command from the - * "used" queue and executing it must be atomic, with regard - * to the "up_mtx" mutex. That means any attempt to queue a - * command by another thread must be blocked until either: - * - * 1) the command sleeps - * - * 2) the command returns - * - * Here is a practical example that shows how this helps - * solving a problem: - * - * Assume that you want to set the baud rate on a USB serial - * device. During the programming of the device you don't - * want to receive nor transmit any data, because it will be - * garbage most likely anyway. The programming of our USB - * device takes 20 milliseconds and it needs to call - * functions that sleep. - * - * Non-working solution: Before we queue the programming - * command, we stop transmission and reception of data. Then - * we queue a programming command. At the end of the - * programming command we enable transmission and reception - * of data. - * - * Problem: If a second programming command is queued while the - * first one is sleeping, we end up enabling transmission - * and reception of data too early. - * - * Working solution: Before we queue the programming command, - * we stop transmission and reception of data. Then we queue - * a programming command. Then we queue a second command - * that only enables transmission and reception of data. - * - * Why it works: If a second programming command is queued - * while the first one is sleeping, then the queueing of a - * second command to enable the data transfers, will cause - * the previous one, which is still on the queue, to be - * removed from the queue, and re-inserted after the last - * baud rate programming command, which then gives the - * desired result. - */ - pm = TAILQ_FIRST(&up->up_qhead); - - if (pm) { - DPRINTF("Message pm=%p, cb=%p (enter)\n", - pm, pm->pm_callback); - - (pm->pm_callback) (pm); - - if (pm == TAILQ_FIRST(&up->up_qhead)) { - /* nothing changed */ - TAILQ_REMOVE(&up->up_qhead, pm, pm_qentry); - pm->pm_qentry.tqe_prev = NULL; - } - DPRINTF("Message pm=%p (leave)\n", pm); - - continue; - } - /* end of messages - check if anyone is waiting for sync */ - if (up->up_dsleep) { - up->up_dsleep = 0; - cv_broadcast(&up->up_drain); - } - up->up_msleep = 1; - cv_wait(&up->up_cv, up->up_mtx); - } - - up->up_ptr = NULL; - cv_signal(&up->up_cv); - USB_MTX_UNLOCK(up->up_mtx); - /* Clear the proc pointer if this is the last thread. */ - if (--usb_pcount == 0) - usbproc = NULL; - - USB_THREAD_EXIT(0); -} - /*------------------------------------------------------------------------* * usb_proc_create * @@ -205,19 +95,16 @@ const char *pmesg, uint8_t prio) { up->up_mtx = p_mtx; - up->up_prio = prio; - - TAILQ_INIT(&up->up_qhead); - - cv_init(&up->up_cv, "-"); - cv_init(&up->up_drain, "usbdrain"); - - if (USB_THREAD_CREATE(&usb_process, up, - &up->up_ptr, "%s", pmesg)) { + if ((up->tq = taskqueue_create(pmesg, M_WAITOK, + &taskqueue_thread_enqueue, &up->tq)) == NULL) { + DPRINTFN(0, "Unable to create taskqueue"); + goto error; + } + if (taskqueue_start_threads(&up->tq, 1, prio, "%s taskq", pmesg) != 0) { DPRINTFN(0, "Unable to create USB process."); - up->up_ptr = NULL; goto error; } + usb_pcount++; return (0); @@ -238,17 +125,12 @@ void usb_proc_free(struct usb_process *up) { - /* check if not initialised */ - if (up->up_mtx == NULL) + if (up->tq == NULL) return; - - usb_proc_drain(up); - - cv_destroy(&up->up_cv); - cv_destroy(&up->up_drain); - - /* make sure that we do not enter here again */ - up->up_mtx = NULL; + taskqueue_drain_all(up->tq); + taskqueue_free(up->tq); + up->tq = NULL; + usb_pcount--; } /*------------------------------------------------------------------------* @@ -262,81 +144,17 @@ * function exploits the fact that a process can only do one callback * at a time. The message that was queued is returned. *------------------------------------------------------------------------*/ -void * -usb_proc_msignal(struct usb_process *up, void *_pm0, void *_pm1) +void +usb_proc_msignal(struct usb_process *up, struct usb_proc_msg *msg) { - struct usb_proc_msg *pm0 = _pm0; - struct usb_proc_msg *pm1 = _pm1; - struct usb_proc_msg *pm2; - usb_size_t d; - uint8_t t; - - /* check if gone or in polling mode, return dummy value */ - if (up->up_gone != 0 || - USB_IN_POLLING_MODE_FUNC() != 0) - return (_pm0); - - USB_MTX_ASSERT(up->up_mtx, MA_OWNED); - - t = 0; - - if (pm0->pm_qentry.tqe_prev) { - t |= 1; - } - if (pm1->pm_qentry.tqe_prev) { - t |= 2; - } - if (t == 0) { - /* - * No entries are queued. Queue "pm0" and use the existing - * message number. - */ - pm2 = pm0; - } else if (t == 1) { - /* Check if we need to increment the message number. */ - if (pm0->pm_num == up->up_msg_num) { - up->up_msg_num++; - } - pm2 = pm1; - } else if (t == 2) { - /* Check if we need to increment the message number. */ - if (pm1->pm_num == up->up_msg_num) { - up->up_msg_num++; - } - pm2 = pm0; - } else if (t == 3) { - /* - * Both entries are queued. Re-queue the entry closest to - * the end. - */ - d = (pm1->pm_num - pm0->pm_num); - - /* Check sign after subtraction */ - if (d & 0x80000000) { - pm2 = pm0; - } else { - pm2 = pm1; - } - - TAILQ_REMOVE(&up->up_qhead, pm2, pm_qentry); - } else { - pm2 = NULL; /* panic - should not happen */ - } - - DPRINTF(" t=%u, num=%u\n", t, up->up_msg_num); - - /* Put message last on queue */ - - pm2->pm_num = up->up_msg_num; - TAILQ_INSERT_TAIL(&up->up_qhead, pm2, pm_qentry); - - /* Check if we need to wakeup the USB process. */ + taskqueue_enqueue(up->tq, &msg->task); +} - if (up->up_msleep) { - up->up_msleep = 0; /* save "cv_signal()" calls */ - cv_signal(&up->up_cv); - } - return (pm2); +int +usb_proc_msignal_pending(struct usb_process *up, struct usb_proc_msg *msg) +{ + return (taskqueue_enqueue_flags(up->tq, &msg->task, + TASKQUEUE_FAIL_IF_PENDING)); } /*------------------------------------------------------------------------* @@ -349,97 +167,19 @@ uint8_t usb_proc_is_gone(struct usb_process *up) { - if (up->up_gone) - return (1); - - /* - * Allow calls when up_mtx is NULL, before the USB process - * structure is initialised. - */ - if (up->up_mtx != NULL) - USB_MTX_ASSERT(up->up_mtx, MA_OWNED); - return (0); -} - -static int -usb_proc_mwait_impl(struct usb_process *up, void *_pm0, void *_pm1, - bool interruptible) -{ - struct usb_proc_msg *pm0 = _pm0; - struct usb_proc_msg *pm1 = _pm1; - int error; - - /* check if gone */ - if (up->up_gone) - return (ENXIO); - - USB_MTX_ASSERT(up->up_mtx, MA_OWNED); - - error = 0; - if (up->up_curtd == curthread) { - /* Just remove the messages from the queue. */ - if (pm0->pm_qentry.tqe_prev) { - TAILQ_REMOVE(&up->up_qhead, pm0, pm_qentry); - pm0->pm_qentry.tqe_prev = NULL; - } - if (pm1->pm_qentry.tqe_prev) { - TAILQ_REMOVE(&up->up_qhead, pm1, pm_qentry); - pm1->pm_qentry.tqe_prev = NULL; - } - } else - while (error == 0 && (pm0->pm_qentry.tqe_prev || - pm1->pm_qentry.tqe_prev)) { - /* check if config thread is gone */ - if (up->up_gone) - return (ENXIO); - up->up_dsleep = 1; - if (interruptible) { - error = cv_wait_sig(&up->up_drain, up->up_mtx); - - /* - * The fact that we were interrupted doesn't - * matter if our goal was accomplished anyways. - */ - if (error != 0 && !USB_PROC_MSG_ENQUEUED(pm0) && - !USB_PROC_MSG_ENQUEUED(pm1)) - error = 0; - } else { - cv_wait(&up->up_drain, up->up_mtx); - } - } - - if (error == ERESTART) - error = EINTR; - return (error); + return (up->tq == NULL); } /*------------------------------------------------------------------------* * usb_proc_mwait * * This function will return when the USB process message pointed to - * by "pm" is no longer on a queue. This function must be called - * having "up->up_mtx" locked. + * by "pm" is no longer on a queue. *------------------------------------------------------------------------*/ void -usb_proc_mwait(struct usb_process *up, void *_pm0, void *_pm1) -{ - - (void)usb_proc_mwait_impl(up, _pm0, _pm1, false); -} - -/*------------------------------------------------------------------------* - * usb_proc_mwait_sig - * - * This function will return when the USB process message pointed to - * by "pm" is no longer on a queue. This function must be called - * having "up->up_mtx" locked. This version of usb_proc_mwait is - * interruptible. - *------------------------------------------------------------------------*/ -int -usb_proc_mwait_sig(struct usb_process *up, void *_pm0, void *_pm1) +usb_proc_mwait(struct usb_process *up, struct usb_proc_msg *msg) { - - return (usb_proc_mwait_impl(up, _pm0, _pm1, true)); + taskqueue_drain(up->tq, &msg->task); } /*------------------------------------------------------------------------* @@ -454,47 +194,7 @@ void usb_proc_drain(struct usb_process *up) { - /* check if not initialised */ - if (up->up_mtx == NULL) - return; - /* handle special case with Giant */ - if (up->up_mtx != &Giant) - USB_MTX_ASSERT(up->up_mtx, MA_NOTOWNED); - - USB_MTX_LOCK(up->up_mtx); - - /* Set the gone flag */ - - up->up_gone = 1; - - while (up->up_ptr) { - /* Check if we need to wakeup the USB process */ - - if (up->up_msleep || up->up_csleep) { - up->up_msleep = 0; - up->up_csleep = 0; - cv_signal(&up->up_cv); - } -#ifndef EARLY_AP_STARTUP - /* Check if we are still cold booted */ - if (cold) { - USB_THREAD_SUSPEND(up->up_ptr); - printf("WARNING: A USB process has " - "been left suspended\n"); - break; - } -#endif - cv_wait(&up->up_cv, up->up_mtx); - } - /* Check if someone is waiting - should not happen */ - - if (up->up_dsleep) { - up->up_dsleep = 0; - cv_broadcast(&up->up_drain); - DPRINTF("WARNING: Someone is waiting " - "for USB process drain!\n"); - } - USB_MTX_UNLOCK(up->up_mtx); + taskqueue_drain_all(up->tq); } /*------------------------------------------------------------------------* @@ -508,29 +208,7 @@ void usb_proc_rewakeup(struct usb_process *up) { - /* check if not initialised */ - if (up->up_mtx == NULL) + if (up->tq == NULL) return; - /* check if gone */ - if (up->up_gone) - return; - - USB_MTX_ASSERT(up->up_mtx, MA_OWNED); - - if (up->up_msleep == 0) { - /* re-wakeup */ - cv_signal(&up->up_cv); - } -} - -/*------------------------------------------------------------------------* - * usb_proc_is_called_from - * - * This function will return non-zero if called from inside the USB - * process passed as first argument. Else this function returns zero. - *------------------------------------------------------------------------*/ -int -usb_proc_is_called_from(struct usb_process *up) -{ - return (up->up_curtd == curthread); + taskqueue_unblock(up->tq); } diff --git a/sys/dev/usb/usb_transfer.h b/sys/dev/usb/usb_transfer.h --- a/sys/dev/usb/usb_transfer.h +++ b/sys/dev/usb/usb_transfer.h @@ -39,15 +39,6 @@ * which is done asynchronously and grows the statemachine. */ -/* - * The following structure defines the messages that is used to signal - * the "done_p" USB process. - */ -struct usb_done_msg { - struct usb_proc_msg hdr; - struct usb_xfer_root *xroot; -}; - #define USB_DMATAG_TO_XROOT(dpt) \ __containerof(dpt, struct usb_xfer_root, dma_parent_tag) @@ -62,7 +53,7 @@ struct usb_xfer_queue dma_q; #endif struct usb_xfer_queue done_q; - struct usb_done_msg done_m[2]; + struct usb_proc_msg done_m; struct cv cv_drain; struct usb_process *done_p; /* pointer to callback process */ diff --git a/sys/dev/usb/usb_transfer.c b/sys/dev/usb/usb_transfer.c --- a/sys/dev/usb/usb_transfer.c +++ b/sys/dev/usb/usb_transfer.c @@ -136,7 +136,7 @@ static void usbd_transfer_unsetup_sub(struct usb_xfer_root *, uint8_t); static void usbd_control_transfer_init(struct usb_xfer *); static int usbd_setup_ctrl_transfer(struct usb_xfer *); -static void usb_callback_proc(struct usb_proc_msg *); +static void usb_callback_proc(void *); static void usbd_callback_ss_done_defer(struct usb_xfer *); static void usbd_callback_wrapper(struct usb_xfer_queue *); static void usbd_transfer_start_cb(void *); @@ -1092,11 +1092,8 @@ TAILQ_INIT(&info->dma_q.head); info->dma_q.command = &usb_bdma_work_loop; #endif - info->done_m[0].hdr.pm_callback = &usb_callback_proc; - info->done_m[0].xroot = info; - info->done_m[1].hdr.pm_callback = &usb_callback_proc; - info->done_m[1].xroot = info; - + USB_PROC_MSG_INIT(&info->done_m, 0, usb_callback_proc, + info); /* * In device side mode control endpoint * requests need to run from a separate @@ -1386,10 +1383,9 @@ } } - /* make sure that our done messages are not queued anywhere */ - usb_proc_mwait(info->done_p, &info->done_m[0], &info->done_m[1]); - USB_BUS_UNLOCK(info->bus); + /* make sure that our done messages are not queued anywhere */ + usb_proc_mwait(info->done_p, &info->done_m); #if USB_HAVE_BUSDMA /* free DMA'able memory, if any */ @@ -2326,13 +2322,9 @@ * This function performs USB callbacks. *------------------------------------------------------------------------*/ static void -usb_callback_proc(struct usb_proc_msg *_pm) +usb_callback_proc(void *ctx) { - struct usb_done_msg *pm = (void *)_pm; - struct usb_xfer_root *info = pm->xroot; - - /* Change locking order */ - USB_BUS_UNLOCK(info->bus); + struct usb_xfer_root *info = ctx; /* * We exploit the fact that the mutex is the same for all @@ -2345,6 +2337,7 @@ usb_command_wrapper(&info->done_q, info->done_q.curr); + USB_BUS_UNLOCK(info->bus); USB_MTX_UNLOCK(info->xfer_mtx); } @@ -2371,8 +2364,7 @@ * will have a Lock Order Reversal, LOR, if we try to * proceed ! */ - (void) usb_proc_msignal(info->done_p, - &info->done_m[0], &info->done_m[1]); + (void)usb_proc_msignal(info->done_p, &info->done_m); } else { /* clear second recurse flag */ pq->recurse_2 = 0; @@ -2414,8 +2406,7 @@ * Postponing the callback also ensures that other USB * transfer queues get a chance. */ - (void) usb_proc_msignal(info->done_p, - &info->done_m[0], &info->done_m[1]); + usb_proc_msignal(info->done_p, &info->done_m); return; } /* @@ -2843,9 +2834,8 @@ udev, ep, &did_stall); } else if (udev->ctrl_xfer[1]) { info = udev->ctrl_xfer[1]->xroot; - usb_proc_msignal( - USB_BUS_CS_PROC(info->bus), - &udev->cs_msg[0], &udev->cs_msg[1]); + usb_proc_msignal(USB_BUS_CS_PROC(info->bus), + &udev->cs_msg); } else { /* should not happen */ DPRINTFN(0, "No stall handler\n"); @@ -3429,7 +3419,7 @@ struct usb_xfer *xfer; struct usb_xfer_root *xroot; struct usb_device *udev; - struct usb_proc_msg *pm; + struct task *task; struct usb_bus *bus; uint16_t n; uint16_t drop_bus_spin; @@ -3479,13 +3469,6 @@ } } - /* Make sure cv_signal() and cv_broadcast() is not called */ - USB_BUS_CONTROL_XFER_PROC(bus)->up_msleep = 0; - USB_BUS_EXPLORE_PROC(bus)->up_msleep = 0; - USB_BUS_GIANT_PROC(bus)->up_msleep = 0; - USB_BUS_NON_GIANT_ISOC_PROC(bus)->up_msleep = 0; - USB_BUS_NON_GIANT_BULK_PROC(bus)->up_msleep = 0; - /* poll USB hardware */ (bus->methods->xfer_poll) (bus); @@ -3494,17 +3477,16 @@ /* check for clear stall */ if (udev->ctrl_xfer[1] != NULL) { /* poll clear stall start */ - pm = &udev->cs_msg[0].hdr; - (pm->pm_callback) (pm); + task = &udev->cs_msg.task; + (task->ta_func)(task->ta_context, 0); /* poll clear stall done thread */ - pm = &udev->ctrl_xfer[1]-> - xroot->done_m[0].hdr; - (pm->pm_callback) (pm); + task = &udev->ctrl_xfer[1]->xroot->done_m.task; + (task->ta_func)(task->ta_context, 0); } /* poll done thread */ - pm = &xroot->done_m[0].hdr; - (pm->pm_callback) (pm); + task = &xroot->done_m.task; + (task->ta_func)(task->ta_context, 0); USB_BUS_UNLOCK(xroot->bus); diff --git a/sys/dev/usb/usbdi.h b/sys/dev/usb/usbdi.h --- a/sys/dev/usb/usbdi.h +++ b/sys/dev/usb/usbdi.h @@ -91,7 +91,7 @@ /* typedefs */ typedef void (usb_callback_t)(struct usb_xfer *, usb_error_t); -typedef void (usb_proc_callback_t)(struct usb_proc_msg *); +typedef void(usb_proc_callback_t)(void *); typedef usb_error_t (usb_handle_req_t)(struct usb_device *, struct usb_device_request *, const void **, uint16_t *); @@ -520,13 +520,16 @@ /* * The following structure defines the USB process message header. */ +#ifndef USB_GLOBAL_INCLUDE_FILE +#include +#endif + struct usb_proc_msg { - TAILQ_ENTRY(usb_proc_msg) pm_qentry; - usb_proc_callback_t *pm_callback; - usb_size_t pm_num; + struct task task; }; -#define USB_PROC_MSG_ENQUEUED(msg) ((msg)->pm_qentry.tqe_prev != NULL) +#define USB_PROC_MSG_INIT(msg, prio, func, context) \ + TASK_INIT(&((msg)->task), prio, (task_fn_t *)func, context) #define USB_FIFO_TX 0 #define USB_FIFO_RX 1