linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RFC PATCH 0/3] SCMI System Power Support
@ 2020-04-27 21:08 Cristian Marussi
  2020-04-27 21:08 ` [RFC PATCH 1/3] firmware: arm_scmi: Add System Power Protocol support Cristian Marussi
                   ` (3 more replies)
  0 siblings, 4 replies; 7+ messages in thread
From: Cristian Marussi @ 2020-04-27 21:08 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: sudeep.holla, lukasz.luba, james.quinlan, Jonathan.Cameron,
	cristian.marussi

Hi all,

this series wants to add the core SCMI System Power support and related
events' handling logic: the protocol support itself is trivial and boils
down to some bare initializations and supporting one SCMI System Power
notification event meant to carry platform-originated System transition
requests. This is patch [1/3].

On top of this a new SCMI driver has been developed which registers for
such System Power notification and acts accordingly to satisfy such
plaform system-state transition requests that can be of forceful or
graceful kind.

In order to comply with such graceful requests, and co-operate with
userspace entities to drive a clean shutdown/reboot, the logic of the
driver relies on the same orderly_* API methods used by ACPI when handling
ACPI Shutdown bus events. This is patch [2/3].

Patch [3/3] is a mere JUNO example of the minimal DT bindings needed to
enable the protocol at the DT level and is NOT meant to be upstream as of
now.

A viable alternative method (not implemented here) for communicating
graceful requests to userspace could be to use instead signals to PID 1
init process (e.g. kill_cad_pid(SIGRTMIN + 4, 1)): this method is supported
out-of-the-box by SystemD and (to some extent) Android, and, maybe, could
be interesting as an optional alternative, since it avoids the dependency
on usermodehelpers introduced by the internals of the orderly_ API calls
above.

Such alternative, if deemed worth, should clearly be configurable via DT
(also in terms of which signals to use), BUT all of this work is not done
in this series: and that's the reason for the RFC tag: does it make sense
to add such a configurable additional option ?


The series is based on SCMI Notifications Core V7 (still not posted though)
which in turn is based on top of scmi-for-next-5.7 and it's available (with
some additional debug on top) at [1].


Thanks

Cristian

----

[1] http://www.linux-arm.org/git?p=linux-cm.git;a=shortlog;h=refs/heads/scmi_system_power_V1


Cristian Marussi (3):
  firmware: arm_scmi: Add System Power Protocol support
  firmware: arm_scmi: Add SCMI System Power Control driver
  arm64: dts: juno: add SCMI SystemPower Protocol support

 arch/arm64/boot/dts/arm/juno-base.dtsi        |   4 +
 drivers/firmware/Kconfig                      |  12 +
 drivers/firmware/arm_scmi/Makefile            |   3 +-
 drivers/firmware/arm_scmi/driver.c            |   1 +
 .../firmware/arm_scmi/scmi_power_control.c    | 359 ++++++++++++++++++
 drivers/firmware/arm_scmi/system.c            | 146 +++++++
 include/linux/scmi_protocol.h                 |  17 +
 7 files changed, 541 insertions(+), 1 deletion(-)
 create mode 100644 drivers/firmware/arm_scmi/scmi_power_control.c
 create mode 100644 drivers/firmware/arm_scmi/system.c

-- 
2.17.1


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [RFC PATCH 1/3] firmware: arm_scmi: Add System Power Protocol support
  2020-04-27 21:08 [RFC PATCH 0/3] SCMI System Power Support Cristian Marussi
@ 2020-04-27 21:08 ` Cristian Marussi
  2020-04-27 21:08 ` [RFC PATCH 2/3] firmware: arm_scmi: Add SCMI System Power Control driver Cristian Marussi
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 7+ messages in thread
From: Cristian Marussi @ 2020-04-27 21:08 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: sudeep.holla, lukasz.luba, james.quinlan, Jonathan.Cameron,
	cristian.marussi

Add bare protocol support for SCMI SystemPower as needed by an OSPM agent:
basic initialization and SYSTEM_POWER_STATE_NOTIFIER core notification
support. No event-handling logic is attached to such notification by this
commit.

Signed-off-by: Cristian Marussi <cristian.marussi@arm.com>
---
 drivers/firmware/arm_scmi/Makefile |   2 +-
 drivers/firmware/arm_scmi/system.c | 146 +++++++++++++++++++++++++++++
 include/linux/scmi_protocol.h      |  17 ++++
 3 files changed, 164 insertions(+), 1 deletion(-)
 create mode 100644 drivers/firmware/arm_scmi/system.c

diff --git a/drivers/firmware/arm_scmi/Makefile b/drivers/firmware/arm_scmi/Makefile
index d55612362d65..e01b67bc74b4 100644
--- a/drivers/firmware/arm_scmi/Makefile
+++ b/drivers/firmware/arm_scmi/Makefile
@@ -5,5 +5,5 @@ scmi-driver-y = driver.o notify.o
 scmi-transport-y = shmem.o
 scmi-transport-$(CONFIG_MAILBOX) += mailbox.o
 scmi-transport-$(CONFIG_HAVE_ARM_SMCCC) += smc.o
