linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Thierry Reding <thierry.reding@gmail.com>
To: Linus Torvalds <torvalds@linux-foundation.org>,
	Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	"Rafael J . Wysocki" <rjw@rjwysocki.net>,
	Pavel Machek <pavel@ucw.cz>
Cc: Sebastian Reichel <sre@kernel.org>,
	Guenter Roeck <linux@roeck-us.net>,
	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	[thread overview]
Message-ID: <20170130171506.3527-2-thierry.reding@gmail.com> (raw)
In-Reply-To: <20170130171506.3527-1-thierry.reding@gmail.com>

From: Thierry Reding <treding@nvidia.com>

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 <treding@nvidia.com>
---
 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 <linux/system-power.h>
+
+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 <linux/device.h>
+#include <linux/list.h>
+#include <linux/reboot.h>
+
+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
-- 
2.11.0

  reply	other threads:[~2017-01-30 17:51 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-01-30 17:15 [RFC 0/3] Add system power and restart framework Thierry Reding
2017-01-30 17:15 ` Thierry Reding [this message]
2017-01-30 21:53   ` [RFC 1/3] system-power: " Pavel Machek
2017-01-31 17:46     ` Thierry Reding
2017-02-01 11:13       ` Pavel Machek
2017-01-30 17:15 ` [RFC 2/3] kernel: Wire up system power framework Thierry Reding
2017-01-30 17:15 ` [RFC 3/3] PM / hibernate: Wire up system-power framework Thierry Reding

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20170130171506.3527-2-thierry.reding@gmail.com \
    --to=thierry.reding@gmail.com \
    --cc=gregkh@linuxfoundation.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-pm@vger.kernel.org \
    --cc=linux@roeck-us.net \
    --cc=pavel@ucw.cz \
    --cc=rjw@rjwysocki.net \
    --cc=sre@kernel.org \
    --cc=torvalds@linux-foundation.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).