From patchwork Mon Jan 30 17:15:04 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thierry Reding X-Patchwork-Id: 9546001 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 9784460415 for ; Mon, 30 Jan 2017 19:24:38 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 863992811E for ; Mon, 30 Jan 2017 19:24:38 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 79430281C3; Mon, 30 Jan 2017 19:24:38 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.3 required=2.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, RCVD_IN_SORBS_SPAM, T_DKIM_INVALID autolearn=unavailable version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 0D9A22811E for ; Mon, 30 Jan 2017 19:24:37 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754139AbdA3TYb (ORCPT ); Mon, 30 Jan 2017 14:24:31 -0500 Received: from mail-wm0-f65.google.com ([74.125.82.65]:35492 "EHLO mail-wm0-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754091AbdA3TYa (ORCPT ); Mon, 30 Jan 2017 14:24:30 -0500 Received: by mail-wm0-f65.google.com with SMTP id u63so10694150wmu.2 for ; Mon, 30 Jan 2017 11:24:29 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=J4NEJobVpyem3yOKgLJBCSS8nmICOE54xiZJg+RXsTI=; b=BFMgVUAJqS88fuSBjk4RktI04qDp0wk1e1+M43O6Q0c8MpXuR7leEzujQGuL2p1QHI wrx+/KdsYv/ZiyzPsJOr6lb/San3L48G75vJQfztvSNChl05gYR2JfuUM8OuBuogWQtT k1LWODaIqeneF2RhG4gpJYDVJ0B4BQQggbEBOOHR7I3gRENlye+NP4q+FaQ6lM0X0zOB adQ93W98apIxlTGdxPPv6gyDo7Y7kTsFFMNNN51JX9McBT2N8mpYw+5LSq74l0GWtFn0 V4CyZpYhlh6zB8nzyFcNhHYnV+52lHvuYvjovt05AhpKRsdE/gGr4ZPMyFWkH4kRUssV HMxw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=J4NEJobVpyem3yOKgLJBCSS8nmICOE54xiZJg+RXsTI=; b=NtXDeMKqQgNGhc/9f5GV1WbZeuG2ILicrtaLtlWH86DKRfN1Ufn1peujgW7MjqNKdl bDqJaGfDYCTvMWA1/vRC3BL+Z+NVXHwHuGTqPRNrGdGV9QyofWXdMt970OeK2pg+6RFH 37i4fBx3N34EhC6pIWVSmcBczqyjyTRf0oVvmjPeOFWZ80jhNAe4/+Mv3vGly35KWx0g 1N5OWIG6z8KY7Pm4s6BxGkaT5XBVZzwc2kaLLVQTflI34v9wzRzpE3vW7oUdWzruPpmX MMzK3wqfFKZVyncfKYsymuizLz46IkvpDXfQ/CsEmxxttXbeeTWSOecVojqp40UkShM6 i84Q== X-Gm-Message-State: AIkVDXJfZkyvYdtQbS3GzOH0iCR/OnWPH3nKTmOghLPa2r2DpF6zg7wVJ+YM2/5/Jmp9hw== X-Received: by 10.223.136.109 with SMTP id e42mr19704746wre.14.1485796510516; Mon, 30 Jan 2017 09:15:10 -0800 (PST) Received: from localhost (port-6519.pppoe.wtnet.de. [84.46.25.144]) by smtp.gmail.com with ESMTPSA id l140sm19759418wmg.12.2017.01.30.09.15.09 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Mon, 30 Jan 2017 09:15:09 -0800 (PST) From: Thierry Reding To: Linus Torvalds , Greg Kroah-Hartman , "Rafael J . Wysocki" , Pavel Machek Cc: Sebastian Reichel , Guenter Roeck , linux-pm@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [RFC 1/3] system-power: Add system power and restart framework Date: Mon, 30 Jan 2017 18:15:04 +0100 Message-Id: <20170130171506.3527-2-thierry.reding@gmail.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20170130171506.3527-1-thierry.reding@gmail.com> References: <20170130171506.3527-1-thierry.reding@gmail.com> Sender: linux-pm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pm@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Thierry Reding This adds a very simple framework that allows drivers to register system power and restart controllers. The goal of this framework is to replace the current notifier based mechanism for restart handlers and the power off equivalent that is the global pm_power_off() function. Both of these approaches currently lack any means of locking against concurrently registering handlers or formal definitions on what proper priorities are to order handlers. The system-power framework attempts to remedy this by adding a system power chip object that drivers can embed in their driver-specific data. A chip contains a description of capabilities that the framework uses to determine a good sequence of handlers to use for restart and power off. Signed-off-by: Thierry Reding --- drivers/base/Makefile | 3 +- drivers/base/system-power.c | 110 +++++++++++++++++++++++++++++++++++++++++++ include/linux/system-power.h | 38 +++++++++++++++ 3 files changed, 150 insertions(+), 1 deletion(-) create mode 100644 drivers/base/system-power.c create mode 100644 include/linux/system-power.h diff --git a/drivers/base/Makefile b/drivers/base/Makefile index f2816f6ff76a..eef165221d9d 100644 --- a/drivers/base/Makefile +++ b/drivers/base/Makefile @@ -4,7 +4,8 @@ obj-y := component.o core.o bus.o dd.o syscore.o \ driver.o class.o platform.o \ cpu.o firmware.o init.o map.o devres.o \ attribute_container.o transport_class.o \ - topology.o container.o property.o cacheinfo.o + topology.o container.o property.o cacheinfo.o \ + system-power.o obj-$(CONFIG_DEVTMPFS) += devtmpfs.o obj-$(CONFIG_DMA_CMA) += dma-contiguous.o obj-y += power/ diff --git a/drivers/base/system-power.c b/drivers/base/system-power.c new file mode 100644 index 000000000000..96c0cb457933 --- /dev/null +++ b/drivers/base/system-power.c @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2017 NVIDIA Corporation + * + * This file is released under the GPL v2 + */ + +#define pr_fmt(fmt) "system-power: " fmt + +#include + +static DEFINE_MUTEX(system_power_lock); +static LIST_HEAD(system_power_chips); + +int system_power_chip_add(struct system_power_chip *chip) +{ + if (!chip->ops || (!chip->ops->restart && !chip->ops->power_off)) { + WARN(1, pr_fmt("must implement restart or power off\n")); + return -EINVAL; + } + + mutex_lock(&system_power_lock); + + INIT_LIST_HEAD(&chip->list); + list_add_tail(&chip->list, &system_power_chips); + + mutex_unlock(&system_power_lock); + + return 0; +} +EXPORT_SYMBOL_GPL(system_power_chip_add); + +int system_power_chip_remove(struct system_power_chip *chip) +{ + mutex_lock(&system_power_lock); + + list_del_init(&chip->list); + + mutex_unlock(&system_power_lock); + + return 0; +} +EXPORT_SYMBOL_GPL(system_power_chip_remove); + +bool system_can_power_off(void) +{ + /* XXX for backwards compatibility */ + return pm_power_off != NULL; +} + +int system_restart(char *cmd) +{ + struct system_power_chip *chip; + int err; + + mutex_lock(&system_power_lock); + + list_for_each_entry(chip, &system_power_chips, list) { + if (!chip->ops->restart) + continue; + + pr_debug("trying to restart using %ps\n", chip); + + err = chip->ops->restart(chip, reboot_mode, cmd); + if (err < 0) + dev_warn(chip->dev, "failed to restart: %d\n", err); + } + + mutex_unlock(&system_power_lock); + + /* XXX for backwards compatibility */ + do_kernel_restart(cmd); + + return 0; +} + +int system_power_off_prepare(void) +{ + /* XXX for backwards compatibility */ + if (pm_power_off_prepare) + pm_power_off_prepare(); + + return 0; +} + +int system_power_off(void) +{ + struct system_power_chip *chip; + int err; + + mutex_lock(&system_power_lock); + + list_for_each_entry(chip, &system_power_chips, list) { + if (!chip->ops->power_off) + continue; + + pr_debug("trying to power off using %ps\n", chip); + + err = chip->ops->power_off(chip); + if (err < 0) + dev_warn(chip->dev, "failed to power off: %d\n", err); + } + + mutex_unlock(&system_power_lock); + + /* XXX for backwards compatibility */ + if (pm_power_off) + pm_power_off(); + + return 0; +} diff --git a/include/linux/system-power.h b/include/linux/system-power.h new file mode 100644 index 000000000000..f709c14c1552 --- /dev/null +++ b/include/linux/system-power.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2017 NVIDIA Corporation + * + * This file is released under the GPL v2 + */ + +#ifndef SYSTEM_POWER_H +#define SYSTEM_POWER_H + +#include +#include +#include + +struct system_power_chip; + +struct system_power_ops { + int (*restart)(struct system_power_chip *chip, enum reboot_mode mode, + char *cmd); + int (*power_off_prepare)(struct system_power_chip *chip); + int (*power_off)(struct system_power_chip *chip); +}; + +struct system_power_chip { + const struct system_power_ops *ops; + struct list_head list; + struct device *dev; +}; + +int system_power_chip_add(struct system_power_chip *chip); +int system_power_chip_remove(struct system_power_chip *chip); + +bool system_can_power_off(void); + +int system_restart(char *cmd); +int system_power_off_prepare(void); +int system_power_off(void); + +#endif