diff options
author | Sebastian Andrzej Siewior <bigeasy@linutronix.de> | 2016-11-17 13:35:40 -0500 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2016-11-22 17:34:43 -0500 |
commit | 89666c50472263fba97b7edbfd2a642d1d9d6f74 (patch) | |
tree | 5e78a0954fc497c5ebc09a40ad06485f159f95b1 | |
parent | 08ed487c819d285c3f6ceafd156094102acdfec2 (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.c | 61 |
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 | ||
342 | static void nmi_cpu_setup(void *dummy) | 342 | static 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 | ||
372 | static void nmi_cpu_shutdown(void *dummy) | 373 | static 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 | ||
390 | static void nmi_cpu_up(void) | 391 | static 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 | ||
400 | static void nmi_cpu_down(void) | 402 | static 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 | ||
410 | static int nmi_create_files(struct dentry *root) | 413 | static 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 | ||
440 | static int oprofile_cpu_notifier(struct notifier_block *b, unsigned long action, | 443 | static 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 | |||
455 | static struct notifier_block oprofile_cpu_nb = { | ||
456 | .notifier_call = oprofile_cpu_notifier | ||
457 | }; | ||
458 | 444 | ||
459 | static int nmi_setup(void) | 445 | static 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; |
495 | fail_nmi: | ||
496 | unregister_nmi_handler(NMI_LOCAL, "oprofile"); | ||
514 | fail: | 497 | fail: |
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(); |