From a827d291bbd915a36d3877174138aa7416e156b4 Mon Sep 17 00:00:00 2001 From: Shen Mintao Date: Mon, 19 Oct 2026 11:31:26 +0800 Subject: [PATCH] fix: select monitor-channel callback from cfg80211 header type Keep the internal monitor-channel API independent of kernel versions and select a correctly typed cfg80211 adapter at compile time. This covers Ubuntu 6.8.0-147 and stable/backports without release-string heuristics or function-pointer casts. Validation: reproduced the original failure on Ubuntu 6.8.0-147; all three modules build on 6.8.0-146, 6.8.0-147 and 6.17.0-14. Fixes #107. --- OPENWRT.md | 6 ++-- drivers/aic8800/aic8800_fdrv/aic_priv_cmd.c | 17 ----------- drivers/aic8800/aic8800_fdrv/aic_priv_cmd.h | 4 --- drivers/aic8800/aic8800_fdrv/rwnx_compat.h | 22 -------------- drivers/aic8800/aic8800_fdrv/rwnx_main.c | 32 +++++++++------------ drivers/aic8800/aic8800_fdrv/rwnx_main.h | 6 ---- 6 files changed, 18 insertions(+), 69 deletions(-) diff --git a/OPENWRT.md b/OPENWRT.md index 1603a4e..dd4bfbb 100644 --- a/OPENWRT.md +++ b/OPENWRT.md @@ -49,8 +49,10 @@ 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 +radio/link arguments, radar notifications and newer cfg80211 callbacks. +The monitor-channel callback is selected from the actual cfg80211 header type +so distribution backports also work without changing the version override. +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. diff --git a/drivers/aic8800/aic8800_fdrv/aic_priv_cmd.c b/drivers/aic8800/aic8800_fdrv/aic_priv_cmd.c index f5b15dd..b7001ad 100644 --- a/drivers/aic8800/aic8800_fdrv/aic_priv_cmd.c +++ b/drivers/aic8800/aic8800_fdrv/aic_priv_cmd.c @@ -1832,19 +1832,10 @@ void set_vendor_extension_ie(char *command){ } #endif//CONFIG_SET_VENDOR_EXTENSION_IE -#ifdef AICWF_CFG80211_SET_MONITOR_CHANNEL_HAS_DEV -int rwnx_cfg80211_set_monitor_channel_(struct wiphy *wiphy, struct net_device *dev, - struct cfg80211_chan_def *chandef); -#else 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 -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) -#endif { struct cfg80211_chan_def *chandef = NULL; int freq = 0; @@ -1867,11 +1858,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 - rwnx_cfg80211_set_monitor_channel_(vif->rwnx_hw->wiphy, dev, chandef); -#else rwnx_cfg80211_set_monitor_channel_(vif->rwnx_hw->wiphy, chandef); -#endif vfree(chandef->chan); vfree(chandef); @@ -2136,11 +2123,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 - set_mon_chan(vif, net, set_parameter); -#else set_mon_chan(vif, set_parameter); -#endif ret = 0; goto exit; } diff --git a/drivers/aic8800/aic8800_fdrv/aic_priv_cmd.h b/drivers/aic8800/aic8800_fdrv/aic_priv_cmd.h index a126c2d..8d58e1e 100644 --- a/drivers/aic8800/aic8800_fdrv/aic_priv_cmd.h +++ b/drivers/aic8800/aic8800_fdrv/aic_priv_cmd.h @@ -62,11 +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 -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); -#endif #endif /* _AIC_PRIV_CMD_H_ */ diff --git a/drivers/aic8800/aic8800_fdrv/rwnx_compat.h b/drivers/aic8800/aic8800_fdrv/rwnx_compat.h index d5737bc..f2e8eb3 100644 --- a/drivers/aic8800/aic8800_fdrv/rwnx_compat.h +++ b/drivers/aic8800/aic8800_fdrv/rwnx_compat.h @@ -28,28 +28,6 @@ #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 diff --git a/drivers/aic8800/aic8800_fdrv/rwnx_main.c b/drivers/aic8800/aic8800_fdrv/rwnx_main.c index 31a010f..fca3237 100644 --- a/drivers/aic8800/aic8800_fdrv/rwnx_main.c +++ b/drivers/aic8800/aic8800_fdrv/rwnx_main.c @@ -4451,13 +4451,8 @@ 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 { struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); struct rwnx_vif *rwnx_vif; @@ -4511,21 +4506,19 @@ static int rwnx_cfg80211_set_monitor_channel(struct wiphy *wiphy, } -#ifdef AICWF_CFG80211_SET_MONITOR_CHANNEL_HAS_DEV -int rwnx_cfg80211_set_monitor_channel_(struct wiphy *wiphy, - struct net_device *dev, - struct cfg80211_chan_def *chandef) +/* Newer cfg80211 stacks pass dev; the firmware still has one monitor vif. */ +static int rwnx_cfg80211_set_monitor_channel_with_dev(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_chan_def *chandef) { - return rwnx_cfg80211_set_monitor_channel(wiphy, dev, chandef); + return rwnx_cfg80211_set_monitor_channel(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); } -#endif - /** * @probe_peer: probe an associated client. Before 7.3 the driver returns a @@ -5119,11 +5112,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 } //Check if channel context is valid @@ -6677,7 +6666,14 @@ 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, + /* Select the actual header ABI, including distro/stable backports such + * as Ubuntu 6.8.0-147 and Linux 6.12.101. No function-pointer casts. */ + .set_monitor_channel = __builtin_choose_expr( + __builtin_types_compatible_p( + typeof(((struct cfg80211_ops *)0)->set_monitor_channel), + typeof(&rwnx_cfg80211_set_monitor_channel_with_dev)), + rwnx_cfg80211_set_monitor_channel_with_dev, + rwnx_cfg80211_set_monitor_channel), #if AICWF_CFG80211_VERSION_CODE >= KERNEL_VERSION(7, 3, 0) .probe_peer = rwnx_cfg80211_probe_client, #else diff --git a/drivers/aic8800/aic8800_fdrv/rwnx_main.h b/drivers/aic8800/aic8800_fdrv/rwnx_main.h index 1cbd95d..1788740 100644 --- a/drivers/aic8800/aic8800_fdrv/rwnx_main.h +++ b/drivers/aic8800/aic8800_fdrv/rwnx_main.h @@ -91,14 +91,8 @@ 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 -int rwnx_cfg80211_set_monitor_channel_(struct wiphy *wiphy, - struct net_device *dev, - struct cfg80211_chan_def *chandef); -#else int rwnx_cfg80211_set_monitor_channel_(struct wiphy *wiphy, struct cfg80211_chan_def *chandef); -#endif #if AICWF_CFG80211_VERSION_CODE >= KERNEL_VERSION(7, 3, 0) int rwnx_cfg80211_probe_client(struct wiphy *wiphy, struct net_device *dev, const u8 *peer, u64 cookie);