pci_rebar_set_size() adjusts BAR size for both normal and IOV BARs. The
struct pci_sriov keeps a cached copy of BAR size 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 <ilpo.jarvinen@linux.intel.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Tested-by: Alex Bennée <alex.bennee@linaro.org> # AVA, AMD GPU
Link: https://patch.msgid.link/20251113162628.5946-3-ilpo.jarvinen@linux.intel.com
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",
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)
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;
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);
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;
}
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)
{
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;
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)