2024-01-08 11:12:02

by Martin Kaistra

[permalink] [raw]
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);
+ 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



2024-01-09 03:14:34

by Ping-Ke Shih

[permalink] [raw]
Subject: RE: [PATCH] wifi: rtl8xxxu: enable channel switch support



> -----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);
> + }
> }
>