File biosdevname_v0.5.0_to_git_c140ce659a204d67e4cc.patch of Package biosdevname

diff --git a/Makefile.am b/Makefile.am
index 28d3e8d..14d9a92 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -6,7 +6,7 @@ dist_noinst_DATA = biosdevname.rules.in biosdevname.spec.fedora biosdevname.spec
 
 
 
-CLEANFILES = version src/version.h
+CLEANFILES = version src/bios_dev_name.h
 install-data-local:
 	mkdir -p $(DESTDIR)@RULEDIR@
 	$(INSTALL_DATA) $(top_srcdir)/biosdevname.rules.in $(DESTDIR)@RULEDEST@
diff --git a/biosdevname.1 b/biosdevname.1
index 7067a56..22a53bd 100644
--- a/biosdevname.1
+++ b/biosdevname.1
@@ -31,16 +31,16 @@ Treat [args] as ethernet devs
 .B \-d, \-\-debug
 Enable debugging
 .TP
-.B \-\-policy \fI[physical|all_ethN]
+.B \-p, \-\-policy \fI[physical|all_ethN]
 .TP
-.B \-\-prefix \fI[string]
+.B \-P, \-\-prefix \fI[string]
 string use for embedded NICs in the physical policy (default=em)
 .TP
-.B \-\-nopirq
+.B \-x, \-\-nopirq
 Do not use $PIR table for mapping PCI device to slot. Some BIOS have
 incorrect values.
 .TP
-.B \-\-smbios \fI[x.y]
+.B \-s, \-\-smbios \fI[x.y]
 Require minimum SMBIOS version x.y
 .SH POLICIES
 .br
diff --git a/configure.ac b/configure.ac
index e26ba98..d08d42f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3,7 +3,7 @@
 # vim:tw=0:ts=8:sw=8:et
 
 AC_PREREQ(2.59)
-AC_INIT([biosdevname],[0.5.0],[Jordan_Hargrave@dell.com])
+AC_INIT([biosdevname],[0.5.1],[Jordan_Hargrave@dell.com])
 AC_LANG([C])
 AC_USE_SYSTEM_EXTENSIONS
 AC_CONFIG_SRCDIR([src/read_proc.c])
@@ -88,5 +88,5 @@ echo "PACKAGE_NAME='$PACKAGE_NAME'" > version
 echo "PACKAGE_VERSION='$PACKAGE_VERSION'" >> version
 echo "PACKAGE_STRING='$PACKAGE_STRING'" >> version
 
-AC_CONFIG_FILES([Makefile biosdevname.spec.fedora biosdevname.spec.suse src/version.h])
+AC_CONFIG_FILES([Makefile biosdevname.spec.fedora biosdevname.spec.suse src/bios_dev_name.h])
 AC_OUTPUT
diff --git a/src/bios_dev_name.c b/src/bios_dev_name.c
index 7374f9b..d0a917a 100644
--- a/src/bios_dev_name.c
+++ b/src/bios_dev_name.c
@@ -10,8 +10,6 @@
 #include <unistd.h>
 #include <sys/types.h>
 
-#include "version.h"
-
 #include "libbiosdevname.h"
 #include "bios_dev_name.h"
 
@@ -27,11 +25,11 @@ static void usage(void)
 	fprintf(stderr, " Options:\n");
 	fprintf(stderr, "   -i        or --interface           treat [args] as ethernet devs\n");
 	fprintf(stderr, "   -d        or --debug               enable debugging\n");
-	fprintf(stderr, "   --policy [physical | all_ethN ]\n");
-	fprintf(stderr, "   --prefix [string]                  string use for embedded NICs (default='em')\n");
-	fprintf(stderr, "   --smbios [x.y]		       Require SMBIOS x.y or greater\n");
-	fprintf(stderr, "   --nopirq			       Don't use $PIR table for slot numbers\n");
-	fprintf(stderr, "   --version                          Show biosdevname version\n");
+	fprintf(stderr, "   -p        or --policy [physical | all_ethN ]\n");
+	fprintf(stderr, "   -P        or --prefix [string]     string use for embedded NICs (default='em')\n");
+	fprintf(stderr, "   -s        or --smbios [x.y]	       Require SMBIOS x.y or greater\n");
+	fprintf(stderr, "   -x        or --nopirq	       Don't use $PIR table for slot numbers\n");
+	fprintf(stderr, "   -v        or --version             Show biosdevname version\n");
 	fprintf(stderr, " Example:  biosdevname -i eth0\n");
 	fprintf(stderr, "  returns: em1\n");
 	fprintf(stderr, "  when eth0 is an embedded NIC with label '1' on the chassis.\n");
@@ -70,7 +68,7 @@ parse_opts(int argc, char **argv)
 			{0, 0, 0, 0}
 		};
 		c = getopt_long(argc, argv,
-				"dinp:",
+				"dip:P:xs:v",
 				long_options, &option_index);
 		if (c == -1)
 			break;
