diff options
-rw-r--r-- | arch/powerpc/platforms/pseries/dlpar.c | 45 | ||||
-rw-r--r-- | drivers/base/cpu.c | 2 | ||||
-rw-r--r-- | include/linux/cpu.h | 13 |
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 | ||
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) |
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) |
118 | int cpu_down(unsigned int cpu); | 118 | int cpu_down(unsigned int cpu); |
119 | 119 | ||
120 | #ifdef CONFIG_ARCH_CPU_PROBE_RELEASE | ||
121 | extern void cpu_hotplug_driver_lock(void); | ||
122 | extern void cpu_hotplug_driver_unlock(void); | ||
123 | #else | ||
124 | static inline void cpu_hotplug_driver_lock(void) | ||
125 | { | ||
126 | } | ||
127 | |||
128 | static 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) |