mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Shameer Kolothum <skolothumtho@nvidia.com>
To: <kvm@vger.kernel.org>, <linux-pci@vger.kernel.org>,
	<linux-kernel@vger.kernel.org>
Cc: <alex@shazbot.org>, <jgg@ziepe.ca>, <kevin.tian@intel.com>,
	<kbusch@meta.com>, <michal.winiarski@intel.com>,
	<satyanarayana.k.v.p@intel.com>, <sonangp@nvidia.com>,
	<ankita@nvidia.com>, <nathanc@nvidia.com>, <mochs@nvidia.com>,
	<skolothumtho@nvidia.com>
Subject: [RFC PATCH v3 03/20] vfio/pci: Avoid waiting for the bus lock when preparing D0
Date: Thu, 12 Nov 2026 14:16:15 +0000	[thread overview]
Message-ID: <20261112141632.918954-4-skolothumtho@nvidia.com> (raw)
In-Reply-To: <20261112141632.918954-1-skolothumtho@nvidia.com>

A D0 transition can wait behind a pci_bus_sem writer while holding locks
needed by PCI error recovery. Recovery holds the bus read lock, leaving
all three tasks waiting for each other.

Use pci_try_set_power_state() for D0 preparation during function reset,
hot reset, runtime suspend and SR-IOV enable. Preserve VFIO's saved PM
state handling and unwind reset and SR-IOV requests if D0 preparation
fails.

Runtime suspend returns -EAGAIN on bus-lock contention. Keep its existing
handling of other D0 errors to avoid leaving runtime PM in an error state.

Apply this even when recovery is disabled, since global IRQ cleanup can
wait for another device's D0 transition. Low-power transitions keep the
existing helper. Subsequent patch handles config-space power requests.

Signed-off-by: Shameer Kolothum <skolothumtho@nvidia.com>
---
 drivers/vfio/pci/vfio_pci_priv.h |  2 ++
 drivers/vfio/pci/vfio_pci_core.c | 49 +++++++++++++++++++++++++++-----
 2 files changed, 44 insertions(+), 7 deletions(-)

diff --git a/drivers/vfio/pci/vfio_pci_priv.h b/drivers/vfio/pci/vfio_pci_priv.h
index 97b69e4bc8be..2a15a8956205 100644
--- a/drivers/vfio/pci/vfio_pci_priv.h
+++ b/drivers/vfio/pci/vfio_pci_priv.h
@@ -67,6 +67,8 @@ void vfio_config_free(struct vfio_pci_core_device *vdev);
 
 int vfio_pci_set_power_state(struct vfio_pci_core_device *vdev,
 			     pci_power_t state);
+int vfio_pci_try_set_power_state(struct vfio_pci_core_device *vdev,
+				 pci_power_t state);
 
 void vfio_pci_zap_and_down_write_memory_lock(struct vfio_pci_core_device *vdev);
 u16 vfio_pci_memory_lock_and_enable(struct vfio_pci_core_device *vdev);
