/* detach */ int url_detach(device_t self, int flags) { struct url_softc *sc = device_private(self); struct ifnet *ifp = GET_IFP(sc); int s; DPRINTF(("%s: %s: enter\n", device_xname(sc->sc_dev), __func__)); /* Detached before attached finished */ if (!sc->sc_attached) return (0); callout_stop(&sc->sc_stat_ch); /* Remove any pending tasks */ usb_rem_task(sc->sc_udev, &sc->sc_tick_task); usb_rem_task(sc->sc_udev, &sc->sc_stop_task); s = splusb(); if (--sc->sc_refcnt >= 0) { /* Wait for processes to go away */ usb_detach_waitold(sc->sc_dev); } if (ifp->if_flags & IFF_RUNNING) url_stop(GET_IFP(sc), 1); rnd_detach_source(&sc->rnd_source); mii_detach(&sc->sc_mii, MII_PHY_ANY, MII_OFFSET_ANY); ifmedia_delete_instance(&sc->sc_mii.mii_media, IFM_INST_ANY); ether_ifdetach(ifp); if_detach(ifp); #ifdef DIAGNOSTIC if (sc->sc_pipe_tx != NULL) aprint_debug_dev(self, "detach has active tx endpoint.\n"); if (sc->sc_pipe_rx != NULL) aprint_debug_dev(self, "detach has active rx endpoint.\n"); if (sc->sc_pipe_intr != NULL) aprint_debug_dev(self, "detach has active intr endpoint.\n"); #endif sc->sc_attached = 0; splx(s); rw_destroy(&sc->sc_mii_rwlock); usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev, sc->sc_dev); return (0); }
/* Abort the device control pipe. */ void usbd_kill_pipe(struct usbd_pipe *pipe) { usbd_abort_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); pipe->up_endpoint->ue_refcnt--; kmem_free(pipe, pipe->up_dev->ud_bus->ub_pipesize); }