aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNathan Fontenot <nfont@linux.vnet.ibm.com>2015-12-16 15:52:39 -0500
committerMichael Ellerman <mpe@ellerman.id.au>2015-12-17 06:41:02 -0500
commite666ae0b10aaa1c961c928558bafc28bc049ac87 (patch)
tree8e552eff4c6eff53ffb6df9454b02b2121d84adb
parentd98389f375329b7a37d0e9211a1216d9141d7a5f (diff)
powerpc/pseries: Update CPU hotplug error recovery
Update the cpu dlpar add/remove paths to do better error recovery when a failure occurs during the add/remove operation. Signed-off-by: Nathan Fontenot <nfont@linux.vnet.ibm.com> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
-rw-r--r--arch/powerpc/platforms/pseries/hotplug-cpu.c76
1 files changed, 63 insertions, 13 deletions
diff --git a/arch/powerpc/platforms/pseries/hotplug-cpu.c b/arch/powerpc/platforms/pseries/hotplug-cpu.c
index 6fb28cf229e7..a54aee982589 100644
--- a/arch/powerpc/platforms/pseries/hotplug-cpu.c
+++ b/arch/powerpc/platforms/pseries/hotplug-cpu.c
@@ -18,6 +18,8 @@
18 * 2 of the License, or (at your option) any later version. 18 * 2 of the License, or (at your option) any later version.
19 */ 19 */
20 20
21#define pr_fmt(fmt) "pseries-hotplug-cpu: " fmt
22
21#include <linux/kernel.h> 23#include <linux/kernel.h>
22#include <linux/interrupt.h> 24#include <linux/interrupt.h>
23#include <linux/delay.h> 25#include <linux/delay.h>
@@ -405,38 +407,67 @@ static bool dlpar_cpu_exists(struct device_node *parent, u32 drc_index)
405static ssize_t dlpar_cpu_add(u32 drc_index) 407static ssize_t dlpar_cpu_add(u32 drc_index)
406{ 408{
407 struct device_node *dn, *parent; 409 struct device_node *dn, *parent;
408 int rc; 410 int rc, saved_rc;
411
412 pr_debug("Attempting to add CPU, drc index: %x\n", drc_index);
409 413
410 parent = of_find_node_by_path("/cpus"); 414 parent = of_find_node_by_path("/cpus");
411 if (!parent) 415 if (!parent) {
416 pr_warn("Failed to find CPU root node \"/cpus\"\n");
412 return -ENODEV; 417 return -ENODEV;
418 }
413 419
414 if (dlpar_cpu_exists(parent, drc_index)) { 420 if (dlpar_cpu_exists(parent, drc_index)) {
415 of_node_put(parent); 421 of_node_put(parent);
416 printk(KERN_WARNING "CPU with drc index %x already exists\n", 422 pr_warn("CPU with drc index %x already exists\n", drc_index);
417 drc_index);
418 return -EINVAL; 423 return -EINVAL;
419 } 424 }
420 425
421 rc = dlpar_acquire_drc(drc_index); 426 rc = dlpar_acquire_drc(drc_index);
422 if (rc) { 427 if (rc) {
428 pr_warn("Failed to acquire DRC, rc: %d, drc index: %x\n",
429 rc, drc_index);
423 of_node_put(parent); 430 of_node_put(parent);
424 return -EINVAL; 431 return -EINVAL;
425 } 432 }
426 433
427 dn = dlpar_configure_connector(cpu_to_be32(drc_index), parent); 434 dn = dlpar_configure_connector(cpu_to_be32(drc_index), parent);
428 of_node_put(parent); 435 of_node_put(parent);
429 if (!dn) 436 if (!dn) {
437 pr_warn("Failed call to configure-connector, drc index: %x\n",
438 drc_index);
439 dlpar_release_drc(drc_index);
430 return -EINVAL; 440 return -EINVAL;
441 }
431 442
432 rc = dlpar_attach_node(dn); 443 rc = dlpar_attach_node(dn);
433 if (rc) { 444 if (rc) {
434 dlpar_release_drc(drc_index); 445 saved_rc = rc;
435 dlpar_free_cc_nodes(dn); 446 pr_warn("Failed to attach node %s, rc: %d, drc index: %x\n",
436 return rc; 447 dn->name, rc, drc_index);
448
449 rc = dlpar_release_drc(drc_index);
450 if (!rc)
451 dlpar_free_cc_nodes(dn);
452
453 return saved_rc;
437 } 454 }
438 455
439 rc = dlpar_online_cpu(dn); 456 rc = dlpar_online_cpu(dn);
457 if (rc) {
458 saved_rc = rc;
459 pr_warn("Failed to online cpu %s, rc: %d, drc index: %x\n",
460 dn->name, rc, drc_index);
461
462 rc = dlpar_detach_node(dn);
463 if (!rc)
464 dlpar_release_drc(drc_index);
465
466 return saved_rc;
467 }
468
469 pr_debug("Successfully added CPU %s, drc index: %x\n", dn->name,
470 drc_index);
440 return rc; 471 return rc;
441} 472}
442 473
@@ -500,19 +531,38 @@ static ssize_t dlpar_cpu_remove(struct device_node *dn, u32 drc_index)
500{ 531{
501 int rc; 532 int rc;
502 533
534 pr_debug("Attemping to remove CPU %s, drc index: %x\n",
535 dn->name, drc_index);
536
503 rc = dlpar_offline_cpu(dn); 537 rc = dlpar_offline_cpu(dn);
504 if (rc) 538 if (rc) {
539 pr_warn("Failed to offline CPU %s, rc: %d\n", dn->name, rc);
505 return -EINVAL; 540 return -EINVAL;
541 }
506 542
507 rc = dlpar_release_drc(drc_index); 543 rc = dlpar_release_drc(drc_index);
508 if (rc) 544 if (rc) {
545 pr_warn("Failed to release drc (%x) for CPU %s, rc: %d\n",
546 drc_index, dn->name, rc);
547 dlpar_online_cpu(dn);
509 return rc; 548 return rc;
549 }
510 550
511 rc = dlpar_detach_node(dn); 551 rc = dlpar_detach_node(dn);
512 if (rc) 552 if (rc) {
513 dlpar_acquire_drc(drc_index); 553 int saved_rc = rc;
514 554
515 return rc; 555 pr_warn("Failed to detach CPU %s, rc: %d", dn->name, rc);
556
557 rc = dlpar_acquire_drc(drc_index);
558 if (!rc)
559 dlpar_online_cpu(dn);
560
561 return saved_rc;
562 }
563
564 pr_debug("Successfully removed CPU, drc index: %x\n", drc_index);
565 return 0;
516} 566}
517 567
518#ifdef CONFIG_ARCH_CPU_PROBE_RELEASE 568#ifdef CONFIG_ARCH_CPU_PROBE_RELEASE