commit 1e3c814f50cd9669be44685a6aa769d72a67990b Author: buzzer-re <22428720+buzzer-re@users.noreply.github.com> Date: Mon May 4 14:06:04 2026 -0300 first commit diff --git a/README.md b/README.md new file mode 100644 index 0000000..d2546e7 --- /dev/null +++ b/README.md @@ -0,0 +1,41 @@ +# PS5 IW620 mwifiex port + +Single-patch PS5 IW620 port for NXP mwifiex. + +## Fresh Build + +Run from this package root: + +```sh +git clone https://github.com/nxp-imx/mwifiex.git && cd mwifiex +git checkout lf-6.18.2_1.0.0 +git apply ../ps5-iw620.patch +make CONFIG_OBJTOOL= +``` + +## Load + +Run from the built driver root: + +```sh +sudo DRIVER_DIR="$PWD" ../test-iw620.sh load +``` + +Equivalent manual load: + +```sh +sudo modprobe cfg80211 +sudo insmod ./mlan.ko +sudo insmod ./moal.ko fw_name=nxp/pcieuartiw620_combo_v1.bin pcie_int_mode=1 drv_mode=1 cfg80211_wext=4 sta_name=mlan ext_scan=1 auto_fw_reload=0 wifi_reset_config=0 sched_scan=0 ps_mode=2 auto_ds=2 amsdu_disable=1 +``` + +## Test + +Run from the built driver root: + +```sh +sudo DRIVER_DIR="$PWD" ../test-iw620.sh capture +``` + +The patch does not add custom module flags. Disconnected scans are real scans; +connected scans complete from cached results to avoid the firmware hang. diff --git a/ps5-iw620.patch b/ps5-iw620.patch new file mode 100644 index 0000000..1b91cb6 --- /dev/null +++ b/ps5-iw620.patch @@ -0,0 +1,180 @@ +diff --git a/Makefile b/Makefile +index 2f9ff1e..6bf6f79 100644 +--- a/Makefile ++++ b/Makefile +@@ -35,23 +35,23 @@ CONFIG_SD8897=n + CONFIG_USB8897=n + CONFIG_PCIE8897=n + CONFIG_SD8977=n +-CONFIG_SD8978=y ++CONFIG_SD8978=n + CONFIG_USB8978=n +-CONFIG_SD8987=y ++CONFIG_SD8987=n + CONFIG_SD9097=n +-CONFIG_SD9177=y ++CONFIG_SD9177=n + CONFIG_USB9097=n +-CONFIG_PCIE9097=n +-CONFIG_SD9098=y ++CONFIG_PCIE9097=y ++CONFIG_SD9098=n + CONFIG_USB9098=n +-CONFIG_PCIE9098=y +-CONFIG_SDIW610=y +-CONFIG_USBIW610=y ++CONFIG_PCIE9098=n ++CONFIG_SDIW610=n ++CONFIG_USBIW610=n + CONFIG_SDIW624=n + CONFIG_SDAW693=n + CONFIG_PCIEIW624=n + CONFIG_USBIW624=n +-CONFIG_PCIEAW693=y ++CONFIG_PCIEAW693=n + + + # Debug Option +@@ -161,7 +161,8 @@ ccflags-y += -DLINUX + + + +-ARCH ?= arm64 ++ARCH ?= x86 ++KERNELDIR ?= /lib/modules/$(shell uname -r)/build + CONFIG_IMX_SUPPORT=y + ifeq ($(CONFIG_IMX_SUPPORT),y) + ccflags-y += -DIMX_SUPPORT +@@ -650,7 +651,7 @@ moal-objs := $(MOALOBJS) + else + + default: +- $(MAKE) -C $(KERNELDIR) M=$(PWD) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) modules ++ $(MAKE) -C $(KERNELDIR) M=$(CURDIR) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) modules + + endif + +diff --git a/mlan/mlan_init.c b/mlan/mlan_init.c +index 1d7dec4..f63fa62 100644 +--- a/mlan/mlan_init.c ++++ b/mlan/mlan_init.c +@@ -778,6 +778,8 @@ t_void wlan_init_adapter(pmlan_adapter pmadapter) + pmadapter->active_scan_triggered = MFALSE; + if (!pmadapter->init_para.ext_scan) + pmadapter->ext_scan = EXT_SCAN_TYPE_ENH; ++ else if (pmadapter->init_para.ext_scan == MLAN_LEGACY_SCAN) ++ pmadapter->ext_scan = MFALSE; + else if (pmadapter->init_para.ext_scan == EXT_SCAN_TYPE_ENH) + pmadapter->ext_scan = EXT_SCAN_TYPE_ENH; + else +diff --git a/mlinux/moal_eth_ioctl.c b/mlinux/moal_eth_ioctl.c +index f093c86..e9d1f3c 100644 +--- a/mlinux/moal_eth_ioctl.c ++++ b/mlinux/moal_eth_ioctl.c +@@ -6967,7 +6967,7 @@ static int woal_priv_get_ap(moal_private *priv, t_u8 *respbuf, t_u32 respbuflen) + moal_memcpy_ext(priv->phandle, mwr->u.ap_addr.sa_data, + &bss_info.bssid, MLAN_MAC_ADDR_LENGTH, + #if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 80) +- sizeof(mwr->u.ap_addr.sa_data_min)); ++ sizeof(mwr->u.ap_addr.sa_data)); + #else + sizeof(mwr->u.ap_addr.sa_data)); + #endif +diff --git a/mlinux/moal_init.c b/mlinux/moal_init.c +index 1979042..343535f 100644 +--- a/mlinux/moal_init.c ++++ b/mlinux/moal_init.c +@@ -3544,7 +3544,7 @@ MODULE_PARM_DESC( + module_param(ext_scan, int, 0660); + MODULE_PARM_DESC( + ext_scan, +- "0: MLAN default; 1: Enable Extended Scan; 2: Enable Enhanced Extended Scan"); ++ "0: MLAN default; 1: Legacy Scan; 2: Enable Extended Scan; 3: Enable Enhanced Extended Scan"); + module_param(bootup_cal_ctrl, int, 0660); + MODULE_PARM_DESC( + bootup_cal_ctrl, +diff --git a/mlinux/moal_pcie.c b/mlinux/moal_pcie.c +index fc1eedb..acd8840 100644 +--- a/mlinux/moal_pcie.c ++++ b/mlinux/moal_pcie.c +@@ -132,6 +132,7 @@ static const struct pci_device_id wlan_ids[] = { + + {}, + }; ++MODULE_DEVICE_TABLE(pci, wlan_ids); + /* moal interface ops */ + static moal_if_ops pcie_ops; + +diff --git a/mlinux/moal_shim.c b/mlinux/moal_shim.c +index 7aebbdf..181c4f2 100644 +--- a/mlinux/moal_shim.c ++++ b/mlinux/moal_shim.c +@@ -3784,7 +3784,7 @@ mlan_status moal_recv_event(t_void *pmoal, pmlan_event pmevent) + moal_memcpy_ext(priv->phandle, wrqu.ap_addr.sa_data, + pmevent->event_buf, ETH_ALEN, + #if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 80) +- sizeof(wrqu.ap_addr.sa_data_min)); ++ sizeof(wrqu.ap_addr.sa_data)); + #else + sizeof(wrqu.ap_addr.sa_data)); + #endif +diff --git a/mlinux/moal_sta_cfg80211.c b/mlinux/moal_sta_cfg80211.c +index 58d4592..2c8b3ec 100644 +--- a/mlinux/moal_sta_cfg80211.c ++++ b/mlinux/moal_sta_cfg80211.c +@@ -5628,6 +5628,20 @@ static int woal_cfg80211_scan(struct wiphy *wiphy, struct net_device *dev, + } + #endif + ++ if (priv->media_connected == MTRUE) { ++ PRINTM(MMSG, ++ "Fake-complete connected-state scan on %s for PS5 IW620 stability\n", ++ dev->name); ++ spin_lock_irqsave(&priv->phandle->scan_req_lock, flags); ++ priv->phandle->fake_scan_complete = MTRUE; ++ priv->phandle->scan_request = request; ++ spin_unlock_irqrestore(&priv->phandle->scan_req_lock, flags); ++ queue_delayed_work(priv->phandle->evt_workqueue, ++ &priv->phandle->scan_timeout_work, ++ msecs_to_jiffies(1000)); ++ return ret; ++ } ++ + /** Cance remain on channel */ + woal_cancel_remain_on_channel(priv); + +diff --git a/mlinux/moal_uap_wext.c b/mlinux/moal_uap_wext.c +index f4b6347..5646778 100644 +--- a/mlinux/moal_uap_wext.c ++++ b/mlinux/moal_uap_wext.c +@@ -244,7 +244,7 @@ static int woal_get_wap(struct net_device *dev, struct iw_request_info *info, + moal_memcpy_ext(priv->phandle, awrq->sa_data, + priv->current_addr, MLAN_MAC_ADDR_LENGTH, + #if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 80) +- sizeof(awrq->sa_data_min)); ++ sizeof(awrq->sa_data)); + #else + sizeof(awrq->sa_data)); + #endif +diff --git a/mlinux/moal_wext.c b/mlinux/moal_wext.c +index 953c60b..694b719 100644 +--- a/mlinux/moal_wext.c ++++ b/mlinux/moal_wext.c +@@ -590,7 +590,7 @@ static int woal_get_wap(struct net_device *dev, struct iw_request_info *info, + moal_memcpy_ext(priv->phandle, awrq->sa_data, &bss_info.bssid, + #if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 80) + MLAN_MAC_ADDR_LENGTH, +- sizeof(awrq->sa_data_min)); ++ sizeof(awrq->sa_data)); + #else + MLAN_MAC_ADDR_LENGTH, sizeof(awrq->sa_data)); + #endif +@@ -3073,7 +3073,7 @@ static int woal_get_scan(struct net_device *dev, struct iw_request_info *info, + moal_memcpy_ext(priv->phandle, iwe.u.ap_addr.sa_data, + &scan_table[i].mac_address, ETH_ALEN, + #if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 80) +- sizeof(iwe.u.ap_addr.sa_data_min)); ++ sizeof(iwe.u.ap_addr.sa_data)); + #else + sizeof(iwe.u.ap_addr.sa_data)); + #endif diff --git a/test-iw620.sh b/test-iw620.sh new file mode 100755 index 0000000..a449d40 --- /dev/null +++ b/test-iw620.sh @@ -0,0 +1,300 @@ +#!/bin/sh +set -eu + +DEV=${DEV:-0000:40:00.7} +FW=${FW:-nxp/pcieuartiw620_combo_v1.bin} +EXT_SCAN=${EXT_SCAN:-1} +DRVDBG=${DRVDBG:-0x7} +DRIVER_DIR=${DRIVER_DIR:-} +MODE=${1:-capture} +LOG_ROOT_INPUT=${LOG_ROOT:-} +DURATION=${DURATION:-600} +INTERVAL=${INTERVAL:-5} +CLEAR_DMESG=${CLEAR_DMESG:-1} +GUIDED=${GUIDED:-1} +RUN_LOAD=${RUN_LOAD:-1} + +need_root() { + if [ "$(id -u)" -ne 0 ]; then + echo "Run this as root: sudo $0" >&2 + exit 1 + fi +} + +find_driver_dir() { + if [ -n "$DRIVER_DIR" ]; then + return 0 + fi + + if [ -f ./mlan.ko ] && [ -f ./moal.ko ]; then + DRIVER_DIR=$PWD + return 0 + fi + + script_dir=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd) + if [ -f "$script_dir/mlan.ko" ] && [ -f "$script_dir/moal.ko" ]; then + DRIVER_DIR=$script_dir + return 0 + fi + + echo "ERROR: unable to find mlan.ko/moal.ko" >&2 + echo "Run from the built driver checkout or set DRIVER_DIR to it" >&2 + exit 1 +} + +module_loaded() { + lsmod | awk -v mod="$1" 'NR > 1 && $1 == mod { found = 1 } END { exit !found }' +} + +find_iface() { + for netdev in /sys/bus/pci/devices/"$DEV"/net/*; do + [ -e "$netdev" ] || continue + basename "$netdev" + return 0 + done + return 1 +} + +say() { + printf '%s\n' "$*" | tee -a "$TRANSCRIPT" +} + +mark() { + msg=$1 + printf '<6>iw620-test: %s\n' "$msg" >/dev/kmsg 2>/dev/null || true + say "== marker: $msg ==" +} + +run_log() { + name=$1 + shift + { + printf '### %s\n' "$name" + printf '### command:' + for arg in "$@"; do + printf ' %s' "$arg" + done + printf '\n' + "$@" + printf '\n' + } >>"$LOG_DIR/$name.log" 2>&1 || true +} + +unload_modules() { + for netdev in /sys/bus/pci/devices/"$DEV"/net/*; do + [ -e "$netdev" ] || continue + netdev=$(basename "$netdev") + echo "bringing down $netdev" + ip link set "$netdev" down || true + done + + for module in moal mlan; do + if module_loaded "$module"; then + echo "rmmod $module" + if ! rmmod "$module"; then + echo "ERROR: failed to unload $module" >&2 + lsmod | awk 'NR == 1 || $1 == "moal" || $1 == "mlan"' + if [ -d "/sys/module/$module/holders" ]; then + echo "holders for $module:" + ls -1 "/sys/module/$module/holders" + fi + return 1 + fi + fi + done +} + +load_driver() { + modprobe cfg80211 + for module in mlan moal; do + if module_loaded "$module"; then + echo "ERROR: $module is still loaded; refusing to insert over it" >&2 + lsmod | awk 'NR == 1 || $1 == "moal" || $1 == "mlan"' + return 1 + fi + done + + insmod "$DRIVER_DIR/mlan.ko" + insmod "$DRIVER_DIR/moal.ko" \ + fw_name="$FW" \ + pcie_int_mode=1 \ + drv_mode=1 \ + cfg80211_wext=4 \ + sta_name=mlan \ + ext_scan="$EXT_SCAN" \ + auto_fw_reload=0 \ + wifi_reset_config=0 \ + sched_scan=0 \ + ps_mode=2 \ + auto_ds=2 \ + amsdu_disable=1 \ + drvdbg="$DRVDBG" +} + +dump_pci_state() { + { + date --iso-8601=seconds + lspci -nnk -s "$DEV" || true + lspci -vvnn -s "$DEV" || true + for attr in enable irq current_link_speed current_link_width \ + power_state resource; do + if [ -e "/sys/bus/pci/devices/$DEV/$attr" ]; then + printf '%s=' "$attr" + cat "/sys/bus/pci/devices/$DEV/$attr" + fi + done + printf '\n' + } >>"$LOG_DIR/pci-state.log" 2>&1 +} + +dump_module_params() { + { + date --iso-8601=seconds + if [ -d /sys/module/moal/parameters ]; then + for param in /sys/module/moal/parameters/*; do + [ -e "$param" ] || continue + printf '%s=' "$(basename "$param")" + cat "$param" + done + else + echo "moal parameters not present" + fi + printf '\n' + } >>"$LOG_DIR/module-params.log" 2>&1 +} + +sample_state() { + while :; do + { + echo "### $(date --iso-8601=seconds)" + iface=$(find_iface || true) + if [ -n "${iface:-}" ]; then + echo "iface=$iface" + ip -d link show "$iface" || true + iw dev "$iface" link || true + if [ -e "/sys/class/net/$iface/operstate" ]; then + printf 'operstate=' + cat "/sys/class/net/$iface/operstate" + fi + if [ -e "/sys/class/net/$iface/carrier" ]; then + printf 'carrier=' + cat "/sys/class/net/$iface/carrier" + fi + else + echo "iface=" + fi + echo + } >>"$LOG_DIR/state-samples.log" 2>&1 + sleep "$INTERVAL" + done +} + +stop_background() { + if [ -n "${STATE_PID:-}" ]; then + kill "$STATE_PID" 2>/dev/null || true + fi + if [ -n "${DMESG_PID:-}" ]; then + kill "$DMESG_PID" 2>/dev/null || true + fi + dmesg >"$LOG_DIR/dmesg-final.log" 2>&1 || true + dump_pci_state || true + dump_module_params || true +} + +wait_step() { + step=$1 + mark "before $step" + say "" + say "Do this now: $step" + say "Press Enter here after that step is done." + read dummy || true + mark "after $step" + dump_pci_state || true + dump_module_params || true +} + +prepare_logs() { + stamp=$(date +%Y%m%d-%H%M%S) + if [ -z "$LOG_ROOT_INPUT" ]; then + LOG_ROOT="$DRIVER_DIR/iw620-test-logs" + else + LOG_ROOT="$LOG_ROOT_INPUT" + fi + LOG_DIR="$LOG_ROOT/$stamp" + mkdir -p "$LOG_DIR" + TRANSCRIPT="$LOG_DIR/transcript.log" + touch "$TRANSCRIPT" +} + +capture_run() { + prepare_logs + trap stop_background EXIT INT TERM + + say "== iw620 test directory: $LOG_DIR ==" + say "== params: DEV=$DEV DRIVER_DIR=$DRIVER_DIR FW=$FW EXT_SCAN=$EXT_SCAN RUN_LOAD=$RUN_LOAD ==" + + run_log uname uname -a + run_log cmdline cat /proc/cmdline + run_log moal-modinfo modinfo "$DRIVER_DIR/moal.ko" + run_log mlan-modinfo modinfo "$DRIVER_DIR/mlan.ko" + dump_pci_state + + if [ "$CLEAR_DMESG" = "1" ]; then + dmesg -C || true + fi + dmesg -wT >"$LOG_DIR/dmesg-live.log" 2>&1 & + DMESG_PID=$! + + mark "capture start" + + if [ "$RUN_LOAD" = "1" ]; then + say "== loading driver ==" + if ! { unload_modules && load_driver; } >"$LOG_DIR/load.log" 2>&1; then + say "ERROR: driver load failed; see $LOG_DIR/load.log" + exit 1 + fi + dump_pci_state || true + dump_module_params || true + fi + + sample_state & + STATE_PID=$! + + if [ "$GUIDED" = "1" ]; then + wait_step "connect to your AP" + wait_step "run a Wi-Fi scan while connected" + wait_step "turn Wi-Fi off" + wait_step "turn Wi-Fi on and reconnect" + wait_step "run another Wi-Fi scan" + else + say "== unguided capture for ${DURATION}s ==" + sleep "$DURATION" + fi + + mark "capture finish" + say "== logs saved in: $LOG_DIR ==" +} + +need_root +find_driver_dir + +case "$MODE" in + load) + unload_modules + load_driver + ;; + unload) + unload_modules + ;; + reload) + unload_modules + load_driver + ;; + capture) + capture_run + ;; + *) + echo "Usage: sudo DRIVER_DIR=\$PWD $0 [capture|load|reload|unload]" >&2 + exit 2 + ;; +esac