Skip to contentSkip to conversation

rtw89: support AP mode

PATCH In review Ping-Ke Shih 2 participants 9 messages Feb 7, 2022 – Feb 10, 2022 Realtek wireless driver (rtw89)

lore
Share & tools
lore

Ping-Ke Shih

author maintainer
#0 lore raw

v2 cover rtw89: support AP mode

To support AP mode, we implement ::start_ap and ::stop_ap to configure firmware and hardware to play an AP. Then, we download beacon content to firmware, so firmware can send out periodically the frames that must have continual sequence number with other management frames.

When mac80211 buffers unicast packets for certain STAs, it tells driver via ::set_tim, and then we download the beacon content to firmware again. On the other hand, if a broadcast packet is going to send out, it should go via HIQ (HI queue) that hardware will raise group frame bit in TIM of beacon frame. But if no STA sleeps, a broadcast packet is sent via AC queue.

When a STA is going to connect, it issues a probe request frame and then auth/assoc frames. To receive these frames before it is connected, we need to consider more RX filter flags to set registers properly.

When a connection is established, we need to assign a mac_id as a behalf of this peer in firmware and hardware, and then use this mac_id to initialize an instance in firmware via H2C(s). The most important part is to add a corresponding address CAM entry that contains peer's MAC address and BSSID, so hardware can determine a packet is belong to which peer. If it is a security connection, keys will be filled to security CAM as well.

Since there are many CAM ID(s), I add a debugfs entry to see if the relations between ID(s) and STA(s) are expected.

v2:
- use full logic style of 'self_role'
- 1~13/19 patches of patchset v1 are merged, so v2 contains remaining 7 patches.

Ping-Ke Shih (7):
rtw89: extend role_maintain to support AP mode
rtw89: add addr_cam field to sta to support AP mode
rtw89: only STA mode change vif_type mapping dynamically
rtw89: maintain assoc/disassoc STA states of firmware and hardware
rtw89: implement ieee80211_ops::start_ap and stop_ap
rtw89: debug: add stations entry to show ID assignment
rtw89: declare AP mode support

 drivers/net/wireless/realtek/rtw89/cam.c      |  6 +-
 drivers/net/wireless/realtek/rtw89/core.c     | 43 +++++++++--
 drivers/net/wireless/realtek/rtw89/core.h     | 62 +++++++++-------
 drivers/net/wireless/realtek/rtw89/debug.c    | 71 +++++++++++++++++++
 drivers/net/wireless/realtek/rtw89/fw.c       | 16 ++++-
 drivers/net/wireless/realtek/rtw89/fw.h       |  1 +
 drivers/net/wireless/realtek/rtw89/mac.c      |  8 +--
 drivers/net/wireless/realtek/rtw89/mac.h      |  1 +
 drivers/net/wireless/realtek/rtw89/mac80211.c | 36 ++++++++++
 9 files changed, 204 insertions(+), 40 deletions(-)
Signature · 1 line
2.25.1
author maintainer
#1 lore raw

PATCH v2 1/7 rtw89: extend role_maintain to support AP mode

Fill mac_id and self_role depends on the operation mode.

In AP mode, echo connected station has an unique mac_id, and each vif also has one mac_id to represent itself.

The self_role is assigned to vif if the operation mode is decided, and RTW89_SELF_ROLE_AP_CLIENT is assigned to the connected STA in AP mode,

---
 drivers/net/wireless/realtek/rtw89/fw.c  | 16 ++++++++++++++--
 drivers/net/wireless/realtek/rtw89/fw.h  |  1 +
 drivers/net/wireless/realtek/rtw89/mac.c |  4 ++--
 3 files changed, 17 insertions(+), 4 deletions(-)
