[Skiboot] [PATCH v4] PCI: create optional loc-code platform callback

Klaus Heinrich Kiwi klaus at linux.vnet.ibm.com
Tue Feb 18 22:37:30 AEDT 2020


Some platforms (mostly OpenPower-based) will favor a short,
slot-label-based string for the "ibm,loc-code" DT property. Other
platforms such as ZZ/FSP-based platforms will prefer the fully-qualified
slot-location-code for it.

This patches creates a new operation on the platform struct, allowing
for an optional callback to create the "ibm,loc-code" property in a
platform-specific way. If the callback is not defined, use the
cleaned-up default that was in use so far.

Signed-off-by: Klaus Heinrich Kiwi <klaus at linux.vnet.ibm.com>
---

 core/pci.c                      | 42 ++++----------------
 include/platform.h              |  8 ++++
 platforms/ibm-fsp/firenze-pci.c | 70 +++++++++++++++++++++++++++++++++
 platforms/ibm-fsp/firenze.c     |  1 +
 platforms/ibm-fsp/ibm-fsp.h     |  2 +
 platforms/ibm-fsp/zz.c          |  1 +
 6 files changed, 89 insertions(+), 35 deletions(-)

diff --git a/core/pci.c b/core/pci.c
index 8b52fc10..d211207b 100644
--- a/core/pci.c
+++ b/core/pci.c
@@ -1383,17 +1383,13 @@ void pci_std_swizzle_irq_map(struct dt_node *np,
 	free(map);
 }
 
