All of lore.kernel.org
 help / color / mirror / Atom feed
* Re: [PATCH 2/2] PM / sleep: Asynchronous threads for dpm_complete
  2014-08-25 15:13 ` [PATCH 2/2] PM / sleep: Asynchronous threads for dpm_complete xiaoming wang
@ 2014-08-25 14:27     ` kodiak furr
  0 siblings, 0 replies; 5+ messages in thread
From: kodiak furr @ 2014-08-25 14:27 UTC (permalink / raw)
  To: xiaoming wang
  Cc: gregkh, linux-pm, rjw, Chuansheng Liu, len.brown, linux-kernel, pavel

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset=utf-8, Size: 3513 bytes --]

kodiak furr liked your message with Boxer for Android.

On Aug 25, 2014 10:13 AM, xiaoming wang <xiaoming.wang@intel.com> wrote:
>
> In analogy with commits 5af84b82701a and 97df8c12995, 
> using asynchronous threads can improve the overall 
> resume time significantly. 
>
> This patch is for dpm_complete phase. 
>
> Signed-off-by: Chuansheng Liu <chuansheng.liu@intel.com> 
> Signed-off-by: xiaoming wang <xiaoming.wang@intel.com> 
> --- 
> drivers/base/power/main.c |   38 ++++++++++++++++++++++++++++++++++---- 
> 1 files changed, 34 insertions(+), 4 deletions(-) 
>
> diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c 
> index f9fe1b3..00c4bf1 100644 
> --- a/drivers/base/power/main.c 
> +++ b/drivers/base/power/main.c 
> @@ -889,14 +889,15 @@ void dpm_resume(pm_message_t state) 
>   * @dev: Device to handle. 
>   * @state: PM transition of the system being carried out. 
>   */ 
> -static void device_complete(struct device *dev, pm_message_t state) 
> +static void device_complete(struct device *dev, pm_message_t state, bool async) 
> { 
> void (*callback)(struct device *) = NULL; 
> char *info = NULL; 
>
> if (dev->power.syscore) 
> - return; 
> + goto Complete; 
>
> + dpm_wait(dev->parent, async); 
> device_lock(dev); 
>
> if (dev->pm_domain) { 
> @@ -928,6 +929,17 @@ static void device_complete(struct device *dev, pm_message_t state) 
> device_unlock(dev); 
>
> pm_runtime_put(dev); 
> + 
> +Complete: 
> + complete_all(&dev->power.completion); 
> +} 
> + 
> +static void async_complete(void *data, async_cookie_t cookie) 
> +{ 
> + struct device *dev = (struct device *)data; 
> + 
> + device_complete(dev, pm_transition, true); 
> + put_device(dev); 
> } 
>
> /** 
> @@ -940,27 +952,45 @@ static void device_complete(struct device *dev, pm_message_t state) 
> void dpm_complete(pm_message_t state) 
> { 
> struct list_head list; 
> + struct device *dev; 
>
> trace_suspend_resume(TPS("dpm_complete"), state.event, true); 
> might_sleep(); 
>
> INIT_LIST_HEAD(&list); 
> mutex_lock(&dpm_list_mtx); 
> + pm_transition = state; 
> + 
> + /* 
> +   * Advanced the async threads upfront, 
> +   * in case the starting of async threads is 
> +   * delayed by non-async resuming devices. 
> +   */ 
> + list_for_each_entry(dev, &dpm_prepared_list, power.entry) { 
> + reinit_completion(&dev->power.completion); 
> + if (is_async(dev)) { 
> + get_device(dev); 
> + async_schedule(async_complete, dev); 
> + } 
> + } 
> + 
> while (!list_empty(&dpm_prepared_list)) { 
> - struct device *dev = to_device(dpm_prepared_list.prev); 
> + dev = to_device(dpm_prepared_list.prev); 
>
> get_device(dev); 
> dev->power.is_prepared = false; 
> list_move(&dev->power.entry, &list); 
> mutex_unlock(&dpm_list_mtx); 
>
> - device_complete(dev, state); 
> + if (!is_async(dev)) 
> + device_complete(dev, state, false); 
>
> mutex_lock(&dpm_list_mtx); 
> put_device(dev); 
> } 
> list_splice(&list, &dpm_list); 
> mutex_unlock(&dpm_list_mtx); 
> + async_synchronize_full(); 
> trace_suspend_resume(TPS("dpm_complete"), state.event, false); 
> } 
>
> -- 
> 1.7.1 
>
> -- 
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in 
> the body of a message to majordomo@vger.kernel.org 
> More majordomo info at  http://vger.kernel.org/majordomo-info.html 
> Please read the FAQ at  http://www.tux.org/lkml/ 
ÿôèº{.nÇ+‰·Ÿ®‰­†+%ŠËÿ±éݶ\x17¥Šwÿº{.nÇ+‰·¥Š{±þG«éÿŠ{ayº\x1dʇڙë,j\a­¢f£¢·hšïêÿ‘êçz_è®\x03(­éšŽŠÝ¢j"ú\x1a¶^[m§ÿÿ¾\a«þG«éÿ¢¸?™¨è­Ú&£ø§~á¶iO•æ¬z·švØ^\x14\x04\x1a¶^[m§ÿÿÃ\fÿ¶ìÿ¢¸?–I¥

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH 2/2] PM / sleep: Asynchronous threads for dpm_complete
@ 2014-08-25 14:27     ` kodiak furr
  0 siblings, 0 replies; 5+ messages in thread
From: kodiak furr @ 2014-08-25 14:27 UTC (permalink / raw)
  To: xiaoming wang
  Cc: gregkh, linux-pm, rjw, Chuansheng Liu, len.brown, linux-kernel, pavel

kodiak furr liked your message with Boxer for Android.

On Aug 25, 2014 10:13 AM, xiaoming wang <xiaoming.wang@intel.com> wrote:
>
> In analogy with commits 5af84b82701a and 97df8c12995, 
> using asynchronous threads can improve the overall 
> resume time significantly. 
>
> This patch is for dpm_complete phase. 
>
> Signed-off-by: Chuansheng Liu <chuansheng.liu@intel.com> 
> Signed-off-by: xiaoming wang <xiaoming.wang@intel.com> 
> --- 
> drivers/base/power/main.c |   38 ++++++++++++++++++++++++++++++++++---- 
> 1 files changed, 34 insertions(+), 4 deletions(-) 
>
> diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c 
> index f9fe1b3..00c4bf1 100644 
> --- a/drivers/base/power/main.c 
> +++ b/drivers/base/power/main.c 
> @@ -889,14 +889,15 @@ void dpm_resume(pm_message_t state) 
>   * @dev: Device to handle. 
>   * @state: PM transition of the system being carried out. 
>   */ 
> -static void device_complete(struct device *dev, pm_message_t state) 
> +static void device_complete(struct device *dev, pm_message_t state, bool async) 
> { 
> void (*callback)(struct device *) = NULL; 
> char *info = NULL; 
>
> if (dev->power.syscore) 
> - return; 
> + goto Complete; 
>
> + dpm_wait(dev->parent, async); 
> device_lock(dev); 
>
> if (dev->pm_domain) { 
> @@ -928,6 +929,17 @@ static void device_complete(struct device *dev, pm_message_t state) 
> device_unlock(dev); 
>
> pm_runtime_put(dev); 
> + 
> +Complete: 
> + complete_all(&dev->power.completion); 
> +} 
> + 
> +static void async_complete(void *data, async_cookie_t cookie) 
> +{ 
> + struct device *dev = (struct device *)data; 
> + 
> + device_complete(dev, pm_transition, true); 
> + put_device(dev); 
> } 
>
> /** 
> @@ -940,27 +952,45 @@ static void device_complete(struct device *dev, pm_message_t state) 
> void dpm_complete(pm_message_t state) 
> { 
> struct list_head list; 
> + struct device *dev; 
>
> trace_suspend_resume(TPS("dpm_complete"), state.event, true); 
> might_sleep(); 
>
> INIT_LIST_HEAD(&list); 
> mutex_lock(&dpm_list_mtx); 
> + pm_transition = state; 
> + 
> + /* 
> +   * Advanced the async threads upfront, 
> +   * in case the starting of async threads is 
> +   * delayed by non-async resuming devices. 
> +   */ 
> + list_for_each_entry(dev, &dpm_prepared_list, power.entry) { 
> + reinit_completion(&dev->power.completion); 
> + if (is_async(dev)) { 
> + get_device(dev); 
> + async_schedule(async_complete, dev); 
> + } 
> + } 
> + 
> while (!list_empty(&dpm_prepared_list)) { 
> - struct device *dev = to_device(dpm_prepared_list.prev); 
> + dev = to_device(dpm_prepared_list.prev); 
>
> get_device(dev); 
> dev->power.is_prepared = false; 
> list_move(&dev->power.entry, &list); 
> mutex_unlock(&dpm_list_mtx); 
>
> - device_complete(dev, state); 
> + if (!is_async(dev)) 
> + device_complete(dev, state, false); 
>
> mutex_lock(&dpm_list_mtx); 
> put_device(dev); 
> } 
> list_splice(&list, &dpm_list); 
> mutex_unlock(&dpm_list_mtx); 
> + async_synchronize_full(); 
> trace_suspend_resume(TPS("dpm_complete"), state.event, false); 
> } 
>
> -- 
> 1.7.1 
>
> -- 
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in 
> the body of a message to majordomo@vger.kernel.org 
> More majordomo info at  http://vger.kernel.org/majordomo-info.html 
> Please read the FAQ at  http://www.tux.org/lkml/ 

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH 1/2] PM / sleep: Asynchronous threads for dpm_prepare
@ 2014-08-25 15:13 xiaoming wang
  2014-08-25 15:13 ` [PATCH 2/2] PM / sleep: Asynchronous threads for dpm_complete xiaoming wang
  0 siblings, 1 reply; 5+ messages in thread
From: xiaoming wang @ 2014-08-25 15:13 UTC (permalink / raw)
  To: rjw, len.brown, pavel, gregkh, linux-pm, linux-kernel
  Cc: xiaoming wang, Chuansheng Liu

In analogy with commits 5af84b82701a and 97df8c12995,
using asynchronous threads can improve the overall
suspend time significantly.

This patch is for dpm_prepare phase.

Signed-off-by: Chuansheng Liu <chuansheng.liu@intel.com>
Signed-off-by: xiaoming wang <xiaoming.wang@intel.com>
---
 drivers/base/power/main.c |   57 +++++++++++++++++++++++++++++++++++++++++----
 1 files changed, 52 insertions(+), 5 deletions(-)

diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
index b67d9ae..f9fe1b3 100644
--- a/drivers/base/power/main.c
+++ b/drivers/base/power/main.c
@@ -1531,15 +1531,24 @@ int dpm_suspend(pm_message_t state)
  * Execute the ->prepare() callback(s) for given device.  No new children of the
  * device may be registered after this function has returned.
  */
-static int device_prepare(struct device *dev, pm_message_t state)
+static int __device_prepare(struct device *dev, pm_message_t state, bool async)
 {
 	int (*callback)(struct device *) = NULL;
 	char *info = NULL;
 	int ret = 0;
 
+	if (async_error)
+		goto Complete;
+
+	if (pm_wakeup_pending()) {
+		async_error = -EBUSY;
+		goto Complete;
+	}
+
 	if (dev->power.syscore)
-		return 0;
+		goto Complete;
 
+	dpm_wait_for_children(dev, async);
 	/*
 	 * If a device's parent goes into runtime suspend at the wrong time,
 	 * it won't be possible to resume the device.  To prevent this we
@@ -1582,7 +1591,7 @@ static int device_prepare(struct device *dev, pm_message_t state)
 	if (ret < 0) {
 		suspend_report_result(callback, ret);
 		pm_runtime_put(dev);
-		return ret;
+		goto Complete;
 	}
 	/*
 	 * A positive return value from ->prepare() means "this device appears
@@ -1594,9 +1603,40 @@ static int device_prepare(struct device *dev, pm_message_t state)
 	spin_lock_irq(&dev->power.lock);
 	dev->power.direct_complete = ret > 0 && state.event == PM_EVENT_SUSPEND;
 	spin_unlock_irq(&dev->power.lock);
-	return 0;
+
+Complete:
+	complete_all(&dev->power.completion);
+	if (ret)
+		async_error = ret;
+
+	return ret;
+}
+
+static void async_prepare(void *data, async_cookie_t cookie)
+{
+	struct device *dev = (struct device *)data;
+	int error;
+
+	error = __device_prepare(dev, pm_transition, true);
+	if (error) {
+		dpm_save_failed_dev(dev_name(dev));
+		pm_dev_err(dev, pm_transition, " async", error);
+	}
+	put_device(dev);
+}
+
+static int device_prepare(struct device *dev)
+{
+	reinit_completion(&dev->power.completion);
+	if (pm_async_enabled && dev->power.async_suspend) {
+		get_device(dev);
+		async_schedule(async_prepare, dev);
+		return 0;
+	}
+	return __device_prepare(dev, pm_transition, false);
 }
 
+
 /**
  * dpm_prepare - Prepare all non-sysdev devices for a system PM transition.
  * @state: PM transition of the system being carried out.
@@ -1611,13 +1651,15 @@ int dpm_prepare(pm_message_t state)
 	might_sleep();
 
 	mutex_lock(&dpm_list_mtx);
+	pm_transition = state;
+	async_error = 0;
 	while (!list_empty(&dpm_list)) {
 		struct device *dev = to_device(dpm_list.next);
 
 		get_device(dev);
 		mutex_unlock(&dpm_list_mtx);
 
-		error = device_prepare(dev, state);
+		error = device_prepare(dev);
 
 		mutex_lock(&dpm_list_mtx);
 		if (error) {
@@ -1636,8 +1678,13 @@ int dpm_prepare(pm_message_t state)
 		if (!list_empty(&dev->power.entry))
 			list_move_tail(&dev->power.entry, &dpm_prepared_list);
 		put_device(dev);
+		if (async_error)
+			break;
 	}
 	mutex_unlock(&dpm_list_mtx);
+	async_synchronize_full();
+	if (!error)
+		error = async_error;
 	trace_suspend_resume(TPS("dpm_prepare"), state.event, false);
 	return error;
 }
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 2/2] PM / sleep: Asynchronous threads for dpm_complete
  2014-08-25 15:13 [PATCH 1/2] PM / sleep: Asynchronous threads for dpm_prepare xiaoming wang
@ 2014-08-25 15:13 ` xiaoming wang
  2014-08-25 14:27     ` kodiak furr
  0 siblings, 1 reply; 5+ messages in thread
From: xiaoming wang @ 2014-08-25 15:13 UTC (permalink / raw)
  To: rjw, len.brown, pavel, gregkh, linux-pm, linux-kernel
  Cc: xiaoming wang, Chuansheng Liu

In analogy with commits 5af84b82701a and 97df8c12995,
using asynchronous threads can improve the overall
resume time significantly.

This patch is for dpm_complete phase.

Signed-off-by: Chuansheng Liu <chuansheng.liu@intel.com>
Signed-off-by: xiaoming wang <xiaoming.wang@intel.com>
---
 drivers/base/power/main.c |   38 ++++++++++++++++++++++++++++++++++----
 1 files changed, 34 insertions(+), 4 deletions(-)

diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
index f9fe1b3..00c4bf1 100644
--- a/drivers/base/power/main.c
+++ b/drivers/base/power/main.c
@@ -889,14 +889,15 @@ void dpm_resume(pm_message_t state)
  * @dev: Device to handle.
  * @state: PM transition of the system being carried out.
  */
-static void device_complete(struct device *dev, pm_message_t state)
+static void device_complete(struct device *dev, pm_message_t state, bool async)
 {
 	void (*callback)(struct device *) = NULL;
 	char *info = NULL;
 
 	if (dev->power.syscore)
-		return;
+		goto Complete;
 
+	dpm_wait(dev->parent, async);
 	device_lock(dev);
 
 	if (dev->pm_domain) {
@@ -928,6 +929,17 @@ static void device_complete(struct device *dev, pm_message_t state)
 	device_unlock(dev);
 
 	pm_runtime_put(dev);
+
+Complete:
+	complete_all(&dev->power.completion);
+}
+
+static void async_complete(void *data, async_cookie_t cookie)
+{
+	struct device *dev = (struct device *)data;
+
+	device_complete(dev, pm_transition, true);
+	put_device(dev);
 }
 
 /**
@@ -940,27 +952,45 @@ static void device_complete(struct device *dev, pm_message_t state)
 void dpm_complete(pm_message_t state)
 {
 	struct list_head list;
+	struct device *dev;
 
 	trace_suspend_resume(TPS("dpm_complete"), state.event, true);
 	might_sleep();
 
 	INIT_LIST_HEAD(&list);
 	mutex_lock(&dpm_list_mtx);
+	pm_transition = state;
+
+	/*
+	  * Advanced the async threads upfront,
+	  * in case the starting of async threads is
+	  * delayed by non-async resuming devices.
+	  */
+	list_for_each_entry(dev, &dpm_prepared_list, power.entry) {
+		reinit_completion(&dev->power.completion);
+		if (is_async(dev)) {
+			get_device(dev);
+			async_schedule(async_complete, dev);
+		}
+	}
+
 	while (!list_empty(&dpm_prepared_list)) {
-		struct device *dev = to_device(dpm_prepared_list.prev);
+		dev = to_device(dpm_prepared_list.prev);
 
 		get_device(dev);
 		dev->power.is_prepared = false;
 		list_move(&dev->power.entry, &list);
 		mutex_unlock(&dpm_list_mtx);
 
-		device_complete(dev, state);
+		if (!is_async(dev))
+			device_complete(dev, state, false);
 
 		mutex_lock(&dpm_list_mtx);
 		put_device(dev);
 	}
 	list_splice(&list, &dpm_list);
 	mutex_unlock(&dpm_list_mtx);
+	async_synchronize_full();
 	trace_suspend_resume(TPS("dpm_complete"), state.event, false);
 }
 
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 2/2] PM / sleep: Asynchronous threads for dpm_complete
  2014-08-19 20:29 [PATCH 1/2] PM / sleep: Asynchronous threads for dpm_prepare xiaoming wang
@ 2014-08-19 20:29 ` xiaoming wang
  0 siblings, 0 replies; 5+ messages in thread
From: xiaoming wang @ 2014-08-19 20:29 UTC (permalink / raw)
  To: rjw, len.brown, pavel, gregkh, linux-pm, linux-kernel
  Cc: xiaoming wang, Chuansheng Liu

In analogy with commits 5af84b82701a and 97df8c12995,
using asynchronous threads can improve the overall
resume time significantly.

This patch is for dpm_complete phase.

Signed-off-by: Chuansheng Liu <chuansheng.liu@intel.com>
Signed-off-by: xiaoming wang <xiaoming.wang@intel.com>
---
 drivers/base/power/main.c |   38 ++++++++++++++++++++++++++++++++++----
 1 files changed, 34 insertions(+), 4 deletions(-)

diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
index f9fe1b3..00c4bf1 100644
--- a/drivers/base/power/main.c
+++ b/drivers/base/power/main.c
@@ -889,14 +889,15 @@ void dpm_resume(pm_message_t state)
  * @dev: Device to handle.
  * @state: PM transition of the system being carried out.
  */
-static void device_complete(struct device *dev, pm_message_t state)
+static void device_complete(struct device *dev, pm_message_t state, bool async)
 {
 	void (*callback)(struct device *) = NULL;
 	char *info = NULL;
 
 	if (dev->power.syscore)
-		return;
+		goto Complete;
 
+	dpm_wait(dev->parent, async);
 	device_lock(dev);
 
 	if (dev->pm_domain) {
@@ -928,6 +929,17 @@ static void device_complete(struct device *dev, pm_message_t state)
 	device_unlock(dev);
 
 	pm_runtime_put(dev);
+
+Complete:
+	complete_all(&dev->power.completion);
+}
+
+static void async_complete(void *data, async_cookie_t cookie)
+{
+	struct device *dev = (struct device *)data;
+
+	device_complete(dev, pm_transition, true);
+	put_device(dev);
 }
 
 /**
@@ -940,27 +952,45 @@ static void device_complete(struct device *dev, pm_message_t state)
 void dpm_complete(pm_message_t state)
 {
 	struct list_head list;
+	struct device *dev;
 
 	trace_suspend_resume(TPS("dpm_complete"), state.event, true);
 	might_sleep();
 
 	INIT_LIST_HEAD(&list);
 	mutex_lock(&dpm_list_mtx);
+	pm_transition = state;
+
+	/*
+	  * Advanced the async threads upfront,
+	  * in case the starting of async threads is
+	  * delayed by non-async resuming devices.
+	  */
+	list_for_each_entry(dev, &dpm_prepared_list, power.entry) {
+		reinit_completion(dev->power.completion);
+		if (is_async(dev)) {
+			get_device(dev);
+			async_schedule(async_complete, dev);
+		}
+	}
+
 	while (!list_empty(&dpm_prepared_list)) {
-		struct device *dev = to_device(dpm_prepared_list.prev);
+		dev = to_device(dpm_prepared_list.prev);
 
 		get_device(dev);
 		dev->power.is_prepared = false;
 		list_move(&dev->power.entry, &list);
 		mutex_unlock(&dpm_list_mtx);
 
-		device_complete(dev, state);
+		if (!is_async(dev))
+			device_complete(dev, state);
 
 		mutex_lock(&dpm_list_mtx);
 		put_device(dev);
 	}
 	list_splice(&list, &dpm_list);
 	mutex_unlock(&dpm_list_mtx);
+	async_synchronize_full();
 	trace_suspend_resume(TPS("dpm_complete"), state.event, false);
 }
 
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2014-08-25 14:27 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-08-25 15:13 [PATCH 1/2] PM / sleep: Asynchronous threads for dpm_prepare xiaoming wang
2014-08-25 15:13 ` [PATCH 2/2] PM / sleep: Asynchronous threads for dpm_complete xiaoming wang
2014-08-25 14:27   ` kodiak furr
2014-08-25 14:27     ` kodiak furr
  -- strict thread matches above, loose matches on Subject: below --
2014-08-19 20:29 [PATCH 1/2] PM / sleep: Asynchronous threads for dpm_prepare xiaoming wang
2014-08-19 20:29 ` [PATCH 2/2] PM / sleep: Asynchronous threads for dpm_complete xiaoming wang

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.