aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/powerpc/platforms/pseries/dlpar.c45
-rw-r--r--drivers/base/cpu.c2
-rw-r--r--include/linux/cpu.h13
3 files changed, 50 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)
diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c
index 7c03af7b84a9..27fd775375b0 100644
--- a/drivers/base/cpu.c
+++ b/drivers/base/cpu.c
@@ -35,6 +35,7 @@ static ssize_t __ref store_online(struct sys_device *dev, struct sysdev_attribut
35 struct cpu *cpu = container_of(dev, struct cpu, sysdev); 35 struct cpu *cpu = container_of(dev, struct cpu, sysdev);
36 ssize_t ret; 36 ssize_t ret;
37 37
38 cpu_hotplug_driver_lock();
38 switch (buf[0]) { 39 switch (buf[0]) {
39 case '0': 40 case '0':
40 ret = cpu_down(cpu->sysdev.id); 41 ret = cpu_down(cpu->sysdev.id);
@@ -49,6 +50,7 @@ static ssize_t __ref store_online(struct sys_device *dev, struct sysdev_attribut
49 default: 50 default:
50 ret = -EINVAL; 51 ret = -EINVAL;
51 } 52 }
53 cpu_hotplug_driver_unlock();
52 54
53 if (ret >= 0) 55 if (ret >= 0)
54 ret = count; 56 ret = count;
diff --git a/include/linux/cpu.h b/include/linux/cpu.h
index c972f7ccb7d3..e287863ac053 100644
--- a/include/linux/cpu.h
+++ b/include/linux/cpu.h
@@ -117,6 +117,19 @@ extern void put_online_cpus(void);
117#define unregister_hotcpu_notifier(nb) unregister_cpu_notifier(nb) 117#define unregister_hotcpu_notifier(nb) unregister_cpu_notifier(nb)
118int cpu_down(unsigned int cpu); 118int cpu_down(unsigned int cpu);
119 119
120#ifdef CONFIG_ARCH_CPU_PROBE_RELEASE
121extern void cpu_hotplug_driver_lock(void);
122extern void cpu_hotplug_driver_unlock(void);
123#else
124static inline void cpu_hotplug_driver_lock(void)
125{
126}
127
128static inline void cpu_hotplug_driver_unlock(void)
129{
130}
131#endif
132
120#else /* CONFIG_HOTPLUG_CPU */ 133#else /* CONFIG_HOTPLUG_CPU */
121 134
122#define get_online_cpus() do { } while (0) 135#define get_online_cpus() do { } while (0)