diff mbox series

[02/14] core/pcie-slots: Make dynamic slot creation generic

Message ID 20170915054059.32109-2-oohall@gmail.com
State Accepted
Headers show
Series [01/14] core/pci-dt-slot: Represent PCIe slots in the devicetree | expand

Commit Message

Oliver O'Halloran Sept. 15, 2017, 5:40 a.m. UTC
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>
---
 core/pcie-slot.c         | 51 +++++++++++++++++++++++++++++++++
 include/pci-slot.h       |  3 ++
 platforms/astbmc/slots.c | 74 ++++++++----------------------------------------
 3 files changed, 66 insertions(+), 62 deletions(-)
diff mbox series

Patch

diff --git a/core/pcie-slot.c b/core/pcie-slot.c
index 1b7e24cbfc67..77e356c8a702 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;
 }
diff --git a/include/pci-slot.h b/include/pci-slot.h
index 51e64d7b2cad..0524652b3142 100644
--- a/include/pci-slot.h
+++ b/include/pci-slot.h
@@ -252,6 +252,9 @@  extern struct pci_slot *pci_slot_alloc(struct phb *phb,
 				       struct pci_device *pd);
 extern struct pci_slot *pcie_slot_create(struct phb *phb,
 					 struct pci_device *pd);
+extern struct pci_slot *pcie_slot_create_dynamic(struct phb *phb,
+		struct pci_device *pd);
+
 extern void pci_slot_add_dt_properties(struct pci_slot *slot,
 				       struct dt_node *np);
 extern struct pci_slot *pci_slot_find(uint64_t id);
diff --git a/platforms/astbmc/slots.c b/platforms/astbmc/slots.c
index a2bec8797b37..92d52f7b5587 100644
--- a/platforms/astbmc/slots.c
+++ b/platforms/astbmc/slots.c
@@ -85,7 +85,7 @@  static const struct slot_table_entry *match_slot_dev_entry(struct phb *phb,
 	return NULL;
 }
 
-static void add_slot_properties(struct pci_slot *slot,
+static void slot_table_add_properties(struct pci_slot *slot,
 				struct dt_node *np)
 {
 	struct phb *phb = slot->phb;
@@ -126,82 +126,32 @@  static void add_slot_properties(struct pci_slot *slot,
 			loc_code, strlen(loc_code) + 1);
 }
 
-static void init_slot_info(struct pci_slot *slot, bool pluggable, void *data)
-{
-	slot->data = data;
-	slot->ops.add_properties = add_slot_properties;
-
-	slot->pluggable      = pluggable;
-	slot->power_ctl      = false;
-	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;
-}
-
-static void create_dynamic_slot(struct phb *phb, struct pci_device *pd)
-{
-	uint32_t ecap, val;
-	struct pci_slot *slot;
-
-	if (!phb || !pd || pd->slot)
-		return;
-
-	/* 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;
-
-	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;
-
-	slot = pcie_slot_create(phb, pd);
-	assert(slot);
-	init_slot_info(slot, true, NULL);
-
-	/* 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);
-}
-
 void slot_table_get_slot_info(struct phb *phb, struct pci_device *pd)
 {
 	const struct slot_table_entry *ent;
 	struct pci_slot *slot;
-	bool pluggable;
 
 	if (!pd || pd->slot)
 		return;
+
 	ent = match_slot_dev_entry(phb, pd);
+
 	if (!ent || !ent->name) {
-		create_dynamic_slot(phb, pd);
+		slot = pcie_slot_create_dynamic(phb, pd);
+		if (slot) {
+			slot->ops.add_properties = slot_table_add_properties;
+			slot->pluggable = true;
+		}
+
 		return;
 	}
 
 	slot = pcie_slot_create(phb, pd);
 	assert(slot);
 
-	pluggable = !!(ent->etype == st_pluggable_slot);
-	init_slot_info(slot, pluggable, (void *)ent);
+	slot->pluggable = !!(ent->etype == st_pluggable_slot);
+	slot->ops.add_properties = slot_table_add_properties;
+	slot->data = (void *)ent;
 }
 
 static int __pci_find_dev_by_location(struct phb *phb,