[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