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