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

Klaus Heinrich Kiwi klaus at linux.vnet.ibm.com
Sat Feb 15 01:17:40 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 patch creates a new optional callbacl on the platform struct,
allowing platforms to create the "ibm,loc-code" property in their 
specific way. If the callback is not defined, default to the cleaned-up
pci_add_loc_code() that was in use so far.

Signed-off-by: Klaus Heinrich Kiwi <klaus at linux.vnet.ibm.com>
---
 core/pci.c                      | 70 +++++++++++----------------------
 include/platform.h              |  8 ++++
 platforms/ibm-fsp/firenze-pci.c | 68 ++++++++++++++++++++++++++++++++
 platforms/ibm-fsp/firenze.c     |  1 +
 platforms/ibm-fsp/ibm-fsp.h     |  2 +
 platforms/ibm-fsp/zz.c          |  1 +
 6 files changed, 103 insertions(+), 47 deletions(-)

diff --git a/core/pci.c b/core/pci.c
index 8b52fc10..5170d30b 100644
--- a/core/pci.c
+++ b/core/pci.c
@@ -1383,75 +1383,45 @@ 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 pci_device *pd __unused)
 {
 	struct dt_node *p = np->parent;
-	const char *blcode = NULL;
-	char *lcode;
-	uint32_t class_code;
-	uint8_t class, sub;
-	uint8_t pos, len;
+	const char *lcode = NULL;
 
 	while (p) {
-		/* if we have a slot label (i.e. openpower) use that */
-		blcode = dt_prop_get_def(p, "ibm,slot-label", NULL);
-		if (blcode)
+		/* prefer slot-label by default */
+		lcode = dt_prop_get_def(p, "ibm,slot-label", NULL);
+		if (lcode)
 			break;
 
 		/* otherwise use the fully qualified location code */
-		blcode = dt_prop_get_def(p, "ibm,slot-location-code", NULL);
-		if (blcode)
+		lcode = dt_prop_get_def(p, "ibm,slot-location-code", NULL);
+		if (lcode)
 			break;
 
 		p = p->parent;
 	}
 
-	if (!blcode)
-		blcode = dt_prop_get_def(np, "ibm,slot-location-code", NULL);
+	/* try the node itself if none is found */
+	if (!lcode)
+		lcode = dt_prop_get_def(np, "ibm,slot-location-code", NULL);
 
-	if (!blcode) {
+	if (!lcode) {
 		/* Fall back to finding a ibm,loc-code */
 		p = np->parent;
 
 		while (p) {
-			blcode = dt_prop_get_def(p, "ibm,loc-code", NULL);
-			if (blcode)
+			lcode = dt_prop_get_def(p, "ibm,loc-code", NULL);
+			if (lcode)
 				break;
 			p = p->parent;
 		}
 	}
 
-	if (!blcode)
+	if (!lcode)
 		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", lcode);
 }
 
 static void pci_print_summary_line(struct phb *phb, struct pci_device *pd,
@@ -1594,8 +1564,14 @@ static void __noinline pci_add_one_device_node(struct phb *phb,
 		dt_add_property_string(np, "ibm,slot-location-code",
 				       phb->base_loc_code);
 
-	/* Make up location code */
-	pci_add_loc_code(np, pd);
+	/*
+	 * Use platform-specific callback (if there is one) to make up
+	 * location code
+	 */
+	if (platform.pci_get_loc_code)
+		platform.pci_get_loc_code(np, pd);
+	else
+		pci_add_loc_code(np, pd);
 
 	/* 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..22b5f6d2 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_get_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..bef69052 100644
--- a/platforms/ibm-fsp/firenze-pci.c
+++ b/platforms/ibm-fsp/firenze-pci.c
@@ -972,3 +972,71 @@ void firenze_pci_get_slot_info(struct phb *phb, struct pci_device *pd)
 		firenze_pci_slot_init(slot);
 	}
 }
+
+void firenze_pci_get_loc_code(struct dt_node *np, struct pci_device *pd)
+{
+	struct dt_node *p = np->parent;
+	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
+	 */
+	while (p) {
+		blcode = dt_prop_get_def(p, "ibm,slot-location-code", NULL);
+		if (blcode)
+			break;
+
+		p = p-> parent;
+	}
+
+	/* 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 */
+		p = np->parent;
+		while (p) {
+			blcode = dt_prop_get_def(p, "ibm,loc-code", NULL);
+			if (blcode)
+				break;
+
+			p = p->parent;
+		}
+	}
+
+	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;
+
+	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..8fc72e9b 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_get_loc_code	= firenze_pci_get_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..122bbb41 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_get_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..a218b328 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_get_loc_code	= firenze_pci_get_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