aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNathan Fontenot <nfont@linux.vnet.ibm.com>2015-12-16 15:50:21 -0500
committerMichael Ellerman <mpe@ellerman.id.au>2015-12-17 06:41:01 -0500
commit183deeea5871a6f750ec64ab1cff85fb089d38df (patch)
treeca13154abda62f630fe22c2fa2f2a76cd326d7da
parent1f859adb9253c201079962582253236e9b2cc3ce (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.c226
-rw-r--r--arch/powerpc/platforms/pseries/hotplug-cpu.c218
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
343static 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
379out:
380 return rc;
381
382}
383
384static 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
410static 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
458static 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
509out:
510 return rc;
511
512}
513
514static 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
555static int handle_dlpar_errorlog(struct pseries_hp_errorlog *hp_elog) 340static 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
660static int __init pseries_dlpar_init(void) 445static 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}
673machine_device_initcall(pseries, pseries_dlpar_init); 449machine_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
340static 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
376out:
377 return rc;
378
379}
380
381static 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
407static 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
453static 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
504out:
505 return rc;
506
507}
508
509static 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
337static int pseries_smp_notifier(struct notifier_block *nb, 550static 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")) {