lkml.org 
[lkml]   [2015]   [May]   [25]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
Subject[PATCH 1/3] usb: add function usb_autopm_get_interface_upgrade
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 | 53 +++++++++++++++++++++++++++++++++++++++++++++++

include/linux/usb.h | 3 +++

2 files changed, 56 insertions(+)

diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c

index 818369a..d07fd8d 100644

--- a/drivers/usb/core/driver.c

+++ b/drivers/usb/core/driver.c

@@ -1684,6 +1684,59 @@ int usb_autopm_get_interface(struct usb_interface *intf)

EXPORT_SYMBOL_GPL(usb_autopm_get_interface);



/**
+ * usb_autopm_get_interface_retry - 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




\
 
 \ /
  Last update: 2015-05-26 04:41    [W:0.095 / U:0.096 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site