/*------------------------------------------------------------------------*
 *	usb_detach
 *------------------------------------------------------------------------*/
static int
usb_detach(device_t dev)
{
	struct usb_bus *bus = device_get_softc(dev);

	DPRINTF("\n");

	if (bus == NULL) {
		/* was never setup properly */
		return (0);
	}
	/* Stop power watchdog */
	usb_callout_drain(&bus->power_wdog);

#if USB_HAVE_ROOT_MOUNT_HOLD
	/* Let the USB explore process detach all devices. */
	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]);

	/* Wait for detach to complete */
	usb_proc_mwait(USB_BUS_EXPLORE_PROC(bus),
	    &bus->detach_msg[0], &bus->detach_msg[1]);

#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]);
#endif
	USB_BUS_UNLOCK(bus);

#if USB_HAVE_PER_BUS_PROCESS
	/* Get rid of USB callback processes */

	usb_proc_free(USB_BUS_GIANT_PROC(bus));
	usb_proc_free(USB_BUS_NON_GIANT_ISOC_PROC(bus));
	usb_proc_free(USB_BUS_NON_GIANT_BULK_PROC(bus));

	/* Get rid of USB explore process */

	usb_proc_free(USB_BUS_EXPLORE_PROC(bus));

	/* Get rid of control transfer process */

	usb_proc_free(USB_BUS_CONTROL_XFER_PROC(bus));
#endif

#if USB_HAVE_PF
	usbpf_detach(bus);
#endif
	return (0);
}
示例#2
0
/*------------------------------------------------------------------------*
 *	usb_detach
 *------------------------------------------------------------------------*/
static int
usb_detach(device_t dev)
{
	struct usb_bus *bus = device_get_softc(dev);

	DPRINTF("\n");

	if (bus == NULL) {
		/* was never setup properly */
		return (0);
	}
	/* Stop power watchdog */
	usb_callout_drain(&bus->power_wdog);

	/* Let the USB explore process detach all devices. */
	usb_root_mount_rel(bus);

	USB_BUS_LOCK(bus);

	/* Queue detach job */
	usb_proc_msignal(&bus->explore_proc,
	    &bus->detach_msg[0], &bus->detach_msg[1]);

	/* Wait for detach to complete */
	usb_proc_mwait(&bus->explore_proc,
	    &bus->detach_msg[0], &bus->detach_msg[1]);

#if USB_HAVE_UGEN
	/* Wait for cleanup to complete */
	usb_proc_mwait(&bus->explore_proc,
	    &bus->cleanup_msg[0], &bus->cleanup_msg[1]);
#endif
	USB_BUS_UNLOCK(bus);

	/* Get rid of USB callback processes */

	usb_proc_free(&bus->giant_callback_proc);
	usb_proc_free(&bus->non_giant_callback_proc);

	/* Get rid of USB explore process */

	usb_proc_free(&bus->explore_proc);

	/* Get rid of control transfer process */

	usb_proc_free(&bus->control_xfer_proc);

#if USB_HAVE_PF
	usbpf_detach(bus);
#endif
	return (0);
}
示例#3
0
/*------------------------------------------------------------------------*
 *	usb_proc_create
 *
 * This function will create a process using the given "prio" that can
 * execute callbacks. The mutex pointed to by "p_mtx" will be applied
 * before calling the callbacks and released after that the callback
 * has returned. The structure pointed to by "up" is assumed to be
 * zeroed before this function is called.
 *
 * Return values:
 *    0: success
 * Else: failure
 *------------------------------------------------------------------------*/
int
usb_proc_create(struct usb_process *up, struct mtx *p_mtx,
    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)) {
		DPRINTFN(0, "Unable to create USB process.");
		up->up_ptr = NULL;
		goto error;
	}
#if (__FreeBSD_version >= 800000)
	usb_pcount++;
#endif
	return (0);

error:
	usb_proc_free(up);
	return (ENOMEM);
}
示例#4
0
/*------------------------------------------------------------------------*
 *	usb_proc_create
 *
 * This function will create a process using the given "prio" that can
 * execute callbacks. The mutex pointed to by "p_mtx" will be applied
 * before calling the callbacks and released after that the callback
 * has returned. The structure pointed to by "up" is assumed to be
 * zeroed before this function is called.
 *
 * Return values:
 *    0: success
 * Else: failure
 *------------------------------------------------------------------------*/
int
usb_proc_create(struct usb_process *up, struct lock *p_lock,
    const char *pmesg, uint8_t prio)
{
	up->up_lock = p_lock;
	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)) {
		DPRINTFN(0, "Unable to create USB process.");
		up->up_ptr = NULL;
		goto error;
	}
	usb_pcount++;
	return (0);