diff --git a/src/bios_dev_name.h b/src/bios_dev_name.h
deleted file mode 100644
index 636c5e1..0000000
--- a/src/bios_dev_name.h
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- *  Copyright (c) 2006 Dell, Inc.
- *  by Matt Domsch <Matt_Domsch@dell.com>
- *  Licensed under the GNU General Public license, version 2.
- */
-#ifndef GLUE_H_INCLUDED
-#define GLUE_H_INCLUDED
-
-struct bios_dev_name_opts {
-	int argc;
-	char **argv;
-	int optind;
-	int sortroutine;
-	int namingpolicy;
-	const char *prefix;
-	unsigned int debug:1;
-	unsigned int interface:1;
-};
-
-#endif /* GLUE_H_INCLUDED */
diff --git a/src/bios_dev_name.h.in b/src/bios_dev_name.h.in
new file mode 100644
index 0000000..444c5e5
--- /dev/null
+++ b/src/bios_dev_name.h.in
@@ -0,0 +1,22 @@
+/*
+ *  Copyright (c) 2006 Dell, Inc.
+ *  by Matt Domsch <Matt_Domsch@dell.com>
+ *  Licensed under the GNU General Public license, version 2.
+ */
+#ifndef GLUE_H_INCLUDED
+#define GLUE_H_INCLUDED
+
+#define BIOSDEVNAME_VERSION "@PACKAGE_VERSION@"
+
+struct bios_dev_name_opts {
+	int argc;
+	char **argv;
+	int optind;
+	int sortroutine;
+	int namingpolicy;
+	const char *prefix;
+	unsigned int debug:1;
+	unsigned int interface:1;
+};
+
+#endif /* GLUE_H_INCLUDED */
diff --git a/src/bios_device.c b/src/bios_device.c
index 9e319a3..ba0661f 100644
--- a/src/bios_device.c
+++ b/src/bios_device.c
@@ -212,33 +212,17 @@ static void sort_device_list(struct libbiosdevname_state *state)
 	list_splice(&sorted_devices, &state->bios_devices);
 }
 
-static void match_pci_and_eth_devs(struct libbiosdevname_state *state)
+/* Check for Mellanox/Chelsio drivers */
+int ismultiport(const char *driver)
 {
-	struct pci_device *p;
-	struct bios_device *b;
-	struct network_device *n;
-
-	list_for_each_entry(n, &state->network_devices, node) {
-		p = find_dev_by_pci_name(state, n->drvinfo.bus_info);
-		if (!p)
-			continue;
-
-		b = malloc(sizeof(*b));
-		if (!b)
-			continue;
-		memset(b, 0, sizeof(*b));
-		INIT_LIST_HEAD(&b->node);
-		b->pcidev = p;
-		b->netdev = n;
-		b->slot_num = -1;
-		b->port_num = -1;
-		claim_netdev(b->netdev);
-		list_add(&b->node, &state->bios_devices);
-	}
+	if (!strncmp(driver, "mlx", 3))
+		return 1;
+	if (!strncmp(driver, "cxgb", 4))
+		return 1;
+	return 0;
 }
 
-
-static void match_eth_and_pci_devs(struct libbiosdevname_state *state)
+static void match_pci_and_eth_devs(struct libbiosdevname_state *state)
 {
 	struct pci_device *p;
 	struct bios_device *b;
@@ -249,22 +233,30 @@ static void match_eth_and_pci_devs(struct libbiosdevname_state *state)
 		if (!is_pci_network(p))
 			continue;
 
+		/* Loop through all ether devices to find match */
 		unparse_pci_name(pci_name, sizeof(pci_name), p->pci_dev);
-		n = find_net_device_by_bus_info(state, pci_name);
-		if (!n)
-			continue;
-
-		b = malloc(sizeof(*b));
-		if (!b)
-			continue;
-		memset(b, 0, sizeof(*b));
-		INIT_LIST_HEAD(&b->node);
-		b->pcidev = p;
-		b->netdev = n;
-		b->slot_num = -1;
-		b->port_num = -1;
-		claim_netdev(b->netdev);
-		list_add(&b->node, &state->bios_devices);
+		list_for_each_entry(n, &state->network_devices, node) {
+			if (strncmp(n->drvinfo.bus_info, pci_name, sizeof(n->drvinfo.bus_info)))
+				continue;
+			b = malloc(sizeof(*b));
+			if (!b)
+				continue;
+			memset(b, 0, sizeof(*b));
+			INIT_LIST_HEAD(&b->node);
+			b->pcidev = p;
+			b->netdev = n;
+			b->port = NULL;
+			if (ismultiport(n->drvinfo.driver)) {
+				b->port = malloc(sizeof(struct pci_port));
+				if (b->port != NULL) {
+					b->port->port = n->devid+1;
+					b->port->pfi = p->is_sriov_virtual_function ?
+						p->vf_index : -1;
+				}
+			}
+			claim_netdev(b->netdev);
+			list_add(&b->node, &state->bios_devices);
+		}
 	}
 }
 
@@ -286,8 +278,7 @@ static void match_unknown_eths(struct libbiosdevname_state *state)
 		memset(b, 0, sizeof(*b));
 		INIT_LIST_HEAD(&b->node);
 		b->netdev = n;
-		b->slot_num = -1;
-		b->port_num = -1;
+		b->port = NULL;
 		list_add(&b->node, &state->bios_devices);
 	}
 }
@@ -355,26 +346,6 @@ static void find_duplicates(struct libbiosdevname_state *state)
 	}
 }
 
