Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0e6c9122 authored by Wei Yang's avatar Wei Yang Committed by Benjamin Herrenschmidt
Browse files

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: default avatarWei Yang <weiyang@linux.vnet.ibm.com>
Acked-by: default avatarBjorn Helgaas <bhelgaas@google.com>
Signed-off-by: default avatarBenjamin Herrenschmidt <benh@kernel.crashing.org>
parent e88ae01d
Loading
Loading
Loading
Loading
+20 −19
Original line number Original line Diff line number Diff line
@@ -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,10 +367,14 @@ static int sriov_init(struct pci_dev *dev, int pos)
	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;
@@ -371,18 +382,14 @@ static int sriov_init(struct pci_dev *dev, int pos)
			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 @@ static int sriov_init(struct pci_dev *dev, int pos)
		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);
}
}


/**
/**
+1 −0
Original line number Original line Diff line number Diff line
@@ -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
+3 −0
Original line number Original line Diff line number Diff line
@@ -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)