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.
This commit is contained in:
Shen Mintao committed 2026-10-19 11:32:32 +08:00
1 parent 1d1b8fff46
commit eef3d25ca4
6 files changed
+16 -67

No files matched your search

+4 -2
View File
@@ -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.
@@ -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;
}
@@ -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_ */
@@ -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
+12 -16
View File
@@ -4420,13 +4420,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;
@@ -4480,21 +4475,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,
/* 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_client: probe an associated client, must return a cookie that it
@@ -5009,11 +5002,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
@@ -6551,7 +6540,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),
.probe_client = rwnx_cfg80211_probe_client,
// .mgmt_frame_register = rwnx_cfg80211_mgmt_frame_register,
.set_wiphy_params = rwnx_cfg80211_set_wiphy_params,
-6
View File
@@ -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
int rwnx_cfg80211_probe_client(struct wiphy *wiphy, struct net_device *dev,
const u8 *peer, u64 *cookie);
void rwnx_cfg80211_mgmt_frame_register(struct wiphy *wiphy,