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

Reply via email to