COMPEX WLE7000Ex(2/5/6) PROOF OF CONCEPT host APD - update on MLO for single band modules
pgupta at hindutool.com
pgupta at hindutool.com
Fri Jun 12 13:45:40 PDT 2026
I have 3 single band compex modules (WLE7000E2, WLE7000E5, WLE7000E6) that I am currently
testing under Ubuntu 26.04 stock kernel.
Below is a PoC (Proof of concept) that these modules can work under plain vanilla linux (ath12k +
HostAPD)
Note: Firmware binaries are needed from compex
NOTE: DKMS custom compiled module needed for ath12k_wifi driver
NOTE: HostAPD requires recompile with 802.11be support
NOTE: Tested, compiled, stress tested, and output formatted with the help of Claude Code Fable 5
NOTE: I have not yet connected devices to the modules, so I do not have info on transmission throughput etc.
Prashant
================================================================================
Compex_Ath12k_HostAPD — Wi-Fi 7 (802.11be / EHT) PROOF OF CONCEPT
================================================================================
Status : PROOF OF CONCEPT — captured live on real hardware
Sanitized : passphrases, SSID branding, usernames, host passwords, MAC
NIC-specific octets, and link-local addresses are MASKED for
public sharing; all command output is otherwise verbatim.
Box : test-router (Dell R730xd), Ubuntu 26.04, kernel 7.0.0-22-generic
Radios : 3× Compex WLE7000E (QCN9274 hw2.0, single-band) on PCIe risers
wlp129s0 = 2.4 GHz (board_id 0x1, PCIe Slot 1 / bus 81)
wlp133s0 = 5 GHz (board_id 0x2, PCIe Slot 2 / bus 85)
wlp132s0 = 6 GHz (board_id 0x4, PCIe Slot 3 / bus 84)
Captured : 2026-06-11/12 during the §S171 on-box test run
Provenance : Doc 10 (HostAPD and WiFi 7 AP Configuration Guide) PART A0 + B1
+ PART D radio configs; bugs found en route fixed in §S171
(corrections.md): fragm/rts_threshold legacy sentinels → -1, and
apt-mark hold hostapd promoted to a required step. Method:
superpowers systematic-debugging + Perplexity research.
Result : ALL THREE radios reach state=ENABLED with ieee80211be=1 and
measurably transmit (beacon airtime) on 2437 / 5745 / 5955 MHz.
================================================================================
--------------------------------------------------------------------------------
SECTION 1 — BUILDING THE DRIVER STACK
--------------------------------------------------------------------------------
The single-band Compex QCN9274 cards do NOT enumerate on the stock Ubuntu
26.04 ath12k. Three fixes are required (Doc 10 PART A0, §S164), plus an
EHT-capable hostapd userspace build (Doc 10 PART B1, §S167 B-26).
1.1 Compex vendor board-2.bin + regdb.bin overlay (Doc 10 A0.1)
The stock linux-firmware package supplies base firmware-2.bin; ONLY the
vendor-tuned board calibration is overlaid (rollback copy kept):
# --- operator-set: lan-fileserver (192.168.0.100) login + the directory
# holding the unzipped Compex package (board-2.bin + regdb.bin) ---
HT_USER=<user> # lan-fileserver SSH login
HT_PASS=<REDACTED> # lan-fileserver SSH password (no keys)
HT_SRC="/home/Shared Folder/Hardware/Compex Wifi/WLE7000x" # dir with the two .bin files
sudo apt-get install -y sshpass
sudo install -d -m 0755 -o root -g root /opt/compex-wle7000e
for f in board-2.bin regdb.bin; do
sshpass -p "$HT_PASS" scp -P 8888 -o StrictHostKeyChecking=accept-new \
"$HT_USER at 192.168.0.100:$HT_SRC/$f" /tmp/
done
sudo install -m 0644 -o root -g root /tmp/board-2.bin /opt/compex-wle7000e/board-2.bin
sudo install -m 0644 -o root -g root /tmp/regdb.bin /opt/compex-wle7000e/regdb.bin
rm -f /tmp/board-2.bin /tmp/regdb.bin
# Integrity gate — MUST print "OK" for BOTH lines before overlaying:
sha256sum -c <<'EOF'
2378f4b8303482b197ee0bffe4146a2c928144f30905df8c14006aafdae5bc09 /opt/compex-wle7000e/board-2.bin
3d4208d28014f80799db048994ddfd13cbcda97d8576a8d9f7d8e55299107140 /opt/compex-wle7000e/regdb.bin
EOF
# Keep a one-time rollback copy of the stock board-2.bin, then overlay:
sudo cp -n /lib/firmware/ath12k/QCN9274/hw2.0/board-2.bin \
/lib/firmware/ath12k/QCN9274/hw2.0/board-2.bin.stock 2>/dev/null || true
sudo install -m 0644 /opt/compex-wle7000e/board-2.bin \
/lib/firmware/ath12k/QCN9274/hw2.0/board-2.bin
sudo install -m 0644 /opt/compex-wle7000e/regdb.bin \
/lib/firmware/ath12k/QCN9274/hw2.0/regdb.bin
echo
echo "Compex board-2.bin board-ID coverage (expect 1, 2, 4 present):"
strings /lib/firmware/ath12k/QCN9274/hw2.0/board-2.bin \
| grep -oE 'qmi-board-id=[0-9]+' | sort -u
1.2 Patched ath12k via DKMS (Doc 10 A0.2 — FIX 1 + FIX 2), VERBATIM.
Installs /usr/local/sbin/ath12k-repatch and builds package
ath12k-qcn9274sb/1.0 for the running kernel. FIX 1 caps wmi_ep_count
for the absent MAC1; FIX 2 skips unknown WMI dma-ring module ids
(fw 1.6 sends id 2/3) instead of aborting the service-ready parse:
install -d -m 0755 /usr/local/sbin
cat > /usr/local/sbin/ath12k-repatch <<'ATH12K_REPATCH'
#!/bin/bash
# /usr/local/sbin/ath12k-repatch — (re)build the patched single-band QCN9274
# ath12k for a kernel (default: running kernel). Installed by Doc 10 A0.2;
# invoked manually (sudo ath12k-repatch), by /etc/kernel/postinst.d/
# zz-ath12k-repatch after a kernel upgrade, and by ath12k-dkms-verify.service
# at boot (both A0.6). Logs to /var/log/ath12k-repatch.log.
KVER="${1:-$(uname -r)}"
exec > >(tee -a /var/log/ath12k-repatch.log) 2>&1
echo "===== $(date -Is) ath12k-repatch kernel=$KVER pid=$ ====="
# if invoked right after an apt run, wait for the dpkg lock to clear:
for _ in $(seq 1 180); do fuser /var/lib/dpkg/lock-frontend >/dev/null 2>&1 || break; sleep 5; done
apt-get update
apt-get install -y build-essential dkms "linux-headers-$KVER"
# enable deb-src and fetch the kernel source (provides the ath12k tree)
sed -i 's/^Types: deb$/Types: deb deb-src/' /etc/apt/sources.list.d/ubuntu.sources
apt-get update
[ -f
"/usr/src/linux-${KVER%%-*}/drivers/net/wireless/ath/ath12k/wmi.c" ] || (
cd /usr/src && { apt-get source "linux-image-unsigned-$KVER" ||
apt-get source linux; } )
PKG=ath12k-qcn9274sb
VER=1.0
SRC="/usr/src/linux-${KVER%%-*}/drivers/net/wireless/ath/ath12k" # e.g. linux-7.0.0
DST="/usr/src/${PKG}-${VER}"
dkms status -m "$PKG" -v "$VER" 2>/dev/null | grep -q "$PKG" && dkms remove -m "$PKG" -v "$VER" --all
rm -rf "$DST"; mkdir -p "$DST"; cp -a "$SRC/." "$DST/"
find "$DST" \( -name '*.o' -o -name '*.ko' -o -name '*.mod' -o -name '*.mod.c' \
-o -name '.*.cmd' -o -name 'modules.order' -o -name 'Module.symvers' \) -delete 2>/dev/null
# apply both patches; the python aborts (non-zero) if any anchor is not an exact single match
if python3 - "$DST" <<'PYEOF'
import sys, os
def patch(path, old, new, label):
d = open(path).read()
n = d.count(old)
if n != 1:
sys.exit(f"[FAIL] {label}: expected 1 match in {os.path.basename(path)}, found {n}")
open(path, "w").write(d.replace(old, new, 1)); print(f"[ OK ] {label}")
ATH = sys.argv[1]; HTC = ATH+"/htc.c"; WMI = ATH+"/wmi.c"
A_OLD = ("\tdefault:\n\t\thtc->wmi_ep_count = ab->hw_params->max_radios;\n\t\tbreak;\n\t}\n")
A_NEW = ("\tdefault:\n\t\thtc->wmi_ep_count = ab->hw_params->max_radios;\n"
"\t\t/* QCN9274 single-band fix (Doc 10 A0.2 / §S164): single-MAC cards\n"
"\t\t * advertise fewer PHYs via QMI (ab->qmi.num_radios) than\n"
"\t\t * hw_params->max_radios (2 for qcn9274 hw2.0); opening a WMI\n"
"\t\t * endpoint for the absent MAC1 fails. Cap to the fw-reported count.\n\t\t */\n"
"\t\tif (ab->qmi.num_radios != U8_MAX &&\n"
"\t\t ab->qmi.num_radios >= 1 &&\n"
"\t\t ab->qmi.num_radios < htc->wmi_ep_count)\n"
"\t\t\thtc->wmi_ep_count = ab->qmi.num_radios;\n\t\tbreak;\n\t}\n")
B1_OLD = ("\tstruct ath12k_dbring_cap *dir_buff_caps;\n\tint ret;\n\tu32 i;\n")
B1_NEW = ("\tstruct ath12k_dbring_cap *dir_buff_caps;\n\tint ret;\n\tu32 i, j;\n")
B2_OLD = ("\tdir_buff_caps = ab->db_caps;\n"
"\tfor (i = 0; i < dma_caps_parse->n_dma_ring_caps; i++) {\n"
"\t\tif (le32_to_cpu(dma_caps[i].module_id) >= WMI_DIRECT_BUF_MAX) {\n"
"\t\t\tath12k_warn(ab, \"Invalid module id %d\\n\",\n"
"\t\t\t\t le32_to_cpu(dma_caps[i].module_id));\n"
"\t\t\tret = -EINVAL;\n\t\t\tgoto free_dir_buff;\n\t\t}\n\n"
"\t\tdir_buff_caps[i].id = le32_to_cpu(dma_caps[i].module_id);\n"
"\t\tdir_buff_caps[i].pdev_id =\n"
"\t\t\tDP_HW2SW_MACID(le32_to_cpu(dma_caps[i].pdev_id));\n"
"\t\tdir_buff_caps[i].min_elem = le32_to_cpu(dma_caps[i].min_elem);\n"
"\t\tdir_buff_caps[i].min_buf_sz = le32_to_cpu(dma_caps[i].min_buf_sz);\n"
"\t\tdir_buff_caps[i].min_buf_align = le32_to_cpu(dma_caps[i].min_buf_align);\n"
"\t}\n\n\treturn 0;\n\nfree_dir_buff:\n"
"\tath12k_wmi_free_dbring_caps(ab);\n\treturn ret;\n}\n")
B2_NEW = ("\tdir_buff_caps = ab->db_caps;\n"
"\tfor (i = 0, j = 0; i < dma_caps_parse->n_dma_ring_caps; i++) {\n"
"\t\tif (le32_to_cpu(dma_caps[i].module_id) >= WMI_DIRECT_BUF_MAX) {\n"
"\t\t\t/* QCN9274 single-band fix (Doc 10 A0.2 / §S164): fw 1.5/1.6\n"
"\t\t\t * advertises dma-ring module ids the host enum does not know;\n"
"\t\t\t * skip them instead of failing the whole service-ready parse.\n\t\t\t */\n"
"\t\t\tath12k_warn(ab, \"skipping unsupported dma ring module id %d\\n\",\n"
"\t\t\t\t le32_to_cpu(dma_caps[i].module_id));\n"
"\t\t\tcontinue;\n\t\t}\n\n"
"\t\tdir_buff_caps[j].id = le32_to_cpu(dma_caps[i].module_id);\n"
"\t\tdir_buff_caps[j].pdev_id =\n"
"\t\t\tDP_HW2SW_MACID(le32_to_cpu(dma_caps[i].pdev_id));\n"
"\t\tdir_buff_caps[j].min_elem = le32_to_cpu(dma_caps[i].min_elem);\n"
"\t\tdir_buff_caps[j].min_buf_sz = le32_to_cpu(dma_caps[i].min_buf_sz);\n"
"\t\tdir_buff_caps[j].min_buf_align = le32_to_cpu(dma_caps[i].min_buf_align);\n"
"\t\tj++;\n\t}\n\n\tab->num_db_cap = j;\n\n\treturn 0;\n}\n")
patch(HTC, A_OLD, A_NEW, "FIX 1 htc.c wmi_ep_count cap")
patch(WMI, B1_OLD, B1_NEW, "FIX 2a wmi.c add index j")
patch(WMI, B2_OLD, B2_NEW, "FIX 2b wmi.c skip unknown dma-ring module id")
print("[DONE] patches applied")
PYEOF
then
cat > "$DST/dkms.conf" <<EOF
PACKAGE_NAME="$PKG"
PACKAGE_VERSION="$VER"
AUTOINSTALL="yes"
MAKE[0]="make -C \${kernel_source_dir} M=\${dkms_tree}/\${PACKAGE_NAME}/\${PACKAGE_VERSION}/build modules"
CLEAN="make -C \${kernel_source_dir} M=\${dkms_tree}/\${PACKAGE_NAME}/\${PACKAGE_VERSION}/build clean"
BUILT_MODULE_NAME[0]="ath12k"
BUILT_MODULE_LOCATION[0]="."
DEST_MODULE_LOCATION[0]="/updates/dkms"
BUILT_MODULE_NAME[1]="ath12k_wifi7"
BUILT_MODULE_LOCATION[1]="wifi7"
DEST_MODULE_LOCATION[1]="/updates/dkms"
EOF
dkms add -m "$PKG" -v "$VER"
if dkms build -m "$PKG" -v "$VER" -k "$KVER"; then
dkms install -m "$PKG" -v "$VER" -k "$KVER" --force
depmod -a "$KVER"
echo "== install paths (MUST be under updates/dkms) =="
modinfo -n ath12k ath12k_wifi7
else
echo "!! dkms build FAILED — tail of make.log:"
find /var/lib/dkms/$PKG/$VER -name make.log -exec tail -n 40 {} \;
fi
else
echo "!! PATCH FAILED — anchors did not match this kernel's source. NOT building."
echo " Re-port the patches against /usr/src/linux-*/drivers/net/wireless/ath/ath12k/"
echo " (see ubuntu2604-compextroubleshooting.txt)."
fi
ATH12K_REPATCH
chmod 0755 /usr/local/sbin/ath12k-repatch
# build + install the patched ath12k for the CURRENT kernel now (output is
# shown on screen and appended to /var/log/ath12k-repatch.log):
ath12k-repatch
1.3 GRUB: REMOVE iommu=pt, KEEP intel_iommu=on (Doc 10 A0.3 — FIX 3), then
reboot. With iommu=pt the firmware's 28 MB 32-bit-coherent HOST_DDR
allocation fails ("qmi dma allocation failed … type 1" → "wmi unified
ready -110"). On-box GRUB state is verified in §3.10 below.
1.4 EHT hostapd userspace build (Doc 10 PART B1) — the stock apt hostapd,
even at v2.11, is compiled WITHOUT CONFIG_IEEE80211BE and rejects
ieee80211be=1. Build 2.11 from source and pin the package:
/usr/sbin/hostapd. The apt package is kept ONLY for its hostapd at .service
systemd template (referenced by the per-radio overrides in PART C):
$ sudo apt install -y build-essential pkg-config libnl-3-dev libnl-genl-3-dev libssl-dev hostapd
$ cd /usr/local/src && sudo rm -rf hostap-2.11 && sudo mkdir -p hostap-2.11 && cd hostap-2.11
$ sudo curl -fsSLo hostapd-2.11.tar.gz https://w1.fi/releases/hostapd-2.11.tar.gz
$ sudo tar xzf hostapd-2.11.tar.gz && cd hostapd-2.11/hostapd
$ sudo cp defconfig .config
# enable Wi-Fi 7 (EHT) + Wi-Fi 6 (HE) + WPA3-SAE + nl80211 driver:
$ for k in CONFIG_DRIVER_NL80211 CONFIG_IEEE80211N
CONFIG_IEEE80211AC CONFIG_IEEE80211AX CONFIG_IEEE80211BE CONFIG_SAE
CONFIG_OWE CONFIG_MBO; do \
sudo sed -i "s|^#${k}=y|${k}=y|" .config; \
grep -q "^${k}=y" .config || echo "${k}=y" | sudo tee -a .config >/dev/null; done
$ sudo make -j"$(nproc)"
$ sudo install -m 0755 hostapd hostapd_cli /usr/sbin/ # overwrite the stock (non-EHT) binary
$ sudo apt-mark hold hostapd # §S171: PIN the package — REQUIRED, not optional.
# A later `apt upgrade` silently reinstalls the stock non-EHT hostapd
# over this binary; the radios then fail D6a with "unknown configuration
# item 'ieee80211be'". Observed live on test-router (§S171): the box had
# reverted to 2:2.11-0ubuntu5 and all radios were dead until this rebuild.
# Un-hold only to deliberately rebuild a newer hostapd: `apt-mark unhold`.
$ /usr/sbin/hostapd -v # Expected: hostapd v2.11
$ grep '^CONFIG_IEEE80211BE=y' .config && echo "EHT compiled in ✓"
# After PART B writes the radio configs, CONFIRM the new binary accepts EHT:
# sudo /usr/sbin/hostapd -t /etc/hostapd/wlp132s0.conf
# -> must NOT print "unknown configuration item 'ieee80211be'"
--------------------------------------------------------------------------------
SECTION 2 — HOSTAPD CONFIGURATION FILES (AS TESTED, ONE PER RADIO)
--------------------------------------------------------------------------------
Written by Doc 10 PART D paste blocks (§S166 inline literals; §S171
fragm/rts_threshold=-1 fix in the 2.4 GHz file). These are the EXACT files
the running APs in Section 4 were started from, fetched off the box:
----------------------------------------------------------------------
/etc/hostapd/wlp129s0.conf (as tested — config hash redacted in this public copy)
----------------------------------------------------------------------
# hostapd configuration — wlp129s0 / 2.4 GHz
# Hardware: Compex WLE7000E2 — test-router
# Bridge: wbr (192.168.1.0/24)
# Generated 2026-06-12T00:49:14+00:00 by Doc 10 PART B3 static-literal paste
interface=wlp129s0
ctrl_interface=/run/hostapd-wlp129s0
ctrl_interface_group=hostapd
bridge=wbr
driver=nl80211
ssid=ExampleNet-2.4GHz
country_code=US
# country_code=US matches the self-managed ath12k US/DFS-FCC domain
# (the radios ignore 'iw reg set'; see PART A7).
hw_mode=g
channel=6
# 2.4 GHz (US): ch 1-11 at 30 dBm; ch 6 chosen for clean non-overlap
# (1/6/11 plan). channel=0 enables ACS if ath12k supports it
# (verify via 'iw phy phyN info | grep -i acs').
ieee80211d=1
ieee80211h=1
ieee80211n=1
ieee80211ac=0
ieee80211ax=1
ieee80211be=1
wds_sta=1
wds_bridge=wbr
ht_capab=[HT40+][SHORT-GI-20][SHORT-GI-40][TX-STBC][RX-STBC1][DSSS_CCK-40]
he_su_beamformer=1
he_su_beamformee=1
he_mu_beamformer=1
he_bss_color=1
he_bss_color_partial=0
# Security — WPA3-Personal transition (SAE + SAE-EXT-KEY + WPA-PSK)
wpa=2
wpa_key_mgmt=SAE SAE-EXT-KEY WPA-PSK
wpa_passphrase=<REDACTED-PASSPHRASE>
rsn_pairwise=CCMP CCMP-256 GCMP-256
group_cipher=CCMP
sae_require_mfp=1
ieee80211w=1
macaddr_acl=0
beacon_int=100
dtim_period=2
rts_threshold=-1
fragm_threshold=-1
max_num_sta=100
logger_syslog=-1
logger_syslog_level=2
logger_stdout=-1
logger_stdout_level=2
----------------------------------------------------------------------
/etc/hostapd/wlp133s0.conf (as tested — config hash redacted in this public copy)
----------------------------------------------------------------------
# hostapd configuration — wlp133s0 / 5 GHz UNII-3 ch149 80 MHz
# Hardware: Compex WLE7000E5 — test-router
# Bridge: wbr (192.168.1.0/24)
# Generated $(date -Iseconds) by Doc 10 PART B4 static-literal paste
interface=wlp133s0
ctrl_interface=/run/hostapd-wlp133s0
ctrl_interface_group=hostapd
bridge=wbr
driver=nl80211
ssid=ExampleNet-5GHz
country_code=US
# country_code=US (self-managed US/DFS-FCC domain). UNII-3 5735-5855
# MHz at 30 dBm, no DFS; ch149 80 MHz (center idx 155) covers 5735-5825.
hw_mode=a
channel=149
ieee80211d=1
ieee80211h=1
ieee80211n=1
ieee80211ac=1
ieee80211ax=1
ieee80211be=1
wds_sta=1
wds_bridge=wbr
vht_capab=[MAX-MPDU-11454][SHORT-GI-80][SHORT-GI-160][TX-STBC-2BY1][RX-STBC-1][SU-BEAMFORMER][SU-BEAMFORMEE][MU-BEAMFORMER][RX-ANTENNA-PATTERN][TX-ANTENNA-PATTERN]
vht_oper_chwidth=1
vht_oper_centr_freq_seg0_idx=155
ht_capab=[HT40+][SHORT-GI-20][SHORT-GI-40][TX-STBC][RX-STBC1]
he_su_beamformer=1
he_su_beamformee=1
he_mu_beamformer=1
he_oper_chwidth=1
he_oper_centr_freq_seg0_idx=155
eht_oper_chwidth=1
eht_oper_centr_freq_seg0_idx=155
he_bss_color=2
he_bss_color_partial=0
# Security — WPA3-Personal transition (SAE + SAE-EXT-KEY + WPA-PSK)
wpa=2
wpa_key_mgmt=SAE SAE-EXT-KEY WPA-PSK
wpa_passphrase=<REDACTED-PASSPHRASE>
rsn_pairwise=CCMP CCMP-256 GCMP-256
group_cipher=CCMP
sae_require_mfp=1
ieee80211w=1
macaddr_acl=0
beacon_int=100
dtim_period=2
max_num_sta=100
logger_syslog=-1
logger_syslog_level=2
----------------------------------------------------------------------
/etc/hostapd/wlp132s0.conf (as tested — config hash redacted in this public copy)
----------------------------------------------------------------------
# hostapd configuration — wlp132s0 / 6 GHz / Indoor LPI
# Hardware: Compex WLE7000E6 — test-router
# Bridge: wbr (192.168.1.0/24)
# Generated $(date -Iseconds) by Doc 10 PART B5 static-literal paste
interface=wlp132s0
ctrl_interface=/run/hostapd-wlp132s0
ctrl_interface_group=hostapd
bridge=wbr
driver=nl80211
ssid=ExampleNet-6GHz
country_code=US
country3=0x49
# country3=0x49 ("I") = Indoor (LPI). ath12k is self-managed US/DFS-FCC;
# the full 6 GHz band (UNII-5/6/7/8) is available at 30 dBm LPI, no AFC.
hw_mode=a
channel=1
op_class=134
ieee80211d=1
ieee80211h=0
ieee80211n=0
ieee80211ac=0
ieee80211ax=1
ieee80211be=1
wds_sta=1
wds_bridge=wbr
he_oper_chwidth=2
he_oper_centr_freq_seg0_idx=15
eht_oper_chwidth=2
eht_oper_centr_freq_seg0_idx=15
he_su_beamformer=1
he_su_beamformee=1
he_mu_beamformer=1
he_bss_color=3
he_bss_color_partial=0
# Security — WPA3-Personal ONLY (mandatory for 6 GHz; PMF required)
wpa=2
wpa_key_mgmt=SAE SAE-EXT-KEY
wpa_passphrase=<REDACTED-PASSPHRASE>
rsn_pairwise=GCMP-256 CCMP-256
group_cipher=GCMP-256
sae_require_mfp=1
ieee80211w=2
macaddr_acl=0
beacon_int=100
dtim_period=2
max_num_sta=100
logger_syslog=-1
logger_syslog_level=2
--------------------------------------------------------------------------------
SECTION 3 — TEST BATTERY: RADIOS UP & HARDWARE RECOGNIZED (live output)
--------------------------------------------------------------------------------
##### SECTION 3 BATTERY — HARDWARE RECOGNITION #####
=== 3.1 PCIe enumeration (lspci) — three QCN9274 radios ===
$ lspci -nn | grep -i 'qcom\|17cb'
81:00.0 Network controller [0280]: Qualcomm Technologies, Inc QCN62xx/92xx Wireless Network Adapter [17cb:1109] (rev 01)
84:00.0 Network controller [0280]: Qualcomm Technologies, Inc QCN62xx/92xx Wireless Network Adapter [17cb:1109] (rev 01)
85:00.0 Network controller [0280]: Qualcomm Technologies, Inc QCN62xx/92xx Wireless Network Adapter [17cb:1109] (rev 01)
=== 3.2 Dell SMBIOS slot mapping ===
$ dmidecode -t slot | grep -E 'Designation|Bus Address' (PCIe slots 1-3)
Designation: PCIe Slot 1
Bus Address: 0000:81:00.0
Designation: PCIe Slot 2
Bus Address: 0000:85:00.0
Designation: PCIe Slot 3
Bus Address: 0000:84:00.0
Bus Address: 0000:82:00.0
=== 3.3 DKMS module (patched ath12k — Doc 10 PART A0.2) ===
$ dkms status
ath12k-qcn9274sb/1.0, 7.0.0-22-generic, x86_64: installed (Original modules exist)
=== 3.4 Loaded driver stack ===
$ lsmod | grep -E 'ath12k|mac80211|cfg80211'
ath12k_wifi7 147456 0
ath12k 921600 1 ath12k_wifi7
mac80211 1933312 2 ath12k,ath12k_wifi7
cfg80211 1536000 3 ath12k,ath12k_wifi7,mac80211
=== 3.5 ath12k firmware + board file probe (dmesg) ===
$ dmesg | grep -iE 'ath12k' | grep -iE 'board|firmware|wmi.*ready|pdev' | head -12
[ 15.505265] ath12k_wifi7_pci 0000:84:00.0: chip_id 0x0 chip_family 0xb board_id 0x4 soc_id 0x401a2200
[ 15.509679] ath12k_wifi7_pci 0000:85:00.0: chip_id 0x0 chip_family 0xb board_id 0x2 soc_id 0x401a2200
[ 15.510291] ath12k_wifi7_pci 0000:81:00.0: chip_id 0x0 chip_family 0xb board_id 0x1 soc_id 0x401a2200
=== 3.6 Compex board-2.bin overlay in place (Doc 10 PART A0.1) ===
$ ls -la /lib/firmware/ath12k/QCN9274/hw2.0/
total 4920
drwxr-xr-x 2 root root 4096 Jun 6 03:51 .
drwxr-xr-x 3 root root 4096 Apr 20 18:07 ..
lrwxrwxrwx 1 root root 44 Mar 19 12:32 Notice.txt.zst -> ../../../ath11k/IPQ6018/hw1.0/Notice.txt.zst
-rw-r--r-- 1 root root 910008 Jun 6 02:22 board-2.bin
-rw-r--r-- 1 root root 45353 Mar 19 12:32 board-2.bin.zst
-rw-r--r-- 1 root root 4035287 Mar 19 12:32 firmware-2.bin.zst
-rw-r--r-- 1 root root 25656 Jun 6 02:22 regdb.bin
=== 3.7 Three PHYs enumerated ===
$ ls /sys/class/ieee80211/ ; iw dev
phy0
phy1
phy2
phy#2
Interface wlp132s0
addr 04:f0:21:xx:xx:3b
type managed
phy#1
Interface wlp129s0
addr 04:f0:21:xx:xx:84
type managed
phy#0
Interface wlp133s0
addr 04:f0:21:xx:xx:fe
type managed
=== 3.8 EHT (Wi-Fi 7 / 802.11be) capability per PHY ===
$ iw phy phy0 info | grep -c EHT → 22 EHT capability lines
[phy0] EHT MAC Capabilities (0x3700):
[phy0] EHT PHY Capabilities (0xe2ffdbe0187700001c):
$ iw phy phy1 info | grep -c EHT → 19 EHT capability lines
[phy1] EHT MAC Capabilities (0xb700):
[phy1] EHT PHY Capabilities (0xe00103e0187700001c):
$ iw phy phy2 info | grep -c EHT → 25 EHT capability lines
[phy2] EHT MAC Capabilities (0x3700):
[phy2] EHT PHY Capabilities (0xe2ffdbe0187700001c):
=== 3.9 Band support per PHY (which radio is which band) ===
phy0 → interface wlp133s0 → Band 2 (Band 1=2.4GHz, Band 2=5GHz, Band 4=6GHz)
phy1 → interface wlp129s0 → Band 1 (Band 1=2.4GHz, Band 2=5GHz, Band 4=6GHz)
phy2 → interface wlp132s0 → Band 4 (Band 1=2.4GHz, Band 2=5GHz, Band 4=6GHz)
=== 3.10 EHT-capable hostapd build (Doc 10 PART B1) ===
$ /usr/sbin/hostapd -v ; apt-mark showhold
hostapd v2.11
apt-mark hold: hostapd
--------------------------------------------------------------------------------
SECTION 4 — TEST BATTERY: RADIOS TRANSMITTING UNDER HOSTAPD (live output)
--------------------------------------------------------------------------------
=== 4.1 Start all three APs (hostapd -B, per-radio config) ===
$ hostapd -B /etc/hostapd/wlp129s0.conf
wlp129s0: interface state UNINITIALIZED->COUNTRY_UPDATE
wlp129s0: interface state COUNTRY_UPDATE->HT_SCAN
$ hostapd -B /etc/hostapd/wlp133s0.conf
wlp133s0: interface state UNINITIALIZED->COUNTRY_UPDATE
wlp133s0: interface state COUNTRY_UPDATE->HT_SCAN
$ hostapd -B /etc/hostapd/wlp132s0.conf
SAE: Enabling SAE H2E on 6 GHz
wlp132s0: interface state UNINITIALIZED->COUNTRY_UPDATE
wlp132s0: interface state COUNTRY_UPDATE->ENABLED
=== 4.2 Daemons running ===
$ pgrep -a hostapd
276000 /usr/sbin/hostapd -B /etc/hostapd/wlp129s0.conf
276004 /usr/sbin/hostapd -B /etc/hostapd/wlp133s0.conf
276009 /usr/sbin/hostapd -B /etc/hostapd/wlp132s0.conf
=== 4.3 hostapd_cli STATUS per radio (the Doc 10 D6a gate) ===
$ hostapd_cli -p /run/hostapd-wlp129s0 -i wlp129s0 status | grep -E 'state|ieee80211be|freq|ssid|channel'
state=ENABLED
phy=phy1
freq=2437
channel=6
ieee80211ax=1
ieee80211be=1
eht_oper_chwidth=0
ssid[0]=ExampleNet-2.4GHz
num_sta[0]=0
$ hostapd_cli -p /run/hostapd-wlp133s0 -i wlp133s0 status | grep -E 'state|ieee80211be|freq|ssid|channel'
state=ENABLED
phy=phy0
freq=5745
channel=149
ieee80211ax=1
ieee80211be=1
eht_oper_chwidth=1
ssid[0]=ExampleNet-5GHz
num_sta[0]=0
$ hostapd_cli -p /run/hostapd-wlp132s0 -i wlp132s0 status | grep -E 'state|ieee80211be|freq|ssid|channel'
state=ENABLED
phy=phy2
freq=5955
channel=1
ieee80211ax=1
ieee80211be=1
eht_oper_chwidth=2
ssid[0]=ExampleNet-6GHz
num_sta[0]=0
=== 4.4 iw dev — AP mode, live channel/width/txpower ===
$ iw dev
Interface wlp132s0
type AP
channel 1 (5955 MHz), width: 160 MHz, center1: 6025 MHz
txpower 21.00 dBm
Interface wlp129s0
type AP
channel 6 (2437 MHz), width: 20 MHz, center1: 2437 MHz
txpower 26.00 dBm
Interface wlp133s0
type AP
channel 149 (5745 MHz), width: 80 MHz, center1: 5775 MHz
txpower 24.00 dBm
=== 4.5 Beacon TX proof — 'channel transmit time' delta over 10 s (0 stations) ===
wlp129s0 : channel-transmit-time 1400 ms -> 1649 ms (Δ=249 ms airtime TX'd in 10 s, zero clients = beacons)
wlp133s0 : channel-transmit-time 417 ms -> 462 ms (Δ=45 ms airtime TX'd in 10 s, zero clients = beacons)
wlp132s0 : channel-transmit-time 209 ms -> 244 ms (Δ=35 ms airtime TX'd in 10 s, zero clients = beacons)
=== 4.5b raw survey excerpt (wlp132s0, 6 GHz, in-use channel) ===
$ iw dev wlp132s0 survey dump (in-use channel block)
frequency: 5955 MHz [in use]
noise: -102 dBm
channel active time: 68960 ms
channel busy time: 1012 ms
channel receive time: 0 ms
channel transmit time: 244 ms
=== 4.6 wbr bridge membership (hostapd auto-enslaved the AP interfaces) ===
$ ip link show master wbr
wlp133s0:
wlp129s0:
wlp132s0:
=== 4.7 eno2 lifeline untouched ===
eno2 UP 192.168.0.252/24 fe80::xxxx:xxxx:xxxx:xxxx/64
--------------------------------------------------------------------------------
NOTES
--------------------------------------------------------------------------------
* Interpretation of §4.5: with num_sta[0]=0 on every BSS (no clients), a
rising "channel transmit time" is airtime spent EMITTING — i.e. beacons.
All three radios accumulate TX airtime (2.4 GHz beacons at 20 MHz cost the
most airtime; 6 GHz EHT160 the least), proving RF output on 2437 MHz,
5745 MHz, and 5955 MHz simultaneously.
* The three APs were LEFT RUNNING after capture so the SSIDs
(ExampleNet-2.4GHz / -5GHz / -6GHz, WPA3-SAE) can be verified with any
client device. Stop them with: sudo pkill -f 'hostapd.*wlp'
* hostapd `-t` is NOT a config-test flag (it means "timestamp logs" and runs
the AP in the foreground); a valid config therefore blocks. Use the D6a
hostapd_cli gate (as in §4.3) for positive verification.
* The eno2 management lifeline (192.168.0.252) was untouched throughout.
================================================================================
END OF DOCUMENT
================================================================================
More information about the ath12k
mailing list