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