-extern int addslot(struct libbiosdevname_state *state, int slot);
-
-/* Fix for RHBZ 816536/757743/756164/: Cards with same PCI but multiple ports
- * chelsio, mellanox */
-static void check_ports(struct libbiosdevname_state *state)
-{
-	struct pci_device *dev;
-	struct bios_device *a;
-
-	list_for_each_entry(a, &state->bios_devices, node) {
-		dev = a->pcidev;
-		if (dev == NULL || dev->is_sriov_virtual_function || dev->vpd_port != INT_MAX)
-			continue;
-		if (dev->physical_slot != PHYSICAL_SLOT_UNKNOWN) {
-			a->slot_num = dev->physical_slot;
-			a->port_num = addslot(state, 0x1000 + dev->physical_slot);
-		}
-	}
-}
-
 void * setup_bios_devices(int namingpolicy, const char *prefix)
 {
 	int rc=1;
@@ -390,7 +361,6 @@ void * setup_bios_devices(int namingpolicy, const char *prefix)
 	get_eths(state);
 	match_all(state);
 	sort_device_list(state);
-	check_ports(state);
 	rc = assign_bios_network_names(state, namingpolicy, prefix);
 	if (rc)
 		goto out;
diff --git a/src/bios_device.h b/src/bios_device.h
index d1ef911..158a2af 100644
--- a/src/bios_device.h
+++ b/src/bios_device.h
@@ -12,16 +12,15 @@
 #include "pci.h"
 #include "naming_policy.h"
 
+struct pci_port;
 
 struct bios_device {
 	struct list_head node;
 	struct network_device *netdev;
 	struct pci_device *pcidev;
 	char *bios_name;
+	struct pci_port *port;
 	int duplicate;
-
-	int slot_num;
-	int port_num;
 };
 
 static inline int is_pci(const struct bios_device *dev)
diff --git a/src/dmidecode/dmidecode.c b/src/dmidecode/dmidecode.c
index 3f761a9..f766b8c 100644
--- a/src/dmidecode/dmidecode.c
+++ b/src/dmidecode/dmidecode.c
@@ -119,14 +119,15 @@ int smbios_setslot(const struct libbiosdevname_state *state,
 	struct pci_device *pdev, *n;
 	int i;
 
-	dprintf("setslot: %.4x:%.2x:%.2x.%x = slot(%2d %2d) %s\n",
-		domain, bus, device, func, slot, index, label);
+	dprintf("setslot: %.4x:%.2x:%.2x.%x = type:%x slot(%2d %2d) %s\n",
+		domain, bus, device, func, type, slot, index, label);
 
 	/* Don't bother with disabled devices */
-	if ((bus == 0 && device == 0 && func == 0) ||    /* bug on HP systems */
+	if ((domain == 0xFFFF) ||
+	    (bus == 0 && device == 0 && func == 0) ||    /* bug on HP systems */
 	    (bus == 0xFF && device == 0x1F && func == 0x7)) 
 	{
-		dprintf("disabled\n");
+		dprintf("  disabled\n");
 		return;
 	}
 
@@ -153,18 +154,11 @@ int smbios_setslot(const struct libbiosdevname_state *state,
 		}
     
 		/* Found a PDEV, now is it a bridge? */
-		if (pdev->sbus == -1)
-		  continue;
-		dprintf("scan subbus: %d\n", pdev->sbus);
-		list_for_each_entry(n, &state->pci_devices, node) {
-			if (matchpci(n, domain, pdev->sbus, -1, -1)) {
-				smbios_setslot(state, n->pci_dev->domain, n->pci_dev->bus, 
-					       n->pci_dev->dev, n->pci_dev->func,
-					       type, slot, index, label);
-			}
+		if (pdev->sbus != -1) {
+			smbios_setslot(state, domain, pdev->sbus, -1, -1, type, slot, index, label);
 		}
-		dprintf("done subbus: %d\n", pdev->sbus);
 	}
+	return 0;
 }
 
 static void dmi_decode(struct dmi_header *h, u16 ver, const struct libbiosdevname_state *state)
@@ -179,12 +173,9 @@ static void dmi_decode(struct dmi_header *h, u16 ver, const struct libbiosdevnam
 			bus = data[0x0F];
 			device = (data[0x10]>>3)&0x1F;
 			function = data[0x10] & 7;
-			if (domain != 0xFFFF) {
-				for (i=0; i<8; i++) 
-					smbios_setslot(state, domain, bus, device, i, 
-						       0x00, WORD(data+0x09), 0x00,
-						       dmi_string(h, data[0x04]));
-			}
+			smbios_setslot(state, domain, bus, device, -1, 
+				       0x00, WORD(data+0x09), 0x00,
+				       dmi_string(h, data[0x04]));
 		}
 		else {
 			dprintf("Old Slot: id:%3d, type:%.2x, label:%-7s\n", WORD(data+0x09), data[0x05], dmi_string(h, data[0x04]));
@@ -361,6 +352,57 @@ static int address_from_efi(size_t *address)
 
 static const char *devmem = "/dev/mem";
 
+int dmidecode_read_file(const struct libbiosdevname_state *state)
+{
+#ifdef _JPH
+	FILE *fp;
+	const char *dmidecode_file = "dmidecode.txt";
+	char line[128], *r;
+	int type = -1, eth=0,s,b,d,f,slot,i;
+
+	if ((fp = fopen(dmidecode_file, "r")) == NULL)
+		return 0;
+	while ((fgets(line, sizeof(line), fp)) != NULL) {
+		if (strstr(line, " DMI type 41,") != NULL) {
+			type = 41;
+			eth = 0;
+			slot = -1;
+		} else if (strstr(line, " DMI type 9,") != NULL) {
+			type = 9;
+		} else if (strstr(line, " DMI type ") != NULL) {
+			type = -1;
+		}
+		if (type == 41) {
+			if ((r = strstr(line, "Type: Ethernet")) != NULL) {
+				eth = 1;
+			}
+			if ((r = strstr(line, "Type Instance: ")) != NULL) {
+				sscanf(r, "Type Instance: %d", &slot);
+			}
+			if ((r = strstr(line, "Bus Address: ")) != NULL && eth) {
+				sscanf(r, "Bus Address: %x:%x:%x.%x", &s,&b,&d,&f);
+				printf("bus: %.4x:%.2x:%.2x.%x\n", s, b, d, f);
+				smbios_setslot(state, s, b, d, f, 0x5, 0x00, slot, "");
+			}
+		}
+		if (type == 9) {
+			/* System Slots */
+			if ((r = strstr(line, "ID: ")) != NULL) {
+				sscanf(r, "ID: %d", &slot);
+			}
+			if ((r = strstr(line, "Bus Address: ")) != NULL) {
+				sscanf(r, "Bus Address: %x:%x:%x.%x", &s,&b,&d,&f);
+				printf("bus: %.4x:%.2x:%.2x.%x = %d\n", s, b, d, f, slot);
+				for (i=0; i<8; i++)
+					smbios_setslot(state, s, b, d, i, 0x00, slot, 0x00, "");
+			}
+		}
+	}
+	return 1;
+#endif
+	return 0;
+}
+
 int dmidecode_main(const struct libbiosdevname_state *state)
 {
 	int ret=0;                  /* Returned value */
@@ -369,6 +411,9 @@ int dmidecode_main(const struct libbiosdevname_state *state)
 	int efi;
 	u8 *buf;
 
+	if (dmidecode_read_file(state))
+		return 0;
+
 	/* First try EFI (ia64, Intel-based Mac) */
 	efi=address_from_efi(&fp);
 	switch(efi)
diff --git a/src/eths.c b/src/eths.c
index bcd02e1..38bb7fe 100644
--- a/src/eths.c
+++ b/src/eths.c
@@ -34,6 +34,20 @@ char *pr_ether(char *buf, const int size, const unsigned char *s)
 	return (buf);
 }
 
+static int eths_get_devid(const char *devname, int *devid)
+{
+	char path[PATH_MAX];
+	char *devidstr = NULL;
+
+	*devid = -1;
+	snprintf(path, sizeof(path), "/sys/class/net/%s/dev_id", devname);
+	if (sysfs_read_file(path, &devidstr) == 0) {
+		sscanf(devidstr, "%i", devid);
+		free(devidstr);
+	}
+	return NULL;
+}
+
 static int eths_get_ifindex(const char *devname, int *ifindex)
 {
 	int fd, err;
@@ -149,6 +163,7 @@ static void fill_eth_dev(struct network_device *dev)
 	eths_get_ifindex(dev->kernel_name, &dev->ifindex);
 	eths_get_hwaddr(dev->kernel_name, dev->dev_addr, sizeof(dev->dev_addr), &dev->arphrd_type);
 	eths_get_permaddr(dev->kernel_name, dev->perm_addr, sizeof(dev->perm_addr));
+	eths_get_devid(dev->kernel_name, &dev->devid);
 	rc = eths_get_info(dev->kernel_name, &dev->drvinfo);
 	if (rc == 0)
 		dev->drvinfo_valid = 1;
diff --git a/src/eths.h b/src/eths.h
index f686136..12c278b 100644
--- a/src/eths.h
+++ b/src/eths.h
@@ -27,6 +27,7 @@ struct network_device {
 	int arphrd_type; /* e.g. ARPHDR_ETHER */
 	int hardware_claimed; /* true when recognized as PCI or PCMCIA and added to list of bios_devices */
   	int ifindex;
+	int devid;
 };
 
 extern void get_eths(struct libbiosdevname_state *state);
diff --git a/src/naming_policy.c b/src/naming_policy.c
index fe7b934..7138a4b 100644
--- a/src/naming_policy.c
+++ b/src/naming_policy.c
@@ -55,12 +55,14 @@ static void use_physical(const struct libbiosdevname_state *state, const char *p
 					vf = vf->vpd_pf;
 				if (vf->pf)
 				  	vf = vf->pf;
-				if (vf->uses_sysfs & HAS_SYSFS_INDEX)
+				if (dev->port)
+					portnum = dev->port->port;
+				else if (vf->uses_sysfs & HAS_SYSFS_INDEX)
 					portnum = vf->sysfs_index;
 				else if (vf->uses_smbios & HAS_SMBIOS_INSTANCE && is_pci_smbios_type_ethernet(vf))
 					portnum = vf->smbios_instance;
-				else if (dev->port_num != -1)
-					portnum = dev->port_num;
+				else if (vf->embedded_index_valid)
+					portnum = vf->embedded_index;
 				if (portnum != INT_MAX) {	
 					snprintf(location, sizeof(location), "%s%u", prefix, portnum);
 					known=1;
@@ -68,10 +70,10 @@ static void use_physical(const struct libbiosdevname_state *state, const char *p
 			}
 			else if (dev->pcidev->physical_slot < PHYSICAL_SLOT_UNKNOWN) {
 				snprintf(location, sizeof(location), "p%u", dev->pcidev->physical_slot);
-				if (dev->pcidev->vpd_port < INT_MAX)
+				if (dev->port)
+					portnum = dev->port->port;
+				else if (dev->pcidev->vpd_port < INT_MAX)
 					portnum = dev->pcidev->vpd_port;
-				else if (dev->port_num != -1)
-					portnum = dev->port_num;
 				else if (!dev->pcidev->is_sriov_virtual_function)
 				  	portnum = dev->pcidev->index_in_slot;
 				else
@@ -80,7 +82,9 @@ static void use_physical(const struct libbiosdevname_state *state, const char *p
 				known=1;
 			}
 
-			if (dev->pcidev->is_sriov_virtual_function)
+			if (dev->port && dev->port->pfi != -1)
+				snprintf(interface, sizeof(interface), "_%u", dev->port->pfi);
+			else if (dev->pcidev->is_sriov_virtual_function)
 				snprintf(interface, sizeof(interface), "_%u", dev->pcidev->vf_index);
 			else if (dev->pcidev->vpd_pfi < INT_MAX)
 				snprintf(interface, sizeof(interface), "_%u", dev->pcidev->vpd_pfi);
diff --git a/src/pci.c b/src/pci.c
index d017c50..7a7cb36 100644
--- a/src/pci.c
+++ b/src/pci.c
@@ -30,6 +30,7 @@ extern int is_valid_smbios;
 /* Borrowed from kernel vpd code */
 #define PCI_VPD_LRDT 			0x80
 #define PCI_VPD_SRDT_END 		0x78
+#define PCI_VPDR_TAG                    0x90
 
 #define PCI_VPD_SRDT_LEN_MASK		0x7
 #define PCI_VPD_LRDT_TAG_SIZE		3
@@ -71,7 +72,7 @@ static int pci_vpd_size(struct pci_device *pdev, int fd)
 			tag = buf[0] & ~PCI_VPD_SRDT_LEN_MASK;
 			off += PCI_VPD_SRDT_TAG_SIZE + pci_vpd_srdt_size(buf);
 		}
-		if (tag == 0 || tag == 0xFF || tag == PCI_VPD_SRDT_END)
+		if (tag == 0 || tag == 0xFF || tag == PCI_VPD_SRDT_END || tag == PCI_VPDR_TAG)
 			break;
 	}
 	return off;
@@ -120,12 +121,31 @@ static int pci_vpd_find_info_subkey(const u8 *buf, unsigned int off, unsigned in
 	return -1;
 }
 
+/* Add port identifier(s) to PCI device */
+static void add_port(struct pci_device *pdev, int port, int pfi)
+{
+	struct pci_port *p;
+
+	list_for_each_entry(p, &pdev->ports, node) {
+		if (p->port == port && p->pfi == pfi)
+			return;
+	}
+	p = malloc(sizeof(*p));
+	if (p == NULL)
+		return;
+	memset(p, 0, sizeof(*p));
+	INIT_LIST_HEAD(&p->node);
+	p->port = port;
+	p->pfi = pfi;
+	list_add_tail(&p->node, &pdev->ports);
+}
+
 static int parse_vpd(struct libbiosdevname_state *state, struct pci_device *pdev, int len, unsigned char *vpd)
 {
 	int i, j, k, isz, jsz, port, func, pfi;
 	struct pci_device *vf;
 
-	i = pci_vpd_find_tag(vpd, 0, len, 0x90);
+	i = pci_vpd_find_tag(vpd, 0, len, PCI_VPDR_TAG);
 	if (i < 0)
 		return 1;
 	isz = pci_vpd_lrdt_size(&vpd[i]);
@@ -154,6 +174,7 @@ static int parse_vpd(struct libbiosdevname_state *state, struct pci_device *pdev
 						   pdev->pci_dev->bus,
 						   pdev->pci_dev->dev,
 						   func)) != NULL) {
+			add_port(vf, port, pfi);
 			if (vf->vpd_port == INT_MAX) {
 				vf->vpd_port = port;
 				vf->vpd_pfi = pfi;
@@ -324,67 +345,15 @@ static int read_pci_sysfs_physfn(char *buf, size_t bufsize, const struct pci_dev
 	return 0;
 }
 
-static int virtfn_filter(const struct dirent *dent)
-{
-        return (!strncmp(dent->d_name,"virtfn",6));
-}
-
-static int _read_virtfn_index(unsigned int *index, const char *path, const char *basename, const char *pci_name)
-{
-	char buf[PATH_MAX], *b;
-	char fullpath[PATH_MAX];
-	ssize_t size;
-	unsigned int u=INT_MAX;
-	int scanned, rc=1;
-
-	snprintf(fullpath, sizeof(fullpath), "%s/%s", path, basename);
-	size = readlink(fullpath, buf, sizeof(buf));
-	if (size > 0) {
-		/* form is ../0000:05:10.0 */
-		b=buf+3; /* skip ../ */
-		if (strlen(b) == strlen(pci_name) &&
-		    !strncmp(b, pci_name, strlen(pci_name))) {
-			scanned = sscanf(basename, "virtfn%u", &u);
-			if (scanned == 1) {
-				rc = 0;
-				*index = u;
-			}
-		}
-	}
-	return rc;
-}
-
-static int read_virtfn_index(unsigned int *index, const struct pci_dev *pdev)
-{
-	char pci_name[16];
-	char path[PATH_MAX];
-	char cpath[PATH_MAX];
-	struct dirent **namelist;
-	int n, rc=1;
-
-	unparse_pci_name(pci_name, sizeof(pci_name), pdev);
-	snprintf(path, sizeof(path), "/sys/bus/pci/devices/%s/physfn", pci_name);
-	if (realpath(path, cpath) == NULL)
-		return rc;
-
-	n = scandir(cpath, &namelist, virtfn_filter, versionsort);
-	if (n < 0)
-		return rc;
-	else {
-		while (n--) {
-			if (rc)
-				rc = _read_virtfn_index(index, cpath, namelist[n]->d_name, pci_name);
-			free(namelist[n]);
-		}
-		free(namelist);
-	}
-
-	return rc;
-}
-
 static int parse_pci_name(const char *s, int *domain, int *bus, int *dev, int *func)
 {
 	int err;
+	const char *r;
+
+	/* Allow parsing pathnames */
+	if ((r = strrchr(s, '/')) != NULL)
+		s = r+1;
+
 /* The domain part was added in 2.6 kernels.  Test for that first. */
 	err = sscanf(s, "%x:%2x:%2x.%x", domain, bus, dev, func);
 	if (err != 4) {
@@ -404,29 +373,6 @@ static struct pci_dev * find_pdev_by_pci_name(struct pci_access *pacc, const cha
 	return pci_get_dev(pacc, domain, bus, device, func);
 }
 
-static struct pci_device *
-find_physfn(struct libbiosdevname_state *state, struct pci_device *dev)
-{
-	int rc;
-	char path[PATH_MAX];
-	char *c;
-	struct pci_dev *pdev;
-	memset(path, 0, sizeof(path));
-	rc = read_pci_sysfs_physfn(path, sizeof(path), dev->pci_dev);
-	if (rc != 0)
-		return NULL;
-	/* we get back a string like
-	   ../0000:05:0.0
-	   where the last component is the parent device
-	*/
-	/* find the last backslash */
-	c = rindex(path, '/');
-	c++;
-	pdev = find_pdev_by_pci_name(state->pacc, c);
-	dev = find_dev_by_pci(state, pdev);
-	return dev;
-}
-
 static int is_same_pci(const struct pci_dev *a, const struct pci_dev *b)
 {
 	if (pci_domain_nr(a) == pci_domain_nr(b) &&
@@ -437,25 +383,6 @@ static int is_same_pci(const struct pci_dev *a, const struct pci_dev *b)
 	return 0;
 }
 
-static void try_add_vf_to_pf(struct libbiosdevname_state *state, struct pci_device *vf)
-{
-	struct pci_device *pf;
-	unsigned int index=0;
-	int rc;
-	pf = find_physfn(state, vf);
-
-	if (!pf)
-		return;
-	list_add_tail(&vf->vfnode, &pf->vfs);
-	rc = read_virtfn_index(&index, vf->pci_dev);
-	if (!rc) {
-		vf->vf_index = index;
-		pf->is_sriov_physical_function = 1;
-	}
-	vf->pf = pf;
-	vf->physical_slot = pf->physical_slot;
-}
-
 static struct pci_device *
 find_parent(struct libbiosdevname_state *state, struct pci_device *dev)
 {
@@ -465,12 +392,6 @@ find_parent(struct libbiosdevname_state *state, struct pci_device *dev)
 	struct pci_device *physfn;
 	struct pci_dev *pdev;
 	memset(path, 0, sizeof(path));
-	/* if this device has a physfn pointer, then treat _that_ as the parent */
-	physfn = find_physfn(state, dev);
-	if (physfn) {
-		dev->is_sriov_virtual_function=1;
-		return physfn;
-	}
 
 	rc = read_pci_sysfs_path(path, sizeof(path), dev->pci_dev);
 	if (rc != 0)
@@ -553,6 +474,7 @@ static int read_pci_sysfs_index(unsigned int *index, const struct pci_dev *pdev)
 	rc = sysfs_read_file(path, &indexstr);
 	if (rc == 0) {
 		rc = sscanf(indexstr, "%u", &i);
+		free(indexstr);
 		if (rc == 1)  {
 			*index = i;
 			return 0;
@@ -595,6 +517,7 @@ static void add_pci_dev(struct libbiosdevname_state *state,
 	INIT_LIST_HEAD(&dev->node);
 	INIT_LIST_HEAD(&dev->vfnode);
 	INIT_LIST_HEAD(&dev->vfs);
+	INIT_LIST_HEAD(&dev->ports);
 	dev->pci_dev = p;
 	dev->physical_slot = PHYSICAL_SLOT_UNKNOWN;
 	dev->class         = pci_read_word(p, PCI_CLASS_DEVICE);
@@ -631,24 +554,6 @@ void free_pci_devices(struct libbiosdevname_state *state)
 	}
 }
 
-int addslot(struct libbiosdevname_state *state, int slot)
-{
-	struct slotlist *s;
-
-	list_for_each_entry(s, &state->slots, node) {
-		if (s->slot == slot) {
-			return ++s->count;
-		}
-	}
-	s = malloc(sizeof(*s));
-	INIT_LIST_HEAD(&s->node);
-	s->slot = slot;
-	s->count = 0;
-	list_add(&s->node, &state->slots);
-
-	return ++s->count;
-}
-
 static void set_pci_slots(struct libbiosdevname_state *state)
 {
 	struct pci_device *dev;
@@ -656,28 +561,105 @@ static void set_pci_slots(struct libbiosdevname_state *state)
 	list_for_each_entry(dev, &state->pci_devices, node) {
 		dev_to_slot(state, dev);
 	}
+}
 
-	/* Get mapping for each slot */
-	list_for_each_entry(dev, &state->pci_devices, node) {
-		if (dev->is_sriov_virtual_function || !is_pci_network(dev) || dev->vpd_port != INT_MAX) {
+static int set_pci_slot_index(struct libbiosdevname_state *state)
+{
+	struct pci_device *pcidev;
+	int prevslot=-1;
+	int index=1;
+
+	/* only iterate over the PCI devices, because the bios_device list may be incomplete due to renames happening in parallel */
+	list_for_each_entry(pcidev, &state->pci_devices, node) {
+		if (pcidev->physical_slot == 0) /* skip embedded devices */
 			continue;
+		if (!is_pci_network(pcidev)) /* only look at PCI network devices */
+			continue;
+		if (pcidev->is_sriov_virtual_function) /* skip sriov VFs, they're handled later */
+			continue;
+		if (pcidev->physical_slot != prevslot) {
+			index=1;
+			prevslot = pcidev->physical_slot;
 		}
-		if (dev->physical_slot == 0) {
-			dev->embedded_index_valid = 1;
-			dev->embedded_index = addslot(state, 0);
-		} else if (dev->physical_slot != PHYSICAL_SLOT_UNKNOWN) {
-			dev->index_in_slot = addslot(state, dev->physical_slot);
-		}
+		else
+			index++;
+		pcidev->index_in_slot = index;
+	}
+	return 0;
+}
+
+static int set_embedded_index(struct libbiosdevname_state *state)
+{
+	struct pci_device *pcidev;
+	int index=1;
+
+	list_for_each_entry(pcidev, &state->pci_devices, node) {
+		if (pcidev->physical_slot != 0) /* skip non-embedded devices */
+			continue;
+		if (!is_pci_network(pcidev)) /* only look at PCI network devices */
+			continue;
+		if (pcidev->is_sriov_virtual_function) /* skip sriov VFs, they're handled later */
+			continue;
+		if (pcidev->vpd_port != INT_MAX)
+			continue;
+		pcidev->embedded_index = index;
+		pcidev->embedded_index_valid = 1;
+		index++;
 	}
+	return 0;
 }
 
-static void set_sriov_pf_vf(struct libbiosdevname_state *state)
+static int virtfn_filter(const struct dirent *dent)
+{
+        return (!strncmp(dent->d_name,"virtfn",6));
+}
+
+/* Assign Virtual Function to Physical Function */
+static void set_sriov(struct libbiosdevname_state *state, struct pci_device *pf, const char *virtpath)
 {
 	struct pci_device *vf;
-	list_for_each_entry(vf, &state->pci_devices, node) {
-		if (!vf->is_sriov_virtual_function)
+	char pci_name[32];
+	char path[PATH_MAX], cpath[PATH_MAX];
+	int vf_index;
+
+	if (sscanf(virtpath, "virtfn%u", &vf_index) != 1)
+		return;
+	unparse_pci_name(pci_name, sizeof(pci_name), pf->pci_dev);
+	snprintf(path, sizeof(path), "/sys/bus/pci/devices/%s/%s", pci_name, virtpath);
+
+	memset(cpath, 0, sizeof(cpath));
+	if (readlink(path, cpath, sizeof(cpath)) < 0)
+		return;
+	if ((vf = find_dev_by_pci_name(state, cpath)) != NULL) {
+		vf->is_sriov_virtual_function = 1;
+		vf->vf_index = vf_index;
+		vf->pf = pf;
+		pf->is_sriov_physical_function = 1;
+		list_add_tail(&vf->vfnode, &pf->vfs);
+	}
+}
+
+static void scan_sriov(struct libbiosdevname_state *state)
+{
+	struct pci_device *pf;
+	char path[PATH_MAX];
+	char pci_name[32];
+	struct dirent **namelist;
+	int n;
+
+	list_for_each_entry(pf, &state->pci_devices, node) {
+		unparse_pci_name(pci_name, sizeof(pci_name), pf->pci_dev);
+		snprintf(path, sizeof(path), "/sys/bus/pci/devices/%s", pci_name);
+
+		namelist = NULL;
+		n = scandir(path, &namelist, virtfn_filter, versionsort);
+		if (n <= 0)
 			continue;
-		try_add_vf_to_pf(state, vf);
+		while (n--) {
+			set_sriov(state, pf, namelist[n]->d_name);
+			free(namelist[n]);
+		}
+		free(namelist);
 	}
 }
 
@@ -753,9 +735,11 @@ int get_pci_devices(struct libbiosdevname_state *state)
 	/* ordering here is important */
 	dmidecode_main(state);	/* this will fail on Xen guests, that's OK */
 	sort_device_list(state);
+	scan_sriov(state);
 	set_pci_vpd_instance(state);
 	set_pci_slots(state);
-	set_sriov_pf_vf(state);
+	set_embedded_index(state);
+	set_pci_slot_index(state);
 
 	return rc;
 }
diff --git a/src/pci.h b/src/pci.h
index 77b4746..eacb539 100644
--- a/src/pci.h
+++ b/src/pci.h
@@ -20,6 +20,12 @@ struct slotlist
 	int count;
 };
 
+struct pci_port {
+	struct list_head node;
+	int port;
+	int pfi;
+};
+
 struct pci_device {
 	struct list_head node;
 	struct pci_dev *pci_dev;
@@ -44,6 +50,7 @@ struct pci_device {
 	struct pci_device *pf;
 	struct list_head vfnode;
 	struct list_head vfs;
+	struct list_head ports;
 	unsigned int is_sriov_physical_function:1;
 	unsigned int is_sriov_virtual_function:1;
 	unsigned int embedded_index_valid:1;
diff --git a/src/pirq.c b/src/pirq.c
index 6568c24..0aa4d0c 100644
--- a/src/pirq.c
+++ b/src/pirq.c
@@ -44,7 +44,53 @@ int pirq_pci_dev_to_slot(struct routing_table *table, int domain, int bus, int d
 	return INT_MAX;
 }
 
+struct routing_table *pirq_read_file()
+{
+#ifdef _JPH
+	FILE *fp;
+	char  line[128];
+	struct routing_table *table;
+	char *r;
+	int count, bus, dev, slot;
+	const char *pirq_file = "biosdecode.txt";
 
+	/* Get count of entries */
+	if ((fp = fopen(pirq_file, "r")) == NULL)
+		return NULL;
+	count = 0;
+	while (fgets(line, sizeof(line), fp) != NULL) {
+		if (strstr(line, "Slot Entry") != NULL)
+			count++;
+	}
+	fclose(fp);
+
+	/* Read table */
+	table = malloc(sizeof(*table) + count * sizeof(struct slot_entry));
+	table->size = 32 + (sizeof(struct slot_entry) * count);
+	if ((fp = fopen(pirq_file, "r")) == NULL)
+		return NULL;
+	count = 0;
+	while (fgets(line, sizeof(line), fp) != NULL) {
+		if ((r = strstr(line, "Slot Entry")) == NULL)
+			continue;
+		if (sscanf(r, "Slot Entry %*d: ID %x:%x", &bus, &dev) == 2) {
+			table->slot[count].bus = bus;
+			table->slot[count].device = dev << 3;
+			if ((r = strstr(line, "on-board")) != NULL)
+				table->slot[count].slot = 0;
+			else if ((r = strstr(line, "slot number ")) != NULL) {
+				sscanf(r, "slot number %d", &slot);
+				table->slot[count].slot = slot;
+			}
+			printf("%d = %.2x:%.2x = %d\n", count, bus, dev, table->slot[count].slot);
+			count++;
+		}
+	}
+	fclose(fp);
+	return table;
+#endif
+	return NULL;
+}
 
 struct routing_table * pirq_alloc_read_table()
 {
@@ -60,6 +106,9 @@ struct routing_table * pirq_alloc_read_table()
 	if (nopirq) {
 		return NULL;
 	}
+	if ((table = pirq_read_file()) != NULL)
+		return table;
+
 	fd = open("/dev/mem", O_RDONLY);
 	if(fd==-1)
 		return NULL;
diff --git a/src/sysfs.c b/src/sysfs.c
index 71e84e7..e276240 100644
--- a/src/sysfs.c
+++ b/src/sysfs.c
@@ -32,7 +32,7 @@ int sysfs_path_is_file(const char * path)
 int sysfs_read_file(const char * path, char **output)
 {
 	int ret;
-	char *result = NULL;
+	char *result = NULL, *n;
 	int fd;
 	unsigned long resultsize = 0;
 	ssize_t length = 0;
@@ -57,8 +57,8 @@ int sysfs_read_file(const char * path, char **output)
 		goto free_out;
 	}
 	result[length] = '\0';
-	if (result[length-1] == '\n')
-		result[length-1] = '\0';
+	if ((n = strchr(result, '\n')) != NULL)
+		*n = '\0';
 	*output = result;
 	ret = 0;
 	goto out;
diff --git a/src/version.h.in b/src/version.h.in
deleted file mode 100644
index bcc0fda..0000000
--- a/src/version.h.in
+++ /dev/null
@@ -1 +0,0 @@
-#define BIOSDEVNAME_VERSION "@PACKAGE_VERSION@"
openSUSE Build Service is sponsored by