static void ue_queue_command(struct usb_ether *ue, usb_proc_callback_t *fn, struct usb_proc_msg *t0, struct usb_proc_msg *t1) { struct usb_ether_cfg_task *task; UE_LOCK_ASSERT(ue, MA_OWNED); if (usb_proc_is_gone(&ue->ue_tq)) { return; /* nothing to do */ } /* * NOTE: The task cannot get executed before we drop the * "sc_mtx" mutex. It is safe to update fields in the message * structure after that the message got queued. */ task = (struct usb_ether_cfg_task *) usb_proc_msignal(&ue->ue_tq, t0, t1); /* Setup callback and self pointers */ task->hdr.pm_callback = fn; task->ue = ue; /* * Start and stop must be synchronous! */ if ((fn == ue_start_task) || (fn == ue_stop_task)) usb_proc_mwait(&ue->ue_tq, t0, t1); }
/* * Return values: * 0: normal * else: taskqueue is draining or gone */ uint8_t ucom_cfg_is_gone(struct ucom_softc *sc) { struct ucom_super_softc *ssc = sc->sc_super; return (usb_proc_is_gone(&ssc->sc_tq)); }
/*------------------------------------------------------------------------* * usbd_do_request_proc - factored out code * * This function is factored out code. It does basically the same like * usbd_do_request_flags, except it will check the status of the * passed process argument before doing the USB request. If the * process is draining the USB_ERR_IOERROR code will be returned. It * is assumed that the mutex associated with the process is locked * when calling this function. *------------------------------------------------------------------------*/ usb_error_t usbd_do_request_proc(struct usb_device *udev, struct usb_process *pproc, struct usb_device_request *req, void *data, uint16_t flags, uint16_t *actlen, usb_timeout_t timeout) { usb_error_t err; uint16_t len; /* get request data length */ len = UGETW(req->wLength); /* check if the device is being detached */ if (usb_proc_is_gone(pproc)) { err = USB_ERR_IOERROR; goto done; } /* forward the USB request */ err = usbd_do_request_flags(udev, pproc->up_mtx, req, data, flags, actlen, timeout); done: /* on failure we zero the data */ /* on short packet we zero the unused data */ if ((len != 0) && (req->bmRequestType & UE_DIR_IN)) { if (err) memset(data, 0, len); else if (actlen && *actlen != len) memset(((uint8_t *)data) + *actlen, 0, len - *actlen); } return (err); }
/* * Return values: * 0: success * Else: device has been detached */ uint8_t uether_pause(struct usb_ether *ue, unsigned int _ticks) { if (usb_proc_is_gone(&ue->ue_tq)) { /* nothing to do */ return (1); } usb_pause_mtx(ue->ue_mtx, _ticks); return (0); }
static void ucom_queue_command(struct ucom_softc *sc, usb_proc_callback_t *fn, struct termios *pt, struct usb_proc_msg *t0, struct usb_proc_msg *t1) { struct ucom_super_softc *ssc = sc->sc_super; struct ucom_param_task *task; UCOM_MTX_ASSERT(sc, MA_OWNED); if (usb_proc_is_gone(&ssc->sc_tq)) { DPRINTF("proc is gone\n"); return; /* nothing to do */ } /* * NOTE: The task cannot get executed before we drop the * "sc_mtx" mutex. It is safe to update fields in the message * structure after that the message got queued. */ task = (struct ucom_param_task *) usb_proc_msignal(&ssc->sc_tq, t0, t1); /* Setup callback and softc pointers */ task->hdr.pm_callback = fn; task->sc = sc; /* * Make a copy of the termios. This field is only present if * the "pt" field is not NULL. */ if (pt != NULL) task->termios_copy = *pt; /* * Closing the device should be synchronous. */ if (fn == ucom_cfg_close) usb_proc_mwait(&ssc->sc_tq, t0, t1); /* * In case of multiple configure requests, * keep track of the last one! */ if (fn == ucom_cfg_start_transfers) sc->sc_last_start_xfer = &task->hdr; }
uint8_t uether_is_gone(struct usb_ether *ue) { return (usb_proc_is_gone(&ue->ue_tq)); }