aboutsummaryrefslogtreecommitdiff
path: root/core/pcie-slot.c
diff options
context:
space:
mode:
authorOliver O'Halloran <oohall@gmail.com>2017-09-15 15:40:47 +1000
committerStewart Smith <stewart@linux.vnet.ibm.com>2017-09-15 02:49:26 -0500
commitcc41ce944b978395366177a29340facde3f1150b (patch)
tree9cede735f4ebaac1f03a46718db3f9f28505bbc9 /core/pcie-slot.c
parent529d86d02aaf5428ec2c6acd912b6a2b7541457a (diff)
downloadskiboot-cc41ce944b978395366177a29340facde3f1150b.zip
skiboot-cc41ce944b978395366177a29340facde3f1150b.tar.gz
skiboot-cc41ce944b978395366177a29340facde3f1150b.tar.bz2
core/pcie-slots: Make dynamic slot creation generic
astbmc has some code to handle devices that are behind a "slot" on a riser card that can't be added to the static slot tables for a system. We probably want to use this code outside the slot table handling so move it somewhere generic and rework it so slot table specifics aren't buried inside it. Signed-off-by: Oliver O'Halloran <oohall@gmail.com> Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com>
Diffstat (limited to 'core/pcie-slot.c')
-rw-r--r--core/pcie-slot.c51
1 files changed, 51 insertions, 0 deletions
diff --git a/core/pcie-slot.c b/core/pcie-slot.c
index 1b7e24c..77e356c 100644
--- a/core/pcie-slot.c
+++ b/core/pcie-slot.c
@@ -528,5 +528,56 @@ struct pci_slot *pcie_slot_create(struct phb *phb, struct pci_device *pd)
slot->ops.hreset = pcie_slot_sm_hreset;
slot->ops.freset = pcie_slot_sm_freset;
+ slot->wired_lanes = PCI_SLOT_WIRED_LANES_UNKNOWN;
+ slot->connector_type = PCI_SLOT_CONNECTOR_PCIE_NS;
+ slot->card_desc = PCI_SLOT_DESC_NON_STANDARD;
+ slot->card_mech = PCI_SLOT_MECH_NONE;
+ slot->power_led_ctl = PCI_SLOT_PWR_LED_CTL_NONE;
+ slot->attn_led_ctl = PCI_SLOT_ATTN_LED_CTL_NONE;
+
+ return slot;
+}
+
+/* FIXME: this is kind of insane */
+struct pci_slot *pcie_slot_create_dynamic(struct phb *phb,
+ struct pci_device *pd)
+{
+ uint32_t ecap, val;
+ struct pci_slot *slot;
+
+ if (!phb || !pd || pd->slot)
+ return NULL;
+
+ /* Try to create slot whose details aren't provided by platform.
+ * We only care the downstream ports of PCIe switch that connects
+ * to root port.
+ */
+ if (pd->dev_type != PCIE_TYPE_SWITCH_DNPORT ||
+ !pd->parent || !pd->parent->parent ||
+ pd->parent->parent->parent)
+ return NULL;
+
+ ecap = pci_cap(pd, PCI_CFG_CAP_ID_EXP, false);
+ pci_cfg_read32(phb, pd->bdfn, ecap + PCICAP_EXP_SLOTCAP, &val);
+ if (!(val & PCICAP_EXP_SLOTCAP_HPLUG_CAP))
+ return NULL;
+
+ slot = pcie_slot_create(phb, pd);
+
+ /* On superMicro's "p8dnu" platform, we create dynamic PCI slots
+ * for all downstream ports of PEX9733 that is connected to PHB
+ * direct slot. The power supply to the PCI slot is lost after
+ * PCI adapter is removed from it. The power supply can't be
+ * turned on when the slot is in empty state. The power supply
+ * isn't turned on automatically when inserting PCI adapter to
+ * the slot at later point. We set a flag to the slot here, to
+ * turn on the power supply in (suprise or managed) hot-add path.
+ *
+ * We have same issue with PEX8718 as above on "p8dnu" platform.
+ */
+ if (dt_node_is_compatible(dt_root, "supermicro,p8dnu") && slot->pd &&
+ (slot->pd->vdid == 0x973310b5 || slot->pd->vdid == 0x871810b5))
+ pci_slot_add_flags(slot, PCI_SLOT_FLAG_FORCE_POWERON);
+
return slot;
}