Re: [PATCH v2] Bluetooth: btusb: Allow firmware re-download when version matches
From: Shuai Zhang
Date: Thu May 14 2026 - 22:42:07 EST
Hi Makro,
Thanks for the detailed analysis.
On 5/14/2026 10:44 AM, makro-kernel wrote:
Hi Shuai, Luiz,
I sent a patch earlier today touching the same function for a related
but distinct failure mode in the same family of chips, and only just
saw this thread.
https://lore.kernel.org/linux-bluetooth/aD_Lix2EVXOHmbZ4L1CunlWiLqfiKlU_1_FcVh4CBuIgud4kmE_544xjW2zFKsmh4pNAo9yIQ7q8_GZ4YcmgAXPp8LgW9rfWKqnu06WSjgk=@proton.me/T/#u
In my case the *outer* check fails first: on Foxconn USB 0489:e10a
(Qualcomm WCN6855/WCN785x, ROM 0x00190200) the chip reports
QCA_CHECK_STATUS = 0xe0 (PATCH_UPDATED | SYSCFG_UPDATED) on every
probe, so btusb_setup_qca() never reaches load_rampatch() or
load_nvm(), returns 0, and the controller runs unpatched firmware.
AVDTP setup later fails on Acquire and A2DP audio cannot stream. The
PATCH_UPDATED bit appears to persist across cold boots somewhere on
chip -- originally set by Windows on dual-boot-then-Linux systems
we've seen, but the bit sticks even after a successful Linux firmware
upload, so subsequent boots also see 0xe0 and skip.
The rampatch itself also persists on this silicon at least across
suspend/hibernate resume cycles and driver reload (whether it
survives a true cold boot I haven't isolated). Either way, once an
upload has succeeded the chip reports patch_version equal to the
file's version on subsequent probes, which is exactly the condition
your patch addresses. With my outer bypass in place but without your
inner change, the second and subsequent probes hit the existing
`rver_patch <= ver_patch` check, return -EINVAL, and controller
setup aborts entirely:
Bluetooth: hci0: using rampatch file: qca/rampatch_usb_00190200.bin
Bluetooth: hci0: QCA: patch rome 0x190200 build 0x8567, firmware rome 0x190200 build 0x8567
Bluetooth: hci0: rampatch file version did not match with firmware
(btusb_setup_qca returns -EINVAL, hci0 never finishes registering)
So your fix is doing the right thing here, and on this hardware both
sides are needed together for the chip to come up cleanly across
reload / reboot cycles.
In my local tree I skip reuploading on equal versions rather than
re-uploading on every probe:
if (rver_rom != ver_rom) {
bt_dev_err(hdev, "rampatch file ROM did not match controller");
err = -EINVAL;
goto done;
}
if (rver_patch <= ver_patch) {
bt_dev_info(hdev, "QCA: rampatch already current, skipping download");
err = 0;
goto done;
}
err = btusb_setup_qca_download_fw(hdev, fw, info->rampatch_hdr);
I tested on another device with the same ROM version (0x00190200) but
a different USB ID (0cf3:e700). After a cold reboot the chip reports
firmware build 0x43fb (ROM state), meaning firmware is reset on power
cycle and QCA_CHECK_STATUS does not return 0xe0. The rampatch download
proceeds normally every boot without any bypass.
This suggests the NVM-persistent status bit behavior you described is
specific to certain vendor configurations (e.g. Foxconn 0489:e10a)
rather than a property of the ROM version itself.
Given that, I wonder if removing the QCA_CHECK_STATUS guard
unconditionally for all QCA USB chips is the right approach. For chips
that reset firmware on cold boot, the unconditional re-upload adds
unnecessary overhead on every probe. A device-specific quirk flag
(keyed on USB ID) might be a more targeted fix, leaving the existing
optimization intact for chips that don't exhibit the NVM persistence
issue.
My inner patch (changing <= to <) addresses the USB disconnect
recovery case and is independent of the chip's NVM behavior, so it
should apply broadly regardless of how the outer check is handled.
Please correct me if I have misunderstood anything.
Hi Luiz, could you take a look at my patch when you get a chance?
https://lore.kernel.org/linux-bluetooth/8f5362ca-5513-4d9a-8922-6603783c9ae7@xxxxxxxxxxxxxxxx
Best,
Makro
Thanks,
Shuai