public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH V3 1/3] usb: add function usb_autopm_get_interface_upgrade
@ 2015-05-27  4:13 Zhang, Yanmin
  0 siblings, 0 replies; only message in thread
From: Zhang, Yanmin @ 2015-05-27  4:13 UTC (permalink / raw)
  To: linux-kernel, xinhuix.pan, gregkh, alan

From: Zhang Yanmin <yanmin.zhang@intel.com>

Some usb driver has a specific requirement. Their critical functions
might be called under both atomic environment and non-atomic environment.

If it's under atomic environment, the driver can wake up the device
by calling pm_runtime_get_sync directly.

If it's under non-atomic environment, the function's caller need wake
up the device before the function accesses the device.

The patch adds usb_autopm_get_interface_upgrade, a new function to
support above capability.

Signed-off-by: Zhang Yanmin <yanmin.zhang@intel.com>
---
 drivers/usb/core/driver.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/usb.h       |  3 +++
 2 files changed, 57 insertions(+)

diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index 818369a..5d6f9ee 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -1684,6 +1684,60 @@ int usb_autopm_get_interface(struct usb_interface *intf)
 EXPORT_SYMBOL_GPL(usb_autopm_get_interface);
 
 /**
+ * usb_autopm_get_interface_upgrade - increment a USB interface's PM-usage
+ * counter
+ * @intf: the usb_interface whose counter should be incremented
+ *
+ * This routine should be called by an interface driver when it wants to
+ * use @intf and needs to guarantee that it is not suspended.  In addition,
+ * the routine prevents @intf from being autosuspended subsequently.  (Note
+ * that this will not prevent suspend events originating in the PM core.)
+ * This prevention will persist until usb_autopm_put_interface() is called
+ * or @intf is unbound.  A typical example would be a character-device
+ * driver when its device file is opened.
+ *
+ * Comparing with usb_autopm_get_interface, usb_autopm_get_interface_upgrade
+ * is more careful when resuming the device.
+ * 1) The caller's caller already resumes resume the device and hold spinlocks.
+ * usb_autopm_get_interface_upgrade couldn't call pm_runtime_get_sync;
+ * 2) The caller's caller doesn't resume the device.
+ * usb_autopm_get_interface_upgrade has to resume the device before going ahead.
+ *
+ * @intf's usage counter is incremented to prevent subsequent autosuspends.
+ * However if the autoresume fails then the counter is re-decremented.
+ *
+ * This routine can run only in process context.
+ *
+ * Return: 0 on success.
+ */
+int usb_autopm_get_interface_upgrade(struct usb_interface *intf)
+{
+	int	status = 0;
+
+	pm_runtime_get(&intf->dev);
+	if (!pm_runtime_active(&intf->dev)) {
+		/* If not active, next _get_sync wakes device up*/
+		status = pm_runtime_get_sync(&intf->dev);
+		/*
+		 * If it's active, next _put_sync wouldn't
+		 * really put it to sleep as the 1st _get
+		 * keeps the device active.
+		 */
+		pm_runtime_put_sync(&intf->dev);
+		if (status < 0)
+			pm_runtime_put(&intf->dev);
+	} else
+		atomic_inc(&intf->pm_usage_cnt);
+	dev_vdbg(&intf->dev, "%s: cnt %d -> %d\n",
+			__func__, atomic_read(&intf->dev.power.usage_count),
+			status);
+	if (status > 0)
+		status = 0;
+	return status;
+}
+EXPORT_SYMBOL_GPL(usb_autopm_get_interface_upgrade);
+
+/**
  * usb_autopm_get_interface_async - increment a USB interface's PM-usage counter
  * @intf: the usb_interface whose counter should be incremented
  *
diff --git a/include/linux/usb.h b/include/linux/usb.h
index 447fe29..0a8a44a 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -663,6 +663,7 @@ extern void usb_enable_autosuspend(struct usb_device *udev);
 extern void usb_disable_autosuspend(struct usb_device *udev);
 
 extern int usb_autopm_get_interface(struct usb_interface *intf);
+extern int usb_autopm_get_interface_upgrade(struct usb_interface *intf);
 extern void usb_autopm_put_interface(struct usb_interface *intf);
 extern int usb_autopm_get_interface_async(struct usb_interface *intf);
 extern void usb_autopm_put_interface_async(struct usb_interface *intf);
@@ -683,6 +684,8 @@ static inline int usb_disable_autosuspend(struct usb_device *udev)
 
 static inline int usb_autopm_get_interface(struct usb_interface *intf)
 { return 0; }
+static inline int usb_autopm_get_interface_upgrade(struct usb_interface *intf)
+{ return 0; }
 static inline int usb_autopm_get_interface_async(struct usb_interface *intf)
 { return 0; }
 
-- 
1.9.1



^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2015-05-27  4:13 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-05-27  4:13 [PATCH V3 1/3] usb: add function usb_autopm_get_interface_upgrade Zhang, Yanmin

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox