brcm2708: organize kernel patches
[openwrt/staging/wigyori.git] / target / linux / brcm2708 / patches-4.19 / 950-0601-usb-add-plumbing-for-updating-interrupt-endpoint-int.patch
diff --git a/target/linux/brcm2708/patches-4.19/950-0601-usb-add-plumbing-for-updating-interrupt-endpoint-int.patch b/target/linux/brcm2708/patches-4.19/950-0601-usb-add-plumbing-for-updating-interrupt-endpoint-int.patch
new file mode 100644 (file)
index 0000000..99c4e4d
--- /dev/null
@@ -0,0 +1,104 @@
+From f9c01b35ec7ea3f981c414af38c92c508487671a Mon Sep 17 00:00:00 2001
+From: Jonathan Bell <jonathan@raspberrypi.org>
+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 <jonathan@raspberrypi.org>
+---
+ 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
+@@ -2071,6 +2071,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
+@@ -1113,6 +1113,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
+@@ -1809,6 +1809,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
+@@ -379,6 +379,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,