diff mbox

Add -Tn to ibm,loc-code for ethernet adaptors

Message ID 1431643868-5581-1-git-send-email-dja@axtens.net
State Accepted
Headers show

Commit Message

Daniel Axtens May 14, 2015, 10:51 p.m. UTC
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(-)

Comments

Benjamin Herrenschmidt May 15, 2015, 12:54 a.m. UTC | #1
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 mbox

Patch

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