Merge remote-tracking branch 'origin/dev/linux-4.4.180' into rel-28
Conflicts:
arch/arm64/kernel/traps.c
drivers/dma/tegra20-apb-dma.c
drivers/gpu/drm/vmwgfx/vmwgfx_fb.c
drivers/hwtracing/coresight/coresight-etm4x.c
drivers/i2c/busses/i2c-tegra.c
drivers/usb/gadget/configfs.c
include/linux/cpu.h
kernel/cpu.c
kernel/sched/fair.c
sound/core/compress_offload.c
Bug 200554552
Change-Id: I6fd681159f3dd91bf1a4e44e8aedf0d556a4a903
diff --git a/kernel/cpu.c b/kernel/cpu.c
index bdf20aa..45a349c 100644
--- a/kernel/cpu.c
+++ b/kernel/cpu.c
@@ -8,6 +8,7 @@
#include <linux/init.h>
#include <linux/notifier.h>
#include <linux/sched.h>
+#include <linux/sched/smt.h>
#include <linux/unistd.h>
#include <linux/cpu.h>
#include <linux/oom.h>
@@ -185,15 +186,28 @@
}
EXPORT_SYMBOL_GPL(cpu_hotplug_disable);
+static void __cpu_hotplug_enable(void)
+{
+ if (WARN_ONCE(!cpu_hotplug_disabled, "Unbalanced cpu hotplug enable\n"))
+ return;
+ cpu_hotplug_disabled--;
+}
+
void cpu_hotplug_enable(void)
{
cpu_maps_update_begin();
- WARN_ON(--cpu_hotplug_disabled < 0);
+ __cpu_hotplug_enable();
cpu_maps_update_done();
}
EXPORT_SYMBOL_GPL(cpu_hotplug_enable);
#endif /* CONFIG_HOTPLUG_CPU */
+/*
+ * Architectures that need SMT-specific errata handling during SMT hotplug
+ * should override this.
+ */
+void __weak arch_smt_update(void) { }
+
/* Need to know about CPUs going up/down? */
int register_cpu_notifier(struct notifier_block *nb)
{
@@ -428,9 +442,9 @@
out_release:
cpu_hotplug_done();
- trace_sched_cpu_hotplug(cpu, err, 0);
if (!err)
cpu_notify_nofail(CPU_POST_DEAD | mod, hcpu);
+ arch_smt_update();
return err;
}
@@ -537,8 +551,7 @@
__cpu_notify(CPU_UP_CANCELED | mod, hcpu, nr_calls, NULL);
out:
cpu_hotplug_done();
- trace_sched_cpu_hotplug(cpu, ret, 1);
-
+ arch_smt_update();
return ret;
}
@@ -637,7 +650,7 @@
/* Allow everyone to use the CPU hotplug again */
cpu_maps_update_begin();
- WARN_ON(--cpu_hotplug_disabled < 0);
+ __cpu_hotplug_enable();
if (cpumask_empty(frozen_cpus))
goto out;
@@ -843,18 +856,31 @@
void idle_notifier_register(struct notifier_block *n)
{
- atomic_notifier_chain_register(&idle_notifier, n);
+ atomic_notifier_chain_register(&idle_notifier, n);
}
EXPORT_SYMBOL_GPL(idle_notifier_register);
void idle_notifier_unregister(struct notifier_block *n)
{
- atomic_notifier_chain_unregister(&idle_notifier, n);
+ atomic_notifier_chain_unregister(&idle_notifier, n);
}
EXPORT_SYMBOL_GPL(idle_notifier_unregister);
void idle_notifier_call_chain(unsigned long val)
{
- atomic_notifier_call_chain(&idle_notifier, val, NULL);
+ atomic_notifier_call_chain(&idle_notifier, val, NULL);
}
EXPORT_SYMBOL_GPL(idle_notifier_call_chain);
+
+enum cpu_mitigations cpu_mitigations = CPU_MITIGATIONS_AUTO;
+
+static int __init mitigations_parse_cmdline(char *arg)
+{
+ if (!strcmp(arg, "off"))
+ cpu_mitigations = CPU_MITIGATIONS_OFF;
+ else if (!strcmp(arg, "auto"))
+ cpu_mitigations = CPU_MITIGATIONS_AUTO;
+
+ return 0;
+}
+early_param("mitigations", mitigations_parse_cmdline);