The CSA countdown in the beacon frames, which are sent out by firmware,
needs to get updated by the driver. Do this at the end of the
update_beacon_work function by sleeping for a bit shorter than the
beacon interval and then either scheduling another run of
update_beacon_work or calling ieee80211_csa_finish() when the end of the
countdown is reached.
Signed-off-by: Martin Kaistra <[email protected]>
---
.../net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c | 13 ++++++++++++-
1 file changed, 12 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
index 5fddbd6594a24..c4f3f52bde303 100644
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
@@ -5696,7 +5696,7 @@ static void rtl8xxxu_send_beacon_frame(struct ieee80211_hw *hw,
struct rtl8xxxu_priv *priv = hw->priv;
struct sk_buff *skb = ieee80211_beacon_get(hw, vif, 0);
struct device *dev = &priv->udev->dev;
- int retry;
+ int retry, interval;
u8 val8;
/* BCN_VALID, write 1 to clear, cleared by SW */
@@ -5722,6 +5722,15 @@ static void rtl8xxxu_send_beacon_frame(struct ieee80211_hw *hw,
if (!retry)
dev_err(dev, "%s: Failed to read beacon valid bit\n", __func__);
+
+ if (vif->bss_conf.csa_active) {
+ interval = 1024 * vif->bss_conf.beacon_int;
+ usleep_range(interval - 2048, interval - 1024);
+ if (ieee80211_beacon_cntdwn_is_complete(vif))
+ ieee80211_csa_finish(vif);
+ else
+ schedule_work(&priv->update_beacon_work);
+ }
}
static void rtl8xxxu_update_beacon_work_callback(struct work_struct *work)
@@ -7825,6 +7834,8 @@ static int rtl8xxxu_probe(struct usb_interface *interface,
hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_AP);
hw->queues = 4;
+ hw->wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
+
if (priv->fops->supports_concurrent) {
hw->wiphy->iface_combinations = rtl8xxxu_combinations;
hw->wiphy->n_iface_combinations = ARRAY_SIZE(rtl8xxxu_combinations);
--
2.39.2
> -----Original Message-----
> From: Martin Kaistra <[email protected]>
> Sent: Monday, January 8, 2024 7:11 PM
> To: [email protected]
> Cc: Jes Sorensen <[email protected]>; Kalle Valo <[email protected]>; Ping-Ke Shih
> <[email protected]>; Bitterblue Smith <[email protected]>; Sebastian Andrzej Siewior
> <[email protected]>
> Subject: [PATCH] wifi: rtl8xxxu: enable channel switch support
>
> The CSA countdown in the beacon frames, which are sent out by firmware,
> needs to get updated by the driver. Do this at the end of the
> update_beacon_work function by sleeping for a bit shorter than the
> beacon interval and then either scheduling another run of
> update_beacon_work or calling ieee80211_csa_finish() when the end of the
> countdown is reached.
>
> Signed-off-by: Martin Kaistra <[email protected]>
> ---
> .../net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c | 13 ++++++++++++-
> 1 file changed, 12 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
> b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
> index 5fddbd6594a24..c4f3f52bde303 100644
> --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
> +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
> @@ -5696,7 +5696,7 @@ static void rtl8xxxu_send_beacon_frame(struct ieee80211_hw *hw,
> struct rtl8xxxu_priv *priv = hw->priv;
> struct sk_buff *skb = ieee80211_beacon_get(hw, vif, 0);
> struct device *dev = &priv->udev->dev;
> - int retry;
> + int retry, interval;
> u8 val8;
>
> /* BCN_VALID, write 1 to clear, cleared by SW */
> @@ -5722,6 +5722,15 @@ static void rtl8xxxu_send_beacon_frame(struct ieee80211_hw *hw,
>
> if (!retry)
> dev_err(dev, "%s: Failed to read beacon valid bit\n", __func__);
> +
> + if (vif->bss_conf.csa_active) {
> + interval = 1024 * vif->bss_conf.beacon_int;
> + usleep_range(interval - 2048, interval - 1024);
Can we use a delayed work? And, re-schedule it as early as possible to execute
this function in accurate interval of beacon_int, otherwise processing time of
this function will be accumulated.
> + if (ieee80211_beacon_cntdwn_is_complete(vif))
> + ieee80211_csa_finish(vif);
> + else
> + schedule_work(&priv->update_beacon_work);
> + }
> }
>