Skip to contentSkip to conversation

rtw89: support AP mode

PATCH Superseded Ping-Ke Shih 2 participants 26 messages Jan 7, 2022 – Feb 3, 2022 Realtek wireless driver (rtw89)

v1 of 2 Superseded Latest is v2 →

lore
Share & tools
lore

Ping-Ke Shih

author maintainer
#0 lore raw

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.

Ping-Ke Shih (19):
rtw89: configure rx_filter according to FIF_PROBE_REQ
rtw89: use hardware SSN to TX management frame
rtw89: download beacon content to firmware
rtw89: add C2H handle of BCN_CNT
rtw89: implement mac80211_ops::set_tim to indicate STA to receive
packets
rtw89: allocate mac_id for each station in AP mode
rtw89: extend firmware commands on states of sta_assoc and
sta_disconnect
rtw89: rename vif_maintain to role_maintain
rtw89: configure mac port HIQ registers
rtw89: send broadcast/multicast packets via HIQ if STAs are in sleep
mode
rtw89: set mac_id and port ID to TXWD
rtw89: separate {init,deinit}_addr_cam functions
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      |  40 +++---
 drivers/net/wireless/realtek/rtw89/cam.h      |   5 +
 drivers/net/wireless/realtek/rtw89/core.c     | 107 ++++++++++++++--
 drivers/net/wireless/realtek/rtw89/core.h     |  83 ++++++++-----
 drivers/net/wireless/realtek/rtw89/debug.c    |  71 +++++++++++
 drivers/net/wireless/realtek/rtw89/fw.c       | 110 ++++++++++++++---
 drivers/net/wireless/realtek/rtw89/fw.h       | 115 +++++++++++++++++-
 drivers/net/wireless/realtek/rtw89/mac.c      |  50 +++++++-
 drivers/net/wireless/realtek/rtw89/mac.h      |   2 +
 drivers/net/wireless/realtek/rtw89/mac80211.c |  67 +++++++++-
 drivers/net/wireless/realtek/rtw89/reg.h      |  14 ++-
 drivers/net/wireless/realtek/rtw89/txrx.h     |   3 +
 12 files changed, 575 insertions(+), 92 deletions(-)
Signature · 1 line
2.25.1
author maintainer
#1 lore raw

PATCH 1/19 rtw89: configure rx_filter according to FIF_PROBE_REQ

With this patch, we can receive probe_req and reply probe_resp, and STA can find us.

---
 drivers/net/wireless/realtek/rtw89/mac80211.c | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)
drivers/net/wireless/realtek/rtw89/mac80211.c +10 -1
index 90b2e2e1473fc..f068c3008b06a 100644
@@ -161,7 +161,7 @@ static void rtw89_ops_configure_filter(struct ieee80211_hw *hw,
 	rtw89_leave_ps_mode(rtwdev);
 
 	*new_flags &= FIF_ALLMULTI | FIF_OTHER_BSS | FIF_FCSFAIL |
-		      FIF_BCN_PRBRESP_PROMISC;
+		      FIF_BCN_PRBRESP_PROMISC | FIF_PROBE_REQ;
 
 	if (changed_flags & FIF_ALLMULTI) {
 		if (*new_flags & FIF_ALLMULTI)
@@ -192,6 +192,15 @@ static void rtw89_ops_configure_filter(struct ieee80211_hw *hw,
 			rtwdev->hal.rx_fltr |= B_AX_A_A1_MATCH;
 		}
 	}
+	if (changed_flags & FIF_PROBE_REQ) {
+		if (*new_flags & FIF_PROBE_REQ) {
+			rtwdev->hal.rx_fltr &= ~B_AX_A_BC_CAM_MATCH;
+			rtwdev->hal.rx_fltr &= ~B_AX_A_UC_CAM_MATCH;
+		} else {
+			rtwdev->hal.rx_fltr |= B_AX_A_BC_CAM_MATCH;
+			rtwdev->hal.rx_fltr |= B_AX_A_UC_CAM_MATCH;
+		}
+	}
 
 	rtw89_write32_mask(rtwdev,
 			   rtw89_mac_reg_by_idx(R_AX_RX_FLTR_OPT, RTW89_MAC_0),
Signature · 1 line
2.25.1
#2 lore raw

Re: [PATCH 01/19] rtw89: configure rx_filter according to FIF_PROBE_REQ

Quoted 4 lines · Ping-Ke Shih

With this patch, we can receive probe_req and reply probe_resp, and STA can find us.

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

6629dc5697cc rtw89: configure rx_filter according to FIF_PROBE_REQ 91644020dbd9 rtw89: use hardware SSN to TX management frame
f7e76d13bb2b rtw89: download beacon content to firmware
fccca9345b25 rtw89: add C2H handle of BCN_CNT
d62816b4a44e rtw89: implement mac80211_ops::set_tim to indicate STA to receive packets c7df64c194f6 rtw89: allocate mac_id for each station in AP mode 742c470b5773 rtw89: extend firmware commands on states of sta_assoc and sta_disconnect 8b252070d790 rtw89: rename vif_maintain to role_maintain
283c3d886fdf rtw89: configure mac port HIQ registers
11d261f24be6 rtw89: send broadcast/multicast packets via HIQ if STAs are in sleep mode 9eecaec238c8 rtw89: set mac_id and port ID to TXWD
14f0999d49e7 rtw89: separate {init,deinit}_addr_cam functions

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 2/19 rtw89: use hardware SSN to TX management frame

In reply to Ping-Ke Shih

Since firmware transmits beacon by hardware SSN, driver does it with the same setting, then packets in the air have continual sequence number.

---
 drivers/net/wireless/realtek/rtw89/core.c | 6 +++++-
 drivers/net/wireless/realtek/rtw89/core.h | 4 ++++
 drivers/net/wireless/realtek/rtw89/txrx.h | 2 ++
 3 files changed, 11 insertions(+), 1 deletion(-)
drivers/net/wireless/realtek/rtw89/core.c +5 -1
index 3d1c4c3b4dcb1..7c5e9bc309706 100644
@@ -383,6 +383,8 @@ rtw89_core_tx_update_mgmt_info(struct rtw89_dev *rtwdev,
 
 	desc_info->qsel = RTW89_TX_QSEL_B0_MGMT;
 	desc_info->ch_dma = ch_dma;
+	desc_info->hw_ssn_sel = RTW89_MGMT_HW_SSN_SEL;
+	desc_info->hw_seq_mode = RTW89_MGMT_HW_SEQ_MODE;
 
 	/* fixed data rate for mgmt frames */
 	desc_info->en_wd_info = true;
@@ -708,7 +710,9 @@ static __le32 rtw89_build_txwd_body0(struct rtw89_tx_desc_info *desc_info)
 		    FIELD_PREP(RTW89_TXWD_BODY0_CHANNEL_DMA, desc_info->ch_dma) |
 		    FIELD_PREP(RTW89_TXWD_BODY0_HDR_LLC_LEN, desc_info->hdr_llc_len) |
 		    FIELD_PREP(RTW89_TXWD_BODY0_WD_PAGE, desc_info->wd_page) |
-		    FIELD_PREP(RTW89_TXWD_BODY0_FW_DL, desc_info->fw_dl);
+		    FIELD_PREP(RTW89_TXWD_BODY0_FW_DL, desc_info->fw_dl) |
+		    FIELD_PREP(RTW89_TXWD_BODY0_HW_SSN_SEL, desc_info->hw_ssn_sel) |
+		    FIELD_PREP(RTW89_TXWD_BODY0_HW_SSN_MODE, desc_info->hw_seq_mode);
 
 	return cpu_to_le32(dword);
 }
drivers/net/wireless/realtek/rtw89/core.h +4 -0
index afadfc5349d35..defa0ceebc20e 100644
@@ -691,6 +691,10 @@ struct rtw89_tx_desc_info {
 	bool fw_dl;
 	u16 seq;
 	bool a_ctrl_bsr;
+	u8 hw_ssn_sel;
+#define RTW89_MGMT_HW_SSN_SEL	1
+	u8 hw_seq_mode;
+#define RTW89_MGMT_HW_SEQ_MODE	1
 };
 
 struct rtw89_core_tx_request {
drivers/net/wireless/realtek/rtw89/txrx.h +2 -0
index 75b11249f3065..fb92973e96c66 100644
@@ -31,6 +31,8 @@
 #define RTW89_TXWD_BODY0_HDR_LLC_LEN GENMASK(15, 11)
 #define RTW89_TXWD_BODY0_WD_PAGE BIT(7)
 #define RTW89_TXWD_BODY0_HW_AMSDU BIT(5)
+#define RTW89_TXWD_BODY0_HW_SSN_SEL GENMASK(3, 2)
+#define RTW89_TXWD_BODY0_HW_SSN_MODE GENMASK(1, 0)
 
 /* TX WD BODY DWORD 1 */
 #define RTW89_TXWD_BODY1_PAYLOAD_ID GENMASK(31, 16)
Signature · 1 line
2.25.1
author maintainer
#4 lore raw

PATCH 3/19 rtw89: download beacon content to firmware

In reply to Ping-Ke Shih

Firmware sends out beacon content generated by mac80211, and then stations can receive beacon and work with this AP properly. Also, we download beacon content again if TIM is changed.

---
 drivers/net/wireless/realtek/rtw89/fw.c       |  53 +++++++++
 drivers/net/wireless/realtek/rtw89/fw.h       | 103 ++++++++++++++++++
 drivers/net/wireless/realtek/rtw89/mac80211.c |   3 +
 3 files changed, 159 insertions(+)
drivers/net/wireless/realtek/rtw89/fw.c +53 -0
index 79bc3e20ab94b..441a8ef838570 100644
@@ -928,6 +928,59 @@ int rtw89_fw_h2c_txtime_cmac_tbl(struct rtw89_dev *rtwdev,
 	return -EBUSY;
 }
 
+#define H2C_BCN_BASE_LEN 12
+int rtw89_fw_h2c_update_beacon(struct rtw89_dev *rtwdev,
+			       struct rtw89_vif *rtwvif)
+{
+	struct rtw89_hal *hal = &rtwdev->hal;
+	struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif);
+	struct sk_buff *skb;
+	struct sk_buff *skb_beacon;
+	u16 tim_offset;
+	int bcn_total_len;
+
+	skb_beacon = ieee80211_beacon_get_tim(rtwdev->hw, vif, &tim_offset, NULL);
+	if (!skb_beacon) {
+		rtw89_err(rtwdev, "failed to get beacon skb\n");
+		return -ENOMEM;
+	}
+
+	bcn_total_len = H2C_BCN_BASE_LEN + skb_beacon->len;
+	skb = rtw89_fw_h2c_alloc_skb_with_hdr(bcn_total_len);
+	if (!skb) {
+		rtw89_err(rtwdev, "failed to alloc skb for fw dl\n");
+		dev_kfree_skb_any(skb_beacon);
+		return -ENOMEM;
+	}
+	skb_put(skb, H2C_BCN_BASE_LEN);
+
+	SET_BCN_UPD_PORT(skb->data, rtwvif->port);
+	SET_BCN_UPD_MBSSID(skb->data, 0);
+	SET_BCN_UPD_BAND(skb->data, rtwvif->mac_idx);
+	SET_BCN_UPD_GRP_IE_OFST(skb->data, tim_offset);
+	SET_BCN_UPD_MACID(skb->data, rtwvif->mac_id);
+	SET_BCN_UPD_SSN_SEL(skb->data, RTW89_MGMT_HW_SSN_SEL);
+	SET_BCN_UPD_SSN_MODE(skb->data, RTW89_MGMT_HW_SEQ_MODE);
+	SET_BCN_UPD_RATE(skb->data, hal->current_band_type == RTW89_BAND_2G ?
+				    RTW89_HW_RATE_CCK1 : RTW89_HW_RATE_OFDM6);
+
+	skb_put_data(skb, skb_beacon->data, skb_beacon->len);
+	dev_kfree_skb_any(skb_beacon);
+
+	rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
+			      H2C_CAT_MAC, H2C_CL_MAC_FR_EXCHG,
+			      H2C_FUNC_MAC_BCN_UPD, 0, 1,
+			      bcn_total_len);
+
+	if (rtw89_h2c_tx(rtwdev, skb, false)) {
+		rtw89_err(rtwdev, "failed to send h2c\n");
+		dev_kfree_skb_any(skb);
+		return -EBUSY;
+	}
+
+	return 0;
+}
+
 #define H2C_VIF_MAINTAIN_LEN 4
 int rtw89_fw_h2c_vif_maintain(struct rtw89_dev *rtwdev,
 			      struct rtw89_vif *rtwvif,
drivers/net/wireless/realtek/rtw89/fw.h +103 -0

121 lines not on this page · raw message

drivers/net/wireless/realtek/rtw89/mac80211.c +3 -0
index f068c3008b06a..682680e18ff46 100644
@@ -349,6 +349,9 @@ static void rtw89_ops_bss_info_changed(struct ieee80211_hw *hw,
 		rtw89_fw_h2c_cam(rtwdev, rtwvif, NULL, NULL);
 	}
 
+	if (changed & BSS_CHANGED_BEACON)
+		rtw89_fw_h2c_update_beacon(rtwdev, rtwvif);
+
 	if (changed & BSS_CHANGED_ERP_SLOT)
 		rtw89_conf_tx(rtwdev, rtwvif);
 
Signature · 1 line
2.25.1
author maintainer
#5 lore raw

PATCH 4/19 rtw89: add C2H handle of BCN_CNT

In reply to Ping-Ke Shih

This C2H notify driver the beacon count we send out. We don't handle the content for now, so add a dummy handler to avoid messages, like
rtw89_pci 0000:03:00.0: c2h class 0 func 3 not support
C2H: 00000000: 01 03 01 3f 0f 00 00 00 80 0a 00 00 00 00 a0 rtw89_pci 0000:03:00.0: c2h class 0 func 3 not support
C2H: 00000000: 01 03 01 40 0f 00 00 00 00 03 20 00 00 00 a5

---
 drivers/net/wireless/realtek/rtw89/mac.c | 6 ++++++
 drivers/net/wireless/realtek/rtw89/mac.h | 1 +
 2 files changed, 7 insertions(+)
drivers/net/wireless/realtek/rtw89/mac.c +6 -0
index b98c47e9ecfe3..59b6ef91afb0a 100644
@@ -3114,6 +3114,11 @@ rtw89_mac_c2h_log(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 len)
 		   RTW89_GET_C2H_LOG_SRT_PRT(c2h->data));
 }
 
