From: Domenico Andreoli <domenico.andreoli@linux.com>
To: linux-arch@vger.kernel.org
Cc: linux-arm-kernel@lists.infradead.org,
linux-mips@lvger.kernel.org,
Russell King <linux@arm.linux.org.uk>,
Arnd Bergmann <arnd@arndb.de>, Olof Johansson <olof@lixom.net>,
Ralf Baechle <ralf@linux-mips.org>,
Catalin Marinas <catalin.marinas@arm.com>,
Will Deacon <will.deacon@arm.com>,
Domenico Andreoli <domenico.andreoli@linux.com>
Subject: [PATCH 01/11] machine-reset: platform generic handling
Date: Thu, 31 Oct 2013 07:27:09 +0100 [thread overview]
Message-ID: <20131031062958.274180101@linux.com> (raw)
In-Reply-To: 20131031062708.520968323@linux.com
[-- Attachment #1: machine-reset-handling.patch --]
[-- Type: text/plain, Size: 8834 bytes --]
From: Domenico Andreoli <domenico.andreoli@linux.com>
Code is not commented but it's really simple. The bulk is in
set_machine_reset(), the static data is hidden in get_descr(). The rest
is just a straightforward consequence with the intent to keep it simple.
Cc: Russell King <linux@arm.linux.org.uk>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Olof Johansson <olof@lixom.net>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: linux-arch@vger.kernel.org
Cc: linux-arm-kernel@lists.infradead.org
Cc: linux-mips@lvger.kernel.org
Signed-off-by: Domenico Andreoli <domenico.andreoli@linux.com>
---
include/linux/machine_reset.h | 79 +++++++++++++++++++++++++
kernel/Makefile | 1 +
kernel/machine_reset.c | 131 ++++++++++++++++++++++++++++++++++++++++++
kernel/power/Kconfig | 4 +
kernel/reboot.c | 3 +
5 files changed, 218 insertions(+)
Index: b/include/linux/machine_reset.h
===================================================================
--- /dev/null
+++ b/include/linux/machine_reset.h
@@ -0,0 +1,79 @@
+/*
+ * Machine reset hooks management
+ *
+ * Copyright (C) 2013 Domenico Andreoli <domenico.andreoli@linux.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/reboot.h>
+
+enum reset_func {
+ RESET_RESTART = 0,
+ RESET_HALT,
+ RESET_POWER_OFF_PREPARE,
+ RESET_POWER_OFF,
+ RESET_CRASH_POWER_OFF,
+ RESET_NR_FUNCS,
+};
+
+struct reset_hook {
+ union {
+ void (*restart)(void *dev, enum reboot_mode, const char *cmd);
+ void (*halt)(void *dev);
+ void (*power_off_prepare)(void *dev);
+ void (*power_off)(void *dev);
+ void (*crash_power_off)(void *dev);
+ void (*handler)(void *dev);
+ };
+ void (*release)(void *dev);
+};
+
+static inline
+void reset_hook_init(struct reset_hook *hook)
+{
+ hook->handler = NULL;
+ hook->release = NULL;
+}
+
+#ifdef CONFIG_MACHINE_RESET
+
+void set_machine_reset(enum reset_func, const struct reset_hook *, void *dev);
+void unset_machine_reset(enum reset_func, const struct reset_hook *);
+int isset_machine_reset(enum reset_func, void *dev);
+
+void default_restart(enum reboot_mode, const char *cmd);
+void default_halt(void);
+void default_power_off_prepare(void);
+void default_power_off(void);
+void default_crash_power_off(void);
+
+#else /* CONFIG_MACHINE_RESET */
+
+static inline
+void set_machine_reset(enum reset_func func,
+ const struct reset_hook *hook, void *dev)
+{
+ if (hook->release)
+ hook->release(dev);
+}
+
+static inline void unset_machine_reset(enum reset_func _f,
+ const struct reset_hook *_h) {}
+static inline int isset_machine_reset(enum reset_func _f, void *_d) { return 0; }
+
+static inline void default_restart(enum reboot_mode _m, const char *_c) {}
+static inline void default_halt(void) {}
+static inline void default_power_off_prepare(void) {}
+static inline void default_power_off(void) {}
+static inline void default_crash_power_off(void) {}
+
+#endif /* CONFIG_MACHINE_RESET */
Index: b/kernel/Makefile
===================================================================
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -111,6 +111,7 @@ obj-$(CONFIG_PADATA) += padata.o
obj-$(CONFIG_CRASH_DUMP) += crash_dump.o
obj-$(CONFIG_JUMP_LABEL) += jump_label.o
obj-$(CONFIG_CONTEXT_TRACKING) += context_tracking.o
+obj-$(CONFIG_MACHINE_RESET) += machine_reset.o
$(obj)/configs.o: $(obj)/config_data.h
Index: b/kernel/machine_reset.c
===================================================================
--- /dev/null
+++ b/kernel/machine_reset.c
@@ -0,0 +1,131 @@
+/*
+ * Machine reset hooks management
+ *
+ * Copyright (C) 2013 Domenico Andreoli <domenico.andreoli@linux.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/export.h>
+#include <linux/spinlock.h>
+#include <linux/reboot.h>
+#include <linux/machine_reset.h>
+
+struct reset_descr {
+ struct reset_hook hook;
+ void *dev;
+};
+static DEFINE_SPINLOCK(descr_lock);
+
+static struct reset_descr *get_descr(enum reset_func func)
+{
+ static struct reset_descr descr[RESET_NR_FUNCS];
+
+ BUG_ON(func >= RESET_NR_FUNCS);
+ spin_lock(&descr_lock);
+ return &descr[func];
+}
+
+static void put_descr(struct reset_descr *descr)
+{
+ spin_unlock(&descr_lock);
+}
+
+#define RESET_FUNC(_func, _member, _args...) \
+{ \
+ struct reset_descr *descr = get_descr(_func); \
+ typeof(descr->hook._member) member = descr->hook._member; \
+ if (member) { \
+ pr_debug("machine_reset: %s (%pf)\n", #_func, member); \
+ member(descr->dev , ##_args); \
+ } \
+ put_descr(descr); \
+ pr_emerg("machine_reset: %s: FAILED\n", #_func); \
+ while (1); \
+}
+
+void default_restart(enum reboot_mode reboot_mode, const char *cmd)
+{
+ RESET_FUNC(RESET_RESTART, restart, reboot_mode, cmd);
+}
+
+void default_halt(void)
+{
+ RESET_FUNC(RESET_HALT, halt);
+}
+
+void default_power_off_prepare(void)
+{
+ RESET_FUNC(RESET_POWER_OFF_PREPARE, power_off_prepare);
+}
+
+void default_power_off(void)
+{
+ RESET_FUNC(RESET_POWER_OFF, power_off);
+}
+
+void default_crash_power_off(void)
+{
+ RESET_FUNC(RESET_CRASH_POWER_OFF, crash_power_off);
+}
+
+void set_machine_reset(enum reset_func func,
+ const struct reset_hook *hook, void *new_dev)
+{
+ struct reset_descr *descr;
+ void (*new_handler)(void *) = hook ? hook->handler : NULL;
+ void (*new_release)(void *) = hook ? hook->release : NULL;
+ void (*old_release)(void *) = NULL;
+ void *old_dev;
+
+ descr = get_descr(func);
+ old_release = descr->hook.release;
+ old_dev = descr->dev;
+ reset_hook_init(&descr->hook);
+ descr->hook.handler = new_handler;
+ descr->hook.release = new_release;
+ descr->dev = new_dev;
+ put_descr(descr);
+
+ if (old_release)
+ old_release(old_dev);
+}
+EXPORT_SYMBOL_GPL(set_machine_reset);
+
+void unset_machine_reset(enum reset_func func, const struct reset_hook *hook)
+{
+ struct reset_descr *descr;
+ void (*old_release)(void *) = NULL;
+ void *old_dev;
+
+ BUG_ON(!hook || !hook->handler);
+
+ descr = get_descr(func);
+ if (descr->hook.handler == hook->handler) {
+ old_release = descr->hook.release;
+ old_dev = descr->dev;
+ reset_hook_init(&descr->hook);
+ }
+ put_descr(descr);
+
+ if (old_release)
+ old_release(old_dev);
+}
+EXPORT_SYMBOL_GPL(unset_machine_reset);
+
+int isset_machine_reset(enum reset_func func, void *dev)
+{
+ struct reset_descr *descr = get_descr(func);
+ int ret = descr->hook.handler && (!dev || descr->dev == dev);
+ put_descr(descr);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(isset_machine_reset);
Index: b/kernel/power/Kconfig
===================================================================
--- a/kernel/power/Kconfig
+++ b/kernel/power/Kconfig
@@ -293,3 +293,7 @@ config PM_GENERIC_DOMAINS_RUNTIME
config CPU_PM
bool
depends on SUSPEND || CPU_IDLE
+
+config MACHINE_RESET
+ bool
+ default n
Index: b/kernel/reboot.c
===================================================================
--- a/kernel/reboot.c
+++ b/kernel/reboot.c
@@ -12,6 +12,7 @@
#include <linux/kmod.h>
#include <linux/kmsg_dump.h>
#include <linux/reboot.h>
+#include <linux/machine_reset.h>
#include <linux/suspend.h>
#include <linux/syscalls.h>
#include <linux/syscore_ops.h>
@@ -178,6 +179,8 @@ void kernel_power_off(void)
kernel_shutdown_prepare(SYSTEM_POWER_OFF);
if (pm_power_off_prepare)
pm_power_off_prepare();
+ else
+ default_power_off_prepare();
migrate_to_reboot_cpu();
syscore_shutdown();
pr_emerg("Power down\n");
next prev parent reply other threads:[~2013-10-31 6:30 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-10-31 6:27 [PATCH 00/11] RFC: Common machine reset handling Domenico Andreoli
2013-10-31 6:27 ` Domenico Andreoli [this message]
2013-10-31 6:27 ` [PATCH 02/11] ARM: use the common " Domenico Andreoli
2013-10-31 6:27 ` [PATCH 03/11] ARM64: " Domenico Andreoli
2013-10-31 6:27 ` [PATCH 04/11] MIPS: " Domenico Andreoli
2013-11-01 5:11 ` Vineet Gupta
2013-11-01 5:26 ` Domenico Andreoli
2013-10-31 6:27 ` [PATCH 05/11] ARM: vexpress: consolidate machine reset func Domenico Andreoli
2013-10-31 6:27 ` [PATCH 06/11] ARM: vexpress: use the common machine reset handling Domenico Andreoli
2013-10-31 6:27 ` [PATCH 07/11] ARM: bcm2835: " Domenico Andreoli
2013-10-31 6:27 ` [PATCH 08/11] ARM: u300: " Domenico Andreoli
2013-10-31 14:40 ` Linus Walleij
2013-10-31 15:19 ` Domenico Andreoli
2013-10-31 6:27 ` [PATCH 09/11] ARM: tps65910: " Domenico Andreoli
2013-10-31 6:27 ` [PATCH 10/11] max8907: " Domenico Andreoli
2013-10-31 6:27 ` [PATCH 11/11] ARM: sp805: " Domenico Andreoli
2013-10-31 10:21 ` [PATCH 00/11] RFC: Common " Russell King - ARM Linux
2013-10-31 21:49 ` Stephen Warren
2013-11-01 5:16 ` Domenico Andreoli
2013-11-01 15:58 ` Stephen Warren
2013-11-01 16:12 ` Russell King - ARM Linux
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=20131031062958.274180101@linux.com \
--to=domenico.andreoli@linux.com \
--cc=arnd@arndb.de \
--cc=catalin.marinas@arm.com \
--cc=linux-arch@vger.kernel.org \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-mips@lvger.kernel.org \
--cc=linux@arm.linux.org.uk \
--cc=olof@lixom.net \
--cc=ralf@linux-mips.org \
--cc=will.deacon@arm.com \
/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).