27 changed files with 534 additions and 469 deletions
-67
View File
@@ -1,67 +0,0 @@
# Building with OpenWrt backports
OpenWrt's target kernel and wireless stack can have different versions.
For example, [issue #94](https://github.com/shenmintao/aic8800d80/issues/94)
uses Linux **6.12.94** with **backports 6.18.26** on OpenWrt 25.12.5.
The Ubuntu build host's kernel version is not used to select these APIs.
## Package Makefile
Pass `CFG80211_VERSION=6.18.26` to the kernel make invocation for that
combination. Use the `PKG_VERSION` from your OpenWrt
`package/kernel/mac80211/Makefile`, in `major.minor.patch` format. Keep the
backports include paths and symbol versions from the same build:
```make
NOSTDINC_FLAGS := \
$(KERNEL_NOSTDINC_FLAGS) \
-I$(STAGING_DIR)/usr/include/mac80211-backport/uapi \
-I$(STAGING_DIR)/usr/include/mac80211-backport \
-I$(STAGING_DIR)/usr/include/mac80211/uapi \
-I$(STAGING_DIR)/usr/include/mac80211 \
-include backport/backport.h
define Build/Compile
+$(KERNEL_MAKE) $(PKG_JOBS) \
M="$(PKG_BUILD_DIR)/drivers/aic8800" \
KBUILD_EXTRA_SYMBOLS="$(LINUX_DIR)/../symvers/mac80211.symvers" \
NOSTDINC_FLAGS="$(NOSTDINC_FLAGS)" \
CFG80211_VERSION=6.18.26 \
modules
endef
```
The package must depend on `kmod-cfg80211` so its headers and symbol versions
are staged before this driver is built. Keep any additional dependencies,
firmware installation rules and module packaging rules your device needs.
Update the package's pinned source revision to one containing this fix, or
apply the fix as an OpenWrt package patch, then clean and rebuild the package:
```sh
make package/kernel/aic8800d80/clean
make package/kernel/aic8800d80/compile V=sc -j1
```
Changing `CFG80211_VERSION` alone does not update the driver source or the
wireless headers. The value must match the actual wireless stack; do not set
it to the host kernel version or redefine `LINUX_VERSION_CODE`.
## Compatibility scope
The override selects the wireless API changes since Linux 6.12, including
monitor-channel callbacks, radio/link arguments, radar notifications and
newer cfg80211 callbacks. Timer, USB, memory-management and module namespace
checks continue to use the target kernel version. Older target kernels with
newer backports may need additional wireless API adaptations.
Leave `CFG80211_VERSION` unset when building against the kernel's own wireless
stack, as on a regular Ubuntu/Debian installation. The driver then uses the
kernel version as before. Hardware revision still determines whether to use
`main` or `legacy-mcu1`; a wireless API mismatch does not change that choice.
The feeds/Kconfig duplicate definitions and recursive dependencies also
reported in issue #94 belong to the OpenWrt build configuration and require
separate investigation.
See the [build regression recipe](tests/openwrt-backports/README.md) for
the tested kernel/backports combinations and a script to repeat the build.
-24
View File
@@ -47,32 +47,8 @@ I did not develop this software, The code is sourced from the Tenda U11 driver.
### Attention
Before installing the driver, delete all aic8800-related folders under /lib/firmware. Using an incorrect firmware version may cause the system to freeze.
#### Pandora 88M80 mode switching
Pandora 88M80 adapters that initially appear as USB device `1111:1111` are
automatically switched to `a69c:8d80` by sending the required `F3` then `F2`
commands. Existing users must rerun `sudo ./install.sh` to replace the installed
usb_modeswitch configuration, then unplug the adapter completely and plug it
back in.
If automatic switching does not occur, try the same sequence manually:
```bash
sudo usb_modeswitch -v 1111 -p 1111 \
-M "555342438765432100000000000010fd0000000000000000000000000000f3" \
-2 "555342438765432100000000000010fd0000000000000000000000000000f2"
```
This only addresses switching from `1111:1111` to `a69c:8d80`. If the device
has reached `a69c:8d80` but firmware startup still fails, see
[issue #79](https://github.com/shenmintao/aic8800d80/issues/79).
### Installation Steps
For OpenWrt SDK/buildroot builds, see [OpenWrt build notes](OPENWRT.md).
OpenWrt can use a newer cfg80211 backport than its target kernel; these builds
must pass the wireless stack version separately.
#### Method 1: [Quick Installation](INSTALL_SCRIPT.md) (Recommended)
#### Method 2: Manual Installation
-1
View File
@@ -1,6 +1,5 @@
# AIC8800 USB mass-storage mode switch rules
KERNEL=="sd*", ATTRS{idVendor}=="a69c", ATTRS{idProduct}=="5721", SYMLINK+="aicudisk", RUN+="/usr/bin/eject /dev/%k"
KERNEL=="sd*", ATTRS{idVendor}=="a69c", ATTRS{idProduct}=="5722", SYMLINK+="aicudisk", RUN+="/usr/bin/eject /dev/%k"
KERNEL=="sd*", ATTRS{idVendor}=="a69c", ATTRS{idProduct}=="5723", SYMLINK+="tendaudisk", RUN+="/usr/bin/eject /dev/%k"
KERNEL=="sd*", ATTRS{idVendor}=="a69c", ATTRS{idProduct}=="5724", SYMLINK+="ugreenax900", RUN+="/usr/bin/eject /dev/%k"
KERNEL=="sd*", ATTRS{idVendor}=="a69c", ATTRS{idProduct}=="5725", SYMLINK+="tendaudiskv2", RUN+="/usr/bin/eject /dev/%k"
+3 -23
View File
@@ -1,14 +1,9 @@
%global commit c8327eab5be246d4b517afdba034775f00afa988
%global commit 51b7b6e72989afe4d21f52e55b70f5a4d6b21e5b
%global shortcommit %(echo %{commit} | cut -c1-7)
%global snapdate 20260924
%global debug_package %{nil}
%{!?kver:%global kver %(uname -r)}
Name: aic8800d80
# Versions before 2026-09-24 were bare commit hashes, which rpm does not
# order by commit history. Epoch 1 sorts every snapshot version after them.
Epoch: 1
Version: 1.0.0^%{snapdate}git%{shortcommit}
Version: %{shortcommit}
Release: 1%{?dist}
Summary: AIC8800 USB Wi-Fi, Bluetooth firmware, and ZLP quirk driver
@@ -22,7 +17,7 @@ BuildRequires: kernel-devel-uname-r = %{kver}
Requires: kernel-uname-r = %{kver}
Requires: /usr/bin/eject
Requires: usb_modeswitch
Requires: /usr/sbin/usb_modeswitch
Requires(post): /usr/sbin/depmod
Requires(postun): /usr/sbin/depmod
@@ -82,21 +77,6 @@ cp -a fw/aic8800* %{buildroot}/usr/lib/firmware/
/usr/lib/firmware/aic8800*
%changelog
* Thu Sep 24 2026 Shen Mintao <shenmintao@gmail.com> - 1:1.0.0^20260924gitc8327ea-1
- Version snapshots as 1.0.0^<date>git<commit> with Epoch 1. The previous
commit-hash versions do not sort in commit order, so rpm could treat a
newer snapshot as an older package.
* Thu Sep 24 2026 Shen Mintao <shenmintao@gmail.com> - c8327ea-1
- Build the current legacy-mcu1 branch, which carries the Linux 7.2
cfg80211 and strncpy() fixes needed to compile on Bazzite 44.
- Include the monitor packet injection path and the 6.12 stable
set_monitor_channel() fix synchronized from main.
* Wed Jul 29 2026 Shen Mintao <shenmintao@gmail.com> - 51b7b6e-2
- Disable automatic debug package generation for Bazzite builds.
- Require usb_modeswitch by package name for rpm-ostree dependency resolution.
* Sat Jul 25 2026 Shen Mintao <shenmintao@gmail.com> - 51b7b6e-1
- Package the unified installer and ZLP quirk with the legacy MCU1 profiles.
- Preserve the matched D80 and DC/DW firmware and loader combinations.
+2
View File
@@ -61,6 +61,8 @@ endif
###########################################
MAKEFLAGS +=-j$(shell nproc)
KERNEL_AUTOCONF := $(KDIR)/include/config/auto.conf
KERNEL_CONFIG := $(KDIR)/.config
KERNEL_CC_IS_CLANG := $(shell if [ -r "$(KERNEL_AUTOCONF)" ] && grep -q '^CONFIG_CC_IS_CLANG=y' "$(KERNEL_AUTOCONF)"; then echo y; elif [ -r "$(KERNEL_CONFIG)" ] && grep -q '^CONFIG_CC_IS_CLANG=y' "$(KERNEL_CONFIG)"; then echo y; fi)
+3 -19
View File
@@ -2,16 +2,6 @@ EXTRA_CFLAGS += $(USER_EXTRA_CFLAGS)
EXTRA_CFLAGS += -Wno-implicit-fallthrough
#EXTRA_CFLAGS += -Wno-unused-variable
# OpenWrt may build a newer cfg80211 backport on an older kernel.
# Set this to the wireless stack's version, e.g. CFG80211_VERSION=6.18.26.
ifneq ($(strip $(CFG80211_VERSION)),)
aicwf_cfg80211_version := $(subst ., ,$(CFG80211_VERSION))
ifneq ($(words $(aicwf_cfg80211_version)),3)
$(error CFG80211_VERSION must have the form major.minor.patch)
endif
ccflags-y += '-DAICWF_CFG80211_VERSION_CODE=KERNEL_VERSION($(word 1,$(aicwf_cfg80211_version)),$(word 2,$(aicwf_cfg80211_version)),$(word 3,$(aicwf_cfg80211_version)))'
endif
RWNX_VERS_NUM := 6.4.3.0
CONFIG_AIC8800_WLAN_SUPPORT = m
@@ -84,11 +74,7 @@ CONFIG_VHT_FOR_OLD_KERNEL = n
CONFIG_COEX = y
CONFIG_ALIGN_8BYTES = y
CONFIG_TXRX_THREAD_PRIO = y
ifdef CONFIG_ARCH_SUN60IW2P1
CONFIG_USB_ALIGN_DATA = n
else
CONFIG_USB_ALIGN_DATA = y
endif
CONFIG_RX_TASKLET = n
CONFIG_TX_TASKLET = n
CONFIG_RX_NETIF_RECV_SKB = y
@@ -102,11 +88,7 @@ CONFIG_WOWLAN ?= n
CONFIG_USB_RX_AGGR = n
CONFIG_USB_TX_AGGR = n
ifdef CONFIG_ARCH_SUN60IW2P1
CONFIG_USB_NO_TRANS_DMA_MAP = y
else
CONFIG_USB_NO_TRANS_DMA_MAP = n
endif
CONFIG_GPIO_WAKEUP = n
CONFIG_CREATE_TRACE_POINTS = n
CONFIG_SUPPORT_REALTIME_CHANGE_MAC = y
@@ -172,7 +154,7 @@ CONFIG_RWNX_BCMC ?= y
# Enable Monitor+Data interface support (need FW support)
CONFIG_RWNX_MON_DATA =n
CONFIG_RWNX_MON_XMIT ?= y
CONFIG_RWNX_MON_XMIT ?= n
CONFIG_RWNX_MON_RXFILTER ?= n
CONFIG_FILTER_TCP_ACK =y
@@ -367,6 +349,8 @@ ccflags-$(CONFIG_TEMP_CONTROL) += -DCONFIG_TEMP_CONTROL
ccflags-$(CONFIG_POWER_LIMIT) += -DCONFIG_POWER_LIMIT
ccflags-$(CONFIG_EXT_FEM_8800DCDW) += -DCONFIG_EXT_FEM_8800DCDW
ccflags-$(CONFIG_WOWLAN) += -DCONFIG_WOWLAN
MAKEFLAGS +=-j$(shell nproc)
# Platform support list
CONFIG_PLATFORM_ROCKCHIP ?= n
CONFIG_PLATFORM_ALLWINNER ?= n
+4 -4
View File
@@ -1832,7 +1832,7 @@ void set_vendor_extension_ie(char *command){
}
#endif//CONFIG_SET_VENDOR_EXTENSION_IE
#ifdef AICWF_CFG80211_SET_MONITOR_CHANNEL_HAS_DEV
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 13, 0))
int rwnx_cfg80211_set_monitor_channel_(struct wiphy *wiphy, struct net_device *dev,
struct cfg80211_chan_def *chandef);
#else
@@ -1840,7 +1840,7 @@ int rwnx_cfg80211_set_monitor_channel_(struct wiphy *wiphy,
struct cfg80211_chan_def *chandef);
#endif
int rwnx_atoi2(char *value, int c_len);
#ifdef AICWF_CFG80211_SET_MONITOR_CHANNEL_HAS_DEV
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 13, 0))
void set_mon_chan(struct rwnx_vif *vif, struct net_device *dev, char *parameter)
#else
void set_mon_chan(struct rwnx_vif *vif, char *parameter)
@@ -1867,7 +1867,7 @@ void set_mon_chan(struct rwnx_vif *vif, char *parameter)
chandef->center_freq1 = chandef->chan->center_freq;
chandef->center_freq2 = 0;
#ifdef AICWF_CFG80211_SET_MONITOR_CHANNEL_HAS_DEV
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 13, 0))
rwnx_cfg80211_set_monitor_channel_(vif->rwnx_hw->wiphy, dev, chandef);
#else
rwnx_cfg80211_set_monitor_channel_(vif->rwnx_hw->wiphy, chandef);
@@ -2136,7 +2136,7 @@ int android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd)
char *set_parameter;
skip = strlen(CMD_SET_MON_FREQ) + 1;
set_parameter = command + skip;
#ifdef AICWF_CFG80211_SET_MONITOR_CHANNEL_HAS_DEV
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 13, 0))
set_mon_chan(vif, net, set_parameter);
#else
set_mon_chan(vif, set_parameter);
+1 -1
View File
@@ -62,7 +62,7 @@ int get_cs_info(struct rwnx_vif *vif, u8 *mac_addr, u8 *val);
unsigned int command_strtoul(const char *cp, char **endp, unsigned int base);
int str_starts(const char *str, const char *start);
int handle_private_cmd(struct net_device *net, char *command, u32 cmd_len);
#ifdef AICWF_CFG80211_SET_MONITOR_CHANNEL_HAS_DEV
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 13, 0))
void set_mon_chan(struct rwnx_vif *vif, struct net_device *dev, char *parameter);
#else
void set_mon_chan(struct rwnx_vif *vif, char *parameter);
@@ -40,8 +40,7 @@ int rwnx_plat_userconfig_load_8800d80(struct rwnx_hw *rwnx_hw){
char *filename = FW_USERCONFIG_NAME_8800D80;
#ifndef ANDROID_PLATFORM
if (strlcat(aic_fw_path, "/aic8800D80", sizeof(aic_fw_path)) >= sizeof(aic_fw_path))
return -ENAMETOOLONG;
sprintf(aic_fw_path, "%s/%s", aic_fw_path, "aic8800D80");
#endif
AICWFDBG(LOGINFO, "userconfig file path:%s \r\n", filename);
@@ -41,8 +41,7 @@ int rwnx_plat_userconfig_load_8800d80x2(struct rwnx_hw *rwnx_hw){
char *filename = FW_USERCONFIG_NAME_8800D80X2;
#ifndef ANDROID_PLATFORM
if (strlcat(aic_fw_path, "/aic8800D80X2", sizeof(aic_fw_path)) >= sizeof(aic_fw_path))
return -ENAMETOOLONG;
sprintf(aic_fw_path, "%s/%s", aic_fw_path, "aic8800D80X2");
#endif
AICWFDBG(LOGINFO, "userconfig file path:%s \r\n", filename);
+30 -6
View File
@@ -297,6 +297,18 @@ static void aicwf_usb_rx_complete(struct urb *urb)
aicwf_usb_rx_buf_put(usb_dev, usb_buf);
if(urb->status < 0){
AICWFDBG(LOGDEBUG, "%s urb->status:%d \r\n", __func__, urb->status);
if(g_rwnx_plat->wait_disconnect_cb == false){
g_rwnx_plat->wait_disconnect_cb = true;
if(atomic_read(&aicwf_deinit_atomic) > 0){
atomic_set(&aicwf_deinit_atomic, 0);
down(&aicwf_deinit_sem);
AICWFDBG(LOGINFO, "%s need to wait for disconnect callback \r\n", __func__);
}else{
g_rwnx_plat->wait_disconnect_cb = false;
}
}
return;
}else{
//schedule_work(&usb_dev->rx_urb_work);
@@ -373,6 +385,18 @@ static void aicwf_usb_rx_complete(struct urb *urb)
aicwf_usb_rx_buf_put(usb_dev, usb_buf);
if(urb->status < 0){
AICWFDBG(LOGDEBUG, "%s urb->status:%d \r\n", __func__, urb->status);
if(g_rwnx_plat->wait_disconnect_cb == false){
g_rwnx_plat->wait_disconnect_cb = true;
if(atomic_read(&aicwf_deinit_atomic) > 0){
atomic_set(&aicwf_deinit_atomic, 0);
down(&aicwf_deinit_sem);
AICWFDBG(LOGINFO, "%s need to wait for disconnect callback \r\n", __func__);
}else{
g_rwnx_plat->wait_disconnect_cb = false;
}
}
return;
}else{
//schedule_work(&usb_dev->rx_urb_work);
@@ -1955,6 +1979,10 @@ static void aicwf_usb_bus_stop(struct device *dev)
if (usb_dev->state == USB_DOWN_ST)
return;
if(g_rwnx_plat && g_rwnx_plat->wait_disconnect_cb == true){
atomic_set(&aicwf_deinit_atomic, 1);
up(&aicwf_deinit_sem);
}
aicwf_usb_state_change(usb_dev, USB_DOWN_ST);
//aicwf_usb_cancel_all_urbs(usb_dev);//AIDEN
}
@@ -2313,8 +2341,7 @@ static int aicwf_usb_chipmatch(struct aic_usb_dev *usb_dev, u16_l vid, u16_l pid
usb_dev->chipid = PRODUCT_ID_AIC8801;
AICWFDBG(LOGINFO, "%s USE AIC8801\r\n", __func__);
return 0;
}else if(pid == USB_PRODUCT_ID_AIC8800DC || pid == USB_PRODUCT_ID_AIC8800DE
|| pid == USB_PRODUCT_ID_TENDA
}else if(pid == USB_PRODUCT_ID_AIC8800DC || pid == USB_PRODUCT_ID_TENDA
|| pid == USB_PRODUCT_ID_TENDA_U2 || pid == USB_PRODUCT_ID_AIC8800FC_CUS1
|| pid == USB_PRODUCT_ID_AIC8800FC_CUS2 || pid == USB_PRODUCT_ID_AIC8800FC_CUS3
|| pid == USB_PRODUCT_ID_AIC8800FC_CUS4 || pid == USB_PRODUCT_ID_AIC8800FC_CUS5
@@ -2333,8 +2360,7 @@ static int aicwf_usb_chipmatch(struct aic_usb_dev *usb_dev, u16_l vid, u16_l pid
|| pid == USB_PRODUCT_ID_AIC8800M80_CUS3 || pid == USB_PRODUCT_ID_AIC8800M80_CUS4
|| pid == USB_PRODUCT_ID_AIC8800M80_CUS5 || pid == USB_PRODUCT_ID_AIC8800M80_CUS6
|| pid == USB_PRODUCT_ID_AIC8800M80_CUS7 || pid == USB_PRODUCT_ID_AIC8800M80_CUS8
|| pid == USB_PRODUCT_ID_AIC8800D80_UGREEN || pid == USB_PRODUCT_ID_MERCURY
|| pid == USB_PRODUCT_ID_TP){
|| pid == USB_PRODUCT_ID_AIC8800D80_UGREEN || pid == USB_PRODUCT_ID_MERCURY){
usb_dev->chipid = PRODUCT_ID_AIC8800D81;
aicwf_usb_rx_aggr = true;
AICWFDBG(LOGINFO, "%s USE AIC8800D81\r\n", __func__);
@@ -2644,7 +2670,6 @@ static struct usb_device_id aicwf_usb_id_table[] = {
{USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_AIC, USB_PRODUCT_ID_AIC8800D81, 0xff, 0xff, 0xff)},
{USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_AIC, USB_PRODUCT_ID_AIC8800D41, 0xff, 0xff, 0xff)},
{USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_AIC, USB_PRODUCT_ID_AIC8800DC, 0xff, 0xff, 0xff)},
{USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_AIC, USB_PRODUCT_ID_AIC8800DE, 0xff, 0xff, 0xff)},
{USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_TENDA_V2, USB_PRODUCT_ID_TENDA_TX1U_NANO, 0xff, 0xff, 0xff)},
{USB_DEVICE(USB_VENDOR_ID_AIC, USB_PRODUCT_ID_AIC8800DW)},
{USB_DEVICE(USB_VENDOR_ID_AIC, USB_PRODUCT_ID_AIC8800M80_CUS1)},
@@ -2680,7 +2705,6 @@ static struct usb_device_id aicwf_usb_id_table[] = {
{USB_DEVICE(USB_VENDOR_ID_AIC_V2, USB_PRODUCT_ID_AIC8800M80_CUS8)},
{USB_DEVICE(USB_VENDOR_ID_AIC_V2, USB_PRODUCT_ID_AIC8800D80_UGREEN)},
{USB_DEVICE(USB_VENDOR_ID_TP, USB_PRODUCT_ID_MERCURY)},
{USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_TP, USB_PRODUCT_ID_TP, 0xff, 0xff, 0xff)},
#endif
{}
};
-1
View File
@@ -38,7 +38,6 @@
#else
#define USB_PRODUCT_ID_AIC8801 0x8801
#define USB_PRODUCT_ID_AIC8800DC 0x88dc
#define USB_PRODUCT_ID_AIC8800DE 0x88de
#define USB_PRODUCT_ID_AIC8800DW 0x88dd
#define USB_PRODUCT_ID_AIC8800D81 0x8d81
#define USB_PRODUCT_ID_AIC8800D41 0x8d41
@@ -23,33 +23,6 @@
#define _RWNX_COMPAT_H_
#include <linux/version.h>
/* Keep wireless API checks separate from timer, USB and other kernel APIs. */
#ifndef AICWF_CFG80211_VERSION_CODE
#define AICWF_CFG80211_VERSION_CODE LINUX_VERSION_CODE
#endif
/*
* cfg80211_ops.set_monitor_channel() gained a "struct net_device *dev"
* parameter. The change went into mainline 6.13, but it was also
* backported to the 6.12 stable series starting with 6.12.101, so a
* plain ">= 6.13.0" test misses 6.12.101 and later. Those kernels then
* compile against the old prototype, which is fatal with
* -Wincompatible-pointer-types:
*
* rwnx_main.c: error: initialization of
* 'int (*)(struct wiphy *, struct net_device *, struct cfg80211_chan_def *)'
* from incompatible pointer type
* 'int (*)(struct wiphy *, struct cfg80211_chan_def *)'
*
* Debian 13 (6.12.107) is one such kernel. The 6.12.101 threshold
* covers both the backport and mainline, and leaves 6.11 and earlier
* 6.12.x on the old prototype. Keep the check in one place so every
* consumer stays in sync.
*/
#if AICWF_CFG80211_VERSION_CODE >= KERNEL_VERSION(6, 12, 101)
#define AICWF_CFG80211_SET_MONITOR_CHANNEL_HAS_DEV
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0)
#error "Minimum kernel version supported is 3.10"
#endif
+347 -107
View File
@@ -2942,7 +2942,7 @@ bool key_flag = false;
* when adding a group key.
*/
static int rwnx_cfg80211_add_key(struct wiphy *wiphy,
#if AICWF_CFG80211_VERSION_CODE >= KERNEL_VERSION(7, 1, 0)
#if LINUX_VERSION_CODE >= KERNEL_VERSION(7, 1, 0)
struct wireless_dev *wdev,
#else
struct net_device *netdev,
@@ -2954,7 +2954,7 @@ static int rwnx_cfg80211_add_key(struct wiphy *wiphy,
struct key_params *params)
{
struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy);
#if AICWF_CFG80211_VERSION_CODE >= KERNEL_VERSION(7, 1, 0)
#if LINUX_VERSION_CODE >= KERNEL_VERSION(7, 1, 0)
struct rwnx_vif *vif = netdev_priv(wdev->netdev);
#else
struct rwnx_vif *vif = netdev_priv(netdev);
@@ -3066,7 +3066,7 @@ static int rwnx_cfg80211_add_key(struct wiphy *wiphy,
*
*/
static int rwnx_cfg80211_get_key(struct wiphy *wiphy,
#if AICWF_CFG80211_VERSION_CODE >= KERNEL_VERSION(7, 1, 0)
#if LINUX_VERSION_CODE >= KERNEL_VERSION(7, 1, 0)
struct wireless_dev *wdev,
#else
struct net_device *netdev,
@@ -3090,7 +3090,7 @@ static int rwnx_cfg80211_get_key(struct wiphy *wiphy,
* and @key_index, return -ENOENT if the key doesn't exist.
*/
static int rwnx_cfg80211_del_key(struct wiphy *wiphy,
#if AICWF_CFG80211_VERSION_CODE >= KERNEL_VERSION(7, 1, 0)
#if LINUX_VERSION_CODE >= KERNEL_VERSION(7, 1, 0)
struct wireless_dev *wdev,
#else
struct net_device *netdev,
@@ -3102,7 +3102,7 @@ static int rwnx_cfg80211_del_key(struct wiphy *wiphy,
u8 key_index, bool pairwise, const u8 *mac_addr)
{
struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy);
#if AICWF_CFG80211_VERSION_CODE >= KERNEL_VERSION(7, 1, 0)
#if LINUX_VERSION_CODE >= KERNEL_VERSION(7, 1, 0)
struct rwnx_vif *vif = netdev_priv(wdev->netdev);
#else
struct rwnx_vif *vif = netdev_priv(netdev);
@@ -3154,7 +3154,7 @@ static int rwnx_cfg80211_set_default_key(struct wiphy *wiphy,
* @set_default_mgmt_key: set the default management frame key on an interface
*/
static int rwnx_cfg80211_set_default_mgmt_key(struct wiphy *wiphy,
#if AICWF_CFG80211_VERSION_CODE >= KERNEL_VERSION(7, 1, 0)
#if LINUX_VERSION_CODE >= KERNEL_VERSION(7, 1, 0)
struct wireless_dev *wdev,
#else
struct net_device *netdev,
@@ -3249,7 +3249,7 @@ static int rwnx_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
key_params.seq_len = 0;
key_params.cipher = sme->crypto.cipher_group;
rwnx_cfg80211_add_key(wiphy,
#if AICWF_CFG80211_VERSION_CODE >= KERNEL_VERSION(7, 1, 0)
#if LINUX_VERSION_CODE >= KERNEL_VERSION(7, 1, 0)
&rwnx_vif->wdev,
#else
dev,
@@ -3480,7 +3480,7 @@ static int rwnx_cfg80211_external_auth(struct wiphy *wiphy, struct net_device *d
* @add_station: Add a new station.
*/
static int rwnx_cfg80211_add_station(struct wiphy *wiphy,
#if AICWF_CFG80211_VERSION_CODE >= KERNEL_VERSION(7, 1, 0)
#if LINUX_VERSION_CODE >= KERNEL_VERSION(7, 1, 0)
struct wireless_dev *wdev,
#else
struct net_device *dev,
@@ -3493,7 +3493,7 @@ static int rwnx_cfg80211_add_station(struct wiphy *wiphy,
struct station_parameters *params)
{
struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy);
#if AICWF_CFG80211_VERSION_CODE >= KERNEL_VERSION(7, 1, 0)
#if LINUX_VERSION_CODE >= KERNEL_VERSION(7, 1, 0)
struct rwnx_vif *rwnx_vif = netdev_priv(wdev->netdev);
#else
struct rwnx_vif *rwnx_vif = netdev_priv(dev);
@@ -3589,7 +3589,7 @@ static int rwnx_cfg80211_add_station(struct wiphy *wiphy,
sinfo.filled |= STATION_INFO_ASSOC_REQ_IES;
#endif
cfg80211_new_sta(
#if AICWF_CFG80211_VERSION_CODE >= KERNEL_VERSION(7, 1, 0)
#if LINUX_VERSION_CODE >= KERNEL_VERSION(7, 1, 0)
&rwnx_vif->wdev,
#else
rwnx_vif->ndev,
@@ -3620,7 +3620,7 @@ static int rwnx_cfg80211_add_station(struct wiphy *wiphy,
(params->sta_flags_set & BIT(NL80211_STA_FLAG_##f) ? "["#f"]" : "")
netdev_info(
#if AICWF_CFG80211_VERSION_CODE >= KERNEL_VERSION(7, 1, 0)
#if LINUX_VERSION_CODE >= KERNEL_VERSION(7, 1, 0)
wdev->netdev,
#else
dev,
@@ -3651,7 +3651,7 @@ static int rwnx_cfg80211_add_station(struct wiphy *wiphy,
* @del_station: Remove a station
*/
static int rwnx_cfg80211_del_station_compat(struct wiphy *wiphy,
#if AICWF_CFG80211_VERSION_CODE >= KERNEL_VERSION(7, 1, 0)
#if LINUX_VERSION_CODE >= KERNEL_VERSION(7, 1, 0)
struct wireless_dev *wdev,
#else
struct net_device *dev,
@@ -3666,7 +3666,7 @@ static int rwnx_cfg80211_del_station_compat(struct wiphy *wiphy,
)
{
struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy);
#if AICWF_CFG80211_VERSION_CODE >= KERNEL_VERSION(7, 1, 0)
#if LINUX_VERSION_CODE >= KERNEL_VERSION(7, 1, 0)
struct rwnx_vif *rwnx_vif = netdev_priv(wdev->netdev);
#else
struct rwnx_vif *rwnx_vif = netdev_priv(dev);
@@ -3711,7 +3711,7 @@ static int rwnx_cfg80211_del_station_compat(struct wiphy *wiphy,
if(found) {
netdev_info(
#if AICWF_CFG80211_VERSION_CODE >= KERNEL_VERSION(7, 1, 0)
#if LINUX_VERSION_CODE >= KERNEL_VERSION(7, 1, 0)
wdev->netdev,
#else
dev,
@@ -3731,7 +3731,7 @@ static int rwnx_cfg80211_del_station_compat(struct wiphy *wiphy,
}
if (rwnx_vif->wdev.iftype == NL80211_IFTYPE_AP || rwnx_vif->wdev.iftype == NL80211_IFTYPE_P2P_GO) {
cfg80211_del_sta(
#if AICWF_CFG80211_VERSION_CODE >= KERNEL_VERSION(7, 1, 0)
#if LINUX_VERSION_CODE >= KERNEL_VERSION(7, 1, 0)
&rwnx_vif->wdev,
#else
rwnx_vif->ndev,
@@ -3962,7 +3962,7 @@ void apm_probe_sta_work_process(struct work_struct *work)
* cfg80211_check_station_change() to validate the information.
*/
static int rwnx_cfg80211_change_station(struct wiphy *wiphy,
#if AICWF_CFG80211_VERSION_CODE >= KERNEL_VERSION(7, 1, 0)
#if LINUX_VERSION_CODE >= KERNEL_VERSION(7, 1, 0)
struct wireless_dev *wdev,
#else
struct net_device *dev,
@@ -3975,7 +3975,7 @@ static int rwnx_cfg80211_change_station(struct wiphy *wiphy,
struct station_parameters *params)
{
struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy);
#if AICWF_CFG80211_VERSION_CODE >= KERNEL_VERSION(7, 1, 0)
#if LINUX_VERSION_CODE >= KERNEL_VERSION(7, 1, 0)
struct rwnx_vif *vif = netdev_priv(wdev->netdev);
#else
struct rwnx_vif *vif = netdev_priv(dev);
@@ -3988,7 +3988,7 @@ static int rwnx_cfg80211_change_station(struct wiphy *wiphy,
/* Add the TDLS station */
if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER))
{
#if AICWF_CFG80211_VERSION_CODE >= KERNEL_VERSION(7, 1, 0)
#if LINUX_VERSION_CODE >= KERNEL_VERSION(7, 1, 0)
struct rwnx_vif *rwnx_vif = netdev_priv(wdev->netdev);
#else
struct rwnx_vif *rwnx_vif = netdev_priv(dev);
@@ -4064,7 +4064,7 @@ static int rwnx_cfg80211_change_station(struct wiphy *wiphy,
(params->sta_flags_set & BIT(NL80211_STA_FLAG_##f) ? "["#f"]" : "")
netdev_info(
#if AICWF_CFG80211_VERSION_CODE >= KERNEL_VERSION(7, 1, 0)
#if LINUX_VERSION_CODE >= KERNEL_VERSION(7, 1, 0)
wdev->netdev,
#else
dev,
@@ -4353,7 +4353,7 @@ static int rwnx_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *dev)
/* delete any remaining STA*/
while (!list_empty(&rwnx_vif->ap.sta_list)) {
rwnx_cfg80211_del_station_compat(wiphy,
#if AICWF_CFG80211_VERSION_CODE >= KERNEL_VERSION(7, 1, 0)
#if LINUX_VERSION_CODE >= KERNEL_VERSION(7, 1, 0)
&rwnx_vif->wdev,
#else
dev,
@@ -4420,13 +4420,29 @@ cfg80211_chandef_identical(const struct cfg80211_chan_def *chandef1,
}
#endif
#ifdef AICWF_CFG80211_SET_MONITOR_CHANNEL_HAS_DEV
static int rwnx_cfg80211_set_monitor_channel(struct wiphy *wiphy, struct net_device *dev,
struct cfg80211_chan_def *chandef)
#else
static int rwnx_cfg80211_set_monitor_channel(struct wiphy *wiphy,
struct cfg80211_chan_def *chandef)
#endif
#define RWNX_CFG80211_OP_TYPE(_member) \
typeof(((struct cfg80211_ops *)0)->_member)
#define RWNX_CFG80211_OP_MATCH(_member, _type) \
__builtin_types_compatible_p(RWNX_CFG80211_OP_TYPE(_member), _type)
#define RWNX_CFG80211_OP_ASSERT(_member, _callback) \
typedef char rwnx_cfg80211_##_member##_signature_must_match[ \
__builtin_types_compatible_p(RWNX_CFG80211_OP_TYPE(_member), \
typeof(&(_callback))) ? 1 : -1]
typedef int (*rwnx_set_monitor_channel_legacy_t)(
struct wiphy *wiphy, struct cfg80211_chan_def *chandef);
typedef int (*rwnx_set_monitor_channel_dev_t)(
struct wiphy *wiphy, struct net_device *dev,
struct cfg80211_chan_def *chandef);
typedef char rwnx_set_monitor_channel_signature_must_be_supported[
(RWNX_CFG80211_OP_MATCH(set_monitor_channel,
rwnx_set_monitor_channel_legacy_t) ||
RWNX_CFG80211_OP_MATCH(set_monitor_channel,
rwnx_set_monitor_channel_dev_t)) ? 1 : -1];
static int rwnx_cfg80211_set_monitor_channel_common(
struct wiphy *wiphy, struct cfg80211_chan_def *chandef)
{
struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy);
struct rwnx_vif *rwnx_vif;
@@ -4479,19 +4495,40 @@ static int rwnx_cfg80211_set_monitor_channel(struct wiphy *wiphy,
return 0;
}
static int rwnx_cfg80211_set_monitor_channel_legacy(
struct wiphy *wiphy, struct cfg80211_chan_def *chandef)
{
return rwnx_cfg80211_set_monitor_channel_common(wiphy, chandef);
}
#ifdef AICWF_CFG80211_SET_MONITOR_CHANNEL_HAS_DEV
static int rwnx_cfg80211_set_monitor_channel_dev(
struct wiphy *wiphy, struct net_device *dev,
struct cfg80211_chan_def *chandef)
{
(void)dev;
return rwnx_cfg80211_set_monitor_channel_common(wiphy, chandef);
}
#define RWNX_CFG80211_SET_MONITOR_CHANNEL_CB \
__builtin_choose_expr( \
RWNX_CFG80211_OP_MATCH(set_monitor_channel, \
rwnx_set_monitor_channel_dev_t), \
rwnx_cfg80211_set_monitor_channel_dev, \
rwnx_cfg80211_set_monitor_channel_legacy)
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 13, 0))
int rwnx_cfg80211_set_monitor_channel_(struct wiphy *wiphy,
struct net_device *dev,
struct cfg80211_chan_def *chandef)
{
return rwnx_cfg80211_set_monitor_channel(wiphy, dev, chandef);
(void)dev;
return rwnx_cfg80211_set_monitor_channel_common(wiphy, chandef);
}
#else
int rwnx_cfg80211_set_monitor_channel_(struct wiphy *wiphy,
struct cfg80211_chan_def *chandef)
{
return rwnx_cfg80211_set_monitor_channel(wiphy, chandef);
return rwnx_cfg80211_set_monitor_channel_common(wiphy, chandef);
}
#endif
@@ -4553,15 +4590,45 @@ void rwnx_cfg80211_mgmt_frame_register(struct wiphy *wiphy,
* have changed. The actual parameter values are available in
* struct wiphy. If returning an error, no value should be changed.
*/
#if AICWF_CFG80211_VERSION_CODE >= KERNEL_VERSION(6, 17, 0)
static int rwnx_cfg80211_set_wiphy_params(struct wiphy *wiphy, int radio_idx, u32 changed)
#else
static int rwnx_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
#endif
typedef int (*rwnx_set_wiphy_params_legacy_t)(struct wiphy *wiphy,
u32 changed);
typedef int (*rwnx_set_wiphy_params_radio_t)(struct wiphy *wiphy,
int radio_idx, u32 changed);
typedef char rwnx_set_wiphy_params_signature_must_be_supported[
(RWNX_CFG80211_OP_MATCH(set_wiphy_params,
rwnx_set_wiphy_params_legacy_t) ||
RWNX_CFG80211_OP_MATCH(set_wiphy_params,
rwnx_set_wiphy_params_radio_t)) ? 1 : -1];
static int rwnx_cfg80211_set_wiphy_params_common(struct wiphy *wiphy,
u32 changed)
{
(void)wiphy;
(void)changed;
return 0;
}
static int rwnx_cfg80211_set_wiphy_params_legacy(struct wiphy *wiphy,
u32 changed)
{
return rwnx_cfg80211_set_wiphy_params_common(wiphy, changed);
}
static int rwnx_cfg80211_set_wiphy_params_radio(struct wiphy *wiphy,
int radio_idx, u32 changed)
{
(void)radio_idx;
return rwnx_cfg80211_set_wiphy_params_common(wiphy, changed);
}
#define RWNX_CFG80211_SET_WIPHY_PARAMS_CB \
__builtin_choose_expr( \
RWNX_CFG80211_OP_MATCH(set_wiphy_params, \
rwnx_set_wiphy_params_radio_t), \
rwnx_cfg80211_set_wiphy_params_radio, \
rwnx_cfg80211_set_wiphy_params_legacy)
/**
* @set_tx_power: set the transmit power according to the parameters,
@@ -4570,18 +4637,25 @@ static int rwnx_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
* always be %NULL unless the driver supports per-vif TX power
* (as advertised by the nl80211 feature flag.)
*/
static int rwnx_cfg80211_set_tx_power(struct wiphy *wiphy,
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
struct wireless_dev *wdev,
#endif
#if AICWF_CFG80211_VERSION_CODE >= KERNEL_VERSION(6, 17, 0)
int radio_idx,
#endif
enum nl80211_tx_power_setting type, int mbm)
typedef int (*rwnx_set_tx_power_no_wdev_t)(
struct wiphy *wiphy, enum nl80211_tx_power_setting type, int mbm);
typedef int (*rwnx_set_tx_power_wdev_t)(
struct wiphy *wiphy, struct wireless_dev *wdev,
enum nl80211_tx_power_setting type, int mbm);
typedef int (*rwnx_set_tx_power_radio_t)(
struct wiphy *wiphy, struct wireless_dev *wdev, int radio_idx,
enum nl80211_tx_power_setting type, int mbm);
typedef char rwnx_set_tx_power_signature_must_be_supported[
(RWNX_CFG80211_OP_MATCH(set_tx_power, rwnx_set_tx_power_no_wdev_t) ||
RWNX_CFG80211_OP_MATCH(set_tx_power, rwnx_set_tx_power_wdev_t) ||
RWNX_CFG80211_OP_MATCH(set_tx_power,
rwnx_set_tx_power_radio_t)) ? 1 : -1];
static int rwnx_cfg80211_set_tx_power_common(
struct wiphy *wiphy, struct wireless_dev *wdev,
enum nl80211_tx_power_setting type, int mbm)
{
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0)
struct wireless_dev *wdev = NULL;
#endif
struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy);
struct rwnx_vif *vif;
s8 pwr;
@@ -4607,31 +4681,112 @@ int radio_idx,
return res;
}
static int rwnx_cfg80211_get_tx_power(struct wiphy *wiphy,
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
struct wireless_dev *wdev,
#endif
#if AICWF_CFG80211_VERSION_CODE >= KERNEL_VERSION(6, 17, 0)
int radio_idx,
#endif
#if AICWF_CFG80211_VERSION_CODE >= KERNEL_VERSION(6, 14, 0)
unsigned int link_id,
#endif
int *mbm)
static int rwnx_cfg80211_set_tx_power_no_wdev(
struct wiphy *wiphy, enum nl80211_tx_power_setting type, int mbm)
{
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0)
struct wireless_dev *wdev = NULL;
#endif
//struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy);
//struct rwnx_vif *vif;
s8 pwr = 0;
int res = 0;
*mbm = get_txpwr_max(pwr);
return res;
return rwnx_cfg80211_set_tx_power_common(wiphy, NULL, type, mbm);
}
static int rwnx_cfg80211_set_tx_power_wdev(
struct wiphy *wiphy, struct wireless_dev *wdev,
enum nl80211_tx_power_setting type, int mbm)
{
return rwnx_cfg80211_set_tx_power_common(wiphy, wdev, type, mbm);
}
static int rwnx_cfg80211_set_tx_power_radio(
struct wiphy *wiphy, struct wireless_dev *wdev, int radio_idx,
enum nl80211_tx_power_setting type, int mbm)
{
(void)radio_idx;
return rwnx_cfg80211_set_tx_power_common(wiphy, wdev, type, mbm);
}
#define RWNX_CFG80211_SET_TX_POWER_CB \
__builtin_choose_expr( \
RWNX_CFG80211_OP_MATCH(set_tx_power, rwnx_set_tx_power_radio_t), \
rwnx_cfg80211_set_tx_power_radio, \
__builtin_choose_expr( \
RWNX_CFG80211_OP_MATCH(set_tx_power, rwnx_set_tx_power_wdev_t), \
rwnx_cfg80211_set_tx_power_wdev, \
rwnx_cfg80211_set_tx_power_no_wdev))
typedef int (*rwnx_get_tx_power_no_wdev_t)(struct wiphy *wiphy, int *dbm);
typedef int (*rwnx_get_tx_power_wdev_t)(struct wiphy *wiphy,
struct wireless_dev *wdev, int *dbm);
typedef int (*rwnx_get_tx_power_link_t)(struct wiphy *wiphy,
struct wireless_dev *wdev,
unsigned int link_id, int *dbm);
typedef int (*rwnx_get_tx_power_radio_link_t)(
struct wiphy *wiphy, struct wireless_dev *wdev, int radio_idx,
unsigned int link_id, int *dbm);
typedef char rwnx_get_tx_power_signature_must_be_supported[
(RWNX_CFG80211_OP_MATCH(get_tx_power, rwnx_get_tx_power_no_wdev_t) ||
RWNX_CFG80211_OP_MATCH(get_tx_power, rwnx_get_tx_power_wdev_t) ||
RWNX_CFG80211_OP_MATCH(get_tx_power, rwnx_get_tx_power_link_t) ||
RWNX_CFG80211_OP_MATCH(get_tx_power,
rwnx_get_tx_power_radio_link_t)) ? 1 : -1];
static int rwnx_cfg80211_get_tx_power_common(struct wiphy *wiphy,
struct wireless_dev *wdev,
int *dbm)
{
s8 pwr = 0;
(void)wiphy;
(void)wdev;
if (!dbm)
return -EINVAL;
*dbm = get_txpwr_max(pwr);
return 0;
}
static int rwnx_cfg80211_get_tx_power_no_wdev(struct wiphy *wiphy, int *dbm)
{
return rwnx_cfg80211_get_tx_power_common(wiphy, NULL, dbm);
}
static int rwnx_cfg80211_get_tx_power_wdev(struct wiphy *wiphy,
struct wireless_dev *wdev,
int *dbm)
{
return rwnx_cfg80211_get_tx_power_common(wiphy, wdev, dbm);
}
static int rwnx_cfg80211_get_tx_power_link(struct wiphy *wiphy,
struct wireless_dev *wdev,
unsigned int link_id, int *dbm)
{
(void)link_id;
return rwnx_cfg80211_get_tx_power_common(wiphy, wdev, dbm);
}
static int rwnx_cfg80211_get_tx_power_radio_link(
struct wiphy *wiphy, struct wireless_dev *wdev, int radio_idx,
unsigned int link_id, int *dbm)
{
(void)radio_idx;
(void)link_id;
return rwnx_cfg80211_get_tx_power_common(wiphy, wdev, dbm);
}
#define RWNX_CFG80211_GET_TX_POWER_CB \
__builtin_choose_expr( \
RWNX_CFG80211_OP_MATCH(get_tx_power, \
rwnx_get_tx_power_radio_link_t), \
rwnx_cfg80211_get_tx_power_radio_link, \
__builtin_choose_expr( \
RWNX_CFG80211_OP_MATCH(get_tx_power, \
rwnx_get_tx_power_link_t), \
rwnx_cfg80211_get_tx_power_link, \
__builtin_choose_expr( \
RWNX_CFG80211_OP_MATCH(get_tx_power, \
rwnx_get_tx_power_wdev_t), \
rwnx_cfg80211_get_tx_power_wdev, \
rwnx_cfg80211_get_tx_power_no_wdev)))
/**
* @set_power_mgmt: set the power save to one of those two modes:
* Power-save off
@@ -4857,17 +5012,7 @@ rwnx_cfg80211_remain_on_channel(struct wiphy *wiphy,
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0)
enum nl80211_channel_type channel_type,
#endif
unsigned int duration, u64 *cookie
#if AICWF_CFG80211_VERSION_CODE >= KERNEL_VERSION(7, 2, 0)
/*
* 7.2 added an optional receive address filter for the off-channel
* period. cfg80211 refuses a non-NULL one unless the driver sets
* NL80211_EXT_FEATURE_ROC_ADDR_FILTER, which this one does not, so it
* is always NULL here. mac80211 ignores it in the same way.
*/
, const u8 *rx_addr
#endif
)
unsigned int duration, u64 *cookie)
{
return rwnx_cfg80211_remain_on_channel_(wiphy,
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
@@ -5009,11 +5154,7 @@ static int rwnx_cfg80211_get_channel(struct wiphy *wiphy,
if (rwnx_vif->vif_index == rwnx_hw->monitor_vif)
{
//retrieve channel from firmware
#ifdef AICWF_CFG80211_SET_MONITOR_CHANNEL_HAS_DEV
rwnx_cfg80211_set_monitor_channel(wiphy, wdev->netdev, NULL);
#else
rwnx_cfg80211_set_monitor_channel(wiphy, NULL);
#endif
rwnx_cfg80211_set_monitor_channel_common(wiphy, NULL);
}
//Check if channel context is valid
@@ -5200,17 +5341,28 @@ send_frame:
/**
* @start_radar_detection: Start radar detection in the driver.
*/
static
int rwnx_cfg80211_start_radar_detection(struct wiphy *wiphy,
struct net_device *dev,
struct cfg80211_chan_def *chandef
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
, u32 cac_time_ms
#endif
#if (AICWF_CFG80211_VERSION_CODE >= KERNEL_VERSION(6, 12, 0))
, int link_id
#endif
)
typedef int (*rwnx_start_radar_detection_legacy_t)(
struct wiphy *wiphy, struct net_device *dev,
struct cfg80211_chan_def *chandef);
typedef int (*rwnx_start_radar_detection_cac_t)(
struct wiphy *wiphy, struct net_device *dev,
struct cfg80211_chan_def *chandef, u32 cac_time_ms);
typedef int (*rwnx_start_radar_detection_link_t)(
struct wiphy *wiphy, struct net_device *dev,
struct cfg80211_chan_def *chandef, u32 cac_time_ms, int link_id);
typedef char rwnx_start_radar_detection_signature_must_be_supported[
(RWNX_CFG80211_OP_MATCH(start_radar_detection,
rwnx_start_radar_detection_legacy_t) ||
RWNX_CFG80211_OP_MATCH(start_radar_detection,
rwnx_start_radar_detection_cac_t) ||
RWNX_CFG80211_OP_MATCH(start_radar_detection,
rwnx_start_radar_detection_link_t)) ? 1 : -1];
static int rwnx_cfg80211_start_radar_detection_common(
struct wiphy *wiphy, struct net_device *dev,
struct cfg80211_chan_def *chandef, u32 cac_time_ms,
bool start_cac_timer)
{
struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy);
struct rwnx_vif *rwnx_vif = netdev_priv(dev);
@@ -5218,9 +5370,8 @@ int rwnx_cfg80211_start_radar_detection(struct wiphy *wiphy,
printk("%s\n", __func__);
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
rwnx_radar_start_cac(&rwnx_hw->radar, cac_time_ms, rwnx_vif);
#endif
if (start_cac_timer)
rwnx_radar_start_cac(&rwnx_hw->radar, cac_time_ms, rwnx_vif);
rwnx_send_apm_start_cac_req(rwnx_hw, rwnx_vif, chandef, &cfm);
if (cfm.status == CO_OK) {
@@ -5238,6 +5389,42 @@ int rwnx_cfg80211_start_radar_detection(struct wiphy *wiphy,
return 0;
}
static int rwnx_cfg80211_start_radar_detection_legacy(
struct wiphy *wiphy, struct net_device *dev,
struct cfg80211_chan_def *chandef)
{
return rwnx_cfg80211_start_radar_detection_common(
wiphy, dev, chandef, 0, false);
}
static int rwnx_cfg80211_start_radar_detection_cac(
struct wiphy *wiphy, struct net_device *dev,
struct cfg80211_chan_def *chandef, u32 cac_time_ms)
{
return rwnx_cfg80211_start_radar_detection_common(
wiphy, dev, chandef, cac_time_ms, true);
}
static int rwnx_cfg80211_start_radar_detection_link(
struct wiphy *wiphy, struct net_device *dev,
struct cfg80211_chan_def *chandef, u32 cac_time_ms, int link_id)
{
(void)link_id;
return rwnx_cfg80211_start_radar_detection_common(
wiphy, dev, chandef, cac_time_ms, true);
}
#define RWNX_CFG80211_START_RADAR_DETECTION_CB \
__builtin_choose_expr( \
RWNX_CFG80211_OP_MATCH(start_radar_detection, \
rwnx_start_radar_detection_link_t), \
rwnx_cfg80211_start_radar_detection_link, \
__builtin_choose_expr( \
RWNX_CFG80211_OP_MATCH(start_radar_detection, \
rwnx_start_radar_detection_cac_t), \
rwnx_cfg80211_start_radar_detection_cac, \
rwnx_cfg80211_start_radar_detection_legacy))
/**
* @update_ft_ies: Provide updated Fast BSS Transition information to the
* driver. If the SME is in the driver/firmware, this information can be
@@ -5991,7 +6178,7 @@ int rwnx_fill_station_info(struct rwnx_sta *sta, struct rwnx_vif *vif,
* @get_station: get station information for the station identified by @mac
*/
static int rwnx_cfg80211_get_station(struct wiphy *wiphy,
#if AICWF_CFG80211_VERSION_CODE >= KERNEL_VERSION(7, 1, 0)
#if LINUX_VERSION_CODE >= KERNEL_VERSION(7, 1, 0)
struct wireless_dev *wdev,
#else
struct net_device *dev,
@@ -6003,7 +6190,7 @@ static int rwnx_cfg80211_get_station(struct wiphy *wiphy,
#endif
struct station_info *sinfo)
{
#if AICWF_CFG80211_VERSION_CODE >= KERNEL_VERSION(7, 1, 0)
#if LINUX_VERSION_CODE >= KERNEL_VERSION(7, 1, 0)
struct rwnx_vif *vif = netdev_priv(wdev->netdev);
#else
struct rwnx_vif *vif = netdev_priv(dev);
@@ -6041,14 +6228,14 @@ static int rwnx_cfg80211_get_station(struct wiphy *wiphy,
* @dump_station: dump station callback -- resume dump at index @idx
*/
static int rwnx_cfg80211_dump_station(struct wiphy *wiphy,
#if AICWF_CFG80211_VERSION_CODE >= KERNEL_VERSION(7, 1, 0)
#if LINUX_VERSION_CODE >= KERNEL_VERSION(7, 1, 0)
struct wireless_dev *wdev,
#else
struct net_device *dev,
#endif
int idx, u8 *mac, struct station_info *sinfo)
{
#if AICWF_CFG80211_VERSION_CODE >= KERNEL_VERSION(7, 1, 0)
#if LINUX_VERSION_CODE >= KERNEL_VERSION(7, 1, 0)
struct rwnx_vif *rwnx_vif = netdev_priv(wdev->netdev);
#else
struct rwnx_vif *rwnx_vif = netdev_priv(dev);
@@ -6530,6 +6717,59 @@ static int rwnx_cfg80211_leave_mesh(struct wiphy *wiphy, struct net_device *dev)
return 0;
}
/*
* Keep every direct cfg80211_ops assignment as a hard compile-time check.
* OpenWrt can backport cfg80211 APIs without changing LINUX_VERSION_CODE, and
* an incompatible callback must remain a build failure even when warnings are
* relaxed by an external package.
*/
RWNX_CFG80211_OP_ASSERT(add_virtual_intf, rwnx_cfg80211_add_iface);
RWNX_CFG80211_OP_ASSERT(del_virtual_intf, rwnx_cfg80211_del_iface);
RWNX_CFG80211_OP_ASSERT(change_virtual_intf, rwnx_cfg80211_change_iface);
RWNX_CFG80211_OP_ASSERT(start_p2p_device, rwnx_cfgp2p_start_p2p_device);
RWNX_CFG80211_OP_ASSERT(stop_p2p_device, rwnx_cfgp2p_stop_p2p_device);
RWNX_CFG80211_OP_ASSERT(scan, rwnx_cfg80211_scan);
RWNX_CFG80211_OP_ASSERT(connect, rwnx_cfg80211_connect);
RWNX_CFG80211_OP_ASSERT(disconnect, rwnx_cfg80211_disconnect);
RWNX_CFG80211_OP_ASSERT(add_key, rwnx_cfg80211_add_key);
RWNX_CFG80211_OP_ASSERT(get_key, rwnx_cfg80211_get_key);
RWNX_CFG80211_OP_ASSERT(del_key, rwnx_cfg80211_del_key);
RWNX_CFG80211_OP_ASSERT(set_default_key, rwnx_cfg80211_set_default_key);
RWNX_CFG80211_OP_ASSERT(set_default_mgmt_key,
rwnx_cfg80211_set_default_mgmt_key);
RWNX_CFG80211_OP_ASSERT(add_station, rwnx_cfg80211_add_station);
RWNX_CFG80211_OP_ASSERT(del_station, rwnx_cfg80211_del_station_compat);
RWNX_CFG80211_OP_ASSERT(change_station, rwnx_cfg80211_change_station);
RWNX_CFG80211_OP_ASSERT(mgmt_tx, rwnx_cfg80211_mgmt_tx);
RWNX_CFG80211_OP_ASSERT(start_ap, rwnx_cfg80211_start_ap);
RWNX_CFG80211_OP_ASSERT(change_beacon, rwnx_cfg80211_change_beacon);
RWNX_CFG80211_OP_ASSERT(stop_ap, rwnx_cfg80211_stop_ap);
RWNX_CFG80211_OP_ASSERT(probe_client, rwnx_cfg80211_probe_client);
RWNX_CFG80211_OP_ASSERT(set_txq_params, rwnx_cfg80211_set_txq_params);
RWNX_CFG80211_OP_ASSERT(set_power_mgmt, rwnx_cfg80211_set_power_mgmt);
RWNX_CFG80211_OP_ASSERT(get_station, rwnx_cfg80211_get_station);
RWNX_CFG80211_OP_ASSERT(remain_on_channel,
rwnx_cfg80211_remain_on_channel);
RWNX_CFG80211_OP_ASSERT(cancel_remain_on_channel,
rwnx_cfg80211_cancel_remain_on_channel);
RWNX_CFG80211_OP_ASSERT(dump_survey, rwnx_cfg80211_dump_survey);
RWNX_CFG80211_OP_ASSERT(get_channel, rwnx_cfg80211_get_channel);
RWNX_CFG80211_OP_ASSERT(update_ft_ies, rwnx_cfg80211_update_ft_ies);
RWNX_CFG80211_OP_ASSERT(set_cqm_rssi_config,
rwnx_cfg80211_set_cqm_rssi_config);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)
RWNX_CFG80211_OP_ASSERT(channel_switch, rwnx_cfg80211_channel_switch);
#endif
RWNX_CFG80211_OP_ASSERT(change_bss, rwnx_cfg80211_change_bss);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0) || \
defined(CONFIG_WPA3_FOR_OLD_KERNEL)
RWNX_CFG80211_OP_ASSERT(external_auth, rwnx_cfg80211_external_auth);
#endif
#ifdef CONFIG_SCHED_SCAN
RWNX_CFG80211_OP_ASSERT(sched_scan_start, rwnx_cfg80211_sched_scan_start);
RWNX_CFG80211_OP_ASSERT(sched_scan_stop, rwnx_cfg80211_sched_scan_stop);
#endif
static struct cfg80211_ops rwnx_cfg80211_ops = {
.add_virtual_intf = rwnx_cfg80211_add_iface,
.del_virtual_intf = rwnx_cfg80211_del_iface,
@@ -6551,20 +6791,20 @@ static struct cfg80211_ops rwnx_cfg80211_ops = {
.start_ap = rwnx_cfg80211_start_ap,
.change_beacon = rwnx_cfg80211_change_beacon,
.stop_ap = rwnx_cfg80211_stop_ap,
.set_monitor_channel = rwnx_cfg80211_set_monitor_channel,
.set_monitor_channel = RWNX_CFG80211_SET_MONITOR_CHANNEL_CB,
.probe_client = rwnx_cfg80211_probe_client,
// .mgmt_frame_register = rwnx_cfg80211_mgmt_frame_register,
.set_wiphy_params = rwnx_cfg80211_set_wiphy_params,
.set_wiphy_params = RWNX_CFG80211_SET_WIPHY_PARAMS_CB,
.set_txq_params = rwnx_cfg80211_set_txq_params,
.set_tx_power = rwnx_cfg80211_set_tx_power,
.get_tx_power = rwnx_cfg80211_get_tx_power,
.set_tx_power = RWNX_CFG80211_SET_TX_POWER_CB,
.get_tx_power = RWNX_CFG80211_GET_TX_POWER_CB,
.set_power_mgmt = rwnx_cfg80211_set_power_mgmt,
.get_station = rwnx_cfg80211_get_station,
.remain_on_channel = rwnx_cfg80211_remain_on_channel,
.cancel_remain_on_channel = rwnx_cfg80211_cancel_remain_on_channel,
.dump_survey = rwnx_cfg80211_dump_survey,
.get_channel = rwnx_cfg80211_get_channel,
.start_radar_detection = rwnx_cfg80211_start_radar_detection,
.start_radar_detection = RWNX_CFG80211_START_RADAR_DETECTION_CB,
.update_ft_ies = rwnx_cfg80211_update_ft_ies,
.set_cqm_rssi_config = rwnx_cfg80211_set_cqm_rssi_config,
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)
+1 -1
View File
@@ -91,7 +91,7 @@ void aicwf_p2p_alive_timeout(struct timer_list *t);
int rwnx_send_check_p2p(struct cfg80211_scan_request *param);
void apm_staloss_work_process(struct work_struct *work);
void apm_probe_sta_work_process(struct work_struct *work);
#ifdef AICWF_CFG80211_SET_MONITOR_CHANNEL_HAS_DEV
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 13, 0))
int rwnx_cfg80211_set_monitor_channel_(struct wiphy *wiphy,
struct net_device *dev,
struct cfg80211_chan_def *chandef);
@@ -825,9 +825,7 @@ static inline int rwnx_rx_scanu_result_ind(struct rwnx_hw *rwnx_hw,
#endif
}
#ifdef CONFIG_USE_WIRELESS_EXT
putbss:
#endif
if (bss != NULL)
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0)
cfg80211_put_bss(bss);
+1 -7
View File
@@ -4849,13 +4849,7 @@ int rwnx_send_dbg_trigger_req(struct rwnx_hw *rwnx_hw, char *msg)
return -ENOMEM;
/* Set parameters for the MM_DBG_TRIGGER_REQ message */
/*
* strncpy() is gone in 7.2. req->error is a fixed 64-byte field of a
* firmware message that is not NUL-terminated, and the message came
* from kzalloc(), so copying at most the field size is all strncpy()
* did here.
*/
memcpy(req->error, msg, strnlen(msg, sizeof(req->error)));
strncpy(req->error, msg, sizeof(req->error));
/* Send the MM_DBG_TRIGGER_REQ message to LMAC FW */
return rwnx_send_msg(rwnx_hw, req, 0, -1, NULL);
+3 -6
View File
@@ -1669,8 +1669,7 @@ static int rwnx_plat_patch_load(struct rwnx_hw *rwnx_hw)
if(rwnx_hw->usbdev->chipid == PRODUCT_ID_AIC8800DC ||
rwnx_hw->usbdev->chipid == PRODUCT_ID_AIC8800DW){
#ifndef ANDROID_PLATFORM
if (strlcat(aic_fw_path, "/aic8800DC", sizeof(aic_fw_path)) >= sizeof(aic_fw_path))
return -ENAMETOOLONG;
sprintf(aic_fw_path, "%s/%s", aic_fw_path, "aic8800DC");
#endif
AICWFDBG(LOGINFO, "testmode=%d\n", testmode);
if (chip_sub_id == 0) {
@@ -1809,8 +1808,7 @@ static int rwnx_plat_patch_load(struct rwnx_hw *rwnx_hw)
}
} else if(rwnx_hw->usbdev->chipid == PRODUCT_ID_AIC8800D80N) {
#ifndef ANDROID_PLATFORM
if (strlcat(aic_fw_path, "/aic8800D80N", sizeof(aic_fw_path)) >= sizeof(aic_fw_path))
return -ENAMETOOLONG;
sprintf(aic_fw_path, "%s/%s", aic_fw_path, "aic8800D80N");
#endif
if (testmode == FW_NORMAL_MODE) {
ret = aicwf_plat_patch_load_8800d80n(rwnx_hw);
@@ -1840,8 +1838,7 @@ static int rwnx_plat_patch_load(struct rwnx_hw *rwnx_hw)
}
else if(rwnx_hw->usbdev->chipid == PRODUCT_ID_AIC8800DLN) {
#ifndef ANDROID_PLATFORM
if (strlcat(aic_fw_path, "/aic8800DLN", sizeof(aic_fw_path)) >= sizeof(aic_fw_path))
return -ENAMETOOLONG;
sprintf(aic_fw_path, "%s/%s", aic_fw_path, "aic8800DLN");
#endif
if (testmode == FW_NORMAL_MODE) {
aicwf_patch_config_8800dln(rwnx_hw);
+51 -18
View File
@@ -22,6 +22,52 @@
#include "rwnx_events.h"
#include "rwnx_compat.h"
#ifdef CONFIG_RWNX_FULLMAC
/* OpenWrt can backport cfg80211 helpers without changing LINUX_VERSION_CODE. */
typedef void (*rwnx_cfg80211_cac_event_no_chandef_t)(
struct net_device *netdev, enum nl80211_radar_event event, gfp_t gfp);
typedef void (*rwnx_cfg80211_cac_event_chandef_t)(
struct net_device *netdev, const struct cfg80211_chan_def *chandef,
enum nl80211_radar_event event, gfp_t gfp);
typedef void (*rwnx_cfg80211_cac_event_link_t)(
struct net_device *netdev, const struct cfg80211_chan_def *chandef,
enum nl80211_radar_event event, gfp_t gfp, unsigned int link_id);
#define RWNX_CFG80211_CAC_EVENT_MATCH(_type) \
__builtin_types_compatible_p(typeof(&cfg80211_cac_event), _type)
typedef char rwnx_cfg80211_cac_event_signature_must_be_supported[
(RWNX_CFG80211_CAC_EVENT_MATCH(
rwnx_cfg80211_cac_event_no_chandef_t) ||
RWNX_CFG80211_CAC_EVENT_MATCH(rwnx_cfg80211_cac_event_chandef_t) ||
RWNX_CFG80211_CAC_EVENT_MATCH(rwnx_cfg80211_cac_event_link_t)) ? 1 : -1];
static void rwnx_cfg80211_cac_event_compat(
struct net_device *netdev, const struct cfg80211_chan_def *chandef,
enum nl80211_radar_event event, gfp_t gfp)
{
union {
typeof(&cfg80211_cac_event) actual;
rwnx_cfg80211_cac_event_no_chandef_t no_chandef;
rwnx_cfg80211_cac_event_chandef_t chandef;
rwnx_cfg80211_cac_event_link_t link;
} helper = { .actual = &cfg80211_cac_event };
if (RWNX_CFG80211_CAC_EVENT_MATCH(
rwnx_cfg80211_cac_event_no_chandef_t)) {
helper.no_chandef(netdev, event, gfp);
return;
}
if (RWNX_CFG80211_CAC_EVENT_MATCH(rwnx_cfg80211_cac_event_link_t)) {
helper.link(netdev, chandef, event, gfp, 0);
return;
}
helper.chandef(netdev, chandef, event, gfp);
}
#endif
/*
* tolerated deviation of radar time stamp in usecs on both sides
* TODO: this might need to be HW-dependent
@@ -1471,15 +1517,8 @@ static void rwnx_radar_cac_work(struct work_struct *ws)
}
ctxt = &rwnx_hw->chanctx_table[radar->cac_vif->ch_index];
cfg80211_cac_event(radar->cac_vif->ndev,
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
&ctxt->chan_def,
#endif
#if AICWF_CFG80211_VERSION_CODE >= KERNEL_VERSION(6, 12, 0)
NL80211_RADAR_CAC_FINISHED, GFP_KERNEL, 0);
#else
NL80211_RADAR_CAC_FINISHED, GFP_KERNEL);
#endif
rwnx_cfg80211_cac_event_compat(radar->cac_vif->ndev, &ctxt->chan_def,
NL80211_RADAR_CAC_FINISHED, GFP_KERNEL);
rwnx_send_apm_stop_cac_req(rwnx_hw, radar->cac_vif);
rwnx_chanctx_unlink(radar->cac_vif);
@@ -1613,15 +1652,9 @@ void rwnx_radar_cancel_cac(struct rwnx_radar *radar)
struct rwnx_chanctx *ctxt;
ctxt = &rwnx_hw->chanctx_table[radar->cac_vif->ch_index];
rwnx_send_apm_stop_cac_req(rwnx_hw, radar->cac_vif);
cfg80211_cac_event(radar->cac_vif->ndev,
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
&ctxt->chan_def,
#endif
#if AICWF_CFG80211_VERSION_CODE >= KERNEL_VERSION(6, 12, 0)
NL80211_RADAR_CAC_FINISHED, GFP_KERNEL, 0);
#else
NL80211_RADAR_CAC_ABORTED, GFP_KERNEL);
#endif
rwnx_cfg80211_cac_event_compat(radar->cac_vif->ndev,
&ctxt->chan_def,
NL80211_RADAR_CAC_ABORTED, GFP_KERNEL);
rwnx_chanctx_unlink(radar->cac_vif);
}
+61 -31
View File
@@ -34,6 +34,60 @@
#define IEEE80211_MAX_CHAINS 4
#endif
/* OpenWrt can backport these helpers without changing LINUX_VERSION_CODE. */
typedef bool (*rwnx_cfg80211_rx_frame_legacy_t)(struct net_device *dev,
const u8 *addr, gfp_t gfp);
typedef bool (*rwnx_cfg80211_rx_frame_link_t)(struct net_device *dev,
const u8 *addr, int link_id,
gfp_t gfp);
#define RWNX_CFG80211_HELPER_MATCH(_helper, _type) \
__builtin_types_compatible_p(typeof(&(_helper)), _type)
typedef char rwnx_cfg80211_rx_spurious_frame_signature_must_be_supported[
(RWNX_CFG80211_HELPER_MATCH(cfg80211_rx_spurious_frame,
rwnx_cfg80211_rx_frame_legacy_t) ||
RWNX_CFG80211_HELPER_MATCH(cfg80211_rx_spurious_frame,
rwnx_cfg80211_rx_frame_link_t)) ? 1 : -1];
typedef char rwnx_cfg80211_rx_unexpected_4addr_frame_signature_must_be_supported[
(RWNX_CFG80211_HELPER_MATCH(cfg80211_rx_unexpected_4addr_frame,
rwnx_cfg80211_rx_frame_legacy_t) ||
RWNX_CFG80211_HELPER_MATCH(cfg80211_rx_unexpected_4addr_frame,
rwnx_cfg80211_rx_frame_link_t)) ? 1 : -1];
static bool rwnx_cfg80211_rx_spurious_frame_compat(struct net_device *dev,
const u8 *addr, gfp_t gfp)
{
union {
typeof(&cfg80211_rx_spurious_frame) actual;
rwnx_cfg80211_rx_frame_legacy_t legacy;
rwnx_cfg80211_rx_frame_link_t link;
} helper = { .actual = &cfg80211_rx_spurious_frame };
if (RWNX_CFG80211_HELPER_MATCH(cfg80211_rx_spurious_frame,
rwnx_cfg80211_rx_frame_link_t))
return helper.link(dev, addr, -1, gfp);
return helper.legacy(dev, addr, gfp);
}
static bool rwnx_cfg80211_rx_unexpected_4addr_frame_compat(
struct net_device *dev, const u8 *addr, gfp_t gfp)
{
union {
typeof(&cfg80211_rx_unexpected_4addr_frame) actual;
rwnx_cfg80211_rx_frame_legacy_t legacy;
rwnx_cfg80211_rx_frame_link_t link;
} helper = { .actual = &cfg80211_rx_unexpected_4addr_frame };
if (RWNX_CFG80211_HELPER_MATCH(cfg80211_rx_unexpected_4addr_frame,
rwnx_cfg80211_rx_frame_link_t))
return helper.link(dev, addr, -1, gfp);
return helper.legacy(dev, addr, gfp);
}
u8 dhcped = 0;
u16 tx_legrates_lut_rate[] = {
@@ -2283,11 +2337,6 @@ u8 rwnx_rxdataind_aicwf(struct rwnx_hw *rwnx_hw, void *hostid, void *rx_priv)
if(hw_rxhdr->flags_upload)
status |= RX_STAT_FORWARD;
#ifndef CONFIG_RWNX_MON_DATA
if (status & RX_STAT_MONITOR)
status &= ~RX_STAT_FORWARD;
#endif
/* Check if we need to delete the buffer */
if (status & RX_STAT_DELETE) {
/* Remove the SK buffer from the rxbuf_elems table */
@@ -2350,24 +2399,13 @@ u8 rwnx_rxdataind_aicwf(struct rwnx_hw *rwnx_hw, void *hostid, void *rx_priv)
} else {
#ifdef CONFIG_RWNX_MON_DATA
skb_monitor = skb_copy_expand(skb, rtap_len, 0, GFP_ATOMIC);
if (skb_monitor) {
skb_monitor->data += (msdu_offset + 2); //sdio/usb word allign
skb_monitor->data += (msdu_offset + 2); //sdio/usb word allign
//Save frame length
frm_len = le32_to_cpu(hw_rxhdr->hwvect.len);
}
//Save frame length
frm_len = le32_to_cpu(hw_rxhdr->hwvect.len);
#endif
}
if (!skb_monitor) {
if (status == RX_STAT_MONITOR) {
dev_kfree_skb(skb);
goto end;
}
goto check_len_update;
}
//skb_reset_tail_pointer(skb);
//skb->len = 0;
skb_reset_tail_pointer(skb_monitor);
@@ -2410,11 +2448,8 @@ check_len_update:
hdr = (struct ieee80211_hdr *)(skb->data + msdu_offset);
rwnx_vif = rwnx_rx_get_vif(rwnx_hw, hw_rxhdr->flags_vif_idx);
if (rwnx_vif) {
#if AICWF_CFG80211_VERSION_CODE >= KERNEL_VERSION(6, 17, 0)
cfg80211_rx_spurious_frame(rwnx_vif->ndev, hdr->addr2, -1, GFP_ATOMIC);
#else
cfg80211_rx_spurious_frame(rwnx_vif->ndev, hdr->addr2, GFP_ATOMIC);
#endif
rwnx_cfg80211_rx_spurious_frame_compat(rwnx_vif->ndev,
hdr->addr2, GFP_ATOMIC);
}
goto end;
}
@@ -2757,13 +2792,8 @@ check_len_update:
if (hw_rxhdr->flags_is_4addr && !rwnx_vif->use_4addr) {
printk("aicwf: 4addr flag error\n");
#if AICWF_CFG80211_VERSION_CODE >= KERNEL_VERSION(6, 17, 0)
cfg80211_rx_unexpected_4addr_frame(rwnx_vif->ndev,
sta->mac_addr, -1, GFP_ATOMIC);
#else
cfg80211_rx_unexpected_4addr_frame(rwnx_vif->ndev,
sta->mac_addr, GFP_ATOMIC);
#endif
rwnx_cfg80211_rx_unexpected_4addr_frame_compat(
rwnx_vif->ndev, sta->mac_addr, GFP_ATOMIC);
}
}
+2 -2
View File
@@ -115,8 +115,8 @@ rwnx_prep_tdls_direct(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif,
switch (action_code) {
case WLAN_PUB_ACTION_TDLS_DISCOVER_RES:
#if AICWF_CFG80211_VERSION_CODE >= KERNEL_VERSION(7, 1, 0)
skb_put(skb, 2 + sizeof(mgmt->u.action.tdls_discover_resp));
#if LINUX_VERSION_CODE >= KERNEL_VERSION(7, 1, 0)
skb_put(skb, 1 + sizeof(mgmt->u.action.tdls_discover_resp));
mgmt->u.action.category = WLAN_CATEGORY_PUBLIC;
mgmt->u.action.action_code = WLAN_PUB_ACTION_TDLS_DISCOVER_RES;
mgmt->u.action.tdls_discover_resp.dialog_token = dialog_token;
+19 -22
View File
@@ -1991,7 +1991,7 @@ free_use:
netdev_tx_t rwnx_start_monitor_if_xmit(struct sk_buff *skb, struct net_device *dev)
{
int rtap_len, ret, idx;
int rtap_len, ret, idx, tmp_len;
struct ieee80211_radiotap_header *rtap_hdr; // net/ieee80211_radiotap.h
struct ieee80211_radiotap_iterator iterator; // net/cfg80211.h
u8_l *rtap_buf = (u8_l *)skb->data;
@@ -2012,29 +2012,9 @@ netdev_tx_t rwnx_start_monitor_if_xmit(struct sk_buff *skb, struct net_device *d
bool offchan = false;
int nx_off_chan_txq_idx = NX_OFF_CHAN_TXQ_IDX;
frame_len = skb->len;
if (unlikely(skb->len < sizeof(*rtap_hdr))) {
AICWFDBG(LOGERROR, "%s radiotap header is truncated\n", __func__);
goto free_tag;
}
rtap_hdr = (struct ieee80211_radiotap_header*)(rtap_buf);
if (unlikely(rtap_hdr->it_version)) {
AICWFDBG(LOGERROR, "%s itv \r\n", __func__);
goto free_tag;
}
rtap_len = ieee80211_get_radiotap_len(rtap_buf);//max_length
if (unlikely(rtap_len < sizeof(*rtap_hdr))) {
AICWFDBG(LOGERROR, "%s rtap_len < sizeof(struct ieee80211_radiotap_header) \r\n", __func__);
goto free_tag;
}
if (unlikely(skb->len < rtap_len)) {
AICWFDBG(LOGERROR, "%s skb->len < rtap_len \r\n", __func__);
goto free_tag;
}
frame_len = skb->len;
AICWFDBG(LOGINFO, "rwnx_start_monitor_if_xmit, skb_len=%d, rtap_len=%d\n", skb->len, rtap_len);
//rwnx_data_dump((char*)__func__, skb->data, skb->len);
@@ -2043,6 +2023,23 @@ netdev_tx_t rwnx_start_monitor_if_xmit(struct sk_buff *skb, struct net_device *d
g_rwnx_plat->usbdev->chipid == PRODUCT_ID_AIC8800DW) && chip_id < 3)){
nx_off_chan_txq_idx = NX_OFF_CHAN_TXQ_IDX_FOR_OLD_IC;
}
if (unlikely(rtap_hdr->it_version)){
AICWFDBG(LOGERROR, "%s itv \r\n", __func__);
goto free_tag;
}
if (unlikely(skb->len < rtap_len)){
AICWFDBG(LOGERROR, "%s skb->len < rtap_len \r\n", __func__);
goto free_tag;
}
if (unlikely(rtap_len < sizeof(struct ieee80211_radiotap_header))){
AICWFDBG(LOGERROR, "%s rtap_len < sizeof(struct ieee80211_radiotap_header) \r\n", __func__);
goto free_tag;
}
frame_len -= rtap_len;
pframe = rtap_buf + rtap_len;
+1 -2
View File
@@ -172,8 +172,7 @@ int rwnx_start_mgmt_xmit(struct rwnx_vif *vif, struct rwnx_sta *sta,
u64 *cookie);
#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) */
#ifdef CONFIG_RWNX_MON_XMIT
netdev_tx_t rwnx_start_monitor_if_xmit(struct sk_buff *skb,
struct net_device *dev);
int rwnx_start_monitor_if_xmit(struct sk_buff *skb, struct net_device *dev);
#endif
int rwnx_txdatacfm(void *pthis, void *host_id);
@@ -149,11 +149,7 @@ static int usb_submit_urb_pre_handler(struct kprobe *p, struct pt_regs *regs)
(void)p;
#if defined(CONFIG_ARM)
urb = (struct urb *)regs->ARM_r0;
#else
urb = (struct urb *)regs_get_kernel_argument(regs, 0);
#endif
if (is_bluetooth_acl_endpoint(urb))
enable_zlp(urb);
-44
View File
@@ -1,44 +0,0 @@
# OpenWrt backports build regression
This checks complete module compilation and MODPOST against real kernel and
wireless-stack headers. It requires an already prepared SDK/buildroot with
cfg80211/mac80211 headers and `mac80211.symvers` staged. It does not install
packages or load modules.
For the x86_64 SDK used in issue #94:
```sh
sdk=/path/to/openwrt-sdk
kernel="$sdk/build_dir/target-x86_64_musl/linux-x86_64/linux-6.12.94"
export STAGING_DIR="$sdk/staging_dir/target-x86_64_musl"
export PATH="$sdk/staging_dir/toolchain-x86_64_gcc-14.3.0_musl/bin:$PATH"
bash tests/openwrt-backports/build.sh \
"$kernel" "$STAGING_DIR/usr/include" \
"$kernel/../symvers/mac80211.symvers" 6.18.26 \
ARCH=x86_64 CROSS_COMPILE=x86_64-openwrt-linux-musl-
```
The script copies the current driver into a fresh temporary directory and
checks that all three `.ko` files are produced. Additional make arguments
can select a compiler or architecture. Use matching headers, configuration
and symbol versions throughout; changing only the version argument is not
a substitute for the matching wireless stack.
## Verified on 2026-09-17
- OpenWrt 25.12.5 x86_64 SDK: Linux 6.12.94, GCC 14.3.0, backports 6.18.26
with the mac80211 patches from OpenWrt revision `f5dae5ece4` applied:
all three modules compile and pass MODPOST with the kernel's `-Werror`.
- Original driver revision `9594c5c`, on the same kernel/backports combination:
reproduces both RX argument-count errors and the four incompatible
`set_monitor_channel`, `set_wiphy_params`, `set_tx_power`, `get_tx_power`
callbacks. This comparison uses `-Wno-error=unused-label`, as the issue's
log does, to reach those failures. The fixed build needs no such override.
- Native kernel headers 6.11.0-17, 6.17.0-14 and 7.2.0-070200, with
`CFG80211_VERSION` unset: all three modules compile and pass MODPOST.
The 7.2 check uses GCC 14 and reports compiler/attribute warnings because
those headers were built with GCC 15.
These are build checks. They do not validate an installable OpenWrt package,
firmware loading, Wi-Fi connectivity or Bluetooth operation on hardware.
-41
View File
@@ -1,41 +0,0 @@
#!/usr/bin/env bash
# Compile a source copy against a prepared kernel and staged wireless backport.
# Leaves the build directory for inspection; does not install or load modules.
set -euo pipefail
if [ "$#" -lt 4 ]; then
echo "Usage: $0 KERNEL_BUILD_DIR STAGED_INCLUDE_DIR MAC80211_SYMVERS CFG80211_VERSION [make arguments...]" >&2
exit 2
fi
kernel_dir=$(realpath "$1")
include_dir=$(realpath "$2")
symvers=$(realpath "$3")
wireless_version=$4
shift 4
for required in "$kernel_dir/Makefile" "$kernel_dir/Module.symvers" \
"$include_dir/mac80211/net/cfg80211.h" \
"$include_dir/mac80211-backport/backport/autoconf.h" "$symvers"; do
if [ ! -f "$required" ]; then
echo "Missing build input: $required" >&2
exit 2
fi
done
repo_dir=$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)
build_dir=$(mktemp -d "${TMPDIR:-/tmp}/aic8800-backports.XXXXXX")
cp -a "$repo_dir/drivers/aic8800/." "$build_dir/"
echo "Build directory: $build_dir"
make -C "$kernel_dir" M="$build_dir" \
NOSTDINC_FLAGS="-I$include_dir/mac80211-backport/uapi -I$include_dir/mac80211-backport -I$include_dir/mac80211/uapi -I$include_dir/mac80211 -include backport/backport.h" \
KBUILD_EXTRA_SYMBOLS="$symvers" \
CFG80211_VERSION="$wireless_version" \
-j"${JOBS:-2}" "$@" modules
for module in aic_load_fw/aic_load_fw.ko aic8800_fdrv/aic8800_fdrv.ko \
aic_zlp_quirk/aic_zlp_quirk.ko; do
test -s "$build_dir/$module"
done
echo "All three modules built successfully in $build_dir"
+3 -5
View File
@@ -2,8 +2,8 @@
# Sends vendor-specific SCSI CDB to trigger mode switch from
# USB Mass Storage to WiFi+BT mode.
#
# The two 16-byte CDBs end in F3 and F2 respectively. Each is wrapped in a
# standard 31-byte SCSI CBW (Command Block Wrapper), and must be sent in order.
# The 16-byte CDB is: FD 00 00 00 00 00 00 00 00 00 00 00 00 00 00 F2
# Wrapped in a standard 31-byte SCSI CBW (Command Block Wrapper).
#
# Install as: /etc/usb_modeswitch.d/1111:1111
# (The filename must contain a colon on Linux; this file is named
@@ -13,6 +13,4 @@ DefaultVendor=0x1111
DefaultProduct=0x1111
TargetVendor=0xa69c
TargetProduct=0x8d80
MessageContent="555342438765432100000000000010fd0000000000000000000000000000f3"
MessageContent2="555342438765432100000000000010fd0000000000000000000000000000f2"
NeedResponse=1
MessageContent="555342438765432100000000000010fd0000000000000000000000000000f2"