+static void
+rtw89_mac_c2h_bcn_cnt(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 len)
+{
+}
+
 static
 void (* const rtw89_mac_c2h_ofld_handler[])(struct rtw89_dev *rtwdev,
 					    struct sk_buff *c2h, u32 len) = {
@@ -3130,6 +3135,7 @@ void (* const rtw89_mac_c2h_info_handler[])(struct rtw89_dev *rtwdev,
 	[RTW89_MAC_C2H_FUNC_REC_ACK] = rtw89_mac_c2h_rec_ack,
 	[RTW89_MAC_C2H_FUNC_DONE_ACK] = rtw89_mac_c2h_done_ack,
 	[RTW89_MAC_C2H_FUNC_C2H_LOG] = rtw89_mac_c2h_log,
+	[RTW89_MAC_C2H_FUNC_BCN_CNT] = rtw89_mac_c2h_bcn_cnt,
 };
 
 void rtw89_mac_c2h_handle(struct rtw89_dev *rtwdev, struct sk_buff *skb,
drivers/net/wireless/realtek/rtw89/mac.h +1 -0
index b7d13edf7dd19..65e4ebe05f6ad 100644
@@ -308,6 +308,7 @@ enum rtw89_mac_c2h_info_func {
 	RTW89_MAC_C2H_FUNC_REC_ACK,
 	RTW89_MAC_C2H_FUNC_DONE_ACK,
 	RTW89_MAC_C2H_FUNC_C2H_LOG,
+	RTW89_MAC_C2H_FUNC_BCN_CNT,
 	RTW89_MAC_C2H_FUNC_INFO_MAX,
 };
 
Signature · 1 line
2.25.1
author maintainer
#6 lore raw

PATCH 5/19 rtw89: implement mac80211_ops::set_tim to indicate STA to receive packets

In reply to Ping-Ke Shih

Update beacon content if TIM bitmap maintained by mac80211 is changed. Since .set_tim must be atomic but driver uses mutex lock, we add a work. Otherwise, kernel says "sched: RT throttling activated" and lock down.

---
 drivers/net/wireless/realtek/rtw89/core.c     | 15 +++++++++++++++
 drivers/net/wireless/realtek/rtw89/core.h     |  3 +++
 drivers/net/wireless/realtek/rtw89/mac80211.c | 17 +++++++++++++++++
 3 files changed, 35 insertions(+)
drivers/net/wireless/realtek/rtw89/core.c +15 -0
index 7c5e9bc309706..7fee45d8b82a1 100644
@@ -2238,6 +2238,21 @@ static void rtw89_core_ppdu_sts_init(struct rtw89_dev *rtwdev)
 		rtwdev->ppdu_sts.curr_rx_ppdu_cnt[i] = U8_MAX;
 }
 
+void rtw89_core_update_beacon_work(struct work_struct *work)
+{
+	struct rtw89_dev *rtwdev;
+	struct rtw89_vif *rtwvif = container_of(work, struct rtw89_vif,
+						update_beacon_work);
+
+	if (rtwvif->net_type != RTW89_NET_TYPE_AP_MODE)
+		return;
+
+	rtwdev = rtwvif->rtwdev;
+	mutex_lock(&rtwdev->mutex);
+	rtw89_fw_h2c_update_beacon(rtwdev, rtwvif);
+	mutex_unlock(&rtwdev->mutex);
+}
+
 int rtw89_core_start(struct rtw89_dev *rtwdev)
 {
 	int ret;
drivers/net/wireless/realtek/rtw89/core.h +3 -0
index defa0ceebc20e..542afe2133b0f 100644
@@ -1928,6 +1928,7 @@ struct rtw89_phy_rate_pattern {
 
 struct rtw89_vif {
 	struct list_head list;
+	struct rtw89_dev *rtwdev;
 	u8 mac_id;
 	u8 port;
 	u8 mac_addr[ETH_ALEN];
@@ -1949,6 +1950,7 @@ struct rtw89_vif {
 	bool wowlan_magic;
 	bool is_hesta;
 	bool last_a_ctrl;
+	struct work_struct update_beacon_work;
 	struct rtw89_addr_cam_entry addr_cam;
 	struct rtw89_bssid_cam_entry bssid_cam;
 	struct ieee80211_tx_queue_params tx_params[IEEE80211_NUM_ACS];
@@ -3396,5 +3398,6 @@ void rtw89_traffic_stats_init(struct rtw89_dev *rtwdev,
 			      struct rtw89_traffic_stats *stats);
 int rtw89_core_start(struct rtw89_dev *rtwdev);
 void rtw89_core_stop(struct rtw89_dev *rtwdev);
+void rtw89_core_update_beacon_work(struct work_struct *work);
 
 #endif
drivers/net/wireless/realtek/rtw89/mac80211.c +17 -0
index 682680e18ff46..26abbe7aa17d8 100644
@@ -102,7 +102,9 @@ static int rtw89_ops_add_interface(struct ieee80211_hw *hw,
 	int ret = 0;
 
 	mutex_lock(&rtwdev->mutex);
+	rtwvif->rtwdev = rtwdev;
 	list_add_tail(&rtwvif->list, &rtwdev->rtwvifs_list);
+	INIT_WORK(&rtwvif->update_beacon_work, rtw89_core_update_beacon_work);
 	rtw89_leave_ps_mode(rtwdev);
 
 	rtw89_traffic_stats_init(rtwdev, &rtwvif->stats);
@@ -141,6 +143,8 @@ static void rtw89_ops_remove_interface(struct ieee80211_hw *hw,
 	struct rtw89_dev *rtwdev = hw->priv;
 	struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
 
+	cancel_work_sync(&rtwvif->update_beacon_work);
+
 	mutex_lock(&rtwdev->mutex);
 	rtw89_leave_ps_mode(rtwdev);
 	rtw89_btc_ntfy_role_info(rtwdev, rtwvif, NULL, BTC_ROLE_STOP);
@@ -364,6 +368,18 @@ static void rtw89_ops_bss_info_changed(struct ieee80211_hw *hw,
 	mutex_unlock(&rtwdev->mutex);
 }
 
+static int rtw89_ops_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta,
+			     bool set)
+{
+	struct rtw89_dev *rtwdev = hw->priv;
+	struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv;
+	struct rtw89_vif *rtwvif = rtwsta->rtwvif;
+
+	ieee80211_queue_work(rtwdev->hw, &rtwvif->update_beacon_work);
+
+	return 0;
+}
+
 static int rtw89_ops_conf_tx(struct ieee80211_hw *hw,
 			     struct ieee80211_vif *vif, u16 ac,
 			     const struct ieee80211_tx_queue_params *params)
@@ -680,6 +696,7 @@ 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,
+	.set_tim		= rtw89_ops_set_tim,
 	.conf_tx		= rtw89_ops_conf_tx,
 	.sta_state		= rtw89_ops_sta_state,
 	.set_key		= rtw89_ops_set_key,
Signature · 1 line
2.25.1
author maintainer
#7 lore raw

PATCH 6/19 rtw89: allocate mac_id for each station in AP mode

In reply to Ping-Ke Shih

In station mode, mac_id of station is the same as rtwvif's one. In AP mode, each station uses individual mac_id.

---
 drivers/net/wireless/realtek/rtw89/core.c | 5 +++++
 1 file changed, 5 insertions(+)
drivers/net/wireless/realtek/rtw89/core.c +5 -0
index 7fee45d8b82a1..3163c63091868 100644
@@ -1885,6 +1885,9 @@ int rtw89_core_sta_add(struct rtw89_dev *rtwdev,
 		rtw89_btc_ntfy_role_info(rtwdev, rtwvif, rtwsta,
 					 BTC_ROLE_MSTS_STA_CONN_START);
 		rtw89_chip_rfk_channel(rtwdev);
+	} else if (vif->type == NL80211_IFTYPE_AP) {
+		rtwsta->mac_id = rtw89_core_acquire_bit_map(rtwdev->mac_id_map,
+							    RTW89_MAX_MAC_ID_NUM);
 	}
 
 	return 0;
@@ -1997,6 +2000,8 @@ int rtw89_core_sta_remove(struct rtw89_dev *rtwdev,
 	if (vif->type == NL80211_IFTYPE_STATION)
 		rtw89_btc_ntfy_role_info(rtwdev, rtwvif, rtwsta,
 					 BTC_ROLE_MSTS_STA_DIS_CONN);
+	else if (vif->type == NL80211_IFTYPE_AP)
+		rtw89_core_release_bit_map(rtwdev->mac_id_map, rtwsta->mac_id);
 
 	return 0;
 }
Signature · 1 line
2.25.1
author maintainer
#8 lore raw

PATCH 7/19 rtw89: extend firmware commands on states of sta_assoc and sta_disconnect

In reply to Ping-Ke Shih

The h2c_join firmware command is used to indicate a station is connected, and the assoc_cmac_tbl firmware command is used to set CMAC table corresponding to a mac_id. Both commands must work in both station and AP modes. Use the mac_id of rtw89_sta naturally and intuitively.

---
 drivers/net/wireless/realtek/rtw89/core.c |  4 +--
 drivers/net/wireless/realtek/rtw89/fw.c   | 35 +++++++++++++++++------
 drivers/net/wireless/realtek/rtw89/fw.h   |  5 ++--
 drivers/net/wireless/realtek/rtw89/mac.c  |  2 +-
 4 files changed, 32 insertions(+), 14 deletions(-)
drivers/net/wireless/realtek/rtw89/core.c +2 -2
index 3163c63091868..175d9924761c1 100644
@@ -1925,7 +1925,7 @@ int rtw89_core_sta_disconnect(struct rtw89_dev *rtwdev,
 		return ret;
 	}
 
-	ret = rtw89_fw_h2c_join_info(rtwdev, rtwvif, 1);
+	ret = rtw89_fw_h2c_join_info(rtwdev, rtwvif, rtwsta, true);
 	if (ret) {
 		rtw89_warn(rtwdev, "failed to send h2c join info\n");
 		return ret;
@@ -1957,7 +1957,7 @@ int rtw89_core_sta_assoc(struct rtw89_dev *rtwdev,
 		return ret;
 	}
 
-	ret = rtw89_fw_h2c_join_info(rtwdev, rtwvif, 0);
+	ret = rtw89_fw_h2c_join_info(rtwdev, rtwvif, rtwsta, false);
 	if (ret) {
 		rtw89_warn(rtwdev, "failed to send h2c join info\n");
 		return ret;
drivers/net/wireless/realtek/rtw89/fw.c +26 -9
index 441a8ef838570..e9f27382d2ba8 100644
@@ -733,12 +733,14 @@ int rtw89_fw_h2c_lps_parm(struct rtw89_dev *rtwdev,
 }
 
 #define H2C_CMC_TBL_LEN 68
-int rtw89_fw_h2c_default_cmac_tbl(struct rtw89_dev *rtwdev, u8 macid)
+int rtw89_fw_h2c_default_cmac_tbl(struct rtw89_dev *rtwdev,
+				  struct rtw89_vif *rtwvif)
 {
 	struct rtw89_hal *hal = &rtwdev->hal;
 	struct sk_buff *skb;
 	u8 ntx_path = hal->antenna_tx ? hal->antenna_tx : RF_B;
 	u8 map_b = hal->antenna_tx == RF_AB ? 1 : 0;
+	u8 macid = rtwvif->mac_id;
 
 	skb = rtw89_fw_h2c_alloc_skb_with_hdr(H2C_CMC_TBL_LEN);
 	if (!skb) {
@@ -760,6 +762,8 @@ int rtw89_fw_h2c_default_cmac_tbl(struct rtw89_dev *rtwdev, u8 macid)
 	SET_CMC_TBL_ANTSEL_D(skb->data, 0);
 	SET_CMC_TBL_DOPPLER_CTRL(skb->data, 0);
 	SET_CMC_TBL_TXPWR_TOLERENCE(skb->data, 0);
+	if (rtwvif->net_type == RTW89_NET_TYPE_AP_MODE)
+		SET_CMC_TBL_DATA_DCM(skb->data, 0);
 
 	rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
 			      H2C_CAT_MAC, H2C_CL_MAC_FR_EXCHG,
@@ -838,13 +842,15 @@ int rtw89_fw_h2c_assoc_cmac_tbl(struct rtw89_dev *rtwdev,
 				struct ieee80211_sta *sta)
 {
 	struct rtw89_hal *hal = &rtwdev->hal;
-	struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv;
+	struct rtw89_sta *rtwsta = sta_to_rtwsta_safe(sta);
 	struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
 	struct sk_buff *skb;
 	u8 pads[RTW89_PPE_BW_NUM];
+	u8 mac_id = rtwsta ? rtwsta->mac_id : rtwvif->mac_id;
 
 	memset(pads, 0, sizeof(pads));
-	__get_sta_he_pkt_padding(rtwdev, sta, pads);
+	if (sta)
+		__get_sta_he_pkt_padding(rtwdev, sta, pads);
 
 	skb = rtw89_fw_h2c_alloc_skb_with_hdr(H2C_CMC_TBL_LEN);
 	if (!skb) {
@@ -852,7 +858,7 @@ int rtw89_fw_h2c_assoc_cmac_tbl(struct rtw89_dev *rtwdev,
 		return -ENOMEM;
 	}
 	skb_put(skb, H2C_CMC_TBL_LEN);
-	SET_CTRL_INFO_MACID(skb->data, rtwsta->mac_id);
+	SET_CTRL_INFO_MACID(skb->data, mac_id);
 	SET_CTRL_INFO_OPERATION(skb->data, 1);
 	SET_CMC_TBL_DISRTSFB(skb->data, 1);
 	SET_CMC_TBL_DISDATAFB(skb->data, 1);
@@ -870,7 +876,10 @@ int rtw89_fw_h2c_assoc_cmac_tbl(struct rtw89_dev *rtwdev,
 	SET_CMC_TBL_NOMINAL_PKT_PADDING(skb->data, pads[RTW89_CHANNEL_WIDTH_20]);
 	SET_CMC_TBL_NOMINAL_PKT_PADDING40(skb->data, pads[RTW89_CHANNEL_WIDTH_40]);
 	SET_CMC_TBL_NOMINAL_PKT_PADDING80(skb->data, pads[RTW89_CHANNEL_WIDTH_80]);
-	SET_CMC_TBL_BSR_QUEUE_SIZE_FORMAT(skb->data, sta->he_cap.has_he);
+	if (sta)
+		SET_CMC_TBL_BSR_QUEUE_SIZE_FORMAT(skb->data, sta->he_cap.has_he);
+	if (rtwvif->net_type == RTW89_NET_TYPE_AP_MODE)
+		SET_CMC_TBL_DATA_DCM(skb->data, 0);
 
 	rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
 			      H2C_CAT_MAC, H2C_CL_MAC_FR_EXCHG,
@@ -1018,9 +1027,17 @@ int rtw89_fw_h2c_vif_maintain(struct rtw89_dev *rtwdev,
 
 #define H2C_JOIN_INFO_LEN 4
 int rtw89_fw_h2c_join_info(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
-			   u8 dis_conn)
+			   struct rtw89_sta *rtwsta, bool dis_conn)
 {
 	struct sk_buff *skb;
+	u8 mac_id = rtwsta ? rtwsta->mac_id : rtwvif->mac_id;
+	u8 self_role = rtwvif->self_role;
+	u8 net_type = rtwvif->net_type;
+
+	if (net_type == RTW89_NET_TYPE_AP_MODE && rtwsta) {
+		self_role = RTW89_SELF_ROLE_AP_CLIENT;
+		net_type = dis_conn ? RTW89_NET_TYPE_NO_LINK : net_type;
+	}
 
 	skb = rtw89_fw_h2c_alloc_skb_with_hdr(H2C_JOIN_INFO_LEN);
 	if (!skb) {
@@ -1028,7 +1045,7 @@ int rtw89_fw_h2c_join_info(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
 		return -ENOMEM;
 	}
 	skb_put(skb, H2C_JOIN_INFO_LEN);
-	SET_JOININFO_MACID(skb->data, rtwvif->mac_id);
+	SET_JOININFO_MACID(skb->data, mac_id);
 	SET_JOININFO_OP(skb->data, dis_conn);
 	SET_JOININFO_BAND(skb->data, rtwvif->mac_idx);
 	SET_JOININFO_WMM(skb->data, rtwvif->wmm);
@@ -1038,9 +1055,9 @@ int rtw89_fw_h2c_join_info(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
 	SET_JOININFO_TF_MAC_PAD(skb->data, 0);
 	SET_JOININFO_DL_T_PE(skb->data, 0);
 	SET_JOININFO_PORT_ID(skb->data, rtwvif->port);
-	SET_JOININFO_NET_TYPE(skb->data, rtwvif->net_type);
+	SET_JOININFO_NET_TYPE(skb->data, net_type);
 	SET_JOININFO_WIFI_ROLE(skb->data, rtwvif->wifi_role);
-	SET_JOININFO_SELF_ROLE(skb->data, rtwvif->self_role);
+	SET_JOININFO_SELF_ROLE(skb->data, self_role);
 
 	rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
 			      H2C_CAT_MAC, H2C_CL_MAC_MEDIA_RPT,
drivers/net/wireless/realtek/rtw89/fw.h +3 -2
index c6e83e4e49fa3..55f11e7886d52 100644
@@ -1871,7 +1871,8 @@ int rtw89_wait_firmware_completion(struct rtw89_dev *rtwdev);
 void rtw89_h2c_pkt_set_hdr(struct rtw89_dev *rtwdev, struct sk_buff *skb,
 			   u8 type, u8 cat, u8 class, u8 func,
 			   bool rack, bool dack, u32 len);
-int rtw89_fw_h2c_default_cmac_tbl(struct rtw89_dev *rtwdev, u8 macid);
+int rtw89_fw_h2c_default_cmac_tbl(struct rtw89_dev *rtwdev,
+				  struct rtw89_vif *rtwvif);
 int rtw89_fw_h2c_assoc_cmac_tbl(struct rtw89_dev *rtwdev,
 				struct ieee80211_vif *vif,
 				struct ieee80211_sta *sta);
@@ -1887,7 +1888,7 @@ int rtw89_fw_h2c_vif_maintain(struct rtw89_dev *rtwdev,
 			      struct rtw89_vif *rtwvif,
 			      enum rtw89_upd_mode upd_mode);
 int rtw89_fw_h2c_join_info(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
-			   u8 dis_conn);
+			   struct rtw89_sta *rtwsta, bool dis_conn);
 int rtw89_fw_h2c_macid_pause(struct rtw89_dev *rtwdev, u8 sh, u8 grp,
 			     bool pause);
 int rtw89_fw_h2c_set_edca(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
drivers/net/wireless/realtek/rtw89/mac.c +1 -1
index 59b6ef91afb0a..58f47b46c2f95 100644
@@ -2994,7 +2994,7 @@ int rtw89_mac_vif_init(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
 	if (ret)
 		return ret;
 
-	ret = rtw89_fw_h2c_default_cmac_tbl(rtwdev, rtwvif->mac_id);
+	ret = rtw89_fw_h2c_default_cmac_tbl(rtwdev, rtwvif);
 	if (ret)
 		return ret;
 
Signature · 1 line
2.25.1
author maintainer
#9 lore raw

PATCH 8/19 rtw89: rename vif_maintain to role_maintain

In reply to Ping-Ke Shih

The H2C_FUNC_MAC_FWROLE_MAINTAIN also maintains the roles of all connected stations; not just the role of VIF. So, I correct the name, but don't change the logic at all.

---
 drivers/net/wireless/realtek/rtw89/core.h | 10 +++++-----
 drivers/net/wireless/realtek/rtw89/fw.c   | 14 +++++++-------
 drivers/net/wireless/realtek/rtw89/fw.h   |  6 +++---
 drivers/net/wireless/realtek/rtw89/mac.c  |  4 ++--
 4 files changed, 17 insertions(+), 17 deletions(-)
drivers/net/wireless/realtek/rtw89/core.h +5 -5
index 542afe2133b0f..ae8943d4fb43d 100644
@@ -140,11 +140,11 @@ enum rtw89_wifi_role {
 };
 
 enum rtw89_upd_mode {
-	RTW89_VIF_CREATE,
-	RTW89_VIF_REMOVE,
-	RTW89_VIF_TYPE_CHANGE,
-	RTW89_VIF_INFO_CHANGE,
-	RTW89_VIF_CON_DISCONN
+	RTW89_ROLE_CREATE,
+	RTW89_ROLE_REMOVE,
+	RTW89_ROLE_TYPE_CHANGE,
+	RTW89_ROLE_INFO_CHANGE,
+	RTW89_ROLE_CON_DISCONN
 };
 
 enum rtw89_self_role {
drivers/net/wireless/realtek/rtw89/fw.c +7 -7
index e9f27382d2ba8..5209813275676 100644
@@ -990,19 +990,19 @@ int rtw89_fw_h2c_update_beacon(struct rtw89_dev *rtwdev,
 	return 0;
 }
 
-#define H2C_VIF_MAINTAIN_LEN 4
-int rtw89_fw_h2c_vif_maintain(struct rtw89_dev *rtwdev,
-			      struct rtw89_vif *rtwvif,
-			      enum rtw89_upd_mode upd_mode)
+#define H2C_ROLE_MAINTAIN_LEN 4
+int rtw89_fw_h2c_role_maintain(struct rtw89_dev *rtwdev,
+			       struct rtw89_vif *rtwvif,
+			       enum rtw89_upd_mode upd_mode)
 {
 	struct sk_buff *skb;
 
-	skb = rtw89_fw_h2c_alloc_skb_with_hdr(H2C_VIF_MAINTAIN_LEN);
+	skb = rtw89_fw_h2c_alloc_skb_with_hdr(H2C_ROLE_MAINTAIN_LEN);
 	if (!skb) {
 		rtw89_err(rtwdev, "failed to alloc skb for h2c join\n");
 		return -ENOMEM;
 	}
-	skb_put(skb, H2C_VIF_MAINTAIN_LEN);
+	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_UPD_MODE(skb->data, upd_mode);
@@ -1011,7 +1011,7 @@ int rtw89_fw_h2c_vif_maintain(struct rtw89_dev *rtwdev,
 	rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
 			      H2C_CAT_MAC, H2C_CL_MAC_MEDIA_RPT,
 			      H2C_FUNC_MAC_FWROLE_MAINTAIN, 0, 1,
-			      H2C_VIF_MAINTAIN_LEN);
+			      H2C_ROLE_MAINTAIN_LEN);
 
 	if (rtw89_h2c_tx(rtwdev, skb, false)) {
 		rtw89_err(rtwdev, "failed to send h2c\n");
drivers/net/wireless/realtek/rtw89/fw.h +3 -3
index 55f11e7886d52..b30cf0a2cc1e0 100644
@@ -1884,9 +1884,9 @@ int rtw89_fw_h2c_cam(struct rtw89_dev *rtwdev, struct rtw89_vif *vif,
 		     struct rtw89_sta *rtwsta, const u8 *scan_mac_addr);
 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_vif_maintain(struct rtw89_dev *rtwdev,
-			      struct rtw89_vif *rtwvif,
-			      enum rtw89_upd_mode upd_mode);
+int rtw89_fw_h2c_role_maintain(struct rtw89_dev *rtwdev,
+			       struct rtw89_vif *rtwvif,
+			       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);
 int rtw89_fw_h2c_macid_pause(struct rtw89_dev *rtwdev, u8 sh, u8 grp,
drivers/net/wireless/realtek/rtw89/mac.c +2 -2
index 58f47b46c2f95..a0ff3d8a3f61b 100644
@@ -2982,7 +2982,7 @@ int rtw89_mac_vif_init(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
 	if (ret)
 		return ret;
 
-	ret = rtw89_fw_h2c_vif_maintain(rtwdev, rtwvif, RTW89_VIF_CREATE);
+	ret = rtw89_fw_h2c_role_maintain(rtwdev, rtwvif, RTW89_ROLE_CREATE);
 	if (ret)
 		return ret;
 
@@ -3005,7 +3005,7 @@ int rtw89_mac_vif_deinit(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
 {
 	int ret;
 
-	ret = rtw89_fw_h2c_vif_maintain(rtwdev, rtwvif, RTW89_VIF_REMOVE);
+	ret = rtw89_fw_h2c_role_maintain(rtwdev, rtwvif, RTW89_ROLE_REMOVE);
 	if (ret)
 		return ret;
 
Signature · 1 line
2.25.1
author maintainer
#10 lore raw

PATCH 9/19 rtw89: configure mac port HIQ registers

In reply to Ping-Ke Shih

HIQ is short for high queue that is used to send broadcast/multicast packets right after TBTT in AP mode. Two registers, DTIM and window size, are configured accordingly.

---
 drivers/net/wireless/realtek/rtw89/mac.c | 34 +++++++++++++++++++++++-
 drivers/net/wireless/realtek/rtw89/reg.h | 14 +++++++++-
 2 files changed, 46 insertions(+), 2 deletions(-)
drivers/net/wireless/realtek/rtw89/mac.c +33 -1
index a0ff3d8a3f61b..58aa24e71637d 100644
@@ -2864,6 +2864,36 @@ static void rtw89_mac_port_cfg_bcn_intv(struct rtw89_dev *rtwdev,
 				bcn_int);
 }
 
+static void rtw89_mac_port_cfg_hiq_win(struct rtw89_dev *rtwdev,
+				       struct rtw89_vif *rtwvif)
+{
+	static const u32 hiq_win_addr[RTW89_PORT_NUM] = {
+		R_AX_P0MB_HGQ_WINDOW_CFG_0, R_AX_PORT_HGQ_WINDOW_CFG,
+		R_AX_PORT_HGQ_WINDOW_CFG + 1, R_AX_PORT_HGQ_WINDOW_CFG + 2,
+		R_AX_PORT_HGQ_WINDOW_CFG + 3,
+	};
+	u8 win = rtwvif->net_type == RTW89_NET_TYPE_AP_MODE ? 16 : 0;
+	u8 port = rtwvif->port;
+	u32 reg;
+
+	reg = rtw89_mac_reg_by_idx(hiq_win_addr[port], rtwvif->mac_idx);
+	rtw89_write8(rtwdev, reg, win);
+}
+
+static void rtw89_mac_port_cfg_hiq_dtim(struct rtw89_dev *rtwdev,
+					struct rtw89_vif *rtwvif)
+{
+	struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif);
+	const struct rtw89_port_reg *p = &rtw_port_base;
+	u32 addr;
+
+	addr = rtw89_mac_reg_by_idx(R_AX_MD_TSFT_STMP_CTL, rtwvif->mac_idx);
+	rtw89_write8_set(rtwdev, addr, B_AX_UPD_HGQMD | B_AX_UPD_TIMIE);
+
+	rtw89_write16_port_mask(rtwdev, rtwvif, p->dtim_ctrl, B_AX_DTIM_NUM_MASK,
+				vif->bss_conf.dtim_period);
+}
+
 static void rtw89_mac_port_cfg_bcn_setup_time(struct rtw89_dev *rtwdev,
 					      struct rtw89_vif *rtwvif)
 {
@@ -3034,13 +3064,15 @@ int rtw89_mac_port_update(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
 	rtw89_mac_port_cfg_rx_sync(rtwdev, rtwvif);
 	rtw89_mac_port_cfg_tx_sw(rtwdev, rtwvif);
 	rtw89_mac_port_cfg_bcn_intv(rtwdev, rtwvif);
+	rtw89_mac_port_cfg_hiq_win(rtwdev, rtwvif);
+	rtw89_mac_port_cfg_hiq_dtim(rtwdev, rtwvif);
+	rtw89_mac_port_cfg_hiq_drop(rtwdev, rtwvif);
 	rtw89_mac_port_cfg_bcn_setup_time(rtwdev, rtwvif);
 	rtw89_mac_port_cfg_bcn_hold_time(rtwdev, rtwvif);
 	rtw89_mac_port_cfg_bcn_mask_area(rtwdev, rtwvif);
 	rtw89_mac_port_cfg_tbtt_early(rtwdev, rtwvif);
 	rtw89_mac_port_cfg_bss_color(rtwdev, rtwvif);
 	rtw89_mac_port_cfg_mbssid(rtwdev, rtwvif);
-	rtw89_mac_port_cfg_hiq_drop(rtwdev, rtwvif);
 	rtw89_mac_port_cfg_func_en(rtwdev, rtwvif);
 	fsleep(BCN_ERLY_SET_DLY);
 	rtw89_mac_port_cfg_bcn_early(rtwdev, rtwvif);
drivers/net/wireless/realtek/rtw89/reg.h +13 -1
index e0a416d37d0e8..5e5cb0fcfa859 100644
@@ -913,7 +913,7 @@
 #define R_AX_DTIM_CTRL_P2 0xC4A6
 #define R_AX_DTIM_CTRL_P3 0xC4E6
 #define R_AX_DTIM_CTRL_P4 0xC526
-#define B_AX_DTIM_NUM_MASK GENMASK(15, 0)
+#define B_AX_DTIM_NUM_MASK GENMASK(15, 8)
 #define B_AX_DTIM_CURRCNT_MASK GENMASK(7, 0)
 
 #define R_AX_TBTT_SHIFT_P0 0xC428
@@ -964,6 +964,11 @@
 #define B_AX_P0MB2_EN BIT(2)
 #define B_AX_P0MB1_EN BIT(1)
 
+#define R_AX_P0MB_HGQ_WINDOW_CFG_0 0xC590
+#define R_AX_P0MB_HGQ_WINDOW_CFG_0_C1 0xE590
+#define R_AX_PORT_HGQ_WINDOW_CFG 0xC5A0
+#define R_AX_PORT_HGQ_WINDOW_CFG_C1 0xE5A0
+
 #define R_AX_AMPDU_AGG_LIMIT 0xC610
 #define B_AX_AMPDU_MAX_TIME_MASK GENMASK(31, 24)
 #define B_AX_RA_TRY_RATE_AGG_LMT_MASK GENMASK(23, 16)
@@ -1080,6 +1085,13 @@
 #define B_AX_TCR_ZLD_USTIME_AFTERPHYTXON GENMASK(11, 8)
 #define B_AX_TCR_TXTIMEOUT GENMASK(7, 0)
 
+#define R_AX_MD_TSFT_STMP_CTL 0xCA08
+#define R_AX_MD_TSFT_STMP_CTL_C1 0xEA08
+#define B_AX_TSFT_OFS_MASK GENMASK(31, 16)
+#define B_AX_STMP_THSD_MASK GENMASK(15, 8)
+#define B_AX_UPD_HGQMD BIT(1)
+#define B_AX_UPD_TIMIE BIT(0)
+
 #define R_AX_PPWRBIT_SETTING 0xCA0C
 #define R_AX_PPWRBIT_SETTING_C1 0xEA0C
 
Signature · 1 line
2.25.1
author maintainer
#11 lore raw

PATCH 10/19 rtw89: send broadcast/multicast packets via HIQ if STAs are in sleep mode

In reply to Ping-Ke Shih

If a packet we are going to send is broadcast/multicast and certain STAs are in sleep mode, a flag IEEE80211_TX_CTL_SEND_AFTER_DTIM is added to txinfo. Then, this kind of packets must be sent via HIQ instead of regular AC queues, because they should be sent right after beacon.

---
 drivers/net/wireless/realtek/rtw89/core.c | 8 +++++---
 drivers/net/wireless/realtek/rtw89/core.h | 1 +
 2 files changed, 6 insertions(+), 3 deletions(-)
drivers/net/wireless/realtek/rtw89/core.c +5 -3
index 175d9924761c1..50bbc93196085 100644
@@ -378,10 +378,10 @@ rtw89_core_tx_update_mgmt_info(struct rtw89_dev *rtwdev,
 	struct rtw89_tx_desc_info *desc_info = &tx_req->desc_info;
 	u8 qsel, ch_dma;
 
-	qsel = RTW89_TX_QSEL_B0_MGMT;
+	qsel = desc_info->hiq ? RTW89_TX_QSEL_B0_HI : RTW89_TX_QSEL_B0_MGMT;
 	ch_dma = rtw89_core_get_ch_dma(rtwdev, qsel);
 
-	desc_info->qsel = RTW89_TX_QSEL_B0_MGMT;
+	desc_info->qsel = qsel;
 	desc_info->ch_dma = ch_dma;
 	desc_info->hw_ssn_sel = RTW89_MGMT_HW_SSN_SEL;
 	desc_info->hw_seq_mode = RTW89_MGMT_HW_SEQ_MODE;
@@ -535,7 +535,7 @@ rtw89_core_tx_update_data_info(struct rtw89_dev *rtwdev,
 
 	tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK;
 	tid_indicate = rtw89_core_get_tid_indicate(rtwdev, tid);
-	qsel = rtw89_core_get_qsel(rtwdev, tid);
+	qsel = desc_info->hiq ? RTW89_TX_QSEL_B0_HI : rtw89_core_get_qsel(rtwdev, tid);
 	ch_dma = rtw89_core_get_ch_dma(rtwdev, qsel);
 
 	desc_info->ch_dma = ch_dma;
@@ -601,6 +601,7 @@ rtw89_core_tx_update_desc_info(struct rtw89_dev *rtwdev,
 {
 	struct rtw89_tx_desc_info *desc_info = &tx_req->desc_info;
 	struct sk_buff *skb = tx_req->skb;
+	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
 	struct ieee80211_hdr *hdr = (void *)skb->data;
 	enum rtw89_core_tx_type tx_type;
 	enum btc_pkt_type pkt_type;
@@ -619,6 +620,7 @@ rtw89_core_tx_update_desc_info(struct rtw89_dev *rtwdev,
 	desc_info->pkt_size = skb->len;
 	desc_info->is_bmc = is_bmc;
 	desc_info->wd_page = true;
+	desc_info->hiq = info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM;
 
 	switch (tx_req->tx_type) {
 	case RTW89_CORE_TX_TYPE_MGMT:
drivers/net/wireless/realtek/rtw89/core.h +1 -0
index ae8943d4fb43d..cf795d2f14776 100644
@@ -695,6 +695,7 @@ struct rtw89_tx_desc_info {
 #define RTW89_MGMT_HW_SSN_SEL	1
 	u8 hw_seq_mode;
 #define RTW89_MGMT_HW_SEQ_MODE	1
+	bool hiq;
 };
 
 struct rtw89_core_tx_request {
Signature · 1 line
2.25.1
author maintainer
#12 lore raw

PATCH 11/19 rtw89: set mac_id and port ID to TXWD

In reply to Ping-Ke Shih

One mac_id is corresponding to one connected station, and port ID is a ID of virtual interfaces. With proper mac_id and port ID, firmware and hardware can handle a packet with correct context.

---
 drivers/net/wireless/realtek/rtw89/core.c | 26 +++++++++++++++++++++--
 drivers/net/wireless/realtek/rtw89/core.h |  2 ++
 drivers/net/wireless/realtek/rtw89/txrx.h |  1 +
 3 files changed, 27 insertions(+), 2 deletions(-)
drivers/net/wireless/realtek/rtw89/core.c +24 -2
index 50bbc93196085..8f8891badf0e8 100644
@@ -375,6 +375,8 @@ static void
 rtw89_core_tx_update_mgmt_info(struct rtw89_dev *rtwdev,
 			       struct rtw89_core_tx_request *tx_req)
 {
+	struct ieee80211_vif *vif = tx_req->vif;
+	struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
 	struct rtw89_tx_desc_info *desc_info = &tx_req->desc_info;
 	u8 qsel, ch_dma;
 
@@ -383,6 +385,7 @@ rtw89_core_tx_update_mgmt_info(struct rtw89_dev *rtwdev,
 
 	desc_info->qsel = qsel;
 	desc_info->ch_dma = ch_dma;
+	desc_info->port = desc_info->hiq ? rtwvif->port : 0;
 	desc_info->hw_ssn_sel = RTW89_MGMT_HW_SSN_SEL;
 	desc_info->hw_seq_mode = RTW89_MGMT_HW_SEQ_MODE;
 
@@ -520,6 +523,21 @@ rtw89_core_tx_update_he_qos_htc(struct rtw89_dev *rtwdev,
 	desc_info->bk = true;
 }
 
+static u8 rtw89_core_tx_get_mac_id(struct rtw89_dev *rtwdev,
+				   struct rtw89_core_tx_request *tx_req)
+{
+	struct ieee80211_vif *vif = tx_req->vif;
+	struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
+	struct ieee80211_sta *sta = tx_req->sta;
+	struct rtw89_sta *rtwsta;
+
+	if (!sta)
+		return rtwvif->mac_id;
+
+	rtwsta = (struct rtw89_sta *)sta->drv_priv;
+	return rtwsta->mac_id;
+}
+
 static void
 rtw89_core_tx_update_data_info(struct rtw89_dev *rtwdev,
 			       struct rtw89_core_tx_request *tx_req)
@@ -541,6 +559,8 @@ rtw89_core_tx_update_data_info(struct rtw89_dev *rtwdev,
 	desc_info->ch_dma = ch_dma;
 	desc_info->tid_indicate = tid_indicate;
 	desc_info->qsel = qsel;
+	desc_info->mac_id = rtw89_core_tx_get_mac_id(rtwdev, tx_req);
+	desc_info->port = desc_info->hiq ? rtwvif->port : 0;
 
 	/* enable wd_info for AMPDU */
 	desc_info->en_wd_info = true;
@@ -723,7 +743,8 @@ static __le32 rtw89_build_txwd_body2(struct rtw89_tx_desc_info *desc_info)
 {
 	u32 dword = FIELD_PREP(RTW89_TXWD_BODY2_TID_INDICATE, desc_info->tid_indicate) |
 		    FIELD_PREP(RTW89_TXWD_BODY2_QSEL, desc_info->qsel) |
-		    FIELD_PREP(RTW89_TXWD_BODY2_TXPKT_SIZE, desc_info->pkt_size);
+		    FIELD_PREP(RTW89_TXWD_BODY2_TXPKT_SIZE, desc_info->pkt_size) |
+		    FIELD_PREP(RTW89_TXWD_BODY2_MACID, desc_info->mac_id);
 
 	return cpu_to_le32(dword);
 }
@@ -741,7 +762,8 @@ static __le32 rtw89_build_txwd_info0(struct rtw89_tx_desc_info *desc_info)
 {
 	u32 dword = FIELD_PREP(RTW89_TXWD_INFO0_USE_RATE, desc_info->use_rate) |
 		    FIELD_PREP(RTW89_TXWD_INFO0_DATA_RATE, desc_info->data_rate) |
-		    FIELD_PREP(RTW89_TXWD_INFO0_DISDATAFB, desc_info->dis_data_fb);
+		    FIELD_PREP(RTW89_TXWD_INFO0_DISDATAFB, desc_info->dis_data_fb) |
+		    FIELD_PREP(RTW89_TXWD_INFO0_MULTIPORT_ID, desc_info->port);
 
 	return cpu_to_le32(dword);
 }
drivers/net/wireless/realtek/rtw89/core.h +2 -0
index cf795d2f14776..8cb907da6cb05 100644
@@ -670,6 +670,7 @@ struct rtw89_rxdesc_long {
 struct rtw89_tx_desc_info {
 	u16 pkt_size;
 	u8 wp_offset;
+	u8 mac_id;
 	u8 qsel;
 	u8 ch_dma;
 	u8 hdr_llc_len;
@@ -696,6 +697,7 @@ struct rtw89_tx_desc_info {
 	u8 hw_seq_mode;
 #define RTW89_MGMT_HW_SEQ_MODE	1
 	bool hiq;
+	u8 port;
 };
 
 struct rtw89_core_tx_request {
drivers/net/wireless/realtek/rtw89/txrx.h +1 -0
index fb92973e96c66..86e3d8b400d6c 100644
@@ -58,6 +58,7 @@
 #define RTW89_TXWD_INFO0_GI_LTF GENMASK(27, 25)
 #define RTW89_TXWD_INFO0_DATA_RATE GENMASK(24, 16)
 #define RTW89_TXWD_INFO0_DISDATAFB BIT(10)
+#define RTW89_TXWD_INFO0_MULTIPORT_ID GENMASK(6, 4)
 
 /* TX WD INFO DWORD 1 */
 #define RTW89_TXWD_INFO1_DATA_RTY_LOWEST_RATE GENMASK(24, 16)
Signature · 1 line
2.25.1
author maintainer
#13 lore raw

PATCH 12/19 rtw89: separate {init,deinit}_addr_cam functions

In reply to Ping-Ke Shih

Each stations connected to AP needs to set an address CAM, so don't combine address and BSSID CAM.

---
 drivers/net/wireless/realtek/rtw89/cam.c  | 34 ++++++++++++++---------
 drivers/net/wireless/realtek/rtw89/cam.h  |  5 ++++
 drivers/net/wireless/realtek/rtw89/core.h |  1 -
 3 files changed, 26 insertions(+), 14 deletions(-)
drivers/net/wireless/realtek/rtw89/cam.c +21 -13
index bd34e4bbe107b..2114d117b603d 100644
@@ -427,15 +427,23 @@ static void rtw89_cam_reset_key_iter(struct ieee80211_hw *hw,
 	rtw89_cam_deinit(rtwdev, rtwvif);
 }
 
+void rtw89_cam_deinit_addr_cam(struct rtw89_dev *rtwdev,
+			       struct rtw89_addr_cam_entry *addr_cam)
+{
+	struct rtw89_cam_info *cam_info = &rtwdev->cam_info;
+
+	addr_cam->valid = false;
+	clear_bit(addr_cam->addr_cam_idx, cam_info->addr_cam_map);
+}
+
 void rtw89_cam_deinit(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
 {
 	struct rtw89_cam_info *cam_info = &rtwdev->cam_info;
 	struct rtw89_addr_cam_entry *addr_cam = &rtwvif->addr_cam;
 	struct rtw89_bssid_cam_entry *bssid_cam = &rtwvif->bssid_cam;
 
-	addr_cam->valid = false;
+	rtw89_cam_deinit_addr_cam(rtwdev, addr_cam);
 	bssid_cam->valid = false;
-	clear_bit(addr_cam->addr_cam_idx, cam_info->addr_cam_map);
 	clear_bit(bssid_cam->bssid_cam_idx, cam_info->bssid_cam_map);
 }
 
@@ -464,10 +472,10 @@ static int rtw89_cam_get_avail_addr_cam(struct rtw89_dev *rtwdev,
 	return 0;
 }
 
-static int rtw89_cam_init_addr_cam(struct rtw89_dev *rtwdev,
-				   struct rtw89_vif *rtwvif)
+int rtw89_cam_init_addr_cam(struct rtw89_dev *rtwdev,
+			    struct rtw89_addr_cam_entry *addr_cam,
+			    const struct rtw89_bssid_cam_entry *bssid_cam)
 {
-	struct rtw89_addr_cam_entry *addr_cam = &rtwvif->addr_cam;
 	u8 addr_cam_idx;
 	int i;
 	int ret;
@@ -484,14 +492,17 @@ static int rtw89_cam_init_addr_cam(struct rtw89_dev *rtwdev,
 	addr_cam->valid = true;
 	addr_cam->addr_mask = 0;
 	addr_cam->mask_sel = RTW89_NO_MSK;
+	addr_cam->sec_ent_mode = RTW89_ADDR_CAM_SEC_NORMAL;
 	bitmap_zero(addr_cam->sec_cam_map, RTW89_SEC_CAM_IN_ADDR_CAM);
-	ether_addr_copy(addr_cam->sma, rtwvif->mac_addr);
 
 	for (i = 0; i < RTW89_SEC_CAM_IN_ADDR_CAM; i++) {
 		addr_cam->sec_ent_keyid[i] = 0;
 		addr_cam->sec_ent[i] = 0;
 	}
 
+	/* associate addr cam with bssid cam */
+	addr_cam->bssid_cam_idx = bssid_cam->bssid_cam_idx;
+
 	return 0;
 }
 
@@ -549,21 +560,18 @@ int rtw89_cam_init(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
 	struct rtw89_bssid_cam_entry *bssid_cam = &rtwvif->bssid_cam;
 	int ret;
 
-	ret = rtw89_cam_init_addr_cam(rtwdev, rtwvif);
+	ret = rtw89_cam_init_bssid_cam(rtwdev, rtwvif);
 	if (ret) {
-		rtw89_err(rtwdev, "failed to init addr cam\n");
+		rtw89_err(rtwdev, "failed to init bssid cam\n");
 		return ret;
 	}
 
-	ret = rtw89_cam_init_bssid_cam(rtwdev, rtwvif);
+	ret = rtw89_cam_init_addr_cam(rtwdev, addr_cam, bssid_cam);
 	if (ret) {
-		rtw89_err(rtwdev, "failed to init bssid cam\n");
+		rtw89_err(rtwdev, "failed to init addr cam\n");
 		return ret;
 	}
 
-	/* associate addr cam with bssid cam */
-	addr_cam->bssid_cam_idx = bssid_cam->bssid_cam_idx;
-
 	return 0;
 }
 
drivers/net/wireless/realtek/rtw89/cam.h +5 -0
index 33a3ad582b818..3a6a786530d17 100644
@@ -346,6 +346,11 @@ static inline void FWCMD_SET_ADDR_BSSID_BSSID5(void *cmd, u32 value)
 
 int rtw89_cam_init(struct rtw89_dev *rtwdev, struct rtw89_vif *vif);
 void rtw89_cam_deinit(struct rtw89_dev *rtwdev, struct rtw89_vif *vif);
+int rtw89_cam_init_addr_cam(struct rtw89_dev *rtwdev,
+			    struct rtw89_addr_cam_entry *addr_cam,
+			    const struct rtw89_bssid_cam_entry *bssid_cam);
+void rtw89_cam_deinit_addr_cam(struct rtw89_dev *rtwdev,
+			       struct rtw89_addr_cam_entry *addr_cam);
 void rtw89_cam_fill_addr_cam_info(struct rtw89_dev *rtwdev,
 				  struct rtw89_vif *vif,
 				  struct rtw89_sta *rtwsta,
drivers/net/wireless/realtek/rtw89/core.h +0 -1
index 8cb907da6cb05..2dd5c4f0a3636 100644
@@ -1884,7 +1884,6 @@ struct rtw89_addr_cam_entry {
 	u8 wapi		: 1;
 	u8 mask_sel	: 2;
 	u8 bssid_cam_idx: 6;
-	u8 sma[ETH_ALEN];
 
 	u8 sec_ent_mode;
 	DECLARE_BITMAP(sec_cam_map, RTW89_SEC_CAM_IN_ADDR_CAM);
Signature · 1 line
2.25.1
author maintainer
#14 lore raw

PATCH 13/19 rtw89: extend role_maintain to support AP mode

In reply to 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,

---
 drivers/net/wireless/realtek/rtw89/fw.c  | 8 ++++++--
 drivers/net/wireless/realtek/rtw89/fw.h  | 1 +
 drivers/net/wireless/realtek/rtw89/mac.c | 4 ++--
 3 files changed, 9 insertions(+), 4 deletions(-)
drivers/net/wireless/realtek/rtw89/fw.c +6 -2
index 5209813275676..4641aadea0386 100644
@@ -993,9 +993,13 @@ 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 = rtwvif->net_type == RTW89_NET_TYPE_AP_MODE && rtwsta ?
+		       RTW89_SELF_ROLE_AP_CLIENT : rtwvif->self_role;
 
 	skb = rtw89_fw_h2c_alloc_skb_with_hdr(H2C_ROLE_MAINTAIN_LEN);
 	if (!skb) {
@@ -1003,8 +1007,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 58aa24e71637d..19eb8ea1ba915 100644
@@ -3012,7 +3012,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;
 
@@ -3035,7 +3035,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
#15 lore raw

Re: [PATCH 13/19] rtw89: extend role_maintain to support AP mode

Quoted 20 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,

---
 drivers/net/wireless/realtek/rtw89/fw.c  | 8 ++++++--
 drivers/net/wireless/realtek/rtw89/fw.h  | 1 +
 drivers/net/wireless/realtek/rtw89/mac.c | 4 ++--
 3 files changed, 9 insertions(+), 4 deletions(-)
drivers/net/wireless/realtek/rtw89/fw.c +0 -0
index 5209813275676..4641aadea0386 100644

drivers/net/wireless/realtek/rtw89/fw.c int rtw89_fw_h2c_update_beacon(struct rtw89_dev *rtwdev, · line 1002

Quoted 10 lines
drivers/net/wireless/realtek/rtw89/fw.c +4 -0
@@ -993,9 +993,13 @@ 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 = rtwvif->net_type == RTW89_NET_TYPE_AP_MODE && rtwsta ?
+		       RTW89_SELF_ROLE_AP_CLIENT : rtwvif->self_role;

It seems you like '?' operator more than I do, and it's ok to use in simple cases. But the latter statement is not really readable, something like this is so much easier to read:

if (rtwvif->net_type == RTW89_NET_TYPE_AP_MODE && rtwsta)
self_role = RTW89_SELF_ROLE_AP_CLIENT
else

    self_role = rtwvif->self_role;

But should there a parenthesis around the == operator? I cannot now recall what's the preference in the kernel, can someone help on that?

Maybe I also move check for rtwsta first?

Signature · 3 lines
https://patchwork.kernel.org/project/linux-wireless/list/

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

Re: [PATCH 13/19] rtw89: extend role_maintain to support AP mode

Quoted 37 lines · Kalle Valo
Quoted 20 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,

---
 drivers/net/wireless/realtek/rtw89/fw.c  | 8 ++++++--
 drivers/net/wireless/realtek/rtw89/fw.h  | 1 +
 drivers/net/wireless/realtek/rtw89/mac.c | 4 ++--
 3 files changed, 9 insertions(+), 4 deletions(-)
drivers/net/wireless/realtek/rtw89/fw.c +0 -0
index 5209813275676..4641aadea0386 100644

drivers/net/wireless/realtek/rtw89/fw.c int rtw89_fw_h2c_update_beacon(struct rtw89_dev *rtwdev, · line 1002

Quoted 10 lines
drivers/net/wireless/realtek/rtw89/fw.c +4 -0
@@ -993,9 +993,13 @@ 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 = rtwvif->net_type == RTW89_NET_TYPE_AP_MODE && rtwsta ?
+		       RTW89_SELF_ROLE_AP_CLIENT : rtwvif->self_role;

It seems you like '?' operator more than I do, and it's ok to use in simple cases. But the latter statement is not really readable, something like this is so much easier to read:

Quoted 5 lines

if (rtwvif->net_type == RTW89_NET_TYPE_AP_MODE && rtwsta)
self_role = RTW89_SELF_ROLE_AP_CLIENT
else

    self_role = rtwvif->self_role;

I use '?' to make code shorter, but your sugeestion would be eaiser to reviewer. I will send v2 after the Lunar New Year.

Quoted 2 lines

But should there a parenthesis around the == operator? I cannot now recall what's the preference in the kernel, can someone help on that?

The checkpatch will warn this if we add parenthesis, so preence is not to use parenthesis.

CHECK:UNNECESSARY_PARENTHESES: Unnecessary parentheses around 'rtwvif->net_type == RTW89_NET_TYPE_AP_MODE'
#9: FILE: fw.c:1004:
+ if ((rtwvif->net_type == RTW89_NET_TYPE_AP_MODE) && rtwsta)

Quoted 3 lines

Maybe I also move check for rtwsta first?

The full logic is

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

And, the meaning of 'rtwsta' here is to indicate we are going to setup a connected station that connects to this AP, but not check if the pointer is NULL. To emphasis the case is only existing in AP_MODE, I prefer to check net_type ahead. Or, this full logic is preferred?

Ping-Ke

#17 lore raw

Re: [PATCH 13/19] rtw89: extend role_maintain to support AP mode

Quoted 38 lines · Pkshih
Quoted 37 lines · Kalle Valo
Quoted 20 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,

---
 drivers/net/wireless/realtek/rtw89/fw.c  | 8 ++++++--
 drivers/net/wireless/realtek/rtw89/fw.h  | 1 +
 drivers/net/wireless/realtek/rtw89/mac.c | 4 ++--
 3 files changed, 9 insertions(+), 4 deletions(-)
drivers/net/wireless/realtek/rtw89/fw.c +0 -0
index 5209813275676..4641aadea0386 100644

drivers/net/wireless/realtek/rtw89/fw.c int rtw89_fw_h2c_update_beacon(struct rtw89_dev *rtwdev, · line 1002

Quoted 10 lines
drivers/net/wireless/realtek/rtw89/fw.c +4 -0
@@ -993,9 +993,13 @@ 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 = rtwvif->net_type == RTW89_NET_TYPE_AP_MODE && rtwsta ?
+		       RTW89_SELF_ROLE_AP_CLIENT : rtwvif->self_role;

It seems you like '?' operator more than I do, and it's ok to use in simple cases. But the latter statement is not really readable, something like this is so much easier to read:

Quoted 8 lines
Quoted 5 lines

if (rtwvif->net_type == RTW89_NET_TYPE_AP_MODE && rtwsta)
self_role = RTW89_SELF_ROLE_AP_CLIENT
else

    self_role = rtwvif->self_role;

I use '?' to make code shorter, but your sugeestion would be eaiser to reviewer. I will send v2 after the Lunar New Year.

Happy New Year :)

Review

Quoted 10 lines
Quoted 2 lines

But should there a parenthesis around the == operator? I cannot now recall what's the preference in the kernel, can someone help on that?

The checkpatch will warn this if we add parenthesis, so preence is not to use parenthesis.

CHECK:UNNECESSARY_PARENTHESES: Unnecessary parentheses around 'rtwvif->net_type == RTW89_NET_TYPE_AP_MODE'
#9: FILE: fw.c:1004:

(quoted diff) +1 -0
+	if ((rtwvif->net_type == RTW89_NET_TYPE_AP_MODE) && rtwsta)

Ok, I need to remember that :)

Quoted 10 lines
Quoted 2 lines

Maybe I also move check for rtwsta first?

The full logic is

if (rtwvif->net_type == RTW89_NET_TYPE_AP_MODE) {
if (rtwsta)
self_role = RTW89_SELF_ROLE_AP_CLIENT
else
self_role = rtwvif->self_role;

Quoted 8 lines
} else {
    self_role = rtwvif->self_role;
}

And, the meaning of 'rtwsta' here is to indicate we are going to setup a connected station that connects to this AP, but not check if the pointer is NULL. To emphasis the case is only existing in AP_MODE, I prefer to check net_type ahead. Or, this full logic is preferred?

I don't know what others think, but I find this full logic style most readable.

Signature · 3 lines
https://patchwork.kernel.org/project/linux-wireless/list/

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

Re: [PATCH 13/19] rtw89: extend role_maintain to support AP mode

Quoted 18 lines · Kalle Valo
Quoted 16 lines · Pkshih
Quoted 3 lines · Kalle Valo

Maybe I also move check for rtwsta first?

The full logic is

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;
}
Quoted 8 lines
Quoted 4 lines

And, the meaning of 'rtwsta' here is to indicate we are going to setup a connected station that connects to this AP, but not check if the pointer is NULL. To emphasis the case is only existing in AP_MODE, I prefer to check net_type ahead. Or, this full logic is preferred?

I don't know what others think, but I find this full logic style most readable.

Maybe, a static analysis tool warns two else branches are the same. If so, we can make a decision at that time.

I will send v2 next week, and wait for people who have other ideas.

Happy New Year.
--
Ping-Ke

#19 lore raw

Re: [PATCH 13/19] rtw89: extend role_maintain to support AP mode

In reply to Ping-Ke Shih
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,

Dropping rest of the patches due to my comment.

7 patches set to Changes Requested.

12706170 [13/19] rtw89: extend role_maintain to support AP mode 12706171 [14/19] rtw89: add addr_cam field to sta to support AP mode 12706172 [15/19] rtw89: only STA mode change vif_type mapping dynamically 12706173 [16/19] rtw89: maintain assoc/disassoc STA states of firmware and hardware 12706174 [17/19] rtw89: implement ieee80211_ops::start_ap and stop_ap 12706175 [18/19] rtw89: debug: add stations entry to show ID assignment 12706176 [19/19] 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
#20 lore raw

PATCH 14/19 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 8f8891badf0e8..aeb7289bd8c33 100644
@@ -2,6 +2,7 @@
 /* Copyright(c) 2019-2020  Realtek Corporation
  */
 
+#include "cam.h"
 #include "coex.h"
 #include "core.h"
 #include "efuse.h"
@@ -298,9 +299,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;
@@ -313,7 +316,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
#21 lore raw

PATCH 15/19 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 aeb7289bd8c33..4756a2e7a2389 100644
@@ -1944,7 +1944,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) {
@@ -1976,7 +1977,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 26abbe7aa17d8..c7208fad31dd6 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
#22 lore raw

PATCH 16/19 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 4756a2e7a2389..d23bd87661d7a 100644
@@ -1943,6 +1943,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);
@@ -1959,8 +1961,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;
@@ -1977,6 +1987,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 19eb8ea1ba915..17a41fddc62e4 100644
@@ -2705,7 +2705,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;
@@ -3008,7 +3008,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 65e4ebe05f6ad..ead385c53331b 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
#23 lore raw

PATCH 17/19 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 c7208fad31dd6..091c0aa631855 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
#24 lore raw

PATCH 18/19 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 9756d75ef24e1..45fefa8bd9562 100644
@@ -2364,6 +2364,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,
@@ -2430,6 +2496,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;			\
@@ -2468,6 +2538,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
#25 lore raw

PATCH 19/19 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 d23bd87661d7a..10eb575b05be0 100644
@@ -2561,7 +2561,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