mirror of
https://github.com/torvalds/linux.git
synced 2024-10-31 09:11:49 +00:00
USB: add urb->ep
This patch (as943) prepares the way for eliminating urb->pipe by introducing an endpoint pointer into struct urb. For now urb->ep is set by usb_submit_urb() from the pipe value; eventually drivers will set it themselves and we will remove urb->pipe completely. The patch also adds new inline routines to retrieve an endpoint descriptor's number and transfer type, essentially as replacements for usb_pipeendpoint and usb_pipetype. usb_submit_urb(), usb_hcd_submit_urb(), and usb_hcd_unlink_urb() are converted to use the new field and new routines. Other parts of usbcore will be converted in later patches. Signed-off-by: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
parent
a96173af52
commit
5b653c79c0
@ -962,14 +962,14 @@ int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags)
|
|||||||
spin_lock_irqsave(&hcd_urb_list_lock, flags);
|
spin_lock_irqsave(&hcd_urb_list_lock, flags);
|
||||||
ep = (usb_pipein(urb->pipe) ? urb->dev->ep_in : urb->dev->ep_out)
|
ep = (usb_pipein(urb->pipe) ? urb->dev->ep_in : urb->dev->ep_out)
|
||||||
[usb_pipeendpoint(urb->pipe)];
|
[usb_pipeendpoint(urb->pipe)];
|
||||||
if (unlikely (!ep))
|
if (unlikely(ep != urb->ep))
|
||||||
status = -ENOENT;
|
status = -ENOENT;
|
||||||
else if (unlikely (urb->reject))
|
else if (unlikely (urb->reject))
|
||||||
status = -EPERM;
|
status = -EPERM;
|
||||||
else switch (hcd->state) {
|
else switch (hcd->state) {
|
||||||
case HC_STATE_RUNNING:
|
case HC_STATE_RUNNING:
|
||||||
case HC_STATE_RESUMING:
|
case HC_STATE_RESUMING:
|
||||||
list_add_tail (&urb->urb_list, &ep->urb_list);
|
list_add_tail (&urb->urb_list, &urb->ep->urb_list);
|
||||||
status = 0;
|
status = 0;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -1022,7 +1022,7 @@ int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags)
|
|||||||
: DMA_TO_DEVICE);
|
: DMA_TO_DEVICE);
|
||||||
}
|
}
|
||||||
|
|
||||||
status = hcd->driver->urb_enqueue (hcd, ep, urb, mem_flags);
|
status = hcd->driver->urb_enqueue (hcd, urb->ep, urb, mem_flags);
|
||||||
done:
|
done:
|
||||||
if (unlikely (status)) {
|
if (unlikely (status)) {
|
||||||
urb_unlink(hcd, urb);
|
urb_unlink(hcd, urb);
|
||||||
@ -1071,7 +1071,6 @@ unlink1 (struct usb_hcd *hcd, struct urb *urb)
|
|||||||
*/
|
*/
|
||||||
int usb_hcd_unlink_urb (struct urb *urb, int status)
|
int usb_hcd_unlink_urb (struct urb *urb, int status)
|
||||||
{
|
{
|
||||||
struct usb_host_endpoint *ep;
|
|
||||||
struct usb_hcd *hcd = NULL;
|
struct usb_hcd *hcd = NULL;
|
||||||
struct device *sys = NULL;
|
struct device *sys = NULL;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
@ -1082,10 +1081,6 @@ int usb_hcd_unlink_urb (struct urb *urb, int status)
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
if (!urb->dev || !urb->dev->bus)
|
if (!urb->dev || !urb->dev->bus)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
ep = (usb_pipein(urb->pipe) ? urb->dev->ep_in : urb->dev->ep_out)
|
|
||||||
[usb_pipeendpoint(urb->pipe)];
|
|
||||||
if (!ep)
|
|
||||||
return -ENODEV;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* we contend for urb->status with the hcd core,
|
* we contend for urb->status with the hcd core,
|
||||||
@ -1109,7 +1104,7 @@ int usb_hcd_unlink_urb (struct urb *urb, int status)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* insist the urb is still queued */
|
/* insist the urb is still queued */
|
||||||
list_for_each(tmp, &ep->urb_list) {
|
list_for_each(tmp, &urb->ep->urb_list) {
|
||||||
if (tmp == &urb->urb_list)
|
if (tmp == &urb->urb_list)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -277,9 +277,10 @@ EXPORT_SYMBOL_GPL(usb_unanchor_urb);
|
|||||||
*/
|
*/
|
||||||
int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
|
int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
|
||||||
{
|
{
|
||||||
int pipe, temp, max;
|
int xfertype, max;
|
||||||
struct usb_device *dev;
|
struct usb_device *dev;
|
||||||
int is_out;
|
struct usb_host_endpoint *ep;
|
||||||
|
int is_out;
|
||||||
|
|
||||||
if (!urb || urb->hcpriv || !urb->complete)
|
if (!urb || urb->hcpriv || !urb->complete)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
@ -291,30 +292,34 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
|
|||||||
|| dev->state == USB_STATE_SUSPENDED)
|
|| dev->state == USB_STATE_SUSPENDED)
|
||||||
return -EHOSTUNREACH;
|
return -EHOSTUNREACH;
|
||||||
|
|
||||||
|
/* For now, get the endpoint from the pipe. Eventually drivers
|
||||||
|
* will be required to set urb->ep directly and we will eliminate
|
||||||
|
* urb->pipe.
|
||||||
|
*/
|
||||||
|
ep = (usb_pipein(urb->pipe) ? dev->ep_in : dev->ep_out)
|
||||||
|
[usb_pipeendpoint(urb->pipe)];
|
||||||
|
if (!ep)
|
||||||
|
return -ENOENT;
|
||||||
|
|
||||||
|
urb->ep = ep;
|
||||||
urb->status = -EINPROGRESS;
|
urb->status = -EINPROGRESS;
|
||||||
urb->actual_length = 0;
|
urb->actual_length = 0;
|
||||||
|
|
||||||
/* Lots of sanity checks, so HCDs can rely on clean data
|
/* Lots of sanity checks, so HCDs can rely on clean data
|
||||||
* and don't need to duplicate tests
|
* and don't need to duplicate tests
|
||||||
*/
|
*/
|
||||||
pipe = urb->pipe;
|
xfertype = usb_endpoint_type(&ep->desc);
|
||||||
temp = usb_pipetype(pipe);
|
is_out = usb_pipeout(urb->pipe);
|
||||||
is_out = usb_pipeout(pipe);
|
|
||||||
|
|
||||||
if (!usb_pipecontrol(pipe) && dev->state < USB_STATE_CONFIGURED)
|
if (xfertype != USB_ENDPOINT_XFER_CONTROL &&
|
||||||
|
dev->state < USB_STATE_CONFIGURED)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
/* FIXME there should be a sharable lock protecting us against
|
max = le16_to_cpu(ep->desc.wMaxPacketSize);
|
||||||
* config/altsetting changes and disconnects, kicking in here.
|
|
||||||
* (here == before maxpacket, and eventually endpoint type,
|
|
||||||
* checks get made.)
|
|
||||||
*/
|
|
||||||
|
|
||||||
max = usb_maxpacket(dev, pipe, is_out);
|
|
||||||
if (max <= 0) {
|
if (max <= 0) {
|
||||||
dev_dbg(&dev->dev,
|
dev_dbg(&dev->dev,
|
||||||
"bogus endpoint ep%d%s in %s (bad maxpacket %d)\n",
|
"bogus endpoint ep%d%s in %s (bad maxpacket %d)\n",
|
||||||
usb_pipeendpoint(pipe), is_out ? "out" : "in",
|
usb_endpoint_num(&ep->desc), is_out ? "out" : "in",
|
||||||
__FUNCTION__, max);
|
__FUNCTION__, max);
|
||||||
return -EMSGSIZE;
|
return -EMSGSIZE;
|
||||||
}
|
}
|
||||||
@ -323,7 +328,7 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
|
|||||||
* but drivers only control those sizes for ISO.
|
* but drivers only control those sizes for ISO.
|
||||||
* while we're checking, initialize return status.
|
* while we're checking, initialize return status.
|
||||||
*/
|
*/
|
||||||
if (temp == PIPE_ISOCHRONOUS) {
|
if (xfertype == USB_ENDPOINT_XFER_ISOC) {
|
||||||
int n, len;
|
int n, len;
|
||||||
|
|
||||||
/* "high bandwidth" mode, 1-3 packets/uframe? */
|
/* "high bandwidth" mode, 1-3 packets/uframe? */
|
||||||
@ -359,19 +364,19 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
|
|||||||
/* enforce simple/standard policy */
|
/* enforce simple/standard policy */
|
||||||
allowed = (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP |
|
allowed = (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP |
|
||||||
URB_NO_INTERRUPT);
|
URB_NO_INTERRUPT);
|
||||||
switch (temp) {
|
switch (xfertype) {
|
||||||
case PIPE_BULK:
|
case USB_ENDPOINT_XFER_BULK:
|
||||||
if (is_out)
|
if (is_out)
|
||||||
allowed |= URB_ZERO_PACKET;
|
allowed |= URB_ZERO_PACKET;
|
||||||
/* FALLTHROUGH */
|
/* FALLTHROUGH */
|
||||||
case PIPE_CONTROL:
|
case USB_ENDPOINT_XFER_CONTROL:
|
||||||
allowed |= URB_NO_FSBR; /* only affects UHCI */
|
allowed |= URB_NO_FSBR; /* only affects UHCI */
|
||||||
/* FALLTHROUGH */
|
/* FALLTHROUGH */
|
||||||
default: /* all non-iso endpoints */
|
default: /* all non-iso endpoints */
|
||||||
if (!is_out)
|
if (!is_out)
|
||||||
allowed |= URB_SHORT_NOT_OK;
|
allowed |= URB_SHORT_NOT_OK;
|
||||||
break;
|
break;
|
||||||
case PIPE_ISOCHRONOUS:
|
case USB_ENDPOINT_XFER_ISOC:
|
||||||
allowed |= URB_ISO_ASAP;
|
allowed |= URB_ISO_ASAP;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -393,9 +398,9 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
|
|||||||
* supports different values... this uses EHCI/UHCI defaults (and
|
* supports different values... this uses EHCI/UHCI defaults (and
|
||||||
* EHCI can use smaller non-default values).
|
* EHCI can use smaller non-default values).
|
||||||
*/
|
*/
|
||||||
switch (temp) {
|
switch (xfertype) {
|
||||||
case PIPE_ISOCHRONOUS:
|
case USB_ENDPOINT_XFER_ISOC:
|
||||||
case PIPE_INTERRUPT:
|
case USB_ENDPOINT_XFER_INT:
|
||||||
/* too small? */
|
/* too small? */
|
||||||
if (urb->interval <= 0)
|
if (urb->interval <= 0)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
@ -405,29 +410,29 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
|
|||||||
// NOTE usb handles 2^15
|
// NOTE usb handles 2^15
|
||||||
if (urb->interval > (1024 * 8))
|
if (urb->interval > (1024 * 8))
|
||||||
urb->interval = 1024 * 8;
|
urb->interval = 1024 * 8;
|
||||||
temp = 1024 * 8;
|
max = 1024 * 8;
|
||||||
break;
|
break;
|
||||||
case USB_SPEED_FULL: /* units are frames/msec */
|
case USB_SPEED_FULL: /* units are frames/msec */
|
||||||
case USB_SPEED_LOW:
|
case USB_SPEED_LOW:
|
||||||
if (temp == PIPE_INTERRUPT) {
|
if (xfertype == USB_ENDPOINT_XFER_INT) {
|
||||||
if (urb->interval > 255)
|
if (urb->interval > 255)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
// NOTE ohci only handles up to 32
|
// NOTE ohci only handles up to 32
|
||||||
temp = 128;
|
max = 128;
|
||||||
} else {
|
} else {
|
||||||
if (urb->interval > 1024)
|
if (urb->interval > 1024)
|
||||||
urb->interval = 1024;
|
urb->interval = 1024;
|
||||||
// NOTE usb and ohci handle up to 2^15
|
// NOTE usb and ohci handle up to 2^15
|
||||||
temp = 1024;
|
max = 1024;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
/* power of two? */
|
/* power of two? */
|
||||||
while (temp > urb->interval)
|
while (max > urb->interval)
|
||||||
temp >>= 1;
|
max >>= 1;
|
||||||
urb->interval = temp;
|
urb->interval = max;
|
||||||
}
|
}
|
||||||
|
|
||||||
return usb_hcd_submit_urb(urb, mem_flags);
|
return usb_hcd_submit_urb(urb, mem_flags);
|
||||||
|
@ -554,6 +554,29 @@ static inline int usb_make_path (struct usb_device *dev, char *buf,
|
|||||||
|
|
||||||
/*-------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* usb_endpoint_num - get the endpoint's number
|
||||||
|
* @epd: endpoint to be checked
|
||||||
|
*
|
||||||
|
* Returns @epd's number: 0 to 15.
|
||||||
|
*/
|
||||||
|
static inline int usb_endpoint_num(const struct usb_endpoint_descriptor *epd)
|
||||||
|
{
|
||||||
|
return epd->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* usb_endpoint_type - get the endpoint's transfer type
|
||||||
|
* @epd: endpoint to be checked
|
||||||
|
*
|
||||||
|
* Returns one of USB_ENDPOINT_XFER_{CONTROL, ISOC, BULK, INT} according
|
||||||
|
* to @epd's transfer type.
|
||||||
|
*/
|
||||||
|
static inline int usb_endpoint_type(const struct usb_endpoint_descriptor *epd)
|
||||||
|
{
|
||||||
|
return epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* usb_endpoint_dir_in - check if the endpoint has IN direction
|
* usb_endpoint_dir_in - check if the endpoint has IN direction
|
||||||
* @epd: endpoint to be checked
|
* @epd: endpoint to be checked
|
||||||
@ -1037,6 +1060,8 @@ typedef void (*usb_complete_t)(struct urb *);
|
|||||||
* @urb_list: For use by current owner of the URB.
|
* @urb_list: For use by current owner of the URB.
|
||||||
* @anchor_list: membership in the list of an anchor
|
* @anchor_list: membership in the list of an anchor
|
||||||
* @anchor: to anchor URBs to a common mooring
|
* @anchor: to anchor URBs to a common mooring
|
||||||
|
* @ep: Points to the endpoint's data structure. Will eventually
|
||||||
|
* replace @pipe.
|
||||||
* @pipe: Holds endpoint number, direction, type, and more.
|
* @pipe: Holds endpoint number, direction, type, and more.
|
||||||
* Create these values with the eight macros available;
|
* Create these values with the eight macros available;
|
||||||
* usb_{snd,rcv}TYPEpipe(dev,endpoint), where the TYPE is "ctrl"
|
* usb_{snd,rcv}TYPEpipe(dev,endpoint), where the TYPE is "ctrl"
|
||||||
@ -1212,6 +1237,7 @@ struct urb
|
|||||||
struct list_head anchor_list; /* the URB may be anchored by the driver */
|
struct list_head anchor_list; /* the URB may be anchored by the driver */
|
||||||
struct usb_anchor *anchor;
|
struct usb_anchor *anchor;
|
||||||
struct usb_device *dev; /* (in) pointer to associated device */
|
struct usb_device *dev; /* (in) pointer to associated device */
|
||||||
|
struct usb_host_endpoint *ep; /* (internal) pointer to endpoint struct */
|
||||||
unsigned int pipe; /* (in) pipe information */
|
unsigned int pipe; /* (in) pipe information */
|
||||||
int status; /* (return) non-ISO status */
|
int status; /* (return) non-ISO status */
|
||||||
unsigned int transfer_flags; /* (in) URB_SHORT_NOT_OK | ...*/
|
unsigned int transfer_flags; /* (in) URB_SHORT_NOT_OK | ...*/
|
||||||
|
Loading…
Reference in New Issue
Block a user