[PATCH 009/142] USB: add urb->ep

Greg Kroah-Hartman <[email protected]>
Newsgroups gmane.linux.usb.devel
Message-ID <[email protected]>
From: Alan Stern <[email protected]>

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 <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
 drivers/usb/core/hcd.c |   13 +++------
 drivers/usb/core/urb.c |   65 +++++++++++++++++++++++++----------------------
 include/linux/usb.h    |   26 +++++++++++++++++++
 3 files changed, 65 insertions(+), 39 deletions(-)

diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index 42ef1d5..fb82c50 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -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;
 	}
diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c
index be63022..ff53acb 100644
--- a/drivers/usb/core/urb.c
+++ b/drivers/usb/core/urb.c
@@ -277,9 +277,10 @@ EXPORT_SYMBOL_GPL(usb_unanchor_urb);
  */
 int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
 {
-	int			pipe, temp, max;
-	struct usb_device	*dev;
-	int			is_out;
+	int				xfertype, max;
+	struct usb_device		*dev;
+	struct usb_host_endpoint	*ep;
+	int				is_out;
 
 	if (!urb || urb->hcpriv || !urb->complete)
 		return -EINVAL;
@@ -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);
diff --git a/include/linux/usb.h b/include/linux/usb.h
index 4f33a58..105e3e9 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -555,6 +555,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 | ...*/
-- 
1.5.3.4


-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems?  Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/
_______________________________________________
[email protected]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.