wip: async BT firmware download attempt — DO NOT MERGE, breaks AX211 bring-up

Deferring the Intel BT firmware download off the boot path made the AX211
bootloader stop answering after the first FC05; even the final synchronous
revert freezes boot, so one of the 'neutral' fixes kept in this diff breaks
the bring-up on its own (candidates: BT-TRACE logging inside TransferCallback,
unconditional interrupt-IN re-queue after error completions on a halted EP,
xHCI interrupt-IN ZLP len fix interacting with HID, InPollContext owner
check).  Full history + next experiments in memory notes, 2026-07-05/06.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
danielandClaude Fable 5 committed 2026-07-06 15:46:06 +02:00
1 parent 6a5eafb4fc
commit 8bf3ceb457
9 files changed
+163 -31

No files matched your search

+18 -4
View File
@@ -428,7 +428,13 @@ namespace Drivers::USB::Xhci {
// sent from a Bluetooth event handler). Such callers must fire-and-forget,
// not wait, since a nested PollEvents is a no-op.
bool InPollContext() {
return g_pollActive.load(std::memory_order_relaxed);
// Same-core only: "nested under PollEvents" means an event callback on
// THIS core issued the query. A different core merely polling must
// not make callers (WaitCommandComplete & co.) skip their wait -- that
// reported success before the reply arrived (same cross-core bug
// ControlTransfer's trueNested check already guards against).
return g_pollActive.load(std::memory_order_relaxed) &&
g_pollOwnerCpu.load(std::memory_order_relaxed) == CurrentCpuIndex();
}
// -------------------------------------------------------------------------
@@ -568,9 +574,17 @@ namespace Drivers::USB::Xhci {
g_transferCallbacks[slotId](slotId, epDci,
nullptr, 0, completionCode);
} else if (epDci == intDci) {
// Interrupt IN — HID or callback dispatch
uint16_t len = dev.InterruptMaxPacket;
if (residual < len) len = dev.InterruptMaxPacket - (uint16_t)residual;
// Interrupt IN — HID or callback dispatch.
// len = actually-transferred bytes. A ZLP has
// residual == requested, so len MUST be 0 (same
// fix as bulk IN above): the old code left len at
// the full max-packet and handed the callback a
// slice of STALE DMA buffer -- for Bluetooth that
// can replay the PREVIOUS HCI event into the
// command-complete mailbox.
uint16_t reqLen = dev.InterruptMaxPacket;
uint16_t len = (residual < reqLen)
? (uint16_t)(reqLen - residual) : 0;
if (dev.InterfaceClass == UsbDevice::CLASS_HID) {
if (dev.InterfaceProtocol == UsbDevice::PROTOCOL_KEYBOARD) {