feat: fast Intel BT firmware download (bulk-pipelined payload, no timeout burns)
Two fixes, verified on the AX211 (8087:0033), ibt-1040-0041.sfi, 720 KB: 1. TryHeader waited 1500+2000 ms for secure-send results after the CSS and key/signature sends, but on success this controller stays SILENT until the end of the whole download (traced) -- both timeouts always burned in full. A rejection arrives within milliseconds, so 250 ms windows lose nothing and save ~3 s per cold boot. 2. The payload now goes over the bulk OUT endpoint with up to 7 fragments in flight (the btusb bootloader path for 0xFC09), replacing ~2900 synchronous 3-stage EP0 control transfers. Headers stay on EP0; the ACL TX DMA ring is reused (no ACL header, no NOCP credit accounting). DrainBulkTx() ensures all bytes reach the controller before waiting for the download-complete result. Also in this branch since main: IRQ-safe BT-TRACE ring (KernelLogStream in TransferCallback deadlocked on the terminal Mutex from MSI context), xHCI interrupt-IN ZLP length fix, always-re-arm of the BT event pipe, InPollContext same-core owner check, TLV version read retry. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
dc89495011
commit
72f6c4449c
4 files changed
+95
-5
No files matched your search
@@ -153,20 +153,25 @@ namespace Drivers::USB::Bluetooth {
|
||||
uint8_t result = 0, status = 0;
|
||||
|
||||
// 1. CSS header init -- check the result before committing key/sig.
|
||||
// A rejection event arrives within milliseconds; on SUCCESS the
|
||||
// controller stays silent until the END of the whole download (traced
|
||||
// on the AX211), so a long timeout here only burns boot time.
|
||||
Hci::ClearSecureSendResult();
|
||||
if (!Hci::IntelSecureSend(0x00, fw + cssOff, 128)) return false;
|
||||
if (Hci::WaitSecureSendResult(1500, &result, &status) && (result || status)) {
|
||||
if (Hci::WaitSecureSendResult(250, &result, &status) && (result || status)) {
|
||||
KernelLogStream(WARNING, "BT-FW") << name << " CSS rejected (result="
|
||||
<< base::hex << (uint64_t)result << " status=" << (uint64_t)status
|
||||
<< base::dec << ")";
|
||||
return false;
|
||||
}
|
||||
|
||||
// 2. Public key + signature.
|
||||
// 2. Public key + signature. Same rule: silence means accepted; a
|
||||
// rejected header also fails the payload phase immediately, so the
|
||||
// short window loses nothing.
|
||||
Hci::ClearSecureSendResult();
|
||||
if (!Hci::IntelSecureSend(0x03, fw + pkeyOff, pkeyLen)) return false;
|
||||
if (!Hci::IntelSecureSend(0x02, fw + sigOff, sigLen)) return false;
|
||||
if (Hci::WaitSecureSendResult(2000, &result, &status) && (result || status)) {
|
||||
if (Hci::WaitSecureSendResult(250, &result, &status) && (result || status)) {
|
||||
KernelLogStream(WARNING, "BT-FW") << name << " header rejected (result="
|
||||
<< base::hex << (uint64_t)result << " status=" << (uint64_t)status
|
||||
<< base::dec << ")";
|
||||
@@ -203,7 +208,10 @@ namespace Drivers::USB::Bluetooth {
|
||||
}
|
||||
|
||||
if ((fragLen % 4) == 0) {
|
||||
if (!Hci::IntelSecureSend(0x01, fw + fwPtr, fragLen)) {
|
||||
// Payload goes over the bulk endpoint, pipelined (the btusb
|
||||
// bootloader path) -- EP0's synchronous 3-stage transfers made
|
||||
// the 720 KB image the dominant boot cost.
|
||||
if (!Hci::IntelSecureSendBulk(0x01, fw + fwPtr, fragLen)) {
|
||||
KernelLogStream(ERROR, "BT-FW") << "Payload secure-send failed at offset "
|
||||
<< fwPtr;
|
||||
return false;
|
||||
@@ -233,6 +241,14 @@ namespace Drivers::USB::Bluetooth {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The bulk pipeline may still hold up to 7 in-flight fragments; make
|
||||
// sure every byte reached the controller before the caller waits for
|
||||
// the download-complete result.
|
||||
if (!Hci::DrainBulkTx(3000)) {
|
||||
KernelLogStream(ERROR, "BT-FW") << "Bulk TX drain timed out at end of payload";
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user