From patchwork Thu Sep 4 21:21:05 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Brian Norris X-Patchwork-Id: 4848061 Return-Path: X-Original-To: patchwork-linux-pm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 6A00A9F3B4 for ; Thu, 4 Sep 2014 21:21:22 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id F0ED120295 for ; Thu, 4 Sep 2014 21:21:20 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id DE99520260 for ; Thu, 4 Sep 2014 21:21:19 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755248AbaIDVVS (ORCPT ); Thu, 4 Sep 2014 17:21:18 -0400 Received: from mail-pd0-f180.google.com ([209.85.192.180]:38763 "EHLO mail-pd0-f180.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754688AbaIDVVR (ORCPT ); Thu, 4 Sep 2014 17:21:17 -0400 Received: by mail-pd0-f180.google.com with SMTP id p10so14504474pdj.39 for ; Thu, 04 Sep 2014 14:21:17 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=r5B8TsqHguKUtIvHLwpCinxssTxOtB+Z3TGPFiRgKIk=; b=OQ8bcFe8ffJKNyerK3cz3jp8hFtl83aDcfodKMuC6wsu+dunrQn37kuTE8z4t2+5un OEkfxccfvNURX94AytyRz6KY5kzxri3FI30JfMlbx3XrUyK04xZGj2gUFsWlchQEJ6tH OZXQgdUJr45rTwBpSXL+qdc3ER/bfQK/HY4LXe9djHQueN0LVmAyh0JEQAK1tXBYOLPV G0QdS/xufHirEWYAORhqJ05viJ4TqFu9OsooplrD6EInTf+Se8fUx5lEgtu4CgrfXWXt 20+KQIVOsOtdydJO4F4amxqQCtGbkvYaRjOOoy0IM7DmT1Hf672lq4Ik/w0/j1uPEQ5w 6u7w== X-Received: by 10.66.157.233 with SMTP id wp9mr13027986pab.11.1409865677157; Thu, 04 Sep 2014 14:21:17 -0700 (PDT) Received: from ld-irv-0074.broadcom.com (5520-maca-inet1-outside.broadcom.com. [216.31.211.11]) by mx.google.com with ESMTPSA id k7sm86930pdn.37.2014.09.04.14.21.15 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 04 Sep 2014 14:21:16 -0700 (PDT) From: Brian Norris To: Greg Kroah-Hartman Cc: , , Linux Kernel , Brian Norris , "Rafael J. Wysocki" Subject: [PATCH 3.10.y+] PM / sleep: Use valid_state() for platform-dependent sleep states only Date: Thu, 4 Sep 2014 14:21:05 -0700 Message-Id: <1409865665-5375-1-git-send-email-computersforpeace@gmail.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1849024.CHOUso6H2K@vostro.rjw.lan> References: <1849024.CHOUso6H2K@vostro.rjw.lan> Sender: linux-pm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pm@vger.kernel.org X-Spam-Status: No, score=-8.4 required=5.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, T_DKIM_INVALID, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: "Rafael J. Wysocki" [Upstream commit 43e8317b0bba1d6eb85f38a4a233d82d7c20d732] Use the observation that, for platform-dependent sleep states (PM_SUSPEND_STANDBY, PM_SUSPEND_MEM), a given state is either always supported or always unsupported and store that information in pm_states[] instead of calling valid_state() every time we need to check it. Also do not use valid_state() for PM_SUSPEND_FREEZE, which is always valid, and move the pm_test_level validity check for PM_SUSPEND_FREEZE directly into enter_state(). Signed-off-by: Rafael J. Wysocki Cc: # 3.10+: 27ddcc6596e5: PM / sleep: Add state field to pm_states[] entries Cc: # 3.10+ --- This is a backport request for these two commits upstream: 27ddcc6596e5 PM / sleep: Add state field to pm_states[] entries 43e8317b0bba PM / sleep: Use valid_state() for platform-dependent sleep states only Rafael ack'd this: https://lkml.org/lkml/2014/9/4/543 I've tested these on 3.14, and it looks like they could go back as far as 3.10. kernel/power/main.c | 9 ++++--- kernel/power/power.h | 2 -- kernel/power/suspend.c | 60 ++++++++++++++++++++++----------------------- kernel/power/suspend_test.c | 2 +- 4 files changed, 36 insertions(+), 37 deletions(-) diff --git a/kernel/power/main.c b/kernel/power/main.c index 8e818432253c..9f51f0ab3d86 100644 --- a/kernel/power/main.c +++ b/kernel/power/main.c @@ -296,7 +296,7 @@ static ssize_t state_show(struct kobject *kobj, struct kobj_attribute *attr, suspend_state_t i; for (i = PM_SUSPEND_MIN; i < PM_SUSPEND_MAX; i++) - if (valid_state(i)) + if (pm_states[i].state) s += sprintf(s,"%s ", pm_states[i].label); #endif @@ -328,8 +328,9 @@ static suspend_state_t decode_state(const char *buf, size_t n) #ifdef CONFIG_SUSPEND for (s = &pm_states[state]; state < PM_SUSPEND_MAX; s++, state++) - if (len == strlen(s->label) && !strncmp(buf, s->label, len)) - return state; + if (s->state && len == strlen(s->label) + && !strncmp(buf, s->label, len)) + return s->state; #endif return PM_SUSPEND_ON; @@ -447,7 +448,7 @@ static ssize_t autosleep_show(struct kobject *kobj, #ifdef CONFIG_SUSPEND if (state < PM_SUSPEND_MAX) - return sprintf(buf, "%s\n", valid_state(state) ? + return sprintf(buf, "%s\n", pm_states[state].state ? pm_states[state].label : "error"); #endif #ifdef CONFIG_HIBERNATION diff --git a/kernel/power/power.h b/kernel/power/power.h index 99539c5da844..c60f13b5270a 100644 --- a/kernel/power/power.h +++ b/kernel/power/power.h @@ -186,14 +186,12 @@ struct pm_sleep_state { /* kernel/power/suspend.c */ extern struct pm_sleep_state pm_states[]; -extern bool valid_state(suspend_state_t state); extern int suspend_devices_and_enter(suspend_state_t state); #else /* !CONFIG_SUSPEND */ static inline int suspend_devices_and_enter(suspend_state_t state) { return -ENOSYS; } -static inline bool valid_state(suspend_state_t state) { return false; } #endif /* !CONFIG_SUSPEND */ #ifdef CONFIG_PM_TEST_SUSPEND diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c index 5d93b138a2d4..00aca60904b0 100644 --- a/kernel/power/suspend.c +++ b/kernel/power/suspend.c @@ -32,9 +32,9 @@ #include "power.h" struct pm_sleep_state pm_states[PM_SUSPEND_MAX] = { - [PM_SUSPEND_FREEZE] = { "freeze", PM_SUSPEND_FREEZE }, - [PM_SUSPEND_STANDBY] = { "standby", PM_SUSPEND_STANDBY }, - [PM_SUSPEND_MEM] = { "mem", PM_SUSPEND_MEM }, + [PM_SUSPEND_FREEZE] = { .label = "freeze", .state = PM_SUSPEND_FREEZE }, + [PM_SUSPEND_STANDBY] = { .label = "standby", }, + [PM_SUSPEND_MEM] = { .label = "mem", }, }; static const struct platform_suspend_ops *suspend_ops; @@ -68,42 +68,34 @@ void freeze_wake(void) } EXPORT_SYMBOL_GPL(freeze_wake); +static bool valid_state(suspend_state_t state) +{ + /* + * PM_SUSPEND_STANDBY and PM_SUSPEND_MEM states need low level + * support and need to be valid to the low level + * implementation, no valid callback implies that none are valid. + */ + return suspend_ops && suspend_ops->valid && suspend_ops->valid(state); +} + /** * suspend_set_ops - Set the global suspend method table. * @ops: Suspend operations to use. */ void suspend_set_ops(const struct platform_suspend_ops *ops) { + suspend_state_t i; + lock_system_sleep(); + suspend_ops = ops; + for (i = PM_SUSPEND_STANDBY; i <= PM_SUSPEND_MEM; i++) + pm_states[i].state = valid_state(i) ? i : 0; + unlock_system_sleep(); } EXPORT_SYMBOL_GPL(suspend_set_ops); -bool valid_state(suspend_state_t state) -{ - if (state == PM_SUSPEND_FREEZE) { -#ifdef CONFIG_PM_DEBUG - if (pm_test_level != TEST_NONE && - pm_test_level != TEST_FREEZER && - pm_test_level != TEST_DEVICES && - pm_test_level != TEST_PLATFORM) { - printk(KERN_WARNING "Unsupported pm_test mode for " - "freeze state, please choose " - "none/freezer/devices/platform.\n"); - return false; - } -#endif - return true; - } - /* - * PM_SUSPEND_STANDBY and PM_SUSPEND_MEMORY states need lowlevel - * support and need to be valid to the lowlevel - * implementation, no valid callback implies that none are valid. - */ - return suspend_ops && suspend_ops->valid && suspend_ops->valid(state); -} - /** * suspend_valid_only_mem - Generic memory-only valid callback. * @@ -330,9 +322,17 @@ static int enter_state(suspend_state_t state) { int error; - if (!valid_state(state)) - return -ENODEV; - + if (state == PM_SUSPEND_FREEZE) { +#ifdef CONFIG_PM_DEBUG + if (pm_test_level != TEST_NONE && pm_test_level <= TEST_CPUS) { + pr_warning("PM: Unsupported test mode for freeze state," + "please choose none/freezer/devices/platform.\n"); + return -EAGAIN; + } +#endif + } else if (!valid_state(state)) { + return -EINVAL; + } if (!mutex_trylock(&pm_mutex)) return -EBUSY; diff --git a/kernel/power/suspend_test.c b/kernel/power/suspend_test.c index d4e3ab167a73..269b097e78ea 100644 --- a/kernel/power/suspend_test.c +++ b/kernel/power/suspend_test.c @@ -162,7 +162,7 @@ static int __init test_suspend(void) /* PM is initialized by now; is that state testable? */ if (test_state == PM_SUSPEND_ON) goto done; - if (!valid_state(test_state)) { + if (!pm_states[test_state].state) { printk(warn_bad_state, pm_states[test_state].label); goto done; }