Files
BFE Engineering 42fb386f60 docs: ASCII typography and style normalization across all repo text
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.
2026-08-31 12:31:27 -06:00

313 lines
18 KiB
Markdown

# 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_initcall`s 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-level `AIC_WLAN_SUPPORT`
bool + `AIC_FW_PATH` string, `source`s the fdrv/btlpm sub-Kconfigs.
Wired into `drivers/net/wireless/Kconfig` (new `source` line, alongside
the existing vendor Kconfig list).
- `drivers/net/wireless/aic8800/Makefile`, `obj-y` list preserving
bsp -> fdrv -> btlpm link order (per PORT-PLAN.md section 4.5, since these are
built-in `=y` now and initcall order follows link order). Wired into
`drivers/net/wireless/Makefile` (`obj-$(CONFIG_AIC_WLAN_SUPPORT) += aic8800/`).
- `aic8800_fdrv/Kconfig`, `aic8800_btlpm/Kconfig`, vendor's `tristate`
symbols changed to `default y` (built-in, not modular; the 6.18 rootfs
has no working module pipeline yet).
- Three new in-tree `Makefile`s (`aic8800_bsp/`, `aic8800_fdrv/`,
`aic8800_btlpm/`) translating the vendor's `ccflags-$(CONFIG_X) += -DX`
pattern into fixed `-D` flags 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_PATH`
needs no `-D`: it's now a real Kconfig string symbol, so
`include/generated/autoconf.h` already defines the `CONFIG_AIC_FW_PATH`
C-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:6177` wasn'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.c` isn't compiled, `CONFIG_SUPPORT_LPM=n`).
- `netif_rx_ni()` -> `netif_rx()`: 3 sites, all `rwnx_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 a `link_id` param before `gfp`; 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`'s `HIGH_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 (`notify` dropped back to 3 args `(dev, chandef, link_id)`;
`started_notify` is 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_ops` struct-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 takes `struct cfg80211_ap_update *` (wraps the old
`cfg80211_beacon_data` as `.beacon`, plus FILS/S1G/unsol fields unused
here); unwrapped with `&update->beacon` so `rwnx_build_bcn()` and its
other 3 callers stay untouched.
- `set_monitor_channel`: gained a `struct net_device *dev` param. Rather
than thread an unused `dev` through the well-used internal 2-arg
`rwnx_cfg80211_set_monitor_channel()` (called elsewhere with `chandef =
NULL` to retrieve firmware-level channel state), added a thin
`rwnx_cfg80211_set_monitor_channel_ops()` adapter and pointed the ops
table at that instead.
- `set_wiphy_params`: gained `int radio_idx` before `changed`.
- `set_tx_power`: gained `int radio_idx` between `wdev` and `type`.
- `get_tx_power`: gained `int radio_idx, unsigned int link_id` before the
output pointer.
- `start_radar_detection`: gained a trailing `int link_id`.
- `tdls_mgmt`: gained `int link_id` right after `peer`.
- **`cfg80211_cac_event()`** (`rwnx_radar.c`, 2 sites): gained a trailing
`unsigned int link_id`; passed `0` (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 in
`drivers/base/power/wakeup.c` but are no longer `EXPORT_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 literally `create()` + conditional sysfs +
`add()`). Rewrote `rwnx_wakeup_init()`/`_deinit()` to call
`wakeup_source_register(NULL, name)` / `wakeup_source_unregister(ws)`:
`dev=NULL` registers an anonymous source not tied to a `struct device`,
matching the old `wakeup_source_create()` behavior used here. (The file
already had a correct modern `rwnx_wakeup_register()`/`_unregister()`
pair for a different call path; this fix makes `rwnx_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-mainline `VFS_internal_I_am_really_a_filesystem_and_am_NOT_a_driver`
namespace token (an Android-GKI-kernel artifact, confirmed absent from
our mainline `fs/` tree, so this is now inert modinfo metadata, not a
real namespace gate). `MODULE_INFO()`/`MODULE_IMPORT_NS()` now require a
quoted string per current `include/linux/module.h`.
- **`rwnx_platform.c`: unconditional `#include "rwnx_pci.h"`**, the header
was dropped with `rwnx_pci.c` (dead code, no PCIe on this board), but this
one `#include` wasn't behind any guard. Guarded it behind
`AICWF_PCIE_SUPPORT` (matching the guard its only two callers,
`rwnx_platform_{,un}register_drv()`, already use at their call sites in
`rwnx_main.c`) and guarded the two functions' `rwnx_pci_{,un}register_drv()`
bodies the same way, returning `0`/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
real `rockchip_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 behind `CONFIG_PLATFORM_ROCKCHIP2` (a symbol
this build never defines, only plain `ROCKCHIP`), so none needed
stubbing individually; only the unconditional header `#include`s needed
removing. The DT's `mmc-pwrseq-simple` node does the power/reset
sequencing instead, as planned.
- **`CONFIG_RFTEST` added to `aic8800_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_t` etc.) 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 is `CONFIG_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-pwrseq` node (`mmc-pwrseq-simple`,
`reset-gpios = <&gpio1 RK_PA2 GPIO_ACTIVE_LOW>`), transplanted verbatim
from the vendor board DTS.
- New `&sdmmc` override: `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>`, pinctrl
`sdmmc0_clk`/`_cmd`/`_bus4`/`_det`, `status = "okay"`.
- `&sdio` (mmc@ff9a0000) left untouched: stays `disabled`, 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_ratelimited`
and the `max_t(u32, cmd_mgr->queue_sz, 1)` clamp are both in
`rwnx_cmds.c` as shipped.
`future-features-2/sdk-patches/wifi/patches/0002-aic8800dc-sdio-wakeup-sleep-not-spin.patch`:
- `usleep_range(200, 400)`, the `woke` flag, and the "SDIO wakeup failed;
chip may be wedged" message are all in `aicwf_sdio.c` as 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:
1. `dmesg`: `dwmmc_rockchip ffaa0000.mmc: ...` binding (mirrors the M3
eMMC pattern on `ffa90000.mmc`), then an SDIO card enumerating on it
(vendor/device ID `0xc8a1`/`0xc08d`), then `aic8800_bsp`'s probe firing.
2. **Firmware path**: `AIC_FW_PATH` defaults to `/oem/usr/ko/aic8800dc_fw`,
a 5.10-era Buildroot `/oem` partition path. Confirm the 6.18 rootfs
actually has firmware there (or update `CONFIG_AIC_FW_PATH` to wherever
it landed), watch specifically for firmware-open failures in dmesg as
the first failure mode, before assuming a driver/DT bug.
3. `wlan0` should appear in `ip link` once `aic8800_fdrv` attaches.
4. `iw phy` should 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).
5. `iw dev wlan0 scan` and 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 from `rwnx_msg_rx.c` were 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).
6. 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_thr` should sleep, not spin).
7. BT: `aic8800_btlpm` should attach; `hciattach -s 1500000 /dev/ttyS1 any
1500000 flow nosleep` should bring up an HCI device.
8. 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-word `sed` scoped to that directory and re-verified by a
clean rebuild, but it touched every `.c`/`.h` in that subtree.