aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Weinberger <richard@nod.at>2016-08-18 08:57:17 -0400
committerThomas Gleixner <tglx@linutronix.de>2016-09-06 12:30:20 -0400
commite6d4989a9ad1ccc343f29578a461612ed80fc6c5 (patch)
tree97b092d2f0505c61d15cf4f2025fddb0c5f6c614
parent017c59c042d01fc84cae7a8ea475861e702c77ab (diff)
relayfs: Convert to hotplug state machine
Install the callbacks via the state machine. They are installed at run time but relay_prepare_cpu() does not need to be invoked by the boot CPU because relay_open() was not yet invoked and there are no pools that need to be created. Signed-off-by: Richard Weinberger <richard@nod.at> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> Reviewed-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> Cc: Peter Zijlstra <peterz@infradead.org> Cc: rt@linutronix.de Cc: Andrew Morton <akpm@linux-foundation.org> Link: http://lkml.kernel.org/r/20160818125731.27256-3-bigeasy@linutronix.de Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
-rw-r--r--include/linux/cpuhotplug.h1
-rw-r--r--include/linux/relay.h6
-rw-r--r--kernel/cpu.c6
-rw-r--r--kernel/relay.c58
4 files changed, 26 insertions, 45 deletions
diff --git a/include/linux/cpuhotplug.h b/include/linux/cpuhotplug.h
index 9e6d10786e29..4c79f40fcebc 100644
--- a/include/linux/cpuhotplug.h
+++ b/include/linux/cpuhotplug.h
@@ -21,6 +21,7 @@ enum cpuhp_state {
21 CPUHP_PROFILE_PREPARE, 21 CPUHP_PROFILE_PREPARE,
22 CPUHP_X2APIC_PREPARE, 22 CPUHP_X2APIC_PREPARE,
23 CPUHP_SMPCFD_PREPARE, 23 CPUHP_SMPCFD_PREPARE,
24 CPUHP_RELAY_PREPARE,
24 CPUHP_RCUTREE_PREP, 25 CPUHP_RCUTREE_PREP,
25 CPUHP_NOTIFY_PREPARE, 26 CPUHP_NOTIFY_PREPARE,
26 CPUHP_TIMERS_DEAD, 27 CPUHP_TIMERS_DEAD,
diff --git a/include/linux/relay.h b/include/linux/relay.h
index eb295e373b90..ecbb34a382b8 100644
--- a/include/linux/relay.h
+++ b/include/linux/relay.h
@@ -288,5 +288,11 @@ static inline void subbuf_start_reserve(struct rchan_buf *buf,
288 */ 288 */
289extern const struct file_operations relay_file_operations; 289extern const struct file_operations relay_file_operations;
290 290
291#ifdef CONFIG_RELAY
292int relay_prepare_cpu(unsigned int cpu);
293#else
294#define relay_prepare_cpu NULL
295#endif
296
291#endif /* _LINUX_RELAY_H */ 297#endif /* _LINUX_RELAY_H */
292 298
diff --git a/kernel/cpu.c b/kernel/cpu.c
index d14ae4438e8e..0c0d4b2ddd1c 100644
--- a/kernel/cpu.c
+++ b/kernel/cpu.c
@@ -23,6 +23,7 @@
23#include <linux/tick.h> 23#include <linux/tick.h>
24#include <linux/irq.h> 24#include <linux/irq.h>
25#include <linux/smpboot.h> 25#include <linux/smpboot.h>
26#include <linux/relay.h>
26 27
27#include <trace/events/power.h> 28#include <trace/events/power.h>
28#define CREATE_TRACE_POINTS 29#define CREATE_TRACE_POINTS
@@ -1272,6 +1273,11 @@ static struct cpuhp_step cpuhp_bp_states[] = {
1272 .startup.single = smpcfd_prepare_cpu, 1273 .startup.single = smpcfd_prepare_cpu,
1273 .teardown.single = smpcfd_dead_cpu, 1274 .teardown.single = smpcfd_dead_cpu,
1274 }, 1275 },
1276 [CPUHP_RELAY_PREPARE] = {
1277 .name = "relay:prepare",
1278 .startup.single = relay_prepare_cpu,
1279 .teardown.single = NULL,
1280 },
1275 [CPUHP_RCUTREE_PREP] = { 1281 [CPUHP_RCUTREE_PREP] = {
1276 .name = "RCU/tree:prepare", 1282 .name = "RCU/tree:prepare",
1277 .startup.single = rcutree_prepare_cpu, 1283 .startup.single = rcutree_prepare_cpu,
diff --git a/kernel/relay.c b/kernel/relay.c
index ed157378f6cb..fc9b4a4af463 100644
--- a/kernel/relay.c
+++ b/kernel/relay.c
@@ -513,48 +513,25 @@ static void setup_callbacks(struct rchan *chan,
513 chan->cb = cb; 513 chan->cb = cb;
514} 514}
515 515
516/** 516int relay_prepare_cpu(unsigned int cpu)
517 * relay_hotcpu_callback - CPU hotplug callback
518 * @nb: notifier block
519 * @action: hotplug action to take
520 * @hcpu: CPU number
521 *
522 * Returns the success/failure of the operation. (%NOTIFY_OK, %NOTIFY_BAD)
523 */
524static int relay_hotcpu_callback(struct notifier_block *nb,
525 unsigned long action,
526 void *hcpu)
527{ 517{
528 unsigned int hotcpu = (unsigned long)hcpu;
529 struct rchan *chan; 518 struct rchan *chan;
530 struct rchan_buf *buf; 519 struct rchan_buf *buf;
531 520
532 switch(action) { 521 mutex_lock(&relay_channels_mutex);
533 case CPU_UP_PREPARE: 522 list_for_each_entry(chan, &relay_channels, list) {
534 case CPU_UP_PREPARE_FROZEN: 523 if ((buf = *per_cpu_ptr(chan->buf, cpu)))
535 mutex_lock(&relay_channels_mutex); 524 continue;
536 list_for_each_entry(chan, &relay_channels, list) { 525 buf = relay_open_buf(chan, cpu);
537 if ((buf = *per_cpu_ptr(chan->buf, hotcpu))) 526 if (!buf) {
538 continue; 527 pr_err("relay: cpu %d buffer creation failed\n", cpu);
539 buf = relay_open_buf(chan, hotcpu); 528 mutex_unlock(&relay_channels_mutex);
540 if (!buf) { 529 return -ENOMEM;
541 printk(KERN_ERR
542 "relay_hotcpu_callback: cpu %d buffer "
543 "creation failed\n", hotcpu);
544 mutex_unlock(&relay_channels_mutex);
545 return notifier_from_errno(-ENOMEM);
546 }
547 *per_cpu_ptr(chan->buf, hotcpu) = buf;
548 } 530 }
549 mutex_unlock(&relay_channels_mutex); 531 *per_cpu_ptr(chan->buf, cpu) = buf;
550 break;
551 case CPU_DEAD:
552 case CPU_DEAD_FROZEN:
553 /* No need to flush the cpu : will be flushed upon
554 * final relay_flush() call. */
555 break;
556 } 532 }
557 return NOTIFY_OK; 533 mutex_unlock(&relay_channels_mutex);
534 return 0;
558} 535}
559 536
560/** 537/**
@@ -1387,12 +1364,3 @@ const struct file_operations relay_file_operations = {
1387 .splice_read = relay_file_splice_read, 1364 .splice_read = relay_file_splice_read,
1388}; 1365};
1389EXPORT_SYMBOL_GPL(relay_file_operations); 1366EXPORT_SYMBOL_GPL(relay_file_operations);
1390
1391static __init int relay_init(void)
1392{
1393
1394 hotcpu_notifier(relay_hotcpu_callback, 0);
1395 return 0;
1396}
1397
1398early_initcall(relay_init);