feat: fully async Intel BT firmware bring-up + HCI multi-packet event reassembly

The BT firmware download now runs from the idle loop after boot (zero boot
stall), completing the async goal.  What made every earlier deferral attempt
fail was a months-latent HCI-layer bug, not the deferred environment:

  WaitCommandComplete returned after the FIRST USB packet of an event, but
  events larger than the 64-byte interrupt max-packet (like the AX211's
  96-byte FC05 TLV version response) span several packets.  Sending the next
  command while the tail of the previous response was still in flight wedges
  the AX211 bootloader into permanently ignoring commands.  Boot-time flanterm
  rendering added milliseconds between commands and accidentally paced the
  protocol past the race -- which is why the synchronous bring-up always
  worked and every log-suppressed (deferred) bring-up went mute at FC05 #2,
  regardless of scheduling/MSI/xHCI fixes.

  Fix: reassemble multi-packet Command Complete/Status events in the
  transfer callback; the mailbox is marked ready only when the declared
  event length has fully arrived.  This inherently paces command flow and,
  as a bonus, the TLV version read now sees the full response (sbe_type
  present -> ECDSA/RSA selection is no longer a guess).

Also: per-slot EP0 completion tracking in the xHCI (a waiting ControlTransfer
can no longer be released early by another device's EP0 completion).

Verified on the AX211: instant boot, background download, real BD_ADDR.

Co-Authored-By: Claude Fable 5 <[email protected]>
This commit is contained in:
2026-07-07 12:31:30 +02:00
co-authored by Claude Fable 5
parent 72f6c4449c
commit 77940cf896
4 changed files with 74 additions and 23 deletions
+13 -11
View File
@@ -186,17 +186,12 @@ extern "C" void kmain() {
Fs::InitializeBootFilesystems(boot.modules);
// A Bluetooth adapter present at boot enumerates during the xHCI port scan,
// before the ramdisk is mounted. Now that drive 0 is up, finish any
// firmware-dependent bring-up that was deferred (loads ibt-*.sfi/.ddc).
//
// Deliberately synchronous, HERE, pre-Sched/pre-SMP/pre-MSI: deferring
// this to the post-boot idle loop made the AX211 bootloader stop
// answering after the first FC05 (2026-07-05, three attempts: CPU
// reservation, restored pipe timing, event-pipe fixes -- identical
// failure each time; suspected xHCI-MSI-context event processing, see
// memory notes). Boot pays the download cost until that is understood.
Drivers::USB::Bluetooth::ServiceDeferredInit();
// EXPERIMENT (wip/bt-deferred-init): the Bluetooth firmware bring-up is
// NOT run here -- the idle loop picks it up via ServiceDeferredInit()
// after boot, with CPU reservation, the IRQ-safe trace ring, and the
// bulk-pipelined download. Earlier deferral attempts (2026-07-05) made
// the AX211 stop answering after the first FC05; this run captures a
// ring trace of exactly what the event pipe delivers in deferred mode.
Hal::LoadTSS();
montauk::abi::InitializeSyscalls();
@@ -207,6 +202,13 @@ extern "C" void kmain() {
// Boot Application Processors (all subsystems ready, APs can schedule)
Smp::BootAPs(boot.smp);
// The Bluetooth firmware bring-up is deferred to the idle loop
// (ServiceDeferredInit from IdleOnce) so its download never stalls boot.
// Requires the HCI multi-packet event reassembly in Hci.cpp: without it,
// the next command races the tail of a multi-packet response and wedges
// the AX211 bootloader -- which only ever worked before because boot-time
// flanterm rendering accidentally paced the commands.
// Flush any stale PS/2 mouse bytes that accumulated during boot
// (edge-triggered IRQs can be lost while spinlocks disable interrupts)
Drivers::PS2::Mouse::FlushState();