mirror of
				git://git.openwrt.org/openwrt/openwrt.git
				synced 2025-11-03 14:34:27 -05:00 
			
		
		
		
	mac80211: rtl8xxxu: sync with linux-next 20240229
Backporting upstream patches to improve RTL8188F support. Signed-off-by: Shiji Yang <yangshiji66@qq.com>
This commit is contained in:
		
							parent
							
								
									860dd27617
								
							
						
					
					
						commit
						97f542238a
					
				@ -0,0 +1,27 @@
 | 
			
		||||
From d55cb6d8a99441aff55cb9ce663a07f7f1667e83 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Martin Kaistra <martin.kaistra@linutronix.de>
 | 
			
		||||
Date: Fri, 22 Dec 2023 11:14:22 +0100
 | 
			
		||||
Subject: [PATCH 01/21] wifi: rtl8xxxu: remove assignment of priv->vif in
 | 
			
		||||
 rtl8xxxu_bss_info_changed()
 | 
			
		||||
 | 
			
		||||
priv->vif gets already set in rtl8xxxu_add_interface, there is no need
 | 
			
		||||
to set it also in rtl8xxxu_bss_info_changed().
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Martin Kaistra <martin.kaistra@linutronix.de>
 | 
			
		||||
Reviewed-by: Ping-Ke Shih <pkshih@realtek.com>
 | 
			
		||||
Signed-off-by: Kalle Valo <kvalo@kernel.org>
 | 
			
		||||
Link: https://msgid.link/20231222101442.626837-2-martin.kaistra@linutronix.de
 | 
			
		||||
---
 | 
			
		||||
 drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c | 1 -
 | 
			
		||||
 1 file changed, 1 deletion(-)
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
 | 
			
		||||
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
 | 
			
		||||