-scmi-protocols-y = base.o clock.o perf.o power.o reset.o sensors.o
+scmi-protocols-y = base.o clock.o perf.o power.o reset.o sensors.o system.o
 obj-$(CONFIG_ARM_SCMI_POWER_DOMAIN) += scmi_pm_domain.o
diff --git a/drivers/firmware/arm_scmi/system.c b/drivers/firmware/arm_scmi/system.c
new file mode 100644
index 000000000000..9b43d9a873f3
--- /dev/null
+++ b/drivers/firmware/arm_scmi/system.c
@@ -0,0 +1,146 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * System Control and Management Interface (SCMI) System Power Protocol
+ *
+ * Copyright (C) 2020 ARM Ltd.
+ */
+
+#include "common.h"
+#include "notify.h"
+
+#define SCMI_SYSTEM_NUM_SOURCES		1
+
+enum scmi_system_protocol_cmd {
+	SYSTEM_POWER_STATE_NOTIFY = 0x5,
+};
+
+enum scmi_system_protocol_notify {
+	SYSTEM_POWER_STATE_NOTIFIER = 0x0,
+};
+
+struct scmi_system_power_state_notify {
+	__le32 notify_enable;
+};
+
+struct scmi_system_power_state_notifier_payld {
+	__le32 agent_id;
+	__le32 flags;
+	__le32 system_state;
+};
+
+struct scmi_system_info {
+	u32 version;
+};
+
+static int scmi_system_request_notify(const struct scmi_handle *handle,
+				      bool enable)
+{
+	int ret;
+	struct scmi_xfer *t;
+	struct scmi_system_power_state_notify *notify;
+
+	ret = scmi_xfer_get_init(handle, SYSTEM_POWER_STATE_NOTIFY,
+				 SCMI_PROTOCOL_SYSTEM, sizeof(*notify), 0, &t);
+	if (ret)
+		return ret;
+
+	notify = t->tx.buf;
+	notify->notify_enable = enable ? cpu_to_le32(BIT(0)) : 0;
+
+	ret = scmi_do_xfer(handle, t);
+
+	scmi_xfer_put(handle, t);
+	return ret;
+}
+
+static bool scmi_system_set_notify_enabled(const struct scmi_handle *handle,
+					   u8 evt_id, u32 src_id, bool enable)
+{
+	int ret;
+
+	ret = scmi_system_request_notify(handle, enable);
+	if (ret)
+		pr_warn("SCMI Notifications - Proto:%X - FAIL_ENABLE - evt[%X] - ret:%d\n",
+				SCMI_PROTOCOL_SYSTEM, evt_id, ret);
+
+	return !ret;
+}
+
+static void *scmi_system_fill_custom_report(const struct scmi_handle *handle,
+					    u8 evt_id, u64 timestamp,
+					    const void *payld, size_t payld_sz,
+					    void *report, u32 *src_id)
+{
+	void *rep = NULL;
+
+	switch (evt_id) {
+	case SYSTEM_POWER_STATE_NOTIFIER:
+	{
+		const struct scmi_system_power_state_notifier_payld *p = payld;
+		struct scmi_system_power_state_notifier_report *r = report;
+
+		if (sizeof(*p) != payld_sz)
+			break;
+
+		r->timestamp = timestamp;
+		r->agent_id = le32_to_cpu(p->agent_id);
+		r->flags = le32_to_cpu(p->flags);
+		r->system_state = le32_to_cpu(p->system_state);
+		*src_id = 0;
+		rep = r;
+		break;
+	}
+	default:
+		break;
+	}
+
+	return rep;
+}
+
+static const struct scmi_event system_events[] = {
+	{
+		.id = SYSTEM_POWER_STATE_NOTIFIER,
+		.max_payld_sz = 12,
+		.max_report_sz =
+			sizeof(struct scmi_system_power_state_notifier_report),
+	},
+};
+
+static const struct scmi_protocol_event_ops system_event_ops = {
+	.set_notify_enabled = scmi_system_set_notify_enabled,
+	.fill_custom_report = scmi_system_fill_custom_report,
+};
+
+static int scmi_system_protocol_init(struct scmi_handle *handle)
+{
+	u32 version;
+	struct scmi_system_info *pinfo;
+
+	scmi_version_get(handle, SCMI_PROTOCOL_SYSTEM, &version);
+
+	dev_dbg(handle->dev, "System Power Version %d.%d\n",
+		PROTOCOL_REV_MAJOR(version), PROTOCOL_REV_MINOR(version));
+
+	pinfo = devm_kzalloc(handle->dev, sizeof(*pinfo), GFP_KERNEL);
+	if (!pinfo)
+		return -ENOMEM;
+
+	scmi_register_protocol_events(handle,
+				      SCMI_PROTOCOL_SYSTEM, PAGE_SIZE,
+				      &system_event_ops,
+				      system_events,
+				      ARRAY_SIZE(system_events),
+				      SCMI_SYSTEM_NUM_SOURCES);
+
+	pinfo->version = version;
+	handle->system_priv = pinfo;
+
+	return 0;
+}
+
+static int __init scmi_system_init(void)
+{
+	return scmi_protocol_register(SCMI_PROTOCOL_SYSTEM,
+				      &scmi_system_protocol_init);
+}
+subsys_initcall(scmi_system_init);
diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h
index 1ee6f0502565..fc9f0105e6cc 100644
--- a/include/linux/scmi_protocol.h
+++ b/include/linux/scmi_protocol.h
@@ -295,6 +295,7 @@ struct scmi_handle {
 	void *sensor_priv;
 	void *reset_priv;
 	void *notify_priv;
+	void *system_priv;
 };
 
 enum scmi_std_protocol {
@@ -307,6 +308,15 @@ enum scmi_std_protocol {
 	SCMI_PROTOCOL_RESET = 0x16,
 };
 
+enum scmi_system_events {
+	SCMI_SYSTEM_SHUTDOWN,
+	SCMI_SYSTEM_COLDRESET,
+	SCMI_SYSTEM_WARMRESET,
+	SCMI_SYSTEM_POWERUP,
+	SCMI_SYSTEM_SUSPEND,
+	SCMI_SYSTEM_MAX
+};
+
 struct scmi_device {
 	u32 id;
 	u8 protocol_id;
@@ -388,6 +398,13 @@ struct scmi_power_state_change_requested_report {
 	u32 power_state;
 };
 
+struct scmi_system_power_state_notifier_report {
+	u64 timestamp;
+	u32 agent_id;
+	u32 flags;
+	u32 system_state;
+};
+
 struct scmi_perf_limits_report {
 	u64 timestamp;
 	u32 agent_id;
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [RFC PATCH 2/3] firmware: arm_scmi: Add SCMI System Power Control driver
  2020-04-27 21:08 [RFC PATCH 0/3] SCMI System Power Support Cristian Marussi
  2020-04-27 21:08 ` [RFC PATCH 1/3] firmware: arm_scmi: Add System Power Protocol support Cristian Marussi
@ 2020-04-27 21:08 ` Cristian Marussi
  2020-04-27 21:08 ` [RFC PATCH 3/3] arm64: dts: juno: add SCMI SystemPower Protocol support Cristian Marussi
  2020-04-28 20:18 ` [RFC PATCH 0/3] SCMI System Power Support Rob Herring
  3 siblings, 0 replies; 7+ messages in thread
From: Cristian Marussi @ 2020-04-27 21:08 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: sudeep.holla, lukasz.luba, james.quinlan, Jonathan.Cameron,
	cristian.marussi

Add an SCMI System Power control driver to handle platform's requests
carried by SYSTEM_POWER_STATE_NOTIFIER notifications: such platform
requested system power state transitions are handled accordingly,
gracefully or forcefully, depending on the notification's flags.

Graceful requests are relayed to userspace using the same Kernel API used
to handle ACPI Shutdown bus events. (orderly_poweroff/reboot()).

For graceful requests grant userspace processes a maximum (configurable)
time to perform their duties and then revert to a forceful transition, so
avoiding completely timing out platform's maximum grace time and hitting
possible abrupt power-cuts.

Signed-off-by: Cristian Marussi <cristian.marussi@arm.com>
---
 drivers/firmware/Kconfig                      |  12 +
 drivers/firmware/arm_scmi/Makefile            |   1 +
 drivers/firmware/arm_scmi/driver.c            |   1 +
 .../firmware/arm_scmi/scmi_power_control.c    | 359 ++++++++++++++++++
 4 files changed, 373 insertions(+)
 create mode 100644 drivers/firmware/arm_scmi/scmi_power_control.c

diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
index 8007d4aa76dc..f064e1f47cb7 100644
--- a/drivers/firmware/Kconfig
+++ b/drivers/firmware/Kconfig
@@ -40,6 +40,18 @@ config ARM_SCMI_POWER_DOMAIN
 	  will be called scmi_pm_domain. Note this may needed early in boot
 	  before rootfs may be available.
 
+config ARM_SCMI_POWER_CONTROL
+	bool "SCMI power control driver"
+	depends on ARM_SCMI_PROTOCOL || (COMPILE_TEST && OF)
+	default y
+	help
+	  This enables System Power control logic which binds system shutdown or
+	  reboot actions to SCMI System Power notificationns generated by SCP
+	  firmware.
+
+	  Graceful requests max timeout can be configured at boot time using
+	  module parameter named scmi_graceful_request_tmo_ms.
+
 config ARM_SCPI_PROTOCOL
 	tristate "ARM System Control and Power Interface (SCPI) Message Protocol"
 	depends on ARM || ARM64 || COMPILE_TEST
diff --git a/drivers/firmware/arm_scmi/Makefile b/drivers/firmware/arm_scmi/Makefile
index e01b67bc74b4..280568632791 100644
--- a/drivers/firmware/arm_scmi/Makefile
+++ b/drivers/firmware/arm_scmi/Makefile
@@ -7,3 +7,4 @@ scmi-transport-$(CONFIG_MAILBOX) += mailbox.o
 scmi-transport-$(CONFIG_HAVE_ARM_SMCCC) += smc.o
 scmi-protocols-y = base.o clock.o perf.o power.o reset.o sensors.o system.o
 obj-$(CONFIG_ARM_SCMI_POWER_DOMAIN) += scmi_pm_domain.o
+obj-$(CONFIG_ARM_SCMI_POWER_CONTROL) += scmi_power_control.o
diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c
index 5d89d0e9d650..dd6ac0819c69 100644
--- a/drivers/firmware/arm_scmi/driver.c
+++ b/drivers/firmware/arm_scmi/driver.c
@@ -733,6 +733,7 @@ struct scmi_prot_devnames {
 
 static struct scmi_prot_devnames devnames[] = {
 	{ SCMI_PROTOCOL_POWER,  { "genpd", "notifytest" },},
+	{ SCMI_PROTOCOL_SYSTEM, {"syspower" },},
 	{ SCMI_PROTOCOL_PERF,   { "cpufreq" },},
 	{ SCMI_PROTOCOL_CLOCK,  { "clocks" },},
 	{ SCMI_PROTOCOL_SENSOR, { "hwmon" },},
diff --git a/drivers/firmware/arm_scmi/scmi_power_control.c b/drivers/firmware/arm_scmi/scmi_power_control.c
new file mode 100644
index 000000000000..3b8d50ae2f25
--- /dev/null
+++ b/drivers/firmware/arm_scmi/scmi_power_control.c
@@ -0,0 +1,359 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * SCMI Generic System Power support.
+ *
+ * Copyright (C) 2020 ARM Ltd.
+ */
+/**
+ * DOC: Theory of operation
+ *
+ * In order to handle platform originated SCMI System Power requests (like
+ * shutdowns or cold/warm resets) we register an SCMI Notification notifier
+ * to react when such SCMI System Power events are emitted.
+ *
+ * Once such a notification is received we act accordingly to perform the
+ * required system transition depending on the kind of request.
+ *
+ * Graceful requests are routed to userspace through the same API methods
+ * (orderly_poweroff/reboot()) used by ACPI when handling ACPI Shutdown bus
+ * events.
+ *
+ * Forceful requests instead simply cause and immediate emergency_sync() and
+ * subsequent Kernel-only shutdown/reboot.
+ *
+ * The assumption here is that even graceful requests can be upper-bound by a
+ * maximum final timeout strictly enforced by the platform itself which can
+ * finally cuts the power off at will: in such a scenario, that we want to
+ * avoid, we track the graceful requests progress through thee means of a
+ * reboot_notifier and promptly convert a timing-out graceful request to a
+ * forceful one when userspace is late, in order to at least perform a clean
+ * sync and shutdown/restart.
+ *
+ * Given that such platform hard-timeout, when present, is anyway highly
+ * platform/event specific and not exposed at run-time, we make it configurable
+ * via the Kernel module param @scmi_graceful_request_tmo_ms.
+ */
+
+#include <linux/atomic.h>
+#include <linux/bitfield.h>
+#include <linux/err.h>
+#include <linux/fs.h>
+#include <linux/module.h>
+#include <linux/reboot.h>
+#include <linux/scmi_protocol.h>
+#include <linux/slab.h>
+#include <linux/timer.h>
+#include <linux/types.h>
+#include <linux/workqueue.h>
+
+#define DEFAULT_GRACE_TMO_MS	5000
+static unsigned int scmi_graceful_request_tmo_ms = DEFAULT_GRACE_TMO_MS;
+
+enum scmi_system_request_status {
+	SCMI_SYSPOWER_IDLE,
+	SCMI_SYSPOWER_SERVED,
+	SCMI_SYSPOWER_INPROGRESS,
+	SCMI_SYSPOWER_FORCING,
+};
+
+struct scmi_syspower_config {
+	struct device *dev;
+
+	atomic_t status;
+
+	u32 required_state;
+
+	void (*request_graceful_transition)(struct scmi_syspower_config *conf);
+	void (*request_forceful_transition)(struct scmi_syspower_config *conf);
+
+	struct notifier_block userspace_nb;
+	struct notifier_block reboot_nb;
+
+	struct timer_list request_timer;
+	struct work_struct forceful_work;
+};
+
+static void scmi_forceful_work_func(struct work_struct *work)
+{
+	struct scmi_syspower_config *conf =
+		container_of(work, struct scmi_syspower_config, forceful_work);
+
+	conf->request_forceful_transition(conf);
+}
+
+/**
+ * scmi_request_timeout  - On timeout trigger a forceful transition
+ * @t: The timer reference
+ *
+ * Actual work is deferred out of the timer IRQ context since shutdown/reboot
+ * code do not play well when !in_task().
+ */
+static void scmi_request_timeout(struct timer_list *t)
+{
+	struct scmi_syspower_config *conf = from_timer(conf, t, request_timer);
+
+	dev_warn(conf->dev,
+		 "SCMI Graceful System Transition request timed out !\n");
+	atomic_set(&conf->status, SCMI_SYSPOWER_FORCING);
+	/* Ensure atomic values are updated */
+	smp_mb__after_atomic();
+	schedule_work(&conf->forceful_work);
+}
+
+/**
+ * scmi_reboot_notifier  - A reboot_notifier to catch an ongoing successful
+ * system transition
+ * @nb: Reference to the related notifier block
+ * @reason: The reason for the ongoing reboot
+ * @__unused: The cmd being executed on a restart request (unused)
+ *
+ * When an ongoing system transition is detected, compatible with the requested
+ * one, cancel the timer work.
+ *
+ * Return: NOTIFY_OK in any case
+ */
+static int scmi_reboot_notifier(struct notifier_block *nb,
+				unsigned long reason, void *__unused)
+{
+	struct scmi_syspower_config *conf;
+
+	conf = container_of(nb, struct scmi_syspower_config, reboot_nb);
+
+	/* Ensure atomic values are updated */
+	smp_mb__before_atomic();
+	if (unlikely(atomic_read(&conf->status) == SCMI_SYSPOWER_FORCING))
+		return NOTIFY_OK;
+
+	switch (reason) {
+	case SYS_HALT:
+	case SYS_POWER_OFF:
+		if (conf->required_state == SCMI_SYSTEM_SHUTDOWN)
+			atomic_set(&conf->status, SCMI_SYSPOWER_INPROGRESS);
+		break;
+	case SYS_RESTART:
+		if (conf->required_state == SCMI_SYSTEM_COLDRESET ||
+		    conf->required_state == SCMI_SYSTEM_WARMRESET)
+			atomic_set(&conf->status, SCMI_SYSPOWER_INPROGRESS);
+		break;
+	default:
+		break;
+	}
+
+	/* Ensure atomic values are updated */
+	smp_mb__after_atomic();
+	if (atomic_read(&conf->status) == SCMI_SYSPOWER_INPROGRESS) {
+		dev_info(conf->dev,
+			 "SCMI System State request in progress...\n");
+		del_timer_sync(&conf->request_timer);
+	}
+
+	return NOTIFY_OK;
+}
+
+/**
+ * scmi_request_graceful_transition  - Request graceful SystemPower transition
+ * @conf: The current SystemPower configuration descriptor
+ *
+ * Initiates the required SystemPower transition, requesting userspace
+ * co-operation using the same orderly_ methods used by ACPI Shutdown event
+ * processing.
+ *
+ * This takes care also to register a reboot notifier and a timer callback in
+ * order to detect if userspace actions are taking too long; in such a case
+ * the timeout callback will finally perform a forceful transition, ignoring
+ * lagging userspace: the aim here is to at least perform an emergency_sync()
+ * and a clean shutdown or reboot transition when userspace is late, avoiding
+ * the brutal final power-cut from platform.
+ */
+static void scmi_request_graceful_transition(struct scmi_syspower_config *conf)
+{
+	int ret;
+	u32 status;
+
+	if (conf->required_state >= SCMI_SYSTEM_POWERUP) {
+		dev_warn(conf->dev,
+			 "Received unexpected SYSTEM POWER request: %d\n",
+			 conf->required_state);
+		return;
+	}
+
+	status = atomic_cmpxchg(&conf->status, SCMI_SYSPOWER_IDLE,
+				SCMI_SYSPOWER_SERVED);
+	if (status != SCMI_SYSPOWER_IDLE)
+		return;
+
+	dev_info(conf->dev,
+		 "Serving SCMI Graceful request: %d (timeout_ms:%d)\n",
+		 conf->required_state, scmi_graceful_request_tmo_ms);
+
+	ret = devm_register_reboot_notifier(conf->dev, &conf->reboot_nb);
+	if (ret)
+		dev_warn(conf->dev, "Cannot register reboot notifier !\n");
+
+	INIT_WORK(&conf->forceful_work, scmi_forceful_work_func);
+	conf->request_timer.expires = jiffies +
+				msecs_to_jiffies(scmi_graceful_request_tmo_ms);
+	timer_setup(&conf->request_timer, scmi_request_timeout, 0);
+	add_timer(&conf->request_timer);
+
+	switch (conf->required_state) {
+	case SCMI_SYSTEM_SHUTDOWN:
+		/*
+		 * When received early at boot-time the 'orderly' part will
+		 * fail due to the lack of userspace itself, but the force=true
+		 * argument will anyway be able trigger a successful forced
+		 * shutdown.
+		 */
+		orderly_poweroff(true);
+		break;
+	case SCMI_SYSTEM_COLDRESET:
+	case SCMI_SYSTEM_WARMRESET:
+		orderly_reboot();
+		break;
+	default:
+		break;
+	}
+}
+
+static void scmi_request_forceful_transition(struct scmi_syspower_config *conf)
+{
+	/* Ensure atomic values are updated */
+	smp_mb__before_atomic();
+	if (unlikely(atomic_read(&conf->status) == SCMI_SYSPOWER_INPROGRESS))
+		return;
+
+	dev_info(conf->dev, "Serving SCMI FORCEFUL SystemPower request:%d\n",
+		 conf->required_state);
+
+	emergency_sync();
+	switch (conf->required_state) {
+	case SCMI_SYSTEM_SHUTDOWN:
+		kernel_power_off();
+		break;
+	case SCMI_SYSTEM_COLDRESET:
+	case SCMI_SYSTEM_WARMRESET:
+		kernel_restart(NULL);
+		break;
+	default:
+		break;
+	}
+}
+
+#define SCMI_IS_REQUEST_GRACEFUL(flags)		((flags) & BIT(0))
+
+/**
+ * scmi_userspace_notifier  - Notifier callback to act on SystemPower
+ * Notifications
+ * @nb: Reference to the related notifier block
+ * @event: The SystemPower notification event id
+ * @data: The SystemPower event report
+ *
+ * This callback is in charge of decoding the received SystemPower report
+ * and act accordingly triggering a graceful or forceful system transition.
+ *
+ * Return: NOTIFY_OK in any case
+ */
+static int scmi_userspace_notifier(struct notifier_block *nb,
+				   unsigned long event, void *data)
+{
+	struct scmi_system_power_state_notifier_report *er = data;
+	struct scmi_syspower_config *conf;
+
+	if (unlikely(system_state > SYSTEM_RUNNING))
+		return NOTIFY_OK;
+
+	conf = container_of(nb, struct scmi_syspower_config, userspace_nb);
+	conf->required_state = er->system_state;
+
+	if (conf->required_state >= SCMI_SYSTEM_MAX)
+		return NOTIFY_OK;
+
+	if (SCMI_IS_REQUEST_GRACEFUL(er->flags))
+		conf->request_graceful_transition(conf);
+	else
+		conf->request_forceful_transition(conf);
+
+	return NOTIFY_OK;
+}
+
+/**
+ * scmi_syspower_configure  - General SystemPower configuration init
+ * @dev: The associated struct device
+ *
+ * Return: SystemPower configuration descriptor on Success, NULL otherwise
+ */
+static void *scmi_syspower_configure(struct device *dev)
+{
+	struct scmi_syspower_config *conf;
+
+	conf = devm_kzalloc(dev, sizeof(*conf), GFP_KERNEL);
+	if (!conf)
+		return NULL;
+
+	conf->dev = dev;
+	conf->required_state = SCMI_SYSTEM_MAX;
+	conf->request_graceful_transition = &scmi_request_graceful_transition;
+	conf->request_forceful_transition = &scmi_request_forceful_transition;
+	conf->userspace_nb.notifier_call = &scmi_userspace_notifier;
+	conf->reboot_nb.notifier_call = &scmi_reboot_notifier;
+	atomic_set(&conf->status, SCMI_SYSPOWER_IDLE);
+	/* Ensure atomic values are updated */
+	smp_mb__after_atomic();
+
+	return conf;
+}
+
+static int scmi_syspower_probe(struct scmi_device *sdev)
+{
+	int ret;
+	struct scmi_handle *handle = sdev->handle;
+	struct scmi_syspower_config *syspower_conf;
+
+	if (!handle)
+		return -ENODEV;
+
+	syspower_conf = scmi_syspower_configure(&sdev->dev);
+	if (!syspower_conf)
+		return -ENOMEM;
+
+	dev_set_drvdata(&sdev->dev, syspower_conf);
+	ret = handle->notify_ops->register_event_notifier(handle,
+						SCMI_PROTOCOL_SYSTEM, 0x0, NULL,
+						  &syspower_conf->userspace_nb);
+
+	return 0;
+}
+
+static void scmi_syspower_remove(struct scmi_device *sdev)
+{
+	int ret;
+	const struct scmi_handle *handle = sdev->handle;
+	struct scmi_syspower_config *syspower_conf;
+
+	syspower_conf = dev_get_drvdata(&sdev->dev);
+	ret = handle->notify_ops->unregister_event_notifier(handle,
+						SCMI_PROTOCOL_SYSTEM, 0x0, NULL,
+						  &syspower_conf->userspace_nb);
+}
+
+static const struct scmi_device_id scmi_id_table[] = {
+	{ SCMI_PROTOCOL_SYSTEM, "syspower" },
+	{ },
+};
+MODULE_DEVICE_TABLE(scmi, scmi_id_table);
+
+static struct scmi_driver scmi_system_power_driver = {
+	.name = "scmi-system-power",
+	.probe = scmi_syspower_probe,
+	.remove = scmi_syspower_remove,
+	.id_table = scmi_id_table,
+};
+module_scmi_driver(scmi_system_power_driver);
+
+module_param(scmi_graceful_request_tmo_ms, uint, 0644);
+MODULE_PARM_DESC(scmi_graceful_request_tmo_ms,
+	"Maximum time(ms) allowed to userspace to comply to the request");
+
+MODULE_AUTHOR("Cristian Marussi <cristian.marussi@arm.com>");
+MODULE_DESCRIPTION("ARM SCMI System Power driver");
+MODULE_LICENSE("GPL v2");
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [RFC PATCH 3/3] arm64: dts: juno: add SCMI SystemPower Protocol support
  2020-04-27 21:08 [RFC PATCH 0/3] SCMI System Power Support Cristian Marussi
  2020-04-27 21:08 ` [RFC PATCH 1/3] firmware: arm_scmi: Add System Power Protocol support Cristian Marussi
  2020-04-27 21:08 ` [RFC PATCH 2/3] firmware: arm_scmi: Add SCMI System Power Control driver Cristian Marussi
@ 2020-04-27 21:08 ` Cristian Marussi
  2020-04-28 20:18 ` [RFC PATCH 0/3] SCMI System Power Support Rob Herring
  3 siblings, 0 replies; 7+ messages in thread
From: Cristian Marussi @ 2020-04-27 21:08 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: sudeep.holla, lukasz.luba, james.quinlan, Jonathan.Cameron,
	cristian.marussi

arm64: dts: juno: add SCMI SystemPower Protocol support

Signed-off-by: Cristian Marussi <cristian.marussi@arm.com>
---
 arch/arm64/boot/dts/arm/juno-base.dtsi | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/arch/arm64/boot/dts/arm/juno-base.dtsi b/arch/arm64/boot/dts/arm/juno-base.dtsi
index af451935146e..ffb429120a13 100644
--- a/arch/arm64/boot/dts/arm/juno-base.dtsi
+++ b/arch/arm64/boot/dts/arm/juno-base.dtsi
@@ -581,6 +581,10 @@
 				#power-domain-cells = <1>;
 			};
 
+			scmi_system: protocol@12 {
+				reg = <0x12>;
+			};
+
 			scmi_dvfs: protocol@13 {
 				reg = <0x13>;
 				#clock-cells = <1>;
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [RFC PATCH 0/3] SCMI System Power Support
  2020-04-27 21:08 [RFC PATCH 0/3] SCMI System Power Support Cristian Marussi
                   ` (2 preceding siblings ...)
  2020-04-27 21:08 ` [RFC PATCH 3/3] arm64: dts: juno: add SCMI SystemPower Protocol support Cristian Marussi
@ 2020-04-28 20:18 ` Rob Herring
       [not found]   ` <DB7PR08MB3657577B2251084FF2B4A0EF9EAA0@DB7PR08MB3657.eurprd08.prod.outlook.com>
  3 siblings, 1 reply; 7+ messages in thread
From: Rob Herring @ 2020-04-28 20:18 UTC (permalink / raw)
  To: Cristian Marussi
  Cc: linux-kernel,
	moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE,
	Jonathan Cameron, james.quinlan, Lukasz Luba, Sudeep Holla

On Mon, Apr 27, 2020 at 4:08 PM Cristian Marussi
<cristian.marussi@arm.com> wrote:
>
> Hi all,
>
> this series wants to add the core SCMI System Power support and related
> events' handling logic: the protocol support itself is trivial and boils
> down to some bare initializations and supporting one SCMI System Power
> notification event meant to carry platform-originated System transition
> requests. This is patch [1/3].
>
> On top of this a new SCMI driver has been developed which registers for
> such System Power notification and acts accordingly to satisfy such
> plaform system-state transition requests that can be of forceful or
> graceful kind.

I needed this 7 years ago. :) (hb_keys_notifier in
arch/arm/mach-highbank/highbank.c)

> In order to comply with such graceful requests, and co-operate with
> userspace entities to drive a clean shutdown/reboot, the logic of the
> driver relies on the same orderly_* API methods used by ACPI when handling
> ACPI Shutdown bus events. This is patch [2/3].
>
> Patch [3/3] is a mere JUNO example of the minimal DT bindings needed to
> enable the protocol at the DT level and is NOT meant to be upstream as of
> now.
>
> A viable alternative method (not implemented here) for communicating
> graceful requests to userspace could be to use instead signals to PID 1
> init process (e.g. kill_cad_pid(SIGRTMIN + 4, 1)): this method is supported
> out-of-the-box by SystemD and (to some extent) Android, and, maybe, could
> be interesting as an optional alternative, since it avoids the dependency
> on usermodehelpers introduced by the internals of the orderly_ API calls
> above.
>
> Such alternative, if deemed worth, should clearly be configurable via DT
> (also in terms of which signals to use), BUT all of this work is not done
> in this series: and that's the reason for the RFC tag: does it make sense
> to add such a configurable additional option ?

Which process signal to use in DT? I don't think so.

> The series is based on SCMI Notifications Core V7 (still not posted though)
> which in turn is based on top of scmi-for-next-5.7 and it's available (with
> some additional debug on top) at [1].
>
>
> Thanks
>
> Cristian
>
> ----
>
> [1] http://www.linux-arm.org/git?p=linux-cm.git;a=shortlog;h=refs/heads/scmi_system_power_V1
>
>
> Cristian Marussi (3):
>   firmware: arm_scmi: Add System Power Protocol support
>   firmware: arm_scmi: Add SCMI System Power Control driver
>   arm64: dts: juno: add SCMI SystemPower Protocol support
>
>  arch/arm64/boot/dts/arm/juno-base.dtsi        |   4 +
>  drivers/firmware/Kconfig                      |  12 +
>  drivers/firmware/arm_scmi/Makefile            |   3 +-
>  drivers/firmware/arm_scmi/driver.c            |   1 +
>  .../firmware/arm_scmi/scmi_power_control.c    | 359 ++++++++++++++++++
>  drivers/firmware/arm_scmi/system.c            | 146 +++++++
>  include/linux/scmi_protocol.h                 |  17 +
>  7 files changed, 541 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/firmware/arm_scmi/scmi_power_control.c
>  create mode 100644 drivers/firmware/arm_scmi/system.c
>
> --
> 2.17.1
>
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [RFC PATCH 0/3] SCMI System Power Support
       [not found]   ` <DB7PR08MB3657577B2251084FF2B4A0EF9EAA0@DB7PR08MB3657.eurprd08.prod.outlook.com>
@ 2020-05-06 19:11     ` Rob Herring
  2020-05-11 16:05       ` Cristian Marussi
  0 siblings, 1 reply; 7+ messages in thread
From: Rob Herring @ 2020-05-06 19:11 UTC (permalink / raw)
  To: Cristian Marussi
  Cc: linux-kernel,
	moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE,
	Jonathan Cameron, james.quinlan, Lukasz Luba, Sudeep Holla

On Thu, Apr 30, 2020 at 12:23 PM Cristian Marussi
<Cristian.Marussi@arm.com> wrote:
>
> Hi Rob
>
> thanks for the feedback.

Plain text for maillists please.

>
> > On top of this a new SCMI driver has been developed which registers for
> > ----
> > such System Power notification and acts accordingly to satisfy such
> > plaform system-state transition requests that can be of forceful or
> > graceful kind.
>
> > I needed this 7 years ago. :) (hb_keys_notifier in
> > arch/arm/mach-highbank/highbank.c)
>
> ...better later than never
>
> > Such alternative, if deemed worth, should clearly be configurable via DT
> > (also in terms of which signals to use), BUT all of this work is not done
> > in this series: and that's the reason for the RFC tag: does it make sense
> > to add such a configurable additional option ?
>
> >Which process signal to use in DT? I don't think so.
>
> ... beside the awkward bad idea of mine of configuring it via DT
> (which I'll drop possibly using modparams for this config), my question
> was more about if it makes sense at all to have another alternative mechanism
> (other than orderly_poweroof/reboot)) based on signals to gracefully ask userspace
> to shutdown

gregkh will tell you no to module params.

If the signal is not standard, then we probably shouldn't go that route.

Rob

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [RFC PATCH 0/3] SCMI System Power Support
  2020-05-06 19:11     ` Rob Herring
@ 2020-05-11 16:05       ` Cristian Marussi
  0 siblings, 0 replies; 7+ messages in thread
From: Cristian Marussi @ 2020-05-11 16:05 UTC (permalink / raw)
  To: Rob Herring
  Cc: linux-kernel,
	moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE,
	Jonathan Cameron, james.quinlan, Lukasz Luba, Sudeep Holla

On Wed, May 06, 2020 at 02:11:45PM -0500, Rob Herring wrote:
> On Thu, Apr 30, 2020 at 12:23 PM Cristian Marussi
> <Cristian.Marussi@arm.com> wrote:
> >
> > Hi Rob
> >
> > thanks for the feedback.
> 
> Plain text for maillists please.
> 
Yes I know, sorry, used wrong client by mistake.

> >
> > > On top of this a new SCMI driver has been developed which registers for
> > > ----
> > > such System Power notification and acts accordingly to satisfy such
> > > plaform system-state transition requests that can be of forceful or
> > > graceful kind.
> >
> > > I needed this 7 years ago. :) (hb_keys_notifier in
> > > arch/arm/mach-highbank/highbank.c)
> >
> > ...better later than never
> >
> > > Such alternative, if deemed worth, should clearly be configurable via DT
> > > (also in terms of which signals to use), BUT all of this work is not done
> > > in this series: and that's the reason for the RFC tag: does it make sense
> > > to add such a configurable additional option ?
> >
> > >Which process signal to use in DT? I don't think so.
> >
> > ... beside the awkward bad idea of mine of configuring it via DT
> > (which I'll drop possibly using modparams for this config), my question
> > was more about if it makes sense at all to have another alternative mechanism
> > (other than orderly_poweroof/reboot)) based on signals to gracefully ask userspace
> > to shutdown
> 
> gregkh will tell you no to module params.
> 
> If the signal is not standard, then we probably shouldn't go that route.
> 

Before this reply, I posted a v2 with alternative signal-method configurable by modparam;
it's anyway a small addition which I can easily remove in a v3.

Thanks

Cristian

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2020-05-11 16:05 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-04-27 21:08 [RFC PATCH 0/3] SCMI System Power Support Cristian Marussi
2020-04-27 21:08 ` [RFC PATCH 1/3] firmware: arm_scmi: Add System Power Protocol support Cristian Marussi
2020-04-27 21:08 ` [RFC PATCH 2/3] firmware: arm_scmi: Add SCMI System Power Control driver Cristian Marussi
2020-04-27 21:08 ` [RFC PATCH 3/3] arm64: dts: juno: add SCMI SystemPower Protocol support Cristian Marussi
2020-04-28 20:18 ` [RFC PATCH 0/3] SCMI System Power Support Rob Herring
     [not found]   ` <DB7PR08MB3657577B2251084FF2B4A0EF9EAA0@DB7PR08MB3657.eurprd08.prod.outlook.com>
2020-05-06 19:11     ` Rob Herring
2020-05-11 16:05       ` Cristian Marussi

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).