[Skiboot] [PATCH v4 07/10] core/pci: PCI slot

Gavin Shan gwshan at linux.vnet.ibm.com
Tue Feb 17 17:48:54 AEDT 2015


Prior to PCI enumeration, fundamental reset and checking RC link
status are carried out. Now, all of them are covered by PHB slot.
The patch switches to PHB slot to do fundamental reset and checking
RC link status.

Signed-off-by: Gavin Shan <gwshan at linux.vnet.ibm.com>
---
 core/pci.c    | 161 +++++++++++++++-------------------------------------------
 include/pci.h |  20 --------
 2 files changed, 42 insertions(+), 139 deletions(-)

diff --git a/core/pci.c b/core/pci.c
index 2869249..8977690 100644
--- a/core/pci.c
+++ b/core/pci.c
@@ -27,22 +27,22 @@ static struct lock pci_lock = LOCK_UNLOCKED;
 static struct phb *phbs[64];
 
 #define PCITRACE(_p, _bdfn, fmt, a...) \
-	prlog(PR_TRACE, "PHB%d:%02x:%02x.%x " fmt,	\
+	prlog(PR_TRACE, "PHB%04x:%02x:%02x.%x " fmt,	\
 	      (_p)->opal_id,				\
 	      ((_bdfn) >> 8) & 0xff,			\
 	      ((_bdfn) >> 3) & 0x1f, (_bdfn) & 0x7, ## a)
 #define PCIDBG(_p, _bdfn, fmt, a...) \
-	prlog(PR_DEBUG, "PHB%d:%02x:%02x.%x " fmt,	\
+	prlog(PR_DEBUG, "PHB%04x:%02x:%02x.%x " fmt,	\
 	      (_p)->opal_id,				\
 	      ((_bdfn) >> 8) & 0xff,			\
 	      ((_bdfn) >> 3) & 0x1f, (_bdfn) & 0x7, ## a)
 #define PCINOTICE(_p, _bdfn, fmt, a...) \
-	prlog(PR_NOTICE, "PHB%d:%02x:%02x.%x " fmt,	\
+	prlog(PR_NOTICE, "PHB%04x:%02x:%02x.%x " fmt,	\
 	      (_p)->opal_id,				\
 	      ((_bdfn) >> 8) & 0xff,			\
 	      ((_bdfn) >> 3) & 0x1f, (_bdfn) & 0x7, ## a)
 #define PCIERR(_p, _bdfn, fmt, a...) \
-	prlog(PR_ERR, "PHB%d:%02x:%02x.%x " fmt,	\
+	prlog(PR_ERR, "PHB%04x:%02x:%02x.%x " fmt,	\
 	      (_p)->opal_id,				\
 	      ((_bdfn) >> 8) & 0xff,			\
 	      ((_bdfn) >> 3) & 0x1f, (_bdfn) & 0x7, ## a)
@@ -656,110 +656,71 @@ void pci_device_init(struct phb *phb, struct pci_device *pd)
 	pci_disable_completion_timeout(phb, pd);
 }
 
-/*
- * The power state would be checked. If the power has
- * been on, we will issue fundamental reset. Otherwise,
- * we will power it on before issuing fundamental reset.
- */
-static int64_t pci_phb_reset(struct phb *phb)
+static void pci_reset_phb(void *data)
 {
-	const char *desc;
+	struct phb *phb = data;
+	struct pci_slot *slot = phb->slot;
 	int64_t rc;
 
-	rc = phb->ops->power_state(phb);
-	if (rc < 0) {
-		PCIERR(phb, 0, "Failed to get power state, rc=%lld\n", rc);
-		return rc;
-	}
-
-	if (rc == OPAL_SHPC_POWER_ON) {
-		desc = "fundamental reset";
-		rc = phb->ops->fundamental_reset(phb);
-	} else {
-		desc = "power on";
-		rc = phb->ops->slot_power_on(phb);
+	/*
+	 * Skip reset without supported PHB slot as we
+	 * rely on the slot callbacks for fundamental
+	 * reset
+	 */
+	if (!slot) {
+		PCINOTICE(phb, 0, "Skip reset without slot\n");
+		return;
+	} else if (!slot->ops.freset) {
+		PCINOTICE(phb, 0, "Skip reset without supported freset\n");
+		return;
 	}
 
+	/* Issue fundamental reset */
+	rc = slot->ops.freset(slot);
 	if (rc < 0) {
-		/* Don't warn if it's just an empty slot */
-		if (rc != OPAL_CLOSED)
-			goto warn_err;
-		return rc;
+		PCIERR(phb, 0, "Failure %lld from fundamental reset\n", rc);
+		return;
 	}
 
-	/* Wait the internal state machine */
+	/* Poll until the reset completes */
 	while (rc > 0) {
 		time_wait(rc);
-		rc = phb->ops->poll(phb);
+		rc = slot->ops.poll(slot, NULL);
 	}
 
- warn_err:
 	if (rc < 0)
-		PCIERR(phb, 0, "Failed to %s, rc=%lld\n", desc, rc);
-
-        return rc;
-}
-
-static void pci_reset_phb(void *data)
-{
-	struct phb *phb = data;
-	int64_t rc;
-
-	PCIDBG(phb, 0, "Init slot...\n");
-
-	/*
-	 * For PCI/PCI-X, we get the slot info and we also
-	 * check if the PHB has anything connected to it
-	 */
-	if (phb->phb_type < phb_type_pcie_v1) {
-		if (platform.pci_get_slot_info)
-			platform.pci_get_slot_info(phb, NULL);
-		rc = phb->ops->presence_detect(phb);
-		if (rc != OPAL_SHPC_DEV_PRESENT) {
-			PCIDBG(phb, 0, "Slot empty\n");
-			return;
-		}
-	}
-
-	/*
-	 * Power on the PHB, the PHB should be reset in
-	 * fundamental way while powering on. The reset
-	 * state machine is going to wait for the link
-	 */
-	pci_phb_reset(phb);
+		PCIERR(phb, 0, "Failure %lld polling slot\n", rc);
 }
 
 static void pci_scan_phb(void *data)
 {
 	struct phb *phb = data;
+	struct pci_slot *slot = phb->slot;
 	uint32_t mps = 0xffffffff;
-	bool has_link = false;
+	uint8_t link = 0;
 	int64_t rc;
 
-	rc = phb->ops->link_state(phb);
-	if (rc < 0) {
-		PCIERR(phb, 0, "Failed to query link state, rc=%lld\n", rc);
-		return;
+	/* Retrieve the link state */
+	if (slot && slot->ops.get_link_status) {
+		rc = slot->ops.get_link_status(slot, &link);
+		if (rc != OPAL_SUCCESS) {
+			PCIERR(phb, 0, "Error %lld to query link state\n", rc);
+			return;
+		}
 	}
 
-	/*
-	 * We will probe the root port. If the PHB has trained
-	 * link, we will probe the downstream port as well.
-	 */
-	if (rc != OPAL_SHPC_LINK_DOWN)
-		has_link = true;
-
-	if (has_link && phb->phb_type >= phb_type_pcie_v1)
-		PCIDBG(phb, 0, "Link up at x%lld width\n", rc);
-	else if (has_link)
+	/* Output link info */
+	if (link && phb->phb_type >= phb_type_pcie_v1)
+		PCIDBG(phb, 0, "Link up at x%d width\n", link);
+	else if (link)
 		PCIDBG(phb, 0, "Link up\n");
 	else
 		PCIDBG(phb, 0, "Link down\n");
 
 	/* Scan root port and downstream ports if applicable */
 	PCIDBG(phb, 0, "Scanning (upstream%s)...\n",
-	       has_link ? "+downsteam" : " only");
-	pci_scan(phb, 0, 0xff, &phb->devices, NULL, has_link);
+	       link ? "+downsteam" : " only");
+	pci_scan(phb, 0, 0xff, &phb->devices, NULL, link);
 
 	/* Configre MPS (Max Payload Size) for PCIe domain */
 	pci_walk_dev(phb, NULL, pci_get_mps, &mps);
@@ -1114,40 +1075,6 @@ void pci_std_swizzle_irq_map(struct dt_node *np,
 	free(map);
 }
 
-static void pci_add_slot_properties(struct phb *phb, struct pci_slot_info *info,
-				    struct dt_node *np)
-{
-	char loc_code[LOC_CODE_SIZE];
-	size_t base_loc_code_len, slot_label_len;
-
-	if (phb->base_loc_code) {
-		base_loc_code_len = strlen(phb->base_loc_code);
-		slot_label_len = strlen(info->label);
-		if ((base_loc_code_len + slot_label_len +1) < LOC_CODE_SIZE) {
-			strcpy(loc_code, phb->base_loc_code);
-			strcat(loc_code, "-");
-			strcat(loc_code, info->label);
-			dt_add_property(np, "ibm,slot-location-code",
-					loc_code, strlen(loc_code) + 1);
-		} else
-			PCIERR(phb, 0, "Loc Code too long - %zu + %zu + 1\n",
-			       base_loc_code_len, slot_label_len);
-	} else
-		PCIERR(phb, 0, "Base Loc code not found...\n");
-
-	/* Add other slot information */
-	dt_add_property_cells(np, "ibm,slot-pluggable", info->pluggable);
-	dt_add_property_cells(np, "ibm,slot-power-ctl", info->power_ctl);
-	dt_add_property_cells(np, "ibm,slot-wired-lanes", info->wired_lanes);
-	/*dt_add_property(np, "ibm,slot-bus-clock", &pd->slot_info->bus_clock, sizeof(uint8_t));*/
-	dt_add_property_cells(np, "ibm,slot-connector-type", info->connector_type);
-	dt_add_property_cells(np, "ibm,slot-card-desc", info->card_desc);
-	dt_add_property_cells(np, "ibm,slot-card-mech", info->card_mech);
-	dt_add_property_cells(np, "ibm,slot-pwr-led-ctl", info->pwr_led_ctl);
-	dt_add_property_cells(np, "ibm,slot-attn-led-ctl", info->attn_led_ctl);
-	dt_add_property_string(np, "ibm,slot-label", info->label);
-}
-
 static void pci_add_loc_code(struct dt_node *np)
 {
 	struct dt_node *p = np->parent;
@@ -1287,8 +1214,8 @@ static void pci_add_one_node(struct phb *phb, struct pci_device *pd,
 	 */
 
 	/* Add slot properties if needed */
-	if (pd->slot_info)
-		pci_add_slot_properties(phb, pd->slot_info, np);
+	if (pd->slot)
+		pci_slot_add_properties(pd->slot, np);
 
 	/* Make up location code */
 	pci_add_loc_code(np);
@@ -1346,10 +1273,6 @@ static void pci_add_nodes(struct phb *phb)
 	struct pci_lsi_state *lstate = &phb->lstate;
 	struct pci_device *pd;
 
-	/* If the PHB has its own slot info, add them */
-	if (phb->slot_info)
-		pci_add_slot_properties(phb, phb->slot_info, NULL);
-
 	/* Add all child devices */
 	list_for_each(&phb->devices, pd, link)
 		pci_add_one_node(phb, pd, phb->dt_node, lstate, 0);
diff --git a/include/pci.h b/include/pci.h
index 94c43a2..fcc8087 100644
--- a/include/pci.h
+++ b/include/pci.h
@@ -21,24 +21,6 @@
 #include <device.h>
 #include <ccan/list/list.h>
 
-/* PCI Slot Entry Information */
-struct pci_slot_info {
-	uint8_t    switch_id;
-	uint8_t    vswitch_id;
-	uint8_t    dev_id;
-	char       label[9];
-	bool       pluggable;
-	bool       power_ctl;
-	uint8_t    wired_lanes;
-	uint8_t    bus_clock;
-	uint8_t    connector_type;
-	uint8_t    card_desc;
-	uint8_t    card_mech;
-	uint8_t    pwr_led_ctl;
-	uint8_t    attn_led_ctl;
-	uint8_t    slot_index;
-};
-
 /*
  * While this might not be necessary in the long run, the existing
  * Linux kernels expect us to provide a device-tree that contains
@@ -73,7 +55,6 @@ struct pci_device {
 	uint32_t		mps;		/* Max payload size capability */
 
 	struct pci_slot		*slot;
-	struct pci_slot_info    *slot_info;
 	struct pci_device	*parent;
 	struct list_head	children;
 	struct list_node	link;
@@ -384,7 +365,6 @@ struct phb {
 
 	/* PCI-X only slot info, for PCI-E this is in the RC bridge */
 	struct pci_slot		*slot;
-	struct pci_slot_info    *slot_info;
 
 	/* Base location code used to generate the children one */
 	const char		*base_loc_code;
-- 
1.8.3.2



More information about the Skiboot mailing list