@@ -5004,7 +5004,6 @@ rtl8xxxu_bss_info_changed(struct ieee802
 | 
			
		||||
 
 | 
			
		||||
 			rtl8xxxu_update_ra_report(rarpt, highest_rate, sgi, bw);
 | 
			
		||||
 
 | 
			
		||||
-			priv->vif = vif;
 | 
			
		||||
 			priv->rssi_level = RTL8XXXU_RATR_STA_INIT;
 | 
			
		||||
 
 | 
			
		||||
 			priv->fops->update_rate_mask(priv, ramask, 0, sgi,
 | 
			
		||||
@ -0,0 +1,61 @@
 | 
			
		||||
From 2bbd7d584046038ce655e476628bb15e1460fac6 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Martin Kaistra <martin.kaistra@linutronix.de>
 | 
			
		||||
Date: Fri, 22 Dec 2023 11:14:23 +0100
 | 
			
		||||
Subject: [PATCH 02/21] wifi: rtl8xxxu: prepare supporting two virtual
 | 
			
		||||
 interfaces
 | 
			
		||||
 | 
			
		||||
To prepare for concurrent mode, add an array ("vifs") to rtl8xxxu_priv
 | 
			
		||||
to keep track of both interfaces.
 | 
			
		||||
 | 
			
		||||
Keep the old priv->vif as long there are still users of it and let
 | 
			
		||||
priv->vifs[0] point to the same location.
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Martin Kaistra <martin.kaistra@linutronix.de>
 | 
			
		||||
Reviewed-by: Ping-Ke Shih <pkshih@realtek.com>
 | 
			
		||||
Signed-off-by: Kalle Valo <kvalo@kernel.org>
 | 
			
		||||
Link: https://msgid.link/20231222101442.626837-3-martin.kaistra@linutronix.de
 | 
			
		||||
---
 | 
			
		||||
 drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h      |  2 ++
 | 
			
		||||
 drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c | 10 +++++++---
 | 
			
		||||
 2 files changed, 9 insertions(+), 3 deletions(-)
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h
 | 
			
		||||
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h
 | 
			
		||||
@@ -1897,6 +1897,8 @@ struct rtl8xxxu_priv {
 | 
			
		||||
 	 * is supported and no iface_combinations are provided.
 | 
			
		||||
 	 */
 | 
			
		||||
 	struct ieee80211_vif *vif;
 | 
			
		||||
+
 | 
			
		||||
+	struct ieee80211_vif *vifs[2];
 | 
			
		||||
 	struct delayed_work ra_watchdog;
 | 
			
		||||
 	struct work_struct c2hcmd_work;
 | 
			
		||||
 	struct sk_buff_head c2hcmd_queue;
 | 
			
		||||
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
 | 
			
		||||
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
 | 
			
		||||
@@ -6569,10 +6569,12 @@ static int rtl8xxxu_add_interface(struct
 | 
			
		||||
 	int ret;
 | 
			
		||||
 	u8 val8;
 | 
			
		||||
 
 | 
			
		||||
-	if (!priv->vif)
 | 
			
		||||
+	if (!priv->vif) {
 | 
			
		||||
 		priv->vif = vif;
 | 
			
		||||
-	else
 | 
			
		||||
+		priv->vifs[0] = vif;
 | 
			
		||||
+	} else {
 | 
			
		||||
 		return -EOPNOTSUPP;
 | 
			
		||||
+	}
 | 
			
		||||
 
 | 
			
		||||
 	switch (vif->type) {
 | 
			
		||||
 	case NL80211_IFTYPE_STATION:
 | 
			
		||||
@@ -6622,8 +6624,10 @@ static void rtl8xxxu_remove_interface(st
 | 
			
		||||
 
 | 
			
		||||
 	dev_dbg(&priv->udev->dev, "%s\n", __func__);
 | 
			
		||||
 
 | 
			
		||||
-	if (priv->vif)
 | 
			
		||||
+	if (priv->vif) {
 | 
			
		||||
 		priv->vif = NULL;
 | 
			
		||||
+		priv->vifs[0] = NULL;
 | 
			
		||||
+	}
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
 static int rtl8xxxu_config(struct ieee80211_hw *hw, u32 changed)
 | 
			
		||||
@ -0,0 +1,102 @@
 | 
			
		||||
From 7f444692cde83c1455682c2d0d2c9a666422b867 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Martin Kaistra <martin.kaistra@linutronix.de>
 | 
			
		||||
Date: Fri, 22 Dec 2023 11:14:24 +0100
 | 
			
		||||
Subject: [PATCH 03/21] wifi: rtl8xxxu: support setting linktype for both
 | 
			
		||||
 interfaces
 | 
			
		||||
 | 
			
		||||
To prepare for concurrent mode, enhance the set_linktype function to be
 | 
			
		||||
able to set the linktype in the MSR register for both hardware ports.
 | 
			
		||||
 | 
			
		||||
Until the users of set_linktype can handle multiple interfaces, use
 | 
			
		||||
port_num = 0.
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Martin Kaistra <martin.kaistra@linutronix.de>
 | 
			
		||||
Reviewed-by: Ping-Ke Shih <pkshih@realtek.com>
 | 
			
		||||
Signed-off-by: Kalle Valo <kvalo@kernel.org>
 | 
			
		||||
Link: https://msgid.link/20231222101442.626837-4-martin.kaistra@linutronix.de
 | 
			
		||||
---
 | 
			
		||||
 .../wireless/realtek/rtl8xxxu/rtl8xxxu_core.c | 37 +++++++++++--------
 | 
			
		||||
 1 file changed, 22 insertions(+), 15 deletions(-)
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
 | 
			
		||||
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
 | 
			
		||||
@@ -1633,33 +1633,41 @@ rtl8xxxu_gen1_set_tx_power(struct rtl8xx
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
 static void rtl8xxxu_set_linktype(struct rtl8xxxu_priv *priv,
 | 
			
		||||
-				  enum nl80211_iftype linktype)
 | 
			
		||||
+				  enum nl80211_iftype linktype, int port_num)
 | 
			
		||||
 {
 | 
			
		||||
-	u8 val8;
 | 
			
		||||
-
 | 
			
		||||
-	val8 = rtl8xxxu_read8(priv, REG_MSR);
 | 
			
		||||
-	val8 &= ~MSR_LINKTYPE_MASK;
 | 
			
		||||
+	u8 val8, type;
 | 
			
		||||
 
 | 
			
		||||
 	switch (linktype) {
 | 
			
		||||
 	case NL80211_IFTYPE_UNSPECIFIED:
 | 
			
		||||
-		val8 |= MSR_LINKTYPE_NONE;
 | 
			
		||||
+		type = MSR_LINKTYPE_NONE;
 | 
			
		||||
 		break;
 | 
			
		||||
 	case NL80211_IFTYPE_ADHOC:
 | 
			
		||||
-		val8 |= MSR_LINKTYPE_ADHOC;
 | 
			
		||||
+		type = MSR_LINKTYPE_ADHOC;
 | 
			
		||||
 		break;
 | 
			
		||||
 	case NL80211_IFTYPE_STATION:
 | 
			
		||||
-		val8 |= MSR_LINKTYPE_STATION;
 | 
			
		||||
+		type = MSR_LINKTYPE_STATION;
 | 
			
		||||
 		break;
 | 
			
		||||
 	case NL80211_IFTYPE_AP:
 | 
			
		||||
-		val8 |= MSR_LINKTYPE_AP;
 | 
			
		||||
+		type = MSR_LINKTYPE_AP;
 | 
			
		||||
 		break;
 | 
			
		||||
 	default:
 | 
			
		||||
-		goto out;
 | 
			
		||||
+		return;
 | 
			
		||||
+	}
 | 
			
		||||
+
 | 
			
		||||
+	switch (port_num) {
 | 
			
		||||
+	case 0:
 | 
			
		||||
+		val8 = rtl8xxxu_read8(priv, REG_MSR) & 0x0c;
 | 
			
		||||
+		val8 |= type;
 | 
			
		||||
+		break;
 | 
			
		||||
+	case 1:
 | 
			
		||||
+		val8 = rtl8xxxu_read8(priv, REG_MSR) & 0x03;
 | 
			
		||||
+		val8 |= type << 2;
 | 
			
		||||
+		break;
 | 
			
		||||
+	default:
 | 
			
		||||
+		return;
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
 	rtl8xxxu_write8(priv, REG_MSR, val8);
 | 
			
		||||
-out:
 | 
			
		||||
-	return;
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
 static void
 | 
			
		||||
@@ -4236,7 +4244,6 @@ static int rtl8xxxu_init_device(struct i
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
 	rtl8xxxu_set_mac(priv);
 | 
			
		||||
-	rtl8xxxu_set_linktype(priv, NL80211_IFTYPE_STATION);
 | 
			
		||||
 
 | 
			
		||||
 	/*
 | 
			
		||||
 	 * Configure initial WMAC settings
 | 
			
		||||
@@ -4964,7 +4971,7 @@ rtl8xxxu_bss_info_changed(struct ieee802
 | 
			
		||||
 	if (changed & BSS_CHANGED_ASSOC) {
 | 
			
		||||
 		dev_dbg(dev, "Changed ASSOC: %i!\n", vif->cfg.assoc);
 | 
			
		||||
 
 | 
			
		||||
-		rtl8xxxu_set_linktype(priv, vif->type);
 | 
			
		||||
+		rtl8xxxu_set_linktype(priv, vif->type, 0);
 | 
			
		||||
 
 | 
			
		||||
 		if (vif->cfg.assoc) {
 | 
			
		||||
 			u32 ramask;
 | 
			
		||||
@@ -6610,7 +6617,7 @@ static int rtl8xxxu_add_interface(struct
 | 
			
		||||
 		ret = -EOPNOTSUPP;
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
-	rtl8xxxu_set_linktype(priv, vif->type);
 | 
			
		||||
+	rtl8xxxu_set_linktype(priv, vif->type, 0);
 | 
			
		||||
 	ether_addr_copy(priv->mac_addr, vif->addr);
 | 
			
		||||
 	rtl8xxxu_set_mac(priv);
 | 
			
		||||
 
 | 
			
		||||
@ -0,0 +1,28 @@
 | 
			
		||||
From a047e46a7b98de384a158b25a05dc09aa7d70c5f Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Martin Kaistra <martin.kaistra@linutronix.de>
 | 
			
		||||
Date: Fri, 22 Dec 2023 11:14:25 +0100
 | 
			
		||||
Subject: [PATCH 04/21] wifi: rtl8xxxu: 8188e: convert usage of priv->vif to
 | 
			
		||||
 priv->vifs[0]
 | 
			
		||||
 | 
			
		||||
The driver currently does not support AP or concurrent mode for 8188e,
 | 
			
		||||
so just use priv->vifs[0] instead of priv->vif for now.
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Martin Kaistra <martin.kaistra@linutronix.de>
 | 
			
		||||
Reviewed-by: Ping-Ke Shih <pkshih@realtek.com>
 | 
			
		||||
Signed-off-by: Kalle Valo <kvalo@kernel.org>
 | 
			
		||||
Link: https://msgid.link/20231222101442.626837-5-martin.kaistra@linutronix.de
 | 
			
		||||
---
 | 
			
		||||
 drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8188e.c | 2 +-
 | 
			
		||||
 1 file changed, 1 insertion(+), 1 deletion(-)
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8188e.c
 | 
			
		||||
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8188e.c
 | 
			
		||||
@@ -1699,7 +1699,7 @@ void rtl8188e_handle_ra_tx_report2(struc
 | 
			
		||||
 	/* We only use macid 0, so only the first item is relevant.
 | 
			
		||||
 	 * AP mode will use more of them if it's ever implemented.
 | 
			
		||||
 	 */
 | 
			
		||||
-	if (!priv->vif || priv->vif->type == NL80211_IFTYPE_STATION)
 | 
			
		||||
+	if (!priv->vifs[0] || priv->vifs[0]->type == NL80211_IFTYPE_STATION)
 | 
			
		||||
 		items = 1;
 | 
			
		||||
 
 | 
			
		||||
 	for (macid = 0; macid < items; macid++) {
 | 
			
		||||
@ -0,0 +1,72 @@
 | 
			
		||||
From 00add60cad3c9690ac0f9d4f6685f96ccd607670 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Martin Kaistra <martin.kaistra@linutronix.de>
 | 
			
		||||
Date: Fri, 22 Dec 2023 11:14:26 +0100
 | 
			
		||||
Subject: [PATCH 05/21] wifi: rtl8xxxu: support setting mac address register
 | 
			
		||||
 for both interfaces
 | 
			
		||||
 | 
			
		||||
To prepare for concurrent mode, enhance rtl8xxxu_set_mac() to write the
 | 
			
		||||
mac address of the respective interface to REG_MACID or REG_MACID1.
 | 
			
		||||
 | 
			
		||||
Remove the call to rtl8xxxu_set_mac() from the init function as we set
 | 
			
		||||
it in rtl8xxxu_add_interface() later anyway.
 | 
			
		||||
 | 
			
		||||
Until rtl8xxxu_add_interface() can handle both interfaces, call
 | 
			
		||||
rtl8xxxu_set_mac() with port_num = 0.
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Martin Kaistra <martin.kaistra@linutronix.de>
 | 
			
		||||
Reviewed-by: Ping-Ke Shih <pkshih@realtek.com>
 | 
			
		||||
Signed-off-by: Kalle Valo <kvalo@kernel.org>
 | 
			
		||||
Link: https://msgid.link/20231222101442.626837-6-martin.kaistra@linutronix.de
 | 
			
		||||
---
 | 
			
		||||
 .../wireless/realtek/rtl8xxxu/rtl8xxxu_core.c | 20 +++++++++++++------
 | 
			
		||||
 1 file changed, 14 insertions(+), 6 deletions(-)
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
 | 
			
		||||
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
 | 
			
		||||
@@ -3580,15 +3580,25 @@ void rtl8723a_phy_lc_calibrate(struct rt
 | 
			
		||||
 		rtl8xxxu_write8(priv, REG_TXPAUSE, 0x00);
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
-static int rtl8xxxu_set_mac(struct rtl8xxxu_priv *priv)
 | 
			
		||||
+static int rtl8xxxu_set_mac(struct rtl8xxxu_priv *priv, int port_num)
 | 
			
		||||
 {
 | 
			
		||||
 	int i;
 | 
			
		||||
 	u16 reg;
 | 
			
		||||
 
 | 
			
		||||
-	reg = REG_MACID;
 | 
			
		||||
+	switch (port_num) {
 | 
			
		||||
+	case 0:
 | 
			
		||||
+		reg = REG_MACID;
 | 
			
		||||
+		break;
 | 
			
		||||
+	case 1:
 | 
			
		||||
+		reg = REG_MACID1;
 | 
			
		||||
+		break;
 | 
			
		||||
+	default:
 | 
			
		||||
+		WARN_ONCE("%s: invalid port_num\n", __func__);
 | 
			
		||||
+		return -EINVAL;
 | 
			
		||||
+	}
 | 
			
		||||
 
 | 
			
		||||
 	for (i = 0; i < ETH_ALEN; i++)
 | 
			
		||||
-		rtl8xxxu_write8(priv, reg + i, priv->mac_addr[i]);
 | 
			
		||||
+		rtl8xxxu_write8(priv, reg + i, priv->vifs[port_num]->addr[i]);
 | 
			
		||||
 
 | 
			
		||||
 	return 0;
 | 
			
		||||
 }
 | 
			
		||||
@@ -4243,8 +4253,6 @@ static int rtl8xxxu_init_device(struct i
 | 
			
		||||
 		rtl8xxxu_write32(priv, REG_HIMR, 0xffffffff);
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
-	rtl8xxxu_set_mac(priv);
 | 
			
		||||
-
 | 
			
		||||
 	/*
 | 
			
		||||
 	 * Configure initial WMAC settings
 | 
			
		||||
 	 */
 | 
			
		||||
@@ -6619,7 +6627,7 @@ static int rtl8xxxu_add_interface(struct
 | 
			
		||||
 
 | 
			
		||||
 	rtl8xxxu_set_linktype(priv, vif->type, 0);
 | 
			
		||||
 	ether_addr_copy(priv->mac_addr, vif->addr);
 | 
			
		||||
-	rtl8xxxu_set_mac(priv);
 | 
			
		||||
+	rtl8xxxu_set_mac(priv, 0);
 | 
			
		||||
 
 | 
			
		||||
 	return ret;
 | 
			
		||||
 }
 | 
			
		||||
@ -0,0 +1,75 @@
 | 
			
		||||
From 9aa776209ca31695bead52674ad943848ccc97d5 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Martin Kaistra <martin.kaistra@linutronix.de>
 | 
			
		||||
Date: Fri, 22 Dec 2023 11:14:27 +0100
 | 
			
		||||
Subject: [PATCH 06/21] wifi: rtl8xxxu: extend wifi connected check to both
 | 
			
		||||
 interfaces
 | 
			
		||||
 | 
			
		||||
There are multiple places in the code where the current connection
 | 
			
		||||
status of wifi is checked. The driver will support two interfaces soon
 | 
			
		||||
and either one of them (or both) could be connected.
 | 
			
		||||
 | 
			
		||||
Convert all uses of (vif && vif->cfg.assoc) to a new helper
 | 
			
		||||
function rtl8xxxu_is_assoc() which checks both interfaces.
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Martin Kaistra <martin.kaistra@linutronix.de>
 | 
			
		||||
Reviewed-by: Ping-Ke Shih <pkshih@realtek.com>
 | 
			
		||||
Signed-off-by: Kalle Valo <kvalo@kernel.org>
 | 
			
		||||
Link: https://msgid.link/20231222101442.626837-7-martin.kaistra@linutronix.de
 | 
			
		||||
---
 | 
			
		||||
 .../wireless/realtek/rtl8xxxu/rtl8xxxu_core.c | 20 +++++++++----------
 | 
			
		||||
 1 file changed, 9 insertions(+), 11 deletions(-)
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
 | 
			
		||||
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
 | 
			
		||||
@@ -6043,18 +6043,20 @@ void rtl8723bu_update_bt_link_info(struc
 | 
			
		||||
 		btcoex->bt_busy = false;
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
+static inline bool rtl8xxxu_is_assoc(struct rtl8xxxu_priv *priv)
 | 
			
		||||
+{
 | 
			
		||||
+	return (priv->vifs[0] && priv->vifs[0]->cfg.assoc) ||
 | 
			
		||||
+	       (priv->vifs[1] && priv->vifs[1]->cfg.assoc);
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
 static
 | 
			
		||||
 void rtl8723bu_handle_bt_inquiry(struct rtl8xxxu_priv *priv)
 | 
			
		||||
 {
 | 
			
		||||
-	struct ieee80211_vif *vif;
 | 
			
		||||
 	struct rtl8xxxu_btcoex *btcoex;
 | 
			
		||||
-	bool wifi_connected;
 | 
			
		||||
 
 | 
			
		||||
-	vif = priv->vif;
 | 
			
		||||
 	btcoex = &priv->bt_coex;
 | 
			
		||||
-	wifi_connected = (vif && vif->cfg.assoc);
 | 
			
		||||
 
 | 
			
		||||
-	if (!wifi_connected) {
 | 
			
		||||
+	if (!rtl8xxxu_is_assoc(priv)) {
 | 
			
		||||
 		rtl8723bu_set_ps_tdma(priv, 0x8, 0x0, 0x0, 0x0, 0x0);
 | 
			
		||||
 		rtl8723bu_set_coex_with_type(priv, 0);
 | 
			
		||||
 	} else if (btcoex->has_sco || btcoex->has_hid || btcoex->has_a2dp) {
 | 
			
		||||
@@ -6072,15 +6074,11 @@ void rtl8723bu_handle_bt_inquiry(struct
 | 
			
		||||
 static
 | 
			
		||||
 void rtl8723bu_handle_bt_info(struct rtl8xxxu_priv *priv)
 | 
			
		||||
 {
 | 
			
		||||
-	struct ieee80211_vif *vif;
 | 
			
		||||
 	struct rtl8xxxu_btcoex *btcoex;
 | 
			
		||||
-	bool wifi_connected;
 | 
			
		||||
 
 | 
			
		||||
-	vif = priv->vif;
 | 
			
		||||
 	btcoex = &priv->bt_coex;
 | 
			
		||||
-	wifi_connected = (vif && vif->cfg.assoc);
 | 
			
		||||
 
 | 
			
		||||
-	if (wifi_connected) {
 | 
			
		||||
+	if (rtl8xxxu_is_assoc(priv)) {
 | 
			
		||||
 		u32 val32 = 0;
 | 
			
		||||
 		u32 high_prio_tx = 0, high_prio_rx = 0;
 | 
			
		||||
 
 | 
			
		||||
@@ -7103,7 +7101,7 @@ static void rtl8xxxu_track_cfo(struct rt
 | 
			
		||||
 	int cfo_khz_a, cfo_khz_b, cfo_average;
 | 
			
		||||
 	int crystal_cap;
 | 
			
		||||
 
 | 
			
		||||
-	if (!priv->vif || !priv->vif->cfg.assoc) {
 | 
			
		||||
+	if (!rtl8xxxu_is_assoc(priv)) {
 | 
			
		||||
 		/* Reset */
 | 
			
		||||
 		cfo->adjust = true;
 | 
			
		||||
 
 | 
			
		||||
@ -0,0 +1,70 @@
 | 
			
		||||
From 80fd8687db41b1e04f78c37137d090f2165cca6e Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Martin Kaistra <martin.kaistra@linutronix.de>
 | 
			
		||||
Date: Fri, 22 Dec 2023 11:14:28 +0100
 | 
			
		||||
Subject: [PATCH 07/21] wifi: rtl8xxxu: extend check for matching bssid to both
 | 
			
		||||
 interfaces
 | 
			
		||||
 | 
			
		||||
The driver will support two interfaces soon, which both can be in
 | 
			
		||||
station mode, so extend the check, whether cfo information should be
 | 
			
		||||
parsed, to cover both interfaces.
 | 
			
		||||
 | 
			
		||||
For better code readability put the lines with priv->vifs[port_num] in a
 | 
			
		||||
separate function.
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Martin Kaistra <martin.kaistra@linutronix.de>
 | 
			
		||||
Reviewed-by: Ping-Ke Shih <pkshih@realtek.com>
 | 
			
		||||
Signed-off-by: Kalle Valo <kvalo@kernel.org>
 | 
			
		||||
Link: https://msgid.link/20231222101442.626837-8-martin.kaistra@linutronix.de
 | 
			
		||||
---
 | 
			
		||||
 .../wireless/realtek/rtl8xxxu/rtl8xxxu_core.c | 22 ++++++++++++-------
 | 
			
		||||
 1 file changed, 14 insertions(+), 8 deletions(-)
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
 | 
			
		||||
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
 | 
			
		||||
@@ -5706,6 +5706,16 @@ static void rtl8xxxu_update_beacon_work_
 | 
			
		||||
 	rtl8xxxu_send_beacon_frame(hw, vif);
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
+static inline bool rtl8xxxu_is_packet_match_bssid(struct rtl8xxxu_priv *priv,
 | 
			
		||||
+						  struct ieee80211_hdr *hdr,
 | 
			
		||||
+						  int port_num)
 | 
			
		||||
+{
 | 
			
		||||
+	return priv->vifs[port_num] &&
 | 
			
		||||
+	       priv->vifs[port_num]->type == NL80211_IFTYPE_STATION &&
 | 
			
		||||
+	       priv->vifs[port_num]->cfg.assoc &&
 | 
			
		||||
+	       ether_addr_equal(priv->vifs[port_num]->bss_conf.bssid, hdr->addr2);
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
 void rtl8723au_rx_parse_phystats(struct rtl8xxxu_priv *priv,
 | 
			
		||||
 				 struct ieee80211_rx_status *rx_status,
 | 
			
		||||
 				 struct rtl8723au_phy_stats *phy_stats,
 | 
			
		||||
@@ -5722,12 +5732,10 @@ void rtl8723au_rx_parse_phystats(struct
 | 
			
		||||
 		rx_status->signal = priv->fops->cck_rssi(priv, phy_stats);
 | 
			
		||||
 	} else {
 | 
			
		||||
 		bool parse_cfo = priv->fops->set_crystal_cap &&
 | 
			
		||||
-				 priv->vif &&
 | 
			
		||||
-				 priv->vif->type == NL80211_IFTYPE_STATION &&
 | 
			
		||||
-				 priv->vif->cfg.assoc &&
 | 
			
		||||
 				 !crc_icv_err &&
 | 
			
		||||
 				 !ieee80211_is_ctl(hdr->frame_control) &&
 | 
			
		||||
-				 ether_addr_equal(priv->vif->bss_conf.bssid, hdr->addr2);
 | 
			
		||||
+				 (rtl8xxxu_is_packet_match_bssid(priv, hdr, 0) ||
 | 
			
		||||
+				  rtl8xxxu_is_packet_match_bssid(priv, hdr, 1));
 | 
			
		||||
 
 | 
			
		||||
 		if (parse_cfo) {
 | 
			
		||||
 			priv->cfo_tracking.cfo_tail[0] = phy_stats->path_cfotail[0];
 | 
			
		||||
@@ -5762,12 +5770,10 @@ static void jaguar2_rx_parse_phystats_ty
 | 
			
		||||
 					    bool crc_icv_err)
 | 
			
		||||
 {
 | 
			
		||||
 	bool parse_cfo = priv->fops->set_crystal_cap &&
 | 
			
		||||
-			 priv->vif &&
 | 
			
		||||
-			 priv->vif->type == NL80211_IFTYPE_STATION &&
 | 
			
		||||
-			 priv->vif->cfg.assoc &&
 | 
			
		||||
 			 !crc_icv_err &&
 | 
			
		||||
 			 !ieee80211_is_ctl(hdr->frame_control) &&
 | 
			
		||||
-			 ether_addr_equal(priv->vif->bss_conf.bssid, hdr->addr2);
 | 
			
		||||
+			 (rtl8xxxu_is_packet_match_bssid(priv, hdr, 0) ||
 | 
			
		||||
+			  rtl8xxxu_is_packet_match_bssid(priv, hdr, 1));
 | 
			
		||||
 	u8 pwdb_max = 0;
 | 
			
		||||
 	int rx_path;
 | 
			
		||||
 
 | 
			
		||||
@ -0,0 +1,51 @@
 | 
			
		||||
From f86dd8eaf8da84ee5b803d90b8c311d7e2725d0b Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Martin Kaistra <martin.kaistra@linutronix.de>
 | 
			
		||||
Date: Fri, 22 Dec 2023 11:14:29 +0100
 | 
			
		||||
Subject: [PATCH 08/21] wifi: rtl8xxxu: don't parse CFO, if both interfaces are
 | 
			
		||||
 connected in STA mode
 | 
			
		||||
 | 
			
		||||
If both interfaces are in STATION mode and both are connected to an AP,
 | 
			
		||||
there might be conflicting CFO values for the two connections. Ignore
 | 
			
		||||
the CFO information in this case.
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Martin Kaistra <martin.kaistra@linutronix.de>
 | 
			
		||||
Reviewed-by: Ping-Ke Shih <pkshih@realtek.com>
 | 
			
		||||
Signed-off-by: Kalle Valo <kvalo@kernel.org>
 | 
			
		||||
Link: https://msgid.link/20231222101442.626837-9-martin.kaistra@linutronix.de
 | 
			
		||||
---
 | 
			
		||||
 drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c | 10 ++++++++++
 | 
			
		||||
 1 file changed, 10 insertions(+)
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
 | 
			
		||||
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
 | 
			
		||||
@@ -5716,6 +5716,14 @@ static inline bool rtl8xxxu_is_packet_ma
 | 
			
		||||
 	       ether_addr_equal(priv->vifs[port_num]->bss_conf.bssid, hdr->addr2);
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
+static inline bool rtl8xxxu_is_sta_sta(struct rtl8xxxu_priv *priv)
 | 
			
		||||
+{
 | 
			
		||||
+	return (priv->vifs[0] && priv->vifs[0]->cfg.assoc &&
 | 
			
		||||
+		priv->vifs[0]->type == NL80211_IFTYPE_STATION) &&
 | 
			
		||||
+	       (priv->vifs[1] && priv->vifs[1]->cfg.assoc &&
 | 
			
		||||
+		priv->vifs[1]->type == NL80211_IFTYPE_STATION);
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
 void rtl8723au_rx_parse_phystats(struct rtl8xxxu_priv *priv,
 | 
			
		||||
 				 struct ieee80211_rx_status *rx_status,
 | 
			
		||||
 				 struct rtl8723au_phy_stats *phy_stats,
 | 
			
		||||
@@ -5734,6 +5742,7 @@ void rtl8723au_rx_parse_phystats(struct
 | 
			
		||||
 		bool parse_cfo = priv->fops->set_crystal_cap &&
 | 
			
		||||
 				 !crc_icv_err &&
 | 
			
		||||
 				 !ieee80211_is_ctl(hdr->frame_control) &&
 | 
			
		||||
+				 !rtl8xxxu_is_sta_sta(priv) &&
 | 
			
		||||
 				 (rtl8xxxu_is_packet_match_bssid(priv, hdr, 0) ||
 | 
			
		||||
 				  rtl8xxxu_is_packet_match_bssid(priv, hdr, 1));
 | 
			
		||||
 
 | 
			
		||||
@@ -5772,6 +5781,7 @@ static void jaguar2_rx_parse_phystats_ty
 | 
			
		||||
 	bool parse_cfo = priv->fops->set_crystal_cap &&
 | 
			
		||||
 			 !crc_icv_err &&
 | 
			
		||||
 			 !ieee80211_is_ctl(hdr->frame_control) &&
 | 
			
		||||
+			 !rtl8xxxu_is_sta_sta(priv) &&
 | 
			
		||||
 			 (rtl8xxxu_is_packet_match_bssid(priv, hdr, 0) ||
 | 
			
		||||
 			  rtl8xxxu_is_packet_match_bssid(priv, hdr, 1));
 | 
			
		||||
 	u8 pwdb_max = 0;
 | 
			
		||||
@ -0,0 +1,67 @@
 | 
			
		||||
From 3ff7a05996f901a7a10068b42e9dc8435f908a4c Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Martin Kaistra <martin.kaistra@linutronix.de>
 | 
			
		||||
Date: Fri, 22 Dec 2023 11:14:30 +0100
 | 
			
		||||
Subject: [PATCH 09/21] wifi: rtl8xxxu: support setting bssid register for
 | 
			
		||||
 multiple interfaces
 | 
			
		||||
 | 
			
		||||
To prepare for concurrent mode, enhance rtl8xxxu_set_bssid() to write the
 | 
			
		||||
BSSID of the respective interface to REG_BSSID or REG_BSSID1.
 | 
			
		||||
 | 
			
		||||
Like done with rtl8xxxu_set_mac(), call rtl8xxxu_set_bssid() with
 | 
			
		||||
port_num = 0, until the callers also support multiple interfaces.
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Martin Kaistra <martin.kaistra@linutronix.de>
 | 
			
		||||
Reviewed-by: Ping-Ke Shih <pkshih@realtek.com>
 | 
			
		||||
Signed-off-by: Kalle Valo <kvalo@kernel.org>
 | 
			
		||||
Link: https://msgid.link/20231222101442.626837-10-martin.kaistra@linutronix.de
 | 
			
		||||
---
 | 
			
		||||
 .../wireless/realtek/rtl8xxxu/rtl8xxxu_core.c  | 18 ++++++++++++++----
 | 
			
		||||
 1 file changed, 14 insertions(+), 4 deletions(-)
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
 | 
			
		||||
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
 | 
			
		||||
@@ -3603,14 +3603,24 @@ static int rtl8xxxu_set_mac(struct rtl8x
 | 
			
		||||
 	return 0;
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
-static int rtl8xxxu_set_bssid(struct rtl8xxxu_priv *priv, const u8 *bssid)
 | 
			
		||||
+static int rtl8xxxu_set_bssid(struct rtl8xxxu_priv *priv, const u8 *bssid, int port_num)
 | 
			
		||||
 {
 | 
			
		||||
 	int i;
 | 
			
		||||
 	u16 reg;
 | 
			
		||||
 
 | 
			
		||||
 	dev_dbg(&priv->udev->dev, "%s: (%pM)\n", __func__, bssid);
 | 
			
		||||
 
 | 
			
		||||
-	reg = REG_BSSID;
 | 
			
		||||
+	switch (port_num) {
 | 
			
		||||
+	case 0:
 | 
			
		||||
+		reg = REG_BSSID;
 | 
			
		||||
+		break;
 | 
			
		||||
+	case 1:
 | 
			
		||||
+		reg = REG_BSSID1;
 | 
			
		||||
+		break;
 | 
			
		||||
+	default:
 | 
			
		||||
+		WARN_ONCE("%s: invalid port_num\n", __func__);
 | 
			
		||||
+		return -EINVAL;
 | 
			
		||||
+	}
 | 
			
		||||
 
 | 
			
		||||
 	for (i = 0; i < ETH_ALEN; i++)
 | 
			
		||||
 		rtl8xxxu_write8(priv, reg + i, bssid[i]);
 | 
			
		||||
@@ -5068,7 +5078,7 @@ rtl8xxxu_bss_info_changed(struct ieee802
 | 
			
		||||
 
 | 
			
		||||
 	if (changed & BSS_CHANGED_BSSID) {
 | 
			
		||||
 		dev_dbg(dev, "Changed BSSID!\n");
 | 
			
		||||
-		rtl8xxxu_set_bssid(priv, bss_conf->bssid);
 | 
			
		||||
+		rtl8xxxu_set_bssid(priv, bss_conf->bssid, 0);
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
 	if (changed & BSS_CHANGED_BASIC_RATES) {
 | 
			
		||||
@@ -5097,7 +5107,7 @@ static int rtl8xxxu_start_ap(struct ieee
 | 
			
		||||
 	struct device *dev = &priv->udev->dev;
 | 
			
		||||
 
 | 
			
		||||
 	dev_dbg(dev, "Start AP mode\n");
 | 
			
		||||
-	rtl8xxxu_set_bssid(priv, vif->bss_conf.bssid);
 | 
			
		||||
+	rtl8xxxu_set_bssid(priv, vif->bss_conf.bssid, 0);
 | 
			
		||||
 	rtl8xxxu_write16(priv, REG_BCN_INTERVAL, vif->bss_conf.beacon_int);
 | 
			
		||||
 	priv->fops->report_connect(priv, RTL8XXXU_BC_MC_MACID, 0, true);
 | 
			
		||||
 
 | 
			
		||||
@ -0,0 +1,44 @@
 | 
			
		||||
From 43532c050f8eec4056a21978fdb5b958e1477553 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Martin Kaistra <martin.kaistra@linutronix.de>
 | 
			
		||||
Date: Fri, 22 Dec 2023 11:14:31 +0100
 | 
			
		||||
Subject: [PATCH 10/21] wifi: rtl8xxxu: support multiple interfaces in
 | 
			
		||||
 set_aifs()
 | 
			
		||||
 | 
			
		||||
In concurrent mode supported by this driver, both interfaces will use
 | 
			
		||||
the same channel and same wireless mode.
 | 
			
		||||
It is therefore possible to get the wireless mode by checking the first
 | 
			
		||||
connected interface.
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Martin Kaistra <martin.kaistra@linutronix.de>
 | 
			
		||||
Reviewed-by: Ping-Ke Shih <pkshih@realtek.com>
 | 
			
		||||
Signed-off-by: Kalle Valo <kvalo@kernel.org>
 | 
			
		||||
Link: https://msgid.link/20231222101442.626837-11-martin.kaistra@linutronix.de
 | 
			
		||||
---
 | 
			
		||||
 drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c | 10 ++++++++--
 | 
			
		||||
 1 file changed, 8 insertions(+), 2 deletions(-)
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
 | 
			
		||||
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
 | 
			
		||||
@@ -4913,14 +4913,20 @@ static void rtl8xxxu_set_aifs(struct rtl
 | 
			
		||||
 	u8 aifs, aifsn, sifs;
 | 
			
		||||
 	int i;
 | 
			
		||||
 
 | 
			
		||||
-	if (priv->vif) {
 | 
			
		||||
+	for (i = 0; i < ARRAY_SIZE(priv->vifs); i++) {
 | 
			
		||||
+		if (!priv->vifs[i])
 | 
			
		||||
+			continue;
 | 
			
		||||
+
 | 
			
		||||
 		struct ieee80211_sta *sta;
 | 
			
		||||
 
 | 
			
		||||
 		rcu_read_lock();
 | 
			
		||||
-		sta = ieee80211_find_sta(priv->vif, priv->vif->bss_conf.bssid);
 | 
			
		||||
+		sta = ieee80211_find_sta(priv->vifs[i], priv->vifs[i]->bss_conf.bssid);
 | 
			
		||||
 		if (sta)
 | 
			
		||||
 			wireless_mode = rtl8xxxu_wireless_mode(priv->hw, sta);
 | 
			
		||||
 		rcu_read_unlock();
 | 
			
		||||
+
 | 
			
		||||
+		if (wireless_mode)
 | 
			
		||||
+			break;
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
 	if (priv->hw->conf.chandef.chan->band == NL80211_BAND_5GHZ ||
 | 
			
		||||
@ -0,0 +1,28 @@
 | 
			
		||||
From 05b22e9b7d84253f765cde01cb09d144094b61c9 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Martin Kaistra <martin.kaistra@linutronix.de>
 | 
			
		||||
Date: Fri, 22 Dec 2023 11:14:32 +0100
 | 
			
		||||
Subject: [PATCH 11/21] wifi: rtl8xxxu: support multiple interfaces in
 | 
			
		||||
 update_beacon_work_callback()
 | 
			
		||||
 | 
			
		||||
As we only want to support AP mode/sending beacons on port 0, it is
 | 
			
		||||
enough to replace priv->vif with priv->vifs[0].
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Martin Kaistra <martin.kaistra@linutronix.de>
 | 
			
		||||
Reviewed-by: Ping-Ke Shih <pkshih@realtek.com>
 | 
			
		||||
Signed-off-by: Kalle Valo <kvalo@kernel.org>
 | 
			
		||||
Link: https://msgid.link/20231222101442.626837-12-martin.kaistra@linutronix.de
 | 
			
		||||
---
 | 
			
		||||
 drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c | 2 +-
 | 
			
		||||
 1 file changed, 1 insertion(+), 1 deletion(-)
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
 | 
			
		||||
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
 | 
			
		||||
@@ -5712,7 +5712,7 @@ static void rtl8xxxu_update_beacon_work_
 | 
			
		||||
 	struct rtl8xxxu_priv *priv =
 | 
			
		||||
 		container_of(work, struct rtl8xxxu_priv, update_beacon_work);
 | 
			
		||||
 	struct ieee80211_hw *hw = priv->hw;
 | 
			
		||||
-	struct ieee80211_vif *vif = priv->vif;
 | 
			
		||||
+	struct ieee80211_vif *vif = priv->vifs[0];
 | 
			
		||||
 
 | 
			
		||||
 	if (!vif) {
 | 
			
		||||
 		WARN_ONCE(true, "no vif to update beacon\n");
 | 
			
		||||
@ -0,0 +1,33 @@
 | 
			
		||||
From 6b76638287055791e74b32c401a39ea1b91e7158 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Martin Kaistra <martin.kaistra@linutronix.de>
 | 
			
		||||
Date: Fri, 22 Dec 2023 11:14:33 +0100
 | 
			
		||||
Subject: [PATCH 12/21] wifi: rtl8xxxu: support multiple interfaces in
 | 
			
		||||
 configure_filter()
 | 
			
		||||
 | 
			
		||||
As we only want to support AP mode/sending beacons on port 0, change
 | 
			
		||||
from priv->vif to priv->vifs[0] in the check for AP mode.
 | 
			
		||||
Additionally, if we are in AP mode, don't filter RX beacon and probe
 | 
			
		||||
response frames to still allow working STATION mode on the other
 | 
			
		||||
interface.
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Martin Kaistra <martin.kaistra@linutronix.de>
 | 
			
		||||
Reviewed-by: Ping-Ke Shih <pkshih@realtek.com>
 | 
			
		||||
Signed-off-by: Kalle Valo <kvalo@kernel.org>
 | 
			
		||||
Link: https://msgid.link/20231222101442.626837-13-martin.kaistra@linutronix.de
 | 
			
		||||
---
 | 
			
		||||
 drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c | 4 ++--
 | 
			
		||||
 1 file changed, 2 insertions(+), 2 deletions(-)
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
 | 
			
		||||
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
 | 
			
		||||
@@ -6794,8 +6794,8 @@ static void rtl8xxxu_configure_filter(st
 | 
			
		||||
 	else
 | 
			
		||||
 		rcr |= RCR_CHECK_BSSID_BEACON | RCR_CHECK_BSSID_MATCH;
 | 
			
		||||
 
 | 
			
		||||
-	if (priv->vif && priv->vif->type == NL80211_IFTYPE_AP)
 | 
			
		||||
-		rcr &= ~RCR_CHECK_BSSID_MATCH;
 | 
			
		||||
+	if (priv->vifs[0] && priv->vifs[0]->type == NL80211_IFTYPE_AP)
 | 
			
		||||
+		rcr &= ~(RCR_CHECK_BSSID_MATCH | RCR_CHECK_BSSID_BEACON);
 | 
			
		||||
 
 | 
			
		||||
 	if (*total_flags & FIF_CONTROL)
 | 
			
		||||
 		rcr |= RCR_ACCEPT_CTRL_FRAME;
 | 
			
		||||
@ -0,0 +1,66 @@
 | 
			
		||||
From 3f9baa99f8429ea6f56e7cc8d881c027518e9573 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Martin Kaistra <martin.kaistra@linutronix.de>
 | 
			
		||||
Date: Fri, 22 Dec 2023 11:14:34 +0100
 | 
			
		||||
Subject: [PATCH 13/21] wifi: rtl8xxxu: support multiple interfaces in
 | 
			
		||||
 watchdog_callback()
 | 
			
		||||
 | 
			
		||||
Check first whether priv->vifs[0] exists and is of type STATION, then go
 | 
			
		||||
to priv->vifs[1]. Make sure to call refresh_rate_mask for both
 | 
			
		||||
interfaces.
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Martin Kaistra <martin.kaistra@linutronix.de>
 | 
			
		||||
Reviewed-by: Ping-Ke Shih <pkshih@realtek.com>
 | 
			
		||||
Signed-off-by: Kalle Valo <kvalo@kernel.org>
 | 
			
		||||
Link: https://msgid.link/20231222101442.626837-14-martin.kaistra@linutronix.de
 | 
			
		||||
---
 | 
			
		||||
 .../wireless/realtek/rtl8xxxu/rtl8xxxu_core.c | 19 +++++++++++--------
 | 
			
		||||
 1 file changed, 11 insertions(+), 8 deletions(-)
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
 | 
			
		||||
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
 | 
			
		||||
@@ -7200,11 +7200,15 @@ static void rtl8xxxu_watchdog_callback(s
 | 
			
		||||
 {
 | 
			
		||||
 	struct ieee80211_vif *vif;
 | 
			
		||||
 	struct rtl8xxxu_priv *priv;
 | 
			
		||||
+	int i;
 | 
			
		||||
 
 | 
			
		||||
 	priv = container_of(work, struct rtl8xxxu_priv, ra_watchdog.work);
 | 
			
		||||
-	vif = priv->vif;
 | 
			
		||||
+	for (i = 0; i < ARRAY_SIZE(priv->vifs); i++) {
 | 
			
		||||
+		vif = priv->vifs[i];
 | 
			
		||||
+
 | 
			
		||||
+		if (!vif || vif->type != NL80211_IFTYPE_STATION)
 | 
			
		||||
+			continue;
 | 
			
		||||
 
 | 
			
		||||
-	if (vif && vif->type == NL80211_IFTYPE_STATION) {
 | 
			
		||||
 		int signal;
 | 
			
		||||
 		struct ieee80211_sta *sta;
 | 
			
		||||
 
 | 
			
		||||
@@ -7215,22 +7219,21 @@ static void rtl8xxxu_watchdog_callback(s
 | 
			
		||||
 
 | 
			
		||||
 			dev_dbg(dev, "%s: no sta found\n", __func__);
 | 
			
		||||
 			rcu_read_unlock();
 | 
			
		||||
-			goto out;
 | 
			
		||||
+			continue;
 | 
			
		||||
 		}
 | 
			
		||||
 		rcu_read_unlock();
 | 
			
		||||
 
 | 
			
		||||
 		signal = ieee80211_ave_rssi(vif);
 | 
			
		||||
 
 | 
			
		||||
-		priv->fops->report_rssi(priv, 0,
 | 
			
		||||
+		priv->fops->report_rssi(priv, rtl8xxxu_get_macid(priv, sta),
 | 
			
		||||
 					rtl8xxxu_signal_to_snr(signal));
 | 
			
		||||
 
 | 
			
		||||
-		if (priv->fops->set_crystal_cap)
 | 
			
		||||
-			rtl8xxxu_track_cfo(priv);
 | 
			
		||||
-
 | 
			
		||||
 		rtl8xxxu_refresh_rate_mask(priv, signal, sta, false);
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
-out:
 | 
			
		||||
+	if (priv->fops->set_crystal_cap)
 | 
			
		||||
+		rtl8xxxu_track_cfo(priv);
 | 
			
		||||
+
 | 
			
		||||
 	schedule_delayed_work(&priv->ra_watchdog, 2 * HZ);
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
@ -0,0 +1,137 @@
 | 
			
		||||
From eef55f1545c92c7181d5083453dee1296298ad3e Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Martin Kaistra <martin.kaistra@linutronix.de>
 | 
			
		||||
Date: Fri, 22 Dec 2023 11:14:35 +0100
 | 
			
		||||
Subject: [PATCH 14/21] wifi: rtl8xxxu: support multiple interfaces in
 | 
			
		||||
 {add,remove}_interface()
 | 
			
		||||
 | 
			
		||||
Add a custom struct to store in vif->drv_priv with a reference to
 | 
			
		||||
port_num and fill it when a new interface is added. Choose a free
 | 
			
		||||
port_num for the newly added interface.
 | 
			
		||||
 | 
			
		||||
As we only want to support AP mode/sending beacons on port 0, only change
 | 
			
		||||
the beacon settings if a new interface is actually assigned to port 0.
 | 
			
		||||
 | 
			
		||||
Call set_linktype() and set_mac() with the appropriate port_num.
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Martin Kaistra <martin.kaistra@linutronix.de>
 | 
			
		||||
Reviewed-by: Ping-Ke Shih <pkshih@realtek.com>
 | 
			
		||||
Signed-off-by: Kalle Valo <kvalo@kernel.org>
 | 
			
		||||
Link: https://msgid.link/20231222101442.626837-15-martin.kaistra@linutronix.de
 | 
			
		||||
---
 | 
			
		||||
 .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.h  |  4 ++
 | 
			
		||||
 .../wireless/realtek/rtl8xxxu/rtl8xxxu_core.c | 52 +++++++++++--------
 | 
			
		||||
 2 files changed, 34 insertions(+), 22 deletions(-)
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h
 | 
			
		||||
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h
 | 
			
		||||
@@ -1921,6 +1921,10 @@ struct rtl8xxxu_sta_info {
 | 
			
		||||
 	u8 macid;
 | 
			
		||||
 };
 | 
			
		||||
 
 | 
			
		||||
+struct rtl8xxxu_vif {
 | 
			
		||||
+	int port_num;
 | 
			
		||||
+};
 | 
			
		||||
+
 | 
			
		||||
 struct rtl8xxxu_rx_urb {
 | 
			
		||||
 	struct urb urb;
 | 
			
		||||
 	struct ieee80211_hw *hw;
 | 
			
		||||
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
 | 
			
		||||
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
 | 
			
		||||
@@ -6610,28 +6610,33 @@ error:
 | 
			
		||||
 static int rtl8xxxu_add_interface(struct ieee80211_hw *hw,
 | 
			
		||||
 				  struct ieee80211_vif *vif)
 | 
			
		||||
 {
 | 
			
		||||
+	struct rtl8xxxu_vif *rtlvif = (struct rtl8xxxu_vif *)vif->drv_priv;
 | 
			
		||||
 	struct rtl8xxxu_priv *priv = hw->priv;
 | 
			
		||||
-	int ret;
 | 
			
		||||
+	int port_num;
 | 
			
		||||
 	u8 val8;
 | 
			
		||||
 
 | 
			
		||||
-	if (!priv->vif) {
 | 
			
		||||
-		priv->vif = vif;
 | 
			
		||||
-		priv->vifs[0] = vif;
 | 
			
		||||
-	} else {
 | 
			
		||||
+	if (!priv->vifs[0])
 | 
			
		||||
+		port_num = 0;
 | 
			
		||||
+	else if (!priv->vifs[1])
 | 
			
		||||
+		port_num = 1;
 | 
			
		||||
+	else
 | 
			
		||||
 		return -EOPNOTSUPP;
 | 
			
		||||
-	}
 | 
			
		||||
 
 | 
			
		||||
 	switch (vif->type) {
 | 
			
		||||
 	case NL80211_IFTYPE_STATION:
 | 
			
		||||
-		rtl8xxxu_stop_tx_beacon(priv);
 | 
			
		||||
+		if (port_num == 0) {
 | 
			
		||||
+			rtl8xxxu_stop_tx_beacon(priv);
 | 
			
		||||
 
 | 
			
		||||
-		val8 = rtl8xxxu_read8(priv, REG_BEACON_CTRL);
 | 
			
		||||
-		val8 |= BEACON_ATIM | BEACON_FUNCTION_ENABLE |
 | 
			
		||||
-			BEACON_DISABLE_TSF_UPDATE;
 | 
			
		||||
-		rtl8xxxu_write8(priv, REG_BEACON_CTRL, val8);
 | 
			
		||||
-		ret = 0;
 | 
			
		||||
+			val8 = rtl8xxxu_read8(priv, REG_BEACON_CTRL);
 | 
			
		||||
+			val8 |= BEACON_ATIM | BEACON_FUNCTION_ENABLE |
 | 
			
		||||
+				BEACON_DISABLE_TSF_UPDATE;
 | 
			
		||||
+			rtl8xxxu_write8(priv, REG_BEACON_CTRL, val8);
 | 
			
		||||
+		}
 | 
			
		||||
 		break;
 | 
			
		||||
 	case NL80211_IFTYPE_AP:
 | 
			
		||||
+		if (port_num == 1)
 | 
			
		||||
+			return -EOPNOTSUPP;
 | 
			
		||||
+
 | 
			
		||||
 		rtl8xxxu_write8(priv, REG_BEACON_CTRL,
 | 
			
		||||
 				BEACON_DISABLE_TSF_UPDATE | BEACON_CTRL_MBSSID);
 | 
			
		||||
 		rtl8xxxu_write8(priv, REG_ATIMWND, 0x0c); /* 12ms */
 | 
			
		||||
@@ -6648,31 +6653,32 @@ static int rtl8xxxu_add_interface(struct
 | 
			
		||||
 		val8 = rtl8xxxu_read8(priv, REG_CCK_CHECK);
 | 
			
		||||
 		val8 &= ~BIT_BCN_PORT_SEL;
 | 
			
		||||
 		rtl8xxxu_write8(priv, REG_CCK_CHECK, val8);
 | 
			
		||||
-
 | 
			
		||||
-		ret = 0;
 | 
			
		||||
 		break;
 | 
			
		||||
 	default:
 | 
			
		||||
-		ret = -EOPNOTSUPP;
 | 
			
		||||
+		return -EOPNOTSUPP;
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
-	rtl8xxxu_set_linktype(priv, vif->type, 0);
 | 
			
		||||
+	priv->vifs[port_num] = vif;
 | 
			
		||||
+	priv->vif = vif;
 | 
			
		||||
+	rtlvif->port_num = port_num;
 | 
			
		||||
+
 | 
			
		||||
+	rtl8xxxu_set_linktype(priv, vif->type, port_num);
 | 
			
		||||
 	ether_addr_copy(priv->mac_addr, vif->addr);
 | 
			
		||||
-	rtl8xxxu_set_mac(priv, 0);
 | 
			
		||||
+	rtl8xxxu_set_mac(priv, port_num);
 | 
			
		||||
 
 | 
			
		||||
-	return ret;
 | 
			
		||||
+	return 0;
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
 static void rtl8xxxu_remove_interface(struct ieee80211_hw *hw,
 | 
			
		||||
 				      struct ieee80211_vif *vif)
 | 
			
		||||
 {
 | 
			
		||||
+	struct rtl8xxxu_vif *rtlvif = (struct rtl8xxxu_vif *)vif->drv_priv;
 | 
			
		||||
 	struct rtl8xxxu_priv *priv = hw->priv;
 | 
			
		||||
 
 | 
			
		||||
 	dev_dbg(&priv->udev->dev, "%s\n", __func__);
 | 
			
		||||
 
 | 
			
		||||
-	if (priv->vif) {
 | 
			
		||||
-		priv->vif = NULL;
 | 
			
		||||
-		priv->vifs[0] = NULL;
 | 
			
		||||
-	}
 | 
			
		||||
+	priv->vif = NULL;
 | 
			
		||||
+	priv->vifs[rtlvif->port_num] = NULL;
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
 static int rtl8xxxu_config(struct ieee80211_hw *hw, u32 changed)
 | 
			
		||||
@@ -7661,6 +7667,8 @@ static int rtl8xxxu_probe(struct usb_int
 | 
			
		||||
 	if (ret)
 | 
			
		||||
 		goto err_set_intfdata;
 | 
			
		||||
 
 | 
			
		||||
+	hw->vif_data_size = sizeof(struct rtl8xxxu_vif);
 | 
			
		||||
+
 | 
			
		||||
 	hw->wiphy->max_scan_ssids = 1;
 | 
			
		||||
 	hw->wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN;
 | 
			
		||||
 	if (priv->fops->max_macid_num)
 | 
			
		||||
@ -0,0 +1,57 @@
 | 
			
		||||
From 073401c3b6b9eaea027240baf07f2b84dd2d2d26 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Martin Kaistra <martin.kaistra@linutronix.de>
 | 
			
		||||
Date: Fri, 22 Dec 2023 11:14:36 +0100
 | 
			
		||||
Subject: [PATCH 15/21] wifi: rtl8xxxu: support multiple interfaces in
 | 
			
		||||
 bss_info_changed()
 | 
			
		||||
 | 
			
		||||
Call set_linktype and set_bssid now with correct port_num. Call
 | 
			
		||||
stop_tx_beacon only for port 0, as we don't support beacons on port 1.
 | 
			
		||||
Explicit changes to BEACON will only happen for AP type interfaces, so
 | 
			
		||||
we don't need an additional check there.
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Martin Kaistra <martin.kaistra@linutronix.de>
 | 
			
		||||
Reviewed-by: Ping-Ke Shih <pkshih@realtek.com>
 | 
			
		||||
Signed-off-by: Kalle Valo <kvalo@kernel.org>
 | 
			
		||||
Link: https://msgid.link/20231222101442.626837-16-martin.kaistra@linutronix.de
 | 
			
		||||
---
 | 
			
		||||
 drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c | 8 +++++---
 | 
			
		||||
 1 file changed, 5 insertions(+), 3 deletions(-)
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
 | 
			
		||||
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
 | 
			
		||||
@@ -4983,6 +4983,7 @@ static void
 | 
			
		||||
 rtl8xxxu_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 | 
			
		||||
 			  struct ieee80211_bss_conf *bss_conf, u64 changed)
 | 
			
		||||
 {
 | 
			
		||||
+	struct rtl8xxxu_vif *rtlvif = (struct rtl8xxxu_vif *)vif->drv_priv;
 | 
			
		||||
 	struct rtl8xxxu_priv *priv = hw->priv;
 | 
			
		||||
 	struct device *dev = &priv->udev->dev;
 | 
			
		||||
 	struct ieee80211_sta *sta;
 | 
			
		||||
@@ -4995,7 +4996,7 @@ rtl8xxxu_bss_info_changed(struct ieee802
 | 
			
		||||
 	if (changed & BSS_CHANGED_ASSOC) {
 | 
			
		||||
 		dev_dbg(dev, "Changed ASSOC: %i!\n", vif->cfg.assoc);
 | 
			
		||||
 
 | 
			
		||||
-		rtl8xxxu_set_linktype(priv, vif->type, 0);
 | 
			
		||||
+		rtl8xxxu_set_linktype(priv, vif->type, rtlvif->port_num);
 | 
			
		||||
 
 | 
			
		||||
 		if (vif->cfg.assoc) {
 | 
			
		||||
 			u32 ramask;
 | 
			
		||||
@@ -5042,7 +5043,8 @@ rtl8xxxu_bss_info_changed(struct ieee802
 | 
			
		||||
 
 | 
			
		||||
 			rtl8xxxu_write8(priv, REG_BCN_MAX_ERR, 0xff);
 | 
			
		||||
 
 | 
			
		||||
-			rtl8xxxu_stop_tx_beacon(priv);
 | 
			
		||||
+			if (rtlvif->port_num == 0)
 | 
			
		||||
+				rtl8xxxu_stop_tx_beacon(priv);
 | 
			
		||||
 
 | 
			
		||||
 			/* joinbss sequence */
 | 
			
		||||
 			rtl8xxxu_write16(priv, REG_BCN_PSR_RPT,
 | 
			
		||||
@@ -5084,7 +5086,7 @@ rtl8xxxu_bss_info_changed(struct ieee802
 | 
			
		||||
 
 | 
			
		||||
 	if (changed & BSS_CHANGED_BSSID) {
 | 
			
		||||
 		dev_dbg(dev, "Changed BSSID!\n");
 | 
			
		||||
-		rtl8xxxu_set_bssid(priv, bss_conf->bssid, 0);
 | 
			
		||||
+		rtl8xxxu_set_bssid(priv, bss_conf->bssid, rtlvif->port_num);
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
 	if (changed & BSS_CHANGED_BASIC_RATES) {
 | 
			
		||||
@ -0,0 +1,32 @@
 | 
			
		||||
From 61fdbd9e2a9d74c716bf4d9684653de5efdee691 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Martin Kaistra <martin.kaistra@linutronix.de>
 | 
			
		||||
Date: Fri, 22 Dec 2023 11:14:37 +0100
 | 
			
		||||
Subject: [PATCH 16/21] wifi: rtl8xxxu: support multiple interface in
 | 
			
		||||
 start_ap()
 | 
			
		||||
 | 
			
		||||
Call set_bssid() with the correct port_num now.
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Martin Kaistra <martin.kaistra@linutronix.de>
 | 
			
		||||
Reviewed-by: Ping-Ke Shih <pkshih@realtek.com>
 | 
			
		||||
Signed-off-by: Kalle Valo <kvalo@kernel.org>
 | 
			
		||||
Link: https://msgid.link/20231222101442.626837-17-martin.kaistra@linutronix.de
 | 
			
		||||
---
 | 
			
		||||
 drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c | 3 ++-
 | 
			
		||||
 1 file changed, 2 insertions(+), 1 deletion(-)
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
 | 
			
		||||
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
 | 
			
		||||
@@ -5111,11 +5111,12 @@ error:
 | 
			
		||||
 static int rtl8xxxu_start_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 | 
			
		||||
 			     struct ieee80211_bss_conf *link_conf)
 | 
			
		||||
 {
 | 
			
		||||
+	struct rtl8xxxu_vif *rtlvif = (struct rtl8xxxu_vif *)vif->drv_priv;
 | 
			
		||||
 	struct rtl8xxxu_priv *priv = hw->priv;
 | 
			
		||||
 	struct device *dev = &priv->udev->dev;
 | 
			
		||||
 
 | 
			
		||||
 	dev_dbg(dev, "Start AP mode\n");
 | 
			
		||||
-	rtl8xxxu_set_bssid(priv, vif->bss_conf.bssid, 0);
 | 
			
		||||
+	rtl8xxxu_set_bssid(priv, vif->bss_conf.bssid, rtlvif->port_num);
 | 
			
		||||
 	rtl8xxxu_write16(priv, REG_BCN_INTERVAL, vif->bss_conf.beacon_int);
 | 
			
		||||
 	priv->fops->report_connect(priv, RTL8XXXU_BC_MC_MACID, 0, true);
 | 
			
		||||
 
 | 
			
		||||
@ -0,0 +1,82 @@
 | 
			
		||||
From 5ce0d7e8aee03e73b35f0fe1f1ebbdd4e45776f3 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Martin Kaistra <martin.kaistra@linutronix.de>
 | 
			
		||||
Date: Fri, 22 Dec 2023 11:14:38 +0100
 | 
			
		||||
Subject: [PATCH 17/21] wifi: rtl8xxxu: add macids for STA mode
 | 
			
		||||
 | 
			
		||||
Until now, the driver only assigned a dedicated macid for connections
 | 
			
		||||
made in AP mode, in STA mode the return value of rtl8xxxu_get_macid()
 | 
			
		||||
was simply 0.
 | 
			
		||||
To differentiate between port 0 and 1, when both are in STA mode,
 | 
			
		||||
allocate a second macid (with value 1) and set sta_info->macid according
 | 
			
		||||
to the used port_num in rtl8xxxu_sta_add().
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Martin Kaistra <martin.kaistra@linutronix.de>
 | 
			
		||||
Reviewed-by: Ping-Ke Shih <pkshih@realtek.com>
 | 
			
		||||
Signed-off-by: Kalle Valo <kvalo@kernel.org>
 | 
			
		||||
Link: https://msgid.link/20231222101442.626837-18-martin.kaistra@linutronix.de
 | 
			
		||||
---
 | 
			
		||||
 .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.h   |  1 +
 | 
			
		||||
 .../wireless/realtek/rtl8xxxu/rtl8xxxu_core.c  | 18 +++++++++++++++++-
 | 
			
		||||
 2 files changed, 18 insertions(+), 1 deletion(-)
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h
 | 
			
		||||
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h
 | 
			
		||||
@@ -1774,6 +1774,7 @@ struct rtl8xxxu_cfo_tracking {
 | 
			
		||||
 #define RTL8XXXU_HW_LED_CONTROL	2
 | 
			
		||||
 #define RTL8XXXU_MAX_MAC_ID_NUM	128
 | 
			
		||||
 #define RTL8XXXU_BC_MC_MACID	0
 | 
			
		||||
+#define RTL8XXXU_BC_MC_MACID1	1
 | 
			
		||||
 
 | 
			
		||||
 struct rtl8xxxu_priv {
 | 
			
		||||
 	struct ieee80211_hw *hw;
 | 
			
		||||
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
 | 
			
		||||
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
 | 
			
		||||
@@ -4053,10 +4053,13 @@ static inline u8 rtl8xxxu_get_macid(stru
 | 
			
		||||
 {
 | 
			
		||||
 	struct rtl8xxxu_sta_info *sta_info;
 | 
			
		||||
 
 | 
			
		||||
-	if (!priv->vif || priv->vif->type == NL80211_IFTYPE_STATION || !sta)
 | 
			
		||||
+	if (!sta)
 | 
			
		||||
 		return 0;
 | 
			
		||||
 
 | 
			
		||||
 	sta_info = (struct rtl8xxxu_sta_info *)sta->drv_priv;
 | 
			
		||||
+	if (!sta_info)
 | 
			
		||||
+		return 0;
 | 
			
		||||
+
 | 
			
		||||
 	return sta_info->macid;
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
@@ -4536,6 +4539,7 @@ static int rtl8xxxu_init_device(struct i
 | 
			
		||||
 		rtl8188e_ra_info_init_all(&priv->ra_info);
 | 
			
		||||
 
 | 
			
		||||
 	set_bit(RTL8XXXU_BC_MC_MACID, priv->mac_id_map);
 | 
			
		||||
+	set_bit(RTL8XXXU_BC_MC_MACID1, priv->mac_id_map);
 | 
			
		||||
 
 | 
			
		||||
 exit:
 | 
			
		||||
 	return ret;
 | 
			
		||||
@@ -7375,6 +7379,7 @@ static int rtl8xxxu_sta_add(struct ieee8
 | 
			
		||||
 			    struct ieee80211_sta *sta)
 | 
			
		||||
 {
 | 
			
		||||
 	struct rtl8xxxu_sta_info *sta_info = (struct rtl8xxxu_sta_info *)sta->drv_priv;
 | 
			
		||||
+	struct rtl8xxxu_vif *rtlvif = (struct rtl8xxxu_vif *)vif->drv_priv;
 | 
			
		||||
 	struct rtl8xxxu_priv *priv = hw->priv;
 | 
			
		||||
 
 | 
			
		||||
 	if (vif->type == NL80211_IFTYPE_AP) {
 | 
			
		||||
@@ -7384,6 +7389,17 @@ static int rtl8xxxu_sta_add(struct ieee8
 | 
			
		||||
 
 | 
			
		||||
 		rtl8xxxu_refresh_rate_mask(priv, 0, sta, true);
 | 
			
		||||
 		priv->fops->report_connect(priv, sta_info->macid, H2C_MACID_ROLE_STA, true);
 | 
			
		||||
+	} else {
 | 
			
		||||
+		switch (rtlvif->port_num) {
 | 
			
		||||
+		case 0:
 | 
			
		||||
+			sta_info->macid = RTL8XXXU_BC_MC_MACID;
 | 
			
		||||
+			break;
 | 
			
		||||
+		case 1:
 | 
			
		||||
+			sta_info->macid = RTL8XXXU_BC_MC_MACID1;
 | 
			
		||||
+			break;
 | 
			
		||||
+		default:
 | 
			
		||||
+			break;
 | 
			
		||||
+		}
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
 	return 0;
 | 
			
		||||
@ -0,0 +1,49 @@
 | 
			
		||||
From f232e9d91bb84817c60c051a3e3b56dd2721a7b3 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Martin Kaistra <martin.kaistra@linutronix.de>
 | 
			
		||||
Date: Fri, 22 Dec 2023 11:14:39 +0100
 | 
			
		||||
Subject: [PATCH 18/21] wifi: rtl8xxxu: remove obsolete priv->vif
 | 
			
		||||
 | 
			
		||||
Now that all uses of priv->vif have been converted to priv->vifs[]
 | 
			
		||||
remove the old attribute.
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Martin Kaistra <martin.kaistra@linutronix.de>
 | 
			
		||||
Reviewed-by: Ping-Ke Shih <pkshih@realtek.com>
 | 
			
		||||
Signed-off-by: Kalle Valo <kvalo@kernel.org>
 | 
			
		||||
Link: https://msgid.link/20231222101442.626837-19-martin.kaistra@linutronix.de
 | 
			
		||||
---
 | 
			
		||||
 drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h      | 5 -----
 | 
			
		||||
 drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c | 2 --
 | 
			
		||||
 2 files changed, 7 deletions(-)
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h
 | 
			
		||||
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h
 | 
			
		||||
@@ -1893,11 +1893,6 @@ struct rtl8xxxu_priv {
 | 
			
		||||
 	u8 rssi_level;
 | 
			
		||||
 	DECLARE_BITMAP(tx_aggr_started, IEEE80211_NUM_TIDS);
 | 
			
		||||
 	DECLARE_BITMAP(tid_tx_operational, IEEE80211_NUM_TIDS);
 | 
			
		||||
-	/*
 | 
			
		||||
-	 * Only one virtual interface permitted because only STA mode
 | 
			
		||||
-	 * is supported and no iface_combinations are provided.
 | 
			
		||||
-	 */
 | 
			
		||||
-	struct ieee80211_vif *vif;
 | 
			
		||||
 
 | 
			
		||||
 	struct ieee80211_vif *vifs[2];
 | 
			
		||||
 	struct delayed_work ra_watchdog;
 | 
			
		||||
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
 | 
			
		||||
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
 | 
			
		||||
@@ -6666,7 +6666,6 @@ static int rtl8xxxu_add_interface(struct
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
 	priv->vifs[port_num] = vif;
 | 
			
		||||
-	priv->vif = vif;
 | 
			
		||||
 	rtlvif->port_num = port_num;
 | 
			
		||||
 
 | 
			
		||||
 	rtl8xxxu_set_linktype(priv, vif->type, port_num);
 | 
			
		||||
@@ -6684,7 +6683,6 @@ static void rtl8xxxu_remove_interface(st
 | 
			
		||||
 
 | 
			
		||||
 	dev_dbg(&priv->udev->dev, "%s\n", __func__);
 | 
			
		||||
 
 | 
			
		||||
-	priv->vif = NULL;
 | 
			
		||||
 	priv->vifs[rtlvif->port_num] = NULL;
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
@ -0,0 +1,226 @@
 | 
			
		||||
From b837f78fbffa5f8e7e7c59879db54793abf161ec Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Martin Kaistra <martin.kaistra@linutronix.de>
 | 
			
		||||
Date: Fri, 22 Dec 2023 11:14:40 +0100
 | 
			
		||||
Subject: [PATCH 19/21] wifi: rtl8xxxu: add hw crypto support for AP mode
 | 
			
		||||
 | 
			
		||||
Add a custom function for allocating entries in the sec cam. This allows
 | 
			
		||||
us to store multiple keys with the same keyidx.
 | 
			
		||||
 | 
			
		||||
The maximum number of sec cam entries for 8188f is 16 according to the
 | 
			
		||||
vendor driver. Add the number to rtl8xxxu_fileops, so that other chips
 | 
			
		||||
which might support more entries, can set a different number there.
 | 
			
		||||
 | 
			
		||||
Set the bssid as mac address for group keys instead of just using the
 | 
			
		||||
ethernet broadcast address and use BIT(6) in the sec cam ctrl entry
 | 
			
		||||
for differentiating them from pairwise keys like in the vendor driver.
 | 
			
		||||
 | 
			
		||||
Add the TXDESC_EN_DESC_ID bit and the hw_key_idx to tx
 | 
			
		||||
broadcast/multicast packets in AP mode.
 | 
			
		||||
 | 
			
		||||
Finally, allow the usage of rtl8xxxu_set_key() for AP mode.
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Martin Kaistra <martin.kaistra@linutronix.de>
 | 
			
		||||
Reviewed-by: Ping-Ke Shih <pkshih@realtek.com>
 | 
			
		||||
Signed-off-by: Kalle Valo <kvalo@kernel.org>
 | 
			
		||||
Link: https://msgid.link/20231222101442.626837-20-martin.kaistra@linutronix.de
 | 
			
		||||
---
 | 
			
		||||
 .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.h  |  5 ++
 | 
			
		||||
 .../realtek/rtl8xxxu/rtl8xxxu_8188f.c         |  1 +
 | 
			
		||||
 .../wireless/realtek/rtl8xxxu/rtl8xxxu_core.c | 48 +++++++++++++++----
 | 
			
		||||
 3 files changed, 44 insertions(+), 10 deletions(-)
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h
 | 
			
		||||
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h
 | 
			
		||||
@@ -498,6 +498,7 @@ struct rtl8xxxu_txdesc40 {
 | 
			
		||||
 #define DESC_RATE_ID_SHIFT		16
 | 
			
		||||
 #define DESC_RATE_ID_MASK		0xf
 | 
			
		||||
 #define TXDESC_NAVUSEHDR		BIT(20)
 | 
			
		||||
+#define TXDESC_EN_DESC_ID		BIT(21)
 | 
			
		||||
 #define TXDESC_SEC_RC4			0x00400000
 | 
			
		||||
 #define TXDESC_SEC_AES			0x00c00000
 | 
			
		||||
 #define TXDESC_PKT_OFFSET_SHIFT		26
 | 
			
		||||
@@ -1775,6 +1776,7 @@ struct rtl8xxxu_cfo_tracking {
 | 
			
		||||
 #define RTL8XXXU_MAX_MAC_ID_NUM	128
 | 
			
		||||
 #define RTL8XXXU_BC_MC_MACID	0
 | 
			
		||||
 #define RTL8XXXU_BC_MC_MACID1	1
 | 
			
		||||
+#define RTL8XXXU_MAX_SEC_CAM_NUM	64
 | 
			
		||||
 
 | 
			
		||||
 struct rtl8xxxu_priv {
 | 
			
		||||
 	struct ieee80211_hw *hw;
 | 
			
		||||
@@ -1908,6 +1910,7 @@ struct rtl8xxxu_priv {
 | 
			
		||||
 	char led_name[32];
 | 
			
		||||
 	struct led_classdev led_cdev;
 | 
			
		||||
 	DECLARE_BITMAP(mac_id_map, RTL8XXXU_MAX_MAC_ID_NUM);
 | 
			
		||||
+	DECLARE_BITMAP(cam_map, RTL8XXXU_MAX_SEC_CAM_NUM);
 | 
			
		||||
 };
 | 
			
		||||
 
 | 
			
		||||
 struct rtl8xxxu_sta_info {
 | 
			
		||||
@@ -1919,6 +1922,7 @@ struct rtl8xxxu_sta_info {
 | 
			
		||||
 
 | 
			
		||||
 struct rtl8xxxu_vif {
 | 
			
		||||
 	int port_num;
 | 
			
		||||
+	u8 hw_key_idx;
 | 
			
		||||
 };
 | 
			
		||||
 
 | 
			
		||||
 struct rtl8xxxu_rx_urb {
 | 
			
		||||
@@ -1993,6 +1997,7 @@ struct rtl8xxxu_fileops {
 | 
			
		||||
 	u16 max_aggr_num;
 | 
			
		||||
 	u8 supports_ap:1;
 | 
			
		||||
 	u16 max_macid_num;
 | 
			
		||||
+	u16 max_sec_cam_num;
 | 
			
		||||
 	u32 adda_1t_init;
 | 
			
		||||
 	u32 adda_1t_path_on;
 | 
			
		||||
 	u32 adda_2t_path_on_a;
 | 
			
		||||
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8188f.c
 | 
			
		||||
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8188f.c
 | 
			
		||||
@@ -1751,6 +1751,7 @@ struct rtl8xxxu_fileops rtl8188fu_fops =
 | 
			
		||||
 	.max_aggr_num = 0x0c14,
 | 
			
		||||
 	.supports_ap = 1,
 | 
			
		||||
 	.max_macid_num = 16,
 | 
			
		||||
+	.max_sec_cam_num = 16,
 | 
			
		||||
 	.adda_1t_init = 0x03c00014,
 | 
			
		||||
 	.adda_1t_path_on = 0x03c00014,
 | 
			
		||||
 	.trxff_boundary = 0x3f7f,
 | 
			
		||||
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
 | 
			
		||||
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
 | 
			
		||||
@@ -4559,8 +4559,10 @@ static void rtl8xxxu_cam_write(struct rt
 | 
			
		||||
 	 * This is a bit of a hack - the lower bits of the cipher
 | 
			
		||||
 	 * suite selector happens to match the cipher index in the CAM
 | 
			
		||||
 	 */
 | 
			
		||||
-	addr = key->keyidx << CAM_CMD_KEY_SHIFT;
 | 
			
		||||
+	addr = key->hw_key_idx << CAM_CMD_KEY_SHIFT;
 | 
			
		||||
 	ctrl = (key->cipher & 0x0f) << 2 | key->keyidx | CAM_WRITE_VALID;
 | 
			
		||||
+	if (!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE))
 | 
			
		||||
+		ctrl |= BIT(6);
 | 
			
		||||
 
 | 
			
		||||
 	for (j = 5; j >= 0; j--) {
 | 
			
		||||
 		switch (j) {
 | 
			
		||||
@@ -5546,13 +5548,14 @@ static void rtl8xxxu_tx(struct ieee80211
 | 
			
		||||
 	struct rtl8xxxu_tx_urb *tx_urb;
 | 
			
		||||
 	struct ieee80211_sta *sta = NULL;
 | 
			
		||||
 	struct ieee80211_vif *vif = tx_info->control.vif;
 | 
			
		||||
+	struct rtl8xxxu_vif *rtlvif = (struct rtl8xxxu_vif *)vif->drv_priv;
 | 
			
		||||
 	struct device *dev = &priv->udev->dev;
 | 
			
		||||
 	u32 queue, rts_rate;
 | 
			
		||||
 	u16 pktlen = skb->len;
 | 
			
		||||
 	int tx_desc_size = priv->fops->tx_desc_size;
 | 
			
		||||
 	u8 macid;
 | 
			
		||||
 	int ret;
 | 
			
		||||
-	bool ampdu_enable, sgi = false, short_preamble = false;
 | 
			
		||||
+	bool ampdu_enable, sgi = false, short_preamble = false, bmc = false;
 | 
			
		||||
 
 | 
			
		||||
 	if (skb_headroom(skb) < tx_desc_size) {
 | 
			
		||||
 		dev_warn(dev,
 | 
			
		||||
@@ -5594,10 +5597,14 @@ static void rtl8xxxu_tx(struct ieee80211
 | 
			
		||||
 		tx_desc->txdw0 =
 | 
			
		||||
 			TXDESC_OWN | TXDESC_FIRST_SEGMENT | TXDESC_LAST_SEGMENT;
 | 
			
		||||
 	if (is_multicast_ether_addr(ieee80211_get_DA(hdr)) ||
 | 
			
		||||
-	    is_broadcast_ether_addr(ieee80211_get_DA(hdr)))
 | 
			
		||||
+	    is_broadcast_ether_addr(ieee80211_get_DA(hdr))) {
 | 
			
		||||
 		tx_desc->txdw0 |= TXDESC_BROADMULTICAST;
 | 
			
		||||
+		bmc = true;
 | 
			
		||||
+	}
 | 
			
		||||
+
 | 
			
		||||
 
 | 
			
		||||
 	tx_desc->txdw1 = cpu_to_le32(queue << TXDESC_QUEUE_SHIFT);
 | 
			
		||||
+	macid = rtl8xxxu_get_macid(priv, sta);
 | 
			
		||||
 
 | 
			
		||||
 	if (tx_info->control.hw_key) {
 | 
			
		||||
 		switch (tx_info->control.hw_key->cipher) {
 | 
			
		||||
@@ -5612,6 +5619,10 @@ static void rtl8xxxu_tx(struct ieee80211
 | 
			
		||||
 		default:
 | 
			
		||||
 			break;
 | 
			
		||||
 		}
 | 
			
		||||
+		if (bmc && rtlvif->hw_key_idx != 0xff) {
 | 
			
		||||
+			tx_desc->txdw1 |= TXDESC_EN_DESC_ID;
 | 
			
		||||
+			macid = rtlvif->hw_key_idx;
 | 
			
		||||
+		}
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
 	/* (tx_info->flags & IEEE80211_TX_CTL_AMPDU) && */
 | 
			
		||||
@@ -5655,7 +5666,6 @@ static void rtl8xxxu_tx(struct ieee80211
 | 
			
		||||
 	else
 | 
			
		||||
 		rts_rate = 0;
 | 
			
		||||
 
 | 
			
		||||
-	macid = rtl8xxxu_get_macid(priv, sta);
 | 
			
		||||
 	priv->fops->fill_txdesc(hw, hdr, tx_info, tx_desc, sgi, short_preamble,
 | 
			
		||||
 				ampdu_enable, rts_rate, macid);
 | 
			
		||||
 
 | 
			
		||||
@@ -6667,6 +6677,7 @@ static int rtl8xxxu_add_interface(struct
 | 
			
		||||
 
 | 
			
		||||
 	priv->vifs[port_num] = vif;
 | 
			
		||||
 	rtlvif->port_num = port_num;
 | 
			
		||||
+	rtlvif->hw_key_idx = 0xff;
 | 
			
		||||
 
 | 
			
		||||
 	rtl8xxxu_set_linktype(priv, vif->type, port_num);
 | 
			
		||||
 	ether_addr_copy(priv->mac_addr, vif->addr);
 | 
			
		||||
@@ -6843,11 +6854,19 @@ static int rtl8xxxu_set_rts_threshold(st
 | 
			
		||||
 	return 0;
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
+static int rtl8xxxu_get_free_sec_cam(struct ieee80211_hw *hw)
 | 
			
		||||
+{
 | 
			
		||||
+	struct rtl8xxxu_priv *priv = hw->priv;
 | 
			
		||||
+
 | 
			
		||||
+	return find_first_zero_bit(priv->cam_map, priv->fops->max_sec_cam_num);
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
 static int rtl8xxxu_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
 | 
			
		||||
 			    struct ieee80211_vif *vif,
 | 
			
		||||
 			    struct ieee80211_sta *sta,
 | 
			
		||||
 			    struct ieee80211_key_conf *key)
 | 
			
		||||
 {
 | 
			
		||||
+	struct rtl8xxxu_vif *rtlvif = (struct rtl8xxxu_vif *)vif->drv_priv;
 | 
			
		||||
 	struct rtl8xxxu_priv *priv = hw->priv;
 | 
			
		||||
 	struct device *dev = &priv->udev->dev;
 | 
			
		||||
 	u8 mac_addr[ETH_ALEN];
 | 
			
		||||
@@ -6859,9 +6878,6 @@ static int rtl8xxxu_set_key(struct ieee8
 | 
			
		||||
 	dev_dbg(dev, "%s: cmd %02x, cipher %08x, index %i\n",
 | 
			
		||||
 		__func__, cmd, key->cipher, key->keyidx);
 | 
			
		||||
 
 | 
			
		||||
-	if (vif->type != NL80211_IFTYPE_STATION)
 | 
			
		||||
-		return -EOPNOTSUPP;
 | 
			
		||||
-
 | 
			
		||||
 	if (key->keyidx > 3)
 | 
			
		||||
 		return -EOPNOTSUPP;
 | 
			
		||||
 
 | 
			
		||||
@@ -6885,7 +6901,7 @@ static int rtl8xxxu_set_key(struct ieee8
 | 
			
		||||
 		ether_addr_copy(mac_addr, sta->addr);
 | 
			
		||||
 	} else {
 | 
			
		||||
 		dev_dbg(dev, "%s: group key\n", __func__);
 | 
			
		||||
-		eth_broadcast_addr(mac_addr);
 | 
			
		||||
+		ether_addr_copy(mac_addr, vif->bss_conf.bssid);
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
 	val16 = rtl8xxxu_read16(priv, REG_CR);
 | 
			
		||||
@@ -6899,16 +6915,28 @@ static int rtl8xxxu_set_key(struct ieee8
 | 
			
		||||
 
 | 
			
		||||
 	switch (cmd) {
 | 
			
		||||
 	case SET_KEY:
 | 
			
		||||
-		key->hw_key_idx = key->keyidx;
 | 
			
		||||
+
 | 
			
		||||
+		retval = rtl8xxxu_get_free_sec_cam(hw);
 | 
			
		||||
+		if (retval < 0)
 | 
			
		||||
+			return -EOPNOTSUPP;
 | 
			
		||||
+
 | 
			
		||||
+		key->hw_key_idx = retval;
 | 
			
		||||
+
 | 
			
		||||
+		if (vif->type == NL80211_IFTYPE_AP && !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE))
 | 
			
		||||
+			rtlvif->hw_key_idx = key->hw_key_idx;
 | 
			
		||||
+
 | 
			
		||||
 		key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
 | 
			
		||||
 		rtl8xxxu_cam_write(priv, key, mac_addr);
 | 
			
		||||
+		set_bit(key->hw_key_idx, priv->cam_map);
 | 
			
		||||
 		retval = 0;
 | 
			
		||||
 		break;
 | 
			
		||||
 	case DISABLE_KEY:
 | 
			
		||||
 		rtl8xxxu_write32(priv, REG_CAM_WRITE, 0x00000000);
 | 
			
		||||
 		val32 = CAM_CMD_POLLING | CAM_CMD_WRITE |
 | 
			
		||||
-			key->keyidx << CAM_CMD_KEY_SHIFT;
 | 
			
		||||
+			key->hw_key_idx << CAM_CMD_KEY_SHIFT;
 | 
			
		||||
 		rtl8xxxu_write32(priv, REG_CAM_CMD, val32);
 | 
			
		||||
+		rtlvif->hw_key_idx = 0xff;
 | 
			
		||||
+		clear_bit(key->hw_key_idx, priv->cam_map);
 | 
			
		||||
 		retval = 0;
 | 
			
		||||
 		break;
 | 
			
		||||
 	default:
 | 
			
		||||
@ -0,0 +1,130 @@
 | 
			
		||||
From 69abad618efd17e50bc6f880332ab36b660b0b34 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Martin Kaistra <martin.kaistra@linutronix.de>
 | 
			
		||||
Date: Fri, 22 Dec 2023 11:14:41 +0100
 | 
			
		||||
Subject: [PATCH 20/21] wifi: rtl8xxxu: make supporting AP mode only on port 0
 | 
			
		||||
 transparent
 | 
			
		||||
 | 
			
		||||
When the driver is used for concurrent mode, both virtual interfaces can
 | 
			
		||||
be set to station or AP mode, though only one can be in AP mode at the
 | 
			
		||||
same time.
 | 
			
		||||
 | 
			
		||||
In order to keep the code simple, use only hw port 0 for AP mode. When
 | 
			
		||||
an interface is added in AP mode which would be assigned to port 1, use
 | 
			
		||||
a switch_port function to transparently swap the mapping between virtual
 | 
			
		||||
interface and hw port.
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Martin Kaistra <martin.kaistra@linutronix.de>
 | 
			
		||||
Reviewed-by: Ping-Ke Shih <pkshih@realtek.com>
 | 
			
		||||
Signed-off-by: Kalle Valo <kvalo@kernel.org>
 | 
			
		||||
Link: https://msgid.link/20231222101442.626837-21-martin.kaistra@linutronix.de
 | 
			
		||||
---
 | 
			
		||||
 .../wireless/realtek/rtl8xxxu/rtl8xxxu_core.c | 91 ++++++++++++++++++-
 | 
			
		||||
 1 file changed, 89 insertions(+), 2 deletions(-)
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
 | 
			
		||||
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
 | 
			
		||||
@@ -6624,6 +6624,91 @@ error:
 | 
			
		||||
 	return ret;
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
+static void rtl8xxxu_switch_ports(struct rtl8xxxu_priv *priv)
 | 
			
		||||
+{
 | 
			
		||||
+	u8 macid[ETH_ALEN], bssid[ETH_ALEN], macid_1[ETH_ALEN], bssid_1[ETH_ALEN];
 | 
			
		||||
+	u8 msr, bcn_ctrl, bcn_ctrl_1, atimwnd[2], atimwnd_1[2];
 | 
			
		||||
+	struct rtl8xxxu_vif *rtlvif;
 | 
			
		||||
+	struct ieee80211_vif *vif;
 | 
			
		||||
+	u8 tsftr[8], tsftr_1[8];
 | 
			
		||||
+	int i;
 | 
			
		||||
+
 | 
			
		||||
+	msr = rtl8xxxu_read8(priv, REG_MSR);
 | 
			
		||||
+	bcn_ctrl = rtl8xxxu_read8(priv, REG_BEACON_CTRL);
 | 
			
		||||
+	bcn_ctrl_1 = rtl8xxxu_read8(priv, REG_BEACON_CTRL_1);
 | 
			
		||||
+
 | 
			
		||||
+	for (i = 0; i < ARRAY_SIZE(atimwnd); i++)
 | 
			
		||||
+		atimwnd[i] = rtl8xxxu_read8(priv, REG_ATIMWND + i);
 | 
			
		||||
+	for (i = 0; i < ARRAY_SIZE(atimwnd_1); i++)
 | 
			
		||||
+		atimwnd_1[i] = rtl8xxxu_read8(priv, REG_ATIMWND_1 + i);
 | 
			
		||||
+
 | 
			
		||||
+	for (i = 0; i < ARRAY_SIZE(tsftr); i++)
 | 
			
		||||
+		tsftr[i] = rtl8xxxu_read8(priv, REG_TSFTR + i);
 | 
			
		||||
+	for (i = 0; i < ARRAY_SIZE(tsftr); i++)
 | 
			
		||||
+		tsftr_1[i] = rtl8xxxu_read8(priv, REG_TSFTR1 + i);
 | 
			
		||||
+
 | 
			
		||||
+	for (i = 0; i < ARRAY_SIZE(macid); i++)
 | 
			
		||||
+		macid[i] = rtl8xxxu_read8(priv, REG_MACID + i);
 | 
			
		||||
+
 | 
			
		||||
+	for (i = 0; i < ARRAY_SIZE(bssid); i++)
 | 
			
		||||
+		bssid[i] = rtl8xxxu_read8(priv, REG_BSSID + i);
 | 
			
		||||
+
 | 
			
		||||
+	for (i = 0; i < ARRAY_SIZE(macid_1); i++)
 | 
			
		||||
+		macid_1[i] = rtl8xxxu_read8(priv, REG_MACID1 + i);
 | 
			
		||||
+
 | 
			
		||||
+	for (i = 0; i < ARRAY_SIZE(bssid_1); i++)
 | 
			
		||||
+		bssid_1[i] = rtl8xxxu_read8(priv, REG_BSSID1 + i);
 | 
			
		||||
+
 | 
			
		||||
+	/* disable bcn function, disable update TSF */
 | 
			
		||||
+	rtl8xxxu_write8(priv, REG_BEACON_CTRL, (bcn_ctrl &
 | 
			
		||||
+			(~BEACON_FUNCTION_ENABLE)) | BEACON_DISABLE_TSF_UPDATE);
 | 
			
		||||
+	rtl8xxxu_write8(priv, REG_BEACON_CTRL_1, (bcn_ctrl_1 &
 | 
			
		||||
+			(~BEACON_FUNCTION_ENABLE)) | BEACON_DISABLE_TSF_UPDATE);
 | 
			
		||||
+
 | 
			
		||||
+	/* switch msr */
 | 
			
		||||
+	msr = (msr & 0xf0) | ((msr & 0x03) << 2) | ((msr & 0x0c) >> 2);
 | 
			
		||||
+	rtl8xxxu_write8(priv, REG_MSR, msr);
 | 
			
		||||
+
 | 
			
		||||
+	/* write port0 */
 | 
			
		||||
+	rtl8xxxu_write8(priv, REG_BEACON_CTRL, bcn_ctrl_1 & ~BEACON_FUNCTION_ENABLE);
 | 
			
		||||
+	for (i = 0; i < ARRAY_SIZE(atimwnd_1); i++)
 | 
			
		||||
+		rtl8xxxu_write8(priv, REG_ATIMWND + i, atimwnd_1[i]);
 | 
			
		||||
+	for (i = 0; i < ARRAY_SIZE(tsftr_1); i++)
 | 
			
		||||
+		rtl8xxxu_write8(priv, REG_TSFTR + i, tsftr_1[i]);
 | 
			
		||||
+	for (i = 0; i < ARRAY_SIZE(macid_1); i++)
 | 
			
		||||
+		rtl8xxxu_write8(priv, REG_MACID + i, macid_1[i]);
 | 
			
		||||
+	for (i = 0; i < ARRAY_SIZE(bssid_1); i++)
 | 
			
		||||
+		rtl8xxxu_write8(priv, REG_BSSID + i, bssid_1[i]);
 | 
			
		||||
+
 | 
			
		||||
+	/* write port1 */
 | 
			
		||||
+	rtl8xxxu_write8(priv, REG_BEACON_CTRL_1, bcn_ctrl & ~BEACON_FUNCTION_ENABLE);
 | 
			
		||||
+	for (i = 0; i < ARRAY_SIZE(atimwnd); i++)
 | 
			
		||||
+		rtl8xxxu_write8(priv, REG_ATIMWND_1 + i, atimwnd[i]);
 | 
			
		||||
+	for (i = 0; i < ARRAY_SIZE(tsftr); i++)
 | 
			
		||||
+		rtl8xxxu_write8(priv, REG_TSFTR1 + i, tsftr[i]);
 | 
			
		||||
+	for (i = 0; i < ARRAY_SIZE(macid); i++)
 | 
			
		||||
+		rtl8xxxu_write8(priv, REG_MACID1 + i, macid[i]);
 | 
			
		||||
+	for (i = 0; i < ARRAY_SIZE(bssid); i++)
 | 
			
		||||
+		rtl8xxxu_write8(priv, REG_BSSID1 + i, bssid[i]);
 | 
			
		||||
+
 | 
			
		||||
+	/* write bcn ctl */
 | 
			
		||||
+	rtl8xxxu_write8(priv, REG_BEACON_CTRL, bcn_ctrl_1);
 | 
			
		||||
+	rtl8xxxu_write8(priv, REG_BEACON_CTRL_1, bcn_ctrl);
 | 
			
		||||
+
 | 
			
		||||
+	vif = priv->vifs[0];
 | 
			
		||||
+	priv->vifs[0] = priv->vifs[1];
 | 
			
		||||
+	priv->vifs[1] = vif;
 | 
			
		||||
+
 | 
			
		||||
+	/* priv->vifs[0] is NULL here, based on how this function is currently
 | 
			
		||||
+	 * called from rtl8xxxu_add_interface().
 | 
			
		||||
+	 * When this function will be used in the future for a different
 | 
			
		||||
+	 * scenario, please check whether vifs[0] or vifs[1] can be NULL and if
 | 
			
		||||
+	 * necessary add code to set port_num = 1.
 | 
			
		||||
+	 */
 | 
			
		||||
+	rtlvif = (struct rtl8xxxu_vif *)priv->vifs[1]->drv_priv;
 | 
			
		||||
+	rtlvif->port_num = 1;
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
 static int rtl8xxxu_add_interface(struct ieee80211_hw *hw,
 | 
			
		||||
 				  struct ieee80211_vif *vif)
 | 
			
		||||
 {
 | 
			
		||||
@@ -6651,8 +6736,10 @@ static int rtl8xxxu_add_interface(struct
 | 
			
		||||
 		}
 | 
			
		||||
 		break;
 | 
			
		||||
 	case NL80211_IFTYPE_AP:
 | 
			
		||||
-		if (port_num == 1)
 | 
			
		||||
-			return -EOPNOTSUPP;
 | 
			
		||||
+		if (port_num == 1) {
 | 
			
		||||
+			rtl8xxxu_switch_ports(priv);
 | 
			
		||||
+			port_num = 0;
 | 
			
		||||
+		}
 | 
			
		||||
 
 | 
			
		||||
 		rtl8xxxu_write8(priv, REG_BEACON_CTRL,
 | 
			
		||||
 				BEACON_DISABLE_TSF_UPDATE | BEACON_CTRL_MBSSID);
 | 
			
		||||
@ -0,0 +1,76 @@
 | 
			
		||||
From 1cd165adf314f6bf25cde58f02f4ff51d01730b0 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Martin Kaistra <martin.kaistra@linutronix.de>
 | 
			
		||||
Date: Fri, 22 Dec 2023 11:14:42 +0100
 | 
			
		||||
Subject: [PATCH 21/21] wifi: rtl8xxxu: declare concurrent mode support for
 | 
			
		||||
 8188f
 | 
			
		||||
 | 
			
		||||
Everything is in place now for concurrent mode, we can tell the system
 | 
			
		||||
that we support it.
 | 
			
		||||
We will allow a maximum of 2 virtual interfaces, one of them can be in
 | 
			
		||||
AP mode.
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Martin Kaistra <martin.kaistra@linutronix.de>
 | 
			
		||||
Reviewed-by: Ping-Ke Shih <pkshih@realtek.com>
 | 
			
		||||
Signed-off-by: Kalle Valo <kvalo@kernel.org>
 | 
			
		||||
Link: https://msgid.link/20231222101442.626837-22-martin.kaistra@linutronix.de
 | 
			
		||||
---
 | 
			
		||||
 .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.h  |  1 +
 | 
			
		||||
 .../realtek/rtl8xxxu/rtl8xxxu_8188f.c         |  1 +
 | 
			
		||||
 .../wireless/realtek/rtl8xxxu/rtl8xxxu_core.c | 19 +++++++++++++++++++
 | 
			
		||||
 3 files changed, 21 insertions(+)
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h
 | 
			
		||||
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h
 | 
			
		||||
@@ -1992,6 +1992,7 @@ struct rtl8xxxu_fileops {
 | 
			
		||||
 	u8 init_reg_rxfltmap:1;
 | 
			
		||||
 	u8 init_reg_pkt_life_time:1;
 | 
			
		||||
 	u8 init_reg_hmtfr:1;
 | 
			
		||||
+	u8 supports_concurrent:1;
 | 
			
		||||
 	u8 ampdu_max_time;
 | 
			
		||||
 	u8 ustime_tsf_edca;
 | 
			
		||||
 	u16 max_aggr_num;
 | 
			
		||||
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8188f.c
 | 
			
		||||
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8188f.c
 | 
			
		||||
@@ -1752,6 +1752,7 @@ struct rtl8xxxu_fileops rtl8188fu_fops =
 | 
			
		||||
 	.supports_ap = 1,
 | 
			
		||||
 	.max_macid_num = 16,
 | 
			
		||||
 	.max_sec_cam_num = 16,
 | 
			
		||||
+	.supports_concurrent = 1,
 | 
			
		||||
 	.adda_1t_init = 0x03c00014,
 | 
			
		||||
 	.adda_1t_path_on = 0x03c00014,
 | 
			
		||||
 	.trxff_boundary = 0x3f7f,
 | 
			
		||||
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
 | 
			
		||||
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
 | 
			
		||||
@@ -7665,6 +7665,20 @@ static void rtl8xxxu_deinit_led(struct r
 | 
			
		||||
 	led_classdev_unregister(led);
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
+struct ieee80211_iface_limit rtl8xxxu_limits[] = {
 | 
			
		||||
+	{ .max = 2, .types = BIT(NL80211_IFTYPE_STATION), },
 | 
			
		||||
+	{ .max = 1, .types = BIT(NL80211_IFTYPE_AP), },
 | 
			
		||||
+};
 | 
			
		||||
+
 | 
			
		||||
+struct ieee80211_iface_combination rtl8xxxu_combinations[] = {
 | 
			
		||||
+	{
 | 
			
		||||
+		.limits = rtl8xxxu_limits,
 | 
			
		||||
+		.n_limits = ARRAY_SIZE(rtl8xxxu_limits),
 | 
			
		||||
+		.max_interfaces = 2,
 | 
			
		||||
+		.num_different_channels = 1,
 | 
			
		||||
+	},
 | 
			
		||||
+};
 | 
			
		||||
+
 | 
			
		||||
 static int rtl8xxxu_probe(struct usb_interface *interface,
 | 
			
		||||
 			  const struct usb_device_id *id)
 | 
			
		||||
 {
 | 
			
		||||
@@ -7810,6 +7824,11 @@ static int rtl8xxxu_probe(struct usb_int
 | 
			
		||||
 		hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_AP);
 | 
			
		||||
 	hw->queues = 4;
 | 
			
		||||
 
 | 
			
		||||
+	if (priv->fops->supports_concurrent) {
 | 
			
		||||
+		hw->wiphy->iface_combinations = rtl8xxxu_combinations;
 | 
			
		||||
+		hw->wiphy->n_iface_combinations = ARRAY_SIZE(rtl8xxxu_combinations);
 | 
			
		||||
+	}
 | 
			
		||||
+
 | 
			
		||||
 	sband = &rtl8xxxu_supported_band;
 | 
			
		||||
 	sband->ht_cap.ht_supported = true;
 | 
			
		||||
 	sband->ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
 | 
			
		||||
@ -0,0 +1,98 @@
 | 
			
		||||
From 9475cc7ac31503521af95e38151e9d856e8ff30b Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Bitterblue Smith <rtl8821cerfe2@gmail.com>
 | 
			
		||||
Date: Sun, 31 Dec 2023 00:45:54 +0200
 | 
			
		||||
Subject: [PATCH 1/2] wifi: rtl8xxxu: Fix LED control code of RTL8192FU
 | 
			
		||||
 | 
			
		||||
Some devices, like the Comfast CF-826F, use LED1, which already works.
 | 
			
		||||
Others, like Asus USB-N13 C1, use LED0, which doesn't work correctly.
 | 
			
		||||
 | 
			
		||||
Write the right values to the LED control registers to make LED0 work
 | 
			
		||||
as well.
 | 
			
		||||
 | 
			
		||||
This is unfortunately tested only with the Comfast CF-826F.
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
 | 
			
		||||
Reviewed-by: Ping-Ke Shih <pkshih@realtek.com>
 | 
			
		||||
Signed-off-by: Kalle Valo <kvalo@kernel.org>
 | 
			
		||||
Link: https://msgid.link/7a2c3158-3a45-4466-b11e-fc09802b20e2@gmail.com
 | 
			
		||||
---
 | 
			
		||||
 .../realtek/rtl8xxxu/rtl8xxxu_8192f.c         | 32 +++++++++++++------
 | 
			
		||||
 .../wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h | 15 +++++++++
 | 
			
		||||
 2 files changed, 38 insertions(+), 9 deletions(-)
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192f.c
 | 
			
		||||
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192f.c
 | 
			
		||||
@@ -2014,26 +2014,40 @@ static int rtl8192fu_led_brightness_set(
 | 
			
		||||
 	struct rtl8xxxu_priv *priv = container_of(led_cdev,
 | 
			
		||||
 						  struct rtl8xxxu_priv,
 | 
			
		||||
 						  led_cdev);
 | 
			
		||||
-	u16 ledcfg;
 | 
			
		||||
+	u32 ledcfg;
 | 
			
		||||
 
 | 
			
		||||
 	/* Values obtained by observing the USB traffic from the Windows driver. */
 | 
			
		||||
 	rtl8xxxu_write32(priv, REG_SW_GPIO_SHARE_CTRL_0, 0x20080);
 | 
			
		||||
 	rtl8xxxu_write32(priv, REG_SW_GPIO_SHARE_CTRL_1, 0x1b0000);
 | 
			
		||||
 
 | 
			
		||||
-	ledcfg = rtl8xxxu_read16(priv, REG_LEDCFG0);
 | 
			
		||||
+	ledcfg = rtl8xxxu_read32(priv, REG_LEDCFG0);
 | 
			
		||||
+
 | 
			
		||||
+	/* Comfast CF-826F uses LED1. Asus USB-N13 C1 uses LED0. Set both. */
 | 
			
		||||
+
 | 
			
		||||
+	u32p_replace_bits(&ledcfg, LED_GPIO_ENABLE, LEDCFG0_LED2EN);
 | 
			
		||||
+	u32p_replace_bits(&ledcfg, LED_IO_MODE_OUTPUT, LEDCFG0_LED0_IO_MODE);
 | 
			
		||||
+	u32p_replace_bits(&ledcfg, LED_IO_MODE_OUTPUT, LEDCFG0_LED1_IO_MODE);
 | 
			
		||||
 
 | 
			
		||||
 	if (brightness == LED_OFF) {
 | 
			
		||||
-		/* Value obtained like above. */
 | 
			
		||||
-		ledcfg = BIT(1) | BIT(7);
 | 
			
		||||
+		u32p_replace_bits(&ledcfg, LED_MODE_SW_CTRL, LEDCFG0_LED0CM);
 | 
			
		||||
+		u32p_replace_bits(&ledcfg, LED_SW_OFF, LEDCFG0_LED0SV);
 | 
			
		||||
+		u32p_replace_bits(&ledcfg, LED_MODE_SW_CTRL, LEDCFG0_LED1CM);
 | 
			
		||||
+		u32p_replace_bits(&ledcfg, LED_SW_OFF, LEDCFG0_LED1SV);
 | 
			
		||||
 	} else if (brightness == LED_ON) {
 | 
			
		||||
-		/* Value obtained like above. */
 | 
			
		||||
-		ledcfg = BIT(1) | BIT(7) | BIT(11);
 | 
			
		||||
+		u32p_replace_bits(&ledcfg, LED_MODE_SW_CTRL, LEDCFG0_LED0CM);
 | 
			
		||||
+		u32p_replace_bits(&ledcfg, LED_SW_ON, LEDCFG0_LED0SV);
 | 
			
		||||
+		u32p_replace_bits(&ledcfg, LED_MODE_SW_CTRL, LEDCFG0_LED1CM);
 | 
			
		||||
+		u32p_replace_bits(&ledcfg, LED_SW_ON, LEDCFG0_LED1SV);
 | 
			
		||||
 	} else if (brightness == RTL8XXXU_HW_LED_CONTROL) {
 | 
			
		||||
-		/* Value obtained by brute force. */
 | 
			
		||||
-		ledcfg = BIT(8) | BIT(9);
 | 
			
		||||
+		u32p_replace_bits(&ledcfg, LED_MODE_TX_OR_RX_EVENTS,
 | 
			
		||||
+				  LEDCFG0_LED0CM);
 | 
			
		||||
+		u32p_replace_bits(&ledcfg, LED_SW_OFF, LEDCFG0_LED0SV);
 | 
			
		||||
+		u32p_replace_bits(&ledcfg, LED_MODE_TX_OR_RX_EVENTS,
 | 
			
		||||
+				  LEDCFG0_LED1CM);
 | 
			
		||||
+		u32p_replace_bits(&ledcfg, LED_SW_OFF, LEDCFG0_LED1SV);
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
-	rtl8xxxu_write16(priv, REG_LEDCFG0, ledcfg);
 | 
			
		||||
+	rtl8xxxu_write32(priv, REG_LEDCFG0, ledcfg);
 | 
			
		||||
 
 | 
			
		||||
 	return 0;
 | 
			
		||||
 }
 | 
			
		||||
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h
 | 
			
		||||
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h
 | 
			
		||||
@@ -146,6 +146,21 @@
 | 
			
		||||
 #define  GPIO_INTM_EDGE_TRIG_IRQ	BIT(9)
 | 
			
		||||
 
 | 
			
		||||
 #define REG_LEDCFG0			0x004c
 | 
			
		||||
+#define  LEDCFG0_LED0CM			GENMASK(2, 0)
 | 
			
		||||
+#define  LEDCFG0_LED1CM			GENMASK(10, 8)
 | 
			
		||||
+#define   LED_MODE_SW_CTRL		0x0
 | 
			
		||||
+#define   LED_MODE_TX_OR_RX_EVENTS	0x3
 | 
			
		||||
+#define  LEDCFG0_LED0SV			BIT(3)
 | 
			
		||||
+#define  LEDCFG0_LED1SV			BIT(11)
 | 
			
		||||
+#define   LED_SW_OFF			0x0
 | 
			
		||||
+#define   LED_SW_ON			0x1
 | 
			
		||||
+#define  LEDCFG0_LED0_IO_MODE		BIT(7)
 | 
			
		||||
+#define  LEDCFG0_LED1_IO_MODE		BIT(15)
 | 
			
		||||
+#define   LED_IO_MODE_OUTPUT		0x0
 | 
			
		||||
+#define   LED_IO_MODE_INPUT		0x1
 | 
			
		||||
+#define  LEDCFG0_LED2EN			BIT(21)
 | 
			
		||||
+#define   LED_GPIO_DISABLE		0x0
 | 
			
		||||
+#define   LED_GPIO_ENABLE		0x1
 | 
			
		||||
 #define  LEDCFG0_DPDT_SELECT		BIT(23)
 | 
			
		||||
 #define REG_LEDCFG1			0x004d
 | 
			
		||||
 #define  LEDCFG1_HW_LED_CONTROL		BIT(1)
 | 
			
		||||
@ -0,0 +1,36 @@
 | 
			
		||||
From 80850ca041f2c7ee28fa5e47c5c1b106415f099f Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Bitterblue Smith <rtl8821cerfe2@gmail.com>
 | 
			
		||||
Date: Tue, 2 Jan 2024 21:33:07 +0200
 | 
			
		||||
Subject: [PATCH 2/2] wifi: rtl8xxxu: Fix off by one initial RTS rate
 | 
			
		||||
 | 
			
		||||
rtl8xxxu_set_basic_rates() sets the wrong initial RTS rate. It sets the
 | 
			
		||||
next higher rate than the one it should set, e.g. 36M instead of 24M.
 | 
			
		||||
 | 
			
		||||
The while loop was supposed to find the index of the most significant
 | 
			
		||||
bit which is 1, but it was copied incorrectly from the vendor driver.
 | 
			
		||||
Use __fls() instead.
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
 | 
			
		||||
Reviewed-by: Ping-Ke Shih <pkshih@realtek.com>
 | 
			
		||||
Signed-off-by: Kalle Valo <kvalo@kernel.org>
 | 
			
		||||
Link: https://msgid.link/761e6836-6cd6-4930-91b6-0446834655c5@gmail.com
 | 
			
		||||
---
 | 
			
		||||
 drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c | 7 +++----
 | 
			
		||||
 1 file changed, 3 insertions(+), 4 deletions(-)
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
 | 
			
		||||
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
 | 
			
		||||
@@ -4870,10 +4870,9 @@ static void rtl8xxxu_set_basic_rates(str
 | 
			
		||||
 
 | 
			
		||||
 	dev_dbg(&priv->udev->dev, "%s: rates %08x\n", __func__,	rate_cfg);
 | 
			
		||||
 
 | 
			
		||||
-	while (rate_cfg) {
 | 
			
		||||
-		rate_cfg = (rate_cfg >> 1);
 | 
			
		||||
-		rate_idx++;
 | 
			
		||||
-	}
 | 
			
		||||
+	if (rate_cfg)
 | 
			
		||||
+		rate_idx = __fls(rate_cfg);
 | 
			
		||||
+
 | 
			
		||||
 	rtl8xxxu_write8(priv, REG_INIRTS_RATE_SEL, rate_idx);
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
@ -0,0 +1,27 @@
 | 
			
		||||
From 1213acb478a7181cd73eeaf00db430f1e45b1361 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Martin Kaistra <martin.kaistra@linutronix.de>
 | 
			
		||||
Date: Thu, 11 Jan 2024 17:36:27 +0100
 | 
			
		||||
Subject: [PATCH 1/2] wifi: rtl8xxxu: add cancel_work_sync() for c2hcmd_work
 | 
			
		||||
 | 
			
		||||
The workqueue might still be running, when the driver is stopped. To
 | 
			
		||||
avoid a use-after-free, call cancel_work_sync() in rtl8xxxu_stop().
 | 
			
		||||
 | 
			
		||||
Fixes: e542e66b7c2e ("rtl8xxxu: add bluetooth co-existence support for single antenna")
 | 
			
		||||
Signed-off-by: Martin Kaistra <martin.kaistra@linutronix.de>
 | 
			
		||||
Reviewed-by: Ping-Ke Shih <pkshih@realtek.com>
 | 
			
		||||
Signed-off-by: Kalle Valo <kvalo@kernel.org>
 | 
			
		||||
Link: https://msgid.link/20240111163628.320697-2-martin.kaistra@linutronix.de
 | 
			
		||||
---
 | 
			
		||||
 drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c | 1 +
 | 
			
		||||
 1 file changed, 1 insertion(+)
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
 | 
			
		||||
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
 | 
			
		||||
@@ -7480,6 +7480,7 @@ static void rtl8xxxu_stop(struct ieee802
 | 
			
		||||
 	if (priv->usb_interrupts)
 | 
			
		||||
 		rtl8xxxu_write32(priv, REG_USB_HIMR, 0);
 | 
			
		||||
 
 | 
			
		||||
+	cancel_work_sync(&priv->c2hcmd_work);
 | 
			
		||||
 	cancel_delayed_work_sync(&priv->ra_watchdog);
 | 
			
		||||
 
 | 
			
		||||
 	rtl8xxxu_free_rx_resources(priv);
 | 
			
		||||
@ -0,0 +1,100 @@
 | 
			
		||||
From ece90a8622320bf5a24d3326da1f8e109891573c Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Martin Kaistra <martin.kaistra@linutronix.de>
 | 
			
		||||
Date: Thu, 11 Jan 2024 17:36:28 +0100
 | 
			
		||||
Subject: [PATCH 2/2] 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. To achieve this, convert
 | 
			
		||||
update_beacon_work to delayed_work and schedule it with the beacon
 | 
			
		||||
interval in case CSA is active and the countdown is not complete.
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Martin Kaistra <martin.kaistra@linutronix.de>
 | 
			
		||||
Reviewed-by: Ping-Ke Shih <pkshih@realtek.com>
 | 
			
		||||
Signed-off-by: Kalle Valo <kvalo@kernel.org>
 | 
			
		||||
Link: https://msgid.link/20240111163628.320697-3-martin.kaistra@linutronix.de
 | 
			
		||||
---
 | 
			
		||||
 .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.h  |  2 +-
 | 
			
		||||
 .../wireless/realtek/rtl8xxxu/rtl8xxxu_core.c | 19 +++++++++++++++----
 | 
			
		||||
 2 files changed, 16 insertions(+), 5 deletions(-)
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h
 | 
			
		||||
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h
 | 
			
		||||
@@ -1900,7 +1900,7 @@ struct rtl8xxxu_priv {
 | 
			
		||||
 	struct delayed_work ra_watchdog;
 | 
			
		||||
 	struct work_struct c2hcmd_work;
 | 
			
		||||
 	struct sk_buff_head c2hcmd_queue;
 | 
			
		||||
-	struct work_struct update_beacon_work;
 | 
			
		||||
+	struct delayed_work update_beacon_work;
 | 
			
		||||
 	struct rtl8xxxu_btcoex bt_coex;
 | 
			
		||||
 	struct rtl8xxxu_ra_report ra_report;
 | 
			
		||||
 	struct rtl8xxxu_cfo_tracking cfo_tracking;
 | 
			
		||||
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
 | 
			
		||||
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
 | 
			
		||||
@@ -4605,7 +4605,7 @@ static int rtl8xxxu_set_tim(struct ieee8
 | 
			
		||||
 {
 | 
			
		||||
 	struct rtl8xxxu_priv *priv = hw->priv;
 | 
			
		||||
 
 | 
			
		||||
-	schedule_work(&priv->update_beacon_work);
 | 
			
		||||
+	schedule_delayed_work(&priv->update_beacon_work, 0);
 | 
			
		||||
 
 | 
			
		||||
 	return 0;
 | 
			
		||||
 }
 | 
			
		||||
@@ -5107,7 +5107,7 @@ rtl8xxxu_bss_info_changed(struct ieee802
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
 	if (changed & BSS_CHANGED_BEACON)
 | 
			
		||||
-		schedule_work(&priv->update_beacon_work);
 | 
			
		||||
+		schedule_delayed_work(&priv->update_beacon_work, 0);
 | 
			
		||||
 
 | 
			
		||||
 error:
 | 
			
		||||
 	return;
 | 
			
		||||
@@ -5726,7 +5726,7 @@ static void rtl8xxxu_send_beacon_frame(s
 | 
			
		||||
 static void rtl8xxxu_update_beacon_work_callback(struct work_struct *work)
 | 
			
		||||
 {
 | 
			
		||||
 	struct rtl8xxxu_priv *priv =
 | 
			
		||||
-		container_of(work, struct rtl8xxxu_priv, update_beacon_work);
 | 
			
		||||
+		container_of(work, struct rtl8xxxu_priv, update_beacon_work.work);
 | 
			
		||||
 	struct ieee80211_hw *hw = priv->hw;
 | 
			
		||||
 	struct ieee80211_vif *vif = priv->vifs[0];
 | 
			
		||||
 
 | 
			
		||||
@@ -5735,6 +5735,14 @@ static void rtl8xxxu_update_beacon_work_
 | 
			
		||||
 		return;
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
+	if (vif->bss_conf.csa_active) {
 | 
			
		||||
+		if (ieee80211_beacon_cntdwn_is_complete(vif)) {
 | 
			
		||||
+			ieee80211_csa_finish(vif);
 | 
			
		||||
+			return;
 | 
			
		||||
+		}
 | 
			
		||||
+		schedule_delayed_work(&priv->update_beacon_work,
 | 
			
		||||
+				      msecs_to_jiffies(vif->bss_conf.beacon_int));
 | 
			
		||||
+	}
 | 
			
		||||
 	rtl8xxxu_send_beacon_frame(hw, vif);
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
@@ -7482,6 +7490,7 @@ static void rtl8xxxu_stop(struct ieee802
 | 
			
		||||
 
 | 
			
		||||
 	cancel_work_sync(&priv->c2hcmd_work);
 | 
			
		||||
 	cancel_delayed_work_sync(&priv->ra_watchdog);
 | 
			
		||||
+	cancel_delayed_work_sync(&priv->update_beacon_work);
 | 
			
		||||
 
 | 
			
		||||
 	rtl8xxxu_free_rx_resources(priv);
 | 
			
		||||
 	rtl8xxxu_free_tx_resources(priv);
 | 
			
		||||
@@ -7763,7 +7772,7 @@ static int rtl8xxxu_probe(struct usb_int
 | 
			
		||||
 	spin_lock_init(&priv->rx_urb_lock);
 | 
			
		||||
 	INIT_WORK(&priv->rx_urb_wq, rtl8xxxu_rx_urb_work);
 | 
			
		||||
 	INIT_DELAYED_WORK(&priv->ra_watchdog, rtl8xxxu_watchdog_callback);
 | 
			
		||||
-	INIT_WORK(&priv->update_beacon_work, rtl8xxxu_update_beacon_work_callback);
 | 
			
		||||
+	INIT_DELAYED_WORK(&priv->update_beacon_work, rtl8xxxu_update_beacon_work_callback);
 | 
			
		||||
 	skb_queue_head_init(&priv->c2hcmd_queue);
 | 
			
		||||
 
 | 
			
		||||
 	usb_set_intfdata(interface, hw);
 | 
			
		||||
@@ -7824,6 +7833,8 @@ static int rtl8xxxu_probe(struct usb_int
 | 
			
		||||
 		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);
 | 
			
		||||
@ -0,0 +1,31 @@
 | 
			
		||||
From 426e7b4773921d07ab4ab8ba16fbad396d6c9971 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Ping-Ke Shih <pkshih@realtek.com>
 | 
			
		||||
Date: Tue, 16 Jan 2024 16:09:44 +0800
 | 
			
		||||
Subject: [PATCH 1/2] wifi: rtl8xxxu: convert EN_DESC_ID of TX descriptor to
 | 
			
		||||
 le32 type
 | 
			
		||||
 | 
			
		||||
Fields of TX descriptor are little-endian order, so correct EN_DESC_ID
 | 
			
		||||
field to le32 type.
 | 
			
		||||
 | 
			
		||||
Fixes: b837f78fbffa ("wifi: rtl8xxxu: add hw crypto support for AP mode")
 | 
			
		||||
Reported-by: kernel test robot <lkp@intel.com>
 | 
			
		||||
Closes: https://lore.kernel.org/oe-kbuild-all/202401161318.YtXoCkjU-lkp@intel.com/
 | 
			
		||||
Cc: Martin Kaistra <martin.kaistra@linutronix.de>
 | 
			
		||||
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
 | 
			
		||||
Signed-off-by: Kalle Valo <kvalo@kernel.org>
 | 
			
		||||
Link: https://msgid.link/20240116080945.20172-1-pkshih@realtek.com
 | 
			
		||||
---
 | 
			
		||||
 drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c | 2 +-
 | 
			
		||||
 1 file changed, 1 insertion(+), 1 deletion(-)
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
 | 
			
		||||
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
 | 
			
		||||
@@ -5619,7 +5619,7 @@ static void rtl8xxxu_tx(struct ieee80211
 | 
			
		||||
 			break;
 | 
			
		||||
 		}
 | 
			
		||||
 		if (bmc && rtlvif->hw_key_idx != 0xff) {
 | 
			
		||||
-			tx_desc->txdw1 |= TXDESC_EN_DESC_ID;
 | 
			
		||||
+			tx_desc->txdw1 |= cpu_to_le32(TXDESC_EN_DESC_ID);
 | 
			
		||||
 			macid = rtlvif->hw_key_idx;
 | 
			
		||||
 		}
 | 
			
		||||
 	}
 | 
			
		||||
@ -0,0 +1,36 @@
 | 
			
		||||
From 92c7428f942da7dfcdc629b05b5114f80822d7a4 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Ping-Ke Shih <pkshih@realtek.com>
 | 
			
		||||
Date: Tue, 16 Jan 2024 16:09:45 +0800
 | 
			
		||||
Subject: [PATCH 2/2] wifi: rtl8xxxu: make instances of iface limit and
 | 
			
		||||
 combination to be static const
 | 
			
		||||
 | 
			
		||||
rtl8xxxu_limits and rtl8xxxu_combinations can be static const, so add
 | 
			
		||||
modifiers as desire. Otherwise, Sparse reports warnings
 | 
			
		||||
 | 
			
		||||
rtl8xxxu_core.c:7677:30: warning: symbol 'rtl8xxxu_limits' was not declared. Should it be static?
 | 
			
		||||
rtl8xxxu_core.c:7682:36: warning: symbol 'rtl8xxxu_combinations' was not declared. Should it be static?
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
 | 
			
		||||
Signed-off-by: Kalle Valo <kvalo@kernel.org>
 | 
			
		||||
Link: https://msgid.link/20240116080945.20172-2-pkshih@realtek.com
 | 
			
		||||
---
 | 
			
		||||
 drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c | 4 ++--
 | 
			
		||||
 1 file changed, 2 insertions(+), 2 deletions(-)
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
 | 
			
		||||
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
 | 
			
		||||
@@ -7674,12 +7674,12 @@ static void rtl8xxxu_deinit_led(struct r
 | 
			
		||||
 	led_classdev_unregister(led);
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
-struct ieee80211_iface_limit rtl8xxxu_limits[] = {
 | 
			
		||||
+static const struct ieee80211_iface_limit rtl8xxxu_limits[] = {
 | 
			
		||||
 	{ .max = 2, .types = BIT(NL80211_IFTYPE_STATION), },
 | 
			
		||||
 	{ .max = 1, .types = BIT(NL80211_IFTYPE_AP), },
 | 
			
		||||
 };
 | 
			
		||||
 
 | 
			
		||||
-struct ieee80211_iface_combination rtl8xxxu_combinations[] = {
 | 
			
		||||
+static const struct ieee80211_iface_combination rtl8xxxu_combinations[] = {
 | 
			
		||||
 	{
 | 
			
		||||
 		.limits = rtl8xxxu_limits,
 | 
			
		||||
 		.n_limits = ARRAY_SIZE(rtl8xxxu_limits),
 | 
			
		||||
@ -0,0 +1,100 @@
 | 
			
		||||
From 563d5025cf3b51c7bf20e6966af433ed5f838875 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Martin Kaistra <martin.kaistra@linutronix.de>
 | 
			
		||||
Date: Tue, 16 Jan 2024 10:50:01 +0100
 | 
			
		||||
Subject: [PATCH] wifi: rtl8xxxu: add missing number of sec cam entries for all
 | 
			
		||||
 variants
 | 
			
		||||
 | 
			
		||||
Commit b837f78fbffa ("wifi: rtl8xxxu: add hw crypto support for AP
 | 
			
		||||
mode") introduced max_sec_cam_num as a member of rtl8xxxu_fileops.
 | 
			
		||||
It was missed to set this number for all variants except 8188f, which
 | 
			
		||||
caused rtl8xxxu_get_free_sec_cam() to always return 0 and therefore breaking
 | 
			
		||||
encrypted traffic.
 | 
			
		||||
 | 
			
		||||
Fix it by adding the numbers for all variants. The values are taken from
 | 
			
		||||
the vendor drivers and rtlwifi.
 | 
			
		||||
 | 
			
		||||
Link: https://lore.kernel.org/linux-wireless/20240111163603.2325-1-zenmchen@gmail.com/
 | 
			
		||||
Fixes: b837f78fbffa ("wifi: rtl8xxxu: add hw crypto support for AP mode")
 | 
			
		||||
Signed-off-by: Martin Kaistra <martin.kaistra@linutronix.de>
 | 
			
		||||
Signed-off-by: Kalle Valo <kvalo@kernel.org>
 | 
			
		||||
Link: https://msgid.link/20240116095001.399500-1-martin.kaistra@linutronix.de
 | 
			
		||||
---
 | 
			
		||||
 drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8188e.c | 1 +
 | 
			
		||||
 drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192c.c | 1 +
 | 
			
		||||
 drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192e.c | 1 +
 | 
			
		||||
 drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192f.c | 1 +
 | 
			
		||||
 drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8710b.c | 1 +
 | 
			
		||||
 drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723a.c | 1 +
 | 
			
		||||
 drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723b.c | 1 +
 | 
			
		||||
 7 files changed, 7 insertions(+)
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8188e.c
 | 
			
		||||
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8188e.c
 | 
			
		||||
@@ -1882,6 +1882,7 @@ struct rtl8xxxu_fileops rtl8188eu_fops =
 | 
			
		||||
 	.has_tx_report = 1,
 | 
			
		||||
 	.init_reg_pkt_life_time = 1,
 | 
			
		||||
 	.gen2_thermal_meter = 1,
 | 
			
		||||
+	.max_sec_cam_num = 32,
 | 
			
		||||
 	.adda_1t_init = 0x0b1b25a0,
 | 
			
		||||
 	.adda_1t_path_on = 0x0bdb25a0,
 | 
			
		||||
 	/*
 | 
			
		||||
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192c.c
 | 
			
		||||
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192c.c
 | 
			
		||||
@@ -613,6 +613,7 @@ struct rtl8xxxu_fileops rtl8192cu_fops =
 | 
			
		||||
 	.rx_agg_buf_size = 16000,
 | 
			
		||||
 	.tx_desc_size = sizeof(struct rtl8xxxu_txdesc32),
 | 
			
		||||
 	.rx_desc_size = sizeof(struct rtl8xxxu_rxdesc16),
 | 
			
		||||
+	.max_sec_cam_num = 32,
 | 
			
		||||
 	.adda_1t_init = 0x0b1b25a0,
 | 
			
		||||
 	.adda_1t_path_on = 0x0bdb25a0,
 | 
			
		||||
 	.adda_2t_path_on_a = 0x04db25a4,
 | 
			
		||||
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192e.c
 | 
			
		||||
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192e.c
 | 
			
		||||
@@ -1769,6 +1769,7 @@ struct rtl8xxxu_fileops rtl8192eu_fops =
 | 
			
		||||
 	.needs_full_init = 1,
 | 
			
		||||
 	.supports_ap = 1,
 | 
			
		||||
 	.max_macid_num = 128,
 | 
			
		||||
+	.max_sec_cam_num = 64,
 | 
			
		||||
 	.adda_1t_init = 0x0fc01616,
 | 
			
		||||
 	.adda_1t_path_on = 0x0fc01616,
 | 
			
		||||
 	.adda_2t_path_on_a = 0x0fc01616,
 | 
			
		||||
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192f.c
 | 
			
		||||
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192f.c
 | 
			
		||||
@@ -2095,6 +2095,7 @@ struct rtl8xxxu_fileops rtl8192fu_fops =
 | 
			
		||||
 	.max_aggr_num = 0x1f1f,
 | 
			
		||||
 	.supports_ap = 1,
 | 
			
		||||
 	.max_macid_num = 128,
 | 
			
		||||
+	.max_sec_cam_num = 64,
 | 
			
		||||
 	.trxff_boundary = 0x3f3f,
 | 
			
		||||
 	.pbp_rx = PBP_PAGE_SIZE_256,
 | 
			
		||||
 	.pbp_tx = PBP_PAGE_SIZE_256,
 | 
			
		||||
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8710b.c
 | 
			
		||||
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8710b.c
 | 
			
		||||
@@ -1877,6 +1877,7 @@ struct rtl8xxxu_fileops rtl8710bu_fops =
 | 
			
		||||
 	.max_aggr_num = 0x0c14,
 | 
			
		||||
 	.supports_ap = 1,
 | 
			
		||||
 	.max_macid_num = 16,
 | 
			
		||||
+	.max_sec_cam_num = 32,
 | 
			
		||||
 	.adda_1t_init = 0x03c00016,
 | 
			
		||||
 	.adda_1t_path_on = 0x03c00016,
 | 
			
		||||
 	.trxff_boundary = 0x3f7f,
 | 
			
		||||
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723a.c
 | 
			
		||||
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723a.c
 | 
			
		||||
@@ -510,6 +510,7 @@ struct rtl8xxxu_fileops rtl8723au_fops =
 | 
			
		||||
 	.rx_agg_buf_size = 16000,
 | 
			
		||||
 	.tx_desc_size = sizeof(struct rtl8xxxu_txdesc32),
 | 
			
		||||
 	.rx_desc_size = sizeof(struct rtl8xxxu_rxdesc16),
 | 
			
		||||
+	.max_sec_cam_num = 32,
 | 
			
		||||
 	.adda_1t_init = 0x0b1b25a0,
 | 
			
		||||
 	.adda_1t_path_on = 0x0bdb25a0,
 | 
			
		||||
 	.adda_2t_path_on_a = 0x04db25a4,
 | 
			
		||||
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723b.c
 | 
			
		||||
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723b.c
 | 
			
		||||
@@ -1744,6 +1744,7 @@ struct rtl8xxxu_fileops rtl8723bu_fops =
 | 
			
		||||
 	.max_aggr_num = 0x0c14,
 | 
			
		||||
 	.supports_ap = 1,
 | 
			
		||||
 	.max_macid_num = 128,
 | 
			
		||||
+	.max_sec_cam_num = 64,
 | 
			
		||||
 	.adda_1t_init = 0x01c00014,
 | 
			
		||||
 	.adda_1t_path_on = 0x01c00014,
 | 
			
		||||
 	.adda_2t_path_on_a = 0x01c00014,
 | 
			
		||||
@ -0,0 +1,37 @@
 | 
			
		||||
From 17903a283593c1dbf9da041f836004163ca30f7b Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Dan Carpenter <dan.carpenter@linaro.org>
 | 
			
		||||
Date: Wed, 31 Jan 2024 10:10:07 +0300
 | 
			
		||||
Subject: [PATCH] wifi: rtl8xxxu: fix error messages
 | 
			
		||||
 | 
			
		||||
The first parameter of WARN_ONCE() is a condition so this code will end
 | 
			
		||||
up printing the function name instead of the proper message.
 | 
			
		||||
 | 
			
		||||
Fixes: 3ff7a05996f9 ("wifi: rtl8xxxu: support setting bssid register for multiple interfaces")
 | 
			
		||||
Signed-off-by: Dan Carpenter <dan.carpenter@linaro.org>
 | 
			
		||||
Reviewed-by: Ping-Ke Shih <pkshih@realtek.com>
 | 
			
		||||
Signed-off-by: Kalle Valo <kvalo@kernel.org>
 | 
			
		||||
Link: https://msgid.link/7b144531-a8da-4725-8911-9b614a525a35@moroto.mountain
 | 
			
		||||
---
 | 
			
		||||
 drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c | 4 ++--
 | 
			
		||||
 1 file changed, 2 insertions(+), 2 deletions(-)
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
 | 
			
		||||
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
 | 
			
		||||
@@ -3593,7 +3593,7 @@ static int rtl8xxxu_set_mac(struct rtl8x
 | 
			
		||||
 		reg = REG_MACID1;
 | 
			
		||||
 		break;
 | 
			
		||||
 	default:
 | 
			
		||||
-		WARN_ONCE("%s: invalid port_num\n", __func__);
 | 
			
		||||
+		WARN_ONCE(1, "%s: invalid port_num\n", __func__);
 | 
			
		||||
 		return -EINVAL;
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
@@ -3618,7 +3618,7 @@ static int rtl8xxxu_set_bssid(struct rtl
 | 
			
		||||
 		reg = REG_BSSID1;
 | 
			
		||||
 		break;
 | 
			
		||||
 	default:
 | 
			
		||||
-		WARN_ONCE("%s: invalid port_num\n", __func__);
 | 
			
		||||
+		WARN_ONCE(1, "%s: invalid port_num\n", __func__);
 | 
			
		||||
 		return -EINVAL;
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
@ -0,0 +1,36 @@
 | 
			
		||||
From 1209f487d452ff7e822dec30661fd6b5163fb8cf Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Chun Qiu <cqca@cock.lu>
 | 
			
		||||
Date: Mon, 29 Jan 2024 13:30:30 +0800
 | 
			
		||||
Subject: [PATCH] wifi: rtl8xxxu: Add TP-Link TL-WN823N V2
 | 
			
		||||
 | 
			
		||||
TP-Link TL-WN823N V2 (2357:0135) is based on rtl8192fu and has been
 | 
			
		||||
tested to work with the rtl8xxxu driver.
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Chun Qiu <cqca@cock.lu>
 | 
			
		||||
Signed-off-by: Kalle Valo <kvalo@kernel.org>
 | 
			
		||||
Link: https://msgid.link/20240129053030.16369-1-cqca@cock.lu
 | 
			
		||||
---
 | 
			
		||||
 drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c | 5 ++++-
 | 
			
		||||
 1 file changed, 4 insertions(+), 1 deletion(-)
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
 | 
			
		||||
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
 | 
			
		||||
@@ -7733,7 +7733,7 @@ static int rtl8xxxu_probe(struct usb_int
 | 
			
		||||
 			untested = 0;
 | 
			
		||||
 		break;
 | 
			
		||||
 	case 0x2357:
 | 
			
		||||
-		if (id->idProduct == 0x0109)
 | 
			
		||||
+		if (id->idProduct == 0x0109 || id->idProduct == 0x0135)
 | 
			
		||||
 			untested = 0;
 | 
			
		||||
 		break;
 | 
			
		||||
 	case 0x0b05:
 | 
			
		||||
@@ -8025,6 +8025,9 @@ static const struct usb_device_id dev_ta
 | 
			
		||||
 	.driver_info = (unsigned long)&rtl8192fu_fops},
 | 
			
		||||
 {USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x318b, 0xff, 0xff, 0xff),
 | 
			
		||||
 	.driver_info = (unsigned long)&rtl8192fu_fops},
 | 
			
		||||
+/* TP-Link TL-WN823N V2 */
 | 
			
		||||
+{USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x0135, 0xff, 0xff, 0xff),
 | 
			
		||||
+	.driver_info = (unsigned long)&rtl8192fu_fops},
 | 
			
		||||
 #ifdef CPTCFG_RTL8XXXU_UNTESTED
 | 
			
		||||
 /* Still supported by rtlwifi */
 | 
			
		||||
 {USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x8176, 0xff, 0xff, 0xff),
 | 
			
		||||
@ -0,0 +1,411 @@
 | 
			
		||||
From 94dd7ce1885e530a7b10bbe50d5d68ba1bb99e6e Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Martin Kaistra <martin.kaistra@linutronix.de>
 | 
			
		||||
Date: Mon, 5 Feb 2024 10:30:40 +0100
 | 
			
		||||
Subject: [PATCH] wifi: rtl8xxxu: update rate mask per sta
 | 
			
		||||
 | 
			
		||||
Until now, rtl8xxxu_watchdog_callback() only fetches RSSI and updates
 | 
			
		||||
the rate mask in station mode. This means, in AP mode only the default
 | 
			
		||||
rate mask is used.
 | 
			
		||||
 | 
			
		||||
In order to have the rate mask reflect the actual connection quality,
 | 
			
		||||
extend rtl8xxxu_watchdog_callback() to iterate over every sta. Like in
 | 
			
		||||
the rtw88 driver, add a function to collect all currently present stas
 | 
			
		||||
and then iterate over a list of copies to ensure no RCU lock problems
 | 
			
		||||
for register access via USB. Remove the existing RCU lock in
 | 
			
		||||
rtl8xxxu_refresh_rate_mask().
 | 
			
		||||
 | 
			
		||||
Since the currently used ieee80211_ave_rssi() is only for 'vif', add
 | 
			
		||||
driver-level tracking of RSSI per sta.
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Martin Kaistra <martin.kaistra@linutronix.de>
 | 
			
		||||
Reviewed-by: Ping-Ke Shih <pkshih@realtek.com>
 | 
			
		||||
Signed-off-by: Kalle Valo <kvalo@kernel.org>
 | 
			
		||||
Link: https://msgid.link/20240205093040.1941140-1-martin.kaistra@linutronix.de
 | 
			
		||||
---
 | 
			
		||||
 .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.h  |   8 +-
 | 
			
		||||
 .../wireless/realtek/rtl8xxxu/rtl8xxxu_core.c | 188 ++++++++++++++----
 | 
			
		||||
 2 files changed, 158 insertions(+), 38 deletions(-)
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h
 | 
			
		||||
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h
 | 
			
		||||
@@ -6,6 +6,7 @@
 | 
			
		||||
  */
 | 
			
		||||
 
 | 
			
		||||
 #include <asm/byteorder.h>
 | 
			
		||||
+#include <linux/average.h>
 | 
			
		||||
 
 | 
			
		||||
 #define RTL8XXXU_DEBUG_REG_WRITE	0x01
 | 
			
		||||
 #define RTL8XXXU_DEBUG_REG_READ		0x02
 | 
			
		||||
@@ -1858,6 +1859,8 @@ struct rtl8xxxu_priv {
 | 
			
		||||
 	int next_mbox;
 | 
			
		||||
 	int nr_out_eps;
 | 
			
		||||
 
 | 
			
		||||
+	/* Ensure no added or deleted stas while iterating */
 | 
			
		||||
+	struct mutex sta_mutex;
 | 
			
		||||
 	struct mutex h2c_mutex;
 | 
			
		||||
 	/* Protect the indirect register accesses of RTL8710BU. */
 | 
			
		||||
 	struct mutex syson_indirect_access_mutex;
 | 
			
		||||
@@ -1892,7 +1895,6 @@ struct rtl8xxxu_priv {
 | 
			
		||||
 	u8 pi_enabled:1;
 | 
			
		||||
 	u8 no_pape:1;
 | 
			
		||||
 	u8 int_buf[USB_INTR_CONTENT_LENGTH];
 | 
			
		||||
-	u8 rssi_level;
 | 
			
		||||
 	DECLARE_BITMAP(tx_aggr_started, IEEE80211_NUM_TIDS);
 | 
			
		||||
 	DECLARE_BITMAP(tid_tx_operational, IEEE80211_NUM_TIDS);
 | 
			
		||||
 
 | 
			
		||||
@@ -1913,11 +1915,15 @@ struct rtl8xxxu_priv {
 | 
			
		||||
 	DECLARE_BITMAP(cam_map, RTL8XXXU_MAX_SEC_CAM_NUM);
 | 
			
		||||
 };
 | 
			
		||||
 
 | 
			
		||||
+DECLARE_EWMA(rssi, 10, 16);
 | 
			
		||||
+
 | 
			
		||||
 struct rtl8xxxu_sta_info {
 | 
			
		||||
 	struct ieee80211_sta *sta;
 | 
			
		||||
 	struct ieee80211_vif *vif;
 | 
			
		||||
 
 | 
			
		||||
 	u8 macid;
 | 
			
		||||
+	struct ewma_rssi avg_rssi;
 | 
			
		||||
+	u8 rssi_level;
 | 
			
		||||
 };
 | 
			
		||||
 
 | 
			
		||||
 struct rtl8xxxu_vif {
 | 
			
		||||
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
 | 
			
		||||
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
 | 
			
		||||
@@ -4991,10 +4991,11 @@ rtl8xxxu_bss_info_changed(struct ieee802
 | 
			
		||||
 	struct rtl8xxxu_vif *rtlvif = (struct rtl8xxxu_vif *)vif->drv_priv;
 | 
			
		||||
 	struct rtl8xxxu_priv *priv = hw->priv;
 | 
			
		||||
 	struct device *dev = &priv->udev->dev;
 | 
			
		||||
+	struct rtl8xxxu_sta_info *sta_info;
 | 
			
		||||
 	struct ieee80211_sta *sta;
 | 
			
		||||
 	struct rtl8xxxu_ra_report *rarpt;
 | 
			
		||||
+	u8 val8, macid;
 | 
			
		||||
 	u32 val32;
 | 
			
		||||
-	u8 val8;
 | 
			
		||||
 
 | 
			
		||||
 	rarpt = &priv->ra_report;
 | 
			
		||||
 
 | 
			
		||||
@@ -5017,6 +5018,7 @@ rtl8xxxu_bss_info_changed(struct ieee802
 | 
			
		||||
 				rcu_read_unlock();
 | 
			
		||||
 				goto error;
 | 
			
		||||
 			}
 | 
			
		||||
+			macid = rtl8xxxu_get_macid(priv, sta);
 | 
			
		||||
 
 | 
			
		||||
 			if (sta->deflink.ht_cap.ht_supported)
 | 
			
		||||
 				dev_info(dev, "%s: HT supported\n", __func__);
 | 
			
		||||
@@ -5037,14 +5039,15 @@ rtl8xxxu_bss_info_changed(struct ieee802
 | 
			
		||||
 				bw = RATE_INFO_BW_40;
 | 
			
		||||
 			else
 | 
			
		||||
 				bw = RATE_INFO_BW_20;
 | 
			
		||||
+
 | 
			
		||||
+			sta_info = (struct rtl8xxxu_sta_info *)sta->drv_priv;
 | 
			
		||||
+			sta_info->rssi_level = RTL8XXXU_RATR_STA_INIT;
 | 
			
		||||
 			rcu_read_unlock();
 | 
			
		||||
 
 | 
			
		||||
 			rtl8xxxu_update_ra_report(rarpt, highest_rate, sgi, bw);
 | 
			
		||||
 
 | 
			
		||||
-			priv->rssi_level = RTL8XXXU_RATR_STA_INIT;
 | 
			
		||||
-
 | 
			
		||||
 			priv->fops->update_rate_mask(priv, ramask, 0, sgi,
 | 
			
		||||
-						     bw == RATE_INFO_BW_40, 0);
 | 
			
		||||
+						     bw == RATE_INFO_BW_40, macid);
 | 
			
		||||
 
 | 
			
		||||
 			rtl8xxxu_write8(priv, REG_BCN_MAX_ERR, 0xff);
 | 
			
		||||
 
 | 
			
		||||
@@ -6317,6 +6320,76 @@ static void rtl8188e_c2hcmd_callback(str
 | 
			
		||||
 	}
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
+#define rtl8xxxu_iterate_vifs_atomic(priv, iterator, data)			\
 | 
			
		||||
+	ieee80211_iterate_active_interfaces_atomic((priv)->hw,			\
 | 
			
		||||
+			IEEE80211_IFACE_ITER_NORMAL, iterator, data)
 | 
			
		||||
+
 | 
			
		||||
+struct rtl8xxxu_rx_update_rssi_data {
 | 
			
		||||
+	struct rtl8xxxu_priv *priv;
 | 
			
		||||
+	struct ieee80211_hdr *hdr;
 | 
			
		||||
+	struct ieee80211_rx_status *rx_status;
 | 
			
		||||
+	u8 *bssid;
 | 
			
		||||
+};
 | 
			
		||||
+
 | 
			
		||||
+static void rtl8xxxu_rx_update_rssi_iter(void *data, u8 *mac,
 | 
			
		||||
+					 struct ieee80211_vif *vif)
 | 
			
		||||
+{
 | 
			
		||||
+	struct rtl8xxxu_rx_update_rssi_data *iter_data = data;
 | 
			
		||||
+	struct ieee80211_sta *sta;
 | 
			
		||||
+	struct ieee80211_hdr *hdr = iter_data->hdr;
 | 
			
		||||
+	struct rtl8xxxu_priv *priv = iter_data->priv;
 | 
			
		||||
+	struct rtl8xxxu_sta_info *sta_info;
 | 
			
		||||
+	struct ieee80211_rx_status *rx_status = iter_data->rx_status;
 | 
			
		||||
+	u8 *bssid = iter_data->bssid;
 | 
			
		||||
+
 | 
			
		||||
+	if (!ether_addr_equal(vif->bss_conf.bssid, bssid))
 | 
			
		||||
+		return;
 | 
			
		||||
+
 | 
			
		||||
+	if (!(ether_addr_equal(vif->addr, hdr->addr1) ||
 | 
			
		||||
+	      ieee80211_is_beacon(hdr->frame_control)))
 | 
			
		||||
+		return;
 | 
			
		||||
+
 | 
			
		||||
+	sta = ieee80211_find_sta_by_ifaddr(priv->hw, hdr->addr2,
 | 
			
		||||
+					   vif->addr);
 | 
			
		||||
+	if (!sta)
 | 
			
		||||
+		return;
 | 
			
		||||
+
 | 
			
		||||
+	sta_info = (struct rtl8xxxu_sta_info *)sta->drv_priv;
 | 
			
		||||
+	ewma_rssi_add(&sta_info->avg_rssi, -rx_status->signal);
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
+static inline u8 *get_hdr_bssid(struct ieee80211_hdr *hdr)
 | 
			
		||||
+{
 | 
			
		||||
+	__le16 fc = hdr->frame_control;
 | 
			
		||||
+	u8 *bssid;
 | 
			
		||||
+
 | 
			
		||||
+	if (ieee80211_has_tods(fc))
 | 
			
		||||
+		bssid = hdr->addr1;
 | 
			
		||||
+	else if (ieee80211_has_fromds(fc))
 | 
			
		||||
+		bssid = hdr->addr2;
 | 
			
		||||
+	else
 | 
			
		||||
+		bssid = hdr->addr3;
 | 
			
		||||
+
 | 
			
		||||
+	return bssid;
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
+static void rtl8xxxu_rx_update_rssi(struct rtl8xxxu_priv *priv,
 | 
			
		||||
+				    struct ieee80211_rx_status *rx_status,
 | 
			
		||||
+				    struct ieee80211_hdr *hdr)
 | 
			
		||||
+{
 | 
			
		||||
+	struct rtl8xxxu_rx_update_rssi_data data = {};
 | 
			
		||||
+
 | 
			
		||||
+	if (ieee80211_is_ctl(hdr->frame_control))
 | 
			
		||||
+		return;
 | 
			
		||||
+
 | 
			
		||||
+	data.priv = priv;
 | 
			
		||||
+	data.hdr = hdr;
 | 
			
		||||
+	data.rx_status = rx_status;
 | 
			
		||||
+	data.bssid = get_hdr_bssid(hdr);
 | 
			
		||||
+
 | 
			
		||||
+	rtl8xxxu_iterate_vifs_atomic(priv, rtl8xxxu_rx_update_rssi_iter, &data);
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
 int rtl8xxxu_parse_rxdesc16(struct rtl8xxxu_priv *priv, struct sk_buff *skb)
 | 
			
		||||
 {
 | 
			
		||||
 	struct ieee80211_hw *hw = priv->hw;
 | 
			
		||||
@@ -6376,18 +6449,26 @@ int rtl8xxxu_parse_rxdesc16(struct rtl8x
 | 
			
		||||
 			skb_queue_tail(&priv->c2hcmd_queue, skb);
 | 
			
		||||
 			schedule_work(&priv->c2hcmd_work);
 | 
			
		||||
 		} else {
 | 
			
		||||
+			struct ieee80211_hdr *hdr;
 | 
			
		||||
+
 | 
			
		||||
 			phy_stats = (struct rtl8723au_phy_stats *)skb->data;
 | 
			
		||||
 
 | 
			
		||||
 			skb_pull(skb, drvinfo_sz + desc_shift);
 | 
			
		||||
 
 | 
			
		||||
 			skb_trim(skb, pkt_len);
 | 
			
		||||
 
 | 
			
		||||
-			if (rx_desc->phy_stats)
 | 
			
		||||
+			hdr = (struct ieee80211_hdr *)skb->data;
 | 
			
		||||
+			if (rx_desc->phy_stats) {
 | 
			
		||||
 				priv->fops->parse_phystats(
 | 
			
		||||
 					priv, rx_status, phy_stats,
 | 
			
		||||
 					rx_desc->rxmcs,
 | 
			
		||||
-					(struct ieee80211_hdr *)skb->data,
 | 
			
		||||
+					hdr,
 | 
			
		||||
 					rx_desc->crc32 || rx_desc->icverr);
 | 
			
		||||
+				if (!rx_desc->crc32 && !rx_desc->icverr)
 | 
			
		||||
+					rtl8xxxu_rx_update_rssi(priv,
 | 
			
		||||
+								rx_status,
 | 
			
		||||
+								hdr);
 | 
			
		||||
+			}
 | 
			
		||||
 
 | 
			
		||||
 			rx_status->mactime = rx_desc->tsfl;
 | 
			
		||||
 			rx_status->flag |= RX_FLAG_MACTIME_START;
 | 
			
		||||
@@ -6484,10 +6565,15 @@ int rtl8xxxu_parse_rxdesc24(struct rtl8x
 | 
			
		||||
 		} else {
 | 
			
		||||
 			struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
 | 
			
		||||
 
 | 
			
		||||
-			if (rx_desc->phy_stats)
 | 
			
		||||
+			if (rx_desc->phy_stats) {
 | 
			
		||||
 				priv->fops->parse_phystats(priv, rx_status, phy_stats,
 | 
			
		||||
 							   rx_desc->rxmcs, hdr,
 | 
			
		||||
 							   rx_desc->crc32 || rx_desc->icverr);
 | 
			
		||||
+				if (!rx_desc->crc32 && !rx_desc->icverr)
 | 
			
		||||
+					rtl8xxxu_rx_update_rssi(priv,
 | 
			
		||||
+								rx_status,
 | 
			
		||||
+								hdr);
 | 
			
		||||
+			}
 | 
			
		||||
 
 | 
			
		||||
 			rx_status->mactime = rx_desc->tsfl;
 | 
			
		||||
 			rx_status->flag |= RX_FLAG_MACTIME_START;
 | 
			
		||||
@@ -7111,6 +7197,7 @@ static void rtl8xxxu_refresh_rate_mask(s
 | 
			
		||||
 				       int signal, struct ieee80211_sta *sta,
 | 
			
		||||
 				       bool force)
 | 
			
		||||
 {
 | 
			
		||||
+	struct rtl8xxxu_sta_info *sta_info = (struct rtl8xxxu_sta_info *)sta->drv_priv;
 | 
			
		||||
 	struct ieee80211_hw *hw = priv->hw;
 | 
			
		||||
 	u16 wireless_mode;
 | 
			
		||||
 	u8 rssi_level, ratr_idx;
 | 
			
		||||
@@ -7119,7 +7206,7 @@ static void rtl8xxxu_refresh_rate_mask(s
 | 
			
		||||
 	u8 go_up_gap = 5;
 | 
			
		||||
 	u8 macid = rtl8xxxu_get_macid(priv, sta);
 | 
			
		||||
 
 | 
			
		||||
-	rssi_level = priv->rssi_level;
 | 
			
		||||
+	rssi_level = sta_info->rssi_level;
 | 
			
		||||
 	snr = rtl8xxxu_signal_to_snr(signal);
 | 
			
		||||
 	snr_thresh_high = RTL8XXXU_SNR_THRESH_HIGH;
 | 
			
		||||
 	snr_thresh_low = RTL8XXXU_SNR_THRESH_LOW;
 | 
			
		||||
@@ -7144,18 +7231,16 @@ static void rtl8xxxu_refresh_rate_mask(s
 | 
			
		||||
 	else
 | 
			
		||||
 		rssi_level = RTL8XXXU_RATR_STA_LOW;
 | 
			
		||||
 
 | 
			
		||||
-	if (rssi_level != priv->rssi_level || force) {
 | 
			
		||||
+	if (rssi_level != sta_info->rssi_level || force) {
 | 
			
		||||
 		int sgi = 0;
 | 
			
		||||
 		u32 rate_bitmap = 0;
 | 
			
		||||
 
 | 
			
		||||
-		rcu_read_lock();
 | 
			
		||||
 		rate_bitmap = (sta->deflink.supp_rates[0] & 0xfff) |
 | 
			
		||||
 				(sta->deflink.ht_cap.mcs.rx_mask[0] << 12) |
 | 
			
		||||
 				(sta->deflink.ht_cap.mcs.rx_mask[1] << 20);
 | 
			
		||||
 		if (sta->deflink.ht_cap.cap &
 | 
			
		||||
 		    (IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SGI_20))
 | 
			
		||||
 			sgi = 1;
 | 
			
		||||
-		rcu_read_unlock();
 | 
			
		||||
 
 | 
			
		||||
 		wireless_mode = rtl8xxxu_wireless_mode(hw, sta);
 | 
			
		||||
 		switch (wireless_mode) {
 | 
			
		||||
@@ -7236,7 +7321,7 @@ static void rtl8xxxu_refresh_rate_mask(s
 | 
			
		||||
 			break;
 | 
			
		||||
 		}
 | 
			
		||||
 
 | 
			
		||||
-		priv->rssi_level = rssi_level;
 | 
			
		||||
+		sta_info->rssi_level = rssi_level;
 | 
			
		||||
 		priv->fops->update_rate_mask(priv, rate_bitmap, ratr_idx, sgi, txbw_40mhz, macid);
 | 
			
		||||
 	}
 | 
			
		||||
 }
 | 
			
		||||
@@ -7329,40 +7414,60 @@ static void rtl8xxxu_track_cfo(struct rt
 | 
			
		||||
 	rtl8xxxu_set_atc_status(priv, abs(cfo_average) >= CFO_TH_ATC);
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
-static void rtl8xxxu_watchdog_callback(struct work_struct *work)
 | 
			
		||||
+static void rtl8xxxu_ra_iter(void *data, struct ieee80211_sta *sta)
 | 
			
		||||
 {
 | 
			
		||||
-	struct ieee80211_vif *vif;
 | 
			
		||||
-	struct rtl8xxxu_priv *priv;
 | 
			
		||||
-	int i;
 | 
			
		||||
+	struct rtl8xxxu_sta_info *sta_info = (struct rtl8xxxu_sta_info *)sta->drv_priv;
 | 
			
		||||
+	struct rtl8xxxu_priv *priv = data;
 | 
			
		||||
+	int signal = -ewma_rssi_read(&sta_info->avg_rssi);
 | 
			
		||||
 
 | 
			
		||||
-	priv = container_of(work, struct rtl8xxxu_priv, ra_watchdog.work);
 | 
			
		||||
-	for (i = 0; i < ARRAY_SIZE(priv->vifs); i++) {
 | 
			
		||||
-		vif = priv->vifs[i];
 | 
			
		||||
+	priv->fops->report_rssi(priv, rtl8xxxu_get_macid(priv, sta),
 | 
			
		||||
+				rtl8xxxu_signal_to_snr(signal));
 | 
			
		||||
+	rtl8xxxu_refresh_rate_mask(priv, signal, sta, false);
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
+struct rtl8xxxu_stas_entry {
 | 
			
		||||
+	struct list_head list;
 | 
			
		||||
+	struct ieee80211_sta *sta;
 | 
			
		||||
+};
 | 
			
		||||
 
 | 
			
		||||
-		if (!vif || vif->type != NL80211_IFTYPE_STATION)
 | 
			
		||||
-			continue;
 | 
			
		||||
+struct rtl8xxxu_iter_stas_data {
 | 
			
		||||
+	struct rtl8xxxu_priv *priv;
 | 
			
		||||
+	struct list_head list;
 | 
			
		||||
+};
 | 
			
		||||
 
 | 
			
		||||
-		int signal;
 | 
			
		||||
-		struct ieee80211_sta *sta;
 | 
			
		||||
+static void rtl8xxxu_collect_sta_iter(void *data, struct ieee80211_sta *sta)
 | 
			
		||||
+{
 | 
			
		||||
+	struct rtl8xxxu_iter_stas_data *iter_stas = data;
 | 
			
		||||
+	struct rtl8xxxu_stas_entry *stas_entry;
 | 
			
		||||
 
 | 
			
		||||
-		rcu_read_lock();
 | 
			
		||||
-		sta = ieee80211_find_sta(vif, vif->bss_conf.bssid);
 | 
			
		||||
-		if (!sta) {
 | 
			
		||||
-			struct device *dev = &priv->udev->dev;
 | 
			
		||||
+	stas_entry = kmalloc(sizeof(*stas_entry), GFP_ATOMIC);
 | 
			
		||||
+	if (!stas_entry)
 | 
			
		||||
+		return;
 | 
			
		||||
 
 | 
			
		||||
-			dev_dbg(dev, "%s: no sta found\n", __func__);
 | 
			
		||||
-			rcu_read_unlock();
 | 
			
		||||
-			continue;
 | 
			
		||||
-		}
 | 
			
		||||
-		rcu_read_unlock();
 | 
			
		||||
+	stas_entry->sta = sta;
 | 
			
		||||
+	list_add_tail(&stas_entry->list, &iter_stas->list);
 | 
			
		||||
+}
 | 
			
		||||
 
 | 
			
		||||
-		signal = ieee80211_ave_rssi(vif);
 | 
			
		||||
+static void rtl8xxxu_watchdog_callback(struct work_struct *work)
 | 
			
		||||
+{
 | 
			
		||||
 
 | 
			
		||||
-		priv->fops->report_rssi(priv, rtl8xxxu_get_macid(priv, sta),
 | 
			
		||||
-					rtl8xxxu_signal_to_snr(signal));
 | 
			
		||||
+	struct rtl8xxxu_iter_stas_data iter_data;
 | 
			
		||||
+	struct rtl8xxxu_stas_entry *sta_entry, *tmp;
 | 
			
		||||
+	struct rtl8xxxu_priv *priv;
 | 
			
		||||
 
 | 
			
		||||
-		rtl8xxxu_refresh_rate_mask(priv, signal, sta, false);
 | 
			
		||||
+	priv = container_of(work, struct rtl8xxxu_priv, ra_watchdog.work);
 | 
			
		||||
+	iter_data.priv = priv;
 | 
			
		||||
+	INIT_LIST_HEAD(&iter_data.list);
 | 
			
		||||
+
 | 
			
		||||
+	mutex_lock(&priv->sta_mutex);
 | 
			
		||||
+	ieee80211_iterate_stations_atomic(priv->hw, rtl8xxxu_collect_sta_iter,
 | 
			
		||||
+					  &iter_data);
 | 
			
		||||
+	list_for_each_entry_safe(sta_entry, tmp, &iter_data.list, list) {
 | 
			
		||||
+		list_del_init(&sta_entry->list);
 | 
			
		||||
+		rtl8xxxu_ra_iter(priv, sta_entry->sta);
 | 
			
		||||
+		kfree(sta_entry);
 | 
			
		||||
 	}
 | 
			
		||||
+	mutex_unlock(&priv->sta_mutex);
 | 
			
		||||
 
 | 
			
		||||
 	if (priv->fops->set_crystal_cap)
 | 
			
		||||
 		rtl8xxxu_track_cfo(priv);
 | 
			
		||||
@@ -7504,10 +7609,15 @@ static int rtl8xxxu_sta_add(struct ieee8
 | 
			
		||||
 	struct rtl8xxxu_vif *rtlvif = (struct rtl8xxxu_vif *)vif->drv_priv;
 | 
			
		||||
 	struct rtl8xxxu_priv *priv = hw->priv;
 | 
			
		||||
 
 | 
			
		||||
+	mutex_lock(&priv->sta_mutex);
 | 
			
		||||
+	ewma_rssi_init(&sta_info->avg_rssi);
 | 
			
		||||
 	if (vif->type == NL80211_IFTYPE_AP) {
 | 
			
		||||
+		sta_info->rssi_level = RTL8XXXU_RATR_STA_INIT;
 | 
			
		||||
 		sta_info->macid = rtl8xxxu_acquire_macid(priv);
 | 
			
		||||
-		if (sta_info->macid >= RTL8XXXU_MAX_MAC_ID_NUM)
 | 
			
		||||
+		if (sta_info->macid >= RTL8XXXU_MAX_MAC_ID_NUM) {
 | 
			
		||||
+			mutex_unlock(&priv->sta_mutex);
 | 
			
		||||
 			return -ENOSPC;
 | 
			
		||||
+		}
 | 
			
		||||
 
 | 
			
		||||
 		rtl8xxxu_refresh_rate_mask(priv, 0, sta, true);
 | 
			
		||||
 		priv->fops->report_connect(priv, sta_info->macid, H2C_MACID_ROLE_STA, true);
 | 
			
		||||
@@ -7523,6 +7633,7 @@ static int rtl8xxxu_sta_add(struct ieee8
 | 
			
		||||
 			break;
 | 
			
		||||
 		}
 | 
			
		||||
 	}
 | 
			
		||||
+	mutex_unlock(&priv->sta_mutex);
 | 
			
		||||
 
 | 
			
		||||
 	return 0;
 | 
			
		||||
 }
 | 
			
		||||
@@ -7534,8 +7645,10 @@ static int rtl8xxxu_sta_remove(struct ie
 | 
			
		||||
 	struct rtl8xxxu_sta_info *sta_info = (struct rtl8xxxu_sta_info *)sta->drv_priv;
 | 
			
		||||
 	struct rtl8xxxu_priv *priv = hw->priv;
 | 
			
		||||
 
 | 
			
		||||
+	mutex_lock(&priv->sta_mutex);
 | 
			
		||||
 	if (vif->type == NL80211_IFTYPE_AP)
 | 
			
		||||
 		rtl8xxxu_release_macid(priv, sta_info->macid);
 | 
			
		||||
+	mutex_unlock(&priv->sta_mutex);
 | 
			
		||||
 
 | 
			
		||||
 	return 0;
 | 
			
		||||
 }
 | 
			
		||||
@@ -7766,6 +7879,7 @@ static int rtl8xxxu_probe(struct usb_int
 | 
			
		||||
 	mutex_init(&priv->usb_buf_mutex);
 | 
			
		||||
 	mutex_init(&priv->syson_indirect_access_mutex);
 | 
			
		||||
 	mutex_init(&priv->h2c_mutex);
 | 
			
		||||
+	mutex_init(&priv->sta_mutex);
 | 
			
		||||
 	INIT_LIST_HEAD(&priv->tx_urb_free_list);
 | 
			
		||||
 	spin_lock_init(&priv->tx_urb_lock);
 | 
			
		||||
 	INIT_LIST_HEAD(&priv->rx_urb_pending_list);
 | 
			
		||||
@ -0,0 +1,40 @@
 | 
			
		||||
From 513c559ca9f05394da79fbf20a8f89eec5f53dce Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Ping-Ke Shih <pkshih@realtek.com>
 | 
			
		||||
Date: Fri, 16 Feb 2024 11:39:23 +0800
 | 
			
		||||
Subject: [PATCH] wifi: rtl8xxxu: check vif before using in rtl8xxxu_tx()
 | 
			
		||||
 | 
			
		||||
The 'vif' is from tx_info of SKB, and other codes check 'vif' before using,
 | 
			
		||||
which raises smatch warnings:
 | 
			
		||||
 | 
			
		||||
drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c:5656 rtl8xxxu_tx()
 | 
			
		||||
   warn: variable dereferenced before check 'vif' (see line 5553)
 | 
			
		||||
 | 
			
		||||
Compile tested only.
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
 | 
			
		||||
Signed-off-by: Kalle Valo <kvalo@kernel.org>
 | 
			
		||||
Link: https://msgid.link/20240216033923.34683-1-pkshih@realtek.com
 | 
			
		||||
---
 | 
			
		||||
 drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c | 4 ++--
 | 
			
		||||
 1 file changed, 2 insertions(+), 2 deletions(-)
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
 | 
			
		||||
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
 | 
			
		||||
@@ -5550,7 +5550,7 @@ static void rtl8xxxu_tx(struct ieee80211
 | 
			
		||||
 	struct rtl8xxxu_tx_urb *tx_urb;
 | 
			
		||||
 	struct ieee80211_sta *sta = NULL;
 | 
			
		||||
 	struct ieee80211_vif *vif = tx_info->control.vif;
 | 
			
		||||
-	struct rtl8xxxu_vif *rtlvif = (struct rtl8xxxu_vif *)vif->drv_priv;
 | 
			
		||||
+	struct rtl8xxxu_vif *rtlvif = vif ? (struct rtl8xxxu_vif *)vif->drv_priv : NULL;
 | 
			
		||||
 	struct device *dev = &priv->udev->dev;
 | 
			
		||||
 	u32 queue, rts_rate;
 | 
			
		||||
 	u16 pktlen = skb->len;
 | 
			
		||||
@@ -5621,7 +5621,7 @@ static void rtl8xxxu_tx(struct ieee80211
 | 
			
		||||
 		default:
 | 
			
		||||
 			break;
 | 
			
		||||
 		}
 | 
			
		||||
-		if (bmc && rtlvif->hw_key_idx != 0xff) {
 | 
			
		||||
+		if (bmc && rtlvif && rtlvif->hw_key_idx != 0xff) {
 | 
			
		||||
 			tx_desc->txdw1 |= cpu_to_le32(TXDESC_EN_DESC_ID);
 | 
			
		||||
 			macid = rtlvif->hw_key_idx;
 | 
			
		||||
 		}
 | 
			
		||||
@ -0,0 +1,34 @@
 | 
			
		||||
From a7e178259c5bc900da762b33d3a20b7ee1206f07 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Shiji Yang <yangshiji66@outlook.com>
 | 
			
		||||
Date: Fri, 23 Feb 2024 21:34:32 +0800
 | 
			
		||||
Subject: [PATCH] wifi: rtl8xxxu: fix mixed declarations in rtl8xxxu_set_aifs()
 | 
			
		||||
 | 
			
		||||
Moving struct ieee80211_sta *sta variable definition to the front
 | 
			
		||||
of the code to fix the ISO C90 forbids mixed declarations and code
 | 
			
		||||
warning.
 | 
			
		||||
 | 
			
		||||
Fixes: 43532c050f8e ("wifi: rtl8xxxu: support multiple interfaces in set_aifs()")
 | 
			
		||||
Signed-off-by: Shiji Yang <yangshiji66@outlook.com>
 | 
			
		||||
Reviewed-by: Ping-Ke Shih <pkshih@realtek.com>
 | 
			
		||||
Signed-off-by: Kalle Valo <kvalo@kernel.org>
 | 
			
		||||
Link: https://msgid.link/TYAP286MB03157A408E0D69F2F6FBD88ABC552@TYAP286MB0315.JPNP286.PROD.OUTLOOK.COM
 | 
			
		||||
---
 | 
			
		||||
 drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c | 4 ++--
 | 
			
		||||
 1 file changed, 2 insertions(+), 2 deletions(-)
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
 | 
			
		||||
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
 | 
			
		||||
@@ -4919,11 +4919,11 @@ static void rtl8xxxu_set_aifs(struct rtl
 | 
			
		||||
 	int i;
 | 
			
		||||
 
 | 
			
		||||
 	for (i = 0; i < ARRAY_SIZE(priv->vifs); i++) {
 | 
			
		||||
+		struct ieee80211_sta *sta;
 | 
			
		||||
+
 | 
			
		||||
 		if (!priv->vifs[i])
 | 
			
		||||
 			continue;
 | 
			
		||||
 
 | 
			
		||||
-		struct ieee80211_sta *sta;
 | 
			
		||||
-
 | 
			
		||||
 		rcu_read_lock();
 | 
			
		||||
 		sta = ieee80211_find_sta(priv->vifs[i], priv->vifs[i]->bss_conf.bssid);
 | 
			
		||||
 		if (sta)
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user