PCI: Keep individual VF BAR size in struct pci_sriov

Currently we don't store the individual VF BAR size.  We calculate it when
needed by dividing the PF's IOV resource size (which contains space for
*all* the VFs) by total_VFs or by reading the BAR in the SR-IOV capability
again.

Keep the individual VF BAR size in struct pci_sriov.barsz[], add
pci_iov_resource_size() to retrieve it, and use that instead of doing the
division or reading the SR-IOV capability BAR.

[bhelgaas: rename to "barsz[]", simplify barsz[] index computation, remove
SR-IOV capability BAR sizing]
Signed-off-by: Wei Yang <weiyang@linux.vnet.ibm.com>
Acked-by: Bjorn Helgaas <bhelgaas@google.com>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
This commit is contained in:
Wei Yang 2015-03-25 16:23:44 +08:00 committed by Benjamin Herrenschmidt
parent e88ae01d2c
commit 0e6c9122a6
3 changed files with 24 additions and 19 deletions

View File

@ -57,6 +57,14 @@ static void virtfn_remove_bus(struct pci_bus *physbus, struct pci_bus *virtbus)
pci_remove_bus(virtbus); pci_remove_bus(virtbus);
} }
resource_size_t pci_iov_resource_size(struct pci_dev *dev, int resno)
{
if (!dev->is_physfn)
return 0;
return dev->sriov->barsz[resno - PCI_IOV_RESOURCES];
}
static int virtfn_add(struct pci_dev *dev, int id, int reset) static int virtfn_add(struct pci_dev *dev, int id, int reset)
{ {
int i; int i;
@ -92,8 +100,7 @@ static int virtfn_add(struct pci_dev *dev, int id, int reset)
continue; continue;
virtfn->resource[i].name = pci_name(virtfn); virtfn->resource[i].name = pci_name(virtfn);
virtfn->resource[i].flags = res->flags; virtfn->resource[i].flags = res->flags;
size = resource_size(res); size = pci_iov_resource_size(dev, i + PCI_IOV_RESOURCES);
do_div(size, iov->total_VFs);
virtfn->resource[i].start = res->start + size * id; virtfn->resource[i].start = res->start + size * id;
virtfn->resource[i].end = virtfn->resource[i].start + size - 1; virtfn->resource[i].end = virtfn->resource[i].start + size - 1;
rc = request_resource(res, &virtfn->resource[i]); rc = request_resource(res, &virtfn->resource[i]);
@ -311,7 +318,7 @@ static void sriov_disable(struct pci_dev *dev)
static int sriov_init(struct pci_dev *dev, int pos) static int sriov_init(struct pci_dev *dev, int pos)
{ {
int i; int i, bar64;
int rc; int rc;
int nres; int nres;
u32 pgsz; u32 pgsz;
@ -360,29 +367,29 @@ found:
pgsz &= ~(pgsz - 1); pgsz &= ~(pgsz - 1);
pci_write_config_dword(dev, pos + PCI_SRIOV_SYS_PGSIZE, pgsz); pci_write_config_dword(dev, pos + PCI_SRIOV_SYS_PGSIZE, pgsz);
iov = kzalloc(sizeof(*iov), GFP_KERNEL);
if (!iov)
return -ENOMEM;
nres = 0; nres = 0;
for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) { for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) {
res = dev->resource + PCI_IOV_RESOURCES + i; res = dev->resource + PCI_IOV_RESOURCES + i;
i += __pci_read_base(dev, pci_bar_unknown, res, bar64 = __pci_read_base(dev, pci_bar_unknown, res,
pos + PCI_SRIOV_BAR + i * 4); pos + PCI_SRIOV_BAR + i * 4);
if (!res->flags) if (!res->flags)
continue; continue;
if (resource_size(res) & (PAGE_SIZE - 1)) { if (resource_size(res) & (PAGE_SIZE - 1)) {
rc = -EIO; rc = -EIO;
goto failed; goto failed;
} }
iov->barsz[i] = resource_size(res);
res->end = res->start + resource_size(res) * total - 1; res->end = res->start + resource_size(res) * total - 1;
dev_info(&dev->dev, "VF(n) BAR%d space: %pR (contains BAR%d for %d VFs)\n", dev_info(&dev->dev, "VF(n) BAR%d space: %pR (contains BAR%d for %d VFs)\n",
i, res, i, total); i, res, i, total);
i += bar64;
nres++; nres++;
} }
iov = kzalloc(sizeof(*iov), GFP_KERNEL);
if (!iov) {
rc = -ENOMEM;
goto failed;
}
iov->pos = pos; iov->pos = pos;
iov->nres = nres; iov->nres = nres;
iov->ctrl = ctrl; iov->ctrl = ctrl;
@ -414,6 +421,7 @@ failed:
res->flags = 0; res->flags = 0;
} }
kfree(iov);
return rc; return rc;
} }
@ -510,14 +518,7 @@ int pci_iov_resource_bar(struct pci_dev *dev, int resno)
*/ */
resource_size_t pci_sriov_resource_alignment(struct pci_dev *dev, int resno) resource_size_t pci_sriov_resource_alignment(struct pci_dev *dev, int resno)
{ {
struct resource tmp; return pci_iov_resource_size(dev, resno);
int reg = pci_iov_resource_bar(dev, resno);
if (!reg)
return 0;
__pci_read_base(dev, pci_bar_unknown, &tmp, reg);
return resource_alignment(&tmp);
} }
/** /**

View File

@ -247,6 +247,7 @@ struct pci_sriov {
struct pci_dev *dev; /* lowest numbered PF */ struct pci_dev *dev; /* lowest numbered PF */
struct pci_dev *self; /* this PF */ struct pci_dev *self; /* this PF */
struct mutex lock; /* lock for VF bus */ struct mutex lock; /* lock for VF bus */
resource_size_t barsz[PCI_SRIOV_NUM_BARS]; /* VF BAR size */
}; };
#ifdef CONFIG_PCI_ATS #ifdef CONFIG_PCI_ATS

View File

@ -1675,6 +1675,7 @@ int pci_num_vf(struct pci_dev *dev);
int pci_vfs_assigned(struct pci_dev *dev); int pci_vfs_assigned(struct pci_dev *dev);
int pci_sriov_set_totalvfs(struct pci_dev *dev, u16 numvfs); int pci_sriov_set_totalvfs(struct pci_dev *dev, u16 numvfs);
int pci_sriov_get_totalvfs(struct pci_dev *dev); int pci_sriov_get_totalvfs(struct pci_dev *dev);
resource_size_t pci_iov_resource_size(struct pci_dev *dev, int resno);
#else #else
static inline int pci_enable_sriov(struct pci_dev *dev, int nr_virtfn) static inline int pci_enable_sriov(struct pci_dev *dev, int nr_virtfn)
{ return -ENODEV; } { return -ENODEV; }
@ -1686,6 +1687,8 @@ static inline int pci_sriov_set_totalvfs(struct pci_dev *dev, u16 numvfs)
{ return 0; } { return 0; }
static inline int pci_sriov_get_totalvfs(struct pci_dev *dev) static inline int pci_sriov_get_totalvfs(struct pci_dev *dev)
{ return 0; } { return 0; }
static inline resource_size_t pci_iov_resource_size(struct pci_dev *dev, int resno)
{ return 0; }
#endif #endif
#if defined(CONFIG_HOTPLUG_PCI) || defined(CONFIG_HOTPLUG_PCI_MODULE) #if defined(CONFIG_HOTPLUG_PCI) || defined(CONFIG_HOTPLUG_PCI_MODULE)