Re: Root hub autosusend delay

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

 



Hi Peter,

On Wed, Jan 23, 2013 at 2:15 PM, Peter Chen <peter.chen@xxxxxxxxxxxxx> wrote:
> Hi Ming, I also find this problem at my platform.
> (At chipidea controller, the resume signal will be ended about 21ms
>  automatically)
>
> Neither delay 30ms at hub_events, nor revert your patch
> (596d789a211d134dc5f94d1e5957248c204ef850) can work.

Good point, looks I can reproduce the problem on Pandaboard too,
and same result with you, but root cause of the problem is what Alan
mentioned, the port change can't be retrieved during root hub ports
resuming.

Looks a little change on my previous patch might fix the problem, could
you test the below patch to see if it can fix that on your board?

diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index 4225d5e..5f5a9ec 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -2112,6 +2112,29 @@ void usb_hcd_resume_root_hub (struct usb_hcd *hcd)
 }
 EXPORT_SYMBOL_GPL(usb_hcd_resume_root_hub);

+void usb_hcd_set_rh_ports_resuming(struct usb_device *rhdev, bool val)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave (&hcd_root_hub_lock, flags);
+	rhdev->rh_resuming_ports = val;
+	spin_unlock_irqrestore (&hcd_root_hub_lock, flags);
+}
+EXPORT_SYMBOL_GPL(usb_hcd_set_rh_ports_resuming);
+
+bool usb_hcd_get_rh_ports_resuming(struct usb_device *rhdev)
+{
+	unsigned long flags;
+	bool val;
+
+	spin_lock_irqsave (&hcd_root_hub_lock, flags);
+	val = rhdev->rh_resuming_ports;
+	spin_unlock_irqrestore (&hcd_root_hub_lock, flags);
+
+	return val;
+}
+EXPORT_SYMBOL_GPL(usb_hcd_get_rh_ports_resuming);
+
 #endif	/* CONFIG_USB_SUSPEND */

 /*-------------------------------------------------------------------------*/
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index a815fd2..0f53d38 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -1034,6 +1034,15 @@ static void hub_activate(struct usb_hub *hub,
enum hub_activation_type type)
 		}
 	}
  init2:
+	if (type == HUB_RESUME) {
+		/* root hub is sending resume signal, so wait for its completion */
+		if (!hdev->parent && usb_hcd_get_rh_ports_resuming(hdev)) {
+			dev_dbg(&hdev->dev, "wait for ports resuming over\n");
+			msleep(30);
+			usb_hcd_set_rh_ports_resuming(hdev, 0);
+			dev_dbg(&hdev->dev, "ports resuming over\n");
+		}
+	}

 	/* Check each port and set hub->change_bits to let khubd know
 	 * which ports need attention.
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index c97503b..3a90150 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -802,6 +802,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
 			set_bit(i, &ehci->resuming_ports);
 			ehci_dbg (ehci, "port %d remote wakeup\n", i + 1);
 			mod_timer(&hcd->rh_timer, ehci->reset_done[i]);
+			usb_hcd_set_rh_ports_resuming(hcd->self.root_hub, 1);
 		}
 	}

diff --git a/include/linux/usb.h b/include/linux/usb.h
index 689b14b..ea16fda 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -562,6 +562,7 @@ struct usb_device {
 	unsigned do_remote_wakeup:1;
 	unsigned reset_resume:1;
 	unsigned port_is_suspended:1;
+	unsigned rh_resuming_ports:1;
 #endif
 	struct wusb_dev *wusb_dev;
 	int slot_id;
diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h
index 608050b..451650d 100644
--- a/include/linux/usb/hcd.h
+++ b/include/linux/usb/hcd.h
@@ -590,11 +590,15 @@ extern int hcd_bus_resume(struct usb_device
*rhdev, pm_message_t msg);

 #ifdef CONFIG_USB_SUSPEND
 extern void usb_hcd_resume_root_hub(struct usb_hcd *hcd);
+extern void usb_hcd_set_rh_ports_resuming(struct usb_device *rhdev, bool val);
+extern bool usb_hcd_get_rh_ports_resuming(struct usb_device *rhdev);
 #else
 static inline void usb_hcd_resume_root_hub(struct usb_hcd *hcd)
 {
 	return;
 }
+static inline void usb_hcd_set_rh_ports_resuming(struct usb_device
*rhdev, bool val) {}
+static inline bool usb_hcd_get_rh_ports_resuming(struct usb_device
*rhdev) {return false;}
 #endif /* CONFIG_USB_SUSPEND */

 /*-------------------------------------------------------------------------*/


Thanks,
--
Ming Lei
--
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