HCDs always needed a per-endpoint queue; this makes
usbcore implement it.
This patch changes the HCD glue code to use the URB queue now kept in
usb_host_endpoint, and matching HCD API changes.

Signed-off-by: David Brownell <[EMAIL PROTECTED]>

--- epmax/drivers/usb/core/config.c	2004-11-27 23:06:08.000000000 -0800
+++ hdev/drivers/usb/core/config.c	2004-11-28 01:49:39.000000000 -0800
@@ -88,6 +88,7 @@
 
 	memcpy(&endpoint->desc, d, n);
 	le16_to_cpus(&endpoint->desc.wMaxPacketSize);
+	INIT_LIST_HEAD(&endpoint->urb_list);
 
 	/* Skip over any Class Specific or Vendor Specific descriptors;
 	 * find the next endpoint or interface descriptor */
--- epmax/drivers/usb/core/hcd.c	2004-11-27 23:29:53.000000000 -0800
+++ hdev/drivers/usb/core/hcd.c	2004-11-28 03:03:48.343773272 -0800
@@ -1079,10 +1079,12 @@
 {
 	int			status;
 	struct usb_hcd		*hcd = urb->dev->bus->hcpriv;
-	struct hcd_dev		*dev = urb->dev->hcpriv;
+	struct usb_host_endpoint *ep;
 	unsigned long		flags;
 
-	if (!hcd || !dev)
+	ep = (usb_pipein(urb->pipe) ? urb->dev->ep_in : urb->dev->ep_out)
+			[usb_pipeendpoint(urb->pipe)];
+	if (!hcd || !ep)
 		return -ENODEV;
 
 	/*
@@ -1109,7 +1111,7 @@
 	case USB_STATE_RUNNING:
 	case USB_STATE_RESUMING:
 		usb_get_dev (urb->dev);
-		list_add_tail (&urb->urb_list, &dev->urb_list);
+		list_add_tail (&urb->urb_list, &ep->urb_list);
 		status = 0;
 		break;
 	default:
@@ -1163,7 +1165,7 @@
 					    : DMA_TO_DEVICE);
 	}
 
-	status = hcd->driver->urb_enqueue (hcd, urb, mem_flags);
+	status = hcd->driver->urb_enqueue (hcd, ep, urb, mem_flags);
 done:
 	if (unlikely (status)) {
 		urb_unlink (urb);
@@ -1222,7 +1224,7 @@
  */
 static int hcd_unlink_urb (struct urb *urb, int status)
 {
-	struct hcd_dev			*dev;
+	struct usb_host_endpoint	*ep;
 	struct usb_hcd			*hcd = NULL;
 	struct device			*sys = NULL;
 	unsigned long			flags;
@@ -1231,6 +1233,12 @@
 
 	if (!urb)
 		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,
@@ -1246,15 +1254,9 @@
 	spin_lock_irqsave (&urb->lock, flags);
 	spin_lock (&hcd_data_lock);
 
-	if (!urb->dev || !urb->dev->bus) {
-		retval = -ENODEV;
-		goto done;
-	}
-
-	dev = urb->dev->hcpriv;
 	sys = &urb->dev->dev;
 	hcd = urb->dev->bus->hcpriv;
-	if (!dev || !hcd) {
+	if (hcd == NULL) {
 		retval = -ENODEV;
 		goto done;
 	}
@@ -1266,7 +1268,7 @@
 	WARN_ON (!HCD_IS_RUNNING (hcd->state) && hcd->state != USB_STATE_HALT);
 
 	/* insist the urb is still queued */
-	list_for_each(tmp, &dev->urb_list) {
+	list_for_each(tmp, &ep->urb_list) {
 		if (tmp == &urb->urb_list)
 			break;
 	}
@@ -1319,40 +1321,36 @@
  * the hcd to make sure all endpoint state is gone from hardware. use for
  * set_configuration, set_interface, driver removal, physical disconnect.
  *
- * example:  a qh stored in hcd_dev.ep[], holding state related to endpoint
+ * example:  a qh stored in ep->hcpriv, holding state related to endpoint
  * type, maxpacket size, toggle, halt status, and scheduling.
  */
-static void hcd_endpoint_disable (struct usb_device *udev, int endpoint)
+static void
+hcd_endpoint_disable (struct usb_device *udev, struct usb_host_endpoint *ep)
 {
-	struct hcd_dev	*dev;
-	struct usb_hcd	*hcd;
-	struct urb	*urb;
-	unsigned	epnum = endpoint & USB_ENDPOINT_NUMBER_MASK;
+	struct usb_hcd		*hcd;
+	struct urb		*urb;
 
-	dev = udev->hcpriv;
 	hcd = udev->bus->hcpriv;
 
 	WARN_ON (!HCD_IS_RUNNING (hcd->state) && hcd->state != USB_STATE_HALT);
 
 	local_irq_disable ();
 
+	/* FIXME move most of this into message.c as part of its
+	 * endpoint disable logic
+	 */
+
 	/* ep is already gone from udev->ep_{in,out}[]; no more submits */
 rescan:
 	spin_lock (&hcd_data_lock);
-	list_for_each_entry (urb, &dev->urb_list, urb_list) {
-		int	tmp = urb->pipe;
-
-		/* ignore urbs for other endpoints */
-		if (usb_pipeendpoint (tmp) != epnum)
-			continue;
-		/* NOTE assumption that only ep0 is a control endpoint */
-		if (epnum != 0 && ((tmp ^ endpoint) & USB_DIR_IN))
-			continue;
+	list_for_each_entry (urb, &ep->urb_list, urb_list) {
+		int	tmp;
 
 		/* another cpu may be in hcd, spinning on hcd_data_lock
 		 * to giveback() this urb.  the races here should be
 		 * small, but a full fix needs a new "can't submit"
 		 * urb state.
+		 * FIXME urb->reject should allow that...
 		 */
 		if (urb->status != -EINPROGRESS)
 			continue;
@@ -1394,7 +1392,7 @@
 	 */
 	might_sleep ();
 	if (hcd->driver->endpoint_disable)
-		hcd->driver->endpoint_disable (hcd, dev, endpoint);
+		hcd->driver->endpoint_disable (hcd, ep);
 }
 
 /*-------------------------------------------------------------------------*/
--- epmax/drivers/usb/core/message.c	2004-11-27 23:33:11.000000000 -0800
+++ hdev/drivers/usb/core/message.c	2004-11-28 01:49:39.000000000 -0800
@@ -932,7 +932,7 @@
 		dev->ep_in[epnum] = NULL;
 	}
 	if (ep && dev->bus && dev->bus->op && dev->bus->op->disable)
-		dev->bus->op->disable(dev, ep->desc.bEndpointAddress);
+		dev->bus->op->disable(dev, ep);
 }
 
 /**
--- epmax/drivers/usb/core/usb.c	2004-11-27 23:25:45.000000000 -0800
+++ hdev/drivers/usb/core/usb.c	2004-11-28 03:03:48.349772360 -0800
@@ -690,6 +690,7 @@
 	dev->dev.release = usb_release_dev;
 	dev->state = USB_STATE_ATTACHED;
 
+	INIT_LIST_HEAD(&dev->ep0.urb_list);
 	dev->ep0.desc.bLength = USB_DT_ENDPOINT_SIZE;
 	dev->ep0.desc.bDescriptorType = USB_DT_ENDPOINT;
 	/* ep0 maxpacket comes later, from device descriptor */

Reply via email to