vfio_pci_core_disable() is a very long function doing multiple things
like exiting runtime power management, setting device to D0 power,
clearing bus master, clearing irqs, freeing eventfds, releasing device
regions, unmapping PCI bars, and performing device/bus resets.

The upcoming VFIO Liveupdate feature will also need to utilize same
reset logic.

Extract device reset code to a new helper function,
vfio_pci_core_try_reset(), and update vfio_pci_core_disable() to use
this new function.

No functional change intended.

Co-developed-by: David Matlack <[email protected]>
Signed-off-by: David Matlack <[email protected]>
Signed-off-by: Vipin Sharma <[email protected]>
---
 drivers/vfio/pci/vfio_pci_core.c | 100 ++++++++++++++++---------------
 1 file changed, 53 insertions(+), 47 deletions(-)

diff --git a/drivers/vfio/pci/vfio_pci_core.c b/drivers/vfio/pci/vfio_pci_core.c
index a28f1e99362c..3c8b990ee92f 100644
--- a/drivers/vfio/pci/vfio_pci_core.c
+++ b/drivers/vfio/pci/vfio_pci_core.c
@@ -623,9 +623,60 @@ int vfio_pci_core_enable(struct vfio_pci_core_device *vdev)
 }
 EXPORT_SYMBOL_GPL(vfio_pci_core_enable);
 
-void vfio_pci_core_disable(struct vfio_pci_core_device *vdev)
+static void vfio_pci_core_try_reset(struct vfio_pci_core_device *vdev)
 {
+       struct pci_dev *pdev = vdev->pdev;
        struct pci_dev *bridge;
+
+       vdev->needs_reset = true;
+
+       /*
+        * If we have saved state, restore it.  If we can reset the device,
+        * even better.  Resetting with current state seems better than
+        * nothing, but saving and restoring current state without reset
+        * is just busy work.
+        */
+       if (pci_load_and_free_saved_state(pdev, &vdev->pci_saved_state)) {
+               pci_info(pdev, "%s: Couldn't reload saved state\n", __func__);
+
+               if (!vdev->reset_works)
+                       return;
+
+               pci_save_state(pdev);
+       }
+
+       /*
+        * Disable INTx and MSI, presumably to avoid spurious interrupts
+        * during reset.  Stolen from pci_reset_function()
+        */
+       pci_write_config_word(pdev, PCI_COMMAND, PCI_COMMAND_INTX_DISABLE);
+
+       /*
+        * Try to get the locks ourselves to prevent a deadlock. The
+        * success of this is dependent on being able to lock the device,
+        * which is not always possible.
+        * We can not use the "try" reset interface here, which will
+        * overwrite the previously restored configuration information.
+        */
+       if (vdev->reset_works) {
+               bridge = pci_upstream_bridge(pdev);
+               if (bridge && !pci_dev_trylock(bridge))
+                       goto out_restore_state;
+               if (pci_dev_trylock(pdev)) {
+                       if (!__pci_reset_function_locked(pdev))
+                               vdev->needs_reset = false;
+                       pci_dev_unlock(pdev);
+               }
+               if (bridge)
+                       pci_dev_unlock(bridge);
+       }
+
+out_restore_state:
+       pci_restore_state(pdev);
+}
+
+void vfio_pci_core_disable(struct vfio_pci_core_device *vdev)
+{
        struct pci_dev *pdev = vdev->pdev;
        struct vfio_pci_dummy_resource *dummy_res, *tmp;
        struct vfio_pci_ioeventfd *ioeventfd, *ioeventfd_tmp;
@@ -700,54 +751,9 @@ void vfio_pci_core_disable(struct vfio_pci_core_device 
*vdev)
                kfree(dummy_res);
        }
 
-       vdev->needs_reset = true;
-
        vfio_pci_zdev_close_device(vdev);
 
-       /*
-        * If we have saved state, restore it.  If we can reset the device,
-        * even better.  Resetting with current state seems better than
-        * nothing, but saving and restoring current state without reset
-        * is just busy work.
-        */
-       if (pci_load_and_free_saved_state(pdev, &vdev->pci_saved_state)) {
-               pci_info(pdev, "%s: Couldn't reload saved state\n", __func__);
-
-               if (!vdev->reset_works)
-                       goto out;
-
-               pci_save_state(pdev);
-       }
-
-       /*
-        * Disable INTx and MSI, presumably to avoid spurious interrupts
-        * during reset.  Stolen from pci_reset_function()
-        */
-       pci_write_config_word(pdev, PCI_COMMAND, PCI_COMMAND_INTX_DISABLE);
-
-       /*
-        * Try to get the locks ourselves to prevent a deadlock. The
-        * success of this is dependent on being able to lock the device,
-        * which is not always possible.
-        * We can not use the "try" reset interface here, which will
-        * overwrite the previously restored configuration information.
-        */
-       if (vdev->reset_works) {
-               bridge = pci_upstream_bridge(pdev);
-               if (bridge && !pci_dev_trylock(bridge))
-                       goto out_restore_state;
-               if (pci_dev_trylock(pdev)) {
-                       if (!__pci_reset_function_locked(pdev))
-                               vdev->needs_reset = false;
-                       pci_dev_unlock(pdev);
-               }
-               if (bridge)
-                       pci_dev_unlock(bridge);
-       }
-
-out_restore_state:
-       pci_restore_state(pdev);
-out:
+       vfio_pci_core_try_reset(vdev);
        pci_disable_device(pdev);
 
        vfio_pci_dev_set_try_reset(vdev->vdev.dev_set);
-- 
2.55.0.795.g602f6c329a-goog


Reply via email to