Message ID | 1431643868-5581-1-git-send-email-dja@axtens.net |
---|---|
State | Accepted |
Headers | show |
On Fri, 2015-05-15 at 08:51 +1000, Daniel Axtens wrote: > On pHyp, the location code of ethernet adaptors ends with -Tn, where n > is the port number on the card. Detect if an adaptor advertises itself > as ethernet based on it's PCI class code, and if it does, give each > PCI function a -Tn suffix, where n = function number + 1. (Therefore n > is between 1 and 8 inclusive) > > This is a reasonably non-invasive change to match pHyp > behaviour. Alternatives considered were: Do we know that's how the "Tn" is assigned, ie, by function number ? Afaik, this is done by the f-code on the card which means it could be completely arbitrary. > - putting this in kernel space, which requires messing with the > device tree, which is frowned upon. > > - putting this in user space, which requires patching every userspace > tool that might consume this data, of which there are several. > > As such, while it's a bit of a hack, this is the best place for it. > > Signed-off-by: Daniel Axtens <dja@axtens.net> > --- > core/pci.c | 34 +++++++++++++++++++++++++++++++--- > 1 file changed, 31 insertions(+), 3 deletions(-) > > diff --git a/core/pci.c b/core/pci.c > index 8ea9177..477f806 100644 > --- a/core/pci.c > +++ b/core/pci.c > @@ -1145,10 +1145,14 @@ static void pci_add_slot_properties(struct phb *phb, struct pci_slot_info *info, > dt_add_property_string(np, "ibm,slot-label", info->label); > } > > -static void pci_add_loc_code(struct dt_node *np) > +static void pci_add_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; > > /* Look for a parent with a slot-location-code */ > while (p && !blcode) { > @@ -1157,7 +1161,31 @@ static void pci_add_loc_code(struct dt_node *np) > } > if (!blcode) > return; > - dt_add_property_string(np, "ibm,loc-code", blcode); > + > + /* 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)(pd->bdfn & 0x7) + '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); > } > > static void pci_print_summary_line(struct phb *phb, struct pci_device *pd, > @@ -1288,7 +1316,7 @@ static void pci_add_one_node(struct phb *phb, struct pci_device *pd, > pci_add_slot_properties(phb, pd->slot_info, np); > > /* Make up location code */ > - pci_add_loc_code(np); > + 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/core/pci.c b/core/pci.c index 8ea9177..477f806 100644 --- a/core/pci.c +++ b/core/pci.c @@ -1145,10 +1145,14 @@ static void pci_add_slot_properties(struct phb *phb, struct pci_slot_info *info, dt_add_property_string(np, "ibm,slot-label", info->label); } -static void pci_add_loc_code(struct dt_node *np) +static void pci_add_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; /* Look for a parent with a slot-location-code */ while (p && !blcode) { @@ -1157,7 +1161,31 @@ static void pci_add_loc_code(struct dt_node *np) } if (!blcode) return; - dt_add_property_string(np, "ibm,loc-code", blcode); + + /* 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)(pd->bdfn & 0x7) + '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); } static void pci_print_summary_line(struct phb *phb, struct pci_device *pd, @@ -1288,7 +1316,7 @@ static void pci_add_one_node(struct phb *phb, struct pci_device *pd, pci_add_slot_properties(phb, pd->slot_info, np); /* Make up location code */ - pci_add_loc_code(np); + 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
On pHyp, the location code of ethernet adaptors ends with -Tn, where n is the port number on the card. Detect if an adaptor advertises itself as ethernet based on it's PCI class code, and if it does, give each PCI function a -Tn suffix, where n = function number + 1. (Therefore n is between 1 and 8 inclusive) This is a reasonably non-invasive change to match pHyp behaviour. Alternatives considered were: - putting this in kernel space, which requires messing with the device tree, which is frowned upon. - putting this in user space, which requires patching every userspace tool that might consume this data, of which there are several. As such, while it's a bit of a hack, this is the best place for it. Signed-off-by: Daniel Axtens <dja@axtens.net> --- core/pci.c | 34 +++++++++++++++++++++++++++++++--- 1 file changed, 31 insertions(+), 3 deletions(-)