Commit 28c11c29 authored by Po-Hao Huang's avatar Po-Hao Huang Committed by Kalle Valo
Browse files

wifi: rtw88: fix not entering PS mode after AP stops



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: default avatarPo-Hao Huang <phhuang@realtek.com>
Signed-off-by: default avatarPing-Ke Shih <pkshih@realtek.com>
Signed-off-by: default avatarKalle Valo <kvalo@kernel.org>
Link: https://lore.kernel.org/r/20230616125540.36877-7-pkshih@realtek.com
parent 455afa45
Loading
Loading
Loading
Loading
+17 −0
Original line number Diff line number Diff line
@@ -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};
+8 −0
Original line number Diff line number Diff line
@@ -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);
+1 −0
Original line number Diff line number Diff line
@@ -382,6 +382,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);
+8 −0
Original line number Diff line number Diff line
@@ -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)
+1 −0
Original line number Diff line number Diff line
@@ -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;