leaving URBs scheduled across system sleep (was:Re: Alan's idea about syspending the whole bus at once)

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

 



Am Sonntag, 20. Dezember 2009 18:10:00 schrieb Alan Stern:
> On Sun, 20 Dec 2009, Oliver Neukum wrote:
> 
> > Hi,
> > 
> > Alan, I took your idea of just suspending the bus. It seems to me
> > that we cannot do that unconditionally, as for some drivers like
> > btusb simply continuing transmission is wrong. But with a flag it
> > is a fascinating idea, because we cannot resume faster than by
> > doing nothing.
> > So this is the first draft. Comments?
> 
> You must have misunderstood my idea.  I never meant to skip notifying
> drivers about suspends.  The point was to avoid actually suspending and
> resuming the devices.  Did you read the test patch?

Ok, I read only the description, jumped to conclusion and thought
that this is an obvious improvement.

> I don't see any benefit to your patch.  Instead of having a
> "supports_transparent_suspend" flag, why not just have suspend and
> resume routines that do nothing?

True, the flag is stupid. Still some support from the core is needed as
drivers cannot know whether they can safely let IO run. How about this?

	Regards
		Oliver

>From 4a82989fb2fd845f42717bb6d037719eeef1fe19 Mon Sep 17 00:00:00 2001
From: Oliver Neukum <oliver@xxxxxxxxxx>
Date: Mon, 28 Dec 2009 12:42:45 +0100
Subject: [PATCH] usb:Leaving URBs submitted across system sleep

---
 drivers/usb/core/driver.c |    9 +++++++++
 drivers/usb/core/hub.c    |    6 ++++--
 include/linux/usb.h       |    1 +
 3 files changed, 14 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index 60a45f1..b47159f 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -1039,6 +1039,7 @@ static int usb_suspend_interface(struct usb_device *udev,
 {
 	struct usb_driver	*driver;
 	int			status = 0;
+	int			wake = udev->do_remote_wakeup;
 
 	/* with no hardware, USB interfaces only use FREEZE and ON states */
 	if (udev->state == USB_STATE_NOTATTACHED || !is_active(intf))
@@ -1049,6 +1050,13 @@ static int usb_suspend_interface(struct usb_device *udev,
 		goto done;
 	driver = to_usb_driver(intf->dev.driver);
 
+	if 	(driver &&
+		!(udev->quirks & USB_QUIRK_RESET_RESUME) &&
+		!(msg.event & PM_EVENT_AUTO) &&
+		(!wake && udev->descriptor.bDeviceClass != USB_CLASS_HUB)) {
+			intf->transparently_suspended = 1;
+			msg.event |= USB_TRANSPARENT_SUSPEND;
+	}
 	if (driver->suspend) {
 		status = driver->suspend(intf, msg);
 		if (status == 0)
@@ -1126,6 +1134,7 @@ static int usb_resume_interface(struct usb_device *udev,
 	}
 
 done:
+	intf->transparently_suspended = 0;
 	dev_vdbg(&intf->dev, "%s: status %d\n", __func__, status);
 	if (status == 0 && intf->condition == USB_INTERFACE_BOUND)
 		mark_active(intf);
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 0cec6ca..96ae677 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -2453,7 +2453,8 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg)
 	dev_dbg(&intf->dev, "%s\n", __func__);
 
 	/* stop khubd and related activity */
-	hub_quiesce(hub, HUB_SUSPEND);
+	if (!(msg.event & USB_TRANSPARENT_SUSPEND))
+		hub_quiesce(hub, HUB_SUSPEND);
 	return 0;
 }
 
@@ -2462,7 +2463,8 @@ static int hub_resume(struct usb_interface *intf)
 	struct usb_hub *hub = usb_get_intfdata(intf);
 
 	dev_dbg(&intf->dev, "%s\n", __func__);
-	hub_activate(hub, HUB_RESUME);
+	if (!intf->transparently_suspended)
+		hub_activate(hub, HUB_RESUME);
 	return 0;
 }
 
diff --git a/include/linux/usb.h b/include/linux/usb.h
index 0f422e4..c5dcb44 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -189,6 +189,7 @@ struct usb_interface {
 	unsigned ep_devs_created:1;	/* endpoint "devices" exist */
 	unsigned unregistering:1;	/* unregistration is in progress */
 	unsigned needs_remote_wakeup:1;	/* driver requires remote wakeup */
+	unsigned transparently_suspended:1; /* the driver has been told IO need not be cancelled */
 	unsigned needs_altsetting0:1;	/* switch to altsetting 0 is pending */
 	unsigned needs_binding:1;	/* needs delayed unbind/rebind */
 	unsigned reset_running:1;
-- 
1.6.4.2


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