Re: About resume time optimization for bus resume routine

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

 



On Fri, 12 Oct 2012, Peter Chen wrote:

> Taking EHCI controller as an example, it just needs to change ehci_bus_resume,
> if there is any enabled, unsuspended port, set hcd->unsuspended_device_on_port

We don't need to do that.  See below.

> > usb_bus_resume() can poll the port statuses to see if there are any 
> > enabled, unsuspended ports.  If there aren't any, the delay can be 
> > skipped.
> Taking EHCI controller as an example, you mean:
> 
> - Change hcd_bus_resume like below:
> 
> 	status = hcd->driver->bus_resume(hcd);
> 	clear_bit(HCD_FLAG_WAKEUP_PENDING, &hcd->flags);
> 	if (status == 0) {
> 		char	buffer[6];
> 
> 		status = hcd->driver->hub_status_data(hcd, buffer);
> 		if (status != 0) {
> 			/* There are any enabled unsuspended ports */
> 			/* TRSMRCY = 10 msec */
> 			msleep(10);
> 		spin_lock_irq(&hcd_root_hub_lock);
> - Add get any enabled, unsuspended port as port change condition at
> ehci_hub_status_data.

No, like this:

--- usb-3.6.orig/drivers/usb/core/hcd.c
+++ usb-3.6/drivers/usb/core/hcd.c
@@ -2023,6 +2023,7 @@ int hcd_bus_resume(struct usb_device *rh
 	struct usb_hcd	*hcd = container_of(rhdev->bus, struct usb_hcd, self);
 	int		status;
 	int		old_state = hcd->state;
+	int		port1;
 
 	dev_dbg(&rhdev->dev, "usb %sresume\n",
 			(PMSG_IS_AUTO(msg) ? "auto-" : ""));
@@ -2039,8 +2040,6 @@ 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);
 		spin_lock_irq(&hcd_root_hub_lock);
 		if (!HCD_DEAD(hcd)) {
 			usb_set_device_state(rhdev, rhdev->actconfig
@@ -2050,6 +2049,22 @@ int hcd_bus_resume(struct usb_device *rh
 			hcd->state = HC_STATE_RUNNING;
 		}
 		spin_unlock_irq(&hcd_root_hub_lock);
+
+		/* Any enabled non-suspended port requires TRSMRCY delay */
+		for (port1 = 1; port1 <= rhdev->maxchild; ++port1) {
+			__le16		buf[2];
+			unsigned	pstatus;
+
+			buf[0] = 0;
+			hcd->driver->hub_control(hcd, USB_DIR_IN | USB_RT_PORT,
+					0, port1, (char *) buf, 4);
+			pstatus = le16_to_cpu(buf[0]);
+			if ((pstatus & USB_PORT_STAT_ENABLE) &&
+					!(pstatus & USB_PORT_STAT_SUSPEND)) {
+				msleep(10);	/* TRSMRCY */
+				break;
+			}
+		}
 	} else {
 		hcd->state = old_state;
 		dev_dbg(&rhdev->dev, "bus %s fail, err %d\n",

I haven't tested this, just compiled it.

Alan Stern

--
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