PCI PF memory decode disable when sizing VF BARs
Ryan Stone
rysto32 at gmail.com
Wed May 6 18:24:26 UTC 2015
On Wed, May 6, 2015 at 11:45 AM, John Baldwin <jhb at freebsd.org> wrote:
> There are some devices with BARs in non-standard locations. :( If there is
> a flag to just disable the VF bar decoding, then ideally we should just be
> doing that and leaving the global decoding flag alone while sizing the VF
> BAR.
>
Disabling SR-IOV BAR decoding in this function is currently redundant, as
it's already done in pci_iov.c, but I guess to keep the interface sane it
makes sense to do it here too. Something like this then?
diff --git a/sys/dev/pci/pci.c b/sys/dev/pci/pci.c
index b4c6151..c9d7541 100644
--- a/sys/dev/pci/pci.c
+++ b/sys/dev/pci/pci.c
@@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$");
#include <sys/module.h>
#include <sys/limits.h>
#include <sys/linker.h>
+#include <sys/nv.h>
#include <sys/fcntl.h>
#include <sys/conf.h>
#include <sys/kernel.h>
@@ -62,6 +63,7 @@ __FBSDID("$FreeBSD$");
#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pci_private.h>
+#include <dev/pci/pci_iov_private.h>
#include <dev/usb/controller/xhcireg.h>
#include <dev/usb/controller/ehcireg.h>
@@ -75,6 +77,11 @@ __FBSDID("$FreeBSD$");
(((cfg)->hdrtype == PCIM_HDRTYPE_NORMAL && reg == PCIR_BIOS) || \
((cfg)->hdrtype == PCIM_HDRTYPE_BRIDGE && reg == PCIR_BIOS_1))
+#define PCIR_IS_IOV(cfg,
reg) \
+ (((cfg)->iov != NULL) && \
+ ((reg) >= (cfg)->iov->iov_pos + PCIR_SRIOV_BAR(0)) && \
+ ((reg) <= (cfg)->iov->iov_pos + PCIR_SRIOV_BAR(PCIR_MAX_BAR_0)))
+
static int pci_has_quirk(uint32_t devid, int quirk);
static pci_addr_t pci_mapbase(uint64_t mapreg);
static const char *pci_maptype(uint64_t mapreg);
@@ -2647,7 +2654,8 @@ pci_read_bar(device_t dev, int reg, pci_addr_t *mapp,
pci_addr_t *testvalp,
struct pci_devinfo *dinfo;
pci_addr_t map, testval;
int ln2range;
- uint16_t cmd;
+ uint32_t restore_reg;
+ uint16_t cmd, mask;
/*
* The device ROM BAR is special. It is always a 32-bit
@@ -2677,9 +2685,21 @@ pci_read_bar(device_t dev, int reg, pci_addr_t
*mapp, pci_addr_t *testvalp,
* determining the BAR's length since we will be placing it in
* a weird state.
*/
- cmd = pci_read_config(dev, PCIR_COMMAND, 2);
- pci_write_config(dev, PCIR_COMMAND,
- cmd & ~(PCI_BAR_MEM(map) ? PCIM_CMD_MEMEN : PCIM_CMD_PORTEN),
2);
+#ifdef PCI_IOV
+ if (PCIR_IS_IOV(&dinfo->cfg, reg)) {
+ restore_reg = dinfo->cfg.iov->iov_pos + PCIR_SRIOV_CTL;
+ cmd = pci_read_config(dev, restore_reg, 2);
+ pci_write_config(dev, restore_reg, cmd &
~PCIM_SRIOV_VF_MSE, 2);
+ } else
+#endif
+ {
+ cmd = pci_read_config(dev, PCIR_COMMAND, 2);
+ mask = PCI_BAR_MEM(map) ? PCIM_CMD_MEMEN : PCIM_CMD_PORTEN;
+ pci_write_config(dev, PCIR_COMMAND, cmd & ~mask, 2);
+ restore_reg = PCIR_COMMAND;
+ }
/*
* Determine the BAR's length by writing all 1's. The bottom
@@ -2701,7 +2721,7 @@ pci_read_bar(device_t dev, int reg, pci_addr_t *mapp,
pci_addr_t *testvalp,
pci_write_config(dev, reg, map, 4);
if (ln2range == 64)
pci_write_config(dev, reg + 4, map >> 32, 4);
- pci_write_config(dev, PCIR_COMMAND, cmd, 2);
+ pci_write_config(dev, restore_reg, cmd, 2);
*mapp = map;
*testvalp = testval;
More information about the freebsd-current
mailing list