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>

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 @@
 	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 @@
 					    : 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 @@
  */
 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 @@
 		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 @@
 	}
 
 	/* 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 @@
  */
 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 @@
 			|| 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 @@
 	 * 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 @@
 	/* 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 @@
 	 * 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 @@
 			// 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);