hv: implement SRIOV-Capable device detection.

if the device has PCIe capability, walks all PCIe extended
capabilities for SRIOV discovery.

v2: avoid type casting and refine naming.

Tracked-On: #4433

Signed-off-by: Yuan Liu <yuan1.liu@intel.com>
Acked-by: Eddie Dong <eddie.dong@intel.com>
This commit is contained in:
Yuan Liu 2020-02-17 15:02:22 +08:00 committed by wenlingz
parent c751a8e88b
commit ac1477956c
2 changed files with 46 additions and 0 deletions

View File

@ -477,6 +477,31 @@ static inline uint32_t pci_pdev_get_nr_bars(uint8_t hdr_type)
return nr_bars; return nr_bars;
} }
/**
* @pre pdev != NULL
*/
static void pci_read_ext_cap(struct pci_pdev *pdev) {
uint32_t hdr, pos;
pos = PCI_ECAP_BASE_PTR;
/* PCI Express Extended Capability must have 4 bytes header */
hdr = pci_pdev_read_cfg(pdev->bdf, pos, 4U);
while (hdr != 0U) {
if (PCI_ECAP_ID(hdr) == PCIZ_SRIOV) {
pdev->sriov.capoff = pos;
pdev->sriov.caplen = PCI_SRIOV_CAP_LEN;
}
pos = PCI_ECAP_NEXT(hdr);
if (pos == 0U) {
break;
}
hdr = pci_pdev_read_cfg(pdev->bdf, pos, 4U);
};
}
/* /*
* @pre pdev != NULL * @pre pdev != NULL
*/ */
@ -487,6 +512,7 @@ static void pci_read_cap(struct pci_pdev *pdev)
uint32_t len, idx; uint32_t len, idx;
uint32_t table_info; uint32_t table_info;
uint32_t pcie_devcap, val; uint32_t pcie_devcap, val;
bool is_pcie = false;
pos = (uint8_t)pci_pdev_read_cfg(pdev->bdf, PCIR_CAP_PTR, 1U); pos = (uint8_t)pci_pdev_read_cfg(pdev->bdf, PCIR_CAP_PTR, 1U);
@ -520,6 +546,7 @@ static void pci_read_cap(struct pci_pdev *pdev)
val = pci_pdev_read_cfg(pdev->bdf, pos + PCIR_PMCSR, 4U); val = pci_pdev_read_cfg(pdev->bdf, pos + PCIR_PMCSR, 4U);
pdev->has_pm_reset = ((val & PCIM_PMCSR_NO_SOFT_RST) == 0U); pdev->has_pm_reset = ((val & PCIM_PMCSR_NO_SOFT_RST) == 0U);
} else if (cap == PCIY_PCIE) { } else if (cap == PCIY_PCIE) {
is_pcie = true;
pcie_devcap = pci_pdev_read_cfg(pdev->bdf, pos + PCIR_PCIE_DEVCAP, 4U); pcie_devcap = pci_pdev_read_cfg(pdev->bdf, pos + PCIR_PCIE_DEVCAP, 4U);
pdev->has_flr = ((pcie_devcap & PCIM_PCIE_FLRCAP) != 0U); pdev->has_flr = ((pcie_devcap & PCIM_PCIE_FLRCAP) != 0U);
} else if (cap == PCIY_AF) { } else if (cap == PCIY_AF) {
@ -531,6 +558,10 @@ static void pci_read_cap(struct pci_pdev *pdev)
pos = (uint8_t)pci_pdev_read_cfg(pdev->bdf, pos + PCICAP_NEXTPTR, 1U); pos = (uint8_t)pci_pdev_read_cfg(pdev->bdf, pos + PCICAP_NEXTPTR, 1U);
} }
if (is_pcie) {
pci_read_ext_cap(pdev);
}
} }
static void init_pdev(uint16_t pbdf, uint32_t drhd_index) static void init_pdev(uint16_t pbdf, uint32_t drhd_index)

View File

@ -106,6 +106,15 @@
#define PCIY_MSI 0x05U #define PCIY_MSI 0x05U
#define PCIY_MSIX 0x11U #define PCIY_MSIX 0x11U
/* PCIe Extended Capability*/
#define PCI_ECAP_BASE_PTR 0x100U
#define PCI_ECAP_ID(hdr) ((uint32_t)((hdr) & 0xFFFFU))
#define PCI_ECAP_NEXT(hdr) ((uint32_t)(((hdr) >> 20U) & 0xFFCU))
#define PCIZ_SRIOV 0x10U
/* SRIOV Definitions */
#define PCI_SRIOV_CAP_LEN 0x40U
/* PCI Message Signalled Interrupts (MSI) */ /* PCI Message Signalled Interrupts (MSI) */
#define PCIR_MSI_CTRL 0x02U #define PCIR_MSI_CTRL 0x02U
#define PCIM_MSICTRL_64BIT 0x80U #define PCIM_MSICTRL_64BIT 0x80U
@ -192,6 +201,11 @@ struct pci_msix_cap {
uint8_t cap[MSIX_CAPLEN]; uint8_t cap[MSIX_CAPLEN];
}; };
struct pci_sriov_cap {
uint32_t capoff;
uint32_t caplen;
};
struct pci_pdev { struct pci_pdev {
uint8_t hdr_type; uint8_t hdr_type;
@ -208,6 +222,7 @@ struct pci_pdev {
uint32_t msi_capoff; uint32_t msi_capoff;
struct pci_msix_cap msix; struct pci_msix_cap msix;
struct pci_sriov_cap sriov;
bool has_pm_reset; bool has_pm_reset;
bool has_flr; bool has_flr;