diff options
author | Akihiko Odaki <akihiko.odaki@daynix.com> | 2024-02-28 20:33:14 +0900 |
---|---|---|
committer | Michael S. Tsirkin <mst@redhat.com> | 2024-03-12 17:56:55 -0400 |
commit | c8bc4db403e17663b69d811e69f88c9dfc6f7be2 (patch) | |
tree | 83a4d140091e226323db81c7926ec4103053fc48 /hw | |
parent | 6081b4243cd64dff1b2cf5b0c215c71e9d7e753b (diff) |
pcie_sriov: Reset SR-IOV extended capability
pcie_sriov_pf_disable_vfs() is called when resetting the PF, but it only
disables VFs and does not reset SR-IOV extended capability, leaking the
state and making the VF Enable register inconsistent with the actual
state.
Replace pcie_sriov_pf_disable_vfs() with pcie_sriov_pf_reset(), which
does not only disable VFs but also resets the capability.
Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
Message-Id: <20240228-reuse-v8-3-282660281e60@daynix.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Sriram Yagnaraman <sriram.yagnaraman@ericsson.com>
Diffstat (limited to 'hw')
-rw-r--r-- | hw/net/igb.c | 2 | ||||
-rw-r--r-- | hw/nvme/ctrl.c | 2 | ||||
-rw-r--r-- | hw/pci/pcie_sriov.c | 26 |
3 files changed, 20 insertions, 10 deletions
diff --git a/hw/net/igb.c b/hw/net/igb.c index 0b5c31a58b..9345506f81 100644 --- a/hw/net/igb.c +++ b/hw/net/igb.c @@ -493,7 +493,7 @@ static void igb_qdev_reset_hold(Object *obj) trace_e1000e_cb_qdev_reset_hold(); - pcie_sriov_pf_disable_vfs(d); + pcie_sriov_pf_reset(d); igb_core_reset(&s->core); } diff --git a/hw/nvme/ctrl.c b/hw/nvme/ctrl.c index 2860a9bed1..447c4de6fd 100644 --- a/hw/nvme/ctrl.c +++ b/hw/nvme/ctrl.c @@ -7116,7 +7116,7 @@ static void nvme_ctrl_reset(NvmeCtrl *n, NvmeResetType rst) } if (rst != NVME_RESET_CONTROLLER) { - pcie_sriov_pf_disable_vfs(pci_dev); + pcie_sriov_pf_reset(pci_dev); } } diff --git a/hw/pci/pcie_sriov.c b/hw/pci/pcie_sriov.c index da209b7f47..51b66d1bb3 100644 --- a/hw/pci/pcie_sriov.c +++ b/hw/pci/pcie_sriov.c @@ -249,16 +249,26 @@ void pcie_sriov_config_write(PCIDevice *dev, uint32_t address, } -/* Reset SR/IOV VF Enable bit to trigger an unregister of all VFs */ -void pcie_sriov_pf_disable_vfs(PCIDevice *dev) +/* Reset SR/IOV */ +void pcie_sriov_pf_reset(PCIDevice *dev) { uint16_t sriov_cap = dev->exp.sriov_cap; - if (sriov_cap) { - uint32_t val = pci_get_byte(dev->config + sriov_cap + PCI_SRIOV_CTRL); - if (val & PCI_SRIOV_CTRL_VFE) { - val &= ~PCI_SRIOV_CTRL_VFE; - pcie_sriov_config_write(dev, sriov_cap + PCI_SRIOV_CTRL, val, 1); - } + if (!sriov_cap) { + return; + } + + pci_set_word(dev->config + sriov_cap + PCI_SRIOV_CTRL, 0); + unregister_vfs(dev); + + /* + * Default is to use 4K pages, software can modify it + * to any of the supported bits + */ + pci_set_word(dev->config + sriov_cap + PCI_SRIOV_SYS_PGSIZE, 0x1); + + for (uint16_t i = 0; i < PCI_NUM_REGIONS; i++) { + pci_set_quad(dev->config + sriov_cap + PCI_SRIOV_BAR + i * 4, + dev->exp.sriov_pf.vf_bar_type[i]); } } |