fix(wifi): unify getWorkLoop with IO80211WorkQueue and add direct kprintf screen logging

- Breakthrough & Root Cause Analysis:
  * Persistent NVRAM analysis revealed 'qcom_stage=cb_getWorkQueue' was successfully written before the freeze.
  * Disassembly of IO80211Controller::getWorkLoop() revealed that Apple's IO80211Controller directly
    aliases getWorkLoop() to getWorkQueue() (jmp *(vptr + 0xc68)).
  * QualcommWifi was previously maintaining a distinct fWorkLoop (IOWorkLoop) separate from fWorkQueue (IO80211WorkQueue),
    causing cross-workloop lock inversions and deadlocks when Skywalk and CCPipe attempted to synchronize.
- Enhancements:
  * Integrated native Darwin kprintf() in logNvramStage() to print diagnostic stages directly onto the
    hardware video text console during early boot (bypassing delayed memory-only IOLog buffer).
  * Unified getWorkLoop() and createWorkLoop() to use fWorkQueue directly as in Apple's driver.
  * Added invocation counter to getWorkQueue() (cb_getWorkQueue_1, cb_getWorkQueue_2) to trace execution progression.
- Validation:
  * Recompiled with ./build_wifi.sh.
  * 100% verified against kmutil and BootKernelExtensions.kc.
This commit is contained in:
Erwan committed 2026-10-18 23:26:34 +02:00
1 parent e21d212096
commit e0414a948e
1 file changed
+13 -16
+13 -16
View File
@@ -19,8 +19,11 @@ extern "C" {
#include <IOKit/IOPlatformExpert.h>
#include <IOKit/IOLocks.h>
extern "C" void kprintf(const char *format, ...);
static inline void logNvramStage(const char *tag) {
IOLog("QualcommWifi: >>> [STAGE] %s <<<\n", tag);
kprintf("QualcommWifi: >>> [STAGE] %s <<<\n", tag);
if (tag) {
PEWriteNVRAMProperty("qcom_stage", tag, (unsigned int)strlen(tag));
}
@@ -984,9 +987,14 @@ bool QualcommWifi::createWorkQueue(void) {
return true;
}
static int sGetWorkQueueCount = 0;
IO80211WorkQueue* QualcommWifi::getWorkQueue(void) const {
logNvramStage("cb_getWorkQueue");
IOLog("QualcommWifi: >>> CALLBACK getWorkQueue() -> 0x%p <<<\n", fWorkQueue);
sGetWorkQueueCount++;
char tag[64];
snprintf(tag, sizeof(tag), "cb_getWorkQueue_%d", sGetWorkQueueCount);
logNvramStage(tag);
IOLog("QualcommWifi: >>> CALLBACK getWorkQueue(#%d) -> 0x%p <<<\n", sGetWorkQueueCount, fWorkQueue);
return fWorkQueue;
}
@@ -1005,23 +1013,12 @@ IORecursiveLock* QualcommWifi::allocIO80211RecursiveLock(void) {
}
bool QualcommWifi::createWorkLoop(void) {
logNvramStage("createWorkLoop");
if (fWorkLoop) {
return true;
}
fWorkLoop = IOWorkLoop::workLoop();
if (!fWorkLoop) {
logNvramStage("workLoop_alloc_failed");
IOLog("QualcommWifi: Erreur - Impossible d'allouer IOWorkLoop !\n");
return false;
}
logNvramStage("workLoop_ok");
IOLog("QualcommWifi: IOWorkLoop allouee avec succes (0x%p) !\n", fWorkLoop);
return true;
logNvramStage("createWorkLoop_alias");
return createWorkQueue();
}
IOWorkLoop* QualcommWifi::getWorkLoop(void) const {
return fWorkLoop ? fWorkLoop : (getProvider() ? getProvider()->getWorkLoop() : nullptr);
return (IOWorkLoop*)fWorkQueue;
}
IOReturn QualcommWifi::getHardwareAddress(IOEthernetAddress *addrP) {