Signed-off-by: Waldemar Kozaczuk <[email protected]>
---
 drivers/pci-function.cc      | 46 +++++++++---------------------
 drivers/pci-function.hh      |  3 +-
 drivers/virtio-pci-device.cc | 54 +++++++++++++++++++++++-------------
 drivers/virtio-pci-device.hh |  7 +++--
 4 files changed, 54 insertions(+), 56 deletions(-)

diff --git a/drivers/pci-function.cc b/drivers/pci-function.cc
index b0fb3674..4866075e 100644
--- a/drivers/pci-function.cc
+++ b/drivers/pci-function.cc
@@ -811,41 +811,17 @@ namespace pci {
     // 0xFF if none found.
     u8 function::find_capability(u8 cap_id)
     {
-        return find_capability(cap_id, [](function *fun, u8 off) { return 
true; } );
-    }
-
-    // Returns the offset of the first capability with id matching @cap_id and
-    // satisfying @predicate (if specified). If none found, returns 0xFF.
-    u8 function::find_capability(u8 cap_id, std::function<bool (function*, 
u8)> predicate)
-    {
-        u8 capabilities_base = pci_readb(PCI_CAPABILITIES_PTR);
-        u8 off = capabilities_base;
-        u8 bad_offset = 0xFF;
-        u8 max_capabilities = 0xF0;
-        u8 ctr = 0;
-
-        while (off != 0) {
-            // Read capability
-            u8 capability = pci_readb(off + PCI_CAP_OFF_ID);
-            if (capability == cap_id && predicate(this, off)) {
-                return off;
-            }
-
-            ctr++;
-            if (ctr > max_capabilities) {
-                return bad_offset;
-            }
-
-            // Next
-            off = pci_readb(off + PCI_CAP_OFF_NEXT);
+        std::vector<u8> cap_offs;
+        if (find_capabilities(cap_id, cap_offs, false)) {
+            return cap_offs[0];
+        } else {
+            return 0xFF;
         }
-
-        return bad_offset;
     }
 
-    // Append to @cap_offs the offsets of all capabilities with id matching
-    // @cap_id. Returns whether any such capabilities were found.
-    bool function::find_capabilities(std::vector<u8>& cap_offs, u8 cap_id)
+    // Append to @cap_offs the offsets of the first one or all capabilities 
with id matching
+    // @cap_id. Returns whether any such capability/-ies were found.
+    bool function::find_capabilities(u8 cap_id, std::vector<u8>& cap_offs, 
bool all)
     {
         u8 capabilities_base = pci_readb(PCI_CAPABILITIES_PTR);
         u8 off = capabilities_base;
@@ -858,7 +834,11 @@ namespace pci {
             u8 capability = pci_readb(off + PCI_CAP_OFF_ID);
             if (capability == cap_id) {
                 cap_offs.push_back(off);
-                found = true;
+                if (all) {
+                    found = true;
+                } else {
+                    return true;
+                }
             }
 
             ctr++;
diff --git a/drivers/pci-function.hh b/drivers/pci-function.hh
index a8904cb0..ef568403 100644
--- a/drivers/pci-function.hh
+++ b/drivers/pci-function.hh
@@ -341,8 +341,7 @@ namespace pci {
 
         // Capability parsing
         u8 find_capability(u8 cap_id);
-        u8 find_capability(u8 cap_id, std::function<bool (function*, u8)> 
predicate);
-        bool find_capabilities(std::vector<u8>& caps, u8 cap_id);
+        bool find_capabilities(u8 cap_id, std::vector<u8>& cap_offs, bool all);
 
         bar * get_bar(int idx);
         void add_bar(int idx, bar* bar);
diff --git a/drivers/virtio-pci-device.cc b/drivers/virtio-pci-device.cc
index d484f3df..89130e01 100644
--- a/drivers/virtio-pci-device.cc
+++ b/drivers/virtio-pci-device.cc
@@ -277,6 +277,17 @@ bool virtio_modern_pci_device::get_shm(u8 id, mmioaddr_t 
&addr, u64 &length)
     return true;
 }
 
+void 
virtio_modern_pci_device::find_vendor_capabilities(std::vector<std::pair<u8,u8>>&
 offsets_and_types)
+{
+    std::vector<u8> cap_offsets;
+    if (_dev->find_capabilities(pci::function::PCI_CAP_VENDOR, cap_offsets, 
true)) {
+        for (auto offset : cap_offsets) {
+            u8 cfg_type = _dev->pci_readb(offset + offsetof(struct 
virtio_pci_cap, cfg_type));
+            offsets_and_types.emplace_back(std::pair<u8,u8>(offset, cfg_type));
+        }
+    }
+}
+
 bool virtio_modern_pci_device::parse_pci_config()
 {
     // Check ABI version
@@ -293,12 +304,14 @@ bool virtio_modern_pci_device::parse_pci_config()
         return false;
     }
 
-    // TODO: Consider consolidating these (they duplicate work)
-    parse_virtio_capability(_common_cfg, VIRTIO_PCI_CAP_COMMON_CFG);
-    parse_virtio_capability(_isr_cfg, VIRTIO_PCI_CAP_ISR_CFG);
-    parse_virtio_capability(_notify_cfg, VIRTIO_PCI_CAP_NOTIFY_CFG);
-    parse_virtio_capability(_device_cfg, VIRTIO_PCI_CAP_DEVICE_CFG);
-    parse_virtio_capabilities(_shm_cfgs, VIRTIO_PCI_CAP_SHARED_MEMORY_CFG);
+    std::vector<std::pair<u8,u8>> offsets_and_types;
+    find_vendor_capabilities(offsets_and_types);
+
+    parse_virtio_capability(offsets_and_types, _common_cfg, 
VIRTIO_PCI_CAP_COMMON_CFG);
+    parse_virtio_capability(offsets_and_types, _isr_cfg, 
VIRTIO_PCI_CAP_ISR_CFG);
+    parse_virtio_capability(offsets_and_types, _notify_cfg, 
VIRTIO_PCI_CAP_NOTIFY_CFG);
+    parse_virtio_capability(offsets_and_types, _device_cfg, 
VIRTIO_PCI_CAP_DEVICE_CFG);
+    parse_virtio_capabilities(offsets_and_types, _shm_cfgs, 
VIRTIO_PCI_CAP_SHARED_MEMORY_CFG);
 
     if (_notify_cfg) {
         _notify_offset_multiplier 
=_dev->pci_readl(_notify_cfg->get_cfg_offset() +
@@ -311,12 +324,17 @@ bool virtio_modern_pci_device::parse_pci_config()
 
 // Parse a single virtio PCI capability, whose type must match @type and store
 // it in @ptr.
-void 
virtio_modern_pci_device::parse_virtio_capability(std::unique_ptr<virtio_capability>
 &ptr, u8 type)
-{
-    u8 cfg_offset = _dev->find_capability(pci::function::PCI_CAP_VENDOR, 
[type] (pci::function *fun, u8 offset) {
-        u8 cfg_type = fun->pci_readb(offset + offsetof(struct virtio_pci_cap, 
cfg_type));
-        return type == cfg_type;
-    });
+void 
virtio_modern_pci_device::parse_virtio_capability(std::vector<std::pair<u8,u8>> 
&offsets_and_types,
+        std::unique_ptr<virtio_capability> &ptr, u8 type)
+{
+    u8 cfg_offset = 0xFF;
+    for (auto cfg_offset_and_type: offsets_and_types) {
+        auto cfg_type = cfg_offset_and_type.second;
+        if (cfg_type == type) {
+            cfg_offset = cfg_offset_and_type.first;
+            break;
+        }
+    }
 
     if (cfg_offset != 0xFF) {
         u8 bar_index = _dev->pci_readb(cfg_offset + offsetof(struct 
virtio_pci_cap, bar));
@@ -340,18 +358,16 @@ void 
virtio_modern_pci_device::parse_virtio_capability(std::unique_ptr<virtio_ca
 // drivers. The order of the capabilities in the capability list specifies the
 // order of preference suggested by the device. A device may specify that this
 // ordering mechanism be overridden by the use of the id field."
-void virtio_modern_pci_device::parse_virtio_capabilities(
-    std::vector<std::unique_ptr<virtio_capability>>& caps, u8 type)
+void virtio_modern_pci_device::parse_virtio_capabilities( 
std::vector<std::pair<u8,u8>> &offsets_and_types,
+                                                          
std::vector<std::unique_ptr<virtio_capability>>& caps, u8 type)
 {
-    std::vector<u8> cap_offs;
-    _dev->find_capabilities(cap_offs, pci::function::PCI_CAP_VENDOR);
-
-    for (auto cfg_offset: cap_offs) {
-        u8 cfg_type = _dev->pci_readb(cfg_offset + offsetof(virtio_pci_cap, 
cfg_type));
+    for (auto cfg_offset_and_type: offsets_and_types) {
+        auto cfg_type = cfg_offset_and_type.second;
         if (cfg_type != type) {
             continue;
         }
 
+        auto cfg_offset = cfg_offset_and_type.first;
         u8 bar_index = _dev->pci_readb(cfg_offset + offsetof(struct 
virtio_pci_cap, bar));
         auto bar_no = bar_index + 1;
         auto bar = _dev->get_bar(bar_no);
diff --git a/drivers/virtio-pci-device.hh b/drivers/virtio-pci-device.hh
index 851b562a..9941bcac 100644
--- a/drivers/virtio-pci-device.hh
+++ b/drivers/virtio-pci-device.hh
@@ -291,8 +291,11 @@ public:
 protected:
     virtual bool parse_pci_config();
 private:
-    void parse_virtio_capability(std::unique_ptr<virtio_capability> &ptr, u8 
type);
-    void 
parse_virtio_capabilities(std::vector<std::unique_ptr<virtio_capability>>& 
caps, u8 type);
+    void find_vendor_capabilities(std::vector<std::pair<u8,u8>>& 
offsets_and_types);
+    void parse_virtio_capability(std::vector<std::pair<u8,u8>> 
&offsets_and_types,
+            std::unique_ptr<virtio_capability> &ptr, u8 type);
+    void parse_virtio_capabilities(std::vector<std::pair<u8,u8>> 
&offsets_and_types,
+            std::vector<std::unique_ptr<virtio_capability>>& caps, u8 type);
 
     std::unique_ptr<virtio_capability> _common_cfg;
     std::unique_ptr<virtio_capability> _isr_cfg;
-- 
2.20.1

-- 
You received this message because you are subscribed to the Google Groups "OSv 
Development" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/osv-dev/20200317044119.1198-1-jwkozaczuk%40gmail.com.

Reply via email to