Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

PCI: Disable VF decoding before pcibios_sriov_disable() updates resources

A struct resource represents the address space consumed by a device. We
should not modify that resource while the device is actively using the
address space. For VFs, pci_iov_update_resource() enforces this by
printing a warning and doing nothing if the VFE (VF Enable) and MSE (VF
Memory Space Enable) bits are set.

Previously, both sriov_enable() and sriov_disable() called the
pcibios_sriov_disable() arch hook, which may update the struct resource,
while VFE and MSE were enabled. This effectively dropped the resource
update pcibios_sriov_disable() intended to do.

Disable VF memory decoding before calling pcibios_sriov_disable().

Reported-by: Carol L Soto <clsoto@us.ibm.com>
Tested-by: Carol L Soto <clsoto@us.ibm.com>
Signed-off-by: Gavin Shan <gwshan@linux.vnet.ibm.com>
Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
[bhelgaas: changelog]
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Cc: shan.gavin@gmail.com
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Paul Mackerras <paulus@samba.org>

authored by

Gavin Shan and committed by
Bjorn Helgaas
0fc690a7 a0418aa2

+4 -3
+4 -3
drivers/pci/iov.c
··· 331 331 while (i--) 332 332 pci_iov_remove_virtfn(dev, i, 0); 333 333 334 - pcibios_sriov_disable(dev); 335 334 err_pcibios: 336 335 iov->ctrl &= ~(PCI_SRIOV_CTRL_VFE | PCI_SRIOV_CTRL_MSE); 337 336 pci_cfg_access_lock(dev); 338 337 pci_write_config_word(dev, iov->pos + PCI_SRIOV_CTRL, iov->ctrl); 339 338 ssleep(1); 340 339 pci_cfg_access_unlock(dev); 340 + 341 + pcibios_sriov_disable(dev); 341 342 342 343 if (iov->link != dev->devfn) 343 344 sysfs_remove_link(&dev->dev.kobj, "dep_link"); ··· 358 357 for (i = 0; i < iov->num_VFs; i++) 359 358 pci_iov_remove_virtfn(dev, i, 0); 360 359 361 - pcibios_sriov_disable(dev); 362 - 363 360 iov->ctrl &= ~(PCI_SRIOV_CTRL_VFE | PCI_SRIOV_CTRL_MSE); 364 361 pci_cfg_access_lock(dev); 365 362 pci_write_config_word(dev, iov->pos + PCI_SRIOV_CTRL, iov->ctrl); 366 363 ssleep(1); 367 364 pci_cfg_access_unlock(dev); 365 + 366 + pcibios_sriov_disable(dev); 368 367 369 368 if (iov->link != dev->devfn) 370 369 sysfs_remove_link(&dev->dev.kobj, "dep_link");