diff mbox series

wifi: rtw88: assign mac_id for vif/sta and update to TX desc

Message ID 20240819025248.17939-1-pkshih@realtek.com (mailing list archive)
State Accepted
Delegated to: Ping-Ke Shih
Headers show
Series wifi: rtw88: assign mac_id for vif/sta and update to TX desc | expand

Commit Message

Ping-Ke Shih Aug. 19, 2024, 2:52 a.m. UTC
A mac_id as an instance in firmware has to be assigned for each station
including AP and connected stations. Firmware will use the mac_id to
control TX rate and do statistics.

Assignment rule is to assign mac_id to each vif when adding vif.
For station mode, sta->mac_id will reuse vif->mac_id. For AP mode,
dynamically allocate an sta->mac_id to a station, and vif->mac_id is
used to send broadcast/multicast packets which are not belong to
a station. For example,

                  vif->mac_id      sta->mac_id
vif0 (STA mode)        0               0
vif1 (AP mode)         1               2...

By the way, remove unused RTW_BC_MC_MACID, which was planed to send
broadcast/multicast packets on fixed mac_id.

Tested-on RTL8822CE with STA + AP SCC mode.

Link: https://lore.kernel.org/linux-wireless/e4be0a75-43b2-4ae5-9aab-5c4a88e78097@gmail.com/
Cc: Bitterblue Smith <rtl8821cerfe2@gmail.com>
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
---
 drivers/net/wireless/realtek/rtw88/mac80211.c | 13 ++++++--
 drivers/net/wireless/realtek/rtw88/main.c     | 30 ++++++++-----------
 drivers/net/wireless/realtek/rtw88/main.h     | 14 +++++++--
 drivers/net/wireless/realtek/rtw88/tx.c       | 11 +++++--
 drivers/net/wireless/realtek/rtw88/tx.h       |  1 +
 5 files changed, 44 insertions(+), 25 deletions(-)

Comments

Bitterblue Smith Aug. 19, 2024, 6:53 p.m. UTC | #1
On 19/08/2024 05:52, Ping-Ke Shih wrote:
> A mac_id as an instance in firmware has to be assigned for each station
> including AP and connected stations. Firmware will use the mac_id to
> control TX rate and do statistics.
> 
> Assignment rule is to assign mac_id to each vif when adding vif.
> For station mode, sta->mac_id will reuse vif->mac_id. For AP mode,
> dynamically allocate an sta->mac_id to a station, and vif->mac_id is
> used to send broadcast/multicast packets which are not belong to
> a station. For example,
> 
>                   vif->mac_id      sta->mac_id
> vif0 (STA mode)        0               0
> vif1 (AP mode)         1               2...
> 
> By the way, remove unused RTW_BC_MC_MACID, which was planed to send
> broadcast/multicast packets on fixed mac_id.
> 

I tested this with RTL8822CE in AP mode with a single vif. It says:

Aug 19 21:32:47 ideapad2 kernel: rtw_8822ce 0000:02:00.0: change vif 00:45:e2:a1:65:ab (2)->(3), p2p (0)->(0)
Aug 19 21:32:47 ideapad2 kernel: rtw_8822ce 0000:02:00.0: stop vif 00:45:e2:a1:65:ab mac_id 0 on port 0
Aug 19 21:32:47 ideapad2 kernel: rtw_8822ce 0000:02:00.0: start vif 00:45:e2:a1:65:ab mac_id 0 on port 0
Aug 19 21:33:54 ideapad2 kernel: rtw_8822ce 0000:02:00.0: sta b6:bd:3c:c0:39:87 joined with macid 1

Then I added another vif:

# iw dev wlp2s0 interface add my_interface type managed

Aug 19 21:36:45 ideapad2 kernel: rtw_8822ce 0000:02:00.0: start vif 3e:60:cc:0b:fa:17 mac_id 2 on port 1

