From 4834d5d108506c979f0e98e50afd570140503338 Mon Sep 17 00:00:00 2001
From: Jordan Hargrave <Jordan_Hargrave@dell.com>
Date: Fri, 28 Feb 2014 14:31:53 -0600
Subject: [PATCH 1/2] Cleanup SRIOV scanner code
---
src/pci.c | 166 ++++++++++++++++++++------------------------------------------
1 file changed, 54 insertions(+), 112 deletions(-)
diff --git a/src/pci.c b/src/pci.c
index dabb158..9b851df 100644
--- a/src/pci.c
+++ b/src/pci.c
@@ -351,67 +351,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) {
@@ -431,29 +379,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) &&
@@ -464,25 +389,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)
{
@@ -492,12 +398,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)
@@ -715,15 +615,57 @@ static int set_embedded_index(struct libbiosdevname_state *state)
return 0;
}
+static int virtfn_filter(const struct dirent *dent)
+{
+ return (!strncmp(dent->d_name,"virtfn",6));
+}
-
-static void set_sriov_pf_vf(struct libbiosdevname_state *state)
+/* 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);
}
}
@@ -799,6 +741,7 @@ 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);
rc = set_pci_slots(state);
if(rc)
@@ -806,7 +749,6 @@ int get_pci_devices(struct libbiosdevname_state *state)
set_embedded_index(state);
set_pci_slot_index(state);
- set_sriov_pf_vf(state);
out:
return rc;
--
1.9.0