pci_rebar_set_size() adjusts BAR size for both normal and IOV BARs. The struct pci_srvio keeps a cached copy of BAR size in unit of resource_size_t in ->barsz[] which is not adjusted by pci_rebar_set_size() but by pci_iov_resource_set_size(). pci_iov_resource_set_size() is called also from pci_resize_resource_set_size().
The current arrangement is problematic once BAR resize algorithm starts to roll back changes properly in case of a failure. The normal resource fitting algorithm rolls back resource size using the struct pci_dev_resource easily but also calling pci_resize_resource_set_size() or pci_iov_resource_set_size() to roll back BAR size would be an extra burden, whereas combining ->barsz[] update with pci_rebar_set_size() naturally rolls back it when restoring the old BAR size on a different layer of the BAR resize operation. Thus, rework pci_rebar_set_size() to also update ->barsz[]. Signed-off-by: Ilpo Järvinen <[email protected]> --- drivers/pci/iov.c | 15 ++++----------- drivers/pci/pci.c | 4 ++++ drivers/pci/pci.h | 5 ++--- drivers/pci/setup-res.c | 10 ++++------ 4 files changed, 14 insertions(+), 20 deletions(-) diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c index 77dee43b7858..04b675e90963 100644 --- a/drivers/pci/iov.c +++ b/drivers/pci/iov.c @@ -158,8 +158,7 @@ resource_size_t pci_iov_resource_size(struct pci_dev *dev, int resno) return dev->sriov->barsz[pci_resource_num_to_vf_bar(resno)]; } -void pci_iov_resource_set_size(struct pci_dev *dev, int resno, - resource_size_t size) +void pci_iov_resource_set_size(struct pci_dev *dev, int resno, int size) { if (!pci_resource_is_iov(resno)) { pci_warn(dev, "%s is not an IOV resource\n", @@ -167,7 +166,8 @@ void pci_iov_resource_set_size(struct pci_dev *dev, int resno, return; } - dev->sriov->barsz[pci_resource_num_to_vf_bar(resno)] = size; + resno = pci_resource_num_to_vf_bar(resno); + dev->sriov->barsz[resno] = pci_rebar_size_to_bytes(size); } bool pci_iov_is_memory_decoding_enabled(struct pci_dev *dev) @@ -1340,7 +1340,6 @@ EXPORT_SYMBOL_GPL(pci_sriov_configure_simple); int pci_iov_vf_bar_set_size(struct pci_dev *dev, int resno, int size) { u32 sizes; - int ret; if (!pci_resource_is_iov(resno)) return -EINVAL; @@ -1355,13 +1354,7 @@ int pci_iov_vf_bar_set_size(struct pci_dev *dev, int resno, int size) if (!(sizes & BIT(size))) return -EINVAL; - ret = pci_rebar_set_size(dev, resno, size); - if (ret) - return ret; - - pci_iov_resource_set_size(dev, resno, pci_rebar_size_to_bytes(size)); - - return 0; + return pci_rebar_set_size(dev, resno, size); } EXPORT_SYMBOL_GPL(pci_iov_vf_bar_set_size); diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index b14dd064006c..7dfc58b0e55e 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -3803,6 +3803,10 @@ int pci_rebar_set_size(struct pci_dev *pdev, int bar, int size) ctrl &= ~PCI_REBAR_CTRL_BAR_SIZE; ctrl |= FIELD_PREP(PCI_REBAR_CTRL_BAR_SIZE, size); pci_write_config_dword(pdev, pos + PCI_REBAR_CTRL, ctrl); + + if (pci_resource_is_iov(bar)) + pci_iov_resource_set_size(pdev, bar, size); + return 0; } diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index 4492b809094b..bf1a577e9623 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -808,8 +808,7 @@ void pci_iov_update_resource(struct pci_dev *dev, int resno); resource_size_t pci_sriov_resource_alignment(struct pci_dev *dev, int resno); void pci_restore_iov_state(struct pci_dev *dev); int pci_iov_bus_range(struct pci_bus *bus); -void pci_iov_resource_set_size(struct pci_dev *dev, int resno, - resource_size_t size); +void pci_iov_resource_set_size(struct pci_dev *dev, int resno, int size); bool pci_iov_is_memory_decoding_enabled(struct pci_dev *dev); static inline u16 pci_iov_vf_rebar_cap(struct pci_dev *dev) { @@ -851,7 +850,7 @@ static inline int pci_iov_bus_range(struct pci_bus *bus) return 0; } static inline void pci_iov_resource_set_size(struct pci_dev *dev, int resno, - resource_size_t size) { } + int size) { } static inline bool pci_iov_is_memory_decoding_enabled(struct pci_dev *dev) { return false; diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c index c3ba4ccecd43..3d0b0b3f60c4 100644 --- a/drivers/pci/setup-res.c +++ b/drivers/pci/setup-res.c @@ -450,12 +450,10 @@ static void pci_resize_resource_set_size(struct pci_dev *dev, int resno, resource_size_t res_size = pci_rebar_size_to_bytes(size); struct resource *res = pci_resource_n(dev, resno); - if (!pci_resource_is_iov(resno)) { - resource_set_size(res, res_size); - } else { - resource_set_size(res, res_size * pci_sriov_get_totalvfs(dev)); - pci_iov_resource_set_size(dev, resno, res_size); - } + if (pci_resource_is_iov(resno)) + res_size *= pci_sriov_get_totalvfs(dev); + + resource_set_size(res, res_size); } int pci_resize_resource(struct pci_dev *dev, int resno, int size) -- 2.39.5
