Commit 8a5f0665da6701f06443ae989e9c0962807a1249

Authored by Hans de Goede
Committed by Simon Glass
1 parent 029fd8ea1f

dm: usb: Add support for interrupt queues to the dm usb code

Interrupt endpoints typically are polled for a long time by the usb
controller before they return anything, so calls to submit_int_msg() can
take a long time to complete this.

To avoid this the u-boot code has the an interrupt queue mechanism / API,
add support for this to the driver-model usb code and implement it for the
dm ehci code.

See the added doc comments for more details.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Acked-by: Simon Glass <sjg@chromium.org>

Showing 3 changed files with 109 additions and 1 deletions Side-by-side Diff

drivers/usb/host/ehci-hcd.c
... ... @@ -1605,6 +1605,29 @@
1605 1605 return _ehci_submit_int_msg(udev, pipe, buffer, length, interval);
1606 1606 }
1607 1607  
  1608 +static struct int_queue *ehci_create_int_queue(struct udevice *dev,
  1609 + struct usb_device *udev, unsigned long pipe, int queuesize,
  1610 + int elementsize, void *buffer, int interval)
  1611 +{
  1612 + debug("%s: dev='%s', udev=%p\n", __func__, dev->name, udev);
  1613 + return _ehci_create_int_queue(udev, pipe, queuesize, elementsize,
  1614 + buffer, interval);
  1615 +}
  1616 +
  1617 +static void *ehci_poll_int_queue(struct udevice *dev, struct usb_device *udev,
  1618 + struct int_queue *queue)
  1619 +{
  1620 + debug("%s: dev='%s', udev=%p\n", __func__, dev->name, udev);
  1621 + return _ehci_poll_int_queue(udev, queue);
  1622 +}
  1623 +
  1624 +static int ehci_destroy_int_queue(struct udevice *dev, struct usb_device *udev,
  1625 + struct int_queue *queue)
  1626 +{
  1627 + debug("%s: dev='%s', udev=%p\n", __func__, dev->name, udev);
  1628 + return _ehci_destroy_int_queue(udev, queue);
  1629 +}
  1630 +
1608 1631 int ehci_register(struct udevice *dev, struct ehci_hccr *hccr,
1609 1632 struct ehci_hcor *hcor, const struct ehci_ops *ops,
1610 1633 uint tweaks, enum usb_init_type init)
... ... @@ -1653,6 +1676,9 @@
1653 1676 .control = ehci_submit_control_msg,
1654 1677 .bulk = ehci_submit_bulk_msg,
1655 1678 .interrupt = ehci_submit_int_msg,
  1679 + .create_int_queue = ehci_create_int_queue,
  1680 + .poll_int_queue = ehci_poll_int_queue,
  1681 + .destroy_int_queue = ehci_destroy_int_queue,
1656 1682 };
1657 1683  
1658 1684 #endif
drivers/usb/host/usb-uclass.c
... ... @@ -65,6 +65,42 @@
65 65 return ops->bulk(bus, udev, pipe, buffer, length);
66 66 }
67 67  
  68 +struct int_queue *create_int_queue(struct usb_device *udev,
  69 + unsigned long pipe, int queuesize, int elementsize,
  70 + void *buffer, int interval)
  71 +{
  72 + struct udevice *bus = udev->controller_dev;
  73 + struct dm_usb_ops *ops = usb_get_ops(bus);
  74 +
  75 + if (!ops->create_int_queue)
  76 + return NULL;
  77 +
  78 + return ops->create_int_queue(bus, udev, pipe, queuesize, elementsize,
  79 + buffer, interval);
  80 +}
  81 +
  82 +void *poll_int_queue(struct usb_device *udev, struct int_queue *queue)
  83 +{
  84 + struct udevice *bus = udev->controller_dev;
  85 + struct dm_usb_ops *ops = usb_get_ops(bus);
  86 +
  87 + if (!ops->poll_int_queue)
  88 + return NULL;
  89 +
  90 + return ops->poll_int_queue(bus, udev, queue);
  91 +}
  92 +
  93 +int destroy_int_queue(struct usb_device *udev, struct int_queue *queue)
  94 +{
  95 + struct udevice *bus = udev->controller_dev;
  96 + struct dm_usb_ops *ops = usb_get_ops(bus);
  97 +
  98 + if (!ops->destroy_int_queue)
  99 + return -ENOSYS;
  100 +
  101 + return ops->destroy_int_queue(bus, udev, queue);
  102 +}
  103 +
68 104 int usb_alloc_device(struct usb_device *udev)
69 105 {
70 106 struct udevice *bus = udev->controller_dev;
... ... @@ -198,7 +198,7 @@
198 198 int submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
199 199 int transfer_len, int interval);
200 200  
201   -#if defined CONFIG_USB_EHCI || defined CONFIG_MUSB_HOST
  201 +#if defined CONFIG_USB_EHCI || defined CONFIG_MUSB_HOST || defined(CONFIG_DM_USB)
202 202 struct int_queue *create_int_queue(struct usb_device *dev, unsigned long pipe,
203 203 int queuesize, int elementsize, void *buffer, int interval);
204 204 int destroy_int_queue(struct usb_device *dev, struct int_queue *queue);
... ... @@ -660,6 +660,52 @@
660 660 int (*interrupt)(struct udevice *bus, struct usb_device *udev,
661 661 unsigned long pipe, void *buffer, int length,
662 662 int interval);
  663 +
  664 + /**
  665 + * create_int_queue() - Create and queue interrupt packets
  666 + *
  667 + * Create and queue @queuesize number of interrupt usb packets of
  668 + * @elementsize bytes each. @buffer must be atleast @queuesize *
  669 + * @elementsize bytes.
  670 + *
  671 + * Note some controllers only support a queuesize of 1.
  672 + *
  673 + * @interval: Interrupt interval
  674 + *
  675 + * @return A pointer to the created interrupt queue or NULL on error
  676 + */
  677 + struct int_queue * (*create_int_queue)(struct udevice *bus,
  678 + struct usb_device *udev, unsigned long pipe,
  679 + int queuesize, int elementsize, void *buffer,
  680 + int interval);
  681 +
  682 + /**
  683 + * poll_int_queue() - Poll an interrupt queue for completed packets
  684 + *
  685 + * Poll an interrupt queue for completed packets. The return value
  686 + * points to the part of the buffer passed to create_int_queue()
  687 + * corresponding to the completed packet.
  688 + *
  689 + * @queue: queue to poll
  690 + *
  691 + * @return Pointer to the data of the first completed packet, or
  692 + * NULL if no packets are ready
  693 + */
  694 + void * (*poll_int_queue)(struct udevice *bus, struct usb_device *udev,
  695 + struct int_queue *queue);
  696 +
  697 + /**
  698 + * destroy_int_queue() - Destroy an interrupt queue
  699 + *
  700 + * Destroy an interrupt queue created by create_int_queue().
  701 + *
  702 + * @queue: queue to poll
  703 + *
  704 + * @return 0 if OK, -ve on error
  705 + */
  706 + int (*destroy_int_queue)(struct udevice *bus, struct usb_device *udev,
  707 + struct int_queue *queue);
  708 +
663 709 /**
664 710 * alloc_device() - Allocate a new device context (XHCI)
665 711 *