diff options
author | Oliver O'Halloran <oohall@gmail.com> | 2017-09-15 15:40:47 +1000 |
---|---|---|
committer | Stewart Smith <stewart@linux.vnet.ibm.com> | 2017-09-15 02:49:26 -0500 |
commit | cc41ce944b978395366177a29340facde3f1150b (patch) | |
tree | 9cede735f4ebaac1f03a46718db3f9f28505bbc9 /core/pcie-slot.c | |
parent | 529d86d02aaf5428ec2c6acd912b6a2b7541457a (diff) | |
download | talos-skiboot-cc41ce944b978395366177a29340facde3f1150b.tar.gz talos-skiboot-cc41ce944b978395366177a29340facde3f1150b.zip |
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.c | 51 |
1 files changed, 51 insertions, 0 deletions
diff --git a/core/pcie-slot.c b/core/pcie-slot.c index 1b7e24cb..77e356c8 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; } |