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