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 */