diff options
-rw-r--r-- | drivers/pci/iov.c | 23 |
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 | */ | ||
40 | static 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 | |||
34 | static struct pci_bus *virtfn_add_bus(struct pci_bus *bus, int busnr) | 49 | static 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 | ||
319 | static int sriov_init(struct pci_dev *dev, int pos) | 334 | static 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); |