[PATCH 1/2] wifi: ath12k: skip PCIe global reset on initial power-up
Nazar Mokrynskyi
nazar at mokrynskyi.com
Sun Jul 12 20:34:36 PDT 2026
The patches I sent only allow VM to start once.
Any attempt to shutdown or reboot the VM results in host crashing instantly due to PCIe errors.
The only way to somewhat gracefully reboot the host that I found is to unbind corresponding host bridge first (so it doesn't propagate PCIe error), then kill the VM (instead of attempting to shut down gracefully) and then reboot the host.
This is not great, but still much better than not being able to use the hardware at all. These cards were paperweight for me for far too long.
I've been running a system with these patches for probably close to 3 months now and have not found other issues except performance is not that great.
I sent a suggestion to allow ignoring PCIe errors in vfio so it doesn't crash the host here: https://lore.kernel.org/kvm/70de9b8f-b7c7-481b-8cb1-931e3b82eb0e@mokrynskyi.com/
But maintainers weren't too happy about it.
While searching for that thread I found this recent development, which looks related to the issues I'm having: https://lkml.org/lkml/2026/6/30/398
Sincerely, Nazar Mokrynskyi
github.com/nazar-pc
13.07.26 06:03, Baochen Qiang:
>
> On 5/6/2026 1:24 AM, Nazar Mokrynskyi wrote:
>> ath12k_pci_sw_reset() unconditionally calls ath12k_pci_soc_global_reset()
>> regardless of whether the device is being powered up for the first time or
>> recovering from a previous run. The global reset drops the PCIe link and
>> relies on the host root complex to perform physical link retraining before
>> the MHI BHI register can be accessed.
>>
>> When the device is passed through to a VM via VFIO, no physical link
>> retraining occurs after the reset since QEMU's virtual PCIe bridge does
>> not implement hardware LTSSM negotiation. As a result, all subsequent
>> MMIO reads return 0xffffffff and MHI initialization fails with -EREMOTEIO.
>>
>> On initial power-up, vfio-pci has already performed a Function Level
>> Reset before handing the device to the guest driver, placing it in a
>> known clean state equivalent to what the global reset achieves. The global
> AFAIK this is not the fact. Some internal registers are not cleanly reset without a global
> reset.
>
>> reset is therefore redundant on power-up and only necessary on the
>> shutdown/recovery path where it tears down an already-running firmware.
> is ath12k recovery working in Qemu in your setup? I doubt it since recovery would also hit
> the link retraining issue ? Also how about the rmmod / insmod sequence in Qemu, since
> rmmod also triggers global reset ?
>
> To me this is more like a Qemu/vfio issue than a driver issue. The QEMU's behavior that
> virtual PCIe bridge does not implement hardware LTSSM negotiation basically breaks all
> hardware requiring runtime PCIe link retraining. Not sure why it is designed like this. If
> it can not be fixed/changed in Qemu, can we do it in the host vfio?
>
>> Skip ath12k_pci_soc_global_reset() when power_on is true to allow MHI
>> initialization to succeed under VFIO passthrough without affecting bare
>> metal behavior.
>>
>> Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.6-01243-QCAHKSWPL_SILICONZ-1
>>
>> Signed-off-by: Nazar Mokrynskyi <nazar at mokrynskyi.com>
>> ---
>> drivers/net/wireless/ath/ath12k/pci.c | 3 ++-
>> 1 file changed, 2 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/net/wireless/ath/ath12k/pci.c b/drivers/net/wireless/ath/ath12k/pci.c
>> index 375277ca2..a3d7aeb72 100644
>> --- a/drivers/net/wireless/ath/ath12k/pci.c
>> +++ b/drivers/net/wireless/ath/ath12k/pci.c
>> @@ -303,7 +303,8 @@ static void ath12k_pci_sw_reset(struct ath12k_base *ab, bool power_on)
>>
>> ath12k_mhi_clear_vector(ab);
>> ath12k_pci_clear_dbg_registers(ab);
>> - ath12k_pci_soc_global_reset(ab);
>> + if (!power_on)
>> + ath12k_pci_soc_global_reset(ab);
>> ath12k_mhi_set_mhictrl_reset(ab);
>> }
>>
More information about the ath12k
mailing list