diff options
Diffstat (limited to 'arch/powerpc/platforms/pseries')
-rw-r--r-- | arch/powerpc/platforms/pseries/dlpar.c | 45 |
1 files changed, 35 insertions, 10 deletions
diff --git a/arch/powerpc/platforms/pseries/dlpar.c b/arch/powerpc/platforms/pseries/dlpar.c index 642e1b2e5c42..fd2f0afeb4de 100644 --- a/arch/powerpc/platforms/pseries/dlpar.c +++ b/arch/powerpc/platforms/pseries/dlpar.c | |||
@@ -436,6 +436,18 @@ int dlpar_release_drc(u32 drc_index) | |||
436 | 436 | ||
437 | #ifdef CONFIG_ARCH_CPU_PROBE_RELEASE | 437 | #ifdef CONFIG_ARCH_CPU_PROBE_RELEASE |
438 | 438 | ||
439 | static DEFINE_MUTEX(pseries_cpu_hotplug_mutex); | ||
440 | |||
441 | void cpu_hotplug_driver_lock() | ||
442 | { | ||
443 | mutex_lock(&pseries_cpu_hotplug_mutex); | ||
444 | } | ||
445 | |||
446 | void cpu_hotplug_driver_unlock() | ||
447 | { | ||
448 | mutex_unlock(&pseries_cpu_hotplug_mutex); | ||
449 | } | ||
450 | |||
439 | static ssize_t dlpar_cpu_probe(const char *buf, size_t count) | 451 | static ssize_t dlpar_cpu_probe(const char *buf, size_t count) |
440 | { | 452 | { |
441 | struct device_node *dn; | 453 | struct device_node *dn; |
@@ -443,13 +455,18 @@ static ssize_t dlpar_cpu_probe(const char *buf, size_t count) | |||
443 | char *cpu_name; | 455 | char *cpu_name; |
444 | int rc; | 456 | int rc; |
445 | 457 | ||
458 | cpu_hotplug_driver_lock(); | ||
446 | rc = strict_strtoul(buf, 0, &drc_index); | 459 | rc = strict_strtoul(buf, 0, &drc_index); |
447 | if (rc) | 460 | if (rc) { |
448 | return -EINVAL; | 461 | rc = -EINVAL; |
462 | goto out; | ||
463 | } | ||
449 | 464 | ||
450 | dn = dlpar_configure_connector(drc_index); | 465 | dn = dlpar_configure_connector(drc_index); |
451 | if (!dn) | 466 | if (!dn) { |
452 | return -EINVAL; | 467 | rc = -EINVAL; |
468 | goto out; | ||
469 | } | ||
453 | 470 | ||
454 | /* configure-connector reports cpus as living in the base | 471 | /* configure-connector reports cpus as living in the base |
455 | * directory of the device tree. CPUs actually live in the | 472 | * directory of the device tree. CPUs actually live in the |
@@ -459,7 +476,8 @@ static ssize_t dlpar_cpu_probe(const char *buf, size_t count) | |||
459 | GFP_KERNEL); | 476 | GFP_KERNEL); |
460 | if (!cpu_name) { | 477 | if (!cpu_name) { |
461 | dlpar_free_cc_nodes(dn); | 478 | dlpar_free_cc_nodes(dn); |
462 | return -ENOMEM; | 479 | rc = -ENOMEM; |
480 | goto out; | ||
463 | } | 481 | } |
464 | 482 | ||
465 | sprintf(cpu_name, "/cpus%s", dn->full_name); | 483 | sprintf(cpu_name, "/cpus%s", dn->full_name); |
@@ -469,7 +487,8 @@ static ssize_t dlpar_cpu_probe(const char *buf, size_t count) | |||
469 | rc = dlpar_acquire_drc(drc_index); | 487 | rc = dlpar_acquire_drc(drc_index); |
470 | if (rc) { | 488 | if (rc) { |
471 | dlpar_free_cc_nodes(dn); | 489 | dlpar_free_cc_nodes(dn); |
472 | return -EINVAL; | 490 | rc = -EINVAL; |
491 | goto out; | ||
473 | } | 492 | } |
474 | 493 | ||
475 | rc = dlpar_attach_node(dn); | 494 | rc = dlpar_attach_node(dn); |
@@ -479,6 +498,8 @@ static ssize_t dlpar_cpu_probe(const char *buf, size_t count) | |||
479 | } | 498 | } |
480 | 499 | ||
481 | rc = online_node_cpus(dn); | 500 | rc = online_node_cpus(dn); |
501 | out: | ||
502 | cpu_hotplug_driver_unlock(); | ||
482 | 503 | ||
483 | return rc ? rc : count; | 504 | return rc ? rc : count; |
484 | } | 505 | } |
@@ -499,26 +520,30 @@ static ssize_t dlpar_cpu_release(const char *buf, size_t count) | |||
499 | return -EINVAL; | 520 | return -EINVAL; |
500 | } | 521 | } |
501 | 522 | ||
523 | cpu_hotplug_driver_lock(); | ||
502 | rc = offline_node_cpus(dn); | 524 | rc = offline_node_cpus(dn); |
503 | if (rc) { | 525 | if (rc) { |
504 | of_node_put(dn); | 526 | of_node_put(dn); |
505 | return -EINVAL; | 527 | rc = -EINVAL; |
528 | goto out; | ||
506 | } | 529 | } |
507 | 530 | ||
508 | rc = dlpar_release_drc(*drc_index); | 531 | rc = dlpar_release_drc(*drc_index); |
509 | if (rc) { | 532 | if (rc) { |
510 | of_node_put(dn); | 533 | of_node_put(dn); |
511 | return -EINVAL; | 534 | goto out; |
512 | } | 535 | } |
513 | 536 | ||
514 | rc = dlpar_detach_node(dn); | 537 | rc = dlpar_detach_node(dn); |
515 | if (rc) { | 538 | if (rc) { |
516 | dlpar_acquire_drc(*drc_index); | 539 | dlpar_acquire_drc(*drc_index); |
517 | return rc; | 540 | goto out; |
518 | } | 541 | } |
519 | 542 | ||
520 | of_node_put(dn); | 543 | of_node_put(dn); |
521 | return count; | 544 | out: |
545 | cpu_hotplug_driver_unlock(); | ||
546 | return rc ? rc : count; | ||
522 | } | 547 | } |
523 | 548 | ||
524 | static int __init pseries_dlpar_init(void) | 549 | static int __init pseries_dlpar_init(void) |