drivers/net/wireless/realtek/rtw89/fw.c +14 -2
index 2d5b6323b607d..7fa60fd00143a 100644
@@ -993,9 +993,21 @@ int rtw89_fw_h2c_update_beacon(struct rtw89_dev *rtwdev,
 #define H2C_ROLE_MAINTAIN_LEN 4
 int rtw89_fw_h2c_role_maintain(struct rtw89_dev *rtwdev,
 			       struct rtw89_vif *rtwvif,
+			       struct rtw89_sta *rtwsta,
 			       enum rtw89_upd_mode upd_mode)
 {
 	struct sk_buff *skb;
+	u8 mac_id = rtwsta ? rtwsta->mac_id : rtwvif->mac_id;
+	u8 self_role;
+
+	if (rtwvif->net_type == RTW89_NET_TYPE_AP_MODE) {
+		if (rtwsta)
+			self_role = RTW89_SELF_ROLE_AP_CLIENT;
+		else
+			self_role = rtwvif->self_role;
+	} else {
+		self_role = rtwvif->self_role;
+	}
 
 	skb = rtw89_fw_h2c_alloc_skb_with_hdr(H2C_ROLE_MAINTAIN_LEN);
 	if (!skb) {
@@ -1003,8 +1015,8 @@ int rtw89_fw_h2c_role_maintain(struct rtw89_dev *rtwdev,
 		return -ENOMEM;
 	}
 	skb_put(skb, H2C_ROLE_MAINTAIN_LEN);
-	SET_FWROLE_MAINTAIN_MACID(skb->data, rtwvif->mac_id);
-	SET_FWROLE_MAINTAIN_SELF_ROLE(skb->data, rtwvif->self_role);
+	SET_FWROLE_MAINTAIN_MACID(skb->data, mac_id);
+	SET_FWROLE_MAINTAIN_SELF_ROLE(skb->data, self_role);
 	SET_FWROLE_MAINTAIN_UPD_MODE(skb->data, upd_mode);
 	SET_FWROLE_MAINTAIN_WIFI_ROLE(skb->data, rtwvif->wifi_role);
 
drivers/net/wireless/realtek/rtw89/fw.h +1 -0
index b30cf0a2cc1e0..83f4eaaf90f3b 100644
@@ -1886,6 +1886,7 @@ void rtw89_fw_c2h_irqsafe(struct rtw89_dev *rtwdev, struct sk_buff *c2h);
 void rtw89_fw_c2h_work(struct work_struct *work);
 int rtw89_fw_h2c_role_maintain(struct rtw89_dev *rtwdev,
 			       struct rtw89_vif *rtwvif,
+			       struct rtw89_sta *rtwsta,
 			       enum rtw89_upd_mode upd_mode);
 int rtw89_fw_h2c_join_info(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
 			   struct rtw89_sta *rtwsta, bool dis_conn);
drivers/net/wireless/realtek/rtw89/mac.c +2 -2
index 2e95d9007c41d..2ced6a8b36c2d 100644
@@ -3025,7 +3025,7 @@ int rtw89_mac_vif_init(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
 	if (ret)
 		return ret;
 
-	ret = rtw89_fw_h2c_role_maintain(rtwdev, rtwvif, RTW89_ROLE_CREATE);
+	ret = rtw89_fw_h2c_role_maintain(rtwdev, rtwvif, NULL, RTW89_ROLE_CREATE);
 	if (ret)
 		return ret;
 
@@ -3048,7 +3048,7 @@ int rtw89_mac_vif_deinit(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
 {
 	int ret;
 
-	ret = rtw89_fw_h2c_role_maintain(rtwdev, rtwvif, RTW89_ROLE_REMOVE);
+	ret = rtw89_fw_h2c_role_maintain(rtwdev, rtwvif, NULL, RTW89_ROLE_REMOVE);
 	if (ret)
 		return ret;
 
Signature · 1 line
2.25.1
#2 lore raw

Re: [PATCH 1/7] rtw89: extend role_maintain to support AP mode

Quoted 9 lines · Ping-Ke Shih

Fill mac_id and self_role depends on the operation mode.

In AP mode, echo connected station has an unique mac_id, and each vif also has one mac_id to represent itself.

The self_role is assigned to vif if the operation mode is decided, and RTW89_SELF_ROLE_AP_CLIENT is assigned to the connected STA in AP mode,

7 patches applied to wireless-next.git, thanks.

ff66964a9467 rtw89: extend role_maintain to support AP mode 2ab856cc3a6c rtw89: add addr_cam field to sta to support AP mode fd7ee4c8ac14 rtw89: only STA mode change vif_type mapping dynamically 1b73e77db1d0 rtw89: maintain assoc/disassoc STA states of firmware and hardware a52e4f2ce0f5 rtw89: implement ieee80211_ops::start_ap and stop_ap d95d8d6bba72 rtw89: debug: add stations entry to show ID assignment b478ff6bcb2d rtw89: declare AP mode support

Signature · 3 lines
https://patchwork.kernel.org/project/linux-wireless/patch/[email protected]/

https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches
author maintainer
#3 lore raw

PATCH v2 2/7 rtw89: add addr_cam field to sta to support AP mode

In reply to Ping-Ke Shih

In AP mode, each connected station needs an entry of address CAM. The address CAM of vif is still needed to assit in AP itself.

For station mode, it still uses vif's address CAM.

Add a help macro rtw89_get_addr_cam_of() to get addr_cam from vif or sta for all use cases.

---
 drivers/net/wireless/realtek/rtw89/cam.c  |  6 +--
 drivers/net/wireless/realtek/rtw89/core.c |  5 +-
 drivers/net/wireless/realtek/rtw89/core.h | 62 +++++++++++++----------
 3 files changed, 43 insertions(+), 30 deletions(-)
drivers/net/wireless/realtek/rtw89/cam.c +3 -3
index 2114d117b603d..305dbbebff6bb 100644
@@ -231,7 +231,7 @@ static int rtw89_cam_attach_sec_cam(struct rtw89_dev *rtwdev,
 	}
 
 	rtwvif = (struct rtw89_vif *)vif->drv_priv;
-	addr_cam = &rtwvif->addr_cam;
+	addr_cam = rtw89_get_addr_cam_of(rtwvif, rtwsta);
 	ret = rtw89_cam_get_addr_cam_key_idx(addr_cam, sec_cam, key, &key_idx);
 	if (ret) {
 		rtw89_err(rtwdev, "failed to get addr cam key idx %d, %d\n",
@@ -387,7 +387,7 @@ int rtw89_cam_sec_key_del(struct rtw89_dev *rtwdev,
 	}
 
 	rtwvif = (struct rtw89_vif *)vif->drv_priv;
-	addr_cam = &rtwvif->addr_cam;
+	addr_cam = rtw89_get_addr_cam_of(rtwvif, rtwsta);
 	sec_cam = addr_cam->sec_entries[key_idx];
 	if (!sec_cam)
 		return -EINVAL;
@@ -617,7 +617,7 @@ void rtw89_cam_fill_addr_cam_info(struct rtw89_dev *rtwdev,
 				  u8 *cmd)
 {
 	struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif);
-	struct rtw89_addr_cam_entry *addr_cam = &rtwvif->addr_cam;
+	struct rtw89_addr_cam_entry *addr_cam = rtw89_get_addr_cam_of(rtwvif, rtwsta);
 	struct ieee80211_sta *sta = rtwsta_to_sta_safe(rtwsta);
 	const u8 *sma = scan_mac_addr ? scan_mac_addr : rtwvif->mac_addr;
 	u8 sma_hash, tma_hash, addr_msk_start;
drivers/net/wireless/realtek/rtw89/core.c +4 -1
index 490f5d86eeb2e..81575463a833f 100644
@@ -4,6 +4,7 @@
 #include <linux/ip.h>
 #include <linux/udp.h>
 
+#include "cam.h"
 #include "coex.h"
 #include "core.h"
 #include "efuse.h"
@@ -399,9 +400,11 @@ rtw89_core_tx_update_sec_key(struct rtw89_dev *rtwdev,
 			     struct rtw89_core_tx_request *tx_req)
 {
 	struct ieee80211_vif *vif = tx_req->vif;
+	struct ieee80211_sta *sta = tx_req->sta;
 	struct ieee80211_tx_info *info;
 	struct ieee80211_key_conf *key;
 	struct rtw89_vif *rtwvif;
+	struct rtw89_sta *rtwsta = sta_to_rtwsta_safe(sta);
 	struct rtw89_addr_cam_entry *addr_cam;
 	struct rtw89_sec_cam_entry *sec_cam;
 	struct rtw89_tx_desc_info *desc_info = &tx_req->desc_info;
@@ -414,7 +417,7 @@ rtw89_core_tx_update_sec_key(struct rtw89_dev *rtwdev,
 	}
 
 	rtwvif = (struct rtw89_vif *)vif->drv_priv;
-	addr_cam = &rtwvif->addr_cam;
+	addr_cam = rtw89_get_addr_cam_of(rtwvif, rtwsta);
 
 	info = IEEE80211_SKB_CB(skb);
 	key = info->control.hw_key;
drivers/net/wireless/realtek/rtw89/core.h +36 -26

80 lines not on this page · raw message

Signature · 1 line
2.25.1
author maintainer
#4 lore raw

PATCH v2 3/7 rtw89: only STA mode change vif_type mapping dynamically

In reply to Ping-Ke Shih

vif_type mapping indicates hardware operating mode corresponding to vif type. In STA mode, hardware mode should be INFRA or NO_LINK mode dynamically according to association status. Since AP mode don't need to change this by association status intuitively, just do the mapping in STA mode.

---
 drivers/net/wireless/realtek/rtw89/core.c     | 4 ++--
 drivers/net/wireless/realtek/rtw89/mac80211.c | 3 +++
 2 files changed, 5 insertions(+), 2 deletions(-)
drivers/net/wireless/realtek/rtw89/core.c +2 -2
index 81575463a833f..8849f3172a341 100644
@@ -2047,7 +2047,8 @@ int rtw89_core_sta_disconnect(struct rtw89_dev *rtwdev,
 	rtw89_mac_bf_disassoc(rtwdev, vif, sta);
 	rtw89_core_free_sta_pending_ba(rtwdev, sta);
 
-	rtw89_vif_type_mapping(vif, false);
+	if (vif->type == NL80211_IFTYPE_STATION)
+		rtw89_vif_type_mapping(vif, false);
 
 	ret = rtw89_fw_h2c_assoc_cmac_tbl(rtwdev, vif, sta);
 	if (ret) {
@@ -2079,7 +2080,6 @@ int rtw89_core_sta_assoc(struct rtw89_dev *rtwdev,
 	struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv;
 	int ret;
 
-	rtw89_vif_type_mapping(vif, true);
 
 	ret = rtw89_fw_h2c_assoc_cmac_tbl(rtwdev, vif, sta);
 	if (ret) {
drivers/net/wireless/realtek/rtw89/mac80211.c +3 -0
index 02480a6bdf4c0..295d54c0fc94a 100644
@@ -324,6 +324,9 @@ static void rtw89_station_mode_sta_assoc(struct rtw89_dev *rtwdev,
 		rtw89_err(rtwdev, "can't find sta to set sta_assoc state\n");
 		return;
 	}
+
+	rtw89_vif_type_mapping(vif, true);
+
 	rtw89_core_sta_assoc(rtwdev, vif, sta);
 }
 
Signature · 1 line
2.25.1
author maintainer
#5 lore raw

PATCH v2 4/7 rtw89: maintain assoc/disassoc STA states of firmware and hardware

In reply to Ping-Ke Shih

In AP mode, when a STA associate to us, we need to create an entry in firmware and hardware, and then they can transmit data properly.

The entry index called mac_id which is assigned when sta_add, and we ask firmware to create an entry for an associated station. Also, the address CAM should be filled so hardware can know which packet is ours, and lookup the mac_id for further use.

---
 drivers/net/wireless/realtek/rtw89/core.c | 31 ++++++++++++++++++++++-
 drivers/net/wireless/realtek/rtw89/mac.c  |  4 +--
 drivers/net/wireless/realtek/rtw89/mac.h  |  1 +
 3 files changed, 33 insertions(+), 3 deletions(-)
drivers/net/wireless/realtek/rtw89/core.c +30 -1
index 8849f3172a341..413bb391c21e3 100644
@@ -2046,6 +2046,8 @@ int rtw89_core_sta_disconnect(struct rtw89_dev *rtwdev,
 	rtw89_mac_bf_monitor_calc(rtwdev, sta, true);
 	rtw89_mac_bf_disassoc(rtwdev, vif, sta);
 	rtw89_core_free_sta_pending_ba(rtwdev, sta);
+	if (vif->type == NL80211_IFTYPE_AP)
+		rtw89_cam_deinit_addr_cam(rtwdev, &rtwsta->addr_cam);
 
 	if (vif->type == NL80211_IFTYPE_STATION)
 		rtw89_vif_type_mapping(vif, false);
@@ -2062,8 +2064,16 @@ int rtw89_core_sta_disconnect(struct rtw89_dev *rtwdev,
 		return ret;
 	}
 
+	if (vif->type == NL80211_IFTYPE_AP) {
+		ret = rtw89_fw_h2c_role_maintain(rtwdev, rtwvif, rtwsta, RTW89_ROLE_REMOVE);
+		if (ret) {
+			rtw89_warn(rtwdev, "failed to send h2c role info\n");
+			return ret;
+		}
+	}
+
 	/* update cam aid mac_id net_type */
-	rtw89_fw_h2c_cam(rtwdev, rtwvif, rtwsta, NULL);
+	ret = rtw89_fw_h2c_cam(rtwdev, rtwvif, rtwsta, NULL);
 	if (ret) {
 		rtw89_warn(rtwdev, "failed to send h2c cam\n");
 		return ret;
@@ -2080,6 +2090,25 @@ int rtw89_core_sta_assoc(struct rtw89_dev *rtwdev,
 	struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv;
 	int ret;
 
+	if (vif->type == NL80211_IFTYPE_AP) {
+		ret = rtw89_mac_set_macid_pause(rtwdev, rtwsta->mac_id, false);
+		if (ret) {
+			rtw89_warn(rtwdev, "failed to send h2c macid pause\n");
+			return ret;
+		}
+
+		ret = rtw89_fw_h2c_role_maintain(rtwdev, rtwvif, rtwsta, RTW89_ROLE_CREATE);
+		if (ret) {
+			rtw89_warn(rtwdev, "failed to send h2c role info\n");
+			return ret;
+		}
+
+		ret = rtw89_cam_init_addr_cam(rtwdev, &rtwsta->addr_cam, &rtwvif->bssid_cam);
+		if (ret) {
+			rtw89_warn(rtwdev, "failed to send h2c init addr cam\n");
+			return ret;
+		}
+	}
 
 	ret = rtw89_fw_h2c_assoc_cmac_tbl(rtwdev, vif, sta);
 	if (ret) {
drivers/net/wireless/realtek/rtw89/mac.c +2 -2
index 2ced6a8b36c2d..3cd208d05c7c0 100644
@@ -2718,7 +2718,7 @@ static void rtw89_mac_cmac_tbl_init(struct rtw89_dev *rtwdev, u8 macid)
 	rtw89_write32(rtwdev, R_AX_INDIR_ACCESS_ENTRY + 28, 0xB8109);
 }
 
-static int rtw89_set_macid_pause(struct rtw89_dev *rtwdev, u8 macid, bool pause)
+int rtw89_mac_set_macid_pause(struct rtw89_dev *rtwdev, u8 macid, bool pause)
 {
 	u8 sh =  FIELD_GET(GENMASK(4, 0), macid);
 	u8 grp = macid >> 5;
@@ -3021,7 +3021,7 @@ int rtw89_mac_vif_init(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
 	rtw89_mac_dmac_tbl_init(rtwdev, rtwvif->mac_id);
 	rtw89_mac_cmac_tbl_init(rtwdev, rtwvif->mac_id);
 
-	ret = rtw89_set_macid_pause(rtwdev, rtwvif->mac_id, false);
+	ret = rtw89_mac_set_macid_pause(rtwdev, rtwvif->mac_id, false);
 	if (ret)
 		return ret;
 
drivers/net/wireless/realtek/rtw89/mac.h +1 -0
index 9fe7629f1da16..e5db0a2eb9c29 100644
@@ -811,6 +811,7 @@ int rtw89_mac_vif_init(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif);
 int rtw89_mac_vif_deinit(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif);
 int rtw89_mac_set_hw_muedca_ctrl(struct rtw89_dev *rtwdev,
 				 struct rtw89_vif *rtwvif, bool en);
+int rtw89_mac_set_macid_pause(struct rtw89_dev *rtwdev, u8 macid, bool pause);
 
 static inline void rtw89_mac_bf_monitor_track(struct rtw89_dev *rtwdev)
 {
Signature · 1 line
2.25.1
author maintainer
#6 lore raw

PATCH v2 5/7 rtw89: implement ieee80211_ops::start_ap and stop_ap

In reply to Ping-Ke Shih

Configure firmware and hardware to run AP mode. The start_ap() setup bssid, mac port, mac_id entry, and does RFK. The stop_ap() reset the state.

---
 drivers/net/wireless/realtek/rtw89/mac80211.c | 33 +++++++++++++++++++
 1 file changed, 33 insertions(+)
drivers/net/wireless/realtek/rtw89/mac80211.c +33 -0
index 295d54c0fc94a..5df7aceabdf5e 100644
@@ -371,6 +371,37 @@ static void rtw89_ops_bss_info_changed(struct ieee80211_hw *hw,
 	mutex_unlock(&rtwdev->mutex);
 }
 
+static int rtw89_ops_start_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
+{
+	struct rtw89_dev *rtwdev = hw->priv;
+	struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
+
+	mutex_lock(&rtwdev->mutex);
+	ether_addr_copy(rtwvif->bssid, vif->bss_conf.bssid);
+	rtw89_cam_bssid_changed(rtwdev, rtwvif);
+	rtw89_mac_port_update(rtwdev, rtwvif);
+	rtw89_fw_h2c_assoc_cmac_tbl(rtwdev, vif, NULL);
+	rtw89_fw_h2c_role_maintain(rtwdev, rtwvif, NULL, RTW89_ROLE_TYPE_CHANGE);
+	rtw89_fw_h2c_join_info(rtwdev, rtwvif, NULL, true);
+	rtw89_fw_h2c_cam(rtwdev, rtwvif, NULL, NULL);
+	rtw89_chip_rfk_channel(rtwdev);
+	mutex_unlock(&rtwdev->mutex);
+
+	return 0;
+}
+
+static
+void rtw89_ops_stop_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
+{
+	struct rtw89_dev *rtwdev = hw->priv;
+	struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
+
+	mutex_lock(&rtwdev->mutex);
+	rtw89_fw_h2c_assoc_cmac_tbl(rtwdev, vif, NULL);
+	rtw89_fw_h2c_join_info(rtwdev, rtwvif, NULL, true);
+	mutex_unlock(&rtwdev->mutex);
+}
+
 static int rtw89_ops_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta,
 			     bool set)
 {
@@ -699,6 +730,8 @@ const struct ieee80211_ops rtw89_ops = {
 	.remove_interface	= rtw89_ops_remove_interface,
 	.configure_filter	= rtw89_ops_configure_filter,
 	.bss_info_changed	= rtw89_ops_bss_info_changed,
+	.start_ap		= rtw89_ops_start_ap,
+	.stop_ap		= rtw89_ops_stop_ap,
 	.set_tim		= rtw89_ops_set_tim,
 	.conf_tx		= rtw89_ops_conf_tx,
 	.sta_state		= rtw89_ops_sta_state,
Signature · 1 line
2.25.1
author maintainer
#7 lore raw

PATCH v2 6/7 rtw89: debug: add stations entry to show ID assignment

In reply to Ping-Ke Shih

In order to trace the relation of IDs, we add this debugfs entry to make them clear.

The output looks like:
map:

          mac_id:    07 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
          addr_cam:  07 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
          bssid_cam: 01 00 00 00 00 00 00 00
          sec_cam:   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  VIF [0] 94:08:53:8e:ef:21
          bssid_cam_idx=0
          addr_cam_idx=0
          -> bssid_cam_idx=0
          sec_cam_bitmap=00 00 00 00 00 00 00 00
  STA [1] 58:00:e3:bb:9c:4f
          addr_cam_idx=1
          -> bssid_cam_idx=0
          sec_cam_bitmap=00 00 00 00 00 00 00 00
  STA [2] 94:08:53:8e:ef:75
          addr_cam_idx=2
          -> bssid_cam_idx=0
          sec_cam_bitmap=00 00 00 00 00 00 00 00
---
 drivers/net/wireless/realtek/rtw89/debug.c | 71 ++++++++++++++++++++++
 1 file changed, 71 insertions(+)
drivers/net/wireless/realtek/rtw89/debug.c +71 -0
index b25d88d508553..b73cc03cecfd7 100644
@@ -2372,6 +2372,72 @@ static int rtw89_debug_priv_phy_info_get(struct seq_file *m, void *v)
 	return 0;
 }
 
+static void rtw89_dump_addr_cam(struct seq_file *m,
+				struct rtw89_addr_cam_entry *addr_cam)
+{
+	struct rtw89_sec_cam_entry *sec_entry;
+	int i;
+
+	seq_printf(m, "\taddr_cam_idx=%u\n", addr_cam->addr_cam_idx);
+	seq_printf(m, "\t-> bssid_cam_idx=%u\n", addr_cam->bssid_cam_idx);
+	seq_printf(m, "\tsec_cam_bitmap=%*ph\n", (int)sizeof(addr_cam->sec_cam_map),
+		   addr_cam->sec_cam_map);
+	for (i = 0; i < RTW89_SEC_CAM_IN_ADDR_CAM; i++) {
+		sec_entry = addr_cam->sec_entries[i];
+		if (!sec_entry)
+			continue;
+		seq_printf(m, "\tsec[%d]: sec_cam_idx %u", i, sec_entry->sec_cam_idx);
+		if (sec_entry->ext_key)
+			seq_printf(m, ", %u", sec_entry->sec_cam_idx + 1);
+		seq_puts(m, "\n");
+	}
+}
+
+static
+void rtw89_vif_ids_get_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
+{
+	struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
+	struct seq_file *m = (struct seq_file *)data;
+	struct rtw89_bssid_cam_entry *bssid_cam = &rtwvif->bssid_cam;
+
+	seq_printf(m, "VIF [%d] %pM\n", rtwvif->mac_id, rtwvif->mac_addr);
+	seq_printf(m, "\tbssid_cam_idx=%u\n", bssid_cam->bssid_cam_idx);
+	rtw89_dump_addr_cam(m, &rtwvif->addr_cam);
+}
+
+static void rtw89_sta_ids_get_iter(void *data, struct ieee80211_sta *sta)
+{
+	struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv;
+	struct seq_file *m = (struct seq_file *)data;
+
+	seq_printf(m, "STA [%d] %pM\n", rtwsta->mac_id, sta->addr);
+	rtw89_dump_addr_cam(m, &rtwsta->addr_cam);
+}
+
+static int rtw89_debug_priv_stations_get(struct seq_file *m, void *v)
+{
+	struct rtw89_debugfs_priv *debugfs_priv = m->private;
+	struct rtw89_dev *rtwdev = debugfs_priv->rtwdev;
+	struct rtw89_cam_info *cam_info = &rtwdev->cam_info;
+
+	seq_puts(m, "map:\n");
+	seq_printf(m, "\tmac_id:    %*ph\n", (int)sizeof(rtwdev->mac_id_map),
+		   rtwdev->mac_id_map);
+	seq_printf(m, "\taddr_cam:  %*ph\n", (int)sizeof(cam_info->addr_cam_map),
+		   cam_info->addr_cam_map);
+	seq_printf(m, "\tbssid_cam: %*ph\n", (int)sizeof(cam_info->bssid_cam_map),
+		   cam_info->bssid_cam_map);
+	seq_printf(m, "\tsec_cam:   %*ph\n", (int)sizeof(cam_info->sec_cam_map),
+		   cam_info->sec_cam_map);
+
+	ieee80211_iterate_active_interfaces_atomic(rtwdev->hw,
+		IEEE80211_IFACE_ITER_NORMAL, rtw89_vif_ids_get_iter, m);
+
+	ieee80211_iterate_stations_atomic(rtwdev->hw, rtw89_sta_ids_get_iter, m);
+
+	return 0;
+}
+
 static struct rtw89_debugfs_priv rtw89_debug_priv_read_reg = {
 	.cb_read = rtw89_debug_priv_read_reg_get,
 	.cb_write = rtw89_debug_priv_read_reg_select,
@@ -2438,6 +2504,10 @@ static struct rtw89_debugfs_priv rtw89_debug_priv_phy_info = {
 	.cb_read = rtw89_debug_priv_phy_info_get,
 };
 
+static struct rtw89_debugfs_priv rtw89_debug_priv_stations = {
+	.cb_read = rtw89_debug_priv_stations_get,
+};
+
 #define rtw89_debugfs_add(name, mode, fopname, parent)				\
 	do {									\
 		rtw89_debug_priv_ ##name.rtwdev = rtwdev;			\
@@ -2476,6 +2546,7 @@ void rtw89_debugfs_init(struct rtw89_dev *rtwdev)
 	rtw89_debugfs_add_w(btc_manual);
 	rtw89_debugfs_add_w(fw_log_manual);
 	rtw89_debugfs_add_r(phy_info);
+	rtw89_debugfs_add_r(stations);
 }
 #endif
 
Signature · 1 line
2.25.1
author maintainer
#8 lore raw

PATCH v2 7/7 rtw89: declare AP mode support

In reply to Ping-Ke Shih

Things are ready for AP mode, so declare this driver can support it.

---
 drivers/net/wireless/realtek/rtw89/core.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/net/wireless/realtek/rtw89/core.c +2 -1
index 413bb391c21e3..a9544b006f0b4 100644
@@ -2696,7 +2696,8 @@ static int rtw89_core_register_hw(struct rtw89_dev *rtwdev)
 	ieee80211_hw_set(hw, SUPPORTS_PS);
 	ieee80211_hw_set(hw, SUPPORTS_DYNAMIC_PS);
 
-	hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
+	hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
+				     BIT(NL80211_IFTYPE_AP);
 	hw->wiphy->available_antennas_tx = BIT(rtwdev->chip->rf_path_num) - 1;
 	hw->wiphy->available_antennas_rx = BIT(rtwdev->chip->rf_path_num) - 1;
 
Signature · 1 line
2.25.1