In AP mode, HI queue is used to transmit broadcast/multicast right after
issuing beacon, and we need set MORE_DATA in TX description to make
hardware transmits all packets in one go. Also, have special deal with
this queue when doing scan and flush.
After stopping AP from SCC (AP + STA), only one STA is working, so PS mode
is expected to enable. However, firmware checks the MAC port used by AP
mode before, and then can't enter PS mode. We add the last patch to set
"default port" to the port used by STA. Then, firmware will check correct
port to enter PS mode in expectation.
Note: The patch 5/6 ("wifi: rtw88: refine register based H2C command")
adds new static function that is used by patch 6/6, so compiler will
warn unused function if we build this path.
v2:
- fix patch 1/6 problems
* correct to use RTW_TX_DESC_W7_DMA_TXAGG_NUM to set agg_num
* use correct le32p_replace_bits() to set value instead
Po-Hao Huang (6):
wifi: rtw88: use struct instead of macros to set TX desc
wifi: rtw88: Fix AP mode incorrect DTIM behavior
wifi: rtw88: Skip high queue in hci_flush
wifi: rtw88: Stop high queue during scan
wifi: rtw88: refine register based H2C command
wifi: rtw88: fix not entering PS mode after AP stops
drivers/net/wireless/realtek/rtw88/fw.c | 68 ++++++++++
drivers/net/wireless/realtek/rtw88/fw.h | 13 ++
drivers/net/wireless/realtek/rtw88/mac80211.c | 3 +
drivers/net/wireless/realtek/rtw88/main.c | 15 ++-
drivers/net/wireless/realtek/rtw88/main.h | 1 +
drivers/net/wireless/realtek/rtw88/pci.c | 5 +-
drivers/net/wireless/realtek/rtw88/reg.h | 2 +
drivers/net/wireless/realtek/rtw88/rtw8723d.c | 6 +-
drivers/net/wireless/realtek/rtw88/tx.c | 84 +++++++-----
drivers/net/wireless/realtek/rtw88/tx.h | 123 ++++++++----------
drivers/net/wireless/realtek/rtw88/usb.c | 15 ++-
11 files changed, 218 insertions(+), 117 deletions(-)
--
2.25.1
From: Po-Hao Huang <[email protected]>
Without this patch, firmware only track beacons for port 0 and since
we will always start AP on port 0, this results in misbehavior of
power saving mode on other ports after AP stops.
The "default port" H2C command is used to notify which port should
firmware track. Update the correct settings to firmware so power
saving mode can work properly.
Signed-off-by: Po-Hao Huang <[email protected]>
Signed-off-by: Ping-Ke Shih <[email protected]>
---
v2: no change
---
drivers/net/wireless/realtek/rtw88/fw.c | 17 +++++++++++++++++
drivers/net/wireless/realtek/rtw88/fw.h | 8 ++++++++
drivers/net/wireless/realtek/rtw88/mac80211.c | 1 +
drivers/net/wireless/realtek/rtw88/main.c | 8 ++++++++
drivers/net/wireless/realtek/rtw88/main.h | 1 +
5 files changed, 35 insertions(+)
diff --git a/drivers/net/wireless/realtek/rtw88/fw.c b/drivers/net/wireless/realtek/rtw88/fw.c
index 5e329bb95bb89..567bbedd8ee09 100644
--- a/drivers/net/wireless/realtek/rtw88/fw.c
+++ b/drivers/net/wireless/realtek/rtw88/fw.c
@@ -519,6 +519,23 @@ void rtw_fw_query_bt_info(struct rtw_dev *rtwdev)
rtw_fw_send_h2c_command(rtwdev, h2c_pkt);
}
+void rtw_fw_default_port(struct rtw_dev *rtwdev, struct rtw_vif *rtwvif)
+{
+ struct rtw_h2c_register h2c = {};
+
+ if (rtwvif->net_type != RTW_NET_MGD_LINKED)
+ return;
+
+ /* Leave LPS before default port H2C so FW timer is correct */
+ rtw_leave_lps(rtwdev);
+
+ h2c.w0 = u32_encode_bits(H2C_CMD_DEFAULT_PORT, RTW_H2C_W0_CMDID) |
+ u32_encode_bits(rtwvif->port, RTW_H2C_DEFAULT_PORT_W0_PORTID) |
+ u32_encode_bits(rtwvif->mac_id, RTW_H2C_DEFAULT_PORT_W0_MACID);
+
+ rtw_fw_send_h2c_command_register(rtwdev, &h2c);
+}
+
void rtw_fw_wl_ch_info(struct rtw_dev *rtwdev, u8 link, u8 ch, u8 bw)
{
u8 h2c_pkt[H2C_PKT_SIZE] = {0};
diff --git a/drivers/net/wireless/realtek/rtw88/fw.h b/drivers/net/wireless/realtek/rtw88/fw.h
index 11a77d86cd144..43ccdf9965ac4 100644
--- a/drivers/net/wireless/realtek/rtw88/fw.h
+++ b/drivers/net/wireless/realtek/rtw88/fw.h
@@ -86,6 +86,12 @@ struct rtw_h2c_register {
u32 w1;
} __packed;
+#define RTW_H2C_W0_CMDID GENMASK(7, 0)
+
+/* H2C_CMD_DEFAULT_PORT command */
+#define RTW_H2C_DEFAULT_PORT_W0_PORTID GENMASK(15, 8)
+#define RTW_H2C_DEFAULT_PORT_W0_MACID GENMASK(23, 16)
+
struct rtw_h2c_cmd {
__le32 msg;
__le32 msg_ext;
@@ -535,6 +541,7 @@ static inline void rtw_h2c_pkt_set_header(u8 *h2c_pkt, u8 sub_id)
#define H2C_CMD_MEDIA_STATUS_RPT 0x01
#define H2C_CMD_SET_PWR_MODE 0x20
#define H2C_CMD_LPS_PG_INFO 0x2b
+#define H2C_CMD_DEFAULT_PORT 0x2c
#define H2C_CMD_RA_INFO 0x40
#define H2C_CMD_RSSI_MONITOR 0x42
#define H2C_CMD_BCN_FILTER_OFFLOAD_P0 0x56
@@ -806,6 +813,7 @@ void rtw_fw_c2h_cmd_rx_irqsafe(struct rtw_dev *rtwdev, u32 pkt_offset,
void rtw_fw_c2h_cmd_handle(struct rtw_dev *rtwdev, struct sk_buff *skb);
void rtw_fw_send_general_info(struct rtw_dev *rtwdev);
void rtw_fw_send_phydm_info(struct rtw_dev *rtwdev);
+void rtw_fw_default_port(struct rtw_dev *rtwdev, struct rtw_vif *rtwvif);
void rtw_fw_do_iqk(struct rtw_dev *rtwdev, struct rtw_iqk_para *para);
void rtw_fw_inform_rfk_status(struct rtw_dev *rtwdev, bool start);
diff --git a/drivers/net/wireless/realtek/rtw88/mac80211.c b/drivers/net/wireless/realtek/rtw88/mac80211.c
index 0dc83c2f420da..c5a07285fa541 100644
--- a/drivers/net/wireless/realtek/rtw88/mac80211.c
+++ b/drivers/net/wireless/realtek/rtw88/mac80211.c
@@ -378,6 +378,7 @@ static void rtw_ops_bss_info_changed(struct ieee80211_hw *hw,
rtw_fw_download_rsvd_page(rtwdev);
rtw_send_rsvd_page_h2c(rtwdev);
+ rtw_fw_default_port(rtwdev, rtwvif);
rtw_coex_media_status_notify(rtwdev, vif->cfg.assoc);
if (rtw_bf_support)
rtw_bf_assoc(rtwdev, vif, conf);
diff --git a/drivers/net/wireless/realtek/rtw88/main.c b/drivers/net/wireless/realtek/rtw88/main.c
index d55b041a6bb93..c853e2f2d448f 100644
--- a/drivers/net/wireless/realtek/rtw88/main.c
+++ b/drivers/net/wireless/realtek/rtw88/main.c
@@ -334,12 +334,15 @@ int rtw_sta_add(struct rtw_dev *rtwdev, struct ieee80211_sta *sta,
struct ieee80211_vif *vif)
{
struct rtw_sta_info *si = (struct rtw_sta_info *)sta->drv_priv;
+ struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv;
int i;
si->mac_id = rtw_acquire_macid(rtwdev);
if (si->mac_id >= RTW_MAX_MAC_ID_NUM)
return -ENOSPC;
+ if (vif->type == NL80211_IFTYPE_STATION && vif->cfg.assoc == 0)
+ rtwvif->mac_id = si->mac_id;
si->rtwdev = rtwdev;
si->sta = sta;
si->vif = vif;
@@ -2340,6 +2343,9 @@ static void rtw_port_switch_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
rtw_dbg(rtwdev, RTW_DBG_STATE, "AP port switch from %d -> %d\n",
rtwvif_ap->port, rtwvif_target->port);
+ /* Leave LPS so the value swapped are not in PS mode */
+ rtw_leave_lps(rtwdev);
+
reg1 = &rtwvif_ap->conf->net_type;
reg2 = &rtwvif_target->conf->net_type;
rtw_swap_reg_mask(rtwdev, reg1, reg2);
@@ -2358,6 +2364,8 @@ static void rtw_port_switch_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
swap(rtwvif_target->port, rtwvif_ap->port);
swap(rtwvif_target->conf, rtwvif_ap->conf);
+
+ rtw_fw_default_port(rtwdev, rtwvif_target);
}
void rtw_core_port_switch(struct rtw_dev *rtwdev, struct ieee80211_vif *vif)
diff --git a/drivers/net/wireless/realtek/rtw88/main.h b/drivers/net/wireless/realtek/rtw88/main.h
index 9e841f6991a9a..f9dd2ab941c8f 100644
--- a/drivers/net/wireless/realtek/rtw88/main.h
+++ b/drivers/net/wireless/realtek/rtw88/main.h
@@ -803,6 +803,7 @@ struct rtw_bf_info {
struct rtw_vif {
enum rtw_net_type net_type;
u16 aid;
+ u8 mac_id; /* for STA mode only */
u8 mac_addr[ETH_ALEN];
u8 bssid[ETH_ALEN];
u8 port;
--
2.25.1
Ping-Ke Shih <[email protected]> writes:
> Note: The patch 5/6 ("wifi: rtw88: refine register based H2C command")
> adds new static function that is used by patch 6/6, so compiler will
> warn unused function if we build this path.
Thanks for the note, this is always good to know. In general it would be
better to avoid having the warning at all, for example in this case one
solution would have been to merge patches 5 and 6 into one patch. But no
need to resend because of this.
--
https://patchwork.kernel.org/project/linux-wireless/list/
https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches