Looks good to me!
Also, nice to make pci::function::find_capability() private, de-cluttering 
the public interface (since all uses are from other functions of 
pci::function).

Τη Τετάρτη, 18 Μαρτίου 2020 - 5:34:29 μ.μ. UTC+2, ο χρήστης Waldemar 
Kozaczuk έγραψε:
>
> --- 
>  drivers/pci-function.cc      | 53 +++++++++++++---------------------- 
>  drivers/pci-function.hh      |  9 ++++-- 
>  drivers/virtio-pci-device.cc | 54 +++++++++++++++++++++++------------- 
>  drivers/virtio-pci-device.hh |  7 +++-- 
>  4 files changed, 66 insertions(+), 57 deletions(-) 
>
> diff --git a/drivers/pci-function.cc b/drivers/pci-function.cc 
> index b0fb3674..9d3641eb 100644 
> --- a/drivers/pci-function.cc 
> +++ b/drivers/pci-function.cc 
> @@ -807,45 +807,28 @@ namespace pci { 
>          write_pci_config(_bus, _device, _func, offset, val); 
>      } 
>   
> -    // Returns the offset of the first capability with id matching 
> @cap_id, or 
> -    // 0xFF if none found. 
> -    u8 function::find_capability(u8 cap_id) 
> +    // 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(u8 cap_id, std::vector<u8>& 
> cap_offs) 
>      { 
> -        return find_capability(cap_id, [](function *fun, u8 off) { return 
> true; } ); 
> +        return find_capabilities(cap_id, cap_offs, 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) 
> +    // Returns the offset of the first capability with id matching 
> @cap_id, or 
> +    // 0xFF if none found. 
> +    u8 function::find_capability(u8 cap_id) 
>      { 
> -        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 +841,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..9847b027 100644 
> --- a/drivers/pci-function.hh 
> +++ b/drivers/pci-function.hh 
> @@ -340,9 +340,7 @@ namespace pci { 
>          virtual void pci_writel(u8 offset, u32 val); 
>   
>          // 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); 
>   
>          bar * get_bar(int idx); 
>          void add_bar(int idx, bar* bar); 
> @@ -402,6 +400,11 @@ namespace pci { 
>          bool _have_msi; 
>          pcicfg_msi _msi; 
>          bool _msi_enabled; 
> + 
> +    private: 
> +        // Capability parsing 
> +        u8 find_capability(u8 cap_id); 
> +        bool find_capabilities(u8 cap_id, std::vector<u8>& cap_offs, bool 
> all); 
>      }; 
>  } 
>   
> diff --git a/drivers/virtio-pci-device.cc b/drivers/virtio-pci-device.cc 
> index d484f3df..a793111a 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)) { 
> +        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/4b21a11e-8b02-4ed8-a1f1-65667c6e3d0f%40googlegroups.com.

Reply via email to