123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104 |
- From 7492e29b5535ca9694e45d6ca600a35169b690ec Mon Sep 17 00:00:00 2001
- From: Jonathan Bell <[email protected]>
- Date: Tue, 11 Jun 2019 10:55:00 +0100
- Subject: [PATCH] usb: add plumbing for updating interrupt endpoint
- interval state
- xHCI caches device and endpoint data after the interface is configured,
- so an explicit command needs to be issued for any device driver wanting
- to alter the polling interval of an endpoint.
- Add usb_fixup_endpoint() to allow drivers to do this. The fixup must be
- called after calculating endpoint bandwidth requirements but before any
- URBs are submitted.
- If polling intervals are shortened, any bandwidth reservations are no
- longer valid but in practice polling intervals are only ever relaxed.
- Limit the scope to interrupt transfers for now.
- Signed-off-by: Jonathan Bell <[email protected]>
- ---
- drivers/usb/core/hcd.c | 10 ++++++++++
- drivers/usb/core/message.c | 15 +++++++++++++++
- include/linux/usb.h | 2 ++
- include/linux/usb/hcd.h | 7 +++++++
- 4 files changed, 34 insertions(+)
- --- a/drivers/usb/core/hcd.c
- +++ b/drivers/usb/core/hcd.c
- @@ -1977,6 +1977,16 @@ reset:
- return ret;
- }
-
- +void usb_hcd_fixup_endpoint(struct usb_device *udev,
- + struct usb_host_endpoint *ep, int interval)
- +{
- + struct usb_hcd *hcd;
- +
- + hcd = bus_to_hcd(udev->bus);
- + if (hcd->driver->fixup_endpoint)
- + hcd->driver->fixup_endpoint(hcd, udev, ep, interval);
- +}
- +
- /* Disables the endpoint: synchronizes with the hcd to make sure all
- * endpoint state is gone from hardware. usb_hcd_flush_endpoint() must
- * have been called previously. Use for set_configuration, set_interface,
- --- a/drivers/usb/core/message.c
- +++ b/drivers/usb/core/message.c
- @@ -1263,6 +1263,21 @@ static void remove_intf_ep_devs(struct u
- intf->ep_devs_created = 0;
- }
-
- +void usb_fixup_endpoint(struct usb_device *dev, int epaddr, int interval)
- +{
- + unsigned int epnum = epaddr & USB_ENDPOINT_NUMBER_MASK;
- + struct usb_host_endpoint *ep;
- +
- + if (usb_endpoint_out(epaddr))
- + ep = dev->ep_out[epnum];
- + else
- + ep = dev->ep_in[epnum];
- +
- + if (ep && usb_endpoint_xfer_int(&ep->desc))
- + usb_hcd_fixup_endpoint(dev, ep, interval);
- +}
- +EXPORT_SYMBOL_GPL(usb_fixup_endpoint);
- +
- /**
- * usb_disable_endpoint -- Disable an endpoint by address
- * @dev: the device whose endpoint is being disabled
- --- a/include/linux/usb.h
- +++ b/include/linux/usb.h
- @@ -1843,6 +1843,8 @@ extern int usb_clear_halt(struct usb_dev
- extern int usb_reset_configuration(struct usb_device *dev);
- extern int usb_set_interface(struct usb_device *dev, int ifnum, int alternate);
- extern void usb_reset_endpoint(struct usb_device *dev, unsigned int epaddr);
- +extern void usb_fixup_endpoint(struct usb_device *dev, int epaddr,
- + int interval);
-
- /* this request isn't really synchronous, but it belongs with the others */
- extern int usb_driver_set_configuration(struct usb_device *udev, int config);
- --- a/include/linux/usb/hcd.h
- +++ b/include/linux/usb/hcd.h
- @@ -371,6 +371,11 @@ struct hc_driver {
- * or bandwidth constraints.
- */
- void (*reset_bandwidth)(struct usb_hcd *, struct usb_device *);
- + /* Override the endpoint-derived interval
- + * (if there is any cached hardware state).
- + */
- + void (*fixup_endpoint)(struct usb_hcd *hcd, struct usb_device *udev,
- + struct usb_host_endpoint *ep, int interval);
- /* Returns the hardware-chosen device address */
- int (*address_device)(struct usb_hcd *, struct usb_device *udev);
- /* prepares the hardware to send commands to the device */
- @@ -435,6 +440,8 @@ extern void usb_hcd_unmap_urb_setup_for_
- extern void usb_hcd_unmap_urb_for_dma(struct usb_hcd *, struct urb *);
- extern void usb_hcd_flush_endpoint(struct usb_device *udev,
- struct usb_host_endpoint *ep);
- +extern void usb_hcd_fixup_endpoint(struct usb_device *udev,
- + struct usb_host_endpoint *ep, int interval);
- extern void usb_hcd_disable_endpoint(struct usb_device *udev,
- struct usb_host_endpoint *ep);
- extern void usb_hcd_reset_endpoint(struct usb_device *udev,
|