linux/drivers/pci/hotplug/pnv_php.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * PCI Hotplug Driver for PowerPC PowerNV platform.
   4 *
   5 * Copyright Gavin Shan, IBM Corporation 2016.
   6 */
   7
   8#include <linux/libfdt.h>
   9#include <linux/module.h>
  10#include <linux/pci.h>
  11#include <linux/pci_hotplug.h>
  12
  13#include <asm/opal.h>
  14#include <asm/pnv-pci.h>
  15#include <asm/ppc-pci.h>
  16
  17#define DRIVER_VERSION  "0.1"
  18#define DRIVER_AUTHOR   "Gavin Shan, IBM Corporation"
  19#define DRIVER_DESC     "PowerPC PowerNV PCI Hotplug Driver"
  20
  21struct pnv_php_event {
  22        bool                    added;
  23        struct pnv_php_slot     *php_slot;
  24        struct work_struct      work;
  25};
  26
  27static LIST_HEAD(pnv_php_slot_list);
  28static DEFINE_SPINLOCK(pnv_php_lock);
  29
  30static void pnv_php_register(struct device_node *dn);
  31static void pnv_php_unregister_one(struct device_node *dn);
  32static void pnv_php_unregister(struct device_node *dn);
  33
  34static void pnv_php_disable_irq(struct pnv_php_slot *php_slot,
  35                                bool disable_device)
  36{
  37        struct pci_dev *pdev = php_slot->pdev;
  38        int irq = php_slot->irq;
  39        u16 ctrl;
  40
  41        if (php_slot->irq > 0) {
  42                pcie_capability_read_word(pdev, PCI_EXP_SLTCTL, &ctrl);
  43                ctrl &= ~(PCI_EXP_SLTCTL_HPIE |
  44                          PCI_EXP_SLTCTL_PDCE |
  45                          PCI_EXP_SLTCTL_DLLSCE);
  46                pcie_capability_write_word(pdev, PCI_EXP_SLTCTL, ctrl);
  47
  48                free_irq(php_slot->irq, php_slot);
  49                php_slot->irq = 0;
  50        }
  51
  52        if (php_slot->wq) {
  53                destroy_workqueue(php_slot->wq);
  54                php_slot->wq = NULL;
  55        }
  56
  57        if (disable_device || irq > 0) {
  58                if (pdev->msix_enabled)
  59                        pci_disable_msix(pdev);
  60                else if (pdev->msi_enabled)
  61                        pci_disable_msi(pdev);
  62
  63                pci_disable_device(pdev);
  64        }
  65}
  66
  67static void pnv_php_free_slot(struct kref *kref)
  68{
  69        struct pnv_php_slot *php_slot = container_of(kref,
  70                                        struct pnv_php_slot, kref);
  71
  72        WARN_ON(!list_empty(&php_slot->children));
  73        pnv_php_disable_irq(php_slot, false);
  74        kfree(php_slot->name);
  75        kfree(php_slot);
  76}
  77
  78static inline void pnv_php_put_slot(struct pnv_php_slot *php_slot)
  79{
  80
  81        if (!php_slot)
  82                return;
  83
  84        kref_put(&php_slot->kref, pnv_php_free_slot);
  85}
  86
  87static struct pnv_php_slot *pnv_php_match(struct device_node *dn,
  88                                          struct pnv_php_slot *php_slot)
  89{
  90        struct pnv_php_slot *target, *tmp;
  91
  92        if (php_slot->dn == dn) {
  93                kref_get(&php_slot->kref);
  94                return php_slot;
  95        }
  96
  97        list_for_each_entry(tmp, &php_slot->children, link) {
  98                target = pnv_php_match(dn, tmp);
  99                if (target)
 100                        return target;
 101        }
 102
 103        return NULL;
 104}
 105
 106struct pnv_php_slot *pnv_php_find_slot(struct device_node *dn)
 107{
 108        struct pnv_php_slot *php_slot, *tmp;
 109        unsigned long flags;
 110
 111        spin_lock_irqsave(&pnv_php_lock, flags);
 112        list_for_each_entry(tmp, &pnv_php_slot_list, link) {
 113                php_slot = pnv_php_match(dn, tmp);
 114                if (php_slot) {
 115                        spin_unlock_irqrestore(&pnv_php_lock, flags);
 116                        return php_slot;
 117                }
 118        }
 119        spin_unlock_irqrestore(&pnv_php_lock, flags);
 120
 121        return NULL;
 122}
 123EXPORT_SYMBOL_GPL(pnv_php_find_slot);
 124
 125/*
 126 * Remove pdn for all children of the indicated device node.
 127 * The function should remove pdn in a depth-first manner.
 128 */
 129static void pnv_php_rmv_pdns(struct device_node *dn)
 130{
 131        struct device_node *child;
 132
 133        for_each_child_of_node(dn, child) {
 134                pnv_php_rmv_pdns(child);
 135
 136                pci_remove_device_node_info(child);
 137        }
 138}
 139
 140/*
 141 * Detach all child nodes of the indicated device nodes. The
 142 * function should handle device nodes in depth-first manner.
 143 *
 144 * We should not invoke of_node_release() as the memory for
 145 * individual device node is part of large memory block. The
 146 * large block is allocated from memblock (system bootup) or
 147 * kmalloc() when unflattening the device tree by OF changeset.
 148 * We can not free the large block allocated from memblock. For
 149 * later case, it should be released at once.
 150 */
 151static void pnv_php_detach_device_nodes(struct device_node *parent)
 152{
 153        struct device_node *dn;
 154        int refcount;
 155
 156        for_each_child_of_node(parent, dn) {
 157                pnv_php_detach_device_nodes(dn);
 158
 159                of_node_put(dn);
 160                refcount = kref_read(&dn->kobj.kref);
 161                if (refcount != 1)
 162                        pr_warn("Invalid refcount %d on <%pOF>\n",
 163                                refcount, dn);
 164
 165                of_detach_node(dn);
 166        }
 167}
 168
 169static void pnv_php_rmv_devtree(struct pnv_php_slot *php_slot)
 170{
 171        pnv_php_rmv_pdns(php_slot->dn);
 172
 173        /*
 174         * Decrease the refcount if the device nodes were created
 175         * through OF changeset before detaching them.
 176         */
 177        if (php_slot->fdt)
 178                of_changeset_destroy(&php_slot->ocs);
 179        pnv_php_detach_device_nodes(php_slot->dn);
 180
 181        if (php_slot->fdt) {
 182                kfree(php_slot->dt);
 183                kfree(php_slot->fdt);
 184                php_slot->dt        = NULL;
 185                php_slot->dn->child = NULL;
 186                php_slot->fdt       = NULL;
 187        }
 188}
 189
 190/*
 191 * As the nodes in OF changeset are applied in reverse order, we
 192 * need revert the nodes in advance so that we have correct node
 193 * order after the changeset is applied.
 194 */
 195static void pnv_php_reverse_nodes(struct device_node *parent)
 196{
 197        struct device_node *child, *next;
 198
 199        /* In-depth first */
 200        for_each_child_of_node(parent, child)
 201                pnv_php_reverse_nodes(child);
 202
 203        /* Reverse the nodes in the child list */
 204        child = parent->child;
 205        parent->child = NULL;
 206        while (child) {
 207                next = child->sibling;
 208
 209                child->sibling = parent->child;
 210                parent->child = child;
 211                child = next;
 212        }
 213}
 214
 215static int pnv_php_populate_changeset(struct of_changeset *ocs,
 216                                      struct device_node *dn)
 217{
 218        struct device_node *child;
 219        int ret = 0;
 220
 221        for_each_child_of_node(dn, child) {
 222                ret = of_changeset_attach_node(ocs, child);
 223                if (ret)
 224                        break;
 225
 226                ret = pnv_php_populate_changeset(ocs, child);
 227                if (ret)
 228                        break;
 229        }
 230
 231        return ret;
 232}
 233
 234static void *pnv_php_add_one_pdn(struct device_node *dn, void *data)
 235{
 236        struct pci_controller *hose = (struct pci_controller *)data;
 237        struct pci_dn *pdn;
 238
 239        pdn = pci_add_device_node_info(hose, dn);
 240        if (!pdn)
 241                return ERR_PTR(-ENOMEM);
 242
 243        return NULL;
 244}
 245
 246static void pnv_php_add_pdns(struct pnv_php_slot *slot)
 247{
 248        struct pci_controller *hose = pci_bus_to_host(slot->bus);
 249
 250        pci_traverse_device_nodes(slot->dn, pnv_php_add_one_pdn, hose);
 251}
 252
 253static int pnv_php_add_devtree(struct pnv_php_slot *php_slot)
 254{
 255        void *fdt, *fdt1, *dt;
 256        int ret;
 257
 258        /* We don't know the FDT blob size. We try to get it through
 259         * maximal memory chunk and then copy it to another chunk that
 260         * fits the real size.
 261         */
 262        fdt1 = kzalloc(0x10000, GFP_KERNEL);
 263        if (!fdt1) {
 264                ret = -ENOMEM;
 265                goto out;
 266        }
 267
 268        ret = pnv_pci_get_device_tree(php_slot->dn->phandle, fdt1, 0x10000);
 269        if (ret) {
 270                pci_warn(php_slot->pdev, "Error %d getting FDT blob\n", ret);
 271                goto free_fdt1;
 272        }
 273
 274        fdt = kzalloc(fdt_totalsize(fdt1), GFP_KERNEL);
 275        if (!fdt) {
 276                ret = -ENOMEM;
 277                goto free_fdt1;
 278        }
 279
 280        /* Unflatten device tree blob */
 281        memcpy(fdt, fdt1, fdt_totalsize(fdt1));
 282        dt = of_fdt_unflatten_tree(fdt, php_slot->dn, NULL);
 283        if (!dt) {
 284                ret = -EINVAL;
 285                pci_warn(php_slot->pdev, "Cannot unflatten FDT\n");
 286                goto free_fdt;
 287        }
 288
 289        /* Initialize and apply the changeset */
 290        of_changeset_init(&php_slot->ocs);
 291        pnv_php_reverse_nodes(php_slot->dn);
 292        ret = pnv_php_populate_changeset(&php_slot->ocs, php_slot->dn);
 293        if (ret) {
 294                pnv_php_reverse_nodes(php_slot->dn);
 295                pci_warn(php_slot->pdev, "Error %d populating changeset\n",
 296                         ret);
 297                goto free_dt;
 298        }
 299
 300        php_slot->dn->child = NULL;
 301        ret = of_changeset_apply(&php_slot->ocs);
 302        if (ret) {
 303                pci_warn(php_slot->pdev, "Error %d applying changeset\n", ret);
 304                goto destroy_changeset;
 305        }
 306
 307        /* Add device node firmware data */
 308        pnv_php_add_pdns(php_slot);
 309        php_slot->fdt = fdt;
 310        php_slot->dt  = dt;
 311        kfree(fdt1);
 312        goto out;
 313
 314destroy_changeset:
 315        of_changeset_destroy(&php_slot->ocs);
 316free_dt:
 317        kfree(dt);
 318        php_slot->dn->child = NULL;
 319free_fdt:
 320        kfree(fdt);
 321free_fdt1:
 322        kfree(fdt1);
 323out:
 324        return ret;
 325}
 326
 327int pnv_php_set_slot_power_state(struct hotplug_slot *slot,
 328                                 uint8_t state)
 329{
 330        struct pnv_php_slot *php_slot = slot->private;
 331        struct opal_msg msg;
 332        int ret;
 333
 334        ret = pnv_pci_set_power_state(php_slot->id, state, &msg);
 335        if (ret > 0) {
 336                if (be64_to_cpu(msg.params[1]) != php_slot->dn->phandle ||
 337                    be64_to_cpu(msg.params[2]) != state                 ||
 338                    be64_to_cpu(msg.params[3]) != OPAL_SUCCESS) {
 339                        pci_warn(php_slot->pdev, "Wrong msg (%lld, %lld, %lld)\n",
 340                                 be64_to_cpu(msg.params[1]),
 341                                 be64_to_cpu(msg.params[2]),
 342                                 be64_to_cpu(msg.params[3]));
 343                        return -ENOMSG;
 344                }
 345        } else if (ret < 0) {
 346                pci_warn(php_slot->pdev, "Error %d powering %s\n",
 347                         ret, (state == OPAL_PCI_SLOT_POWER_ON) ? "on" : "off");
 348                return ret;
 349        }
 350
 351        if (state == OPAL_PCI_SLOT_POWER_OFF || state == OPAL_PCI_SLOT_OFFLINE)
 352                pnv_php_rmv_devtree(php_slot);
 353        else
 354                ret = pnv_php_add_devtree(php_slot);
 355
 356        return ret;
 357}
 358EXPORT_SYMBOL_GPL(pnv_php_set_slot_power_state);
 359
 360static int pnv_php_get_power_state(struct hotplug_slot *slot, u8 *state)
 361{
 362        struct pnv_php_slot *php_slot = slot->private;
 363        uint8_t power_state = OPAL_PCI_SLOT_POWER_ON;
 364        int ret;
 365
 366        /*
 367         * Retrieve power status from firmware. If we fail
 368         * getting that, the power status fails back to
 369         * be on.
 370         */
 371        ret = pnv_pci_get_power_state(php_slot->id, &power_state);
 372        if (ret) {
 373                pci_warn(php_slot->pdev, "Error %d getting power status\n",
 374                         ret);
 375        } else {
 376                *state = power_state;
 377                slot->info->power_status = power_state;
 378        }
 379
 380        return 0;
 381}
 382
 383static int pnv_php_get_adapter_state(struct hotplug_slot *slot, u8 *state)
 384{
 385        struct pnv_php_slot *php_slot = slot->private;
 386        uint8_t presence = OPAL_PCI_SLOT_EMPTY;
 387        int ret;
 388
 389        /*
 390         * Retrieve presence status from firmware. If we can't
 391         * get that, it will fail back to be empty.
 392         */
 393        ret = pnv_pci_get_presence_state(php_slot->id, &presence);
 394        if (ret >= 0) {
 395                *state = presence;
 396                slot->info->adapter_status = presence;
 397                ret = 0;
 398        } else {
 399                pci_warn(php_slot->pdev, "Error %d getting presence\n", ret);
 400        }
 401
 402        return ret;
 403}
 404
 405static int pnv_php_set_attention_state(struct hotplug_slot *slot, u8 state)
 406{
 407        /* FIXME: Make it real once firmware supports it */
 408        slot->info->attention_status = state;
 409
 410        return 0;
 411}
 412
 413static int pnv_php_enable(struct pnv_php_slot *php_slot, bool rescan)
 414{
 415        struct hotplug_slot *slot = &php_slot->slot;
 416        uint8_t presence = OPAL_PCI_SLOT_EMPTY;
 417        uint8_t power_status = OPAL_PCI_SLOT_POWER_ON;
 418        int ret;
 419
 420        /* Check if the slot has been configured */
 421        if (php_slot->state != PNV_PHP_STATE_REGISTERED)
 422                return 0;
 423
 424        /* Retrieve slot presence status */
 425        ret = pnv_php_get_adapter_state(slot, &presence);
 426        if (ret)
 427                return ret;
 428
 429        /*
 430         * Proceed if there have nothing behind the slot. However,
 431         * we should leave the slot in registered state at the
 432         * beginning. Otherwise, the PCI devices inserted afterwards
 433         * won't be probed and populated.
 434         */
 435        if (presence == OPAL_PCI_SLOT_EMPTY) {
 436                if (!php_slot->power_state_check) {
 437                        php_slot->power_state_check = true;
 438
 439                        return 0;
 440                }
 441
 442                goto scan;
 443        }
 444
 445        /*
 446         * If the power supply to the slot is off, we can't detect
 447         * adapter presence state. That means we have to turn the
 448         * slot on before going to probe slot's presence state.
 449         *
 450         * On the first time, we don't change the power status to
 451         * boost system boot with assumption that the firmware
 452         * supplies consistent slot power status: empty slot always
 453         * has its power off and non-empty slot has its power on.
 454         */
 455        if (!php_slot->power_state_check) {
 456                php_slot->power_state_check = true;
 457
 458                ret = pnv_php_get_power_state(slot, &power_status);
 459                if (ret)
 460                        return ret;
 461
 462                if (power_status != OPAL_PCI_SLOT_POWER_ON)
 463                        return 0;
 464        }
 465
 466        /* Check the power status. Scan the slot if it is already on */
 467        ret = pnv_php_get_power_state(slot, &power_status);
 468        if (ret)
 469                return ret;
 470
 471        if (power_status == OPAL_PCI_SLOT_POWER_ON)
 472                goto scan;
 473
 474        /* Power is off, turn it on and then scan the slot */
 475        ret = pnv_php_set_slot_power_state(slot, OPAL_PCI_SLOT_POWER_ON);
 476        if (ret)
 477                return ret;
 478
 479scan:
 480        if (presence == OPAL_PCI_SLOT_PRESENT) {
 481                if (rescan) {
 482                        pci_lock_rescan_remove();
 483                        pci_hp_add_devices(php_slot->bus);
 484                        pci_unlock_rescan_remove();
 485                }
 486
 487                /* Rescan for child hotpluggable slots */
 488                php_slot->state = PNV_PHP_STATE_POPULATED;
 489                if (rescan)
 490                        pnv_php_register(php_slot->dn);
 491        } else {
 492                php_slot->state = PNV_PHP_STATE_POPULATED;
 493        }
 494
 495        return 0;
 496}
 497
 498static int pnv_php_enable_slot(struct hotplug_slot *slot)
 499{
 500        struct pnv_php_slot *php_slot = container_of(slot,
 501                                                     struct pnv_php_slot, slot);
 502
 503        return pnv_php_enable(php_slot, true);
 504}
 505
 506static int pnv_php_disable_slot(struct hotplug_slot *slot)
 507{
 508        struct pnv_php_slot *php_slot = slot->private;
 509        int ret;
 510
 511        if (php_slot->state != PNV_PHP_STATE_POPULATED)
 512                return 0;
 513
 514        /* Remove all devices behind the slot */
 515        pci_lock_rescan_remove();
 516        pci_hp_remove_devices(php_slot->bus);
 517        pci_unlock_rescan_remove();
 518
 519        /* Detach the child hotpluggable slots */
 520        pnv_php_unregister(php_slot->dn);
 521
 522        /* Notify firmware and remove device nodes */
 523        ret = pnv_php_set_slot_power_state(slot, OPAL_PCI_SLOT_POWER_OFF);
 524
 525        php_slot->state = PNV_PHP_STATE_REGISTERED;
 526        return ret;
 527}
 528
 529static struct hotplug_slot_ops php_slot_ops = {
 530        .get_power_status       = pnv_php_get_power_state,
 531        .get_adapter_status     = pnv_php_get_adapter_state,
 532        .set_attention_status   = pnv_php_set_attention_state,
 533        .enable_slot            = pnv_php_enable_slot,
 534        .disable_slot           = pnv_php_disable_slot,
 535};
 536
 537static void pnv_php_release(struct hotplug_slot *slot)
 538{
 539        struct pnv_php_slot *php_slot = slot->private;
 540        unsigned long flags;
 541
 542        /* Remove from global or child list */
 543        spin_lock_irqsave(&pnv_php_lock, flags);
 544        list_del(&php_slot->link);
 545        spin_unlock_irqrestore(&pnv_php_lock, flags);
 546
 547        /* Detach from parent */
 548        pnv_php_put_slot(php_slot);
 549        pnv_php_put_slot(php_slot->parent);
 550}
 551
 552static struct pnv_php_slot *pnv_php_alloc_slot(struct device_node *dn)
 553{
 554        struct pnv_php_slot *php_slot;
 555        struct pci_bus *bus;
 556        const char *label;
 557        uint64_t id;
 558        int ret;
 559
 560        ret = of_property_read_string(dn, "ibm,slot-label", &label);
 561        if (ret)
 562                return NULL;
 563
 564        if (pnv_pci_get_slot_id(dn, &id))
 565                return NULL;
 566
 567        bus = pci_find_bus_by_node(dn);
 568        if (!bus)
 569                return NULL;
 570
 571        php_slot = kzalloc(sizeof(*php_slot), GFP_KERNEL);
 572        if (!php_slot)
 573                return NULL;
 574
 575        php_slot->name = kstrdup(label, GFP_KERNEL);
 576        if (!php_slot->name) {
 577                kfree(php_slot);
 578                return NULL;
 579        }
 580
 581        if (dn->child && PCI_DN(dn->child))
 582                php_slot->slot_no = PCI_SLOT(PCI_DN(dn->child)->devfn);
 583        else
 584                php_slot->slot_no = -1;   /* Placeholder slot */
 585
 586        kref_init(&php_slot->kref);
 587        php_slot->state                 = PNV_PHP_STATE_INITIALIZED;
 588        php_slot->dn                    = dn;
 589        php_slot->pdev                  = bus->self;
 590        php_slot->bus                   = bus;
 591        php_slot->id                    = id;
 592        php_slot->power_state_check     = false;
 593        php_slot->slot.ops              = &php_slot_ops;
 594        php_slot->slot.info             = &php_slot->slot_info;
 595        php_slot->slot.release          = pnv_php_release;
 596        php_slot->slot.private          = php_slot;
 597
 598        INIT_LIST_HEAD(&php_slot->children);
 599        INIT_LIST_HEAD(&php_slot->link);
 600
 601        return php_slot;
 602}
 603
 604static int pnv_php_register_slot(struct pnv_php_slot *php_slot)
 605{
 606        struct pnv_php_slot *parent;
 607        struct device_node *dn = php_slot->dn;
 608        unsigned long flags;
 609        int ret;
 610
 611        /* Check if the slot is registered or not */
 612        parent = pnv_php_find_slot(php_slot->dn);
 613        if (parent) {
 614                pnv_php_put_slot(parent);
 615                return -EEXIST;
 616        }
 617
 618        /* Register PCI slot */
 619        ret = pci_hp_register(&php_slot->slot, php_slot->bus,
 620                              php_slot->slot_no, php_slot->name);
 621        if (ret) {
 622                pci_warn(php_slot->pdev, "Error %d registering slot\n", ret);
 623                return ret;
 624        }
 625
 626        /* Attach to the parent's child list or global list */
 627        while ((dn = of_get_parent(dn))) {
 628                if (!PCI_DN(dn)) {
 629                        of_node_put(dn);
 630                        break;
 631                }
 632
 633                parent = pnv_php_find_slot(dn);
 634                if (parent) {
 635                        of_node_put(dn);
 636                        break;
 637                }
 638
 639                of_node_put(dn);
 640        }
 641
 642        spin_lock_irqsave(&pnv_php_lock, flags);
 643        php_slot->parent = parent;
 644        if (parent)
 645                list_add_tail(&php_slot->link, &parent->children);
 646        else
 647                list_add_tail(&php_slot->link, &pnv_php_slot_list);
 648        spin_unlock_irqrestore(&pnv_php_lock, flags);
 649
 650        php_slot->state = PNV_PHP_STATE_REGISTERED;
 651        return 0;
 652}
 653
 654static int pnv_php_enable_msix(struct pnv_php_slot *php_slot)
 655{
 656        struct pci_dev *pdev = php_slot->pdev;
 657        struct msix_entry entry;
 658        int nr_entries, ret;
 659        u16 pcie_flag;
 660
 661        /* Get total number of MSIx entries */
 662        nr_entries = pci_msix_vec_count(pdev);
 663        if (nr_entries < 0)
 664                return nr_entries;
 665
 666        /* Check hotplug MSIx entry is in range */
 667        pcie_capability_read_word(pdev, PCI_EXP_FLAGS, &pcie_flag);
 668        entry.entry = (pcie_flag & PCI_EXP_FLAGS_IRQ) >> 9;
 669        if (entry.entry >= nr_entries)
 670                return -ERANGE;
 671
 672        /* Enable MSIx */
 673        ret = pci_enable_msix_exact(pdev, &entry, 1);
 674        if (ret) {
 675                pci_warn(pdev, "Error %d enabling MSIx\n", ret);
 676                return ret;
 677        }
 678
 679        return entry.vector;
 680}
 681
 682static void pnv_php_event_handler(struct work_struct *work)
 683{
 684        struct pnv_php_event *event =
 685                container_of(work, struct pnv_php_event, work);
 686        struct pnv_php_slot *php_slot = event->php_slot;
 687
 688        if (event->added)
 689                pnv_php_enable_slot(&php_slot->slot);
 690        else
 691                pnv_php_disable_slot(&php_slot->slot);
 692
 693        kfree(event);
 694}
 695
 696static irqreturn_t pnv_php_interrupt(int irq, void *data)
 697{
 698        struct pnv_php_slot *php_slot = data;
 699        struct pci_dev *pchild, *pdev = php_slot->pdev;
 700        struct eeh_dev *edev;
 701        struct eeh_pe *pe;
 702        struct pnv_php_event *event;
 703        u16 sts, lsts;
 704        u8 presence;
 705        bool added;
 706        unsigned long flags;
 707        int ret;
 708
 709        pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &sts);
 710        sts &= (PCI_EXP_SLTSTA_PDC | PCI_EXP_SLTSTA_DLLSC);
 711        pcie_capability_write_word(pdev, PCI_EXP_SLTSTA, sts);
 712        if (sts & PCI_EXP_SLTSTA_DLLSC) {
 713                pcie_capability_read_word(pdev, PCI_EXP_LNKSTA, &lsts);
 714                added = !!(lsts & PCI_EXP_LNKSTA_DLLLA);
 715        } else if (!(php_slot->flags & PNV_PHP_FLAG_BROKEN_PDC) &&
 716                   (sts & PCI_EXP_SLTSTA_PDC)) {
 717                ret = pnv_pci_get_presence_state(php_slot->id, &presence);
 718                if (ret) {
 719                        pci_warn(pdev, "PCI slot [%s] error %d getting presence (0x%04x), to retry the operation.\n",
 720                                 php_slot->name, ret, sts);
 721                        return IRQ_HANDLED;
 722                }
 723
 724                added = !!(presence == OPAL_PCI_SLOT_PRESENT);
 725        } else {
 726                return IRQ_NONE;
 727        }
 728
 729        /* Freeze the removed PE to avoid unexpected error reporting */
 730        if (!added) {
 731                pchild = list_first_entry_or_null(&php_slot->bus->devices,
 732                                                  struct pci_dev, bus_list);
 733                edev = pchild ? pci_dev_to_eeh_dev(pchild) : NULL;
 734                pe = edev ? edev->pe : NULL;
 735                if (pe) {
 736                        eeh_serialize_lock(&flags);
 737                        eeh_pe_state_mark(pe, EEH_PE_ISOLATED);
 738                        eeh_serialize_unlock(flags);
 739                        eeh_pe_set_option(pe, EEH_OPT_FREEZE_PE);
 740                }
 741        }
 742
 743        /*
 744         * The PE is left in frozen state if the event is missed. It's
 745         * fine as the PCI devices (PE) aren't functional any more.
 746         */
 747        event = kzalloc(sizeof(*event), GFP_ATOMIC);
 748        if (!event) {
 749                pci_warn(pdev, "PCI slot [%s] missed hotplug event 0x%04x\n",
 750                         php_slot->name, sts);
 751                return IRQ_HANDLED;
 752        }
 753
 754        pci_info(pdev, "PCI slot [%s] %s (IRQ: %d)\n",
 755                 php_slot->name, added ? "added" : "removed", irq);
 756        INIT_WORK(&event->work, pnv_php_event_handler);
 757        event->added = added;
 758        event->php_slot = php_slot;
 759        queue_work(php_slot->wq, &event->work);
 760
 761        return IRQ_HANDLED;
 762}
 763
 764static void pnv_php_init_irq(struct pnv_php_slot *php_slot, int irq)
 765{
 766        struct pci_dev *pdev = php_slot->pdev;
 767        u32 broken_pdc = 0;
 768        u16 sts, ctrl;
 769        int ret;
 770
 771        /* Allocate workqueue */
 772        php_slot->wq = alloc_workqueue("pciehp-%s", 0, 0, php_slot->name);
 773        if (!php_slot->wq) {
 774                pci_warn(pdev, "Cannot alloc workqueue\n");
 775                pnv_php_disable_irq(php_slot, true);
 776                return;
 777        }
 778
 779        /* Check PDC (Presence Detection Change) is broken or not */
 780        ret = of_property_read_u32(php_slot->dn, "ibm,slot-broken-pdc",
 781                                   &broken_pdc);
 782        if (!ret && broken_pdc)
 783                php_slot->flags |= PNV_PHP_FLAG_BROKEN_PDC;
 784
 785        /* Clear pending interrupts */
 786        pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &sts);
 787        if (php_slot->flags & PNV_PHP_FLAG_BROKEN_PDC)
 788                sts |= PCI_EXP_SLTSTA_DLLSC;
 789        else
 790                sts |= (PCI_EXP_SLTSTA_PDC | PCI_EXP_SLTSTA_DLLSC);
 791        pcie_capability_write_word(pdev, PCI_EXP_SLTSTA, sts);
 792
 793        /* Request the interrupt */
 794        ret = request_irq(irq, pnv_php_interrupt, IRQF_SHARED,
 795                          php_slot->name, php_slot);
 796        if (ret) {
 797                pnv_php_disable_irq(php_slot, true);
 798                pci_warn(pdev, "Error %d enabling IRQ %d\n", ret, irq);
 799                return;
 800        }
 801
 802        /* Enable the interrupts */
 803        pcie_capability_read_word(pdev, PCI_EXP_SLTCTL, &ctrl);
 804        if (php_slot->flags & PNV_PHP_FLAG_BROKEN_PDC) {
 805                ctrl &= ~PCI_EXP_SLTCTL_PDCE;
 806                ctrl |= (PCI_EXP_SLTCTL_HPIE |
 807                         PCI_EXP_SLTCTL_DLLSCE);
 808        } else {
 809                ctrl |= (PCI_EXP_SLTCTL_HPIE |
 810                         PCI_EXP_SLTCTL_PDCE |
 811                         PCI_EXP_SLTCTL_DLLSCE);
 812        }
 813        pcie_capability_write_word(pdev, PCI_EXP_SLTCTL, ctrl);
 814
 815        /* The interrupt is initialized successfully when @irq is valid */
 816        php_slot->irq = irq;
 817}
 818
 819static void pnv_php_enable_irq(struct pnv_php_slot *php_slot)
 820{
 821        struct pci_dev *pdev = php_slot->pdev;
 822        int irq, ret;
 823
 824        /*
 825         * The MSI/MSIx interrupt might have been occupied by other
 826         * drivers. Don't populate the surprise hotplug capability
 827         * in that case.
 828         */
 829        if (pci_dev_msi_enabled(pdev))
 830                return;
 831
 832        ret = pci_enable_device(pdev);
 833        if (ret) {
 834                pci_warn(pdev, "Error %d enabling device\n", ret);
 835                return;
 836        }
 837
 838        pci_set_master(pdev);
 839
 840        /* Enable MSIx interrupt */
 841        irq = pnv_php_enable_msix(php_slot);
 842        if (irq > 0) {
 843                pnv_php_init_irq(php_slot, irq);
 844                return;
 845        }
 846
 847        /*
 848         * Use MSI if MSIx doesn't work. Fail back to legacy INTx
 849         * if MSI doesn't work either
 850         */
 851        ret = pci_enable_msi(pdev);
 852        if (!ret || pdev->irq) {
 853                irq = pdev->irq;
 854                pnv_php_init_irq(php_slot, irq);
 855        }
 856}
 857
 858static int pnv_php_register_one(struct device_node *dn)
 859{
 860        struct pnv_php_slot *php_slot;
 861        u32 prop32;
 862        int ret;
 863
 864        /* Check if it's hotpluggable slot */
 865        ret = of_property_read_u32(dn, "ibm,slot-pluggable", &prop32);
 866        if (ret || !prop32)
 867                return -ENXIO;
 868
 869        ret = of_property_read_u32(dn, "ibm,reset-by-firmware", &prop32);
 870        if (ret || !prop32)
 871                return -ENXIO;
 872
 873        php_slot = pnv_php_alloc_slot(dn);
 874        if (!php_slot)
 875                return -ENODEV;
 876
 877        ret = pnv_php_register_slot(php_slot);
 878        if (ret)
 879                goto free_slot;
 880
 881        ret = pnv_php_enable(php_slot, false);
 882        if (ret)
 883                goto unregister_slot;
 884
 885        /* Enable interrupt if the slot supports surprise hotplug */
 886        ret = of_property_read_u32(dn, "ibm,slot-surprise-pluggable", &prop32);
 887        if (!ret && prop32)
 888                pnv_php_enable_irq(php_slot);
 889
 890        return 0;
 891
 892unregister_slot:
 893        pnv_php_unregister_one(php_slot->dn);
 894free_slot:
 895        pnv_php_put_slot(php_slot);
 896        return ret;
 897}
 898
 899static void pnv_php_register(struct device_node *dn)
 900{
 901        struct device_node *child;
 902
 903        /*
 904         * The parent slots should be registered before their
 905         * child slots.
 906         */
 907        for_each_child_of_node(dn, child) {
 908                pnv_php_register_one(child);
 909                pnv_php_register(child);
 910        }
 911}
 912
 913static void pnv_php_unregister_one(struct device_node *dn)
 914{
 915        struct pnv_php_slot *php_slot;
 916
 917        php_slot = pnv_php_find_slot(dn);
 918        if (!php_slot)
 919                return;
 920
 921        php_slot->state = PNV_PHP_STATE_OFFLINE;
 922        pci_hp_deregister(&php_slot->slot);
 923        pnv_php_put_slot(php_slot);
 924}
 925
 926static void pnv_php_unregister(struct device_node *dn)
 927{
 928        struct device_node *child;
 929
 930        /* The child slots should go before their parent slots */
 931        for_each_child_of_node(dn, child) {
 932                pnv_php_unregister(child);
 933                pnv_php_unregister_one(child);
 934        }
 935}
 936
 937static int __init pnv_php_init(void)
 938{
 939        struct device_node *dn;
 940
 941        pr_info(DRIVER_DESC " version: " DRIVER_VERSION "\n");
 942        for_each_compatible_node(dn, NULL, "ibm,ioda2-phb")
 943                pnv_php_register(dn);
 944
 945        return 0;
 946}
 947
 948static void __exit pnv_php_exit(void)
 949{
 950        struct device_node *dn;
 951
 952        for_each_compatible_node(dn, NULL, "ibm,ioda2-phb")
 953                pnv_php_unregister(dn);
 954}
 955
 956module_init(pnv_php_init);
 957module_exit(pnv_php_exit);
 958
 959MODULE_VERSION(DRIVER_VERSION);
 960MODULE_LICENSE("GPL v2");
 961MODULE_AUTHOR(DRIVER_AUTHOR);
 962MODULE_DESCRIPTION(DRIVER_DESC);
 963