aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/platforms/pseries/dlpar.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/platforms/pseries/dlpar.c')
-rw-r--r--arch/powerpc/platforms/pseries/dlpar.c45
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
439static DEFINE_MUTEX(pseries_cpu_hotplug_mutex);
440
441void cpu_hotplug_driver_lock()
442{
443 mutex_lock(&pseries_cpu_hotplug_mutex);
444}
445
446void cpu_hotplug_driver_unlock()
447{
448 mutex_unlock(&pseries_cpu_hotplug_mutex);
449}
450
439static ssize_t dlpar_cpu_probe(const char *buf, size_t count) 451static 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);
501out:
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; 544out:
545 cpu_hotplug_driver_unlock();
546 return rc ? rc : count;
522} 547}
523 548
524static int __init pseries_dlpar_init(void) 549static int __init pseries_dlpar_init(void)