Module Name: src Committed By: martin Date: Wed Aug 8 10:28:35 UTC 2018
Modified Files: src/sys/dev/usb [netbsd-8]: if_athn_usb.c if_atu.c if_aue.c if_axe.c if_axen.c if_cue.c if_otus.c if_rum.c if_run.c if_smsc.c if_udav.c if_upgt.c if_ural.c if_url.c if_urtw.c if_urtwn.c if_zyd.c uatp.c umcs.c usb.c usb_subr.c usbdi.h Log Message: Pull up following revision(s) (requested by riastradh in ticket #963): sys/dev/usb/if_cue.c: revision 1.80 sys/dev/usb/umcs.c: revision 1.11 sys/dev/usb/umcs.c: revision 1.12 sys/dev/usb/if_ural.c: revision 1.56 sys/dev/usb/if_run.c: revision 1.28 sys/dev/usb/if_ural.c: revision 1.57 sys/dev/usb/if_run.c: revision 1.29 sys/dev/usb/uatp.c: revision 1.16 sys/dev/usb/uatp.c: revision 1.17 sys/dev/usb/if_axe.c: revision 1.91 sys/dev/usb/if_axe.c: revision 1.92 sys/dev/usb/if_zyd.c: revision 1.49 sys/dev/usb/if_axen.c: revision 1.15 sys/dev/usb/if_url.c: revision 1.60 sys/dev/usb/if_udav.c: revision 1.54 sys/dev/usb/if_axen.c: revision 1.16 sys/dev/usb/if_udav.c: revision 1.55 sys/dev/usb/if_athn_usb.c: revision 1.28 sys/dev/usb/if_athn_usb.c: revision 1.29 sys/dev/usb/if_urtw.c: revision 1.16 sys/dev/usb/if_urtw.c: revision 1.17 sys/dev/usb/if_cue.c: revision 1.79 sys/dev/usb/if_rum.c: revision 1.62 sys/dev/usb/if_urtwn.c: revision 1.61 sys/dev/usb/if_rum.c: revision 1.63 sys/dev/usb/if_urtwn.c: revision 1.63 sys/dev/usb/usb.c: revision 1.170 sys/dev/usb/usb.c: revision 1.171 sys/dev/usb/if_smsc.c: revision 1.35 sys/dev/usb/if_smsc.c: revision 1.36 sys/dev/usb/if_zyd.c: revision 1.50 sys/dev/usb/if_aue.c: revision 1.144 sys/dev/usb/if_aue.c: revision 1.145 sys/dev/usb/usb_subr.c: revision 1.225 sys/dev/usb/usb_subr.c: revision 1.226 sys/dev/usb/if_upgt.c: revision 1.21 sys/dev/usb/usbdi.h: revision 1.93 sys/dev/usb/if_upgt.c: revision 1.22 sys/dev/usb/if_url.c: revision 1.59 sys/dev/usb/usbdi.h: revision 1.95 sys/dev/usb/if_otus.c: revision 1.34 sys/dev/usb/if_atu.c: revision 1.62 sys/dev/usb/if_otus.c: revision 1.35 sys/dev/usb/if_atu.c: revision 1.63 New function usb_rem_task_wait(dev, task, queue). If task is scheduled to run, removes it from the queue. If it may have already begun to run, waits for it to complete. Caller must guarantee it will not switch to another queue. If caller guarantees it will not be scheduled again, then usb_rem_task_wait guarantees it is not running on return. This will enable us to fix a litany of bugs in detach where we currently fail to wait for a pending task. Use usb_rem_task_wait in various drivers. To generate a diff of this commit: cvs rdiff -u -r1.22.2.2 -r1.22.2.3 src/sys/dev/usb/if_athn_usb.c cvs rdiff -u -r1.55.8.2 -r1.55.8.3 src/sys/dev/usb/if_atu.c cvs rdiff -u -r1.141.8.1 -r1.141.8.2 src/sys/dev/usb/if_aue.c cvs rdiff -u -r1.82.6.3 -r1.82.6.4 src/sys/dev/usb/if_axe.c cvs rdiff -u -r1.11.8.1 -r1.11.8.2 src/sys/dev/usb/if_axen.c cvs rdiff -u -r1.76.8.1 -r1.76.8.2 src/sys/dev/usb/if_cue.c cvs rdiff -u -r1.31.2.1 -r1.31.2.2 src/sys/dev/usb/if_otus.c cvs rdiff -u -r1.58.2.1 -r1.58.2.2 src/sys/dev/usb/if_rum.c cvs rdiff -u -r1.22.2.1 -r1.22.2.2 src/sys/dev/usb/if_run.c cvs rdiff -u -r1.30.8.1 -r1.30.8.2 src/sys/dev/usb/if_smsc.c cvs rdiff -u -r1.51.8.1 -r1.51.8.2 src/sys/dev/usb/if_udav.c cvs rdiff -u -r1.17.8.1 -r1.17.8.2 src/sys/dev/usb/if_upgt.c cvs rdiff -u -r1.51.8.2 -r1.51.8.3 src/sys/dev/usb/if_ural.c cvs rdiff -u -r1.56.8.1 -r1.56.8.2 src/sys/dev/usb/if_url.c cvs rdiff -u -r1.13.8.1 -r1.13.8.2 src/sys/dev/usb/if_urtw.c cvs rdiff -u -r1.53.2.3 -r1.53.2.4 src/sys/dev/usb/if_urtwn.c cvs rdiff -u -r1.44.2.1 -r1.44.2.2 src/sys/dev/usb/if_zyd.c cvs rdiff -u -r1.14 -r1.14.6.1 src/sys/dev/usb/uatp.c cvs rdiff -u -r1.10 -r1.10.10.1 src/sys/dev/usb/umcs.c cvs rdiff -u -r1.165.6.2 -r1.165.6.3 src/sys/dev/usb/usb.c cvs rdiff -u -r1.220.2.2 -r1.220.2.3 src/sys/dev/usb/usb_subr.c cvs rdiff -u -r1.92 -r1.92.8.1 src/sys/dev/usb/usbdi.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/dev/usb/if_athn_usb.c diff -u src/sys/dev/usb/if_athn_usb.c:1.22.2.2 src/sys/dev/usb/if_athn_usb.c:1.22.2.3 --- src/sys/dev/usb/if_athn_usb.c:1.22.2.2 Wed Jan 31 18:01:54 2018 +++ src/sys/dev/usb/if_athn_usb.c Wed Aug 8 10:28:35 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: if_athn_usb.c,v 1.22.2.2 2018/01/31 18:01:54 martin Exp $ */ +/* $NetBSD: if_athn_usb.c,v 1.22.2.3 2018/08/08 10:28:35 martin Exp $ */ /* $OpenBSD: if_athn_usb.c,v 1.12 2013/01/14 09:50:31 jsing Exp $ */ /*- @@ -22,7 +22,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if_athn_usb.c,v 1.22.2.2 2018/01/31 18:01:54 martin Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_athn_usb.c,v 1.22.2.3 2018/08/08 10:28:35 martin Exp $"); #ifdef _KERNEL_OPT #include "opt_inet.h" @@ -334,7 +334,8 @@ athn_usb_attach(device_t parent, device_ athn_usb_free_tx_cmd(usc); athn_usb_free_tx_msg(usc); athn_usb_close_pipes(usc); - usb_rem_task(usc->usc_udev, &usc->usc_task); + usb_rem_task_wait(usc->usc_udev, &usc->usc_task, USB_TASKQ_DRIVER, + NULL); cv_destroy(&usc->usc_cmd_cv); cv_destroy(&usc->usc_msg_cv); @@ -500,7 +501,8 @@ athn_usb_detach(device_t self, int flags athn_usb_wait_async(usc); - usb_rem_task(usc->usc_udev, &usc->usc_task); + usb_rem_task_wait(usc->usc_udev, &usc->usc_task, USB_TASKQ_DRIVER, + NULL); /* Abort Tx/Rx pipes. */ athn_usb_abort_pipes(usc); Index: src/sys/dev/usb/if_atu.c diff -u src/sys/dev/usb/if_atu.c:1.55.8.2 src/sys/dev/usb/if_atu.c:1.55.8.3 --- src/sys/dev/usb/if_atu.c:1.55.8.2 Thu Jul 26 23:55:30 2018 +++ src/sys/dev/usb/if_atu.c Wed Aug 8 10:28:35 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: if_atu.c,v 1.55.8.2 2018/07/26 23:55:30 snj Exp $ */ +/* $NetBSD: if_atu.c,v 1.55.8.3 2018/08/08 10:28:35 martin Exp $ */ /* $OpenBSD: if_atu.c,v 1.48 2004/12/30 01:53:21 dlg Exp $ */ /* * Copyright (c) 2003, 2004 @@ -48,7 +48,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if_atu.c,v 1.55.8.2 2018/07/26 23:55:30 snj Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_atu.c,v 1.55.8.3 2018/08/08 10:28:35 martin Exp $"); #ifdef _KERNEL_OPT #include "opt_usb.h" @@ -2239,7 +2239,7 @@ atu_stop(struct ifnet *ifp, int disable) ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); ifp->if_timer = 0; - usb_rem_task(sc->atu_udev, &sc->sc_task); + usb_rem_task_wait(sc->atu_udev, &sc->sc_task, USB_TASKQ_DRIVER, NULL); ieee80211_new_state(ic, IEEE80211_S_INIT, -1); /* Stop transfers. */ Index: src/sys/dev/usb/if_aue.c diff -u src/sys/dev/usb/if_aue.c:1.141.8.1 src/sys/dev/usb/if_aue.c:1.141.8.2 --- src/sys/dev/usb/if_aue.c:1.141.8.1 Wed Jan 31 18:01:55 2018 +++ src/sys/dev/usb/if_aue.c Wed Aug 8 10:28:35 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: if_aue.c,v 1.141.8.1 2018/01/31 18:01:55 martin Exp $ */ +/* $NetBSD: if_aue.c,v 1.141.8.2 2018/08/08 10:28:35 martin Exp $ */ /* * Copyright (c) 1997, 1998, 1999, 2000 @@ -78,7 +78,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if_aue.c,v 1.141.8.1 2018/01/31 18:01:55 martin Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_aue.c,v 1.141.8.2 2018/08/08 10:28:35 martin Exp $"); #ifdef _KERNEL_OPT #include "opt_usb.h" @@ -886,13 +886,18 @@ aue_detach(device_t self, int flags) return 0; } - callout_stop(&sc->aue_stat_ch); /* - * Remove any pending tasks. They cannot be executing because they run - * in the same thread as detach. + * XXX Halting callout guarantees no more tick tasks. What + * guarantees no more stop tasks? What guarantees no more + * calls to aue_send? Don't we need to wait for if_detach or + * something? Should we set sc->aue_dying here? Is device + * deactivation guaranteed to have already happened? */ - usb_rem_task(sc->aue_udev, &sc->aue_tick_task); - usb_rem_task(sc->aue_udev, &sc->aue_stop_task); + callout_halt(&sc->aue_stat_ch, NULL); + usb_rem_task_wait(sc->aue_udev, &sc->aue_tick_task, USB_TASKQ_DRIVER, + NULL); + usb_rem_task_wait(sc->aue_udev, &sc->aue_stop_task, USB_TASKQ_DRIVER, + NULL); sc->aue_closing = 1; cv_signal(&sc->aue_domc); Index: src/sys/dev/usb/if_axe.c diff -u src/sys/dev/usb/if_axe.c:1.82.6.3 src/sys/dev/usb/if_axe.c:1.82.6.4 --- src/sys/dev/usb/if_axe.c:1.82.6.3 Mon May 7 13:26:03 2018 +++ src/sys/dev/usb/if_axe.c Wed Aug 8 10:28:35 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: if_axe.c,v 1.82.6.3 2018/05/07 13:26:03 martin Exp $ */ +/* $NetBSD: if_axe.c,v 1.82.6.4 2018/08/08 10:28:35 martin Exp $ */ /* $OpenBSD: if_axe.c,v 1.137 2016/04/13 11:03:37 mpi Exp $ */ /* @@ -87,7 +87,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if_axe.c,v 1.82.6.3 2018/05/07 13:26:03 martin Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_axe.c,v 1.82.6.4 2018/08/08 10:28:35 martin Exp $"); #ifdef _KERNEL_OPT #include "opt_inet.h" @@ -1111,11 +1111,9 @@ axe_detach(device_t self, int flags) if (sc->axe_ep[AXE_ENDPT_INTR] != NULL) usbd_abort_pipe(sc->axe_ep[AXE_ENDPT_INTR]); - /* - * Remove any pending tasks. They cannot be executing because they run - * in the same thread as detach. - */ - usb_rem_task(sc->axe_udev, &sc->axe_tick_task); + callout_halt(&sc->axe_stat_ch, NULL); + usb_rem_task_wait(sc->axe_udev, &sc->axe_tick_task, USB_TASKQ_DRIVER, + NULL); s = splusb(); Index: src/sys/dev/usb/if_axen.c diff -u src/sys/dev/usb/if_axen.c:1.11.8.1 src/sys/dev/usb/if_axen.c:1.11.8.2 --- src/sys/dev/usb/if_axen.c:1.11.8.1 Wed Jan 31 18:01:54 2018 +++ src/sys/dev/usb/if_axen.c Wed Aug 8 10:28:35 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: if_axen.c,v 1.11.8.1 2018/01/31 18:01:54 martin Exp $ */ +/* $NetBSD: if_axen.c,v 1.11.8.2 2018/08/08 10:28:35 martin Exp $ */ /* $OpenBSD: if_axen.c,v 1.3 2013/10/21 10:10:22 yuo Exp $ */ /* @@ -23,7 +23,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if_axen.c,v 1.11.8.1 2018/01/31 18:01:54 martin Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_axen.c,v 1.11.8.2 2018/08/08 10:28:35 martin Exp $"); #ifdef _KERNEL_OPT #include "opt_inet.h" @@ -826,11 +826,9 @@ axen_detach(device_t self, int flags) sc->axen_dying = true; - /* - * Remove any pending tasks. They cannot be executing because they run - * in the same thread as detach. - */ - usb_rem_task(sc->axen_udev, &sc->axen_tick_task); + callout_halt(&sc->axen_stat_ch, NULL); + usb_rem_task_wait(sc->axen_udev, &sc->axen_tick_task, + USB_TASKQ_DRIVER, NULL); s = splusb(); Index: src/sys/dev/usb/if_cue.c diff -u src/sys/dev/usb/if_cue.c:1.76.8.1 src/sys/dev/usb/if_cue.c:1.76.8.2 --- src/sys/dev/usb/if_cue.c:1.76.8.1 Wed Jan 31 18:01:54 2018 +++ src/sys/dev/usb/if_cue.c Wed Aug 8 10:28:35 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: if_cue.c,v 1.76.8.1 2018/01/31 18:01:54 martin Exp $ */ +/* $NetBSD: if_cue.c,v 1.76.8.2 2018/08/08 10:28:35 martin Exp $ */ /* * Copyright (c) 1997, 1998, 1999, 2000 * Bill Paul <wp...@ee.columbia.edu>. All rights reserved. @@ -56,7 +56,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if_cue.c,v 1.76.8.1 2018/01/31 18:01:54 martin Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_cue.c,v 1.76.8.2 2018/08/08 10:28:35 martin Exp $"); #ifdef _KERNEL_OPT #include "opt_inet.h" @@ -571,13 +571,18 @@ cue_detach(device_t self, int flags) DPRINTFN(2,("%s: %s: enter\n", device_xname(sc->cue_dev), __func__)); - callout_stop(&sc->cue_stat_ch); /* - * Remove any pending task. It cannot be executing because it run - * in the same thread as detach. + * XXX Halting callout guarantees no more tick tasks. What + * guarantees no more stop tasks? What guarantees no more + * calls to cue_send? Don't we need to wait for if_detach or + * something? Should we set sc->cue_dying here? Is device + * deactivation guaranteed to have already happened? */ - usb_rem_task(sc->cue_udev, &sc->cue_tick_task); - usb_rem_task(sc->cue_udev, &sc->cue_stop_task); + callout_halt(&sc->cue_stat_ch, NULL); + usb_rem_task_wait(sc->cue_udev, &sc->cue_tick_task, USB_TASKQ_DRIVER, + NULL); + usb_rem_task_wait(sc->cue_udev, &sc->cue_stop_task, USB_TASKQ_DRIVER, + NULL); if (!sc->cue_attached) { /* Detached before attached finished, so just bail out. */ Index: src/sys/dev/usb/if_otus.c diff -u src/sys/dev/usb/if_otus.c:1.31.2.1 src/sys/dev/usb/if_otus.c:1.31.2.2 --- src/sys/dev/usb/if_otus.c:1.31.2.1 Wed Jan 31 18:01:55 2018 +++ src/sys/dev/usb/if_otus.c Wed Aug 8 10:28:35 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: if_otus.c,v 1.31.2.1 2018/01/31 18:01:55 martin Exp $ */ +/* $NetBSD: if_otus.c,v 1.31.2.2 2018/08/08 10:28:35 martin Exp $ */ /* $OpenBSD: if_otus.c,v 1.18 2010/08/27 17:08:00 jsg Exp $ */ /*- @@ -23,7 +23,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if_otus.c,v 1.31.2.1 2018/01/31 18:01:55 martin Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_otus.c,v 1.31.2.2 2018/08/08 10:28:35 martin Exp $"); #ifdef _KERNEL_OPT #include "opt_usb.h" @@ -701,7 +701,7 @@ otus_detach(device_t self, int flags) if (ifp != NULL) /* Failed to attach properly */ otus_stop(ifp); - usb_rem_task(sc->sc_udev, &sc->sc_task); + usb_rem_task_wait(sc->sc_udev, &sc->sc_task, USB_TASKQ_DRIVER, NULL); callout_destroy(&sc->sc_scan_to); callout_destroy(&sc->sc_calib_to); Index: src/sys/dev/usb/if_rum.c diff -u src/sys/dev/usb/if_rum.c:1.58.2.1 src/sys/dev/usb/if_rum.c:1.58.2.2 --- src/sys/dev/usb/if_rum.c:1.58.2.1 Wed Jan 31 18:01:54 2018 +++ src/sys/dev/usb/if_rum.c Wed Aug 8 10:28:35 2018 @@ -1,5 +1,5 @@ /* $OpenBSD: if_rum.c,v 1.40 2006/09/18 16:20:20 damien Exp $ */ -/* $NetBSD: if_rum.c,v 1.58.2.1 2018/01/31 18:01:54 martin Exp $ */ +/* $NetBSD: if_rum.c,v 1.58.2.2 2018/08/08 10:28:35 martin Exp $ */ /*- * Copyright (c) 2005-2007 Damien Bergamini <damien.bergam...@free.fr> @@ -24,7 +24,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if_rum.c,v 1.58.2.1 2018/01/31 18:01:54 martin Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_rum.c,v 1.58.2.2 2018/08/08 10:28:35 martin Exp $"); #ifdef _KERNEL_OPT #include "opt_usb.h" @@ -508,9 +508,9 @@ rum_detach(device_t self, int flags) s = splusb(); rum_stop(ifp, 1); - usb_rem_task(sc->sc_udev, &sc->sc_task); - callout_stop(&sc->sc_scan_ch); - callout_stop(&sc->sc_amrr_ch); + callout_halt(&sc->sc_scan_ch, NULL); + callout_halt(&sc->sc_amrr_ch, NULL); + usb_rem_task_wait(sc->sc_udev, &sc->sc_task, USB_TASKQ_DRIVER, NULL); bpf_detach(ifp); ieee80211_ifdetach(ic); /* free all nodes */ @@ -747,6 +747,11 @@ rum_newstate(struct ieee80211com *ic, en { struct rum_softc *sc = ic->ic_ifp->if_softc; + /* + * XXXSMP: This does not wait for the task, if it is in flight, + * to complete. If this code works at all, it must rely on the + * kernel lock to serialize with the USB task thread. + */ usb_rem_task(sc->sc_udev, &sc->sc_task); callout_stop(&sc->sc_scan_ch); callout_stop(&sc->sc_amrr_ch); Index: src/sys/dev/usb/if_run.c diff -u src/sys/dev/usb/if_run.c:1.22.2.1 src/sys/dev/usb/if_run.c:1.22.2.2 --- src/sys/dev/usb/if_run.c:1.22.2.1 Wed Jan 31 18:01:54 2018 +++ src/sys/dev/usb/if_run.c Wed Aug 8 10:28:35 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: if_run.c,v 1.22.2.1 2018/01/31 18:01:54 martin Exp $ */ +/* $NetBSD: if_run.c,v 1.22.2.2 2018/08/08 10:28:35 martin Exp $ */ /* $OpenBSD: if_run.c,v 1.90 2012/03/24 15:11:04 jsg Exp $ */ /*- @@ -23,7 +23,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if_run.c,v 1.22.2.1 2018/01/31 18:01:54 martin Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_run.c,v 1.22.2.2 2018/08/08 10:28:35 martin Exp $"); #ifdef _KERNEL_OPT #include "opt_usb.h" @@ -759,8 +759,11 @@ run_detach(device_t self, int flags) sc->sc_flags |= RUN_DETACHING; if (ifp->if_flags & IFF_RUNNING) { - usb_rem_task(sc->sc_udev, &sc->sc_task); run_stop(ifp, 0); + callout_halt(&sc->scan_to, NULL); + callout_halt(&sc->calib_to, NULL); + usb_rem_task_wait(sc->sc_udev, &sc->sc_task, USB_TASKQ_DRIVER, + NULL); } ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); Index: src/sys/dev/usb/if_smsc.c diff -u src/sys/dev/usb/if_smsc.c:1.30.8.1 src/sys/dev/usb/if_smsc.c:1.30.8.2 --- src/sys/dev/usb/if_smsc.c:1.30.8.1 Wed Jan 31 18:01:55 2018 +++ src/sys/dev/usb/if_smsc.c Wed Aug 8 10:28:35 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: if_smsc.c,v 1.30.8.1 2018/01/31 18:01:55 martin Exp $ */ +/* $NetBSD: if_smsc.c,v 1.30.8.2 2018/08/08 10:28:35 martin Exp $ */ /* $OpenBSD: if_smsc.c,v 1.4 2012/09/27 12:38:11 jsg Exp $ */ /* $FreeBSD: src/sys/dev/usb/net/if_smsc.c,v 1.1 2012/08/15 04:03:55 gonzo Exp $ */ @@ -1140,7 +1140,7 @@ smsc_detach(device_t self, int flags) struct ifnet *ifp = &sc->sc_ec.ec_if; int s; - callout_stop(&sc->sc_stat_ch); + callout_halt(&sc->sc_stat_ch, NULL); if (sc->sc_ep[SMSC_ENDPT_TX] != NULL) usbd_abort_pipe(sc->sc_ep[SMSC_ENDPT_TX]); @@ -1149,12 +1149,10 @@ smsc_detach(device_t self, int flags) if (sc->sc_ep[SMSC_ENDPT_INTR] != NULL) usbd_abort_pipe(sc->sc_ep[SMSC_ENDPT_INTR]); - /* - * Remove any pending tasks. They cannot be executing because they run - * in the same thread as detach. - */ - usb_rem_task(sc->sc_udev, &sc->sc_tick_task); - usb_rem_task(sc->sc_udev, &sc->sc_stop_task); + usb_rem_task_wait(sc->sc_udev, &sc->sc_tick_task, USB_TASKQ_DRIVER, + NULL); + usb_rem_task_wait(sc->sc_udev, &sc->sc_stop_task, USB_TASKQ_DRIVER, + NULL); s = splusb(); Index: src/sys/dev/usb/if_udav.c diff -u src/sys/dev/usb/if_udav.c:1.51.8.1 src/sys/dev/usb/if_udav.c:1.51.8.2 --- src/sys/dev/usb/if_udav.c:1.51.8.1 Wed Jan 31 18:01:54 2018 +++ src/sys/dev/usb/if_udav.c Wed Aug 8 10:28:35 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: if_udav.c,v 1.51.8.1 2018/01/31 18:01:54 martin Exp $ */ +/* $NetBSD: if_udav.c,v 1.51.8.2 2018/08/08 10:28:35 martin Exp $ */ /* $nabe: if_udav.c,v 1.3 2003/08/21 16:57:19 nabe Exp $ */ /* @@ -45,7 +45,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if_udav.c,v 1.51.8.1 2018/01/31 18:01:54 martin Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_udav.c,v 1.51.8.2 2018/08/08 10:28:35 martin Exp $"); #ifdef _KERNEL_OPT #include "opt_inet.h" @@ -352,11 +352,13 @@ udav_detach(device_t self, int flags) if (!sc->sc_attached) return 0; - callout_stop(&sc->sc_stat_ch); + callout_halt(&sc->sc_stat_ch, NULL); /* Remove any pending tasks */ - usb_rem_task(sc->sc_udev, &sc->sc_tick_task); - usb_rem_task(sc->sc_udev, &sc->sc_stop_task); + usb_rem_task_wait(sc->sc_udev, &sc->sc_tick_task, USB_TASKQ_DRIVER, + NULL); + usb_rem_task_wait(sc->sc_udev, &sc->sc_stop_task, USB_TASKQ_DRIVER, + NULL); s = splusb(); Index: src/sys/dev/usb/if_upgt.c diff -u src/sys/dev/usb/if_upgt.c:1.17.8.1 src/sys/dev/usb/if_upgt.c:1.17.8.2 --- src/sys/dev/usb/if_upgt.c:1.17.8.1 Wed Jan 31 18:01:54 2018 +++ src/sys/dev/usb/if_upgt.c Wed Aug 8 10:28:35 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: if_upgt.c,v 1.17.8.1 2018/01/31 18:01:54 martin Exp $ */ +/* $NetBSD: if_upgt.c,v 1.17.8.2 2018/08/08 10:28:35 martin Exp $ */ /* $OpenBSD: if_upgt.c,v 1.49 2010/04/20 22:05:43 tedu Exp $ */ /* @@ -18,7 +18,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if_upgt.c,v 1.17.8.1 2018/01/31 18:01:54 martin Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_upgt.c,v 1.17.8.2 2018/08/08 10:28:35 martin Exp $"); #ifdef _KERNEL_OPT #include "opt_usb.h" @@ -504,8 +504,12 @@ upgt_detach(device_t self, int flags) upgt_stop(sc); /* remove tasks and timeouts */ - usb_rem_task(sc->sc_udev, &sc->sc_task_newstate); - usb_rem_task(sc->sc_udev, &sc->sc_task_tx); + callout_halt(&sc->scan_to, NULL); + callout_halt(&sc->led_to, NULL); + usb_rem_task_wait(sc->sc_udev, &sc->sc_task_newstate, USB_TASKQ_DRIVER, + NULL); + usb_rem_task_wait(sc->sc_udev, &sc->sc_task_tx, USB_TASKQ_DRIVER, + NULL); callout_destroy(&sc->scan_to); callout_destroy(&sc->led_to); @@ -1346,6 +1350,11 @@ upgt_newstate(struct ieee80211com *ic, e { struct upgt_softc *sc = ic->ic_ifp->if_softc; + /* + * XXXSMP: This does not wait for the task, if it is in flight, + * to complete. If this code works at all, it must rely on the + * kernel lock to serialize with the USB task thread. + */ usb_rem_task(sc->sc_udev, &sc->sc_task_newstate); callout_stop(&sc->scan_to); Index: src/sys/dev/usb/if_ural.c diff -u src/sys/dev/usb/if_ural.c:1.51.8.2 src/sys/dev/usb/if_ural.c:1.51.8.3 --- src/sys/dev/usb/if_ural.c:1.51.8.2 Wed Jan 31 18:01:54 2018 +++ src/sys/dev/usb/if_ural.c Wed Aug 8 10:28:35 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: if_ural.c,v 1.51.8.2 2018/01/31 18:01:54 martin Exp $ */ +/* $NetBSD: if_ural.c,v 1.51.8.3 2018/08/08 10:28:35 martin Exp $ */ /* $FreeBSD: /repoman/r/ncvs/src/sys/dev/usb/if_ural.c,v 1.40 2006/06/02 23:14:40 sam Exp $ */ /*- @@ -24,7 +24,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if_ural.c,v 1.51.8.2 2018/01/31 18:01:54 martin Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_ural.c,v 1.51.8.3 2018/08/08 10:28:35 martin Exp $"); #ifdef _KERNEL_OPT #include "opt_usb.h" @@ -546,9 +546,9 @@ ural_detach(device_t self, int flags) s = splusb(); ural_stop(ifp, 1); - usb_rem_task(sc->sc_udev, &sc->sc_task); - callout_stop(&sc->sc_scan_ch); - callout_stop(&sc->sc_amrr_ch); + callout_halt(&sc->sc_scan_ch, NULL); + callout_halt(&sc->sc_amrr_ch, NULL); + usb_rem_task_wait(sc->sc_udev, &sc->sc_task, USB_TASKQ_DRIVER, NULL); bpf_detach(ifp); ieee80211_ifdetach(ic); @@ -796,6 +796,11 @@ ural_newstate(struct ieee80211com *ic, e { struct ural_softc *sc = ic->ic_ifp->if_softc; + /* + * XXXSMP: This does not wait for the task, if it is in flight, + * to complete. If this code works at all, it must rely on the + * kernel lock to serialize with the USB task thread. + */ usb_rem_task(sc->sc_udev, &sc->sc_task); callout_stop(&sc->sc_scan_ch); callout_stop(&sc->sc_amrr_ch); Index: src/sys/dev/usb/if_url.c diff -u src/sys/dev/usb/if_url.c:1.56.8.1 src/sys/dev/usb/if_url.c:1.56.8.2 --- src/sys/dev/usb/if_url.c:1.56.8.1 Wed Jan 31 18:01:55 2018 +++ src/sys/dev/usb/if_url.c Wed Aug 8 10:28:35 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: if_url.c,v 1.56.8.1 2018/01/31 18:01:55 martin Exp $ */ +/* $NetBSD: if_url.c,v 1.56.8.2 2018/08/08 10:28:35 martin Exp $ */ /* * Copyright (c) 2001, 2002 @@ -44,7 +44,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if_url.c,v 1.56.8.1 2018/01/31 18:01:55 martin Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_url.c,v 1.56.8.2 2018/08/08 10:28:35 martin Exp $"); #ifdef _KERNEL_OPT #include "opt_inet.h" @@ -346,11 +346,20 @@ url_detach(device_t self, int flags) if (!sc->sc_attached) return 0; - callout_stop(&sc->sc_stat_ch); + /* + * XXX Halting callout guarantees no more tick tasks. What + * guarantees no more stop tasks? What guarantees no more + * calls to url_send? Don't we need to wait for if_detach or + * something? Should set sc->sc_dying here? Is device + * deactivation guaranteed to have already happened? + */ + callout_halt(&sc->sc_stat_ch, NULL); /* Remove any pending tasks */ - usb_rem_task(sc->sc_udev, &sc->sc_tick_task); - usb_rem_task(sc->sc_udev, &sc->sc_stop_task); + usb_rem_task_wait(sc->sc_udev, &sc->sc_tick_task, USB_TASKQ_DRIVER, + NULL); + usb_rem_task_wait(sc->sc_udev, &sc->sc_stop_task, USB_TASKQ_DRIVER, + NULL); s = splusb(); Index: src/sys/dev/usb/if_urtw.c diff -u src/sys/dev/usb/if_urtw.c:1.13.8.1 src/sys/dev/usb/if_urtw.c:1.13.8.2 --- src/sys/dev/usb/if_urtw.c:1.13.8.1 Wed Jan 31 18:01:54 2018 +++ src/sys/dev/usb/if_urtw.c Wed Aug 8 10:28:35 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: if_urtw.c,v 1.13.8.1 2018/01/31 18:01:54 martin Exp $ */ +/* $NetBSD: if_urtw.c,v 1.13.8.2 2018/08/08 10:28:35 martin Exp $ */ /* $OpenBSD: if_urtw.c,v 1.39 2011/07/03 15:47:17 matthew Exp $ */ /*- @@ -19,7 +19,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if_urtw.c,v 1.13.8.1 2018/01/31 18:01:54 martin Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_urtw.c,v 1.13.8.2 2018/08/08 10:28:35 martin Exp $"); #ifdef _KERNEL_OPT #include "opt_usb.h" @@ -774,11 +774,14 @@ urtw_detach(device_t self, int flags) sc->sc_dying = true; + callout_halt(&sc->scan_to, NULL); + callout_halt(&sc->sc_led_ch, NULL); callout_destroy(&sc->scan_to); callout_destroy(&sc->sc_led_ch); - usb_rem_task(sc->sc_udev, &sc->sc_task); - usb_rem_task(sc->sc_udev, &sc->sc_ledtask); + usb_rem_task_wait(sc->sc_udev, &sc->sc_task, USB_TASKQ_DRIVER, NULL); + usb_rem_task_wait(sc->sc_udev, &sc->sc_ledtask, USB_TASKQ_DRIVER, + NULL); if (ifp->if_softc != NULL) { bpf_detach(ifp); @@ -1042,6 +1045,11 @@ urtw_newstate(struct ieee80211com *ic, e { struct urtw_softc *sc = ic->ic_ifp->if_softc; + /* + * XXXSMP: This does not wait for the task, if it is in flight, + * to complete. If this code works at all, it must rely on the + * kernel lock to serialize with the USB task thread. + */ usb_rem_task(sc->sc_udev, &sc->sc_task); callout_stop(&sc->scan_to); Index: src/sys/dev/usb/if_urtwn.c diff -u src/sys/dev/usb/if_urtwn.c:1.53.2.3 src/sys/dev/usb/if_urtwn.c:1.53.2.4 --- src/sys/dev/usb/if_urtwn.c:1.53.2.3 Thu Jun 7 18:16:43 2018 +++ src/sys/dev/usb/if_urtwn.c Wed Aug 8 10:28:35 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: if_urtwn.c,v 1.53.2.3 2018/06/07 18:16:43 martin Exp $ */ +/* $NetBSD: if_urtwn.c,v 1.53.2.4 2018/08/08 10:28:35 martin Exp $ */ /* $OpenBSD: if_urtwn.c,v 1.42 2015/02/10 23:25:46 mpi Exp $ */ /*- @@ -25,7 +25,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if_urtwn.c,v 1.53.2.3 2018/06/07 18:16:43 martin Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_urtwn.c,v 1.53.2.4 2018/08/08 10:28:35 martin Exp $"); #ifdef _KERNEL_OPT #include "opt_inet.h" @@ -537,12 +537,13 @@ urtwn_detach(device_t self, int flags) sc->sc_dying = 1; - callout_stop(&sc->sc_scan_to); - callout_stop(&sc->sc_calib_to); + callout_halt(&sc->sc_scan_to, NULL); + callout_halt(&sc->sc_calib_to, NULL); if (ISSET(sc->sc_flags, URTWN_FLAG_ATTACHED)) { - usb_rem_task(sc->sc_udev, &sc->sc_task); urtwn_stop(ifp, 0); + usb_rem_task_wait(sc->sc_udev, &sc->sc_task, USB_TASKQ_DRIVER, + NULL); ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); bpf_detach(ifp); Index: src/sys/dev/usb/if_zyd.c diff -u src/sys/dev/usb/if_zyd.c:1.44.2.1 src/sys/dev/usb/if_zyd.c:1.44.2.2 --- src/sys/dev/usb/if_zyd.c:1.44.2.1 Wed Jan 31 18:01:54 2018 +++ src/sys/dev/usb/if_zyd.c Wed Aug 8 10:28:35 2018 @@ -1,5 +1,5 @@ /* $OpenBSD: if_zyd.c,v 1.52 2007/02/11 00:08:04 jsg Exp $ */ -/* $NetBSD: if_zyd.c,v 1.44.2.1 2018/01/31 18:01:54 martin Exp $ */ +/* $NetBSD: if_zyd.c,v 1.44.2.2 2018/08/08 10:28:35 martin Exp $ */ /*- * Copyright (c) 2006 by Damien Bergamini <damien.bergam...@free.fr> @@ -23,7 +23,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if_zyd.c,v 1.44.2.1 2018/01/31 18:01:54 martin Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_zyd.c,v 1.44.2.2 2018/08/08 10:28:35 martin Exp $"); #ifdef _KERNEL_OPT #include "opt_usb.h" @@ -474,9 +474,9 @@ zyd_detach(device_t self, int flags) s = splusb(); zyd_stop(ifp, 1); - usb_rem_task(sc->sc_udev, &sc->sc_task); - callout_stop(&sc->sc_scan_ch); - callout_stop(&sc->sc_amrr_ch); + callout_halt(&sc->sc_scan_ch, NULL); + callout_halt(&sc->sc_amrr_ch, NULL); + usb_rem_task_wait(sc->sc_udev, &sc->sc_task, USB_TASKQ_DRIVER, NULL); /* Abort, etc. done by zyd_stop */ zyd_close_pipes(sc); @@ -769,6 +769,11 @@ zyd_newstate(struct ieee80211com *ic, en if (!sc->attached) return ENXIO; + /* + * XXXSMP: This does not wait for the task, if it is in flight, + * to complete. If this code works at all, it must rely on the + * kernel lock to serialize with the USB task thread. + */ usb_rem_task(sc->sc_udev, &sc->sc_task); callout_stop(&sc->sc_scan_ch); callout_stop(&sc->sc_amrr_ch); Index: src/sys/dev/usb/uatp.c diff -u src/sys/dev/usb/uatp.c:1.14 src/sys/dev/usb/uatp.c:1.14.6.1 --- src/sys/dev/usb/uatp.c:1.14 Sun Apr 9 16:40:42 2017 +++ src/sys/dev/usb/uatp.c Wed Aug 8 10:28:35 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: uatp.c,v 1.14 2017/04/09 16:40:42 riastradh Exp $ */ +/* $NetBSD: uatp.c,v 1.14.6.1 2018/08/08 10:28:35 martin Exp $ */ /*- * Copyright (c) 2011-2014 The NetBSD Foundation, Inc. @@ -146,7 +146,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: uatp.c,v 1.14 2017/04/09 16:40:42 riastradh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: uatp.c,v 1.14.6.1 2018/08/08 10:28:35 martin Exp $"); #ifdef _KERNEL_OPT #include "opt_usb.h" @@ -1362,7 +1362,8 @@ geyser34_finalize(struct uatp_softc *sc) { DPRINTF(sc, UATP_DEBUG_MISC, ("finalizing\n")); - usb_rem_task(sc->sc_hdev.sc_parent->sc_udev, &sc->sc_reset_task); + usb_rem_task_wait(sc->sc_hdev.sc_parent->sc_udev, &sc->sc_reset_task, + USB_TASKQ_DRIVER, NULL); return 0; } Index: src/sys/dev/usb/umcs.c diff -u src/sys/dev/usb/umcs.c:1.10 src/sys/dev/usb/umcs.c:1.10.10.1 --- src/sys/dev/usb/umcs.c:1.10 Thu Jul 7 06:55:42 2016 +++ src/sys/dev/usb/umcs.c Wed Aug 8 10:28:35 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: umcs.c,v 1.10 2016/07/07 06:55:42 msaitoh Exp $ */ +/* $NetBSD: umcs.c,v 1.10.10.1 2018/08/08 10:28:35 martin Exp $ */ /* $FreeBSD: head/sys/dev/usb/serial/umcs.c 260559 2014-01-12 11:44:28Z hselasky $ */ /*- @@ -41,7 +41,7 @@ * */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: umcs.c,v 1.10 2016/07/07 06:55:42 msaitoh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: umcs.c,v 1.10.10.1 2018/08/08 10:28:35 martin Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -517,7 +517,8 @@ umcs7840_detach(device_t self, int flags kmem_free(sc->sc_intr_buf, sc->sc_intr_buflen); sc->sc_intr_pipe = NULL; } - usb_rem_task(sc->sc_udev, &sc->sc_change_task); + usb_rem_task_wait(sc->sc_udev, &sc->sc_change_task, USB_TASKQ_DRIVER, + NULL); /* detach children */ for (i = 0; i < sc->sc_numports; i++) { Index: src/sys/dev/usb/usb.c diff -u src/sys/dev/usb/usb.c:1.165.6.2 src/sys/dev/usb/usb.c:1.165.6.3 --- src/sys/dev/usb/usb.c:1.165.6.2 Thu Nov 2 21:29:52 2017 +++ src/sys/dev/usb/usb.c Wed Aug 8 10:28:35 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: usb.c,v 1.165.6.2 2017/11/02 21:29:52 snj Exp $ */ +/* $NetBSD: usb.c,v 1.165.6.3 2018/08/08 10:28:35 martin Exp $ */ /* * Copyright (c) 1998, 2002, 2008, 2012 The NetBSD Foundation, Inc. @@ -37,7 +37,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: usb.c,v 1.165.6.2 2017/11/02 21:29:52 snj Exp $"); +__KERNEL_RCSID(0, "$NetBSD: usb.c,v 1.165.6.3 2018/08/08 10:28:35 martin Exp $"); #ifdef _KERNEL_OPT #include "opt_usb.h" @@ -146,6 +146,7 @@ struct usb_taskq { kcondvar_t cv; struct lwp *task_thread_lwp; const char *name; + struct usb_task *current_task; }; static struct usb_taskq usb_taskq[USB_NUM_TASKQS]; @@ -293,6 +294,7 @@ usb_once_init(void) mutex_init(&taskq->lock, MUTEX_DEFAULT, IPL_USB); cv_init(&taskq->cv, "usbtsk"); taskq->name = taskq_names[i]; + taskq->current_task = NULL; if (kthread_create(PRI_NONE, KTHREAD_MPSAFE, NULL, usb_task_thread, taskq, &taskq->task_thread_lwp, "%s", taskq->name)) { @@ -422,8 +424,14 @@ usb_add_task(struct usbd_device *dev, st } /* - * XXX This does not wait for completion! Most uses need such an - * operation. Urgh... + * usb_rem_task(dev, task) + * + * If task is queued to run, remove it from the queue. + * + * Caller is _not_ guaranteed that the task is not running when + * this is done. + * + * Never sleeps. */ void usb_rem_task(struct usbd_device *dev, struct usb_task *task) @@ -445,6 +453,74 @@ usb_rem_task(struct usbd_device *dev, st } } +/* + * usb_rem_task_wait(dev, task, queue, interlock) + * + * If task is scheduled to run, remove it from the queue. If it + * may have already begun to run, drop interlock if not null, wait + * for it to complete, and reacquire interlock if not null. + * Return true if it successfully removed the task from the queue, + * false if not. + * + * Caller MUST guarantee that task will not be scheduled on a + * _different_ queue, at least until after this returns. + * + * If caller guarantees that task will not be scheduled on the + * same queue before this returns, then caller is guaranteed that + * the task is not running at all when this returns. + * + * May sleep. + */ +bool +usb_rem_task_wait(struct usbd_device *dev, struct usb_task *task, int queue, + kmutex_t *interlock) +{ + struct usb_taskq *taskq; + int queue1; + bool removed; + + USBHIST_FUNC(); USBHIST_CALLED(usbdebug); + ASSERT_SLEEPABLE(); + KASSERT(0 <= queue); + KASSERT(queue < USB_NUM_TASKQS); + + taskq = &usb_taskq[queue]; + mutex_enter(&taskq->lock); + queue1 = task->queue; + if (queue1 == USB_NUM_TASKQS) { + /* + * It is not on the queue. It may be about to run, or + * it may have already finished running -- there is no + * stopping it now. Wait for it if it is running. + */ + if (interlock) + mutex_exit(interlock); + while (taskq->current_task == task) + cv_wait(&taskq->cv, &taskq->lock); + removed = false; + } else { + /* + * It is still on the queue. We can stop it before the + * task thread will run it. + */ + KASSERTMSG(queue1 == queue, "task %p on q%d expected on q%d", + task, queue1, queue); + TAILQ_REMOVE(&taskq->tasks, task, next); + task->queue = USB_NUM_TASKQS; + removed = true; + } + mutex_exit(&taskq->lock); + + /* + * If there's an interlock, and we dropped it to wait, + * reacquire it. + */ + if (interlock && !removed) + mutex_enter(interlock); + + return removed; +} + void usb_event_thread(void *arg) { @@ -513,6 +589,7 @@ usb_task_thread(void *arg) mpsafe = ISSET(task->flags, USB_TASKQ_MPSAFE); TAILQ_REMOVE(&taskq->tasks, task, next); task->queue = USB_NUM_TASKQS; + taskq->current_task = task; mutex_exit(&taskq->lock); if (!mpsafe) @@ -523,6 +600,10 @@ usb_task_thread(void *arg) KERNEL_UNLOCK_ONE(curlwp); mutex_enter(&taskq->lock); + KASSERTMSG(taskq->current_task == task, + "somebody scribbled on usb taskq %p", taskq); + taskq->current_task = NULL; + cv_broadcast(&taskq->cv); } } mutex_exit(&taskq->lock); Index: src/sys/dev/usb/usb_subr.c diff -u src/sys/dev/usb/usb_subr.c:1.220.2.2 src/sys/dev/usb/usb_subr.c:1.220.2.3 --- src/sys/dev/usb/usb_subr.c:1.220.2.2 Thu Dec 21 21:32:10 2017 +++ src/sys/dev/usb/usb_subr.c Wed Aug 8 10:28:35 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: usb_subr.c,v 1.220.2.2 2017/12/21 21:32:10 snj Exp $ */ +/* $NetBSD: usb_subr.c,v 1.220.2.3 2018/08/08 10:28:35 martin Exp $ */ /* $FreeBSD: src/sys/dev/usb/usb_subr.c,v 1.18 1999/11/17 22:33:47 n_hibma Exp $ */ /* @@ -32,7 +32,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: usb_subr.c,v 1.220.2.2 2017/12/21 21:32:10 snj Exp $"); +__KERNEL_RCSID(0, "$NetBSD: usb_subr.c,v 1.220.2.3 2018/08/08 10:28:35 martin Exp $"); #ifdef _KERNEL_OPT #include "opt_compat_netbsd.h" @@ -823,7 +823,8 @@ usbd_kill_pipe(struct usbd_pipe *pipe) usbd_lock_pipe(pipe); pipe->up_methods->upm_close(pipe); usbd_unlock_pipe(pipe); - usb_rem_task(pipe->up_dev, &pipe->up_async_task); + usb_rem_task_wait(pipe->up_dev, &pipe->up_async_task, USB_TASKQ_DRIVER, + NULL); pipe->up_endpoint->ue_refcnt--; kmem_free(pipe, pipe->up_dev->ud_bus->ub_pipesize); } Index: src/sys/dev/usb/usbdi.h diff -u src/sys/dev/usb/usbdi.h:1.92 src/sys/dev/usb/usbdi.h:1.92.8.1 --- src/sys/dev/usb/usbdi.h:1.92 Sun Aug 14 14:42:22 2016 +++ src/sys/dev/usb/usbdi.h Wed Aug 8 10:28:35 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: usbdi.h,v 1.92 2016/08/14 14:42:22 skrll Exp $ */ +/* $NetBSD: usbdi.h,v 1.92.8.1 2018/08/08 10:28:35 martin Exp $ */ /* $FreeBSD: src/sys/dev/usb/usbdi.h,v 1.18 1999/11/17 22:33:49 n_hibma Exp $ */ /* @@ -219,6 +219,8 @@ struct usb_task { void usb_add_task(struct usbd_device *, struct usb_task *, int); void usb_rem_task(struct usbd_device *, struct usb_task *); +bool usb_rem_task_wait(struct usbd_device *, struct usb_task *, int, + kmutex_t *); #define usb_init_task(t, f, a, fl) ((t)->fun = (f), (t)->arg = (a), (t)->queue = USB_NUM_TASKQS, (t)->flags = (fl)) struct usb_devno {