So in this case the AP vif's rtwvif->mac_id is 0, and the first
station gets 1. The managed vif's rtwvif->mac_id is 2. Is it okay
if the numbers are not assigned like in your example?
Ping-Ke Shih Aug. 20, 2024, 12:32 a.m. UTC | #2
Bitterblue Smith <rtl8821cerfe2@gmail.com> wrote:
> On 19/08/2024 05:52, Ping-Ke Shih wrote:
> > A mac_id as an instance in firmware has to be assigned for each station
> > including AP and connected stations. Firmware will use the mac_id to
> > control TX rate and do statistics.
> >
> > Assignment rule is to assign mac_id to each vif when adding vif.
> > For station mode, sta->mac_id will reuse vif->mac_id. For AP mode,
> > dynamically allocate an sta->mac_id to a station, and vif->mac_id is
> > used to send broadcast/multicast packets which are not belong to
> > a station. For example,
> >
> >                   vif->mac_id      sta->mac_id
> > vif0 (STA mode)        0               0
> > vif1 (AP mode)         1               2...
> >
> > By the way, remove unused RTW_BC_MC_MACID, which was planed to send
> > broadcast/multicast packets on fixed mac_id.
> >
> 
> I tested this with RTL8822CE in AP mode with a single vif. It says:
> 
> Aug 19 21:32:47 ideapad2 kernel: rtw_8822ce 0000:02:00.0: change vif 00:45:e2:a1:65:ab (2)->(3), p2p
> (0)->(0)
> Aug 19 21:32:47 ideapad2 kernel: rtw_8822ce 0000:02:00.0: stop vif 00:45:e2:a1:65:ab mac_id 0 on port 0
> Aug 19 21:32:47 ideapad2 kernel: rtw_8822ce 0000:02:00.0: start vif 00:45:e2:a1:65:ab mac_id 0 on port 0
> Aug 19 21:33:54 ideapad2 kernel: rtw_8822ce 0000:02:00.0: sta b6:bd:3c:c0:39:87 joined with macid 1
> 
> Then I added another vif:
> 
> # iw dev wlp2s0 interface add my_interface type managed
> 
> Aug 19 21:36:45 ideapad2 kernel: rtw_8822ce 0000:02:00.0: start vif 3e:60:cc:0b:fa:17 mac_id 2 on port 1
> 
> So in this case the AP vif's rtwvif->mac_id is 0, and the first
> station gets 1. The managed vif's rtwvif->mac_id is 2. Is it okay
> if the numbers are not assigned like in your example?

All mac_id are assigned dynamically. I think your case should be still fine.
Is there any problem you met?

I can change the real number to algebra

                   vif->mac_id      sta->mac_id
 vif0 (STA mode)        n               n
 vif1 (AP mode)         m               a, b, c ...

Where, n, m, a, b, c, ... are all different number. The special number is only 'n'
presents on two places.

The limit of hardware is AP mode should work on port 0, so you can find the
condition to switch port in rtw_core_port_switch():

	if (vif->type != NL80211_IFTYPE_AP || rtwvif->port == RTW_PORT_0)
		return;

Ping-Ke
Ping-Ke Shih Sept. 2, 2024, 12:49 a.m. UTC | #3
Ping-Ke Shih <pkshih@realtek.com> wrote:

> A mac_id as an instance in firmware has to be assigned for each station
> including AP and connected stations. Firmware will use the mac_id to
> control TX rate and do statistics.
> 
> Assignment rule is to assign mac_id to each vif when adding vif.
> For station mode, sta->mac_id will reuse vif->mac_id. For AP mode,
> dynamically allocate an sta->mac_id to a station, and vif->mac_id is
> used to send broadcast/multicast packets which are not belong to
> a station. For example,
> 
>                   vif->mac_id      sta->mac_id
> vif0 (STA mode)        0               0
> vif1 (AP mode)         1               2...
> 
> By the way, remove unused RTW_BC_MC_MACID, which was planed to send
> broadcast/multicast packets on fixed mac_id.
> 
> Tested-on RTL8822CE with STA + AP SCC mode.
> 
> Link: https://lore.kernel.org/linux-wireless/e4be0a75-43b2-4ae5-9aab-5c4a88e78097@gmail.com/
> Cc: Bitterblue Smith <rtl8821cerfe2@gmail.com>
> Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>

