aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Johnston <markj@FreeBSD.org>2021-11-09 18:07:57 +0000
committerMark Johnston <markj@FreeBSD.org>2021-11-09 18:13:36 +0000
commit1f960e646b7280795766fdaa183e3b9bd4cea345 (patch)
tree2896038bc20c2060984004b9091a15f2c13ebfe6
parent57093f9366b7eeb48054ff2fa77b9d01d2b3cfc2 (diff)
pci: Implement pci_bar_enabled() for SR-IOV VFs
In a VF's configuration space, "memory space enable" is hard-wired to 0, so the existing implementation always returns false. We need to read the SR-IOV control register from the PF device to get the value of the MSE bit. Fix pci_bar_enabled() to read this register instead for VFs. I don't see any way to access the PF's config space without a backpointer in the pci device ivars, so I added one. This fixes a regression where bhyve(8) fails to map the MSI-X table after commit 7fa233534736 ("bhyve: Map the MSI-X table unconditionally for passthrough") when a VF is passed through, since with that commit we use PCIOCBARMMAP to map the table and that ioctl always fails for VFs without this change. As a bonus, pciconf(8) now correctly reports the enablement of BARs for VFs. Reported and tested by: Raúl Muñoz <raul.munoz@custos.es> Reviewed by: rstone, jhb MFC after: 1 week Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D32839
-rw-r--r--sys/dev/pci/pci.c10
-rw-r--r--sys/dev/pci/pci_iov.c1
-rw-r--r--sys/dev/pci/pci_iov_private.h1
3 files changed, 12 insertions, 0 deletions
diff --git a/sys/dev/pci/pci.c b/sys/dev/pci/pci.c
index 702f9fc3aa05..7493ae1727fb 100644
--- a/sys/dev/pci/pci.c
+++ b/sys/dev/pci/pci.c
@@ -3151,6 +3151,16 @@ pci_bar_enabled(device_t dev, struct pci_map *pm)
if (PCIR_IS_BIOS(&dinfo->cfg, pm->pm_reg) &&
!(pm->pm_value & PCIM_BIOS_ENABLE))
return (0);
+#ifdef PCI_IOV
+ if ((dinfo->cfg.flags & PCICFG_VF) != 0) {
+ struct pcicfg_iov *iov;
+
+ iov = dinfo->cfg.iov;
+ cmd = pci_read_config(iov->iov_pf,
+ iov->iov_pos + PCIR_SRIOV_CTL, 2);
+ return ((cmd & PCIM_SRIOV_VF_MSE) != 0);
+ }
+#endif
cmd = pci_read_config(dev, PCIR_COMMAND, 2);
if (PCIR_IS_BIOS(&dinfo->cfg, pm->pm_reg) || PCI_BAR_MEM(pm->pm_value))
return ((cmd & PCIM_CMD_MEMEN) != 0);
diff --git a/sys/dev/pci/pci_iov.c b/sys/dev/pci/pci_iov.c
index 6db2cf445843..f577640595a9 100644
--- a/sys/dev/pci/pci_iov.c
+++ b/sys/dev/pci/pci_iov.c
@@ -151,6 +151,7 @@ pci_iov_attach_method(device_t bus, device_t dev, nvlist_t *pf_schema,
error = EBUSY;
goto cleanup;
}
+ iov->iov_pf = dev;
iov->iov_pos = iov_pos;
schema = pci_iov_build_schema(&pf_schema, &vf_schema);
diff --git a/sys/dev/pci/pci_iov_private.h b/sys/dev/pci/pci_iov_private.h
index 0d1dda871b44..be3456d4781f 100644
--- a/sys/dev/pci/pci_iov_private.h
+++ b/sys/dev/pci/pci_iov_private.h
@@ -37,6 +37,7 @@ struct pci_iov_bar {
};
struct pcicfg_iov {
+ device_t iov_pf;
struct cdev *iov_cdev;
nvlist_t *iov_schema;