We cannot assume extended config space to (still) be accessible when
cleaning up. Necessary value need caching instead. In fact, as the caller
also cannot look up extended capabilities, the cleanup function needs to
cope with being called when there's no ReBAR capability at all.
As kind of a side effect nbars being 0 (which init_rebar() doesn't
explicitly reject) no longer results in a bogus call to
vpci_remove_registers().
Fixes: ee459aeac096 ("vpci/rebar: Implement cleanup function for Rebar")
Signed-off-by: Jan Beulich <jbeulich@suse.com>
---
v5: New.
--- a/xen/drivers/vpci/rebar.c
+++ b/xen/drivers/vpci/rebar.c
@@ -53,17 +53,12 @@ static void cf_check rebar_ctrl_write(co
static int cf_check cleanup_rebar(const struct pci_dev *pdev, bool hide)
{
int rc;
- uint32_t ctrl;
- unsigned int nbars;
- unsigned int rebar_offset = pci_find_ext_capability(pdev,
- PCI_EXT_CAP_ID_REBAR);
+ unsigned int nbars = pdev->vpci->rebar.nbars;
+ unsigned int rebar_offset = pdev->vpci->rebar.offset;
- if ( !hide )
+ if ( !rebar_offset || !nbars || !hide )
return 0;
- ctrl = pci_conf_read32(pdev->sbdf, rebar_offset + PCI_REBAR_CTRL(0));
- nbars = MASK_EXTR(ctrl, PCI_REBAR_CTRL_NBAR_MASK);
-
rc = vpci_remove_registers(pdev->vpci, rebar_offset + PCI_REBAR_CAP(0),
PCI_REBAR_CTRL(nbars - 1));
if ( rc )
@@ -121,6 +116,10 @@ static int cf_check init_rebar(struct pc
ctrl = pci_conf_read32(pdev->sbdf, rebar_offset + PCI_REBAR_CTRL(0));
nbars = MASK_EXTR(ctrl, PCI_REBAR_CTRL_NBAR_MASK);
+
+ pdev->vpci->rebar.offset = rebar_offset;
+ pdev->vpci->rebar.nbars = nbars;
+
for ( unsigned int i = 0; i < nbars; i++ )
{
int rc;
--- a/xen/include/xen/vpci.h
+++ b/xen/include/xen/vpci.h
@@ -135,6 +135,13 @@ struct vpci {
struct vpci_arch_msix_entry arch;
} entries[];
} *msix;
+
+ /* Resizable BARs data */
+ struct vpci_rebar {
+ unsigned int offset:12;
+ unsigned int nbars:3;
+ } rebar;
+
#ifdef CONFIG_HAS_VPCI_GUEST_SUPPORT
/* Guest SBDF of the device. */
#define INVALID_GUEST_SBDF ((pci_sbdf_t){ .sbdf = ~0U })