This is only relevant to implementations with multiple clusters, where clusters
have separate clock lines but all CPUs within a cluster share it.
Consider a dual cluster platform with 2 cores per cluster. During suspend we
start offlining CPUs from 1 to 3. When CPU2 is remove, policy->kobj would be
moved to CPU3 and when CPU3 goes down we wouldn't free policy or its kobj.
Now on resume, we will get CPU2 before CPU3 and will call __cpufreq_add_dev().
We will recover the old policy and update policy->cpu from 3 to 2 from
update_policy_cpu().
But the kobj is still tied to CPU3 and wasn't moved to CPU2. We wouldn't create
a link for CPU2, but would try that while bringing CPU3 online. Which will
report errors as CPU3 already has kobj assigned to it.
This bug got introduced with commit 42f921a, which overlooked this scenario.
To fix this, lets move kobj to the new policy->cpu while bringing first CPU of a
cluster back. We already have update_policy_cpu() routine which can be updated
with this change. That would get rid of the cpufreq_nominate_new_policy_cpu() as
update_policy_cpu() is also called on CPU removal.
To achieve that we add another parameter to update_policy_cpu() as cpu_dev is
present with both the callers.
Fixes: ("42f921a cpufreq: remove sysfs files for CPUs which failed to come back after resume")
Cc: Stable <stable(a)vger.kernel.org> # 3.13+
Reported-by: Bu Yitian <ybu(a)qti.qualcomm.com>
Reported-by: Saravana Kannan <skannan(a)codeaurora.org>
Signed-off-by: Viresh Kumar <viresh.kumar(a)linaro.org>
---
V1->V2: Move kobject_move() call to update_policy_cpu(), which makes
cpufreq_nominate_new_policy_cpu() almost empty. So we remove it completely.
@Yitian: Sorry, but you need to test this again as there were enough
modifications in V2.
drivers/cpufreq/cpufreq.c | 73 +++++++++++++++++++++++------------------------
1 file changed, 36 insertions(+), 37 deletions(-)
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 62259d2..c81d9ec6 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -1076,10 +1076,20 @@ static void cpufreq_policy_free(struct cpufreq_policy *policy)
kfree(policy);
}
-static void update_policy_cpu(struct cpufreq_policy *policy, unsigned int cpu)
+static int update_policy_cpu(struct cpufreq_policy *policy, unsigned int cpu,
+ struct device *cpu_dev)
{
+ int ret;
+
if (WARN_ON(cpu == policy->cpu))
- return;
+ return 0;
+
+ /* Move kobject to the new policy->cpu */
+ ret = kobject_move(&policy->kobj, &cpu_dev->kobj);
+ if (ret) {
+ pr_err("%s: Failed to move kobj: %d\n", __func__, ret);
+ return ret;
+ }
down_write(&policy->rwsem);
@@ -1090,6 +1100,8 @@ static void update_policy_cpu(struct cpufreq_policy *policy, unsigned int cpu)
blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
CPUFREQ_UPDATE_POLICY_CPU, policy);
+
+ return 0;
}
static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif)
@@ -1154,7 +1166,7 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif)
* by invoking update_policy_cpu().
*/
if (recover_policy && cpu != policy->cpu)
- update_policy_cpu(policy, cpu);
+ WARN_ON(update_policy_cpu(policy, cpu, dev));
else
policy->cpu = cpu;
@@ -1307,38 +1319,11 @@ static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif)
return __cpufreq_add_dev(dev, sif);
}
-static int cpufreq_nominate_new_policy_cpu(struct cpufreq_policy *policy,
- unsigned int old_cpu)
-{
- struct device *cpu_dev;
- int ret;
-
- /* first sibling now owns the new sysfs dir */
- cpu_dev = get_cpu_device(cpumask_any_but(policy->cpus, old_cpu));
-
- sysfs_remove_link(&cpu_dev->kobj, "cpufreq");
- ret = kobject_move(&policy->kobj, &cpu_dev->kobj);
- if (ret) {
- pr_err("%s: Failed to move kobj: %d\n", __func__, ret);
-
- down_write(&policy->rwsem);
- cpumask_set_cpu(old_cpu, policy->cpus);
- up_write(&policy->rwsem);
-
- ret = sysfs_create_link(&cpu_dev->kobj, &policy->kobj,
- "cpufreq");
-
- return -EINVAL;
- }
-
- return cpu_dev->id;
-}
-
static int __cpufreq_remove_dev_prepare(struct device *dev,
struct subsys_interface *sif)
{
unsigned int cpu = dev->id, cpus;
- int new_cpu, ret;
+ int ret;
unsigned long flags;
struct cpufreq_policy *policy;
@@ -1378,14 +1363,28 @@ static int __cpufreq_remove_dev_prepare(struct device *dev,
if (cpu != policy->cpu) {
sysfs_remove_link(&dev->kobj, "cpufreq");
} else if (cpus > 1) {
- new_cpu = cpufreq_nominate_new_policy_cpu(policy, cpu);
- if (new_cpu >= 0) {
- update_policy_cpu(policy, new_cpu);
+ /* Nominate new CPU */
+ int new_cpu = cpumask_any_but(policy->cpus, cpu);
+ struct device *cpu_dev = get_cpu_device(new_cpu);
- if (!cpufreq_suspended)
- pr_debug("%s: policy Kobject moved to cpu: %d from: %d\n",
- __func__, new_cpu, cpu);
+ sysfs_remove_link(&cpu_dev->kobj, "cpufreq");
+ ret = update_policy_cpu(policy, new_cpu, cpu_dev);
+ if (ret) {
+ /*
+ * To supress compilation warning about return value of
+ * sysfs_create_link().
+ */
+ int temp;
+
+ /* Create link again if we failed. */
+ temp = sysfs_create_link(&cpu_dev->kobj, &policy->kobj,
+ "cpufreq");
+ return ret;
}
+
+ if (!cpufreq_suspended)
+ pr_debug("%s: policy Kobject moved to cpu: %d from: %d\n",
+ __func__, new_cpu, cpu);
} else if (cpufreq_driver->stop_cpu && cpufreq_driver->setpolicy) {
cpufreq_driver->stop_cpu(policy);
}
--
2.0.0.rc2
At present it is not possible to boot with the ttyNMI0 console treating
character input normally. To use the console requires that kdb be
entered and the nmi_console command be used to enable the console (or if
only kgdb is present then gdb must directly manipulate the value of
kgdb_nmi_tty_enabled).
Introducing a module parameter makes the console much more usable.
Signed-off-by: Daniel Thompson <daniel.thompson(a)linaro.org>
Cc: Greg Kroah-Hartman <gregkh(a)linuxfoundation.org>
Cc: Jiri Slaby <jslaby(a)suse.cz>
Cc: linux-serial(a)vger.kernel.org
---
drivers/tty/serial/kgdb_nmi.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/drivers/tty/serial/kgdb_nmi.c b/drivers/tty/serial/kgdb_nmi.c
index cfadf29..9361d69 100644
--- a/drivers/tty/serial/kgdb_nmi.c
+++ b/drivers/tty/serial/kgdb_nmi.c
@@ -43,6 +43,11 @@ module_param_named(magic, kgdb_nmi_magic, charp, 0600);
MODULE_PARM_DESC(magic, "magic sequence to enter NMI debugger (default $3#33)");
static bool kgdb_nmi_tty_enabled;
+module_param_named(tty, kgdb_nmi_tty_enabled, bool, 0600);
+MODULE_PARM_DESC(tty, "if set to false (default), characters received from "
+ "the UART will be passed exclusively to the knock "
+ "detector; when set to true characters will be passed "
+ "both to the knock detector and to the TTY layer");
static int kgdb_nmi_console_setup(struct console *co, char *options)
{
--
1.9.3
As part of the migration a couple of uart definitions have been copied
from of the platform specific header files.
Note that, in order to keep oldconfig working nicely we must defer the
removal of arch/arm/mach-ks8695/include/mach/debug-macro.S until
DEBUG_LL_UART_NONE has been removed.
Signed-off-by: Daniel Thompson <daniel.thompson(a)linaro.org>
Cc: Russell King <linux(a)arm.linux.org.uk>
Cc: Greg Ungerer <gerg(a)uclinux.org>
Cc: Arnd Bergmann <arnd.bergmann(a)linaro.org>
---
Notes:
This is a contribution towards the removal of DEBUG_LL_UART_NONE, see
http://thread.gmane.org/gmane.linux.kernel/1712068/focus=1746065 for
details.
arch/arm/Kconfig.debug | 8 ++++++++
arch/arm/include/debug/ks8695.S | 40 ++++++++++++++++++++++++++++++++++++++++
2 files changed, 48 insertions(+)
create mode 100644 arch/arm/include/debug/ks8695.S
diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug
index 8f90595..6f9664a 100644
--- a/arch/arm/Kconfig.debug
+++ b/arch/arm/Kconfig.debug
@@ -340,6 +340,13 @@ choice
Say Y here if you want the debug print routines to direct
their output to UART1 serial port on KEYSTONE2 devices.
+ config DEBUG_KS8695_UART
+ bool "KS8695 Debug UART"
+ depends on ARCH_KS8695
+ help
+ Say Y here if you want kernel low-level debugging support
+ on KS8695.
+
config DEBUG_MMP_UART2
bool "Kernel low-level debugging message via MMP UART2"
depends on ARCH_MMP
@@ -1006,6 +1013,7 @@ config DEBUG_LL_INCLUDE
DEBUG_IMX6Q_UART || \
DEBUG_IMX6SL_UART || \
DEBUG_IMX6SX_UART
+ default "debug/ks8695.S" if DEBUG_KS8695_UART
default "debug/msm.S" if DEBUG_MSM_UART || DEBUG_QCOM_UARTDM
default "debug/omap2plus.S" if DEBUG_OMAP2PLUS_UART
default "debug/s3c24xx.S" if DEBUG_S3C24XX_UART
diff --git a/arch/arm/include/debug/ks8695.S b/arch/arm/include/debug/ks8695.S
new file mode 100644
index 0000000..961da1f
--- /dev/null
+++ b/arch/arm/include/debug/ks8695.S
@@ -0,0 +1,40 @@
+/*
+ * arch/arm/include/debug/ks8695.S
+ *
+ * Copyright (C) 2006 Ben Dooks <ben(a)simtec.co.uk>
+ * Copyright (C) 2006 Simtec Electronics
+ *
+ * KS8695 - Debug macros
+ *
+ * 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.
+ */
+
+#define KS8695_UART_PA 0x03ffe000
+#define KS8695_UART_VA 0xf00fe000
+#define KS8695_URTH (0x04)
+#define KS8695_URLS (0x14)
+#define URLS_URTE (1 << 6)
+#define URLS_URTHRE (1 << 5)
+
+ .macro addruart, rp, rv, tmp
+ ldr \rp, =KS8695_UART_PA @ physical base address
+ ldr \rv, =KS8695_UART_VA @ virtual base address
+ .endm
+
+ .macro senduart, rd, rx
+ str \rd, [\rx, #KS8695_URTH] @ Write to Transmit Holding Register
+ .endm
+
+ .macro busyuart, rd, rx
+1001: ldr \rd, [\rx, #KS8695_URLS] @ Read Line Status Register
+ tst \rd, #URLS_URTE @ Holding & Shift registers empty?
+ beq 1001b
+ .endm
+
+ .macro waituart, rd, rx
+1001: ldr \rd, [\rx, #KS8695_URLS] @ Read Line Status Register
+ tst \rd, #URLS_URTHRE @ Holding Register empty?
+ beq 1001b
+ .endm
--
1.9.3