aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastian Andrzej Siewior <bigeasy@linutronix.de>2016-11-17 13:35:40 -0500
committerThomas Gleixner <tglx@linutronix.de>2016-11-22 17:34:43 -0500
commit89666c50472263fba97b7edbfd2a642d1d9d6f74 (patch)
tree5e78a0954fc497c5ebc09a40ad06485f159f95b1
parent08ed487c819d285c3f6ceafd156094102acdfec2 (diff)
x86/oprofile/nmi: Convert to hotplug state machine
Install the callbacks via the state machine and let the core invoke the callbacks on the already online CPUs. Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> Cc: Robert Richter <rric@kernel.org> Cc: oprofile-list@lists.sf.net Cc: rt@linuxtronix.de Link: http://lkml.kernel.org/r/20161117183541.8588-20-bigeasy@linutronix.de Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
-rw-r--r--arch/x86/oprofile/nmi_int.c61
1 files changed, 18 insertions, 43 deletions
diff --git a/arch/x86/oprofile/nmi_int.c b/arch/x86/oprofile/nmi_int.c
index c39172cd6c87..ffdbc4836b4f 100644
--- a/arch/x86/oprofile/nmi_int.c
+++ b/arch/x86/oprofile/nmi_int.c
@@ -339,10 +339,11 @@ fail:
339 return 0; 339 return 0;
340} 340}
341 341
342static void nmi_cpu_setup(void *dummy) 342static void nmi_cpu_setup(void)
343{ 343{
344 int cpu = smp_processor_id(); 344 int cpu = smp_processor_id();
345 struct op_msrs *msrs = &per_cpu(cpu_msrs, cpu); 345 struct op_msrs *msrs = &per_cpu(cpu_msrs, cpu);
346
346 nmi_cpu_save_registers(msrs); 347 nmi_cpu_save_registers(msrs);
347 raw_spin_lock(&oprofilefs_lock); 348 raw_spin_lock(&oprofilefs_lock);
348 model->setup_ctrs(model, msrs); 349 model->setup_ctrs(model, msrs);
@@ -369,7 +370,7 @@ static void nmi_cpu_restore_registers(struct op_msrs *msrs)
369 } 370 }
370} 371}
371 372
372static void nmi_cpu_shutdown(void *dummy) 373static void nmi_cpu_shutdown(void)
373{ 374{
374 unsigned int v; 375 unsigned int v;
375 int cpu = smp_processor_id(); 376 int cpu = smp_processor_id();
@@ -387,24 +388,26 @@ static void nmi_cpu_shutdown(void *dummy)
387 nmi_cpu_restore_registers(msrs); 388 nmi_cpu_restore_registers(msrs);
388} 389}
389 390
390static void nmi_cpu_up(void) 391static int nmi_cpu_online(unsigned int cpu)
391{ 392{
392 local_irq_disable(); 393 local_irq_disable();
393 if (nmi_enabled) 394 if (nmi_enabled)
394 nmi_cpu_setup(NULL); 395 nmi_cpu_setup();
395 if (ctr_running) 396 if (ctr_running)
396 nmi_cpu_start(NULL); 397 nmi_cpu_start(NULL);
397 local_irq_enable(); 398 local_irq_enable();
399 return 0;
398} 400}
399 401
400static void nmi_cpu_down(void) 402static int nmi_cpu_down_prep(unsigned int cpu)
401{ 403{
402 local_irq_disable(); 404 local_irq_disable();
403 if (ctr_running) 405 if (ctr_running)
404 nmi_cpu_stop(NULL); 406 nmi_cpu_stop(NULL);
405 if (nmi_enabled) 407 if (nmi_enabled)
406 nmi_cpu_shutdown(NULL); 408 nmi_cpu_shutdown();
407 local_irq_enable(); 409 local_irq_enable();
410 return 0;
408} 411}
409 412
410static int nmi_create_files(struct dentry *root) 413static int nmi_create_files(struct dentry *root)
@@ -437,24 +440,7 @@ static int nmi_create_files(struct dentry *root)
437 return 0; 440 return 0;
438} 441}
439 442
440static int oprofile_cpu_notifier(struct notifier_block *b, unsigned long action, 443static enum cpuhp_state cpuhp_nmi_online;
441 void *data)
442{
443 switch (action & ~CPU_TASKS_FROZEN) {
444 case CPU_DOWN_FAILED:
445 case CPU_ONLINE:
446 nmi_cpu_up();
447 break;
448 case CPU_DOWN_PREPARE:
449 nmi_cpu_down();
450 break;
451 }
452 return NOTIFY_DONE;
453}
454
455static struct notifier_block oprofile_cpu_nb = {
456 .notifier_call = oprofile_cpu_notifier
457};
458 444
459static int nmi_setup(void) 445static int nmi_setup(void)
460{ 446{
@@ -497,20 +483,17 @@ static int nmi_setup(void)
497 if (err) 483 if (err)
498 goto fail; 484 goto fail;
499 485
500 cpu_notifier_register_begin();
501
502 /* Use get/put_online_cpus() to protect 'nmi_enabled' */
503 get_online_cpus();
504 nmi_enabled = 1; 486 nmi_enabled = 1;
505 /* make nmi_enabled visible to the nmi handler: */ 487 /* make nmi_enabled visible to the nmi handler: */
506 smp_mb(); 488 smp_mb();
507 on_each_cpu(nmi_cpu_setup, NULL, 1); 489 err = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "x86/oprofile:online",
508 __register_cpu_notifier(&oprofile_cpu_nb); 490 nmi_cpu_online, nmi_cpu_down_prep);
509 put_online_cpus(); 491 if (err < 0)
510 492 goto fail_nmi;
511 cpu_notifier_register_done(); 493 cpuhp_nmi_online = err;
512
513 return 0; 494 return 0;
495fail_nmi:
496 unregister_nmi_handler(NMI_LOCAL, "oprofile");
514fail: 497fail:
515 free_msrs(); 498 free_msrs();
516 return err; 499 return err;
@@ -520,17 +503,9 @@ static void nmi_shutdown(void)
520{ 503{
521 struct op_msrs *msrs; 504 struct op_msrs *msrs;
522 505
523 cpu_notifier_register_begin(); 506 cpuhp_remove_state(cpuhp_nmi_online);
524
525 /* Use get/put_online_cpus() to protect 'nmi_enabled' & 'ctr_running' */
526 get_online_cpus();
527 on_each_cpu(nmi_cpu_shutdown, NULL, 1);
528 nmi_enabled = 0; 507 nmi_enabled = 0;
529 ctr_running = 0; 508 ctr_running = 0;
530 __unregister_cpu_notifier(&oprofile_cpu_nb);
531 put_online_cpus();
532
533 cpu_notifier_register_done();
534 509
535 /* make variables visible to the nmi handler: */ 510 /* make variables visible to the nmi handler: */
536 smp_mb(); 511 smp_mb();