mirror of
				https://github.com/Ysurac/openmptcprouter.git
				synced 2025-03-09 15:40:20 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			104 lines
		
	
	
	
		
			3.9 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			104 lines
		
	
	
	
		
			3.9 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
| From de0e13a4060fb6bc211f2da0bd62be08244eafab 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
 | |
| @@ -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,
 |