diff --git a/drivers/vfio/pci/vfio_pci_core.c b/drivers/vfio/pci/vfio_pci_core.c
index b7d81233b99b..6529eab7865b 100644
--- a/drivers/vfio/pci/vfio_pci_core.c
+++ b/drivers/vfio/pci/vfio_pci_core.c
@@ -378,7 +378,10 @@ long vfio_pci_core_access(struct vfio_pci_core_device *vdev,
  * by PM capability emulation and separately from pci_dev internal saved state
  * to avoid it being overwritten and consumed around other resets.
  */
-int vfio_pci_set_power_state(struct vfio_pci_core_device *vdev, pci_power_t state)
+static int __vfio_pci_set_power_state(struct vfio_pci_core_device *vdev,
+				      pci_power_t state,
+				      int (*set_power_state)(struct pci_dev *,
+							     pci_power_t))
 {
 	struct pci_dev *pdev = vdev->pdev;
 	bool needs_restore = false, needs_save = false;
@@ -401,7 +404,7 @@ int vfio_pci_set_power_state(struct vfio_pci_core_device *vdev, pci_power_t stat
 			needs_restore = true;
 	}
 
-	ret = pci_set_power_state(pdev, state);
+	ret = set_power_state(pdev, state);
 
 	if (!ret) {
 		/* D3 might be unsupported via quirk, skip unless in D3 */
@@ -429,6 +432,20 @@ int vfio_pci_set_power_state(struct vfio_pci_core_device *vdev, pci_power_t stat
 	return ret;
 }
 
+int vfio_pci_set_power_state(struct vfio_pci_core_device *vdev, pci_power_t state)
+{
+	return __vfio_pci_set_power_state(vdev, state, pci_set_power_state);
+}
+
+/* Avoid waiting for pci_bus_sem under locks needed by PCI recovery. */
+int vfio_pci_try_set_power_state(struct vfio_pci_core_device *vdev,
+				 pci_power_t state)
+{
+	return __vfio_pci_set_power_state(vdev, state,
+					state == PCI_D0 ? pci_try_set_power_state :
+					pci_set_power_state);
+}
+
 static int vfio_pci_runtime_pm_entry(struct vfio_pci_core_device *vdev,
 				     struct eventfd_ctx *efdctx)
 {
@@ -550,6 +567,8 @@ static int vfio_pci_core_pm_exit(struct vfio_pci_core_device *vdev, u32 flags,
 #ifdef CONFIG_PM
 int vfio_pci_core_runtime_suspend(struct vfio_pci_core_device *vdev)
 {
+	int ret;
+
 	down_write(&vdev->memory_lock);
 	/*
 	 * The user can move the device into D3hot state before invoking
@@ -559,8 +578,11 @@ int vfio_pci_core_runtime_suspend(struct vfio_pci_core_device *vdev)
 	 * NoSoftRst-, it will help in restoring the original state
 	 * (saved locally in 'vdev->pm_save').
 	 */
-	vfio_pci_set_power_state(vdev, PCI_D0);
+	ret = vfio_pci_try_set_power_state(vdev, PCI_D0);
 	up_write(&vdev->memory_lock);
+	/* Preserve the existing handling of other D0 transition errors. */
+	if (ret == -EAGAIN)
+		return ret;
 
 	/*
 	 * If INTx is enabled, then mask INTx before going into the runtime
@@ -1401,7 +1423,11 @@ static int vfio_pci_ioctl_reset(struct vfio_pci_core_device *vdev,
 	 * reset without restoring the original state (saved locally in
 	 * 'vdev->pm_save').
 	 */
-	vfio_pci_set_power_state(vdev, PCI_D0);
+	ret = vfio_pci_try_set_power_state(vdev, PCI_D0);
+	if (ret) {
+		up_write(&vdev->memory_lock);
+		return ret;
+	}
 
 	vfio_pci_dma_buf_move(vdev, true);
 	ret = pci_try_reset_function(vdev->pdev);
@@ -2453,7 +2479,12 @@ int vfio_pci_core_sriov_configure(struct vfio_pci_core_device *vdev,
 			goto out_del;
 
 		down_write(&vdev->memory_lock);
-		vfio_pci_set_power_state(vdev, PCI_D0);
+		ret = vfio_pci_try_set_power_state(vdev, PCI_D0);
+		if (ret) {
+			up_write(&vdev->memory_lock);
+			pm_runtime_put(&pdev->dev);
+			goto out_del;
+		}
 		vdev->sriov_active = true;
 		up_write(&vdev->memory_lock);
 		ret = pci_enable_sriov(pdev, nr_virtfn);
@@ -2656,11 +2687,15 @@ static int vfio_pci_dev_set_hot_reset(struct vfio_device_set *dev_set,
 	 * cause the PCI config space reset without restoring the original
 	 * state (saved locally in 'vdev->pm_save').
 	 */
-	list_for_each_entry(vdev, &dev_set->device_list, vdev.dev_set_list)
-		vfio_pci_set_power_state(vdev, PCI_D0);
+	list_for_each_entry(vdev, &dev_set->device_list, vdev.dev_set_list) {
+		ret = vfio_pci_try_set_power_state(vdev, PCI_D0);
+		if (ret)
+			goto out_unlock_memory;
+	}
 
 	ret = pci_reset_bus(pdev);
 
+out_unlock_memory:
 	vdev = list_last_entry(&dev_set->device_list,
 			       struct vfio_pci_core_device, vdev.dev_set_list);
 
-- 
2.43.0


  parent reply	other threads:[~2026-11-12 14:18 UTC|newest]

Thread overview: 21+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-12 14:16 [RFC PATCH v3 00/20] vfio/pci: Handle PCI error recovery and report state to userspace Shameer Kolothum
2026-11-12 14:16 ` [RFC PATCH v3 01/20] vfio/pci: Add SRCU-protected access ops Shameer Kolothum
2026-11-12 14:16 ` [RFC PATCH v3 02/20] PCI/PM: Add a power-state helper that tries the bus lock Shameer Kolothum
2026-11-12 14:16 ` Shameer Kolothum [this message]
2026-11-12 14:16 ` [RFC PATCH v3 04/20] vfio/pci: Use access ops for config-space accesses Shameer Kolothum
2026-11-12 14:16 ` [RFC PATCH v3 05/20] vfio/pci: Buffer ROM reads before copying to userspace Shameer Kolothum
2026-11-12 14:16 ` [RFC PATCH v3 06/20] vfio/pci: Use access ops for BAR and ROM accesses Shameer Kolothum
2026-11-12 14:16 ` [RFC PATCH v3 07/20] vfio/pci: Use access ops when mapping BAR pages Shameer Kolothum
2026-11-12 14:16 ` [RFC PATCH v3 08/20] vfio/pci: Use access ops for hardware IRQ operations Shameer Kolothum
2026-11-12 14:16 ` [RFC PATCH v3 09/20] vfio/pci: Use access ops for function reset Shameer Kolothum
2026-11-12 14:16 ` [RFC PATCH v3 10/20] vfio/pci: Use access ops for runtime-PM requests Shameer Kolothum
2026-11-12 14:16 ` [RFC PATCH v3 11/20] vfio/pci: Use access ops for hardware information queries Shameer Kolothum
2026-11-12 14:16 ` [RFC PATCH v3 12/20] vfio/pci: Use access ops for DMA-BUF export and restoration Shameer Kolothum
2026-11-12 14:16 ` [RFC PATCH v3 13/20] vfio/pci: Track PCI recovery state Shameer Kolothum
2026-11-12 14:16 ` [RFC PATCH v3 14/20] vfio/pci: Add INTx recovery operations Shameer Kolothum
2026-11-12 14:16 ` [RFC PATCH v3 15/20] vfio/pci: Use access ops for SR-IOV configuration and shared reset Shameer Kolothum
2026-11-12 14:16 ` [RFC PATCH v3 16/20] vfio/pci: Restore device state from slot_reset() Shameer Kolothum
2026-11-12 14:16 ` [RFC PATCH v3 17/20] vfio/pci: Complete recovery in resume() Shameer Kolothum
2026-11-12 14:16 ` [RFC PATCH v3 18/20] vfio/pci: Block device access during host recovery Shameer Kolothum
2026-11-12 14:16 ` [RFC PATCH v3 19/20] vfio/pci: Add VFIO_DEVICE_FEATURE_PCI_ERROR_RECOVERY Shameer Kolothum
2026-11-12 14:16 ` [RFC PATCH v3 20/20] vfio/pci: Enable recovery for supported native PCIe endpoints Shameer Kolothum

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20261112141632.918954-4-skolothumtho@nvidia.com \
    --to=skolothumtho@nvidia.com \
    --cc=alex@shazbot.org \
    --cc=ankita@nvidia.com \
    --cc=jgg@ziepe.ca \
    --cc=kbusch@meta.com \
    --cc=kevin.tian@intel.com \
    --cc=kvm@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-pci@vger.kernel.org \
    --cc=michal.winiarski@intel.com \
    --cc=mochs@nvidia.com \
    --cc=nathanc@nvidia.com \
    --cc=satyanarayana.k.v.p@intel.com \
    --cc=sonangp@nvidia.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®