Replace every em dash with real punctuation (rewrites, not hyphen swaps) in docs, code comments, scripts, configs, and the port records; convert en dashes, curly quotes, ellipsis glyphs, arrows, and section signs to ASCII; drop machine-writing tell phrases from living docs. ADR titles now use a colon. The M2 bring-up DTS model string carried an em dash into the patch series and its record echoes; fixed at both, and the full series re-verified to apply cleanly onto pristine 6.18.46. One comment in freshness.h deliberately names the em dash glyph the UI renders as the unknown mark; that is data, kept as prose naming it. Verified: cargo tests (sim, config-lint, rs485-bridge), shellcheck, both driver MC/DC harnesses, patches-apply.
18 KiB
AIC8800 wifi+BT port: M5 progress (2026-08-24)
Status: DONE, zImage + rv1106-warden.dtb build clean with the driver built in. Not flashed/booted (parent session verifies on hardware).
Build status
export PATH=".../sdk/tools/linux/toolchain/arm-rockchip830-linux-uclibcgnueabihf/bin:/usr/bin:/bin"
export ARCH=arm CROSS_COMPILE=arm-rockchip830-linux-uclibcgnueabihf-
make ARCH=arm CROSS_COMPILE=$CROSS_COMPILE zImage
make ARCH=arm CROSS_COMPILE=$CROSS_COMPILE rockchip/rv1106-warden.dtb
Clean rebuild (all aic8800 sources touched to force recompilation): 0
errors, 104 warnings, all benign vendor-code style (101 -Wmissing-prototypes on internal non-static helper functions that were
never prototyped in headers, 3 -Wempty-body on an existing if (...);-with-no-body debug macro expansion), none are correctness issues
and none were introduced by version-delta fixes. zImage is ready;
rv1106-warden.dtb compiles with only the pre-existing, unrelated &rgb
graph-endpoint warning (already known from M4 display work, not
wifi-related). Confirmed via nm vmlinux.unstripped that the driver is
actually linked in, not silently dropped: aicbsp_sdio_driver,
aicwf_sdio_driver, rwnx_cfg80211_ops all present, and the three
module_init()s appear as device_initcalls in the correct link order,
__initcall__kmod_aic8800_fdrv__...rwnx_mod_init after bsp's init and
__initcall__kmod_aic8800_btlpm__...aic_bluetooth_mod_init last.
What was copied/wired
Copied flare-edge/sdk/sysdrv/drv_ko/wifi/aic8800dc/{aic8800_bsp,aic8800_fdrv, aic8800_btlpm}/*.{c,h} into drivers/net/wireless/aic8800/ in the 6.18
tree, source-only (excluded .mod.c/.o/Module.symvers/etc build
artifacts left over in the vendor tree from prior out-of-tree builds).
Dropped as dead code for this board (SDIO-only, no USB/PCIe, CONFIG_SDIO_BT=n):
usb_host.{c,h}, rwnx_pci.{c,h}, aicwf_usb.c, btsdio.c, aic_btsdio.c.
One exception the plan flagged correctly: rwnx_mesh.{c,h} was
initially dropped on the same "dead code" theory but had to be restored,
rwnx_tx.c's NL80211_IFTYPE_MESH_POINT switch-case block is not
preprocessor-gated, so rwnx_mesh.h's types (struct rwnx_mesh_path,
struct rwnx_mesh_proxy) and prototypes are needed to compile even though
this board never creates a mesh-type interface. Restored both files
(1KB each) and added rwnx_mesh.o back to the fdrv Makefile object list.
usb_host.c/rwnx_pci.c did NOT need restoring: no build error ever
referenced them.
New in-tree Kbuild wiring (not copied from vendor, vendor Makefiles are
out-of-tree KDIR= external-module style and don't apply directly):
drivers/net/wireless/aic8800/Kconfig, top-levelAIC_WLAN_SUPPORTbool +AIC_FW_PATHstring,sources the fdrv/btlpm sub-Kconfigs. Wired intodrivers/net/wireless/Kconfig(newsourceline, alongside the existing vendor Kconfig list).drivers/net/wireless/aic8800/Makefile,obj-ylist preserving bsp -> fdrv -> btlpm link order (per PORT-PLAN.md section 4.5, since these are built-in=ynow and initcall order follows link order). Wired intodrivers/net/wireless/Makefile(obj-$(CONFIG_AIC_WLAN_SUPPORT) += aic8800/).aic8800_fdrv/Kconfig,aic8800_btlpm/Kconfig, vendor'stristatesymbols changed todefault y(built-in, not modular; the 6.18 rootfs has no working module pipeline yet).- Three new in-tree
Makefiles (aic8800_bsp/,aic8800_fdrv/,aic8800_btlpm/) translating the vendor'sccflags-$(CONFIG_X) += -DXpattern into fixed-Dflags for the one build configuration this board actually uses (SDIO, Rockchip, no USB/PCI/mesh-in-practice, TCP-ACK filter, preallocated TXQ, RF test support, see each Makefile's ccflags for the full list, matching the vendor Makefile defaults).CONFIG_AIC_FW_PATHneeds no-D: it's now a real Kconfig string symbol, soinclude/generated/autoconf.halready defines theCONFIG_AIC_FW_PATHC-string macro the driver expects (aicsdio.c:59,aic_bsp_driver.h:348).
API-delta fixes (file -> change)
Plan-anticipated mechanical renames (applied via scoped sed, all call sites)
from_timer()->timer_container_of(), 7 sites:aicsdio.c,aicwf_sdio.c(x3),rwnx_main.c,rwnx_rx.c(x2).del_timer_sync()->timer_delete_sync(), 10 sites:aicsdio.c,aicwf_sdio.c(x5),rwnx_main.c(x2, one more than the plan's count,rwnx_main.c:6177wasn't in the plan's list but grep found it),rwnx_rx.c(x2).del_timer()->timer_delete(), 9 sites:aicwf_tcp_ack.c(x4),rwnx_rx.c(x2),aic8800_btlpm/aic8800_btlpm.c(x3, dead, not in this build's object list, fixed anyway for tree hygiene),aic8800_btlpm/lpm.c(x3, same,lpm.cisn't compiled,CONFIG_SUPPORT_LPM=n).netif_rx_ni()->netif_rx(): 3 sites, allrwnx_rx.c.
Deltas beyond the plan's list (found by the compiler, fixed against 6.18 headers)
cfg80211_rx_spurious_frame()/cfg80211_rx_unexpected_4addr_frame()(rwnx_rx.c, 2 sites): gained alink_idparam beforegfp; passed-1("not applicable", per the header's own doc comment, this driver has no MLO).cfg80211_ch_switch_notify()/cfg80211_ch_switch_started_notify()(rwnx_main.c, 2 sites): the vendor's own version-gated compat shim (rwnx_compat.h'sHIGH_KERNEL_VERSION3/4= 6.3.0) already anticipated an API change here but guessed a 6.3-era signature that's since changed again by 6.18 (notifydropped back to 3 args(dev, chandef, link_id);started_notifyis 5 args(dev, chandef, link_id, count, quiet), no trailing reserved arg). Added a new#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 7, 0)tier ahead of the existing chain rather than edit the historical shim;link_id = 0(mandatory for non-MLO per the header).cfg80211_opsstruct-initializer type mismatches (rwnx_main.c, 7 callbacks, all gained new params, all effectively "not applicable" for this single-radio, non-MLO, SDIO full-MAC driver, so the new params are accepted and ignored):change_beacon: now takesstruct cfg80211_ap_update *(wraps the oldcfg80211_beacon_dataas.beacon, plus FILS/S1G/unsol fields unused here); unwrapped with&update->beaconsorwnx_build_bcn()and its other 3 callers stay untouched.set_monitor_channel: gained astruct net_device *devparam. Rather than thread an unuseddevthrough the well-used internal 2-argrwnx_cfg80211_set_monitor_channel()(called elsewhere withchandef = NULLto retrieve firmware-level channel state), added a thinrwnx_cfg80211_set_monitor_channel_ops()adapter and pointed the ops table at that instead.set_wiphy_params: gainedint radio_idxbeforechanged.set_tx_power: gainedint radio_idxbetweenwdevandtype.get_tx_power: gainedint radio_idx, unsigned int link_idbefore the output pointer.start_radar_detection: gained a trailingint link_id.tdls_mgmt: gainedint link_idright afterpeer.
cfg80211_cac_event()(rwnx_radar.c, 2 sites): gained a trailingunsigned int link_id; passed0(mandatory for non-MLO per doc comment).wakeup_source_create()/_add()/_remove()/_destroy()(rwnx_wakelock.c): removed from the public API entirely (still exist internally indrivers/base/power/wakeup.cbut are no longerEXPORT_SYMBOL'd);wakeup_source_register(dev, name)/wakeup_source_unregister(ws)is now the only supported entry point (confirmed:wakeup_source_register()'s own implementation is literallycreate()+ conditional sysfs +add()). Rewroterwnx_wakeup_init()/_deinit()to callwakeup_source_register(NULL, name)/wakeup_source_unregister(ws):dev=NULLregisters an anonymous source not tied to astruct device, matching the oldwakeup_source_create()behavior used here. (The file already had a correct modernrwnx_wakeup_register()/_unregister()pair for a different call path; this fix makesrwnx_wakeup_init()consistent with it.)MODULE_IMPORT_NS(bare_token)->MODULE_IMPORT_NS("string"): 3 sites (aic_bsp_driver.c,rwnx_platform.c,rwnx_main.c), all importing the same non-mainlineVFS_internal_I_am_really_a_filesystem_and_am_NOT_a_drivernamespace token (an Android-GKI-kernel artifact, confirmed absent from our mainlinefs/tree, so this is now inert modinfo metadata, not a real namespace gate).MODULE_INFO()/MODULE_IMPORT_NS()now require a quoted string per currentinclude/linux/module.h.rwnx_platform.c: unconditional#include "rwnx_pci.h", the header was dropped withrwnx_pci.c(dead code, no PCIe on this board), but this one#includewasn't behind any guard. Guarded it behindAICWF_PCIE_SUPPORT(matching the guard its only two callers,rwnx_platform_{,un}register_drv(), already use at their call sites inrwnx_main.c) and guarded the two functions'rwnx_pci_{,un}register_drv()bodies the same way, returning0/no-op for the SDIO-only build instead.<linux/rfkill-wlan.h>(vendor-only, PORT-PLAN.md section 3.7): removed from 3 files (aicsdio.c,aicwf_sdio.c,rwnx_main.c). Traced every realrockchip_wifi_power()/_set_carddetect()call site first: all of them are either already#if 0'd out in the vendor source (aicwf_sdio.c) or gated behindCONFIG_PLATFORM_ROCKCHIP2(a symbol this build never defines, only plainROCKCHIP), so none needed stubbing individually; only the unconditional header#includes needed removing. The DT'smmc-pwrseq-simplenode does the power/reset sequencing instead, as planned.CONFIG_RFTESTadded toaic8800_fdrv's ccflags: not itself a version delta, but needed:aic_priv_cmd.c's RF-test-mode enum (SET_TX,RDWR_EFUSE_*, ~50 constants) and struct typedefs (cmd_rf_settx_tetc.) are defined inline in the file under#ifdef CONFIG_RFTEST, and later code in the same file references them unconditionally. Omitting-DCONFIG_RFTEST(as an initial conservative default) produced ~90 "undeclared identifier" errors; the vendor Makefile's own default isCONFIG_RFTEST=y, so restoring it matches vendor intent, not a workaround.
Duplicate-symbol fixes (the biggest surprise, not in the plan)
The vendor aic8800_bsp and aic8800_fdrv were always built as two
independent .ko modules, each with its own private symbol namespace.
Built in-tree as =y, both link into one vmlinux, and it turns out
aic8800_bsp carries a complete second, self-contained copy of large
parts of aic8800_fdrv's machinery: its own SDIO byte/frame transport
(aicwf_sdio_*, aicwf_bus_*, aicwf_frame_*, aicwf_tx_*,
aicwf_rx_*, crc8_ponl_107), its own message/debug-command layer
(rwnx_send_dbg_*_req, rwnx_cmd_mgr_{init,deinit},
rwnx_rx_handle_msg), and a few globals (chip_mcu_id, chip_sub_id,
aic_fw_path, testmode), used for the bsp-side firmware bring-up phase
before fdrv's own driver instance re-probes and takes over the SDIO
function for real runtime operation. 49 symbols total, ld caught
every one as "multiple definition" at the final vmlinux.o link (the
per-subdirectory built-in.a build had already succeeded: this class of
error only surfaces at the whole-image link, which is worth knowing for
anyone repeating this kind of port).
Verified via aic_bsp_export.h (the real, narrow, intentional
aicbsp_*-prefixed bsp->fdrv API surface) that none of the 49 are part of
the actual cross-module contract, and via grep -rlw that fdrv has its
own complete definition of every one (not an extern pointing at
bsp's copy), confirming these are two truly independent implementations,
not one legitimately shared. Fix: renamed all 49 symbols with an
aicbsp_priv_ prefix, scoped strictly to aic8800_bsp/*.{c,h} (both
definitions and bsp-internal call sites via whole-word sed); fdrv's
copies are untouched. One of the 49, md5.c's MD5 functions, got a
different (smaller-footprint) fix: aic8800_bsp/md5.c and
aic8800_fdrv/md5.c are byte-identical files, so md5.o was simply
dropped from aic8800_fdrv's object list instead of renamed, fdrv's
calls resolve against bsp's copy at link time since bsp links first.
Config symbols set
CONFIG_AIC_WLAN_SUPPORT=y
CONFIG_AIC8800_WLAN_SUPPORT=y
CONFIG_AIC8800_BTLPM_SUPPORT=y
CONFIG_AIC_FW_PATH="/oem/usr/ko/aic8800dc_fw"
CONFIG_WIRELESS=y CONFIG_CFG80211=y CONFIG_WLAN=y (already y pre-port)
CONFIG_MMC=y CONFIG_MMC_DW_ROCKCHIP=y CONFIG_RFKILL=y (already y pre-port)
CONFIG_BT=y (was =m, flipped to =y, no module pipeline yet)
CONFIG_BT_HCIUART=y (was =m, flipped to =y)
CONFIG_BT_HCIUART_H4=y (already y)
CONFIG_CRYPTO_ARC4=y CONFIG_CRYPTO_CTR=y CONFIG_CRYPTO_CCM=y CONFIG_CRYPTO_AES=y
# CONFIG_MAC80211 is not set (explicitly left off, pure cfg80211 full-MAC
driver, confirmed no mac80211/ieee80211_hw
symbol usage anywhere in aic8800_fdrv)
Ran olddefconfig after setting these; verified afterward that other
ported drivers' symbols (CONFIG_CLK_RV1106, CONFIG_PINCTRL_ROCKCHIP,
CONFIG_DRM_ROCKCHIP, CONFIG_MMC_DW_ROCKCHIP) are untouched.
Device tree
arch/arm/boot/dts/rockchip/rv1106-warden.dts:
- New root-level
sdio_pwrseq: sdio-pwrseqnode (mmc-pwrseq-simple,reset-gpios = <&gpio1 RK_PA2 GPIO_ACTIVE_LOW>), transplanted verbatim from the vendor board DTS. - New
&sdmmcoverride:max-frequency = <50000000>,bus-width = <4>,cap-sd-highspeed,cap-sdio-irq,keep-power-in-suspend,non-removable,rockchip,default-sample-phase = <90>,supports-sdio,mmc-pwrseq = <&sdio_pwrseq>, pinctrlsdmmc0_clk/_cmd/_bus4/_det,status = "okay". &sdio(mmc@ff9a0000) left untouched: staysdisabled, genuinely unused hardware on this board.
Note: the &sdmmc node itself (mmc@ffaa0000) in rv1106.dtsi and
the sdmmc0_* pinctrl groups in rv1106-pinctrl.dtsi were already
present in this tree from earlier M1-M3 work (not added by this task),
this task only added the board-DTS enablement (status = "okay" +
properties) and the new sdio_pwrseq node. Verified in the compiled
.dtb (decompiled with dtc -I dtb -O dts) that both nodes carry the
correct phandles/properties.
Hardening patches
Both hardware-verified patches from the plan are already present in the
vendor SDK source we copied from (not merely trackable-but-unapplied),
confirmed two ways: patch -p5 --dry-run on both reported "Reversed (or
previously applied) patch detected" against the freshly-copied tree, and
grep found their exact markers already in place:
0001-aic8800dc-no-zero-timeout-spin-and-ratelimit.patch(major-app-additions/sdk-patches/wifi/patches/):printk_ratelimitedand themax_t(u32, cmd_mgr->queue_sz, 1)clamp are both inrwnx_cmds.cas shipped.future-features-2/sdk-patches/wifi/patches/0002-aic8800dc-sdio-wakeup-sleep-not-spin.patch:usleep_range(200, 400), thewokeflag, and the "SDIO wakeup failed; chip may be wedged" message are all inaicwf_sdio.cas shipped.
No action needed beyond copying the source. Known housekeeping gap
(pre-existing, not fixed by this task, flagged by the plan): patch 0002
is still only tracked under future-features-2/sdk-patches/wifi/patches/,
not this branch's own sdk-patches/wifi/patches/, worth closing
separately since the fix is live in the vendor tree either way.
Constraints honored
Only touched: the wifi driver tree (drivers/net/wireless/aic8800/), its
Kconfig/Makefile wiring (drivers/net/wireless/{Kconfig,Makefile}), the
board DTS wifi nodes (rv1106-warden.dts, additive only), and
wifi/BT/crypto-related .config symbols. Did not touch any other driver,
DT node, or unrelated config symbol: spot-checked after the port that
CONFIG_CLK_RV1106, CONFIG_PINCTRL_ROCKCHIP, CONFIG_DRM_ROCKCHIP,
CONFIG_MMC_DW_ROCKCHIP are all still =y, and the &rgb/VOP-related dtc
warning is the same pre-existing one from M4 (not new). Never touched
hardware: no kflash, no reboot, no /dev/ttyUSB2, no Pi.
What the parent should watch for on hardware
Per PORT-PLAN.md section 6's verify sequence:
dmesg:dwmmc_rockchip ffaa0000.mmc: ...binding (mirrors the M3 eMMC pattern onffa90000.mmc), then an SDIO card enumerating on it (vendor/device ID0xc8a1/0xc08d), thenaic8800_bsp's probe firing.- Firmware path:
AIC_FW_PATHdefaults to/oem/usr/ko/aic8800dc_fw, a 5.10-era Buildroot/oempartition path. Confirm the 6.18 rootfs actually has firmware there (or updateCONFIG_AIC_FW_PATHto wherever it landed), watch specifically for firmware-open failures in dmesg as the first failure mode, before assuming a driver/DT bug. wlan0should appear inip linkonceaic8800_fdrvattaches.iw physhould show one 2.4 GHz band, 14 channels (matches the known 5.10 baseline: a mismatch signals a cfg80211/wiphy port bug, not a chip issue).iw dev wlan0 scanand a real AP association exercise the wiphy-locking behavior (section 3.3 of the plan): this is the area with the least direct verification in this port (the driver's own ops callbacks need no new locking per the plan's analysis, since cfg80211 core now holds the wiphy mutex before calling in; the async-context notification calls fromrwnx_msg_rx.cwere flagged as the highest-residual-risk area and were NOT touched by this build-fix pass beyond the signature changes above, if scan/connect hang or lockdep splats appear, look there first).- Confirm the two hardening patches are actually effective under load: no
"cmd timed-out" console flood, no CPU-pinning busy-spin on a stressed/
wedged SDIO link (
aicwf_bustx_thrshould sleep, not spin). - BT:
aic8800_btlpmshould attach;hciattach -s 1500000 /dev/ttyS1 any 1500000 flow nosleepshould bring up an HCI device. - Given the scale of the bsp/fdrv duplicate-symbol rename (49 symbols),
if anything behaves subtly wrong in the bsp-side firmware bring-up
phase specifically (vs. fdrv's runtime path), double-check the rename
didn't miss a cross-file reference within
aic8800_bsp/: it was done with whole-wordsedscoped to that directory and re-verified by a clean rebuild, but it touched every.c/.hin that subtree.