1 patch(es) applied to rtw-next branch of rtw.git, thanks.

902cb7b11f9a wifi: rtw88: assign mac_id for vif/sta and update to TX desc

---
https://github.com/pkshih/rtw.git
diff mbox series

Patch

diff --git a/drivers/net/wireless/realtek/rtw88/mac80211.c b/drivers/net/wireless/realtek/rtw88/mac80211.c
index 63326b352738..b39e90fb66b4 100644
--- a/drivers/net/wireless/realtek/rtw88/mac80211.c
+++ b/drivers/net/wireless/realtek/rtw88/mac80211.c
@@ -167,6 +167,12 @@  static int rtw_ops_add_interface(struct ieee80211_hw *hw,
 
 	mutex_lock(&rtwdev->mutex);
 
+	rtwvif->mac_id = rtw_acquire_macid(rtwdev);
+	if (rtwvif->mac_id >= RTW_MAX_MAC_ID_NUM) {
+		mutex_unlock(&rtwdev->mutex);
+		return -ENOSPC;
+	}
+
 	port = find_first_zero_bit(rtwdev->hw_port, RTW_PORT_NUM);
 	if (port >= RTW_PORT_NUM) {
 		mutex_unlock(&rtwdev->mutex);
@@ -214,7 +220,8 @@  static int rtw_ops_add_interface(struct ieee80211_hw *hw,
 
 	mutex_unlock(&rtwdev->mutex);
 
-	rtw_dbg(rtwdev, RTW_DBG_STATE, "start vif %pM on port %d\n", vif->addr, rtwvif->port);
+	rtw_dbg(rtwdev, RTW_DBG_STATE, "start vif %pM mac_id %d on port %d\n",
+		vif->addr, rtwvif->mac_id, rtwvif->port);
 	return 0;
 }
 
@@ -225,7 +232,8 @@  static void rtw_ops_remove_interface(struct ieee80211_hw *hw,
 	struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv;
 	u32 config = 0;
 
-	rtw_dbg(rtwdev, RTW_DBG_STATE, "stop vif %pM on port %d\n", vif->addr, rtwvif->port);
+	rtw_dbg(rtwdev, RTW_DBG_STATE, "stop vif %pM mac_id %d on port %d\n",
+		vif->addr, rtwvif->mac_id, rtwvif->port);
 
 	mutex_lock(&rtwdev->mutex);
 
@@ -242,6 +250,7 @@  static void rtw_ops_remove_interface(struct ieee80211_hw *hw,
 	config |= PORT_SET_BCN_CTRL;
 	rtw_vif_port_config(rtwdev, rtwvif, config);
 	clear_bit(rtwvif->port, rtwdev->hw_port);
+	rtw_release_macid(rtwdev, rtwvif->mac_id);
 	rtw_recalc_lps(rtwdev, NULL);
 
 	mutex_unlock(&rtwdev->mutex);
diff --git a/drivers/net/wireless/realtek/rtw88/main.c b/drivers/net/wireless/realtek/rtw88/main.c
index b0c9b0ff7017..bbdef38c7e34 100644
--- a/drivers/net/wireless/realtek/rtw88/main.c
+++ b/drivers/net/wireless/realtek/rtw88/main.c
@@ -311,17 +311,6 @@  static void rtw_ips_work(struct work_struct *work)
 	mutex_unlock(&rtwdev->mutex);
 }
 
-static u8 rtw_acquire_macid(struct rtw_dev *rtwdev)
-{
-	unsigned long mac_id;
-
-	mac_id = find_first_zero_bit(rtwdev->mac_id_map, RTW_MAX_MAC_ID_NUM);
-	if (mac_id < RTW_MAX_MAC_ID_NUM)
-		set_bit(mac_id, rtwdev->mac_id_map);
-
-	return mac_id;
-}
-
 static void rtw_sta_rc_work(struct work_struct *work)
 {
 	struct rtw_sta_info *si = container_of(work, struct rtw_sta_info,
@@ -340,12 +329,14 @@  int rtw_sta_add(struct rtw_dev *rtwdev, struct ieee80211_sta *sta,
 	struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv;
 	int i;
 
-	si->mac_id = rtw_acquire_macid(rtwdev);
-	if (si->mac_id >= RTW_MAX_MAC_ID_NUM)
-		return -ENOSPC;
+	if (vif->type == NL80211_IFTYPE_STATION) {
+		si->mac_id = rtwvif->mac_id;
+	} else {
+		si->mac_id = rtw_acquire_macid(rtwdev);
+		if (si->mac_id >= RTW_MAX_MAC_ID_NUM)
+			return -ENOSPC;
+	}
 
-	if (vif->type == NL80211_IFTYPE_STATION && vif->cfg.assoc == 0)
-		rtwvif->mac_id = si->mac_id;
 	si->rtwdev = rtwdev;
 	si->sta = sta;
 	si->vif = vif;
@@ -370,11 +361,13 @@  void rtw_sta_remove(struct rtw_dev *rtwdev, struct ieee80211_sta *sta,
 		    bool fw_exist)
 {
 	struct rtw_sta_info *si = (struct rtw_sta_info *)sta->drv_priv;
+	struct ieee80211_vif *vif = si->vif;
 	int i;
 
 	cancel_work_sync(&si->rc_work);
 
-	rtw_release_macid(rtwdev, si->mac_id);
+	if (vif->type != NL80211_IFTYPE_STATION)
+		rtw_release_macid(rtwdev, si->mac_id);
 	if (fw_exist)
 		rtw_fw_media_status_report(rtwdev, si->mac_id, false);
 
@@ -614,6 +607,8 @@  static void rtw_reset_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
 	rtw_bf_disassoc(rtwdev, vif, NULL);
 	rtw_vif_assoc_changed(rtwvif, NULL);
 	rtw_txq_cleanup(rtwdev, vif->txq);
+
+	rtw_release_macid(rtwdev, rtwvif->mac_id);
 }
 
 void rtw_fw_recovery(struct rtw_dev *rtwdev)
@@ -2139,7 +2134,6 @@  int rtw_core_init(struct rtw_dev *rtwdev)
 	rtwdev->sec.total_cam_num = 32;
 	rtwdev->hal.current_channel = 1;
 	rtwdev->dm_info.fix_rate = U8_MAX;
-	set_bit(RTW_BC_MC_MACID, rtwdev->mac_id_map);
 
 	rtw_stats_init(rtwdev);
 
diff --git a/drivers/net/wireless/realtek/rtw88/main.h b/drivers/net/wireless/realtek/rtw88/main.h
index 12b564ad3a58..945117afe143 100644
--- a/drivers/net/wireless/realtek/rtw88/main.h
+++ b/drivers/net/wireless/realtek/rtw88/main.h
@@ -742,7 +742,6 @@  struct rtw_txq {
 	unsigned long flags;
 };
 
-#define RTW_BC_MC_MACID 1
 DECLARE_EWMA(rssi, 10, 16);
 
 struct rtw_sta_info {
@@ -805,7 +804,7 @@  struct rtw_bf_info {
 struct rtw_vif {
 	enum rtw_net_type net_type;
 	u16 aid;
-	u8 mac_id; /* for STA mode only */
+	u8 mac_id;
 	u8 mac_addr[ETH_ALEN];
 	u8 bssid[ETH_ALEN];
 	u8 port;
@@ -2131,6 +2130,17 @@  static inline bool rtw_chip_has_tx_stbc(struct rtw_dev *rtwdev)
 	return rtwdev->chip->tx_stbc;
 }
 
+static inline u8 rtw_acquire_macid(struct rtw_dev *rtwdev)
+{
+	unsigned long mac_id;
+
+	mac_id = find_first_zero_bit(rtwdev->mac_id_map, RTW_MAX_MAC_ID_NUM);
+	if (mac_id < RTW_MAX_MAC_ID_NUM)
+		set_bit(mac_id, rtwdev->mac_id_map);
+
+	return mac_id;
+}
+
 static inline void rtw_release_macid(struct rtw_dev *rtwdev, u8 mac_id)
 {
 	clear_bit(mac_id, rtwdev->mac_id_map);
diff --git a/drivers/net/wireless/realtek/rtw88/tx.c b/drivers/net/wireless/realtek/rtw88/tx.c
index c02ac673be32..dae7ca148865 100644
--- a/drivers/net/wireless/realtek/rtw88/tx.c
+++ b/drivers/net/wireless/realtek/rtw88/tx.c
@@ -46,7 +46,8 @@  void rtw_tx_fill_tx_desc(struct rtw_tx_pkt_info *pkt_info, struct sk_buff *skb)
 		      le32_encode_bits(pkt_info->ls, RTW_TX_DESC_W0_LS) |
 		      le32_encode_bits(pkt_info->dis_qselseq, RTW_TX_DESC_W0_DISQSELSEQ);
 
-	tx_desc->w1 = le32_encode_bits(pkt_info->qsel, RTW_TX_DESC_W1_QSEL) |
+	tx_desc->w1 = le32_encode_bits(pkt_info->mac_id, RTW_TX_DESC_W1_MACID) |
+		      le32_encode_bits(pkt_info->qsel, RTW_TX_DESC_W1_QSEL) |
 		      le32_encode_bits(pkt_info->rate_id, RTW_TX_DESC_W1_RATE_ID) |
 		      le32_encode_bits(pkt_info->sec_type, RTW_TX_DESC_W1_SEC_TYPE) |
 		      le32_encode_bits(pkt_info->pkt_offset, RTW_TX_DESC_W1_PKT_OFFSET) |
@@ -401,14 +402,18 @@  void rtw_tx_pkt_info_update(struct rtw_dev *rtwdev,
 	const struct rtw_chip_info *chip = rtwdev->chip;
 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+	struct ieee80211_vif *vif = info->control.vif;
 	struct rtw_sta_info *si;
-	struct ieee80211_vif *vif = NULL;
+	struct rtw_vif *rtwvif;
 	__le16 fc = hdr->frame_control;
 	bool bmc;
 
 	if (sta) {
 		si = (struct rtw_sta_info *)sta->drv_priv;
-		vif = si->vif;
+		pkt_info->mac_id = si->mac_id;
+	} else if (vif) {
+		rtwvif = (struct rtw_vif *)vif->drv_priv;
+		pkt_info->mac_id = rtwvif->mac_id;
 	}
 
 	if (ieee80211_is_mgmt(fc) || ieee80211_is_nullfunc(fc))
diff --git a/drivers/net/wireless/realtek/rtw88/tx.h b/drivers/net/wireless/realtek/rtw88/tx.h
index 324189606257..3d544fd7f60f 100644
--- a/drivers/net/wireless/realtek/rtw88/tx.h
+++ b/drivers/net/wireless/realtek/rtw88/tx.h
@@ -27,6 +27,7 @@  struct rtw_tx_desc {
 #define RTW_TX_DESC_W0_BMC BIT(24)
 #define RTW_TX_DESC_W0_LS BIT(26)
 #define RTW_TX_DESC_W0_DISQSELSEQ BIT(31)
+#define RTW_TX_DESC_W1_MACID GENMASK(7, 0)
 #define RTW_TX_DESC_W1_QSEL GENMASK(12, 8)
 #define RTW_TX_DESC_W1_RATE_ID GENMASK(20, 16)
 #define RTW_TX_DESC_W1_SEC_TYPE GENMASK(23, 22)