From ad4d14e37f6b74e63ed2367cda3c24c453a58aa2 Mon Sep 17 00:00:00 2001 From: Minggui Cao Date: Mon, 2 Mar 2020 14:26:36 +0800 Subject: [PATCH] HV: enable ARI if PCI bridge support it For SRIOV needs ARI support, so enable it in HV if the PCI bridge support it. TODO: need check all the PCI devices under this bridge can support ARI, if not, it is better not enable it as PCIe spec. That check will be done when scanning PCI devices. Tracked-On: #3381 Signed-off-by: Yin Fengwei Signed-off-by: Minggui Cao Acked-by: Eddie Dong --- hypervisor/hw/pci.c | 25 +++++++++++++++++++++++++ hypervisor/include/hw/pci.h | 6 ++++++ 2 files changed, 31 insertions(+) diff --git a/hypervisor/hw/pci.c b/hypervisor/hw/pci.c index 13f437ab9..da2b5d43a 100644 --- a/hypervisor/hw/pci.c +++ b/hypervisor/hw/pci.c @@ -450,6 +450,26 @@ static void pci_parse_iommu_devscopes(struct pci_bdf_set *const bdfs_from_drhds, } } +/* do enabling or limitation to pci bridge */ +static void config_pci_bridge(struct pci_pdev *pdev) +{ + uint32_t offset, val; + + /* Enable ARI if PCIe bridge could support it for SRIOV needs it */ + if (pdev->pcie_capoff != 0x00UL) { + offset = pdev->pcie_capoff + PCIR_PCIE_DEVCAP2; + val = pci_pdev_read_cfg(pdev->bdf, offset, 2U); + + if (val & PCIM_PCIE_DEVCAP2_ARI) { + offset = pdev->pcie_capoff + PCIR_PCIE_DEVCTL2; + + val = pci_pdev_read_cfg(pdev->bdf, offset, 2U); + val |= PCIM_PCIE_DEVCTL2_ARI; + pci_pdev_write_cfg(pdev->bdf, offset, 2U, val); + } + } +} + /* * @brief: walks through all pdevs that have been initialized and determine * which pdevs need to be added to pci dev_config. The pdevs added to pci @@ -464,6 +484,10 @@ static void init_all_dev_config(void) for (idx = 0U; idx < num_pci_pdev; idx++) { pdev = &pci_pdev_array[idx]; + if (pdev->hdr_type == PCIM_HDRTYPE_BRIDGE) { + config_pci_bridge(pdev); + } + /* * FIXME: Mask the SR-IOV capability instead drop the device * when supporting PCIe extended capabilities whitelist. @@ -605,6 +629,7 @@ static void pci_enumerate_cap(struct pci_pdev *pdev) } else if (cap == PCIY_PCIE) { is_pcie = true; pcie_devcap = pci_pdev_read_cfg(pdev->bdf, pos + PCIR_PCIE_DEVCAP, 4U); + pdev->pcie_capoff = pos; pdev->has_flr = ((pcie_devcap & PCIM_PCIE_FLRCAP) != 0U); } else if (cap == PCIY_AF) { val = pci_pdev_read_cfg(pdev->bdf, pos, 4U); diff --git a/hypervisor/include/hw/pci.h b/hypervisor/include/hw/pci.h index b67fdd62e..9893fadde 100644 --- a/hypervisor/include/hw/pci.h +++ b/hypervisor/include/hw/pci.h @@ -169,6 +169,11 @@ #define PCIM_PCIE_FLRCAP (0x1U << 28U) #define PCIM_PCIE_FLR (0x1U << 15U) +#define PCIR_PCIE_DEVCAP2 0x24U +#define PCIM_PCIE_DEVCAP2_ARI (0x1U << 5U) +#define PCIR_PCIE_DEVCTL2 0x28U +#define PCIM_PCIE_DEVCTL2_ARI (0x1U << 5U) + /* Conventional PCI Advanced Features Capability */ #define PCIY_AF 0x13U #define PCIM_AF_FLR_CAP (0x1U << 25U) @@ -228,6 +233,7 @@ struct pci_pdev { union pci_bdf bdf; uint32_t msi_capoff; + uint32_t pcie_capoff; struct pci_msix_cap msix; struct pci_sriov_cap sriov;