diff mbox series

wifi: rtl8xxxu: enable channel switch support

Message ID 20240108111103.121378-1-martin.kaistra@linutronix.de (mailing list archive)
State Changes Requested
Delegated to: Kalle Valo
Headers show
Series wifi: rtl8xxxu: enable channel switch support | expand

Commit Message

Martin Kaistra Jan. 8, 2024, 11:11 a.m. UTC
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 <martin.kaistra@linutronix.de>
---
 .../net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c   | 13 ++++++++++++-
 1 file changed, 12 insertions(+), 1 deletion(-)

Comments

Ping-Ke Shih Jan. 9, 2024, 3:14 a.m. UTC | #1
> -----Original Message-----
> From: Martin Kaistra <martin.kaistra@linutronix.de>
> Sent: Monday, January 8, 2024 7:11 PM
> To: linux-wireless@vger.kernel.org
> Cc: Jes Sorensen <Jes.Sorensen@gmail.com>; Kalle Valo <kvalo@kernel.org>; Ping-Ke Shih
> <pkshih@realtek.com>; Bitterblue Smith <rtl8821cerfe2@gmail.com>; Sebastian Andrzej Siewior
> <bigeasy@linutronix.de>
> 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 <martin.kaistra@linutronix.de>
> ---
>  .../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);
> +       }
>  }
>
diff mbox series

Patch

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