sysvinit: disable all cpu cores but cpu0 on halt/reboot
This is a user-space workaround for the reboot/poweroff problems we are having in the ccimx6sbc. Seems that they are not reproducible when only one core is enabled, so the workaround is to disable the rest of the cores for rebooting/halting. https://jira.digi.com/browse/DEL-2133 https://jira.digi.com/browse/DEL-2148 Signed-off-by: Javier Viguera <javier.viguera@digi.com> (cherry picked from commit a9e36a74bb20ab38f220116ba2742dca3d80c293)
This commit is contained in:
parent
ef230a3616
commit
0b07af3bef
|
|
@ -0,0 +1,215 @@
|
|||
From: Javier Viguera <javier.viguera@digi.com>
|
||||
Date: Wed, 29 Oct 2014 13:06:15 +0100
|
||||
Subject: [PATCH] sysvinit: disable all cpus but cpu0 for halt/reboot
|
||||
|
||||
Signed-off-by: Javier Viguera <javier.viguera@digi.com>
|
||||
---
|
||||
src/Makefile | 6 +++---
|
||||
src/halt.c | 20 +++++++++++-------
|
||||
src/init.c | 5 +++++
|
||||
src/shutdown.c | 3 +++
|
||||
src/sysfs_cpu.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
src/sysfs_cpu.h | 24 ++++++++++++++++++++++
|
||||
6 files changed, 111 insertions(+), 10 deletions(-)
|
||||
create mode 100644 src/sysfs_cpu.c
|
||||
create mode 100644 src/sysfs_cpu.h
|
||||
|
||||
diff --git a/src/Makefile b/src/Makefile
|
||||
index a6f9f4052926..d5bd705955c5 100644
|
||||
--- a/src/Makefile
|
||||
+++ b/src/Makefile
|
||||
@@ -101,9 +101,9 @@ all: $(BIN) $(SBIN) $(USRBIN)
|
||||
# $(CC) $(CFLAGS) $(CPPFLAGS) -c $^ -o $@
|
||||
|
||||
init: LDLIBS += $(INITLIBS) $(STATIC)
|
||||
-init: init.o init_utmp.o
|
||||
+init: init.o init_utmp.o sysfs_cpu.o
|
||||
|
||||
-halt: halt.o ifdown.o hddown.o utmp.o
|
||||
+halt: halt.o ifdown.o hddown.o utmp.o sysfs_cpu.o
|
||||
|
||||
last: last.o
|
||||
|
||||
@@ -120,7 +120,7 @@ sulogin: sulogin.o
|
||||
|
||||
wall: dowall.o wall.o
|
||||
|
||||
-shutdown: dowall.o shutdown.o utmp.o
|
||||
+shutdown: dowall.o shutdown.o utmp.o sysfs_cpu.o
|
||||
|
||||
bootlogd: LDLIBS += -lutil
|
||||
bootlogd: bootlogd.o
|
||||
diff --git a/src/halt.c b/src/halt.c
|
||||
index 499e9734056c..7ded393caf46 100644
|
||||
--- a/src/halt.c
|
||||
+++ b/src/halt.c
|
||||
@@ -57,6 +57,7 @@
|
||||
#include <stdio.h>
|
||||
#include <getopt.h>
|
||||
#include "reboot.h"
|
||||
+#include "sysfs_cpu.h"
|
||||
|
||||
char *Version = "@(#)halt 2.86 31-Jul-2004 miquels@cistron.nl";
|
||||
char *progname;
|
||||
@@ -241,13 +242,18 @@ int main(int argc, char **argv)
|
||||
|
||||
(void)chdir("/");
|
||||
|
||||
- if (!do_hard && !do_nothing) {
|
||||
- /*
|
||||
- * See if we are in runlevel 0 or 6.
|
||||
- */
|
||||
- c = get_runlevel();
|
||||
- if (c != '0' && c != '6')
|
||||
- do_shutdown(do_reboot ? "-r" : "-h", tm);
|
||||
+ if (!do_nothing) {
|
||||
+ if (!do_hard) {
|
||||
+ /*
|
||||
+ * See if we are in runlevel 0 or 6.
|
||||
+ */
|
||||
+ c = get_runlevel();
|
||||
+ if (c != '0' && c != '6')
|
||||
+ do_shutdown(do_reboot ? "-r" : "-h", tm);
|
||||
+ } else {
|
||||
+ /* Disable cores for halt/reboot */
|
||||
+ sysfs_disable_cpu_all();
|
||||
+ }
|
||||
}
|
||||
|
||||
/*
|
||||
diff --git a/src/init.c b/src/init.c
|
||||
index 27532aded622..84cb03523677 100644
|
||||
--- a/src/init.c
|
||||
+++ b/src/init.c
|
||||
@@ -78,6 +78,7 @@
|
||||
#include "paths.h"
|
||||
#include "reboot.h"
|
||||
#include "set.h"
|
||||
+#include "sysfs_cpu.h"
|
||||
|
||||
#ifndef SIGPWR
|
||||
# define SIGPWR SIGUSR2
|
||||
@@ -2731,6 +2732,10 @@ int telinit(char *progname, int argc, char **argv)
|
||||
request.cmd = INIT_CMD_RUNLVL;
|
||||
request.runlevel = env ? 0 : argv[optind][0];
|
||||
request.sleeptime = sltime;
|
||||
+
|
||||
+ /* Disable cores for halt/reboot */
|
||||
+ if (request.runlevel == '0' || request.runlevel == '6')
|
||||
+ sysfs_disable_cpu_all();
|
||||
}
|
||||
|
||||
/* Change to the root directory. */
|
||||
diff --git a/src/shutdown.c b/src/shutdown.c
|
||||
index 7e997da84e3a..f3b5aae2f07a 100644
|
||||
--- a/src/shutdown.c
|
||||
+++ b/src/shutdown.c
|
||||
@@ -326,6 +326,9 @@ void fastdown()
|
||||
}
|
||||
#endif
|
||||
|
||||
+ /* Disable cores for halt/reboot */
|
||||
+ sysfs_disable_cpu_all();
|
||||
+
|
||||
/* First close all files. */
|
||||
for(i = 0; i < 3; i++)
|
||||
if (!isatty(i)) {
|
||||
diff --git a/src/sysfs_cpu.c b/src/sysfs_cpu.c
|
||||
new file mode 100644
|
||||
index 000000000000..fe14ff71c382
|
||||
--- /dev/null
|
||||
+++ b/src/sysfs_cpu.c
|
||||
@@ -0,0 +1,63 @@
|
||||
+/*
|
||||
+ * sysfs_cpu.c
|
||||
+ *
|
||||
+ * Copyright (C) 2014 by Digi International Inc.
|
||||
+ * All rights reserved.
|
||||
+ *
|
||||
+ * This program is free software; you can redistribute it and/or modify it
|
||||
+ * under the terms of the GNU General Public License version 2 as published by
|
||||
+ * the Free Software Foundation.
|
||||
+ *
|
||||
+ * Description: CPU SYSFS API
|
||||
+ *
|
||||
+ */
|
||||
+
|
||||
+#include <fcntl.h>
|
||||
+#include <stdio.h>
|
||||
+#include <sys/sysinfo.h>
|
||||
+#include <unistd.h>
|
||||
+
|
||||
+#include "sysfs_cpu.h"
|
||||
+
|
||||
+static int sysfs_cpu_set_value(int cpu, int value)
|
||||
+{
|
||||
+ int fd = -1, len;
|
||||
+ char buf[64];
|
||||
+
|
||||
+ if (cpu < 0)
|
||||
+ return 0;
|
||||
+
|
||||
+ snprintf(buf, sizeof(buf), CPUS_SYSDIR "/cpu%d/online", cpu);
|
||||
+ fd = open(buf, O_WRONLY);
|
||||
+ if (fd < 0) {
|
||||
+ fprintf(stderr, "unable to open %s.\r\n", buf);
|
||||
+ return fd;
|
||||
+ }
|
||||
+ snprintf(buf, sizeof(buf), "%s", value ? "1" : "0");
|
||||
+ len = write(fd, buf, 1);
|
||||
+ close(fd);
|
||||
+
|
||||
+ return (len < 1) ? -1 : 0;
|
||||
+}
|
||||
+
|
||||
+int sysfs_disable_cpu(int cpu)
|
||||
+{
|
||||
+ return sysfs_cpu_set_value(cpu, 0);
|
||||
+}
|
||||
+
|
||||
+/* Disable all CPUS but 'cpu0' */
|
||||
+int sysfs_disable_cpu_all(void)
|
||||
+{
|
||||
+ int i, ncores;
|
||||
+
|
||||
+ ncores = get_nprocs_conf();
|
||||
+ for (i = 1; i < ncores; i++)
|
||||
+ sysfs_disable_cpu(i);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+int sysfs_enable_cpu(int cpu)
|
||||
+{
|
||||
+ return sysfs_cpu_set_value(cpu, 1);
|
||||
+}
|
||||
diff --git a/src/sysfs_cpu.h b/src/sysfs_cpu.h
|
||||
new file mode 100644
|
||||
index 000000000000..7728d52fe4d9
|
||||
--- /dev/null
|
||||
+++ b/src/sysfs_cpu.h
|
||||
@@ -0,0 +1,24 @@
|
||||
+/*
|
||||
+ * sysfs_cpu.h
|
||||
+ *
|
||||
+ * Copyright (C) 2014 by Digi International Inc.
|
||||
+ * All rights reserved.
|
||||
+ *
|
||||
+ * This program is free software; you can redistribute it and/or modify it
|
||||
+ * under the terms of the GNU General Public License version 2 as published by
|
||||
+ * the Free Software Foundation.
|
||||
+ *
|
||||
+ * Description: CPU SYSFS API
|
||||
+ *
|
||||
+ */
|
||||
+
|
||||
+#ifndef SYSFS_CPU_H
|
||||
+#define SYSFS_CPU_H
|
||||
+
|
||||
+#define CPUS_SYSDIR "/sys/devices/system/cpu"
|
||||
+
|
||||
+int sysfs_disable_cpu(int cpu);
|
||||
+int sysfs_disable_cpu_all(void);
|
||||
+int sysfs_enable_cpu(int cpu);
|
||||
+
|
||||
+#endif /* SYSFS_CPU_H */
|
||||
|
|
@ -1,7 +1,13 @@
|
|||
# Copyright (C) 2013-2014 Digi International.
|
||||
|
||||
FILESEXTRAPATHS_prepend := "${THISDIR}/${BP}:"
|
||||
|
||||
SRC_URI_append_ccimx6 = " file://0001-sysvinit-disable-all-cpus-but-cpu0-for-halt-reboot.patch"
|
||||
|
||||
do_install_append() {
|
||||
# Remove 'bootlogd' bootscript symlinks
|
||||
update-rc.d -f -r ${D} stop-bootlogd remove
|
||||
update-rc.d -f -r ${D} bootlogd remove
|
||||
}
|
||||
|
||||
PACKAGE_ARCH = "${MACHINE_ARCH}"
|
||||
|
|
|
|||
Loading…
Reference in New Issue