USB CORE - compat Linux:
- Patch request from Tim Borgeaud: - add automatic locking - add refcount for killing URB's Submitted by: hps Approved by: re
This commit is contained in:
parent
a0c61406ad
commit
bf3254f22e
@ -398,15 +398,32 @@ int
|
||||
usb_submit_urb(struct urb *urb, uint16_t mem_flags)
|
||||
{
|
||||
struct usb_host_endpoint *uhe;
|
||||
uint8_t do_unlock;
|
||||
int err;
|
||||
|
||||
if (urb == NULL) {
|
||||
if (urb == NULL)
|
||||
return (-EINVAL);
|
||||
}
|
||||
mtx_assert(&Giant, MA_OWNED);
|
||||
|
||||
do_unlock = mtx_owned(&Giant) ? 0 : 1;
|
||||
if (do_unlock)
|
||||
mtx_lock(&Giant);
|
||||
|
||||
if (urb->endpoint == NULL) {
|
||||
return (-EINVAL);
|
||||
err = -EINVAL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check to see if the urb is in the process of being killed
|
||||
* and stop a urb that is in the process of being killed from
|
||||
* being re-submitted (e.g. from its completion callback
|
||||
* function).
|
||||
*/
|
||||
if (urb->kill_count != 0) {
|
||||
err = -EPERM;
|
||||
goto done;
|
||||
}
|
||||
|
||||
uhe = urb->endpoint;
|
||||
|
||||
/*
|
||||
@ -424,12 +441,16 @@ usb_submit_urb(struct urb *urb, uint16_t mem_flags)
|
||||
|
||||
usbd_transfer_start(uhe->bsd_xfer[0]);
|
||||
usbd_transfer_start(uhe->bsd_xfer[1]);
|
||||
err = 0;
|
||||
} else {
|
||||
/* no pipes have been setup yet! */
|
||||
urb->status = -EINVAL;
|
||||
return (-EINVAL);
|
||||
err = -EINVAL;
|
||||
}
|
||||
return (0);
|
||||
done:
|
||||
if (do_unlock)
|
||||
mtx_unlock(&Giant);
|
||||
return (err);
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*
|
||||
@ -448,9 +469,11 @@ static void
|
||||
usb_unlink_bsd(struct usb_xfer *xfer,
|
||||
struct urb *urb, uint8_t drain)
|
||||
{
|
||||
if (xfer &&
|
||||
usbd_transfer_pending(xfer) &&
|
||||
(xfer->priv_fifo == (void *)urb)) {
|
||||
if (xfer == NULL)
|
||||
return;
|
||||
if (!usbd_transfer_pending(xfer))
|
||||
return;
|
||||
if (xfer->priv_fifo == (void *)urb) {
|
||||
if (drain) {
|
||||
mtx_unlock(&Giant);
|
||||
usbd_transfer_drain(xfer);
|
||||
@ -467,14 +490,21 @@ usb_unlink_urb_sub(struct urb *urb, uint8_t drain)
|
||||
{
|
||||
struct usb_host_endpoint *uhe;
|
||||
uint16_t x;
|
||||
uint8_t do_unlock;
|
||||
int err;
|
||||
|
||||
if (urb == NULL) {
|
||||
if (urb == NULL)
|
||||
return (-EINVAL);
|
||||
}
|
||||
mtx_assert(&Giant, MA_OWNED);
|
||||
|
||||
do_unlock = mtx_owned(&Giant) ? 0 : 1;
|
||||
if (do_unlock)
|
||||
mtx_lock(&Giant);
|
||||
if (drain)
|
||||
urb->kill_count++;
|
||||
|
||||
if (urb->endpoint == NULL) {
|
||||
return (-EINVAL);
|
||||
err = -EINVAL;
|
||||
goto done;
|
||||
}
|
||||
uhe = urb->endpoint;
|
||||
|
||||
@ -504,7 +534,13 @@ usb_unlink_urb_sub(struct urb *urb, uint8_t drain)
|
||||
usb_unlink_bsd(uhe->bsd_xfer[0], urb, drain);
|
||||
usb_unlink_bsd(uhe->bsd_xfer[1], urb, drain);
|
||||
}
|
||||
return (0);
|
||||
err = 0;
|
||||
done:
|
||||
if (drain)
|
||||
urb->kill_count--;
|
||||
if (do_unlock)
|
||||
mtx_unlock(&Giant);
|
||||
return (err);
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*
|
||||
@ -555,6 +591,7 @@ static int
|
||||
usb_start_wait_urb(struct urb *urb, usb_timeout_t timeout, uint16_t *p_actlen)
|
||||
{
|
||||
int err;
|
||||
uint8_t do_unlock;
|
||||
|
||||
/* you must have a timeout! */
|
||||
if (timeout == 0) {
|
||||
@ -565,6 +602,9 @@ usb_start_wait_urb(struct urb *urb, usb_timeout_t timeout, uint16_t *p_actlen)
|
||||
urb->transfer_flags |= URB_WAIT_WAKEUP;
|
||||
urb->transfer_flags &= ~URB_IS_SLEEPING;
|
||||
|
||||
do_unlock = mtx_owned(&Giant) ? 0 : 1;
|
||||
if (do_unlock)
|
||||
mtx_lock(&Giant);
|
||||
err = usb_submit_urb(urb, 0);
|
||||
if (err)
|
||||
goto done;
|
||||
@ -582,6 +622,8 @@ usb_start_wait_urb(struct urb *urb, usb_timeout_t timeout, uint16_t *p_actlen)
|
||||
err = urb->status;
|
||||
|
||||
done:
|
||||
if (do_unlock)
|
||||
mtx_unlock(&Giant);
|
||||
if (err) {
|
||||
*p_actlen = 0;
|
||||
} else {
|
||||
@ -638,7 +680,7 @@ usb_control_msg(struct usb_device *dev, struct usb_host_endpoint *uhe,
|
||||
* transfers on control endpoint zero:
|
||||
*/
|
||||
err = usbd_do_request_flags(dev,
|
||||
&Giant, &req, data, USB_SHORT_XFER_OK,
|
||||
NULL, &req, data, USB_SHORT_XFER_OK,
|
||||
&actlen, timeout);
|
||||
if (err) {
|
||||
err = -EPIPE;
|
||||
@ -1216,9 +1258,7 @@ usb_init_urb(struct urb *urb)
|
||||
void
|
||||
usb_kill_urb(struct urb *urb)
|
||||
{
|
||||
if (usb_unlink_urb_sub(urb, 1)) {
|
||||
/* ignore */
|
||||
}
|
||||
usb_unlink_urb_sub(urb, 1);
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*
|
||||
|
@ -262,6 +262,7 @@ struct urb {
|
||||
uint8_t setup_dma; /* (in) not used on FreeBSD */
|
||||
uint8_t transfer_dma; /* (in) not used on FreeBSD */
|
||||
uint8_t bsd_isread;
|
||||
uint8_t kill_count; /* FreeBSD specific */
|
||||
|
||||
struct usb_iso_packet_descriptor iso_frame_desc[]; /* (in) ISO ONLY */
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user