error:
	usb_proc_free(up);
	return (ENOMEM);
}
void
uether_ifdetach(struct usb_ether *ue)
{
	struct ifnet *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;

	if (ifp != NULL) {

		/* we are not running any more */
		UE_LOCK(ue);
		ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
		UE_UNLOCK(ue);

		/* drain any callouts */
		usb_callout_drain(&ue->ue_watchdog);

		/* detach miibus */
		if (ue->ue_miibus != NULL) {
			mtx_lock(&Giant);	/* device_xxx() depends on this */
			device_delete_child(ue->ue_dev, ue->ue_miibus);
			mtx_unlock(&Giant);
		}

		/* detach ethernet */
		ether_ifdetach(ifp);

		/* free interface instance */
		if_free(ifp);

		/* free sysctl */
		sysctl_ctx_free(&ue->ue_sysctl_ctx);

		/* free unit */
		free_unr(ueunit, ue->ue_unit);
	}

	/* free taskqueue, if any */
	usb_proc_free(&ue->ue_tq);
}
/*
 * NOTE: the following function will do nothing if
 * the structure pointed to by "ssc" and "sc" is zero.
 */
void
ucom_detach(struct ucom_super_softc *ssc, struct ucom_softc *sc,
    uint32_t sub_units)
{
	uint32_t n;

	usb_proc_drain(&ssc->sc_tq);

	for (n = 0; n != sub_units; n++, sc++) {
		if (sc->sc_flag & UCOM_FLAG_ATTACHED) {

			ucom_detach_tty(sc);

			ucom_units_free(sc->sc_unit, 1);

			/* avoid duplicate detach: */
			sc->sc_flag &= ~UCOM_FLAG_ATTACHED;
		}
	}
	usb_proc_free(&ssc->sc_tq);
}
示例#7
0
/*
 * The following function will do nothing if the structure pointed to
 * by "ssc" and "sc" is zero or has already been detached.
 */
void
ucom_detach(struct ucom_super_softc *ssc, struct ucom_softc *sc)
{
	int subunit;

	if (!(ssc->sc_flag & UCOM_FLAG_ATTACHED))
		return;		/* not initialized */

	if (ssc->sc_sysctl_ttyname != NULL) {
		sysctl_remove_oid(ssc->sc_sysctl_ttyname, 1, 0);
		ssc->sc_sysctl_ttyname = NULL;
	}

	if (ssc->sc_sysctl_ttyports != NULL) {
		sysctl_remove_oid(ssc->sc_sysctl_ttyports, 1, 0);
		ssc->sc_sysctl_ttyports = NULL;
	}

	usb_proc_drain(&ssc->sc_tq);

	for (subunit = 0; subunit < ssc->sc_subunits; subunit++) {
		if (sc[subunit].sc_flag & UCOM_FLAG_ATTACHED) {

			ucom_detach_tty(ssc, &sc[subunit]);

			/* avoid duplicate detach */
			sc[subunit].sc_flag &= ~UCOM_FLAG_ATTACHED;
		}
	}
	usb_proc_free(&ssc->sc_tq);

	ucom_unref(ssc);

	if (ssc->sc_flag & UCOM_FLAG_WAIT_REFS)
		ucom_drain(ssc);

	/* make sure we don't detach twice */
	ssc->sc_flag &= ~UCOM_FLAG_ATTACHED;
}
示例#8
0
void
uether_ifdetach(struct usb_ether *ue)
{
	struct ifnet *ifp;

	/* wait for any post attach or other command to complete */
	usb_proc_drain(&ue->ue_tq);

	/* read "ifnet" pointer after taskqueue drain */
	ifp = uether_getifp(ue);

	if (ifp != NULL) {

		/* we are not running any more */
		UE_LOCK(ue);
		ifp->if_flags &= ~IFF_RUNNING;
		UE_UNLOCK(ue);

		/* drain any callouts */
		usb_callout_drain(&ue->ue_watchdog);

		/* detach miibus */
		if (ue->ue_miibus != NULL) {
			device_delete_child(ue->ue_dev, ue->ue_miibus);
		}

		/* detach ethernet */
		ether_ifdetach(ifp);

		/* free sysctl */
		sysctl_ctx_free(&ue->ue_sysctl_ctx);

		/* free unit */
		devfs_clone_bitmap_put(&DEVFS_CLONE_BITMAP(ue), ue->ue_unit);
	}

	/* free taskqueue, if any */
	usb_proc_free(&ue->ue_tq);
}