aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/pci/iov.c23
1 files changed, 19 insertions, 4 deletions
diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c
index 27b98c361823..a8752c2c2b53 100644
--- a/drivers/pci/iov.c
+++ b/drivers/pci/iov.c
@@ -31,6 +31,21 @@ static inline u8 virtfn_devfn(struct pci_dev *dev, int id)
31 dev->sriov->stride * id) & 0xff; 31 dev->sriov->stride * id) & 0xff;
32} 32}
33 33
34/*
35 * Per SR-IOV spec sec 3.3.10 and 3.3.11, First VF Offset and VF Stride may
36 * change when NumVFs changes.
37 *
38 * Update iov->offset and iov->stride when NumVFs is written.
39 */
40static inline void pci_iov_set_numvfs(struct pci_dev *dev, int nr_virtfn)
41{
42 struct pci_sriov *iov = dev->sriov;
43
44 pci_write_config_word(dev, iov->pos + PCI_SRIOV_NUM_VF, nr_virtfn);
45 pci_read_config_word(dev, iov->pos + PCI_SRIOV_VF_OFFSET, &iov->offset);
46 pci_read_config_word(dev, iov->pos + PCI_SRIOV_VF_STRIDE, &iov->stride);
47}
48
34static struct pci_bus *virtfn_add_bus(struct pci_bus *bus, int busnr) 49static struct pci_bus *virtfn_add_bus(struct pci_bus *bus, int busnr)
35{ 50{
36 struct pci_bus *child; 51 struct pci_bus *child;
@@ -253,7 +268,7 @@ static int sriov_enable(struct pci_dev *dev, int nr_virtfn)
253 return rc; 268 return rc;
254 } 269 }
255 270
256 pci_write_config_word(dev, iov->pos + PCI_SRIOV_NUM_VF, nr_virtfn); 271 pci_iov_set_numvfs(dev, nr_virtfn);
257 iov->ctrl |= PCI_SRIOV_CTRL_VFE | PCI_SRIOV_CTRL_MSE; 272 iov->ctrl |= PCI_SRIOV_CTRL_VFE | PCI_SRIOV_CTRL_MSE;
258 pci_cfg_access_lock(dev); 273 pci_cfg_access_lock(dev);
259 pci_write_config_word(dev, iov->pos + PCI_SRIOV_CTRL, iov->ctrl); 274 pci_write_config_word(dev, iov->pos + PCI_SRIOV_CTRL, iov->ctrl);
@@ -282,7 +297,7 @@ failed:
282 iov->ctrl &= ~(PCI_SRIOV_CTRL_VFE | PCI_SRIOV_CTRL_MSE); 297 iov->ctrl &= ~(PCI_SRIOV_CTRL_VFE | PCI_SRIOV_CTRL_MSE);
283 pci_cfg_access_lock(dev); 298 pci_cfg_access_lock(dev);
284 pci_write_config_word(dev, iov->pos + PCI_SRIOV_CTRL, iov->ctrl); 299 pci_write_config_word(dev, iov->pos + PCI_SRIOV_CTRL, iov->ctrl);
285 pci_write_config_word(dev, iov->pos + PCI_SRIOV_NUM_VF, 0); 300 pci_iov_set_numvfs(dev, 0);
286 ssleep(1); 301 ssleep(1);
287 pci_cfg_access_unlock(dev); 302 pci_cfg_access_unlock(dev);
288 303
@@ -313,7 +328,7 @@ static void sriov_disable(struct pci_dev *dev)
313 sysfs_remove_link(&dev->dev.kobj, "dep_link"); 328 sysfs_remove_link(&dev->dev.kobj, "dep_link");
314 329
315 iov->num_VFs = 0; 330 iov->num_VFs = 0;
316 pci_write_config_word(dev, iov->pos + PCI_SRIOV_NUM_VF, 0); 331 pci_iov_set_numvfs(dev, 0);
317} 332}
318 333
319static int sriov_init(struct pci_dev *dev, int pos) 334static int sriov_init(struct pci_dev *dev, int pos)
@@ -452,7 +467,7 @@ static void sriov_restore_state(struct pci_dev *dev)
452 pci_update_resource(dev, i); 467 pci_update_resource(dev, i);
453 468
454 pci_write_config_dword(dev, iov->pos + PCI_SRIOV_SYS_PGSIZE, iov->pgsz); 469 pci_write_config_dword(dev, iov->pos + PCI_SRIOV_SYS_PGSIZE, iov->pgsz);
455 pci_write_config_word(dev, iov->pos + PCI_SRIOV_NUM_VF, iov->num_VFs); 470 pci_iov_set_numvfs(dev, iov->num_VFs);
456 pci_write_config_word(dev, iov->pos + PCI_SRIOV_CTRL, iov->ctrl); 471 pci_write_config_word(dev, iov->pos + PCI_SRIOV_CTRL, iov->ctrl);
457 if (iov->ctrl & PCI_SRIOV_CTRL_VFE) 472 if (iov->ctrl & PCI_SRIOV_CTRL_VFE)
458 msleep(100); 473 msleep(100);