From 154cdb82e33f6e44a7c088642a373745b01ce145 Mon Sep 17 00:00:00 2001 From: Theo Debrouwere Date: Mon, 24 Apr 2023 13:26:32 +0200 Subject: [PATCH 1/3] Bugfix: fix active roaming capability. According to the makefile, it should be possible to keep roaming active: Set #bit2 of CONFIG_ROAMING_FLAG, like this: CONFIG_ROAMING_FLAG = 0x7 But, when trying out this option, it appears that active roaming is not working as expected. It only changes if the old AP is expired. This patch fixes this behaviour, but does NOT set BIT2. Reason for failure: The linked_status_chk function runs every 2 seconds. There is an internal roaming flag (need_to_roam) that is set when the current signal is below a threshold AND if it hasn't been set during a predefined time. Setting the flag also updates the last_time_roaming timestamp. If either of these fails, then the flag (need_to_roam) is cleared. This causes a race condition: 1) Threshold is too low + long last_time_roaming -> flag is set + last_time_roaming is updated. 2) Chipset starts scanning / surveying (this takes > 3 sec) 3) Conditions are rechecked: threshold is still to low, but last_time_roaming is now too recent -> flag is cleared. 4) Survey finishes, but since the flag is cleared, roaming will be ignored. The solution in this patch: Once the flag (need_to_roam) has been set, it should only be cleared if the signal strength is above the threshold. It should not be cleared based on the last_time_roaming timestamp. --- core/rtw_mlme_ext.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/core/rtw_mlme_ext.c b/core/rtw_mlme_ext.c index 5fa2000..ebb93e5 100644 --- a/core/rtw_mlme_ext.c +++ b/core/rtw_mlme_ext.c @@ -12799,14 +12799,15 @@ void linked_status_chk(_adapter *padapter, u8 from_timer) #elif defined(CONFIG_LAYER2_ROAMING) if (rtw_chk_roam_flags(padapter, RTW_ROAM_ACTIVE)) { RTW_INFO("signal_strength_data.avg_val = %d\n", precvpriv->signal_strength_data.avg_val); - if ((precvpriv->signal_strength_data.avg_val < pmlmepriv->roam_rssi_threshold) - && (rtw_get_passing_time_ms(pmlmepriv->last_roaming) >= pmlmepriv->roam_scan_int*2000)) { + if (precvpriv->signal_strength_data.avg_val < pmlmepriv->roam_rssi_threshold) { + if (rtw_get_passing_time_ms(pmlmepriv->last_roaming) >= pmlmepriv->roam_scan_int*2000) { #ifdef CONFIG_RTW_80211K - rtw_roam_nb_discover(padapter, _FALSE); + rtw_roam_nb_discover(padapter, _FALSE); #endif - pmlmepriv->need_to_roam = _TRUE; - rtw_drv_scan_by_self(padapter, RTW_AUTO_SCAN_REASON_ROAM); - pmlmepriv->last_roaming = rtw_get_current_time(); + pmlmepriv->need_to_roam = _TRUE; + rtw_drv_scan_by_self(padapter, RTW_AUTO_SCAN_REASON_ROAM); + pmlmepriv->last_roaming = rtw_get_current_time(); + } } else pmlmepriv->need_to_roam = _FALSE; } From d239b9105d9b5d884a5a459bd6096a3342eb8475 Mon Sep 17 00:00:00 2001 From: Theo Debrouwere Date: Mon, 24 Apr 2023 16:18:10 +0200 Subject: [PATCH 2/3] Improve roaming documentation. Improve existing documentation. Add documentation to undocumented variables. --- include/rtw_mlme.h | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/include/rtw_mlme.h b/include/rtw_mlme.h index e3095a5..6d48fba 100644 --- a/include/rtw_mlme.h +++ b/include/rtw_mlme.h @@ -539,9 +539,9 @@ struct tdls_txmgmt { /* used for mlme_priv.roam_flags */ enum { - RTW_ROAM_ON_EXPIRED = BIT0, - RTW_ROAM_ON_RESUME = BIT1, - RTW_ROAM_ACTIVE = BIT2, + RTW_ROAM_ON_EXPIRED = BIT0, /* roam when AP is expired */ + RTW_ROAM_ON_RESUME = BIT1, /* roam when device is resumed (after being suspended) */ + RTW_ROAM_ACTIVE = BIT2, /* active roam when current rssi (signal strength) is too low */ }; #define UNASOC_STA_SRC_RX_BMC 0 @@ -568,22 +568,22 @@ struct unassoc_sta_info { #endif struct mlme_priv { - _lock lock; sint fw_state; /* shall we protect this variable? maybe not necessarily... */ u8 to_join; /* flag */ u16 join_status; #ifdef CONFIG_LAYER2_ROAMING - u8 to_roam; /* roaming trying times */ + u8 to_roam; /* internal counter for #roaming scans */ struct wlan_network *roam_network; /* the target of active roam */ - u8 roam_flags; - u8 roam_rssi_diff_th; /* rssi difference threshold for active scan candidate selection */ - u32 roam_scan_int; /* scan interval for active roam (Unit:2 second)*/ - u32 roam_scanr_exp_ms; /* scan result expire time in ms for roam */ + u8 roam_flags; /* defines roam types - check enum above */ + u8 roam_rssi_diff_th; /* during network scan/survey: the rssi difference between the current network and + * the candidate network must be above this threshold to withhold the candidate */ + u32 roam_scan_int; /* minimum interval (unit: 2 seconds) between roaming scans */ + u32 roam_scanr_exp_ms; /* expire time in ms: only withhold candidate if last seen within expire time */ u8 roam_tgt_addr[ETH_ALEN]; /* request to roam to speicific target without other consideration */ - u8 roam_rssi_threshold; - systime last_roaming; - bool need_to_roam; + u8 roam_rssi_threshold; /* rssi (signal strength) must be below this threshold to start a roaming scan */ + systime last_roaming; /* time of start of last roaming scan */ + bool need_to_roam; /* flag to check if roaming is (still) necessary */ #endif u32 defs_lmt_sta; From d83ae81d01c53dcc282f71c92765aff149a3d8a7 Mon Sep 17 00:00:00 2001 From: Theo Debrouwere Date: Thu, 27 Apr 2023 11:08:00 +0200 Subject: [PATCH 3/3] Fix support for SIOCDEVPRIVATE ioctls from 5.15.0 onwards. From 5.15.0 onwards, SIOCDEVPRIVATE has been split into a seperate function. https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=b9067f5dc4a07c8e24e01a1b277c6722d91be39e This patch fixes support for the new SIOCDEVPRIVATE handling. Notes: In order to access these commands, CONFIG_MP_INCLUDED must be set to 'y'. They can then be accessed with the correct ioctl. Example application to do this can be found here: https://github.com/lfelten/rtl_iw_priv --- include/osdep_intf.h | 5 +++++ os_dep/linux/ioctl_linux.c | 11 +++++++++++ os_dep/linux/os_intfs.c | 6 ++++++ 3 files changed, 22 insertions(+) diff --git a/include/osdep_intf.h b/include/osdep_intf.h index 63e535e..4b209fb 100644 --- a/include/osdep_intf.h +++ b/include/osdep_intf.h @@ -79,6 +79,11 @@ uint loadparam(_adapter *adapter); #ifdef PLATFORM_LINUX int rtw_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); +#if ((LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0)) && defined(CONFIG_MP_INCLUDED)) +int rtw_siocdevprivate(struct net_device *dev, struct ifreq *ifr, + void __user *data, int cmd); +#endif + int rtw_init_netdev_name(struct net_device *pnetdev, const char *ifname); struct net_device *rtw_init_netdev(_adapter *padapter); diff --git a/os_dep/linux/ioctl_linux.c b/os_dep/linux/ioctl_linux.c index 1c52acc..7d8d09c 100644 --- a/os_dep/linux/ioctl_linux.c +++ b/os_dep/linux/ioctl_linux.c @@ -13058,3 +13058,14 @@ int rtw_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) return ret; } + +#if ((LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0)) && defined(CONFIG_MP_INCLUDED)) +int rtw_siocdevprivate(struct net_device *dev, struct ifreq *ifr, + void __user *data, int cmd) +{ + if (cmd != SIOCDEVPRIVATE) + return -EOPNOTSUPP; + + return rtw_ioctl_standard_wext_private(dev, ifr); +} +#endif diff --git a/os_dep/linux/os_intfs.c b/os_dep/linux/os_intfs.c index bb4e15d..2c07635 100644 --- a/os_dep/linux/os_intfs.c +++ b/os_dep/linux/os_intfs.c @@ -1849,6 +1849,9 @@ static const struct net_device_ops rtw_netdev_ops = { .ndo_set_mac_address = rtw_net_set_mac_address, .ndo_get_stats = rtw_net_get_stats, .ndo_do_ioctl = rtw_ioctl, +#if ((LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0)) && defined(CONFIG_MP_INCLUDED)) + .ndo_siocdevprivate = rtw_siocdevprivate, +#endif }; #endif @@ -3347,6 +3350,9 @@ static const struct net_device_ops rtw_netdev_vir_if_ops = { .ndo_set_mac_address = rtw_net_set_mac_address, .ndo_get_stats = rtw_net_get_stats, .ndo_do_ioctl = rtw_ioctl, +#if ((LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0)) && defined(CONFIG_MP_INCLUDED)) + .ndo_siocdevprivate = rtw_siocdevprivate, +#endif #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)) .ndo_select_queue = rtw_select_queue, #endif