Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5b653c79 authored by Alan Stern's avatar Alan Stern Committed by Greg Kroah-Hartman
Browse files

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: default avatarAlan Stern <stern@rowland.harvard.edu>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent a96173af
Loading
Loading
Loading
Loading
+4 −9
Original line number Diff line number Diff line
@@ -962,14 +962,14 @@ int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags)
	spin_lock_irqsave(&hcd_urb_list_lock, flags);
	ep = (usb_pipein(urb->pipe) ? urb->dev->ep_in : urb->dev->ep_out)
			[usb_pipeendpoint(urb->pipe)];
	if (unlikely (!ep))
	if (unlikely(ep != urb->ep))
		status = -ENOENT;
	else if (unlikely (urb->reject))
		status = -EPERM;
	else switch (hcd->state) {
	case HC_STATE_RUNNING:
	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;
		break;
	default:
@@ -1022,7 +1022,7 @@ int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags)
					    : 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:
	if (unlikely (status)) {
		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)
{
	struct usb_host_endpoint	*ep;
	struct usb_hcd			*hcd = NULL;
	struct device			*sys = NULL;
	unsigned long			flags;
@@ -1082,10 +1081,6 @@ int usb_hcd_unlink_urb (struct urb *urb, int status)
		return -EINVAL;
	if (!urb->dev || !urb->dev->bus)
		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,
@@ -1109,7 +1104,7 @@ int usb_hcd_unlink_urb (struct urb *urb, int status)
	}

	/* 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)
			break;
	}
+35 −30
Original line number Diff line number Diff line
@@ -277,8 +277,9 @@ EXPORT_SYMBOL_GPL(usb_unanchor_urb);
 */
int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
{
	int			pipe, temp, max;
	int				xfertype, max;
	struct usb_device		*dev;
	struct usb_host_endpoint	*ep;
	int				is_out;

	if (!urb || urb->hcpriv || !urb->complete)
@@ -291,30 +292,34 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
			|| dev->state == USB_STATE_SUSPENDED)
		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->actual_length = 0;

	/* Lots of sanity checks, so HCDs can rely on clean data
	 * and don't need to duplicate tests
	 */
	pipe = urb->pipe;
	temp = usb_pipetype(pipe);
	is_out = usb_pipeout(pipe);
	xfertype = usb_endpoint_type(&ep->desc);
	is_out = usb_pipeout(urb->pipe);

	if (!usb_pipecontrol(pipe) && dev->state < USB_STATE_CONFIGURED)
	if (xfertype != USB_ENDPOINT_XFER_CONTROL &&
			dev->state < USB_STATE_CONFIGURED)
		return -ENODEV;

	/* FIXME there should be a sharable lock protecting us against
	 * 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);
	max = le16_to_cpu(ep->desc.wMaxPacketSize);
	if (max <= 0) {
		dev_dbg(&dev->dev,
			"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);
		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.
	 * while we're checking, initialize return status.
	 */
	if (temp == PIPE_ISOCHRONOUS) {
	if (xfertype == USB_ENDPOINT_XFER_ISOC) {
		int	n, len;

		/* "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 */
	allowed = (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP |
			URB_NO_INTERRUPT);
	switch (temp) {
	case PIPE_BULK:
	switch (xfertype) {
	case USB_ENDPOINT_XFER_BULK:
		if (is_out)
			allowed |= URB_ZERO_PACKET;
		/* FALLTHROUGH */
	case PIPE_CONTROL:
	case USB_ENDPOINT_XFER_CONTROL:
		allowed |= URB_NO_FSBR;	/* only affects UHCI */
		/* FALLTHROUGH */
	default:			/* all non-iso endpoints */
		if (!is_out)
			allowed |= URB_SHORT_NOT_OK;
		break;
	case PIPE_ISOCHRONOUS:
	case USB_ENDPOINT_XFER_ISOC:
		allowed |= URB_ISO_ASAP;
		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
	 * EHCI can use smaller non-default values).
	 */
	switch (temp) {
	case PIPE_ISOCHRONOUS:
	case PIPE_INTERRUPT:
	switch (xfertype) {
	case USB_ENDPOINT_XFER_ISOC:
	case USB_ENDPOINT_XFER_INT:
		/* too small? */
		if (urb->interval <= 0)
			return -EINVAL;
@@ -405,29 +410,29 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
			// NOTE usb handles 2^15
			if (urb->interval > (1024 * 8))
				urb->interval = 1024 * 8;
			temp = 1024 * 8;
			max = 1024 * 8;
			break;
		case USB_SPEED_FULL:	/* units are frames/msec */
		case USB_SPEED_LOW:
			if (temp == PIPE_INTERRUPT) {
			if (xfertype == USB_ENDPOINT_XFER_INT) {
				if (urb->interval > 255)
					return -EINVAL;
				// NOTE ohci only handles up to 32
				temp = 128;
				max = 128;
			} else {
				if (urb->interval > 1024)
					urb->interval = 1024;
				// NOTE usb and ohci handle up to 2^15
				temp = 1024;
				max = 1024;
			}
			break;
		default:
			return -EINVAL;
		}
		/* power of two? */
		while (temp > urb->interval)
			temp >>= 1;
		urb->interval = temp;
		while (max > urb->interval)
			max >>= 1;
		urb->interval = max;
	}

	return usb_hcd_submit_urb(urb, mem_flags);
+26 −0
Original line number Diff line number Diff line
@@ -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
 * @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.
 * @anchor_list: membership in the list of an anchor
 * @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.
 *	Create these values with the eight macros available;
 *	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 usb_anchor *anchor;
	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 */
	int status;			/* (return) non-ISO status */
	unsigned int transfer_flags;	/* (in) URB_SHORT_NOT_OK | ...*/