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) |
