From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755290AbbEaFHz (ORCPT ); Sun, 31 May 2015 01:07:55 -0400 Received: from mailout1.samsung.com ([203.254.224.24]:47062 "EHLO mailout1.samsung.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751921AbbEaFHo (ORCPT ); Sun, 31 May 2015 01:07:44 -0400 X-AuditID: cbfee690-f796f6d000005054-b6-556a971ee092 Date: Sun, 31 May 2015 05:07:42 +0000 (GMT) From: EunTaik Lee Subject: [RFC PATCH v2] suspend/resume performance improvement To: "rjw@rjwysocki.net" , "pavel@ucw.cz" , "len.brown@intel.com" , "linux-pm@vger.kernel.org" , "linux-kernel@vger.kernel.org" Reply-to: eun.taik.lee@samsung.com MIME-version: 1.0 X-MTR: 20150531050559005@eun.taik.lee Msgkey: 20150531050559005@eun.taik.lee X-EPLocale: ko_KR.utf-8 X-Priority: 3 X-EPWebmail-Msg-Type: personal X-EPWebmail-Reply-Demand: 0 X-EPApproval-Locale: X-EPHeader: ML X-MLAttribute: X-RootMTR: 20150531050559005@eun.taik.lee X-ParentMTR: X-ArchiveUser: EV X-CPGSPASS: N X-ConfirmMail: N,general Content-type: text/plain; charset=utf-8 MIME-version: 1.0 Message-id: <671217780.313831433048860626.JavaMail.weblogic@epmlwas05b> X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFprFJsWRmVeSWpSXmKPExsVy+t8zHV256VmhBpc6dC0u75rD5sDo8XmT XABjVAOjTWJRckZmWapCal5yfkpmXrqtUmiIm66FkkJGfnGJrVK0kYGxnpGpiZ6RibmepUGs lZGpkkJeYm6qrVKFLlSvkkJRcgFQbW5lMdCAnFQ9qLhecWpeikNWfinIJXrFibnFpXnpesn5 uUoKZYk5pUAjlPQTpjJmbNh/ka3gglbF80fH2RoYD2h2MXJyCAmoS5zYvYYFxJYQMJHYMnkL lC0mceHeerYuRi6gmmWMEsv6DjHCFHV0b2WFSMxhlFj7bQIbSIJFQFVixuulYDabgK7E/49d 7F2MHBzCAnYS0y5UgNSLCHxllPi+9Rc7xGYlifmHG8C28QoISpyc+QRqs6rE8wvfWSHiahLb Dm1nh4iLS1yYewnK5pWY0f4Uql5OYtrXNcwQtrTE+VkbGGE+WPz9MVScX+LY7R1MELaAxNQz B6FqtCT6bx6Bsvkk1ix8CzVTUOL0tW5mmF33t8yF6pWQ2NryBOw2ZgFFiSndD8F+ZBbQlFi/ Sx/dK7wC7hILfv5lB/ldQqCTQ6Jt7jRmSFgJSHybfIhlAqPiLCQ9s5CMnYUwFlnJAkaWVYyi qQXJBcVJ6UUmyLG9iRGSCCfsYLx3wPoQowAHoxIPb0RgVqgQa2JZcWXuIcZkoM0TmaVEk/OB 6TavJN7Q2MzIwtTE1NjI3NIMQ9jE1MLCxAiHsJI472upn8FCAumJJanZqakFqUXxRaU5qcWH GJk4OKUaGDNUw1ivvWdoeu/xIjt4c6KR74vKfW8mn/5gGJTTM0Wxp7MskZf/2OTXsSL8N3u+ T7lxKbl9erKb650ZqZa5EqLz9EOMNX8Jn6+YlVJdGvi2svgeZ1yZtL3SyUPPau60plX3fmfR 1VgUwMFYrP2i7dTB4tvqt/5uPHc3SLksoODMi0XtJ6YnKrEUZyQaajEXFScCAD9sKkCtAwAA X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFtrNKsWRmVeSWpSXmKPExsVy+t/tPl256VmhBocualpc3jWHzYHR4/Mm uQDGqAybjNTElNQihdS85PyUzLx0WyXv4HjneFMzA0NdQ0sLcyWFvMTcVFslF58AXbfMHKCh SgpliTmlQKGAxOJiJX07m6L80pJUhYz84hJbpWgjA2M9I1MTPSNjAz0Tg1grQwMDI1OgqoSM jA37L7IVXNCqeP7oOFsD4wHNLkZODiEBdYkTu9ewgNgSAiYSHd1bWSFsMYkL99azdTFyAdXM YZRY+20CG0iCRUBVYsbrpWA2m4CuxP+PXexdjBwcwgJ2EtMuVIDUiwh8ZZT4vvUXO8QCJYn5 hxvAFvAKCEqcnPkEapmqxPML31kh4moS2w5tZ4eIi0tcmHsJyuaVmNH+FKpeTmLa1zXMELa0 xPlZGxhhDl38/TFUnF/i2O0dTBC2gMTUMweharQk+m8egbL5JNYsfAs1U1Di9LVuZphd97fM heqVkNja8gTsNmYBRYkp3Q/BfmQW0JRYv0sf3Su8Au4SC37+ZZ/AKDMLSWoWku5ZCN3IShYw sqxiFE0tSC4oTkqvMNYrTswtLs1L10vOz93ECE44zxbvYPx/3voQowAHoxIPb0RgVqgQa2JZ cWXuIUYJDmYlEV7GLqAQb0piZVVqUX58UWlOavEhRlNgPE1klhJNzgcmw7ySeENjA2NDQ0tz A1NDIwslcd7/53JDhATSE0tSs1NTC1KLYPqYODilGhglnp9aZNiw/KvQ3MgL/DpLHs09Ns08 arez/uHMFt7zvfd891SWp73a3BP386qn9D0nv62PhPKibqWzfb0n7mh1eP+BIu2Ej5FtERUW 132zDv6L11/7YlJbUbb1swVcdT5uDJ23blRIfmE9zdmVbD5nl5LJa1YpI+5PHAftvd+Gp1dG 1yfx3FFiKc5INNRiLipOBABGZydFTgMAAA== DLP-Filter: Pass X-CFilter-Loop: Reflected Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: 8bit X-MIME-Autoconverted: from base64 to 8bit by nfs id t4V57xqH008456 When a task that calls state_store() to suspend the device has used up most of its time slice, suspend sometimes take too long. (User noticeable) Suspend/resume is a system wide operation. So, instead of depending on a userspace task's time slice, let kworker do the work to avoid a long wait on the runqueue. Signed-off-by: Eun Taik Lee --- kernel/power/main.c | 95 ++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 90 insertions(+), 5 deletions(-) diff --git a/kernel/power/main.c b/kernel/power/main.c index 86e8157..848bf2d 100644 --- a/kernel/power/main.c +++ b/kernel/power/main.c @@ -15,7 +15,7 @@ #include #include #include - +#include #include "power.h" DEFINE_MUTEX(pm_mutex); @@ -335,15 +335,46 @@ static suspend_state_t decode_state(const char *buf, size_t n) return PM_SUSPEND_ON; } +static struct workqueue_struct *suspend_helper_wq; +struct state_store_params { + const char *buf; + size_t n; +}; + +struct suspend_helper_data { + struct work_struct work; + struct completion done; + struct state_store_params params; + int result; +}; +struct suspend_helper_data suspend_helper_data; + +static ssize_t state_store_helper(struct kobject *kobj, + struct kobj_attribute *attr, + const char *buf, size_t n); + static ssize_t state_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t n) { + return state_store_helper(kobj, attr, buf, n); +} + +power_attr(state); + +static void suspend_helper(struct work_struct *work) +{ + struct suspend_helper_data *data = (struct suspend_helper_data *) + container_of(work, struct suspend_helper_data, work); + const char *buf = data->params.buf; + size_t n = data->params.n; suspend_state_t state; - int error; + int error = 0; + + pr_debug("%s: start!\n", __func__); error = pm_autosleep_lock(); if (error) - return error; + goto out_nolock; if (pm_autosleep_state() > PM_SUSPEND_ON) { error = -EBUSY; @@ -358,12 +389,64 @@ static ssize_t state_store(struct kobject *kobj, struct kobj_attribute *attr, else error = -EINVAL; - out: +out: pm_autosleep_unlock(); + +out_nolock: + /* set result and notify completion */ + data->result = error; + complete(&data->done); + + pr_debug("%s: result = %d\n", __func__, error); +} + +static ssize_t state_store_helper(struct kobject *kobj, + struct kobj_attribute *attr, + const char *buf, size_t n) +{ + int error; + int freezable = 0; + + /* we don't need to freeze. so tell the freezer */ + if (!freezer_should_skip(current)) { + freezable = 1; + freezer_do_not_count(); + pr_debug("%s: freezer should skip me (%s:%d)\n", + __func__, current->comm, current->pid); + } + + suspend_helper_data.params.buf = buf; + suspend_helper_data.params.n = n; + init_completion(&suspend_helper_data.done); + + /* use kworker for suspend resume */ + queue_work(suspend_helper_wq, &suspend_helper_data.work); + + /* wait for suspend/resume work to be complete */ + wait_for_completion(&suspend_helper_data.done); + + if (freezable) { + /* set ourself as freezable */ + freezer_count(); + } + + error = suspend_helper_data.result; + pr_debug("%s: suspend_helper returned %d\n", __func__, error); + return error ? error : n; } -power_attr(state); +static int suspend_helper_init(void) +{ + suspend_helper_wq = alloc_ordered_workqueue("suspend_helper", 0); + if (!suspend_helper_wq) + return -ENOMEM; + + INIT_WORK(&suspend_helper_data.work, suspend_helper); + init_completion(&suspend_helper_data.done); + + return 0; +} #ifdef CONFIG_PM_SLEEP /* @@ -640,6 +723,8 @@ static int __init pm_init(void) if (error) return error; pm_print_times_init(); + suspend_helper_init(); + return pm_autosleep_init(); } -- 1.9.1 {.n++%ݶw{.n+{G{ayʇڙ,jfhz_(階ݢj"mG?&~iOzv^m ?I