lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite for Android: free password hash cracker in your pocket
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-Id: <1408979617-14140-1-git-send-email-xiaoming.wang@intel.com>
Date:	Mon, 25 Aug 2014 11:13:36 -0400
From:	xiaoming wang <xiaoming.wang@...el.com>
To:	rjw@...ysocki.net, len.brown@...el.com, pavel@....cz,
	gregkh@...uxfoundation.org, linux-pm@...r.kernel.org,
	linux-kernel@...r.kernel.org
Cc:	xiaoming wang <xiaoming.wang@...el.com>,
	Chuansheng Liu <chuansheng.liu@...el.com>
Subject: [PATCH 1/2] PM / sleep: Asynchronous threads for dpm_prepare

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@...el.com>
Signed-off-by: xiaoming wang <xiaoming.wang@...el.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

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