Blob Blame History Raw
From 76ada4fa8f5aa64d2de254aa5081582a77384b09 Mon Sep 17 00:00:00 2001
From: Petr Oros <poros@redhat.com>
Date: Thu, 16 Mar 2017 17:50:53 +0100
Subject: [PATCH] Proper detect vendor_id/device_id for virtual functions

  PCI Single Root I/O Virtualization and Sharing  (AKA SRIOV)
  Specification Revision 1.1 sections 3.4.1.1 and 3.4.1.2 control these values.
  Both the Vendor ID and the Device ID are required to return values of "FFFFh when read.

  Proper value can read from sysfs

  Tests:
  Before patch
    # lshw -short -numeric -class network
    H/W path            Device      Class          Description
    ==========================================================
    /0/9/0                          network        82599ES 10-Gigabit SFI/SFP+ Network Connection [8086:10FB]
    /0/9/0.1            p3p2        network        82599ES 10-Gigabit SFI/SFP+ Network Connection [8086:10FB]
    /0/9/10.1           p3p2_0      network        Illegal Vendor ID [FFFF:FFFF]
    /0/9/10.3           p3p2_1      network        Illegal Vendor ID [FFFF:FFFF]

  After patch
    # lshw -short -numeric -class network
    H/W path            Device      Class      Description
    ======================================================
    /0/9/0                          network    82599ES 10-Gigabit SFI/SFP+ Network Connection [8086:10FB]
    /0/9/0.1            p3p2        network    82599ES 10-Gigabit SFI/SFP+ Network Connection [8086:10FB]
    /0/9/10.1           p3p2_0      network    82599 Ethernet Controller Virtual Function [8086:10ED]
    /0/9/10.3           p3p2_1      network    82599 Ethernet Controller Virtual Function [8086:10ED]

Signed-off-by: Petr Oros <poros@redhat.com>
---
 src/core/pci.cc   | 13 ++++++++++---
 src/core/sysfs.cc | 10 ++++++++++
 src/core/sysfs.h  |  2 ++
 3 files changed, 22 insertions(+), 3 deletions(-)

diff --git a/src/core/pci.cc b/src/core/pci.cc
index d1625cf..7803eac 100644
--- a/src/core/pci.cc
+++ b/src/core/pci.cc
@@ -774,8 +774,12 @@ static hwNode *scan_pci_dev(struct pci_dev &d, hwNode & n)
   if(!pcidb_loaded)
     pcidb_loaded = load_pcidb();
 
-      d.vendor_id = get_conf_word(d, PCI_VENDOR_ID);
-      d.device_id = get_conf_word(d, PCI_DEVICE_ID);
+      u_int16_t tmp_vendor_id = get_conf_word(d, PCI_VENDOR_ID);
+      u_int16_t tmp_device_id = get_conf_word(d, PCI_DEVICE_ID);
+      if ((tmp_vendor_id & tmp_device_id) != 0xffff) {
+        d.vendor_id = tmp_vendor_id;
+        d.device_id = tmp_device_id;
+      }
       u_int16_t dclass = get_conf_word(d, PCI_CLASS_DEVICE);
       u_int16_t cmd = get_conf_word(d, PCI_COMMAND);
       u_int16_t status = get_conf_word(d, PCI_STATUS);
@@ -1122,6 +1126,7 @@ bool scan_pci(hwNode & n)
     if(matches(devices[i]->d_name, "^[[:xdigit:]]+:[[:xdigit:]]+:[[:xdigit:]]+\\.[[:xdigit:]]+$"))
     {
       string devicepath = string(devices[i]->d_name)+"/config";
+      sysfs::entry device_entry = sysfs::entry::byBus("pci", devices[i]->d_name);
       struct pci_dev d;
       int fd = open(devicepath.c_str(), O_RDONLY);
       if (fd >= 0)
@@ -1136,6 +1141,8 @@ bool scan_pci(hwNode & n)
       }
 
       sscanf(devices[i]->d_name, "%hx:%hx:%hhx.%hhx", &d.domain, &d.bus, &d.dev, &d.func);
+      sscanf(device_entry.vendor().c_str(), "%hx", &d.vendor_id);
+      sscanf(device_entry.device().c_str(), "%hx", &d.device_id);
       hwNode *device = scan_pci_dev(d, n);
 
       if(device)
@@ -1166,7 +1173,7 @@ bool scan_pci(hwNode & n)
           device->claim();
         }
 
-	device->setModalias(sysfs::entry::byBus("pci", devices[i]->d_name).modalias());
+        device->setModalias(device_entry.modalias());
 
         if(exists(resourcename))
         {
diff --git a/src/core/sysfs.cc b/src/core/sysfs.cc
index 97dbab5..486f8ee 100644
--- a/src/core/sysfs.cc
+++ b/src/core/sysfs.cc
@@ -358,6 +358,16 @@ string entry::modalias() const
   return get_string(This->devpath+"/modalias");
 }
 
+string entry::device() const
+{
+  return get_string(This->devpath+"/device");
+}
+
+string entry::vendor() const
+{
+  return get_string(This->devpath+"/vendor");
+}
+
 vector < entry > sysfs::entries_by_bus(const string & busname)
 {
   vector < entry > result;
diff --git a/src/core/sysfs.h b/src/core/sysfs.h
index d37e2d4..dffa4b2 100644
--- a/src/core/sysfs.h
+++ b/src/core/sysfs.h
@@ -26,6 +26,8 @@ namespace sysfs
       string businfo() const;
       string driver() const;
       string modalias() const;
+      string device() const;
+      string vendor() const;
       entry parent() const;
       string name_in_class(const string &) const;
       string string_attr(const string & name, const string & def = "") const;
-- 
2.10.2