linux/arch/powerpc/platforms/pseries/hotplug-cpu.c
<<
>>
Prefs
   1/*
   2 * pseries CPU Hotplug infrastructure.
   3 *
   4 * Split out from arch/powerpc/platforms/pseries/setup.c
   5 *  arch/powerpc/kernel/rtas.c, and arch/powerpc/platforms/pseries/smp.c
   6 *
   7 * Peter Bergner, IBM   March 2001.
   8 * Copyright (C) 2001 IBM.
   9 * Dave Engebretsen, Peter Bergner, and
  10 * Mike Corrigan {engebret|bergner|mikec}@us.ibm.com
  11 * Plus various changes from other IBM teams...
  12 *
  13 * Copyright (C) 2006 Michael Ellerman, IBM Corporation
  14 *
  15 *      This program is free software; you can redistribute it and/or
  16 *      modify it under the terms of the GNU General Public License
  17 *      as published by the Free Software Foundation; either version
  18 *      2 of the License, or (at your option) any later version.
  19 */
  20
  21#define pr_fmt(fmt)     "pseries-hotplug-cpu: " fmt
  22
  23#include <linux/kernel.h>
  24#include <linux/interrupt.h>
  25#include <linux/delay.h>
  26#include <linux/sched.h>        /* for idle_task_exit */
  27#include <linux/sched/hotplug.h>
  28#include <linux/cpu.h>
  29#include <linux/of.h>
  30#include <linux/slab.h>
  31#include <asm/prom.h>
  32#include <asm/rtas.h>
  33#include <asm/firmware.h>
  34#include <asm/machdep.h>
  35#include <asm/vdso_datapage.h>
  36#include <asm/xics.h>
  37#include <asm/xive.h>
  38#include <asm/plpar_wrappers.h>
  39
  40#include "pseries.h"
  41#include "offline_states.h"
  42
  43/* This version can't take the spinlock, because it never returns */
  44static int rtas_stop_self_token = RTAS_UNKNOWN_SERVICE;
  45
  46static DEFINE_PER_CPU(enum cpu_state_vals, preferred_offline_state) =
  47                                                        CPU_STATE_OFFLINE;
  48static DEFINE_PER_CPU(enum cpu_state_vals, current_state) = CPU_STATE_OFFLINE;
  49
  50static enum cpu_state_vals default_offline_state = CPU_STATE_OFFLINE;
  51
  52static bool cede_offline_enabled __read_mostly = true;
  53
  54/*
  55 * Enable/disable cede_offline when available.
  56 */
  57static int __init setup_cede_offline(char *str)
  58{
  59        return (kstrtobool(str, &cede_offline_enabled) == 0);
  60}
  61
  62__setup("cede_offline=", setup_cede_offline);
  63
  64enum cpu_state_vals get_cpu_current_state(int cpu)
  65{
  66        return per_cpu(current_state, cpu);
  67}
  68
  69void set_cpu_current_state(int cpu, enum cpu_state_vals state)
  70{
  71        per_cpu(current_state, cpu) = state;
  72}
  73
  74enum cpu_state_vals get_preferred_offline_state(int cpu)
  75{
  76        return per_cpu(preferred_offline_state, cpu);
  77}
  78
  79void set_preferred_offline_state(int cpu, enum cpu_state_vals state)
  80{
  81        per_cpu(preferred_offline_state, cpu) = state;
  82}
  83
  84void set_default_offline_state(int cpu)
  85{
  86        per_cpu(preferred_offline_state, cpu) = default_offline_state;
  87}
  88
  89static void rtas_stop_self(void)
  90{
  91        static struct rtas_args args;
  92
  93        local_irq_disable();
  94
  95        BUG_ON(rtas_stop_self_token == RTAS_UNKNOWN_SERVICE);
  96
  97        printk("cpu %u (hwid %u) Ready to die...\n",
  98               smp_processor_id(), hard_smp_processor_id());
  99
 100        rtas_call_unlocked(&args, rtas_stop_self_token, 0, 1, NULL);
 101
 102        panic("Alas, I survived.\n");
 103}
 104
 105static void pseries_mach_cpu_die(void)
 106{
 107        unsigned int cpu = smp_processor_id();
 108        unsigned int hwcpu = hard_smp_processor_id();
 109        u8 cede_latency_hint = 0;
 110
 111        local_irq_disable();
 112        idle_task_exit();
 113        if (xive_enabled())
 114                xive_teardown_cpu();
 115        else
 116                xics_teardown_cpu();
 117
 118        if (get_preferred_offline_state(cpu) == CPU_STATE_INACTIVE) {
 119                set_cpu_current_state(cpu, CPU_STATE_INACTIVE);
 120                if (ppc_md.suspend_disable_cpu)
 121                        ppc_md.suspend_disable_cpu();
 122
 123                cede_latency_hint = 2;
 124
 125                get_lppaca()->idle = 1;
 126                if (!lppaca_shared_proc(get_lppaca()))
 127                        get_lppaca()->donate_dedicated_cpu = 1;
 128
 129                while (get_preferred_offline_state(cpu) == CPU_STATE_INACTIVE) {
 130                        while (!prep_irq_for_idle()) {
 131                                local_irq_enable();
 132                                local_irq_disable();
 133                        }
 134
 135                        extended_cede_processor(cede_latency_hint);
 136                }
 137
 138                local_irq_disable();
 139
 140                if (!lppaca_shared_proc(get_lppaca()))
 141                        get_lppaca()->donate_dedicated_cpu = 0;
 142                get_lppaca()->idle = 0;
 143
 144                if (get_preferred_offline_state(cpu) == CPU_STATE_ONLINE) {
 145                        unregister_slb_shadow(hwcpu);
 146
 147                        hard_irq_disable();
 148                        /*
 149                         * Call to start_secondary_resume() will not return.
 150                         * Kernel stack will be reset and start_secondary()
 151                         * will be called to continue the online operation.
 152                         */
 153                        start_secondary_resume();
 154                }
 155        }
 156
 157        /* Requested state is CPU_STATE_OFFLINE at this point */
 158        WARN_ON(get_preferred_offline_state(cpu) != CPU_STATE_OFFLINE);
 159
 160        set_cpu_current_state(cpu, CPU_STATE_OFFLINE);
 161        unregister_slb_shadow(hwcpu);
 162        rtas_stop_self();
 163
 164        /* Should never get here... */
 165        BUG();
 166        for(;;);
 167}
 168
 169static int pseries_cpu_disable(void)
 170{
 171        int cpu = smp_processor_id();
 172
 173        set_cpu_online(cpu, false);
 174        vdso_data->processorCount--;
 175
 176        /*fix boot_cpuid here*/
 177        if (cpu == boot_cpuid)
 178                boot_cpuid = cpumask_any(cpu_online_mask);
 179
 180        /* FIXME: abstract this to not be platform specific later on */
 181        if (xive_enabled())
 182                xive_smp_disable_cpu();
 183        else
 184                xics_migrate_irqs_away();
 185        return 0;
 186}
 187
 188/*
 189 * pseries_cpu_die: Wait for the cpu to die.
 190 * @cpu: logical processor id of the CPU whose death we're awaiting.
 191 *
 192 * This function is called from the context of the thread which is performing
 193 * the cpu-offline. Here we wait for long enough to allow the cpu in question
 194 * to self-destroy so that the cpu-offline thread can send the CPU_DEAD
 195 * notifications.
 196 *
 197 * OTOH, pseries_mach_cpu_die() is called by the @cpu when it wants to
 198 * self-destruct.
 199 */
 200static void pseries_cpu_die(unsigned int cpu)
 201{
 202        int tries;
 203        int cpu_status = 1;
 204        unsigned int pcpu = get_hard_smp_processor_id(cpu);
 205
 206        if (get_preferred_offline_state(cpu) == CPU_STATE_INACTIVE) {
 207                cpu_status = 1;
 208                for (tries = 0; tries < 5000; tries++) {
 209                        if (get_cpu_current_state(cpu) == CPU_STATE_INACTIVE) {
 210                                cpu_status = 0;
 211                                break;
 212                        }
 213                        msleep(1);
 214                }
 215        } else if (get_preferred_offline_state(cpu) == CPU_STATE_OFFLINE) {
 216
 217                for (tries = 0; tries < 25; tries++) {
 218                        cpu_status = smp_query_cpu_stopped(pcpu);
 219                        if (cpu_status == QCSS_STOPPED ||
 220                            cpu_status == QCSS_HARDWARE_ERROR)
 221                                break;
 222                        cpu_relax();
 223                }
 224        }
 225
 226        if (cpu_status != 0) {
 227                printk("Querying DEAD? cpu %i (%i) shows %i\n",
 228                       cpu, pcpu, cpu_status);
 229        }
 230
 231        /* Isolation and deallocation are definitely done by
 232         * drslot_chrp_cpu.  If they were not they would be
 233         * done here.  Change isolate state to Isolate and
 234         * change allocation-state to Unusable.
 235         */
 236        paca[cpu].cpu_start = 0;
 237}
 238
 239/*
 240 * Update cpu_present_mask and paca(s) for a new cpu node.  The wrinkle
 241 * here is that a cpu device node may represent up to two logical cpus
 242 * in the SMT case.  We must honor the assumption in other code that
 243 * the logical ids for sibling SMT threads x and y are adjacent, such
 244 * that x^1 == y and y^1 == x.
 245 */
 246static int pseries_add_processor(struct device_node *np)
 247{
 248        unsigned int cpu;
 249        cpumask_var_t candidate_mask, tmp;
 250        int err = -ENOSPC, len, nthreads, i;
 251        const __be32 *intserv;
 252
 253        intserv = of_get_property(np, "ibm,ppc-interrupt-server#s", &len);
 254        if (!intserv)
 255                return 0;
 256
 257        zalloc_cpumask_var(&candidate_mask, GFP_KERNEL);
 258        zalloc_cpumask_var(&tmp, GFP_KERNEL);
 259
 260        nthreads = len / sizeof(u32);
 261        for (i = 0; i < nthreads; i++)
 262                cpumask_set_cpu(i, tmp);
 263
 264        cpu_maps_update_begin();
 265
 266        BUG_ON(!cpumask_subset(cpu_present_mask, cpu_possible_mask));
 267
 268        /* Get a bitmap of unoccupied slots. */
 269        cpumask_xor(candidate_mask, cpu_possible_mask, cpu_present_mask);
 270        if (cpumask_empty(candidate_mask)) {
 271                /* If we get here, it most likely means that NR_CPUS is
 272                 * less than the partition's max processors setting.
 273                 */
 274                printk(KERN_ERR "Cannot add cpu %pOF; this system configuration"
 275                       " supports %d logical cpus.\n", np,
 276                       num_possible_cpus());
 277                goto out_unlock;
 278        }
 279
 280        while (!cpumask_empty(tmp))
 281                if (cpumask_subset(tmp, candidate_mask))
 282                        /* Found a range where we can insert the new cpu(s) */
 283                        break;
 284                else
 285                        cpumask_shift_left(tmp, tmp, nthreads);
 286
 287        if (cpumask_empty(tmp)) {
 288                printk(KERN_ERR "Unable to find space in cpu_present_mask for"
 289                       " processor %s with %d thread(s)\n", np->name,
 290                       nthreads);
 291                goto out_unlock;
 292        }
 293
 294        for_each_cpu(cpu, tmp) {
 295                BUG_ON(cpu_present(cpu));
 296                set_cpu_present(cpu, true);
 297                set_hard_smp_processor_id(cpu, be32_to_cpu(*intserv++));
 298        }
 299        err = 0;
 300out_unlock:
 301        cpu_maps_update_done();
 302        free_cpumask_var(candidate_mask);
 303        free_cpumask_var(tmp);
 304        return err;
 305}
 306
 307/*
 308 * Update the present map for a cpu node which is going away, and set
 309 * the hard id in the paca(s) to -1 to be consistent with boot time
 310 * convention for non-present cpus.
 311 */
 312static void pseries_remove_processor(struct device_node *np)
 313{
 314        unsigned int cpu;
 315        int len, nthreads, i;
 316        const __be32 *intserv;
 317        u32 thread;
 318
 319        intserv = of_get_property(np, "ibm,ppc-interrupt-server#s", &len);
 320        if (!intserv)
 321                return;
 322
 323        nthreads = len / sizeof(u32);
 324
 325        cpu_maps_update_begin();
 326        for (i = 0; i < nthreads; i++) {
 327                thread = be32_to_cpu(intserv[i]);
 328                for_each_present_cpu(cpu) {
 329                        if (get_hard_smp_processor_id(cpu) != thread)
 330                                continue;
 331                        BUG_ON(cpu_online(cpu));
 332                        set_cpu_present(cpu, false);
 333                        set_hard_smp_processor_id(cpu, -1);
 334                        break;
 335                }
 336                if (cpu >= nr_cpu_ids)
 337                        printk(KERN_WARNING "Could not find cpu to remove "
 338                               "with physical id 0x%x\n", thread);
 339        }
 340        cpu_maps_update_done();
 341}
 342
 343static int dlpar_online_cpu(struct device_node *dn)
 344{
 345        int rc = 0;
 346        unsigned int cpu;
 347        int len, nthreads, i;
 348        const __be32 *intserv;
 349        u32 thread;
 350
 351        intserv = of_get_property(dn, "ibm,ppc-interrupt-server#s", &len);
 352        if (!intserv)
 353                return -EINVAL;
 354
 355        nthreads = len / sizeof(u32);
 356
 357        cpu_maps_update_begin();
 358        for (i = 0; i < nthreads; i++) {
 359                thread = be32_to_cpu(intserv[i]);
 360                for_each_present_cpu(cpu) {
 361                        if (get_hard_smp_processor_id(cpu) != thread)
 362                                continue;
 363                        BUG_ON(get_cpu_current_state(cpu)
 364                                        != CPU_STATE_OFFLINE);
 365                        cpu_maps_update_done();
 366                        timed_topology_update(1);
 367                        rc = device_online(get_cpu_device(cpu));
 368                        if (rc)
 369                                goto out;
 370                        cpu_maps_update_begin();
 371
 372                        break;
 373                }
 374                if (cpu == num_possible_cpus())
 375                        printk(KERN_WARNING "Could not find cpu to online "
 376                               "with physical id 0x%x\n", thread);
 377        }
 378        cpu_maps_update_done();
 379
 380out:
 381        return rc;
 382
 383}
 384
 385static bool dlpar_cpu_exists(struct device_node *parent, u32 drc_index)
 386{
 387        struct device_node *child = NULL;
 388        u32 my_drc_index;
 389        bool found;
 390        int rc;
 391
 392        /* Assume cpu doesn't exist */
 393        found = false;
 394
 395        for_each_child_of_node(parent, child) {
 396                rc = of_property_read_u32(child, "ibm,my-drc-index",
 397                                          &my_drc_index);
 398                if (rc)
 399                        continue;
 400
 401                if (my_drc_index == drc_index) {
 402                        of_node_put(child);
 403                        found = true;
 404                        break;
 405                }
 406        }
 407
 408        return found;
 409}
 410
 411static bool valid_cpu_drc_index(struct device_node *parent, u32 drc_index)
 412{
 413        bool found = false;
 414        int rc, index;
 415
 416        index = 0;
 417        while (!found) {
 418                u32 drc;
 419
 420                rc = of_property_read_u32_index(parent, "ibm,drc-indexes",
 421                                                index++, &drc);
 422                if (rc)
 423                        break;
 424
 425                if (drc == drc_index)
 426                        found = true;
 427        }
 428
 429        return found;
 430}
 431
 432static ssize_t dlpar_cpu_add(u32 drc_index)
 433{
 434        struct device_node *dn, *parent;
 435        int rc, saved_rc;
 436
 437        pr_debug("Attempting to add CPU, drc index: %x\n", drc_index);
 438
 439        parent = of_find_node_by_path("/cpus");
 440        if (!parent) {
 441                pr_warn("Failed to find CPU root node \"/cpus\"\n");
 442                return -ENODEV;
 443        }
 444
 445        if (dlpar_cpu_exists(parent, drc_index)) {
 446                of_node_put(parent);
 447                pr_warn("CPU with drc index %x already exists\n", drc_index);
 448                return -EINVAL;
 449        }
 450
 451        if (!valid_cpu_drc_index(parent, drc_index)) {
 452                of_node_put(parent);
 453                pr_warn("Cannot find CPU (drc index %x) to add.\n", drc_index);
 454                return -EINVAL;
 455        }
 456
 457        rc = dlpar_acquire_drc(drc_index);
 458        if (rc) {
 459                pr_warn("Failed to acquire DRC, rc: %d, drc index: %x\n",
 460                        rc, drc_index);
 461                of_node_put(parent);
 462                return -EINVAL;
 463        }
 464
 465        dn = dlpar_configure_connector(cpu_to_be32(drc_index), parent);
 466        if (!dn) {
 467                pr_warn("Failed call to configure-connector, drc index: %x\n",
 468                        drc_index);
 469                dlpar_release_drc(drc_index);
 470                of_node_put(parent);
 471                return -EINVAL;
 472        }
 473
 474        rc = dlpar_attach_node(dn, parent);
 475
 476        /* Regardless we are done with parent now */
 477        of_node_put(parent);
 478
 479        if (rc) {
 480                saved_rc = rc;
 481                pr_warn("Failed to attach node %s, rc: %d, drc index: %x\n",
 482                        dn->name, rc, drc_index);
 483
 484                rc = dlpar_release_drc(drc_index);
 485                if (!rc)
 486                        dlpar_free_cc_nodes(dn);
 487
 488                return saved_rc;
 489        }
 490
 491        rc = dlpar_online_cpu(dn);
 492        if (rc) {
 493                saved_rc = rc;
 494                pr_warn("Failed to online cpu %s, rc: %d, drc index: %x\n",
 495                        dn->name, rc, drc_index);
 496
 497                rc = dlpar_detach_node(dn);
 498                if (!rc)
 499                        dlpar_release_drc(drc_index);
 500
 501                return saved_rc;
 502        }
 503
 504        pr_debug("Successfully added CPU %s, drc index: %x\n", dn->name,
 505                 drc_index);
 506        return rc;
 507}
 508
 509static int dlpar_offline_cpu(struct device_node *dn)
 510{
 511        int rc = 0;
 512        unsigned int cpu;
 513        int len, nthreads, i;
 514        const __be32 *intserv;
 515        u32 thread;
 516
 517        intserv = of_get_property(dn, "ibm,ppc-interrupt-server#s", &len);
 518        if (!intserv)
 519                return -EINVAL;
 520
 521        nthreads = len / sizeof(u32);
 522
 523        cpu_maps_update_begin();
 524        for (i = 0; i < nthreads; i++) {
 525                thread = be32_to_cpu(intserv[i]);
 526                for_each_present_cpu(cpu) {
 527                        if (get_hard_smp_processor_id(cpu) != thread)
 528                                continue;
 529
 530                        if (get_cpu_current_state(cpu) == CPU_STATE_OFFLINE)
 531                                break;
 532
 533                        if (get_cpu_current_state(cpu) == CPU_STATE_ONLINE) {
 534                                set_preferred_offline_state(cpu,
 535                                                            CPU_STATE_OFFLINE);
 536                                cpu_maps_update_done();
 537                                timed_topology_update(1);
 538                                rc = device_offline(get_cpu_device(cpu));
 539                                if (rc)
 540                                        goto out;
 541                                cpu_maps_update_begin();
 542                                break;
 543
 544                        }
 545
 546                        /*
 547                         * The cpu is in CPU_STATE_INACTIVE.
 548                         * Upgrade it's state to CPU_STATE_OFFLINE.
 549                         */
 550                        set_preferred_offline_state(cpu, CPU_STATE_OFFLINE);
 551                        BUG_ON(plpar_hcall_norets(H_PROD, thread)
 552                                                                != H_SUCCESS);
 553                        __cpu_die(cpu);
 554                        break;
 555                }
 556                if (cpu == num_possible_cpus())
 557                        printk(KERN_WARNING "Could not find cpu to offline with physical id 0x%x\n", thread);
 558        }
 559        cpu_maps_update_done();
 560
 561out:
 562        return rc;
 563
 564}
 565
 566static ssize_t dlpar_cpu_remove(struct device_node *dn, u32 drc_index)
 567{
 568        int rc;
 569
 570        pr_debug("Attempting to remove CPU %s, drc index: %x\n",
 571                 dn->name, drc_index);
 572
 573        rc = dlpar_offline_cpu(dn);
 574        if (rc) {
 575                pr_warn("Failed to offline CPU %s, rc: %d\n", dn->name, rc);
 576                return -EINVAL;
 577        }
 578
 579        rc = dlpar_release_drc(drc_index);
 580        if (rc) {
 581                pr_warn("Failed to release drc (%x) for CPU %s, rc: %d\n",
 582                        drc_index, dn->name, rc);
 583                dlpar_online_cpu(dn);
 584                return rc;
 585        }
 586
 587        rc = dlpar_detach_node(dn);
 588        if (rc) {
 589                int saved_rc = rc;
 590
 591                pr_warn("Failed to detach CPU %s, rc: %d", dn->name, rc);
 592
 593                rc = dlpar_acquire_drc(drc_index);
 594                if (!rc)
 595                        dlpar_online_cpu(dn);
 596
 597                return saved_rc;
 598        }
 599
 600        pr_debug("Successfully removed CPU, drc index: %x\n", drc_index);
 601        return 0;
 602}
 603
 604static struct device_node *cpu_drc_index_to_dn(u32 drc_index)
 605{
 606        struct device_node *dn;
 607        u32 my_index;
 608        int rc;
 609
 610        for_each_node_by_type(dn, "cpu") {
 611                rc = of_property_read_u32(dn, "ibm,my-drc-index", &my_index);
 612                if (rc)
 613                        continue;
 614
 615                if (my_index == drc_index)
 616                        break;
 617        }
 618
 619        return dn;
 620}
 621
 622static int dlpar_cpu_remove_by_index(u32 drc_index)
 623{
 624        struct device_node *dn;
 625        int rc;
 626
 627        dn = cpu_drc_index_to_dn(drc_index);
 628        if (!dn) {
 629                pr_warn("Cannot find CPU (drc index %x) to remove\n",
 630                        drc_index);
 631                return -ENODEV;
 632        }
 633
 634        rc = dlpar_cpu_remove(dn, drc_index);
 635        of_node_put(dn);
 636        return rc;
 637}
 638
 639static int find_dlpar_cpus_to_remove(u32 *cpu_drcs, int cpus_to_remove)
 640{
 641        struct device_node *dn;
 642        int cpus_found = 0;
 643        int rc;
 644
 645        /* We want to find cpus_to_remove + 1 CPUs to ensure we do not
 646         * remove the last CPU.
 647         */
 648        for_each_node_by_type(dn, "cpu") {
 649                cpus_found++;
 650
 651                if (cpus_found > cpus_to_remove) {
 652                        of_node_put(dn);
 653                        break;
 654                }
 655
 656                /* Note that cpus_found is always 1 ahead of the index
 657                 * into the cpu_drcs array, so we use cpus_found - 1
 658                 */
 659                rc = of_property_read_u32(dn, "ibm,my-drc-index",
 660                                          &cpu_drcs[cpus_found - 1]);
 661                if (rc) {
 662                        pr_warn("Error occurred getting drc-index for %s\n",
 663                                dn->name);
 664                        of_node_put(dn);
 665                        return -1;
 666                }
 667        }
 668
 669        if (cpus_found < cpus_to_remove) {
 670                pr_warn("Failed to find enough CPUs (%d of %d) to remove\n",
 671                        cpus_found, cpus_to_remove);
 672        } else if (cpus_found == cpus_to_remove) {
 673                pr_warn("Cannot remove all CPUs\n");
 674        }
 675
 676        return cpus_found;
 677}
 678
 679static int dlpar_cpu_remove_by_count(u32 cpus_to_remove)
 680{
 681        u32 *cpu_drcs;
 682        int cpus_found;
 683        int cpus_removed = 0;
 684        int i, rc;
 685
 686        pr_debug("Attempting to hot-remove %d CPUs\n", cpus_to_remove);
 687
 688        cpu_drcs = kcalloc(cpus_to_remove, sizeof(*cpu_drcs), GFP_KERNEL);
 689        if (!cpu_drcs)
 690                return -EINVAL;
 691
 692        cpus_found = find_dlpar_cpus_to_remove(cpu_drcs, cpus_to_remove);
 693        if (cpus_found <= cpus_to_remove) {
 694                kfree(cpu_drcs);
 695                return -EINVAL;
 696        }
 697
 698        for (i = 0; i < cpus_to_remove; i++) {
 699                rc = dlpar_cpu_remove_by_index(cpu_drcs[i]);
 700                if (rc)
 701                        break;
 702
 703                cpus_removed++;
 704        }
 705
 706        if (cpus_removed != cpus_to_remove) {
 707                pr_warn("CPU hot-remove failed, adding back removed CPUs\n");
 708
 709                for (i = 0; i < cpus_removed; i++)
 710                        dlpar_cpu_add(cpu_drcs[i]);
 711
 712                rc = -EINVAL;
 713        } else {
 714                rc = 0;
 715        }
 716
 717        kfree(cpu_drcs);
 718        return rc;
 719}
 720
 721static int find_dlpar_cpus_to_add(u32 *cpu_drcs, u32 cpus_to_add)
 722{
 723        struct device_node *parent;
 724        int cpus_found = 0;
 725        int index, rc;
 726
 727        parent = of_find_node_by_path("/cpus");
 728        if (!parent) {
 729                pr_warn("Could not find CPU root node in device tree\n");
 730                kfree(cpu_drcs);
 731                return -1;
 732        }
 733
 734        /* Search the ibm,drc-indexes array for possible CPU drcs to
 735         * add. Note that the format of the ibm,drc-indexes array is
 736         * the number of entries in the array followed by the array
 737         * of drc values so we start looking at index = 1.
 738         */
 739        index = 1;
 740        while (cpus_found < cpus_to_add) {
 741                u32 drc;
 742
 743                rc = of_property_read_u32_index(parent, "ibm,drc-indexes",
 744                                                index++, &drc);
 745                if (rc)
 746                        break;
 747
 748                if (dlpar_cpu_exists(parent, drc))
 749                        continue;
 750
 751                cpu_drcs[cpus_found++] = drc;
 752        }
 753
 754        of_node_put(parent);
 755        return cpus_found;
 756}
 757
 758static int dlpar_cpu_add_by_count(u32 cpus_to_add)
 759{
 760        u32 *cpu_drcs;
 761        int cpus_added = 0;
 762        int cpus_found;
 763        int i, rc;
 764
 765        pr_debug("Attempting to hot-add %d CPUs\n", cpus_to_add);
 766
 767        cpu_drcs = kcalloc(cpus_to_add, sizeof(*cpu_drcs), GFP_KERNEL);
 768        if (!cpu_drcs)
 769                return -EINVAL;
 770
 771        cpus_found = find_dlpar_cpus_to_add(cpu_drcs, cpus_to_add);
 772        if (cpus_found < cpus_to_add) {
 773                pr_warn("Failed to find enough CPUs (%d of %d) to add\n",
 774                        cpus_found, cpus_to_add);
 775                kfree(cpu_drcs);
 776                return -EINVAL;
 777        }
 778
 779        for (i = 0; i < cpus_to_add; i++) {
 780                rc = dlpar_cpu_add(cpu_drcs[i]);
 781                if (rc)
 782                        break;
 783
 784                cpus_added++;
 785        }
 786
 787        if (cpus_added < cpus_to_add) {
 788                pr_warn("CPU hot-add failed, removing any added CPUs\n");
 789
 790                for (i = 0; i < cpus_added; i++)
 791                        dlpar_cpu_remove_by_index(cpu_drcs[i]);
 792
 793                rc = -EINVAL;
 794        } else {
 795                rc = 0;
 796        }
 797
 798        kfree(cpu_drcs);
 799        return rc;
 800}
 801
 802int dlpar_cpu(struct pseries_hp_errorlog *hp_elog)
 803{
 804        u32 count, drc_index;
 805        int rc;
 806
 807        count = hp_elog->_drc_u.drc_count;
 808        drc_index = hp_elog->_drc_u.drc_index;
 809
 810        lock_device_hotplug();
 811
 812        switch (hp_elog->action) {
 813        case PSERIES_HP_ELOG_ACTION_REMOVE:
 814                if (hp_elog->id_type == PSERIES_HP_ELOG_ID_DRC_COUNT)
 815                        rc = dlpar_cpu_remove_by_count(count);
 816                else if (hp_elog->id_type == PSERIES_HP_ELOG_ID_DRC_INDEX)
 817                        rc = dlpar_cpu_remove_by_index(drc_index);
 818                else
 819                        rc = -EINVAL;
 820                break;
 821        case PSERIES_HP_ELOG_ACTION_ADD:
 822                if (hp_elog->id_type == PSERIES_HP_ELOG_ID_DRC_COUNT)
 823                        rc = dlpar_cpu_add_by_count(count);
 824                else if (hp_elog->id_type == PSERIES_HP_ELOG_ID_DRC_INDEX)
 825                        rc = dlpar_cpu_add(drc_index);
 826                else
 827                        rc = -EINVAL;
 828                break;
 829        default:
 830                pr_err("Invalid action (%d) specified\n", hp_elog->action);
 831                rc = -EINVAL;
 832                break;
 833        }
 834
 835        unlock_device_hotplug();
 836        return rc;
 837}
 838
 839#ifdef CONFIG_ARCH_CPU_PROBE_RELEASE
 840
 841static ssize_t dlpar_cpu_probe(const char *buf, size_t count)
 842{
 843        u32 drc_index;
 844        int rc;
 845
 846        rc = kstrtou32(buf, 0, &drc_index);
 847        if (rc)
 848                return -EINVAL;
 849
 850        rc = dlpar_cpu_add(drc_index);
 851
 852        return rc ? rc : count;
 853}
 854
 855static ssize_t dlpar_cpu_release(const char *buf, size_t count)
 856{
 857        struct device_node *dn;
 858        u32 drc_index;
 859        int rc;
 860
 861        dn = of_find_node_by_path(buf);
 862        if (!dn)
 863                return -EINVAL;
 864
 865        rc = of_property_read_u32(dn, "ibm,my-drc-index", &drc_index);
 866        if (rc) {
 867                of_node_put(dn);
 868                return -EINVAL;
 869        }
 870
 871        rc = dlpar_cpu_remove(dn, drc_index);
 872        of_node_put(dn);
 873
 874        return rc ? rc : count;
 875}
 876
 877#endif /* CONFIG_ARCH_CPU_PROBE_RELEASE */
 878
 879static int pseries_smp_notifier(struct notifier_block *nb,
 880                                unsigned long action, void *data)
 881{
 882        struct of_reconfig_data *rd = data;
 883        int err = 0;
 884
 885        switch (action) {
 886        case OF_RECONFIG_ATTACH_NODE:
 887                err = pseries_add_processor(rd->dn);
 888                break;
 889        case OF_RECONFIG_DETACH_NODE:
 890                pseries_remove_processor(rd->dn);
 891                break;
 892        }
 893        return notifier_from_errno(err);
 894}
 895
 896static struct notifier_block pseries_smp_nb = {
 897        .notifier_call = pseries_smp_notifier,
 898};
 899
 900#define MAX_CEDE_LATENCY_LEVELS         4
 901#define CEDE_LATENCY_PARAM_LENGTH       10
 902#define CEDE_LATENCY_PARAM_MAX_LENGTH   \
 903        (MAX_CEDE_LATENCY_LEVELS * CEDE_LATENCY_PARAM_LENGTH * sizeof(char))
 904#define CEDE_LATENCY_TOKEN              45
 905
 906static char cede_parameters[CEDE_LATENCY_PARAM_MAX_LENGTH];
 907
 908static int parse_cede_parameters(void)
 909{
 910        memset(cede_parameters, 0, CEDE_LATENCY_PARAM_MAX_LENGTH);
 911        return rtas_call(rtas_token("ibm,get-system-parameter"), 3, 1,
 912                         NULL,
 913                         CEDE_LATENCY_TOKEN,
 914                         __pa(cede_parameters),
 915                         CEDE_LATENCY_PARAM_MAX_LENGTH);
 916}
 917
 918static int __init pseries_cpu_hotplug_init(void)
 919{
 920        int cpu;
 921        int qcss_tok;
 922
 923#ifdef CONFIG_ARCH_CPU_PROBE_RELEASE
 924        ppc_md.cpu_probe = dlpar_cpu_probe;
 925        ppc_md.cpu_release = dlpar_cpu_release;
 926#endif /* CONFIG_ARCH_CPU_PROBE_RELEASE */
 927
 928        rtas_stop_self_token = rtas_token("stop-self");
 929        qcss_tok = rtas_token("query-cpu-stopped-state");
 930
 931        if (rtas_stop_self_token == RTAS_UNKNOWN_SERVICE ||
 932                        qcss_tok == RTAS_UNKNOWN_SERVICE) {
 933                printk(KERN_INFO "CPU Hotplug not supported by firmware "
 934                                "- disabling.\n");
 935                return 0;
 936        }
 937
 938        ppc_md.cpu_die = pseries_mach_cpu_die;
 939        smp_ops->cpu_disable = pseries_cpu_disable;
 940        smp_ops->cpu_die = pseries_cpu_die;
 941
 942        /* Processors can be added/removed only on LPAR */
 943        if (firmware_has_feature(FW_FEATURE_LPAR)) {
 944                of_reconfig_notifier_register(&pseries_smp_nb);
 945                cpu_maps_update_begin();
 946                if (cede_offline_enabled && parse_cede_parameters() == 0) {
 947                        default_offline_state = CPU_STATE_INACTIVE;
 948                        for_each_online_cpu(cpu)
 949                                set_default_offline_state(cpu);
 950                }
 951                cpu_maps_update_done();
 952        }
 953
 954        return 0;
 955}
 956machine_arch_initcall(pseries, pseries_cpu_hotplug_init);
 957