PCI: Refresh First VF Offset and VF Stride when updating NumVFs
The First VF Offset and VF Stride fields depend on the NumVFs setting, so refresh the cached fields in struct pci_sriov when updating NumVFs. See the SR-IOV spec r1.1, sec 3.3.9 and 3.3.10. [bhelgaas: changelog, remove kernel-doc comment marker] 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:
parent
c1fe1f96e3
commit
f59dca27d2
@ -31,6 +31,21 @@ static inline u8 virtfn_devfn(struct pci_dev *dev, int id)
|
||||
dev->sriov->stride * id) & 0xff;
|
||||
}
|
||||
|
||||
/*
|
||||
* Per SR-IOV spec sec 3.3.10 and 3.3.11, First VF Offset and VF Stride may
|
||||
* change when NumVFs changes.
|
||||
*
|
||||
* Update iov->offset and iov->stride when NumVFs is written.
|
||||
*/
|
||||
static inline void pci_iov_set_numvfs(struct pci_dev *dev, int nr_virtfn)
|
||||
{
|
||||
struct pci_sriov *iov = dev->sriov;
|
||||
|
||||
pci_write_config_word(dev, iov->pos + PCI_SRIOV_NUM_VF, nr_virtfn);
|
||||
pci_read_config_word(dev, iov->pos + PCI_SRIOV_VF_OFFSET, &iov->offset);
|
||||
pci_read_config_word(dev, iov->pos + PCI_SRIOV_VF_STRIDE, &iov->stride);
|
||||
}
|
||||
|
||||
static struct pci_bus *virtfn_add_bus(struct pci_bus *bus, int busnr)
|
||||
{
|
||||
struct pci_bus *child;
|
||||
@ -253,7 +268,7 @@ static int sriov_enable(struct pci_dev *dev, int nr_virtfn)
|
||||
return rc;
|
||||
}
|
||||
|
||||
pci_write_config_word(dev, iov->pos + PCI_SRIOV_NUM_VF, nr_virtfn);
|
||||
pci_iov_set_numvfs(dev, nr_virtfn);
|
||||
iov->ctrl |= PCI_SRIOV_CTRL_VFE | PCI_SRIOV_CTRL_MSE;
|
||||
pci_cfg_access_lock(dev);
|
||||
pci_write_config_word(dev, iov->pos + PCI_SRIOV_CTRL, iov->ctrl);
|
||||
@ -282,7 +297,7 @@ failed:
|
||||
iov->ctrl &= ~(PCI_SRIOV_CTRL_VFE | PCI_SRIOV_CTRL_MSE);
|
||||
pci_cfg_access_lock(dev);
|
||||
pci_write_config_word(dev, iov->pos + PCI_SRIOV_CTRL, iov->ctrl);
|
||||
pci_write_config_word(dev, iov->pos + PCI_SRIOV_NUM_VF, 0);
|
||||
pci_iov_set_numvfs(dev, 0);
|
||||
ssleep(1);
|
||||
pci_cfg_access_unlock(dev);
|
||||
|
||||
@ -313,7 +328,7 @@ static void sriov_disable(struct pci_dev *dev)
|
||||
sysfs_remove_link(&dev->dev.kobj, "dep_link");
|
||||
|
||||
iov->num_VFs = 0;
|
||||
pci_write_config_word(dev, iov->pos + PCI_SRIOV_NUM_VF, 0);
|
||||
pci_iov_set_numvfs(dev, 0);
|
||||
}
|
||||
|
||||
static int sriov_init(struct pci_dev *dev, int pos)
|
||||
@ -452,7 +467,7 @@ static void sriov_restore_state(struct pci_dev *dev)
|
||||
pci_update_resource(dev, i);
|
||||
|
||||
pci_write_config_dword(dev, iov->pos + PCI_SRIOV_SYS_PGSIZE, iov->pgsz);
|
||||
pci_write_config_word(dev, iov->pos + PCI_SRIOV_NUM_VF, iov->num_VFs);
|
||||
pci_iov_set_numvfs(dev, iov->num_VFs);
|
||||
pci_write_config_word(dev, iov->pos + PCI_SRIOV_CTRL, iov->ctrl);
|
||||
if (iov->ctrl & PCI_SRIOV_CTRL_VFE)
|
||||
msleep(100);
|
||||
|
Loading…
Reference in New Issue
Block a user