Skip to content

Commit

Permalink
PCI: create optional loc-code platform callback
Browse files Browse the repository at this point in the history
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@linux.vnet.ibm.com>
Signed-off-by: Oliver O'Halloran <oohall@gmail.com>
  • Loading branch information
Klaus Heinrich Kiwi authored and oohal committed Feb 24, 2020
1 parent 59482b9 commit ab1b05d
Show file tree
Hide file tree
Showing 6 changed files with 89 additions and 35 deletions.
42 changes: 7 additions & 35 deletions core/pci.c
Expand Up @@ -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;
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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
Expand Down
8 changes: 8 additions & 0 deletions include/platform.h
Expand Up @@ -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
Expand Down
70 changes: 70 additions & 0 deletions platforms/ibm-fsp/firenze-pci.c
Expand Up @@ -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);
}
}
1 change: 1 addition & 0 deletions platforms/ibm-fsp/firenze.c
Expand Up @@ -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,
Expand Down
2 changes: 2 additions & 0 deletions platforms/ibm-fsp/ibm-fsp.h
Expand Up @@ -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);
Expand Down
1 change: 1 addition & 0 deletions platforms/ibm-fsp/zz.c
Expand Up @@ -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,
Expand Down

0 comments on commit ab1b05d

Please sign in to comment.