Re: [PATCH v10] Add device-specific reset for Qualcomm devices
Baochen Qiang <[email protected]> Mon, 29 Jun 2026 17:44:35 +0800
| Newsgroups | dev.linux.lists.mhi,org.infradead.lists.ath11k,org.infradead.lists.ath12k,org.kernel.vger.linux-kernel,org.kernel.vger.linux-pci,org.kernel.vger.linux-wireless |
|---|---|
| Message-ID | <[email protected]> |
On 6/25/2026 9:03 PM, Manivannan Sadhasivam wrote: > On Wed, Jun 24, 2026 at 03:47:12PM +0800, Baochen Qiang wrote: >> >> >> On 6/24/2026 2:31 AM, Jose Ignacio Tornos Martinez 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 (17cb:1103) and WCN7850 (17cb:1107) WiFi devices: >>> 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. >>> >>> - SDX62/SDX65 (17cb:0308) 5G modems: Never successfully initialize even >>> on first VM assignment without proper reset capability. >>> >>> Add device-specific reset methods using BAR-space hardware reset registers >>> that exist in these devices: >>> >>> - WCN6855/WCN7850 WiFi devices use SoC global reset via BAR0 (sequence from >>> ath11k/ath12k driver: ath11k_pci_soc_global_reset(), ath11k_pci_sw_reset(), >>> ath11k_mhi_set_mhictrl_reset()): >>> - Write/clear reset bit at offset 0x3008 >>> - Wait for PCIe link recovery (up to 5 seconds) >>> - Clear MHI controller SYSERR status at offset 0x38 >>> >>> - SDX62/SDX65 modem devices use MHI SoC reset via BAR0 (sequence from MHI >>> driver: mhi_soc_reset(), mhi_pci_reset_prepare()): >>> - Write reset request to offset 0xb0 >>> - Wait 2 seconds for reset completion >>> >>> These are true hardware reset mechanisms (not power management or firmware >>> error recovery), providing proper device reset for VFIO scenarios. >>> >>> Testing was performed on desktop platforms with M.2 WiFi and modem cards >>> using M.2-to-PCIe adapters, including extensive force-reset cycling to >>> verify stability. >>> >>> Signed-off-by: Jose Ignacio Tornos Martinez <[email protected]> >>> --- >>> v10: >>> - Complete redesign based on maintainer feedback (Manivannan Sadhasivam, >>> Alex Williamson): use actual hardware reset registers from >>> device drivers instead of D3hot power cycling >>> v9: https://lore.kernel.org/all/[email protected]/ >>> >>> drivers/pci/quirks.c | 118 +++++++++++++++++++++++++++++++++++++++++++ >>> 1 file changed, 118 insertions(+) >>> >>> diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c >>> index 431c021d7414..8ad3f214e520 100644 >>> --- a/drivers/pci/quirks.c >>> +++ b/drivers/pci/quirks.c >>> @@ -4240,6 +4240,121 @@ static int reset_hinic_vf_dev(struct pci_dev *pdev, bool probe) >>> return 0; >>> } >>> >>> +#define QUALCOMM_WIFI_PCIE_SOC_GLOBAL_RESET 0x3008 >>> +#define QUALCOMM_WIFI_PCIE_SOC_GLOBAL_RESET_V BIT(0) >>> +#define QUALCOMM_WIFI_MHISTATUS 0x48 >>> +#define QUALCOMM_WIFI_MHICTRL 0x38 >>> +#define QUALCOMM_WIFI_MHICTRL_RESET_MASK 0x2 >>> + >>> +/* >>> + * Qualcomm WiFi device-specific reset using SoC global reset via BAR0 >>> + * registers. >>> + */ >>> +static int reset_qualcomm_wifi(struct pci_dev *pdev, bool probe) >>> +{ >>> + bool link_recovered = false; >>> + unsigned long timeout; >>> + void __iomem *bar; >>> + u32 val; >>> + u16 cmd; >>> + >>> + if (probe) >>> + return 0; >>> + >>> + if (pdev->current_state != PCI_D0) >>> + return -EINVAL; >>> + >>> + pci_read_config_word(pdev, PCI_COMMAND, &cmd); >>> + pci_write_config_word(pdev, PCI_COMMAND, cmd | PCI_COMMAND_MEMORY); >>> + >>> + bar = pci_iomap(pdev, 0, 0); >>> + if (!bar) { >>> + pci_write_config_word(pdev, PCI_COMMAND, cmd); >>> + return -ENODEV; >>> + } >>> + >>> + val = ioread32(bar + QUALCOMM_WIFI_PCIE_SOC_GLOBAL_RESET); >> >> QUALCOMM_WIFI_PCIE_SOC_GLOBAL_RESET is beyond the first 4K bar area hence requires MHI >> wakeup before accessing, see [1]. the wakeup callback for WCN6855 is >> ath11k_pci_bus_wake_up() which calls mhi_device_get_sync(). Not sure how this can be done >> here. Maybe Mani can provide some hints? >> > > I don't think the device needs to be waken up before > QUALCOMM_WIFI_PCIE_SOC_GLOBAL_RESET. ath11k driver wakes up the device for > accessing the MHI interface I believe. Since this callback is not touching MHI, > there is no need to wakeup the device, AFAIK. MHI register space is constitute with 3 segments, with mhi offset always being 0, bhi offset 0x100 and bhie offset 0x224 (the latter two offsets are for WCN7850, but I think also apply to other devices). That said the whole MHI register space does not go beyond the first 4K region, hence wakeup is not for accessing MHI interface. > > - Mani >