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