I have been looking at doing somrhing similar because I have a usb wlan that for some reason unplugs it self (the device seems to die, I think it's broken or something). I will try this diff when I get a chance.
BR Dunceor On Thu, Dec 23, 2010 at 1:36 AM, Jacob Meuser <jake...@sdf.lonestar.org> wrote: > no feedback yet. B anyone care to comment on this? > > On Thu, Dec 16, 2010 at 12:28:56AM +0000, Jacob Meuser wrote: >> the following diff tries to make sure that no other processes/threads >> are or will be using the drivers software context when the driver is >> detached. >> >> this diff covers rum(4), run(4), ural(4) and urtw(4). B without the >> diff, I can get the kernel to crash by starting a scan with >> the deice, then ejecting it while the scan is running. B with this >> diff, I cannot get a crash. >> >> normally, usb device detach happens in the usb_task thread. B the sole >> exception is when the usb bus itself is being detached. B this happens >> with cardbus devices, and in that case, the usb device detach happens >> in the generic workq thread. >> >> this adds a simple reference counting/waiting mechanism. B this is >> definitely needed for ioctl(2), which can sleep then start using the >> driver again. B it may not be needed for timeout(9)s now, but maybe >> someday it will. B another possible process using the device is the >> usb_task thread. B in the normal case, this is the same process that >> is detaching, so there is no concurrency issue. B there is already >> usb_rem_wait_task() to deal with detaches from other processes, >> because the bus driver needs it. >> >> this also adds more uses of usbd_is_dying() to check if the device >> has been detached: >> * before adding timeouts >> * when entering timeouts, usb_tasks, and ioctl >> >> also of note is the order things are done in the detach routines: >> 1) remove pending timeouts >> 2) remove (and possibly wait for) pending usb_tasks >> 3) wait for other processes >> 4) detach from the network stack >> 5) cleanup/free usb resources >> >> thoughts? B ok? >> >> -- >> jake...@sdf.lonestar.org >> SDF Public Access UNIX System - http://sdf.lonestar.org >> >> >> Index: if_ral.c >> =================================================================== >> RCS file: /cvs/src/sys/dev/usb/if_ral.c,v >> retrieving revision 1.117 >> diff -u -p -r1.117 if_ral.c >> --- if_ral.c B 6 Dec 2010 04:41:39 -0000 B B B 1.117 >> +++ if_ral.c B 15 Dec 2010 02:58:35 -0000 >> @@ -363,17 +363,20 @@ ural_detach(struct device *self, int fla >> >> B B B s = splusb(); >> >> - B B if (ifp->if_softc != NULL) { >> - B B B B B B ieee80211_ifdetach(ifp); B B B B /* free all nodes */ >> - B B B B B B if_detach(ifp); >> - B B } >> - >> - B B usb_rem_task(sc->sc_udev, &sc->sc_task); >> B B B if (timeout_initialized(&sc->scan_to)) >> B B B B B B B timeout_del(&sc->scan_to); >> B B B if (timeout_initialized(&sc->amrr_to)) >> B B B B B B B timeout_del(&sc->amrr_to); >> >> + B B usb_rem_wait_task(sc->sc_udev, &sc->sc_task); >> + >> + B B usbd_ref_wait(sc->sc_udev); >> + >> + B B if (ifp->if_softc != NULL) { >> + B B B B B B ieee80211_ifdetach(ifp); B B B B /* free all nodes */ >> + B B B B B B if_detach(ifp); >> + B B } >> + >> B B B if (sc->amrr_xfer != NULL) { >> B B B B B B B usbd_free_xfer(sc->amrr_xfer); >> B B B B B B B sc->amrr_xfer = NULL; >> @@ -547,8 +550,15 @@ ural_next_scan(void *arg) >> B B B struct ieee80211com *ic = &sc->sc_ic; >> B B B struct ifnet *ifp = &ic->ic_if; >> >> + B B if (usbd_is_dying(sc->sc_udev)) >> + B B B B B B return; >> + >> + B B usbd_ref_incr(sc->sc_udev); >> + >> B B B if (ic->ic_state == IEEE80211_S_SCAN) >> B B B B B B B ieee80211_next_scan(ifp); >> + >> + B B usbd_ref_decr(sc->sc_udev); >> B } >> >> B void >> @@ -559,6 +569,9 @@ ural_task(void *arg) >> B B B enum ieee80211_state ostate; >> B B B struct ieee80211_node *ni; >> >> + B B if (usbd_is_dying(sc->sc_udev)) >> + B B B B B B return; >> + >> B B B ostate = ic->ic_state; >> >> B B B switch (sc->sc_state) { >> @@ -574,7 +587,8 @@ ural_task(void *arg) >> >> B B B case IEEE80211_S_SCAN: >> B B B B B B B ural_set_chan(sc, ic->ic_bss->ni_chan); >> - B B B B B B timeout_add_msec(&sc->scan_to, 200); >> + B B B B B B if (!usbd_is_dying(sc->sc_udev)) >> + B B B B B B B B B B timeout_add_msec(&sc->scan_to, 200); >> B B B B B B B break; >> >> B B B case IEEE80211_S_AUTH: >> @@ -1324,6 +1338,11 @@ ural_ioctl(struct ifnet *ifp, u_long cmd >> B B B struct ifreq *ifr; >> B B B int s, error = 0; >> >> + B B if (usbd_is_dying(sc->sc_udev)) >> + B B B B B B return ENXIO; >> + >> + B B usbd_ref_incr(sc->sc_udev); >> + >> B B B s = splnet(); >> >> B B B switch (cmd) { >> @@ -1387,6 +1406,8 @@ ural_ioctl(struct ifnet *ifp, u_long cmd >> >> B B B splx(s); >> >> + B B usbd_ref_decr(sc->sc_udev); >> + >> B B B return error; >> B } >> >> @@ -2147,7 +2168,8 @@ ural_amrr_start(struct ural_softc *sc, s >> B B B B B B i--); >> B B B ni->ni_txrate = i; >> >> - B B timeout_add_sec(&sc->amrr_to, 1); >> + B B if (!usbd_is_dying(sc->sc_udev)) >> + B B B B B B timeout_add_sec(&sc->amrr_to, 1); >> B } >> >> B void >> @@ -2157,6 +2179,11 @@ ural_amrr_timeout(void *arg) >> B B B usb_device_request_t req; >> B B B int s; >> >> + B B if (usbd_is_dying(sc->sc_udev)) >> + B B B B B B return; >> + >> + B B usbd_ref_incr(sc->sc_udev); >> + >> B B B s = splusb(); >> >> B B B /* >> @@ -2174,6 +2201,8 @@ ural_amrr_timeout(void *arg) >> B B B (void)usbd_transfer(sc->amrr_xfer); >> >> B B B splx(s); >> + >> + B B usbd_ref_decr(sc->sc_udev); >> B } >> >> B void >> @@ -2203,7 +2232,8 @@ ural_amrr_update(usbd_xfer_handle xfer, >> >> B B B ieee80211_amrr_choose(&sc->amrr, sc->sc_ic.ic_bss, &sc->amn); >> >> - B B timeout_add_sec(&sc->amrr_to, 1); >> + B B if (!usbd_is_dying(sc->sc_udev)) >> + B B B B B B timeout_add_sec(&sc->amrr_to, 1); >> B } >> >> B int >> Index: if_rum.c >> =================================================================== >> RCS file: /cvs/src/sys/dev/usb/if_rum.c,v >> retrieving revision 1.94 >> diff -u -p -r1.94 if_rum.c >> --- if_rum.c B 6 Dec 2010 04:41:39 -0000 B B B 1.94 >> +++ if_rum.c B 15 Dec 2010 02:58:35 -0000 >> @@ -460,17 +460,20 @@ rum_detach(struct device *self, int flag >> >> B B B s = splusb(); >> >> - B B if (ifp->if_softc != NULL) { >> - B B B B B B ieee80211_ifdetach(ifp); B B B B /* free all nodes */ >> - B B B B B B if_detach(ifp); >> - B B } >> - >> - B B usb_rem_task(sc->sc_udev, &sc->sc_task); >> B B B if (timeout_initialized(&sc->scan_to)) >> B B B B B B B timeout_del(&sc->scan_to); >> B B B if (timeout_initialized(&sc->amrr_to)) >> B B B B B B B timeout_del(&sc->amrr_to); >> >> + B B usb_rem_wait_task(sc->sc_udev, &sc->sc_task); >> + >> + B B usbd_ref_wait(sc->sc_udev); >> + >> + B B if (ifp->if_softc != NULL) { >> + B B B B B B ieee80211_ifdetach(ifp); B B B B /* free all nodes */ >> + B B B B B B if_detach(ifp); >> + B B } >> + >> B B B if (sc->amrr_xfer != NULL) { >> B B B B B B B usbd_free_xfer(sc->amrr_xfer); >> B B B B B B B sc->amrr_xfer = NULL; >> @@ -647,8 +650,12 @@ rum_next_scan(void *arg) >> B B B if (usbd_is_dying(sc->sc_udev)) >> B B B B B B B return; >> >> + B B usbd_ref_incr(sc->sc_udev); >> + >> B B B if (ic->ic_state == IEEE80211_S_SCAN) >> B B B B B B B ieee80211_next_scan(ifp); >> + >> + B B usbd_ref_decr(sc->sc_udev); >> B } >> >> B void >> @@ -676,7 +683,8 @@ rum_task(void *arg) >> >> B B B case IEEE80211_S_SCAN: >> B B B B B B B rum_set_chan(sc, ic->ic_bss->ni_chan); >> - B B B B B B timeout_add_msec(&sc->scan_to, 200); >> + B B B B B B if (!usbd_is_dying(sc->sc_udev)) >> + B B B B B B B B B B timeout_add_msec(&sc->scan_to, 200); >> B B B B B B B break; >> >> B B B case IEEE80211_S_AUTH: >> @@ -1350,6 +1358,11 @@ rum_ioctl(struct ifnet *ifp, u_long cmd, >> B B B struct ifreq *ifr; >> B B B int s, error = 0; >> >> + B B if (usbd_is_dying(sc->sc_udev)) >> + B B B B B B return ENXIO; >> + >> + B B usbd_ref_incr(sc->sc_udev); >> + >> B B B s = splnet(); >> >> B B B switch (cmd) { >> @@ -1413,6 +1426,8 @@ rum_ioctl(struct ifnet *ifp, u_long cmd, >> >> B B B splx(s); >> >> + B B usbd_ref_decr(sc->sc_udev); >> + >> B B B return error; >> B } >> >> @@ -2236,7 +2251,8 @@ rum_amrr_start(struct rum_softc *sc, str >> B B B B B B i--); >> B B B ni->ni_txrate = i; >> >> - B B timeout_add_sec(&sc->amrr_to, 1); >> + B B if (!usbd_is_dying(sc->sc_udev)) >> + B B B B B B timeout_add_sec(&sc->amrr_to, 1); >> B } >> >> B void >> @@ -2290,7 +2306,8 @@ rum_amrr_update(usbd_xfer_handle xfer, u >> >> B B B ieee80211_amrr_choose(&sc->amrr, sc->sc_ic.ic_bss, &sc->amn); >> >> - B B timeout_add_sec(&sc->amrr_to, 1); >> + B B if (!usbd_is_dying(sc->sc_udev)) >> + B B B B B B timeout_add_sec(&sc->amrr_to, 1); >> B } >> >> B int >> Index: if_run.c >> =================================================================== >> RCS file: /cvs/src/sys/dev/usb/if_run.c,v >> retrieving revision 1.81 >> diff -u -p -r1.81 if_run.c >> --- if_run.c B 6 Nov 2010 00:09:30 -0000 B B B 1.81 >> +++ if_run.c B 15 Dec 2010 02:58:36 -0000 >> @@ -283,6 +283,7 @@ static const struct usb_devno run_devs[] >> B int B B B B B run_match(struct device *, void *, void *); >> B void B B B B run_attach(struct device *, struct device *, void *); >> B int B B B B B run_detach(struct device *, int); >> +int B B B B B run_activate(struct device *, int); >> B int B B B B B run_alloc_rx_ring(struct run_softc *); >> B void B B B B run_free_rx_ring(struct run_softc *); >> B int B B B B B run_alloc_tx_ring(struct run_softc *, int); >> @@ -368,7 +369,8 @@ struct cfdriver run_cd = { >> B }; >> >> B const struct cfattach run_ca = { >> - B B sizeof (struct run_softc), run_match, run_attach, run_detach >> + B B sizeof (struct run_softc), run_match, run_attach, run_detach, >> + B B B B run_activate >> B }; >> >> B static const struct { >> @@ -590,17 +592,32 @@ run_detach(struct device *self, int flag >> B B B struct ifnet *ifp = &sc->sc_ic.ic_if; >> B B B int qid, s; >> >> - B B s = splnet(); >> - >> - B B /* wait for all queued asynchronous commands to complete */ >> - B B while (sc->cmdq.queued > 0) >> - B B B B B B tsleep(&sc->cmdq, 0, "cmdq", 0); >> + B B s = splusb(); >> >> B B B if (timeout_initialized(&sc->scan_to)) >> B B B B B B B timeout_del(&sc->scan_to); >> B B B if (timeout_initialized(&sc->calib_to)) >> B B B B B B B timeout_del(&sc->calib_to); >> >> + B B /* wait for all queued asynchronous commands to complete */ >> +#if 0 >> + B B while (sc->cmdq.queued > 0) >> + B B B B B B tsleep(&sc->cmdq, 0, "cmdq", 0); >> +#endif >> + B B /* the async commands are run in a task */ >> + B B usb_rem_wait_task(sc->sc_udev, &sc->sc_task); >> + >> + B B /* but the task might not have run if it did not start before >> + B B B * usbd_deactivate() was called, so wakeup now. B we're >> + B B B * detaching, no need to try to run more commands. >> + B B B */ >> + B B if (sc->cmdq.queued > 0) { >> + B B B B B B sc->cmdq.queued = 0; >> + B B B B B B wakeup(&sc->cmdq); >> + B B } >> + >> + B B usbd_ref_wait(sc->sc_udev); >> + >> B B B if (ifp->if_softc != NULL) { >> B B B B B B B ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); >> B B B B B B B ieee80211_ifdetach(ifp); >> @@ -1437,8 +1454,15 @@ run_next_scan(void *arg) >> B { >> B B B struct run_softc *sc = arg; >> >> + B B if (usbd_is_dying(sc->sc_udev)) >> + B B B B B B return; >> + >> + B B usbd_ref_incr(sc->sc_udev); >> + >> B B B if (sc->sc_ic.ic_state == IEEE80211_S_SCAN) >> B B B B B B B ieee80211_next_scan(&sc->sc_ic.ic_if); >> + >> + B B usbd_ref_decr(sc->sc_udev); >> B } >> >> B void >> @@ -1449,6 +1473,9 @@ run_task(void *arg) >> B B B struct run_host_cmd *cmd; >> B B B int s; >> >> + B B if (usbd_is_dying(sc->sc_udev)) >> + B B B B B B return; >> + >> B B B /* process host commands */ >> B B B s = splusb(); >> B B B while (ring->next != ring->cur) { >> @@ -1472,6 +1499,9 @@ run_do_async(struct run_softc *sc, void >> B B B struct run_host_cmd *cmd; >> B B B int s; >> >> + B B if (usbd_is_dying(sc->sc_udev)) >> + B B B B B B return; >> + >> B B B s = splusb(); >> B B B cmd = &ring->cmd[ring->cur]; >> B B B cmd->cb = cb; >> @@ -1530,7 +1560,8 @@ run_newstate_cb(struct run_softc *sc, vo >> >> B B B case IEEE80211_S_SCAN: >> B B B B B B B run_set_chan(sc, ic->ic_bss->ni_chan); >> - B B B B B B timeout_add_msec(&sc->scan_to, 200); >> + B B B B B B if (!usbd_is_dying(sc->sc_udev)) >> + B B B B B B B B B B timeout_add_msec(&sc->scan_to, 200); >> B B B B B B B break; >> >> B B B case IEEE80211_S_AUTH: >> @@ -1566,7 +1597,8 @@ run_newstate_cb(struct run_softc *sc, vo >> B B B B B B B B B B B run_read_region_1(sc, RT2860_TX_STA_CNT0, >> B B B B B B B B B B B B B (uint8_t *)sta, sizeof sta); >> B B B B B B B B B B B /* start calibration timer */ >> - B B B B B B B B B B timeout_add_sec(&sc->calib_to, 1); >> + B B B B B B B B B B if (!usbd_is_dying(sc->sc_udev)) >> + B B B B B B B B B B B B B B timeout_add_sec(&sc->calib_to, 1); >> B B B B B B B } >> >> B B B B B B B /* turn link LED on */ >> @@ -1812,7 +1844,9 @@ run_calibrate_cb(struct run_softc *sc, v >> B B B ieee80211_amrr_choose(&sc->amrr, sc->sc_ic.ic_bss, &sc->amn); >> B B B splx(s); >> >> -skip: B B B B timeout_add_sec(&sc->calib_to, 1); >> +skip: >> + B B if (!usbd_is_dying(sc->sc_udev)) >> + B B B B B B timeout_add_sec(&sc->calib_to, 1); >> B } >> >> B void >> @@ -2290,6 +2324,11 @@ run_ioctl(struct ifnet *ifp, u_long cmd, >> B B B struct ifreq *ifr; >> B B B int s, error = 0; >> >> + B B if (usbd_is_dying(sc->sc_udev)) >> + B B B B B B return ENXIO; >> + >> + B B usbd_ref_incr(sc->sc_udev); >> + >> B B B s = splnet(); >> >> B B B switch (cmd) { >> @@ -2352,6 +2391,8 @@ run_ioctl(struct ifnet *ifp, u_long cmd, >> >> B B B splx(s); >> >> + B B usbd_ref_decr(sc->sc_udev); >> + >> B B B return error; >> B } >> >> @@ -3263,6 +3304,9 @@ run_init(struct ifnet *ifp) >> B B B uint8_t bbp1, bbp3; >> B B B int i, error, qid, ridx, ntries; >> >> + B B if (usbd_is_dying(sc->sc_udev)) >> + B B B B B B return ENXIO; >> + >> B B B for (ntries = 0; ntries < 100; ntries++) { >> B B B B B B B if ((error = run_read(sc, RT2860_ASIC_VER_ID, &tmp)) != 0) >> B B B B B B B B B B B goto fail; >> @@ -3520,4 +3564,21 @@ run_stop(struct ifnet *ifp, int disable) >> B B B for (qid = 0; qid < 4; qid++) >> B B B B B B B run_free_tx_ring(sc, qid); >> B B B run_free_rx_ring(sc); >> +} >> + >> +int >> +run_activate(struct device *self, int act) >> +{ >> + B B struct run_softc *sc = (struct run_softc *)self; >> + >> + B B switch (act) { >> + B B case DVACT_ACTIVATE: >> + B B B B B B break; >> + >> + B B case DVACT_DEACTIVATE: >> + B B B B B B usbd_deactivate(sc->sc_udev); >> + B B B B B B break; >> + B B } >> + >> + B B return 0; >> B } >> Index: if_urtw.c >> =================================================================== >> RCS file: /cvs/src/sys/dev/usb/if_urtw.c,v >> retrieving revision 1.35 >> diff -u -p -r1.35 if_urtw.c >> --- if_urtw.c 6 Dec 2010 04:41:39 -0000 B B B 1.35 >> +++ if_urtw.c 15 Dec 2010 02:58:37 -0000 >> @@ -775,18 +775,21 @@ urtw_detach(struct device *self, int fla >> >> B B B s = splusb(); >> >> - B B if (ifp->if_softc != NULL) { >> - B B B B B B ieee80211_ifdetach(ifp); B B B B /* free all nodes */ >> - B B B B B B if_detach(ifp); >> - B B } >> - >> - B B usb_rem_task(sc->sc_udev, &sc->sc_task); >> - B B usb_rem_task(sc->sc_udev, &sc->sc_ledtask); >> B B B if (timeout_initialized(&sc->scan_to)) >> B B B B B B B timeout_del(&sc->scan_to); >> B B B if (timeout_initialized(&sc->sc_led_ch)) >> B B B B B B B timeout_del(&sc->sc_led_ch); >> >> + B B usb_rem_wait_task(sc->sc_udev, &sc->sc_task); >> + B B usb_rem_wait_task(sc->sc_udev, &sc->sc_ledtask); >> + >> + B B usbd_ref_wait(sc->sc_udev); >> + >> + B B if (ifp->if_softc != NULL) { >> + B B B B B B ieee80211_ifdetach(ifp); B B B B /* free all nodes */ >> + B B B B B B if_detach(ifp); >> + B B } >> + >> B B B /* abort and free xfers */ >> B B B urtw_free_tx_data_list(sc); >> B B B urtw_free_rx_data_list(sc); >> @@ -1913,7 +1916,8 @@ urtw_led_mode0(struct urtw_softc *sc, in >> B B B B B B B B B B B URTW_LED_OFF : URTW_LED_ON; >> B B B B B B B t.tv_sec = 0; >> B B B B B B B t.tv_usec = 100 * 1000L; >> - B B B B B B timeout_add(&sc->sc_led_ch, tvtohz(&t)); >> + B B B B B B if (!usbd_is_dying(sc->sc_udev)) >> + B B B B B B B B B B timeout_add(&sc->sc_led_ch, tvtohz(&t)); >> B B B B B B B break; >> B B B case URTW_LED_POWER_ON_BLINK: >> B B B B B B B urtw_led_on(sc, URTW_LED_GPIO); >> @@ -2034,7 +2038,8 @@ urtw_led_blink(struct urtw_softc *sc) >> B B B case URTW_LED_BLINK_NORMAL: >> B B B B B B B t.tv_sec = 0; >> B B B B B B B t.tv_usec = 100 * 1000L; >> - B B B B B B timeout_add(&sc->sc_led_ch, tvtohz(&t)); >> + B B B B B B if (!usbd_is_dying(sc->sc_udev)) >> + B B B B B B B B B B timeout_add(&sc->sc_led_ch, tvtohz(&t)); >> B B B B B B B break; >> B B B default: >> B B B B B B B panic("unknown LED status 0x%x", sc->sc_gpio_ledstate); >> @@ -2397,6 +2402,11 @@ urtw_ioctl(struct ifnet *ifp, u_long cmd >> B B B struct ifreq *ifr; >> B B B int s, error = 0; >> >> + B B if (usbd_is_dying(sc->sc_udev)) >> + B B B B B B return (ENXIO); >> + >> + B B usbd_ref_incr(sc->sc_udev); >> + >> B B B s = splnet(); >> >> B B B switch (cmd) { >> @@ -2470,6 +2480,8 @@ urtw_ioctl(struct ifnet *ifp, u_long cmd >> >> B B B splx(s); >> >> + B B usbd_ref_decr(sc->sc_udev); >> + >> B B B return (error); >> B } >> >> @@ -3513,8 +3525,15 @@ urtw_next_scan(void *arg) >> B B B struct ieee80211com *ic = &sc->sc_ic; >> B B B struct ifnet *ifp = &ic->ic_if; >> >> + B B if (usbd_is_dying(sc->sc_udev)) >> + B B B B B B return; >> + >> + B B usbd_ref_incr(sc->sc_udev); >> + >> B B B if (ic->ic_state == IEEE80211_S_SCAN) >> B B B B B B B ieee80211_next_scan(ifp); >> + >> + B B usbd_ref_decr(sc->sc_udev); >> B } >> >> B void >> @@ -3526,6 +3545,9 @@ urtw_task(void *arg) >> B B B enum ieee80211_state ostate; >> B B B usbd_status error = 0; >> >> + B B if (usbd_is_dying(sc->sc_udev)) >> + B B B B B B return; >> + >> B B B ostate = ic->ic_state; >> >> B B B switch (sc->sc_state) { >> @@ -3538,7 +3560,8 @@ urtw_task(void *arg) >> >> B B B case IEEE80211_S_SCAN: >> B B B B B B B urtw_set_chan(sc, ic->ic_bss->ni_chan); >> - B B B B B B timeout_add_msec(&sc->scan_to, 200); >> + B B B B B B if (!usbd_is_dying(sc->sc_udev)) >> + B B B B B B B B B B timeout_add_msec(&sc->scan_to, 200); >> B B B B B B B break; >> >> B B B case IEEE80211_S_AUTH: >> Index: usbdi.c >> =================================================================== >> RCS file: /cvs/src/sys/dev/usb/usbdi.c,v >> retrieving revision 1.41 >> diff -u -p -r1.41 usbdi.c >> --- usbdi.c B 6 Dec 2010 04:25:27 -0000 B B B 1.41 >> +++ usbdi.c B 15 Dec 2010 02:58:37 -0000 >> @@ -97,6 +97,26 @@ usbd_deactivate(usbd_device_handle dev) >> B B B dev->dying = 1; >> B } >> >> +void >> +usbd_ref_incr(usbd_device_handle dev) >> +{ >> + B B dev->ref_cnt++; >> +} >> + >> +void >> +usbd_ref_decr(usbd_device_handle dev) >> +{ >> + B B if (--dev->ref_cnt == 0 && dev->dying) >> + B B B B B B wakeup(&dev->ref_cnt); >> +} >> + >> +void >> +usbd_ref_wait(usbd_device_handle dev) >> +{ >> + B B while (dev->ref_cnt > 0) >> + B B B B B B tsleep(&dev->ref_cnt, PWAIT, "usbref", hz * 60); >> +} >> + >> B static __inline int >> B usbd_xfer_isread(usbd_xfer_handle xfer) >> B { >> Index: usbdi.h >> =================================================================== >> RCS file: /cvs/src/sys/dev/usb/usbdi.h,v >> retrieving revision 1.36 >> diff -u -p -r1.36 usbdi.h >> --- usbdi.h B 6 Dec 2010 04:25:27 -0000 B B B 1.36 >> +++ usbdi.h B 15 Dec 2010 02:58:37 -0000 >> @@ -168,6 +168,10 @@ int usbd_ratecheck(struct timeval *last) >> B int usbd_is_dying(usbd_device_handle); >> B void usbd_deactivate(usbd_device_handle); >> >> +void usbd_ref_incr(usbd_device_handle); >> +void usbd_ref_decr(usbd_device_handle); >> +void usbd_ref_wait(usbd_device_handle); >> + >> B /* An iterator for descriptors. */ >> B typedef struct { >> B B B const uByte *cur; >> Index: usbdivar.h >> =================================================================== >> RCS file: /cvs/src/sys/dev/usb/usbdivar.h,v >> retrieving revision 1.40 >> diff -u -p -r1.40 usbdivar.h >> --- usbdivar.h B B B B 6 Dec 2010 04:25:27 -0000 B B B 1.40 >> +++ usbdivar.h B B B B 15 Dec 2010 02:58:37 -0000 >> @@ -125,7 +125,8 @@ struct usbd_bus { >> B struct usbd_device { >> B B B struct usbd_bus B B B B *bus; B B B B B /* our controller */ >> B B B struct usbd_pipe B B B *default_pipe; B /* pipe 0 */ >> - B B u_int8_t B B B B B B B B dying; B B B B /* removed */ >> + B B u_int8_t B B B B B B B B dying; B B B B /* hardware removed */ >> + B B u_int8_t B B B B B B B B ref_cnt; B B B /* # of procs using device */ >> B B B u_int8_t B B B B B B B B address; B B B /* device address */ >> B B B u_int8_t B B B B B B B B config; B B B B /* current configuration # */ >> B B B u_int8_t B B B B B B B B depth; B B B B /* distance from root hub */ > > -- > jake...@sdf.lonestar.org > SDF Public Access UNIX System - http://sdf.lonestar.org