diff options
author | Nathan Fontenot <nfont@linux.vnet.ibm.com> | 2015-12-16 15:50:21 -0500 |
---|---|---|
committer | Michael Ellerman <mpe@ellerman.id.au> | 2015-12-17 06:41:01 -0500 |
commit | 183deeea5871a6f750ec64ab1cff85fb089d38df (patch) | |
tree | ca13154abda62f630fe22c2fa2f2a76cd326d7da | |
parent | 1f859adb9253c201079962582253236e9b2cc3ce (diff) |
powerpc/pseries: Consolidate CPU hotplug code to hotplug-cpu.c
No functional changes, this patch is simply a move of the cpu hotplug
code from pseries/dlpar.c to pseries/hotplug-cpu.c. This is in an effort
to consolidate all of the cpu hotplug code in a common place.
Signed-off-by: Nathan Fontenot <nfont@linux.vnet.ibm.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
-rw-r--r-- | arch/powerpc/platforms/pseries/dlpar.c | 226 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/hotplug-cpu.c | 218 |
2 files changed, 219 insertions, 225 deletions
diff --git a/arch/powerpc/platforms/pseries/dlpar.c b/arch/powerpc/platforms/pseries/dlpar.c index fe6320db9255..438fdbd7e40e 100644 --- a/arch/powerpc/platforms/pseries/dlpar.c +++ b/arch/powerpc/platforms/pseries/dlpar.c | |||
@@ -20,7 +20,6 @@ | |||
20 | #include <linux/of.h> | 20 | #include <linux/of.h> |
21 | 21 | ||
22 | #include "of_helpers.h" | 22 | #include "of_helpers.h" |
23 | #include "offline_states.h" | ||
24 | #include "pseries.h" | 23 | #include "pseries.h" |
25 | 24 | ||
26 | #include <asm/prom.h> | 25 | #include <asm/prom.h> |
@@ -338,220 +337,6 @@ int dlpar_release_drc(u32 drc_index) | |||
338 | return 0; | 337 | return 0; |
339 | } | 338 | } |
340 | 339 | ||
341 | #ifdef CONFIG_ARCH_CPU_PROBE_RELEASE | ||
342 | |||
343 | static int dlpar_online_cpu(struct device_node *dn) | ||
344 | { | ||
345 | int rc = 0; | ||
346 | unsigned int cpu; | ||
347 | int len, nthreads, i; | ||
348 | const __be32 *intserv; | ||
349 | u32 thread; | ||
350 | |||
351 | intserv = of_get_property(dn, "ibm,ppc-interrupt-server#s", &len); | ||
352 | if (!intserv) | ||
353 | return -EINVAL; | ||
354 | |||
355 | nthreads = len / sizeof(u32); | ||
356 | |||
357 | cpu_maps_update_begin(); | ||
358 | for (i = 0; i < nthreads; i++) { | ||
359 | thread = be32_to_cpu(intserv[i]); | ||
360 | for_each_present_cpu(cpu) { | ||
361 | if (get_hard_smp_processor_id(cpu) != thread) | ||
362 | continue; | ||
363 | BUG_ON(get_cpu_current_state(cpu) | ||
364 | != CPU_STATE_OFFLINE); | ||
365 | cpu_maps_update_done(); | ||
366 | rc = device_online(get_cpu_device(cpu)); | ||
367 | if (rc) | ||
368 | goto out; | ||
369 | cpu_maps_update_begin(); | ||
370 | |||
371 | break; | ||
372 | } | ||
373 | if (cpu == num_possible_cpus()) | ||
374 | printk(KERN_WARNING "Could not find cpu to online " | ||
375 | "with physical id 0x%x\n", thread); | ||
376 | } | ||
377 | cpu_maps_update_done(); | ||
378 | |||
379 | out: | ||
380 | return rc; | ||
381 | |||
382 | } | ||
383 | |||
384 | static bool dlpar_cpu_exists(struct device_node *parent, u32 drc_index) | ||
385 | { | ||
386 | struct device_node *child = NULL; | ||
387 | u32 my_drc_index; | ||
388 | bool found; | ||
389 | int rc; | ||
390 | |||
391 | /* Assume cpu doesn't exist */ | ||
392 | found = false; | ||
393 | |||
394 | for_each_child_of_node(parent, child) { | ||
395 | rc = of_property_read_u32(child, "ibm,my-drc-index", | ||
396 | &my_drc_index); | ||
397 | if (rc) | ||
398 | continue; | ||
399 | |||
400 | if (my_drc_index == drc_index) { | ||
401 | of_node_put(child); | ||
402 | found = true; | ||
403 | break; | ||
404 | } | ||
405 | } | ||
406 | |||
407 | return found; | ||
408 | } | ||
409 | |||
410 | static ssize_t dlpar_cpu_probe(const char *buf, size_t count) | ||
411 | { | ||
412 | struct device_node *dn, *parent; | ||
413 | u32 drc_index; | ||
414 | int rc; | ||
415 | |||
416 | rc = kstrtou32(buf, 0, &drc_index); | ||
417 | if (rc) | ||
418 | return -EINVAL; | ||
419 | |||
420 | parent = of_find_node_by_path("/cpus"); | ||
421 | if (!parent) | ||
422 | return -ENODEV; | ||
423 | |||
424 | if (dlpar_cpu_exists(parent, drc_index)) { | ||
425 | of_node_put(parent); | ||
426 | printk(KERN_WARNING "CPU with drc index %x already exists\n", | ||
427 | drc_index); | ||
428 | return -EINVAL; | ||
429 | } | ||
430 | |||
431 | rc = dlpar_acquire_drc(drc_index); | ||
432 | if (rc) { | ||
433 | of_node_put(parent); | ||
434 | return -EINVAL; | ||
435 | } | ||
436 | |||
437 | dn = dlpar_configure_connector(cpu_to_be32(drc_index), parent); | ||
438 | of_node_put(parent); | ||
439 | if (!dn) { | ||
440 | dlpar_release_drc(drc_index); | ||
441 | return -EINVAL; | ||
442 | } | ||
443 | |||
444 | rc = dlpar_attach_node(dn); | ||
445 | if (rc) { | ||
446 | dlpar_release_drc(drc_index); | ||
447 | dlpar_free_cc_nodes(dn); | ||
448 | return rc; | ||
449 | } | ||
450 | |||
451 | rc = dlpar_online_cpu(dn); | ||
452 | if (rc) | ||
453 | return rc; | ||
454 | |||
455 | return count; | ||
456 | } | ||
457 | |||
458 | static int dlpar_offline_cpu(struct device_node *dn) | ||
459 | { | ||
460 | int rc = 0; | ||
461 | unsigned int cpu; | ||
462 | int len, nthreads, i; | ||
463 | const __be32 *intserv; | ||
464 | u32 thread; | ||
465 | |||
466 | intserv = of_get_property(dn, "ibm,ppc-interrupt-server#s", &len); | ||
467 | if (!intserv) | ||
468 | return -EINVAL; | ||
469 | |||
470 | nthreads = len / sizeof(u32); | ||
471 | |||
472 | cpu_maps_update_begin(); | ||
473 | for (i = 0; i < nthreads; i++) { | ||
474 | thread = be32_to_cpu(intserv[i]); | ||
475 | for_each_present_cpu(cpu) { | ||
476 | if (get_hard_smp_processor_id(cpu) != thread) | ||
477 | continue; | ||
478 | |||
479 | if (get_cpu_current_state(cpu) == CPU_STATE_OFFLINE) | ||
480 | break; | ||
481 | |||
482 | if (get_cpu_current_state(cpu) == CPU_STATE_ONLINE) { | ||
483 | set_preferred_offline_state(cpu, CPU_STATE_OFFLINE); | ||
484 | cpu_maps_update_done(); | ||
485 | rc = device_offline(get_cpu_device(cpu)); | ||
486 | if (rc) | ||
487 | goto out; | ||
488 | cpu_maps_update_begin(); | ||
489 | break; | ||
490 | |||
491 | } | ||
492 | |||
493 | /* | ||
494 | * The cpu is in CPU_STATE_INACTIVE. | ||
495 | * Upgrade it's state to CPU_STATE_OFFLINE. | ||
496 | */ | ||
497 | set_preferred_offline_state(cpu, CPU_STATE_OFFLINE); | ||
498 | BUG_ON(plpar_hcall_norets(H_PROD, thread) | ||
499 | != H_SUCCESS); | ||
500 | __cpu_die(cpu); | ||
501 | break; | ||
502 | } | ||
503 | if (cpu == num_possible_cpus()) | ||
504 | printk(KERN_WARNING "Could not find cpu to offline " | ||
505 | "with physical id 0x%x\n", thread); | ||
506 | } | ||
507 | cpu_maps_update_done(); | ||
508 | |||
509 | out: | ||
510 | return rc; | ||
511 | |||
512 | } | ||
513 | |||
514 | static ssize_t dlpar_cpu_release(const char *buf, size_t count) | ||
515 | { | ||
516 | struct device_node *dn; | ||
517 | u32 drc_index; | ||
518 | int rc; | ||
519 | |||
520 | dn = of_find_node_by_path(buf); | ||
521 | if (!dn) | ||
522 | return -EINVAL; | ||
523 | |||
524 | rc = of_property_read_u32(dn, "ibm,my-drc-index", &drc_index); | ||
525 | if (rc) { | ||
526 | of_node_put(dn); | ||
527 | return -EINVAL; | ||
528 | } | ||
529 | |||
530 | rc = dlpar_offline_cpu(dn); | ||
531 | if (rc) { | ||
532 | of_node_put(dn); | ||
533 | return -EINVAL; | ||
534 | } | ||
535 | |||
536 | rc = dlpar_release_drc(drc_index); | ||
537 | if (rc) { | ||
538 | of_node_put(dn); | ||
539 | return rc; | ||
540 | } | ||
541 | |||
542 | rc = dlpar_detach_node(dn); | ||
543 | if (rc) { | ||
544 | dlpar_acquire_drc(drc_index); | ||
545 | return rc; | ||
546 | } | ||
547 | |||
548 | of_node_put(dn); | ||
549 | |||
550 | return count; | ||
551 | } | ||
552 | |||
553 | #endif /* CONFIG_ARCH_CPU_PROBE_RELEASE */ | ||
554 | |||
555 | static int handle_dlpar_errorlog(struct pseries_hp_errorlog *hp_elog) | 340 | static int handle_dlpar_errorlog(struct pseries_hp_errorlog *hp_elog) |
556 | { | 341 | { |
557 | int rc; | 342 | int rc; |
@@ -659,16 +444,7 @@ static CLASS_ATTR(dlpar, S_IWUSR, NULL, dlpar_store); | |||
659 | 444 | ||
660 | static int __init pseries_dlpar_init(void) | 445 | static int __init pseries_dlpar_init(void) |
661 | { | 446 | { |
662 | int rc; | 447 | return sysfs_create_file(kernel_kobj, &class_attr_dlpar.attr); |
663 | |||
664 | #ifdef CONFIG_ARCH_CPU_PROBE_RELEASE | ||
665 | ppc_md.cpu_probe = dlpar_cpu_probe; | ||
666 | ppc_md.cpu_release = dlpar_cpu_release; | ||
667 | #endif /* CONFIG_ARCH_CPU_PROBE_RELEASE */ | ||
668 | |||
669 | rc = sysfs_create_file(kernel_kobj, &class_attr_dlpar.attr); | ||
670 | |||
671 | return rc; | ||
672 | } | 448 | } |
673 | machine_device_initcall(pseries, pseries_dlpar_init); | 449 | machine_device_initcall(pseries, pseries_dlpar_init); |
674 | 450 | ||
diff --git a/arch/powerpc/platforms/pseries/hotplug-cpu.c b/arch/powerpc/platforms/pseries/hotplug-cpu.c index 86d2ecacb237..66d8c2c64aa9 100644 --- a/arch/powerpc/platforms/pseries/hotplug-cpu.c +++ b/arch/powerpc/platforms/pseries/hotplug-cpu.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include <asm/xics.h> | 32 | #include <asm/xics.h> |
33 | #include <asm/plpar_wrappers.h> | 33 | #include <asm/plpar_wrappers.h> |
34 | 34 | ||
35 | #include "pseries.h" | ||
35 | #include "offline_states.h" | 36 | #include "offline_states.h" |
36 | 37 | ||
37 | /* This version can't take the spinlock, because it never returns */ | 38 | /* This version can't take the spinlock, because it never returns */ |
@@ -334,6 +335,218 @@ static void pseries_remove_processor(struct device_node *np) | |||
334 | cpu_maps_update_done(); | 335 | cpu_maps_update_done(); |
335 | } | 336 | } |
336 | 337 | ||
338 | #ifdef CONFIG_ARCH_CPU_PROBE_RELEASE | ||
339 | |||
340 | static int dlpar_online_cpu(struct device_node *dn) | ||
341 | { | ||
342 | int rc = 0; | ||
343 | unsigned int cpu; | ||
344 | int len, nthreads, i; | ||
345 | const __be32 *intserv; | ||
346 | u32 thread; | ||
347 | |||
348 | intserv = of_get_property(dn, "ibm,ppc-interrupt-server#s", &len); | ||
349 | if (!intserv) | ||
350 | return -EINVAL; | ||
351 | |||
352 | nthreads = len / sizeof(u32); | ||
353 | |||
354 | cpu_maps_update_begin(); | ||
355 | for (i = 0; i < nthreads; i++) { | ||
356 | thread = be32_to_cpu(intserv[i]); | ||
357 | for_each_present_cpu(cpu) { | ||
358 | if (get_hard_smp_processor_id(cpu) != thread) | ||
359 | continue; | ||
360 | BUG_ON(get_cpu_current_state(cpu) | ||
361 | != CPU_STATE_OFFLINE); | ||
362 | cpu_maps_update_done(); | ||
363 | rc = device_online(get_cpu_device(cpu)); | ||
364 | if (rc) | ||
365 | goto out; | ||
366 | cpu_maps_update_begin(); | ||
367 | |||
368 | break; | ||
369 | } | ||
370 | if (cpu == num_possible_cpus()) | ||
371 | printk(KERN_WARNING "Could not find cpu to online " | ||
372 | "with physical id 0x%x\n", thread); | ||
373 | } | ||
374 | cpu_maps_update_done(); | ||
375 | |||
376 | out: | ||
377 | return rc; | ||
378 | |||
379 | } | ||
380 | |||
381 | static bool dlpar_cpu_exists(struct device_node *parent, u32 drc_index) | ||
382 | { | ||
383 | struct device_node *child = NULL; | ||
384 | u32 my_drc_index; | ||
385 | bool found; | ||
386 | int rc; | ||
387 | |||
388 | /* Assume cpu doesn't exist */ | ||
389 | found = false; | ||
390 | |||
391 | for_each_child_of_node(parent, child) { | ||
392 | rc = of_property_read_u32(child, "ibm,my-drc-index", | ||
393 | &my_drc_index); | ||
394 | if (rc) | ||
395 | continue; | ||
396 | |||
397 | if (my_drc_index == drc_index) { | ||
398 | of_node_put(child); | ||
399 | found = true; | ||
400 | break; | ||
401 | } | ||
402 | } | ||
403 | |||
404 | return found; | ||
405 | } | ||
406 | |||
407 | static ssize_t dlpar_cpu_probe(const char *buf, size_t count) | ||
408 | { | ||
409 | struct device_node *dn, *parent; | ||
410 | u32 drc_index; | ||
411 | int rc; | ||
412 | |||
413 | rc = kstrtou32(buf, 0, &drc_index); | ||
414 | if (rc) | ||
415 | return -EINVAL; | ||
416 | |||
417 | parent = of_find_node_by_path("/cpus"); | ||
418 | if (!parent) | ||
419 | return -ENODEV; | ||
420 | |||
421 | if (dlpar_cpu_exists(parent, drc_index)) { | ||
422 | of_node_put(parent); | ||
423 | printk(KERN_WARNING "CPU with drc index %x already exists\n", | ||
424 | drc_index); | ||
425 | return -EINVAL; | ||
426 | } | ||
427 | |||
428 | rc = dlpar_acquire_drc(drc_index); | ||
429 | if (rc) { | ||
430 | of_node_put(parent); | ||
431 | return -EINVAL; | ||
432 | } | ||
433 | |||
434 | dn = dlpar_configure_connector(cpu_to_be32(drc_index), parent); | ||
435 | of_node_put(parent); | ||
436 | if (!dn) | ||
437 | return -EINVAL; | ||
438 | |||
439 | rc = dlpar_attach_node(dn); | ||
440 | if (rc) { | ||
441 | dlpar_release_drc(drc_index); | ||
442 | dlpar_free_cc_nodes(dn); | ||
443 | return rc; | ||
444 | } | ||
445 | |||
446 | rc = dlpar_online_cpu(dn); | ||
447 | if (rc) | ||
448 | return rc; | ||
449 | |||
450 | return count; | ||
451 | } | ||
452 | |||
453 | static int dlpar_offline_cpu(struct device_node *dn) | ||
454 | { | ||
455 | int rc = 0; | ||
456 | unsigned int cpu; | ||
457 | int len, nthreads, i; | ||
458 | const __be32 *intserv; | ||
459 | u32 thread; | ||
460 | |||
461 | intserv = of_get_property(dn, "ibm,ppc-interrupt-server#s", &len); | ||
462 | if (!intserv) | ||
463 | return -EINVAL; | ||
464 | |||
465 | nthreads = len / sizeof(u32); | ||
466 | |||
467 | cpu_maps_update_begin(); | ||
468 | for (i = 0; i < nthreads; i++) { | ||
469 | thread = be32_to_cpu(intserv[i]); | ||
470 | for_each_present_cpu(cpu) { | ||
471 | if (get_hard_smp_processor_id(cpu) != thread) | ||
472 | continue; | ||
473 | |||
474 | if (get_cpu_current_state(cpu) == CPU_STATE_OFFLINE) | ||
475 | break; | ||
476 | |||
477 | if (get_cpu_current_state(cpu) == CPU_STATE_ONLINE) { | ||
478 | set_preferred_offline_state(cpu, | ||
479 | CPU_STATE_OFFLINE); | ||
480 | cpu_maps_update_done(); | ||
481 | rc = device_offline(get_cpu_device(cpu)); | ||
482 | if (rc) | ||
483 | goto out; | ||
484 | cpu_maps_update_begin(); | ||
485 | break; | ||
486 | |||
487 | } | ||
488 | |||
489 | /* | ||
490 | * The cpu is in CPU_STATE_INACTIVE. | ||
491 | * Upgrade it's state to CPU_STATE_OFFLINE. | ||
492 | */ | ||
493 | set_preferred_offline_state(cpu, CPU_STATE_OFFLINE); | ||
494 | BUG_ON(plpar_hcall_norets(H_PROD, thread) | ||
495 | != H_SUCCESS); | ||
496 | __cpu_die(cpu); | ||
497 | break; | ||
498 | } | ||
499 | if (cpu == num_possible_cpus()) | ||
500 | printk(KERN_WARNING "Could not find cpu to offline with physical id 0x%x\n", thread); | ||
501 | } | ||
502 | cpu_maps_update_done(); | ||
503 | |||
504 | out: | ||
505 | return rc; | ||
506 | |||
507 | } | ||
508 | |||
509 | static ssize_t dlpar_cpu_release(const char *buf, size_t count) | ||
510 | { | ||
511 | struct device_node *dn; | ||
512 | u32 drc_index; | ||
513 | int rc; | ||
514 | |||
515 | dn = of_find_node_by_path(buf); | ||
516 | if (!dn) | ||
517 | return -EINVAL; | ||
518 | |||
519 | rc = of_property_read_u32(dn, "ibm,my-drc-index", &drc_index); | ||
520 | if (rc) { | ||
521 | of_node_put(dn); | ||
522 | return -EINVAL; | ||
523 | } | ||
524 | |||
525 | rc = dlpar_offline_cpu(dn); | ||
526 | if (rc) { | ||
527 | of_node_put(dn); | ||
528 | return -EINVAL; | ||
529 | } | ||
530 | |||
531 | rc = dlpar_release_drc(drc_index); | ||
532 | if (rc) { | ||
533 | of_node_put(dn); | ||
534 | return rc; | ||
535 | } | ||
536 | |||
537 | rc = dlpar_detach_node(dn); | ||
538 | if (rc) { | ||
539 | dlpar_acquire_drc(drc_index); | ||
540 | return rc; | ||
541 | } | ||
542 | |||
543 | of_node_put(dn); | ||
544 | |||
545 | return count; | ||
546 | } | ||
547 | |||
548 | #endif /* CONFIG_ARCH_CPU_PROBE_RELEASE */ | ||
549 | |||
337 | static int pseries_smp_notifier(struct notifier_block *nb, | 550 | static int pseries_smp_notifier(struct notifier_block *nb, |
338 | unsigned long action, void *data) | 551 | unsigned long action, void *data) |
339 | { | 552 | { |
@@ -380,6 +593,11 @@ static int __init pseries_cpu_hotplug_init(void) | |||
380 | int cpu; | 593 | int cpu; |
381 | int qcss_tok; | 594 | int qcss_tok; |
382 | 595 | ||
596 | #ifdef CONFIG_ARCH_CPU_PROBE_RELEASE | ||
597 | ppc_md.cpu_probe = dlpar_cpu_probe; | ||
598 | ppc_md.cpu_release = dlpar_cpu_release; | ||
599 | #endif /* CONFIG_ARCH_CPU_PROBE_RELEASE */ | ||
600 | |||
383 | for_each_node_by_name(np, "interrupt-controller") { | 601 | for_each_node_by_name(np, "interrupt-controller") { |
384 | typep = of_get_property(np, "compatible", NULL); | 602 | typep = of_get_property(np, "compatible", NULL); |
385 | if (strstr(typep, "open-pic")) { | 603 | if (strstr(typep, "open-pic")) { |