* [PATCH v8 0/3] PCI: Add d3cold and device-specific reset for Qualcomm devices
@ 2026-06-09 16:36 Jose Ignacio Tornos Martinez
2026-06-09 16:36 ` [PATCH v8 1/3] PCI: Add d3cold as general reset method Jose Ignacio Tornos Martinez
` (2 more replies)
0 siblings, 3 replies; 7+ messages in thread
From: Jose Ignacio Tornos Martinez @ 2026-06-09 16:36 UTC (permalink / raw)
To: bhelgaas, alex
Cc: jjohnson, mani, linux-pci, linux-wireless, ath11k, ath12k, mhi,
linux-kernel, Jose Ignacio Tornos Martinez
Some PCIe devices lack working reset methods for VFIO passthrough scenarios.
These devices typically have no FLR, advertise NoSoftRst+ (blocking PM reset),
and have broken or unavailable bus reset. When a VM crashes, VFIO cannot reset
the device for reuse without a working reset method.
This series addresses the problem by adding general d3cold infrastructure and
device-specific reset for Qualcomm devices:
**Patch 1/3: d3cold reset method**
Adds D3cold as a general reset method with strict _PR3 requirement. Only
attempts true power cycling via platform control (ACPI _PR3), never falls
back to D3hot. This provides genuine power-off reset on platforms that
support it.
**Patch 2/3: device-specific reset for Qualcomm devices**
Adds device-specific reset entries for Qualcomm WCN6855/WCN7850 WiFi cards and
SDX62/SDX65 modems using D3cold power cycling with automatic D3hot fallback.
Uses pci_set_power_state(D3cold) which automatically falls back to D3hot on
platforms without _PR3. Extracts shared pci_dev_d3cold_d0_cycle() helper to
avoid code duplication with general d3cold method. Device-specific reset is
position #1 in reset hierarchy, providing immediate working reset for these
Qualcomm devices.
**Patch 3/3: Qualcomm quirk_no_bus_reset**
Disables broken bus reset for Qualcomm devices. Testing proves this is
device-specific: MediaTek MT7925e works correctly with bus reset using the
same passive M.2-to-PCIe adapters where Qualcomm devices fail, confirming
PERST# is properly wired and the issue is not deployment-specific. Acts as
safety net to prevent broken SBR if users override via sysfs.
v8: Fix commit message in patch 2/3: correct IOMMU handling description
Patches 1/3 and 3/3 unchanged from v7
v7: https://lore.kernel.org/all/20260603105853.326290-1-jtornosm@redhat.com/
Jose Ignacio Tornos Martinez (3):
PCI: Add d3cold as general reset method
PCI: Add device-specific reset for Qualcomm devices
PCI: Disable broken bus reset on Qualcomm devices
--
2.53.0
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v8 1/3] PCI: Add d3cold as general reset method
2026-06-09 16:36 [PATCH v8 0/3] PCI: Add d3cold and device-specific reset for Qualcomm devices Jose Ignacio Tornos Martinez
@ 2026-06-09 16:36 ` Jose Ignacio Tornos Martinez
2026-06-09 16:56 ` sashiko-bot
2026-06-09 16:36 ` [PATCH v8 2/3] PCI: Add device-specific reset for Qualcomm devices Jose Ignacio Tornos Martinez
2026-06-09 16:36 ` [PATCH v8 3/3] PCI: Disable broken bus reset on " Jose Ignacio Tornos Martinez
2 siblings, 1 reply; 7+ messages in thread
From: Jose Ignacio Tornos Martinez @ 2026-06-09 16:36 UTC (permalink / raw)
To: bhelgaas, alex
Cc: jjohnson, mani, linux-pci, linux-wireless, ath11k, ath12k, mhi,
linux-kernel, Jose Ignacio Tornos Martinez
Add D3cold power cycle as a general PCI reset method for single-function
devices on platforms with ACPI _PR3 power resources. This provides true
power cycle reset capability when the platform can physically cut power
to the device.
The implementation strictly requires _PR3 to be present - the platform
must be able to control device power. This ensures d3cold only attempts
true power cycling, not falling back to D3hot transitions.
D3cold reset is placed at the end of the reset hierarchy since it requires
specific platform support and should be tried after standard methods.
Reset hierarchy with this change:
1. device_specific
2. acpi
3. flr
4. af_flr
5. pm (D3hot via config space, checks NoSoftRst)
6. bus (SBR)
7. cxl_bus
8. d3cold (NEW - true power cycle, requires _PR3)
This benefits:
- Platforms with _PR3 support
- Single-function devices needing true power cycle
- VFIO passthrough scenarios where FLR/PM unavailable
Signed-off-by: Jose Ignacio Tornos Martinez <jtornosm@redhat.com>
---
v8: code unchanged from v7
v7: https://lore.kernel.org/all/20260603105853.326290-2-jtornosm@redhat.com/
drivers/pci/pci.c | 50 +++++++++++++++++++++++++++++++++++++++++++++
include/linux/pci.h | 2 +-
2 files changed, 51 insertions(+), 1 deletion(-)
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 8f7cfcc00090..096868f80cd4 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -4491,6 +4491,55 @@ static int pci_pm_reset(struct pci_dev *dev, bool probe)
return ret;
}
+/**
+ * pci_d3cold_reset - Put device into D3cold and back to D0 for reset
+ * @dev: PCI device to reset
+ * @probe: if true, check if D3cold reset is supported; if false, perform reset
+ *
+ * Reset the device by transitioning through D3cold (actual power removal via
+ * platform power control) and back to D0. This requires ACPI _PR3 power
+ * resources to be present - the platform must be able to physically cut power
+ * to the device.
+ *
+ * Only available for single-function devices to avoid affecting other
+ * functions in multi-function devices.
+ *
+ * Returns 0 if device can be/was reset this way, -ENOTTY if not supported,
+ * or other negative error code on failure.
+ */
+static int pci_d3cold_reset(struct pci_dev *dev, bool probe)
+{
+ int ret;
+
+ if (dev->multifunction)
+ return -ENOTTY;
+
+ if (!pci_pr3_present(dev))
+ return -ENOTTY;
+
+ if (probe)
+ return 0;
+
+ if (dev->current_state != PCI_D0)
+ return -EINVAL;
+
+ ret = pci_dev_reset_iommu_prepare(dev);
+ if (ret) {
+ pci_err(dev, "failed to stop IOMMU for a PCI reset: %d\n", ret);
+ return ret;
+ }
+
+ ret = pci_set_power_state(dev, PCI_D3cold);
+ if (ret)
+ goto done;
+
+ ret = pci_set_power_state(dev, PCI_D0);
+
+done:
+ pci_dev_reset_iommu_done(dev);
+ return ret;
+}
+
/**
* pcie_wait_for_link_status - Wait for link status change
* @pdev: Device whose link to wait for.
@@ -5065,6 +5114,7 @@ const struct pci_reset_fn_method pci_reset_fn_methods[] = {
{ pci_pm_reset, .name = "pm" },
{ pci_reset_bus_function, .name = "bus" },
{ cxl_reset_bus_function, .name = "cxl_bus" },
+ { pci_d3cold_reset, .name = "d3cold" },
};
/**
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 2c4454583c11..1ca7b880ead7 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -51,7 +51,7 @@
PCI_STATUS_PARITY)
/* Number of reset methods used in pci_reset_fn_methods array in pci.c */
-#define PCI_NUM_RESET_METHODS 8
+#define PCI_NUM_RESET_METHODS 9
#define PCI_RESET_PROBE true
#define PCI_RESET_DO_RESET false
--
2.54.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH v8 2/3] PCI: Add device-specific reset for Qualcomm devices
2026-06-09 16:36 [PATCH v8 0/3] PCI: Add d3cold and device-specific reset for Qualcomm devices Jose Ignacio Tornos Martinez
2026-06-09 16:36 ` [PATCH v8 1/3] PCI: Add d3cold as general reset method Jose Ignacio Tornos Martinez
@ 2026-06-09 16:36 ` Jose Ignacio Tornos Martinez
2026-06-09 17:11 ` sashiko-bot
2026-06-09 17:53 ` Alex Williamson
2026-06-09 16:36 ` [PATCH v8 3/3] PCI: Disable broken bus reset on " Jose Ignacio Tornos Martinez
2 siblings, 2 replies; 7+ messages in thread
From: Jose Ignacio Tornos Martinez @ 2026-06-09 16:36 UTC (permalink / raw)
To: bhelgaas, alex
Cc: jjohnson, mani, linux-pci, linux-wireless, ath11k, ath12k, mhi,
linux-kernel, Jose Ignacio Tornos Martinez
Some Qualcomm PCIe devices (WCN6855/WCN7850 WiFi cards, SDX62/SDX65 modems)
lack working reset methods for VFIO passthrough scenarios. These devices
have no FLR capability, advertise NoSoftRst+ (blocking PM reset), and have
broken bus reset.
The problem manifests in VFIO passthrough scenarios:
- WCN6855 WiFi card (17cb:1103): Normal VM operation works fine, including
clean shutdown/reboot. However, when the VM terminates uncleanly
(crash, force-off), VFIO attempts to reset the device before it can
be assigned to another VM. Without a working reset method, the device
remains in an undefined state, preventing reuse.
- WCN7850 WiFi card (17cb:1107): Same behavior as WCN6855.
- SDX62/SDX65 5G modems (17cb:0308): Never successfully initialize even
on first VM assignment without proper reset capability.
Add device-specific reset entries for these Qualcomm devices using D3cold
power cycling with automatic D3hot fallback. The implementation uses
pci_set_power_state(D3cold) which automatically falls back to D3hot on
platforms without ACPI _PR3 power resources. While not a complete reset
(BARs preserved), testing shows D3hot transition provides sufficient reset
for VFIO reuse.
Extract a shared pci_dev_d3cold_d0_cycle() helper function to avoid code
duplication between pci_d3cold_reset() (strict _PR3 requirement) and the
new reset_d3cold_d3hot() device-specific reset (automatic fallback).
The helper performs only the power cycle; IOMMU handling is done by the
caller (pci_d3cold_reset() for general method, __pci_dev_specific_reset()
wrapper for device-specific methods).
Device-specific reset is position #1 in the reset hierarchy, so these
Qualcomm devices will use power cycling as their primary reset method,
with the general d3cold method (position #8) available as a fallback on
_PR3-capable platforms if users override via sysfs.
Signed-off-by: Jose Ignacio Tornos Martinez <jtornosm@redhat.com>
---
v8: Fix commit message: correct IOMMU handling description. The helper
performs only the power cycle; IOMMU is handled by callers (this was
v6 fix)
v7: https://lore.kernel.org/all/20260603105853.326290-3-jtornosm@redhat.com/
drivers/pci/pci.c | 37 +++++++++++++++++++++++++++----------
drivers/pci/pci.h | 1 +
drivers/pci/quirks.c | 19 +++++++++++++++++++
3 files changed, 47 insertions(+), 10 deletions(-)
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 096868f80cd4..f7a7443287fd 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -4491,6 +4491,32 @@ static int pci_pm_reset(struct pci_dev *dev, bool probe)
return ret;
}
+/**
+ * pci_dev_d3cold_d0_cycle - Perform D3cold->D0 power cycle
+ * @dev: Device to power cycle
+ *
+ * Common helper to perform D3cold->D0 power cycle for reset methods.
+ * Attempts D3cold transition with automatic fallback to D3hot on platforms
+ * without ACPI _PR3 power resources.
+ *
+ * Caller must handle IOMMU preparation/cleanup if needed.
+ *
+ * Returns 0 on success, negative error code on failure.
+ */
+int pci_dev_d3cold_d0_cycle(struct pci_dev *dev)
+{
+ int ret;
+
+ if (dev->current_state != PCI_D0)
+ return -EINVAL;
+
+ ret = pci_set_power_state(dev, PCI_D3cold);
+ if (ret)
+ return ret;
+
+ return pci_set_power_state(dev, PCI_D0);
+}
+
/**
* pci_d3cold_reset - Put device into D3cold and back to D0 for reset
* @dev: PCI device to reset
@@ -4520,22 +4546,13 @@ static int pci_d3cold_reset(struct pci_dev *dev, bool probe)
if (probe)
return 0;
- if (dev->current_state != PCI_D0)
- return -EINVAL;
-
ret = pci_dev_reset_iommu_prepare(dev);
if (ret) {
pci_err(dev, "failed to stop IOMMU for a PCI reset: %d\n", ret);
return ret;
}
- ret = pci_set_power_state(dev, PCI_D3cold);
- if (ret)
- goto done;
-
- ret = pci_set_power_state(dev, PCI_D0);
-
-done:
+ ret = pci_dev_d3cold_d0_cycle(dev);
pci_dev_reset_iommu_done(dev);
return ret;
}
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index 4a14f88e543a..a9942787de9e 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -234,6 +234,7 @@ void pci_init_reset_methods(struct pci_dev *dev);
int pci_bridge_secondary_bus_reset(struct pci_dev *dev);
int pci_bus_error_reset(struct pci_dev *dev);
int pci_try_reset_bridge(struct pci_dev *bridge);
+int pci_dev_d3cold_d0_cycle(struct pci_dev *dev);
struct pci_cap_saved_data {
u16 cap_nr;
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index e49136ac5dbf..70f3b0f26799 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -4237,6 +4237,22 @@ static int reset_hinic_vf_dev(struct pci_dev *pdev, bool probe)
return 0;
}
+/*
+ * Device-specific reset method via D3cold/D3hot power cycle.
+ *
+ * Some devices lack working FLR, advertise NoSoftRst+ (blocking PM reset),
+ * and have broken bus reset. This function provides device-specific reset via
+ * power cycling, attempting D3cold with automatic fallback to D3hot on platforms
+ * without ACPI _PR3 power resources.
+ */
+static int reset_d3cold_d3hot(struct pci_dev *dev, bool probe)
+{
+ if (probe)
+ return 0;
+
+ return pci_dev_d3cold_d0_cycle(dev);
+}
+
static const struct pci_dev_reset_methods pci_dev_reset_methods[] = {
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82599_SFP_VF,
reset_intel_82599_sfp_virtfn },
@@ -4252,6 +4268,9 @@ static const struct pci_dev_reset_methods pci_dev_reset_methods[] = {
reset_chelsio_generic_dev },
{ PCI_VENDOR_ID_HUAWEI, PCI_DEVICE_ID_HINIC_VF,
reset_hinic_vf_dev },
+ { PCI_VENDOR_ID_QCOM, 0x1103, reset_d3cold_d3hot }, /* WCN6855 */
+ { PCI_VENDOR_ID_QCOM, 0x1107, reset_d3cold_d3hot }, /* WCN7850 */
+ { PCI_VENDOR_ID_QCOM, 0x0308, reset_d3cold_d3hot }, /* SDX62/SDX65 */
{ 0 }
};
--
2.54.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH v8 3/3] PCI: Disable broken bus reset on Qualcomm devices
2026-06-09 16:36 [PATCH v8 0/3] PCI: Add d3cold and device-specific reset for Qualcomm devices Jose Ignacio Tornos Martinez
2026-06-09 16:36 ` [PATCH v8 1/3] PCI: Add d3cold as general reset method Jose Ignacio Tornos Martinez
2026-06-09 16:36 ` [PATCH v8 2/3] PCI: Add device-specific reset for Qualcomm devices Jose Ignacio Tornos Martinez
@ 2026-06-09 16:36 ` Jose Ignacio Tornos Martinez
2 siblings, 0 replies; 7+ messages in thread
From: Jose Ignacio Tornos Martinez @ 2026-06-09 16:36 UTC (permalink / raw)
To: bhelgaas, alex
Cc: jjohnson, mani, linux-pci, linux-wireless, ath11k, ath12k, mhi,
linux-kernel, Jose Ignacio Tornos Martinez
Some Qualcomm PCIe devices (WCN6855/WCN7850 WiFi cards, SDX62/SDX65 modems)
do not properly support Secondary Bus Reset (SBR).
Testing confirms this is device-specific, not deployment-specific:
MediaTek MT7925e successfully uses bus reset through the same passive
M.2-to-PCIe adapters where Qualcomm devices fail, proving PERST# is
properly wired through the adapters.
This quirk acts as a safety net, preventing the broken bus reset from being
attempted if users override reset methods (device_specific or d3cold when
available) via sysfs.
Signed-off-by: Jose Ignacio Tornos Martinez <jtornosm@redhat.com>
---
v8: code unchanged from v7
v7: https://lore.kernel.org/all/20260603105853.326290-4-jtornosm@redhat.com/
drivers/pci/quirks.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 000000000000..111111111111 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -3789,6 +3789,9 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x0030, quirk_no_bus_reset);
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x0032, quirk_no_bus_reset);
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x003c, quirk_no_bus_reset);
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x0033, quirk_no_bus_reset);
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x0034, quirk_no_bus_reset);
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x003e, quirk_no_bus_reset);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_QCOM, 0x1103, quirk_no_bus_reset); /* WCN6855 */
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_QCOM, 0x1107, quirk_no_bus_reset); /* WCN7850 */
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_QCOM, 0x0308, quirk_no_bus_reset); /* SDX62/SDX65 */
/*
* Root port on some Cavium CN8xxx chips do not successfully complete a bus
--
2.53.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH v8 1/3] PCI: Add d3cold as general reset method
2026-06-09 16:36 ` [PATCH v8 1/3] PCI: Add d3cold as general reset method Jose Ignacio Tornos Martinez
@ 2026-06-09 16:56 ` sashiko-bot
0 siblings, 0 replies; 7+ messages in thread
From: sashiko-bot @ 2026-06-09 16:56 UTC (permalink / raw)
To: Jose Ignacio Tornos Martinez; +Cc: linux-pci
Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider:
- [Critical] pci_d3cold_reset() falsely claims a successful reset if the ACPI _PR3 power resource is shared, failing to perform a hardware reset.
- [High] Missing Device Readiness Wait after D3cold-to-D0 transition causes reset to fail systematically and triggers PCIe UR errors.
- [High] Improper error handling leaves the device in an unpowered state while the PCI core issues configuration restores, triggering fatal PCIe errors.
- [High] Function-level D3cold reset on a bridge device powers off and permanently corrupts the software and hardware state of all subordinate devices.
--
commit caf228f3a4ff5314b9f25df6186bf1777e5708ae
Author: Jose Ignacio Tornos Martinez <jtornosm@redhat.com>
PCI: Add d3cold as general reset method
This commit adds D3cold power cycle as a general PCI reset method for
single-function devices with ACPI _PR3 power resources. It places the
D3cold reset at the end of the reset hierarchy, executing a transition
through D3cold and back to D0.
> diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
> index 8f7cfcc000901..096868f80cd4c 100644
> --- a/drivers/pci/pci.c
> +++ b/drivers/pci/pci.c
[ ... ]
> @@ -4491,6 +4491,55 @@ static int pci_pm_reset(struct pci_dev *dev, bool probe)
> return ret;
> }
>
> +/**
> + * pci_d3cold_reset - Put device into D3cold and back to D0 for reset
> + * @dev: PCI device to reset
> + * @probe: if true, check if D3cold reset is supported; if false, perform reset
[ ... ]
> +static int pci_d3cold_reset(struct pci_dev *dev, bool probe)
> +{
> + int ret;
> +
> + if (dev->multifunction)
> + return -ENOTTY;
[Severity: High]
Does this also need to check if the device is a bridge?
If pci_d3cold_reset() is invoked on a bridge (e.g., via sysfs), transitioning
to D3cold cuts power to the entire downstream hierarchy. The software state of
all child devices is updated to PCI_D3cold.
When the bridge is restored to PCI_D0, only the bridge's software state is
updated. The subordinate devices' power is restored, but they remain marked
as PCI_D3cold without their drivers being notified. This exposes wiped hardware
state to active drivers and can lead to system crashes.
Could we add a check for pci_is_bridge(dev) or dev->subordinate here?
> +
> + if (!pci_pr3_present(dev))
> + return -ENOTTY;
[Severity: Critical]
Is there a way to verify that the _PR3 power resource is exclusively owned by
this device?
ACPI power resources are reference-counted. If the _PR3 resource is shared
among multiple devices, transitioning this single device to D3cold merely
decrements the OS reference count. Physical power is not actually cut unless
all other dependent devices are also in D3cold.
The pci_set_power_state() call will succeed logically, but if the device has
NoSoftRst=1, returning it to D0 will not actually reset the internal state.
This could falsely indicate a full reset was performed, which is a significant
risk in VFIO passthrough scenarios.
> +
> + if (probe)
> + return 0;
> +
> + if (dev->current_state != PCI_D0)
> + return -EINVAL;
> +
> + ret = pci_dev_reset_iommu_prepare(dev);
> + if (ret) {
> + pci_err(dev, "failed to stop IOMMU for a PCI reset: %d\n", ret);
> + return ret;
> + }
> +
> + ret = pci_set_power_state(dev, PCI_D3cold);
> + if (ret)
> + goto done;
[Severity: High]
This isn't a bug introduced by this patch, but how does this error path
interact with the PCI reset framework?
If pci_set_power_state() fails here, the device might remain in an unpowered
or partially powered state (D3cold or D3hot). The PCI reset framework in
pci_reset_function() ignores this failure and unconditionally executes
pci_dev_restore(dev).
Executing pci_restore_state() on a device stuck in D3hot or D3cold generates
configuration space accesses that result in Unsupported Requests (UR), PCIe
Completion Timeouts, or Master Aborts.
> +
> + ret = pci_set_power_state(dev, PCI_D0);
[Severity: High]
Is a delay required here before returning to allow the link to retrain?
A transition from D3cold to D0 acts as a Conventional Reset. The PCIe
specification requires the host to wait for the link to retrain and poll for
Configuration Request Retry Status (CRS) completions.
Because this returns immediately, the underlying pci_power_up() function reads
the PCI_PM_CTRL register while the link is still down, typically receiving
~0 (0xFFFF). This causes pci_power_up() to conclude the device is
inaccessible, returning -EIO.
Should this sleep for dev->d3cold_delay and call pci_dev_wait() before
returning?
> +
> +done:
> + pci_dev_reset_iommu_done(dev);
> + return ret;
> +}
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260609163649.319755-1-jtornosm@redhat.com?part=1
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v8 2/3] PCI: Add device-specific reset for Qualcomm devices
2026-06-09 16:36 ` [PATCH v8 2/3] PCI: Add device-specific reset for Qualcomm devices Jose Ignacio Tornos Martinez
@ 2026-06-09 17:11 ` sashiko-bot
2026-06-09 17:53 ` Alex Williamson
1 sibling, 0 replies; 7+ messages in thread
From: sashiko-bot @ 2026-06-09 17:11 UTC (permalink / raw)
To: Jose Ignacio Tornos Martinez; +Cc: linux-pci
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] The newly extracted `pci_dev_d3cold_d0_cycle()` helper, and thus the new device-specific method `reset_d3cold_d3hot()`, fails to wait for device readiness after transitioning the device to D0.
--
commit f0c27acd50ba34288a06f87ab1b9a8e74f06aba2
Author: Jose Ignacio Tornos Martinez <jtornosm@redhat.com>
PCI: Add device-specific reset for Qualcomm devices
This commit adds device-specific reset entries for several Qualcomm PCIe
devices that lack working reset methods. It implements a reset via D3cold
power cycling with automatic D3hot fallback, extracting a shared
pci_dev_d3cold_d0_cycle() helper for this purpose.
> diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
> index 096868f80cd4c..f7a7443287fdf 100644
> --- a/drivers/pci/pci.c
> +++ b/drivers/pci/pci.c
[ ... ]
> +int pci_dev_d3cold_d0_cycle(struct pci_dev *dev)
> +{
> + int ret;
> +
> + if (dev->current_state != PCI_D0)
> + return -EINVAL;
> +
> + ret = pci_set_power_state(dev, PCI_D3cold);
> + if (ret)
> + return ret;
> +
> + return pci_set_power_state(dev, PCI_D0);
> +}
[Severity: High]
Is there a missing wait for device readiness after transitioning to D0?
Standard reset implementations like pci_pm_reset() explicitly call
pci_dev_wait() after setting D0 to ensure the device has finished its
internal reset:
pci_pm_reset() {
...
csr |= PCI_D0;
pci_write_config_word(dev, dev->pm_cap + PCI_PM_CTRL, csr);
pci_dev_d3_sleep(dev);
ret = pci_dev_wait(dev, "PM D3hot->D0", PCIE_RESET_READY_POLL_MS);
...
}
Without this wait, does pci_dev_d3cold_d0_cycle() return before the
device is fully ready? If the caller (like VFIO via pci_reset_function)
immediately proceeds to restore the device's config space and BARs, could
those configuration writes be dropped or hit Configuration Request Retry
Status (CRS), leaving the device unconfigured?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260609163649.319755-1-jtornosm@redhat.com?part=2
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v8 2/3] PCI: Add device-specific reset for Qualcomm devices
2026-06-09 16:36 ` [PATCH v8 2/3] PCI: Add device-specific reset for Qualcomm devices Jose Ignacio Tornos Martinez
2026-06-09 17:11 ` sashiko-bot
@ 2026-06-09 17:53 ` Alex Williamson
1 sibling, 0 replies; 7+ messages in thread
From: Alex Williamson @ 2026-06-09 17:53 UTC (permalink / raw)
To: Jose Ignacio Tornos Martinez
Cc: bhelgaas, jjohnson, mani, linux-pci, linux-wireless, ath11k,
ath12k, mhi, linux-kernel, alex
On Tue, 9 Jun 2026 18:36:48 +0200
Jose Ignacio Tornos Martinez <jtornosm@redhat.com> wrote:
> Some Qualcomm PCIe devices (WCN6855/WCN7850 WiFi cards, SDX62/SDX65 modems)
> lack working reset methods for VFIO passthrough scenarios. These devices
> have no FLR capability, advertise NoSoftRst+ (blocking PM reset), and have
> broken bus reset.
>
> The problem manifests in VFIO passthrough scenarios:
>
> - WCN6855 WiFi card (17cb:1103): Normal VM operation works fine, including
> clean shutdown/reboot. However, when the VM terminates uncleanly
> (crash, force-off), VFIO attempts to reset the device before it can
> be assigned to another VM. Without a working reset method, the device
> remains in an undefined state, preventing reuse.
>
> - WCN7850 WiFi card (17cb:1107): Same behavior as WCN6855.
>
> - SDX62/SDX65 5G modems (17cb:0308): Never successfully initialize even
> on first VM assignment without proper reset capability.
>
> Add device-specific reset entries for these Qualcomm devices using D3cold
> power cycling with automatic D3hot fallback. The implementation uses
> pci_set_power_state(D3cold) which automatically falls back to D3hot on
> platforms without ACPI _PR3 power resources. While not a complete reset
> (BARs preserved), testing shows D3hot transition provides sufficient reset
> for VFIO reuse.
>
> Extract a shared pci_dev_d3cold_d0_cycle() helper function to avoid code
> duplication between pci_d3cold_reset() (strict _PR3 requirement) and the
> new reset_d3cold_d3hot() device-specific reset (automatic fallback).
> The helper performs only the power cycle; IOMMU handling is done by the
> caller (pci_d3cold_reset() for general method, __pci_dev_specific_reset()
> wrapper for device-specific methods).
>
> Device-specific reset is position #1 in the reset hierarchy, so these
> Qualcomm devices will use power cycling as their primary reset method,
> with the general d3cold method (position #8) available as a fallback on
> _PR3-capable platforms if users override via sysfs.
>
> Signed-off-by: Jose Ignacio Tornos Martinez <jtornosm@redhat.com>
> ---
> v8: Fix commit message: correct IOMMU handling description. The helper
> performs only the power cycle; IOMMU is handled by callers (this was
> v6 fix)
> v7: https://lore.kernel.org/all/20260603105853.326290-3-jtornosm@redhat.com/
>
> drivers/pci/pci.c | 37 +++++++++++++++++++++++++++----------
> drivers/pci/pci.h | 1 +
> drivers/pci/quirks.c | 19 +++++++++++++++++++
> 3 files changed, 47 insertions(+), 10 deletions(-)
>
> diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
> index 096868f80cd4..f7a7443287fd 100644
> --- a/drivers/pci/pci.c
> +++ b/drivers/pci/pci.c
> @@ -4491,6 +4491,32 @@ static int pci_pm_reset(struct pci_dev *dev, bool probe)
> return ret;
> }
>
> +/**
> + * pci_dev_d3cold_d0_cycle - Perform D3cold->D0 power cycle
> + * @dev: Device to power cycle
> + *
> + * Common helper to perform D3cold->D0 power cycle for reset methods.
> + * Attempts D3cold transition with automatic fallback to D3hot on platforms
> + * without ACPI _PR3 power resources.
> + *
> + * Caller must handle IOMMU preparation/cleanup if needed.
> + *
> + * Returns 0 on success, negative error code on failure.
> + */
> +int pci_dev_d3cold_d0_cycle(struct pci_dev *dev)
> +{
> + int ret;
> +
> + if (dev->current_state != PCI_D0)
> + return -EINVAL;
> +
> + ret = pci_set_power_state(dev, PCI_D3cold);
> + if (ret)
> + return ret;
> +
> + return pci_set_power_state(dev, PCI_D0);
> +}
> +
> /**
> * pci_d3cold_reset - Put device into D3cold and back to D0 for reset
> * @dev: PCI device to reset
> @@ -4520,22 +4546,13 @@ static int pci_d3cold_reset(struct pci_dev *dev, bool probe)
> if (probe)
> return 0;
>
> - if (dev->current_state != PCI_D0)
> - return -EINVAL;
> -
> ret = pci_dev_reset_iommu_prepare(dev);
> if (ret) {
> pci_err(dev, "failed to stop IOMMU for a PCI reset: %d\n", ret);
> return ret;
> }
>
> - ret = pci_set_power_state(dev, PCI_D3cold);
> - if (ret)
> - goto done;
> -
> - ret = pci_set_power_state(dev, PCI_D0);
> -
> -done:
> + ret = pci_dev_d3cold_d0_cycle(dev);
> pci_dev_reset_iommu_done(dev);
> return ret;
> }
> diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
> index 4a14f88e543a..a9942787de9e 100644
> --- a/drivers/pci/pci.h
> +++ b/drivers/pci/pci.h
> @@ -234,6 +234,7 @@ void pci_init_reset_methods(struct pci_dev *dev);
> int pci_bridge_secondary_bus_reset(struct pci_dev *dev);
> int pci_bus_error_reset(struct pci_dev *dev);
> int pci_try_reset_bridge(struct pci_dev *bridge);
> +int pci_dev_d3cold_d0_cycle(struct pci_dev *dev);
>
> struct pci_cap_saved_data {
> u16 cap_nr;
> diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
> index e49136ac5dbf..70f3b0f26799 100644
> --- a/drivers/pci/quirks.c
> +++ b/drivers/pci/quirks.c
> @@ -4237,6 +4237,22 @@ static int reset_hinic_vf_dev(struct pci_dev *pdev, bool probe)
> return 0;
> }
>
> +/*
> + * Device-specific reset method via D3cold/D3hot power cycle.
> + *
> + * Some devices lack working FLR, advertise NoSoftRst+ (blocking PM reset),
> + * and have broken bus reset. This function provides device-specific reset via
> + * power cycling, attempting D3cold with automatic fallback to D3hot on platforms
> + * without ACPI _PR3 power resources.
> + */
My only complaint is that this is positioned a bit generically. If the
reset only achieves D3hot on a device that reports NoSoftRst+, then
this appears as a no-op reset method. The claim here is instead that
despite reporting NoSoftRst+, the devices using this reset have notably
improved behavior, especially across unexpected resets in device
assignment scenarios. This leads us to believe that some degree of
reset is achieved, for devices that otherwise have no viable
alternative reset method.
Also, I know from previous discussions that much of the testing was
done with M.2 adapters in slots without _PR3 support, which exercises
the D3hot fallback rather than an actual D3cold power cycle. Has each
of these devices been tested on a platform where D3cold is actually
achieved through this method? Thanks,
Alex
> +static int reset_d3cold_d3hot(struct pci_dev *dev, bool probe)
> +{
> + if (probe)
> + return 0;
> +
> + return pci_dev_d3cold_d0_cycle(dev);
> +}
> +
> static const struct pci_dev_reset_methods pci_dev_reset_methods[] = {
> { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82599_SFP_VF,
> reset_intel_82599_sfp_virtfn },
> @@ -4252,6 +4268,9 @@ static const struct pci_dev_reset_methods pci_dev_reset_methods[] = {
> reset_chelsio_generic_dev },
> { PCI_VENDOR_ID_HUAWEI, PCI_DEVICE_ID_HINIC_VF,
> reset_hinic_vf_dev },
> + { PCI_VENDOR_ID_QCOM, 0x1103, reset_d3cold_d3hot }, /* WCN6855 */
> + { PCI_VENDOR_ID_QCOM, 0x1107, reset_d3cold_d3hot }, /* WCN7850 */
> + { PCI_VENDOR_ID_QCOM, 0x0308, reset_d3cold_d3hot }, /* SDX62/SDX65 */
> { 0 }
> };
>
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2026-06-09 17:53 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-09 16:36 [PATCH v8 0/3] PCI: Add d3cold and device-specific reset for Qualcomm devices Jose Ignacio Tornos Martinez
2026-06-09 16:36 ` [PATCH v8 1/3] PCI: Add d3cold as general reset method Jose Ignacio Tornos Martinez
2026-06-09 16:56 ` sashiko-bot
2026-06-09 16:36 ` [PATCH v8 2/3] PCI: Add device-specific reset for Qualcomm devices Jose Ignacio Tornos Martinez
2026-06-09 17:11 ` sashiko-bot
2026-06-09 17:53 ` Alex Williamson
2026-06-09 16:36 ` [PATCH v8 3/3] PCI: Disable broken bus reset on " Jose Ignacio Tornos Martinez
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.