-static void pci_add_loc_code(struct dt_node *np, struct pci_device *pd)
+static void pci_add_loc_code(struct dt_node *np)
 {
 	struct dt_node *p = np->parent;
 	const char *blcode = NULL;
-	char *lcode;
-	uint32_t class_code;
-	uint8_t class, sub;
-	uint8_t pos, len;
 
 	while (p) {
-		/* if we have a slot label (i.e. openpower) use that */
+		/* prefer slot-label by default */
 		blcode = dt_prop_get_def(p, "ibm,slot-label", NULL);
 		if (blcode)
 			break;
@@ -1424,34 +1420,7 @@ static void pci_add_loc_code(struct dt_node *np, struct pci_device *pd)
 	if (!blcode)
 		return;
 
-	/* ethernet devices get port codes */
-	class_code = dt_prop_get_u32(np, "class-code");
-	class = class_code >> 16;
-	sub = (class_code >> 8) & 0xff;
-
-	/* XXX Don't do that on openpower for now, we will need to sort things
-	 * out later, otherwise the mezzanine slot on Habanero gets weird results
-	 */
-	if (class == 0x02 && sub == 0x00 && !platform.bmc) {
-		/* There's usually several spaces at the end of the property.
-		   Test for, but don't rely on, that being the case */
-		len = strlen(blcode);
-		for (pos = 0; pos < len; pos++)
-			if (blcode[pos] == ' ') break;
-		if (pos + 3 < len)
-			lcode = strdup(blcode);
-		else {
-			lcode = malloc(pos + 3);
-			memcpy(lcode, blcode, len);
-		}
-		lcode[pos++] = '-';
-		lcode[pos++] = 'T';
-		lcode[pos++] = (char)PCI_FUNC(pd->bdfn) + '1';
-		lcode[pos++] = '\0';
-		dt_add_property_string(np, "ibm,loc-code", lcode);
-		free(lcode);
-	} else
-		dt_add_property_string(np, "ibm,loc-code", blcode);
+	dt_add_property_string(np, "ibm,loc-code", blcode);
 }
 
 static void pci_print_summary_line(struct phb *phb, struct pci_device *pd,
@@ -1595,7 +1564,10 @@ static void __noinline pci_add_one_device_node(struct phb *phb,
 				       phb->base_loc_code);
 
 	/* Make up location code */
-	pci_add_loc_code(np, pd);
+	if (platform.pci_add_loc_code)
+		platform.pci_add_loc_code(np, pd);
+	else
+		pci_add_loc_code(np);
 
 	/* XXX FIXME: We don't look for BARs, we only put the config space
 	 * entry in the "reg" property. That's enough for Linux and we might
diff --git a/include/platform.h b/include/platform.h
index 6909a6a4..671878b9 100644
--- a/include/platform.h
+++ b/include/platform.h
@@ -185,6 +185,14 @@ struct platform {
 	void		(*pci_get_slot_info)(struct phb *phb,
 					     struct pci_device *pd);
 
+	/*
+	 * Called for each device during pci_add_device_nodes() descend
+	 * to create the device tree, in order to get the correct per-platform
+	 * preference for the ibm,loc-code property
+	 */
+	void		(*pci_add_loc_code)(struct dt_node *np,
+					     struct pci_device *pd);
+
 	/*
 	 * Called after PCI probe is complete and before inventory is
 	 * displayed in console. This can either run platform fixups or
diff --git a/platforms/ibm-fsp/firenze-pci.c b/platforms/ibm-fsp/firenze-pci.c
index 6d5aab1e..efbe5525 100644
--- a/platforms/ibm-fsp/firenze-pci.c
+++ b/platforms/ibm-fsp/firenze-pci.c
@@ -972,3 +972,73 @@ void firenze_pci_get_slot_info(struct phb *phb, struct pci_device *pd)
 		firenze_pci_slot_init(slot);
 	}
 }
+
+void firenze_pci_add_loc_code(struct dt_node *np, struct pci_device *pd)
+{
+	struct dt_node *p;
+	const char *blcode = NULL;
+	char *lcode;
+	uint32_t class_code;
+	uint8_t class,sub;
+	uint8_t pos, len;
+
+
+	/*
+	 * prefer fully-qualified slot-location-code, walk-up parent tree
+	 * to find one
+	 */
+	for (p = np->parent; p; p = np->parent) {
+		blcode = dt_prop_get_def(p, "ibm,slot-location-code", NULL);
+		if (blcode)
+			break;
+	}
+
+	/* try the node itself if none is found */
+	if (!blcode)
+		blcode = dt_prop_get_def(np, "ibm,slot-location-code", NULL);
+
+	if (!blcode) {
+		/* still not found, fall back to ibm,loc-code */
+
+		for (p = np->parent; p; p = p->parent) {
+			blcode = dt_prop_get_def(p, "ibm,loc-code", NULL);
+			if (blcode)
+				break;
+		}
+	}
+
+	if (!blcode) {
+		prlog(PR_ERR,
+			"No suitable location code to add for device PHB#%04x:%02x:%02x.%x\n",
+			pd->phb->opal_id, PCI_BUS_NUM(pd->bdfn),
+			PCI_DEV(pd->bdfn), PCI_FUNC(pd->bdfn));
+		return;
+	}
+
+	/* ethernet devices get port codes */
+	class_code = dt_prop_get_u32(np, "class-code");
+	class = class_code >> 16;
+	sub = (class_code >> 8) & 0xff;
+
+	if (class == 0x02 && sub == 0x00) {
+		/* There's usually several spaces at the end of the property.
+		   Test for, but don't rely on, that being the case */
+		len = strlen(blcode);
+		for (pos = 0; pos < len; pos++)
+			if (blcode[pos] == ' ') break;
+		if (pos + 3 < len)
+			lcode = strdup(blcode);
+		else {
+			lcode = malloc(pos + 3);
+			memcpy(lcode, blcode, len);
+		}
+		lcode[pos++] = '-';
+		lcode[pos++] = 'T';
+		lcode[pos++] = (char)PCI_FUNC(pd->bdfn) + '1';
+		lcode[pos++] = '\0';
+		dt_add_property_string(np, "ibm,loc-code", lcode);
+		free(lcode);
+	} else {
+		dt_add_property_string(np, "ibm,loc-code", blcode);
+	}
+}
diff --git a/platforms/ibm-fsp/firenze.c b/platforms/ibm-fsp/firenze.c
index 26977450..f4389049 100644
--- a/platforms/ibm-fsp/firenze.c
+++ b/platforms/ibm-fsp/firenze.c
@@ -206,6 +206,7 @@ DECLARE_PLATFORM(firenze) = {
 	.cec_reboot		= ibm_fsp_cec_reboot,
 	.pci_setup_phb		= firenze_pci_setup_phb,
 	.pci_get_slot_info	= firenze_pci_get_slot_info,
+	.pci_add_loc_code	= firenze_pci_add_loc_code,
 	.pci_probe_complete	= firenze_pci_send_inventory,
 	.nvram_info		= fsp_nvram_info,
 	.nvram_start_read	= fsp_nvram_start_read,
diff --git a/platforms/ibm-fsp/ibm-fsp.h b/platforms/ibm-fsp/ibm-fsp.h
index 16af68f8..145ac0ad 100644
--- a/platforms/ibm-fsp/ibm-fsp.h
+++ b/platforms/ibm-fsp/ibm-fsp.h
@@ -29,6 +29,8 @@ extern void firenze_pci_setup_phb(struct phb *phb,
 				  unsigned int index);
 extern void firenze_pci_get_slot_info(struct phb *phb,
 				      struct pci_device *pd);
+extern void firenze_pci_add_loc_code(struct dt_node *np,
+				      struct pci_device *pd);
 
 /* VPD support */
 void vpd_iohub_load(struct dt_node *hub_node);
diff --git a/platforms/ibm-fsp/zz.c b/platforms/ibm-fsp/zz.c
index f4aa85fa..14a54d64 100644
--- a/platforms/ibm-fsp/zz.c
+++ b/platforms/ibm-fsp/zz.c
@@ -184,6 +184,7 @@ DECLARE_PLATFORM(zz) = {
 	.cec_reboot		= ibm_fsp_cec_reboot,
 	.pci_setup_phb		= firenze_pci_setup_phb,
 	.pci_get_slot_info	= firenze_pci_get_slot_info,
+	.pci_add_loc_code	= firenze_pci_add_loc_code,
 	.pci_probe_complete	= firenze_pci_send_inventory,
 	.nvram_info		= fsp_nvram_info,
 	.nvram_start_read	= fsp_nvram_start_read,
-- 
2.17.1



More information about the Skiboot mailing list