Re: About resume time optimization for bus resume routine

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Thu, Oct 18, 2012 at 03:16:04PM -0400, Alan Stern wrote:
> On Thu, 18 Oct 2012, Peter Chen wrote:
> 
> > > I decided to use a different approach.  The core should know which 
> > > ports are suspended without asking the HCD.  Can you test this patch in 
> > > place of the other one?
> > It shows below oops, you may not consider there is no device at port
> > condition.
> 
> Quite right.  I consider this to be a bug in hub_for_each_child; the 
> first patch below fixes that bug.
> 
> > Besides, how about using usleep_range instead of msleep? msleep is not
> > precise, and should not be used at (<20ms) condition, at my platform,
> > msleep 10 consumes about 19-20ms.
> 
> Good idea; the second patch below is updated to use usleep_range 
> instead of msleep.  These two patches together should do what you want.
> 
> Alan Stern
> 
> 
> 
> First patch: Fix hub_for_each_child
> 
> Index: usb-3.6/include/linux/usb.h
> ===================================================================
> --- usb-3.6.orig/include/linux/usb.h
> +++ usb-3.6/include/linux/usb.h
> @@ -588,8 +588,9 @@ extern struct usb_device *usb_hub_find_c
>   */
>  #define usb_hub_for_each_child(hdev, port1, child) \
>  	for (port1 = 1,	child =	usb_hub_find_child(hdev, port1); \
> -		port1 <= hdev->maxchild; \
> -		child = usb_hub_find_child(hdev, ++port1))
> +			port1 <= hdev->maxchild; \
> +			child = usb_hub_find_child(hdev, ++port1)) \
> +		if (!child) continue; else
>  
>  /* USB device locking */
>  #define usb_lock_device(udev)		device_lock(&(udev)->dev)
> 
> 
> 
> Second patch: Speed up bus resumes
> 
> Index: usb-3.6/include/linux/usb.h
> ===================================================================
> --- usb-3.6.orig/include/linux/usb.h
> +++ usb-3.6/include/linux/usb.h
> @@ -482,6 +482,7 @@ struct usb3_lpm_parameters {
>   * @connect_time: time device was first connected
>   * @do_remote_wakeup:  remote wakeup should be enabled
>   * @reset_resume: needs reset instead of resume
> + * @port_is_suspended: the upstream port is suspended (L2 or U3)
>   * @wusb_dev: if this is a Wireless USB device, link to the WUSB
>   *	specific data for the device.
>   * @slot_id: Slot ID assigned by xHCI
> @@ -560,6 +561,7 @@ struct usb_device {
>  
>  	unsigned do_remote_wakeup:1;
>  	unsigned reset_resume:1;
> +	unsigned port_is_suspended:1;
>  #endif
>  	struct wusb_dev *wusb_dev;
>  	int slot_id;
> Index: usb-3.6/drivers/usb/core/hub.c
> ===================================================================
> --- usb-3.6.orig/drivers/usb/core/hub.c
> +++ usb-3.6/drivers/usb/core/hub.c
> @@ -2876,6 +2876,7 @@ int usb_port_suspend(struct usb_device *
>  				(PMSG_IS_AUTO(msg) ? "auto-" : ""),
>  				udev->do_remote_wakeup);
>  		usb_set_device_state(udev, USB_STATE_SUSPENDED);
> +		udev->port_is_suspended = 1;
>  		msleep(10);
>  	}
>  	usb_mark_last_busy(hub->hdev);
> @@ -3040,6 +3041,7 @@ int usb_port_resume(struct usb_device *u
>  
>   SuspendCleared:
>  	if (status == 0) {
> +		udev->port_is_suspended = 0;
>  		if (hub_is_superspeed(hub->hdev)) {
>  			if (portchange & USB_PORT_STAT_C_LINK_STATE)
>  				clear_port_feature(hub->hdev, port1,
> Index: usb-3.6/drivers/usb/core/hcd.c
> ===================================================================
> --- usb-3.6.orig/drivers/usb/core/hcd.c
> +++ usb-3.6/drivers/usb/core/hcd.c
> @@ -2039,8 +2039,9 @@ int hcd_bus_resume(struct usb_device *rh
>  	status = hcd->driver->bus_resume(hcd);
>  	clear_bit(HCD_FLAG_WAKEUP_PENDING, &hcd->flags);
>  	if (status == 0) {
> -		/* TRSMRCY = 10 msec */
> -		msleep(10);
> +		struct usb_device *udev;
> +		int port1;
> +
>  		spin_lock_irq(&hcd_root_hub_lock);
>  		if (!HCD_DEAD(hcd)) {
>  			usb_set_device_state(rhdev, rhdev->actconfig
> @@ -2050,6 +2051,20 @@ int hcd_bus_resume(struct usb_device *rh
>  			hcd->state = HC_STATE_RUNNING;
>  		}
>  		spin_unlock_irq(&hcd_root_hub_lock);
> +
> +		/*
> +		 * Check whether any of the enabled ports on the root hub are
> +		 * unsuspended.  If they are then a TRSMRCY delay is needed
> +		 * (this is what the USB-2 spec calls a "global resume").
> +		 * Otherwise we can skip the delay.
> +		 */
> +		usb_hub_for_each_child(rhdev, port1, udev) {
> +			if (udev->state != USB_STATE_NOTATTACHED &&
> +					!udev->port_is_suspended) {
> +				usleep_range(10000, 11000);	/* TRSMRCY */
> +				break;
> +			}
> +		}
>  	} else {
>  		hcd->state = old_state;
>  		dev_dbg(&rhdev->dev, "bus %s fail, err %d\n",
> 
> 
Reviewed-by: Peter Chen <peter.chen@xxxxxxxxxxxxx>
Tested-by: Peter Chen <peter.chen@xxxxxxxxxxxxx>

-- 

Best Regards,
Peter Chen

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux