This page is the handoff checklist for the current port state. It exists so the next hardware session starts from known facts instead of rediscovering them from terminal scrollback.
Current known state
That leaves one immediate hypothesis: the SDIO card interrupt is armed in
CCCR and unmasked in DWMMC, but the card clock is being low-power gated while
the bus is idle. The next code patch is 5c4b836 Keep DWMMC clock running for SDIO IRQ , which clears
DWMMC CLKENA_LP while SDIO IRQ mode is enabled and records the resulting
clock state in the passive sdio_state sysctl.
Next hardware session
Do not start with a transfer. First prove the new kernel boots and that the WiFi module can attach without making WiFi persistent.
mise run patch
mise run build-kernel
mise run build-module -- bwfm_sdio
mise run kernel:deploy:phone
mise run module:deploy:phone -- bwfm_sdio
ssh pinephone 'sudo sysrc bwfm_sdio_enable=NO'
ssh pinephone 'sudo reboot' || true After USB networking returns:
ssh pinephone '
uname -a
sha256 -q /boot/kernel/kernel
sha256 -q /boot/kernel/bwfm_sdio.ko
sysrc -n bwfm_sdio_enable
kldstat -v | egrep "bwfm|sdiob|dwmmc" || true
' Expected: new kernel hash, new module hash, bwfm_sdio_enable=NO, and no
loaded bwfm_sdio module.
WiFi IRQ test
Start serial capture before loading WiFi. The serial log is the durable record if the phone panics before USB SSH returns.
mise run serial:capture:daemon -- wifi-sdio-irq
timeout 45 ssh pinephone '
date
sudo service bwfm_sdio onestart
date
sysctl debug.bwfm_state 2>&1 || true
for oid in $(sysctl -aN | awk "/dev\\.rockchip_dwmmc\\.[0-9]+\\.sdio_state|dev\\.sdiob\\.[0-9]+\\.irq_state/"); do
sysctl "$oid"
done
ifconfig wlan0 2>/dev/null || true
' Expected after 5c4b836 Keep DWMMC clock running for SDIO IRQ :
dev.sdiob.0.irq_statestill shows function 1 claimed and CCCR interrupt enable moving to0x03.- The active
rockchip_dwmmcinstance showsintmaskwith SDIO unmasked. - The same instance shows
clkenawith card clock enabled and low-power mode cleared. clk_error=0.
If attach fails or the phone panics here, stop. Do not run a transfer. Use the
serial log plus kernel.prev recovery.
Transfer matrix
Only run transfers after the attach state is clean.
ssh pinephone 'sudo service netif start wlan0; ifconfig wlan0'
SIZE_MIB=2 \
POLL_SECS=5 \
DEBUG_TIMEOUT=5 \
TRANSFER_TIMEOUT=120 \
DUMP_TRACE=0 \
mise run debug:wifi:transfer -- both sdio-irq-clock-fix-small # Defaults: MATRIX_RATES="100 50 20 10", MATRIX_SIZE_MIBS="2 8".
# The script restores dev.bwfm_sdio.0.poll_fallback_hz when it finishes.
POLL_SECS=5 \
DEBUG_TIMEOUT=5 \
TRANSFER_TIMEOUT=120 \
DUMP_TRACE=0 \
mise run debug:wifi:fallback-matrix -- both poll-fallback The transfer harness now emits the same WiFi receipt block before,
during, and after each leg: debug.bwfm_state, debug.bwfm_fw_state,
DWMMC sdio_state and sdio_intrs, sdiob irq_state, the
bwfm_sdio power-save/fallback-rate sysctls, ifconfig, and
netstat -I wlan0 -b.
mise run debug:wifi:phone -- <name> emits the same block for one-shot
state captures. Both scripts now append mise run debug:wifi:analyze output
to the log so the first screen of the receipt says whether this was
irq-active-watchdog, irq-armed-poll-fallback, poll-only, or an
insufficient legacy capture.
Decision points:
- ● working Real SDIO IRQ delivery is confirmed on kernel
#160+c312250dwmmc: use Rockchip SDIO interrupt bit +9703c32bwfm: defer SDIO IRQ tasking during attach . The Rockchip DWMMC host uses SDIO interrupt bit 24 (sdio_mask=0x01000000), not the generic bit 16. The bounded 2 MiB bidirectional run atlogs/wifi-transfer/20260505-095119-sdio-bit24-irq-active.logcompleted withirqmode=irq-active-watchdog,bwfm_irq=201..515,task_irq=180..417,cmd53_err=0,rx_err=0,tx_err=0, and no packet errors. - ● working The VOP vblank storm that made USB SSH look newly broken is fixed by
fb81d0frk_vop: mask vblank interrupts when idle .rk_vop0dropped from roughly 413k interrupts/sec to single digits/sec while Sway was up. - ● working USB Ethernet is not the throughput limiter. A 2026-05-05 host-to-phone local HTTP fetch over
ue0downloaded the same 64 MiB file three times at23.3-23.5 MB/s(~186-188 Mbit/s). That isolates the 42-43 KB/s native-WiFi ceiling to the WiFi / SDIO /bwfm_sdiodata path. - ● working WiFi firmware PM/MPC is now controllable at runtime with
2458d80bwfm: expose firmware power save control .dev.bwfm_sdio.0.power_save=1reportspm=2 mpc=1; toggling it to0reportspm=0 mpc=0; toggling it back leaves low-power policy enabled. - ● working The native WiFi throughput ceiling was the SDIO card clock, not USB, PM/MPC, or missing SDIO IRQs. Pre-fix,
clk_sdioandclk_sdio_cwere both stuck at800000; aftercf62d1bdwmmc: raise RK3399 SDIO CIU clock for high-speed traffic +8c61d6dsdiob: enable SDIO run clock by default , the 2026-05-06 post-reboot receipt showsdebug.sdiob_run_clock_hz=25000000,clk_sdio=50000000, andclk_sdio_c=50000000. A 256 KiB local HTTP fetch forced overwlan0measured2336 kBps, and the same-size phone-to-hostncupload completed in0.14s;cmd53_err=0,rx_err=0,tx_err=0. - ● working The larger-transfer proof is no longer pending. With
power_save=1,pm=2,mpc=1, andirqmode=irq-active-watchdog, 8 MiB host-to-phone HTTP overwlan0measured1504 kBps, 32 MiB measured2294 kBps, and an 8 MiB phone-to-hostncupload completed in7.55s;cmd53_err=0,rx_err=0,tx_err=0, andrx_glom_errors=0. - ● working Reboot DHCP works once the stale USB-default-route rc.conf is replaced with the installer path.
mise run wifi:boot:phonebacked up/etc/rc.conf, installedifconfig_wlan0="WPA SYNCDHCP", setbackground_dhclient_wlan0="NO", removeddefaultrouter, and the next reboot returned withwlan0=192.168.1.142plus the default route onwlan0. - ○ blocked USB SSH drops, WiFi SSH drops, or the framebuffer shows a panic: preserve the serial log, restore
kernel.previf needed, and do not repeat the same transfer until the panic site is understood.
Poll fallback plan
This was the contingency plan while the host delivered zero SDIO function
interrupts. It is no longer the primary path after c312250 dwmmc: use Rockchip SDIO interrupt bit ,
and it should not be used to hide a clock regression after 8c61d6d sdiob: enable SDIO run clock by default :
- read
debug.bwfm_stateand recordirqmode=irq-armed-poll-fallbackversusirqmode=irq-active-watchdog - record
task_irq,task_watchdog, andtask_coalescedalongsidedev.rockchip_dwmmc.0.sdio_intrs - keep
dev.bwfm_sdio.0.irq_watchdog_hz=1as a low-rate safety net while IRQs are active - only return to
mise run debug:wifi:fallback-matrix -- both poll-fallbackif a future regression takessdio_intrsback to zero - compare
wlan0byte deltas, error deltas, USB stalls, elapsed time, and the classification line across matrix points - document CPU cost and throughput honestly in essay 15
WiFi polish plan
The throughput blocker is closed enough to move to policy and coverage:
- Keep the 8 MiB / 32 MiB receipts as the baseline for future regressions:
1504 kBpsand2294 kBpshost-to-phone HTTP overwlan0, plus an 8 MiB phone-to-hostncupload in7.55s, all with clean bwfm counters. - Confirm the same DHCP behavior on a true cold boot; reboot already came back
with
wlan0=192.168.1.142and the default route onwlan0. - Leave
dev.bwfm_sdio.0.power_save=1for a long idle test and confirmdebug.bwfm_fw_statestill reportspm=2 mpc=1. - Keep
debug.sdiob_run_clock_hztunable.25000000is the default proof point;0is the recovery knob if an SDIO card regresses during bring-up. - Treat RX glomming separately. The parser has
rx_glom_errors=0under load, but the clock-only negative control still measured2034 kBps, so glomming is not the primary throughput fix.
The fallback can be acceptable for recovery if it is predictable, bounded, and named correctly. It should not replace a working IRQ path.
Bluetooth audio reconfirmation
After WiFi is either fixed or explicitly demoted to fallback mode, rerun A2DP as a clean confidence test. The recent bench session proved on-device speaker audio again; it did not re-prove Bluetooth speaker output.
# Pick the paired speaker's bdaddr from /dev/bluetooth or the pairing log.
ssh pinephone 'ls /dev/bluetooth 2>/dev/null || true'
# Start the existing A2DP script/tooling against that peer.
# Keep /dev/dsp0 / RT5640 playback out of the test so loudspeaker output
# cannot be mistaken for A2DP. Pass condition: audible output from the external Bluetooth speaker, with the phone loudspeaker silent.
After WiFi and A2DP
The next subsystem arc is still modem:
- install the SIM adapter
- rerun
mise run modem:power:phoneandmise run modem:status:phone - resolve
AT+CPIN?returning+CME ERROR: 10 - switch EG25-G to ECM mode only after SIM detection is real
- port the smallest useful subset of sxmo modem scripts for calls/SMS
Sensors and UI policy remain bounded follow-ups: proximity screen blanking, orientation policy, LED patterns, and headphone/microphone routing.