Commit 7bfd05ff authored by Chin-Yen Lee's avatar Chin-Yen Lee Committed by Kalle Valo
Browse files

rtw89: add tx_wake notify for low ps mode



We found management frames get stuck when wifi chip
enters low ps mode. So we add one notify wake function
to trigger wifi chip into normal mode before forwarding
management frames.

Signed-off-by: default avatarChin-Yen Lee <timlee@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/20220225030851.13327-3-pkshih@realtek.com
parent 89590777
Loading
Loading
Loading
Loading
+19 −0
Original line number Original line Diff line number Diff line
@@ -755,6 +755,22 @@ rtw89_core_tx_btc_spec_pkt_notify(struct rtw89_dev *rtwdev,
	return PACKET_MAX;
	return PACKET_MAX;
}
}


static void
rtw89_core_tx_wake(struct rtw89_dev *rtwdev,
		   struct rtw89_core_tx_request *tx_req)
{
	if (!rtwdev->fw.tx_wake)
		return;

	if (!test_bit(RTW89_FLAG_LOW_POWER_MODE, rtwdev->flags))
		return;

	if (tx_req->tx_type != RTW89_CORE_TX_TYPE_MGMT)
		return;

	rtw89_mac_notify_wake(rtwdev);
}

static void
static void
rtw89_core_tx_update_desc_info(struct rtw89_dev *rtwdev,
rtw89_core_tx_update_desc_info(struct rtw89_dev *rtwdev,
			       struct rtw89_core_tx_request *tx_req)
			       struct rtw89_core_tx_request *tx_req)
@@ -853,6 +869,8 @@ int rtw89_core_tx_write(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif,
	rtw89_traffic_stats_accu(rtwdev, &rtwdev->stats, skb, true);
	rtw89_traffic_stats_accu(rtwdev, &rtwdev->stats, skb, true);
	rtw89_traffic_stats_accu(rtwdev, &rtwvif->stats, skb, true);
	rtw89_traffic_stats_accu(rtwdev, &rtwvif->stats, skb, true);
	rtw89_core_tx_update_desc_info(rtwdev, &tx_req);
	rtw89_core_tx_update_desc_info(rtwdev, &tx_req);
	rtw89_core_tx_wake(rtwdev, &tx_req);

	ret = rtw89_hci_tx_write(rtwdev, &tx_req);
	ret = rtw89_hci_tx_write(rtwdev, &tx_req);
	if (ret) {
	if (ret) {
		rtw89_err(rtwdev, "failed to transmit skb to HCI\n");
		rtw89_err(rtwdev, "failed to transmit skb to HCI\n");
@@ -2618,6 +2636,7 @@ int rtw89_core_init(struct rtw89_dev *rtwdev)
	INIT_DELAYED_WORK(&rtwdev->cfo_track_work, rtw89_phy_cfo_track_work);
	INIT_DELAYED_WORK(&rtwdev->cfo_track_work, rtw89_phy_cfo_track_work);
	rtwdev->txq_wq = alloc_workqueue("rtw89_tx_wq", WQ_UNBOUND | WQ_HIGHPRI, 0);
	rtwdev->txq_wq = alloc_workqueue("rtw89_tx_wq", WQ_UNBOUND | WQ_HIGHPRI, 0);
	spin_lock_init(&rtwdev->ba_lock);
	spin_lock_init(&rtwdev->ba_lock);
	spin_lock_init(&rtwdev->rpwm_lock);
	mutex_init(&rtwdev->mutex);
	mutex_init(&rtwdev->mutex);
	mutex_init(&rtwdev->rf_mutex);
	mutex_init(&rtwdev->rf_mutex);
	rtwdev->total_sta_assoc = 0;
	rtwdev->total_sta_assoc = 0;
+3 −0
Original line number Original line Diff line number Diff line
@@ -2376,6 +2376,7 @@ struct rtw89_fw_info {
	bool fw_log_enable;
	bool fw_log_enable;
	bool old_ht_ra_format;
	bool old_ht_ra_format;
	bool scan_offload;
	bool scan_offload;
	bool tx_wake;
};
};


struct rtw89_cam_info {
struct rtw89_cam_info {
@@ -2877,6 +2878,8 @@ struct rtw89_dev {
	/* txqs to setup ba session */
	/* txqs to setup ba session */
	struct list_head ba_list;
	struct list_head ba_list;
	struct work_struct ba_work;
	struct work_struct ba_work;
	/* used to protect rpwm */
	spinlock_t rpwm_lock;


	struct rtw89_cam_info cam_info;
	struct rtw89_cam_info cam_info;


+4 −0
Original line number Original line Diff line number Diff line
@@ -205,6 +205,10 @@ static void rtw89_fw_recognize_features(struct rtw89_dev *rtwdev)
	if (chip->chip_id == RTL8852A &&
	if (chip->chip_id == RTL8852A &&
	    RTW89_FW_SUIT_VER_CODE(fw_suit) >= RTW89_FW_VER_CODE(0, 13, 35, 0))
	    RTW89_FW_SUIT_VER_CODE(fw_suit) >= RTW89_FW_VER_CODE(0, 13, 35, 0))
		rtwdev->fw.scan_offload = true;
		rtwdev->fw.scan_offload = true;

	if (chip->chip_id == RTL8852A &&
	    RTW89_FW_SUIT_VER_CODE(fw_suit) >= RTW89_FW_VER_CODE(0, 13, 35, 0))
		rtwdev->fw.tx_wake = true;
}
}


int rtw89_fw_recognize(struct rtw89_dev *rtwdev)
int rtw89_fw_recognize(struct rtw89_dev *rtwdev)
+25 −9
Original line number Original line Diff line number Diff line
@@ -917,23 +917,31 @@ rtw89_mac_get_req_pwr_state(struct rtw89_dev *rtwdev)
}
}


static void rtw89_mac_send_rpwm(struct rtw89_dev *rtwdev,
static void rtw89_mac_send_rpwm(struct rtw89_dev *rtwdev,
				enum rtw89_rpwm_req_pwr_state req_pwr_state)
				enum rtw89_rpwm_req_pwr_state req_pwr_state,
				bool notify_wake)
{
{
	u16 request;
	u16 request;


	spin_lock_bh(&rtwdev->rpwm_lock);

	request = rtw89_read16(rtwdev, R_AX_RPWM);
	request = rtw89_read16(rtwdev, R_AX_RPWM);
	request ^= request | PS_RPWM_TOGGLE;
	request ^= request | PS_RPWM_TOGGLE;
	request |= req_pwr_state;


	if (notify_wake) {
		request |= PS_RPWM_NOTIFY_WAKE;
	} else {
		rtwdev->mac.rpwm_seq_num = (rtwdev->mac.rpwm_seq_num + 1) &
		rtwdev->mac.rpwm_seq_num = (rtwdev->mac.rpwm_seq_num + 1) &
					    RPWM_SEQ_NUM_MAX;
					    RPWM_SEQ_NUM_MAX;
	request |= FIELD_PREP(PS_RPWM_SEQ_NUM, rtwdev->mac.rpwm_seq_num);
		request |= FIELD_PREP(PS_RPWM_SEQ_NUM,

				      rtwdev->mac.rpwm_seq_num);
	request |= req_pwr_state;


		if (req_pwr_state < RTW89_MAC_RPWM_REQ_PWR_STATE_CLK_GATED)
		if (req_pwr_state < RTW89_MAC_RPWM_REQ_PWR_STATE_CLK_GATED)
			request |= PS_RPWM_ACK;
			request |= PS_RPWM_ACK;

	}
	rtw89_write16(rtwdev, rtwdev->hci.rpwm_addr, request);
	rtw89_write16(rtwdev, rtwdev->hci.rpwm_addr, request);

	spin_unlock_bh(&rtwdev->rpwm_lock);
}
}


static int rtw89_mac_check_cpwm_state(struct rtw89_dev *rtwdev,
static int rtw89_mac_check_cpwm_state(struct rtw89_dev *rtwdev,
@@ -993,7 +1001,7 @@ void rtw89_mac_power_mode_change(struct rtw89_dev *rtwdev, bool enter)
	else
	else
		state = RTW89_MAC_RPWM_REQ_PWR_STATE_ACTIVE;
		state = RTW89_MAC_RPWM_REQ_PWR_STATE_ACTIVE;


	rtw89_mac_send_rpwm(rtwdev, state);
	rtw89_mac_send_rpwm(rtwdev, state, false);
	ret = read_poll_timeout_atomic(rtw89_mac_check_cpwm_state, ret, !ret,
	ret = read_poll_timeout_atomic(rtw89_mac_check_cpwm_state, ret, !ret,
				       1000, 15000, false, rtwdev, state);
				       1000, 15000, false, rtwdev, state);
	if (ret)
	if (ret)
@@ -1001,6 +1009,14 @@ void rtw89_mac_power_mode_change(struct rtw89_dev *rtwdev, bool enter)
			  enter ? "entering" : "leaving");
			  enter ? "entering" : "leaving");
}
}


void rtw89_mac_notify_wake(struct rtw89_dev *rtwdev)
{
	enum rtw89_rpwm_req_pwr_state state;

	state = rtw89_mac_get_req_pwr_state(rtwdev);
	rtw89_mac_send_rpwm(rtwdev, state, true);
}

static int rtw89_mac_power_switch(struct rtw89_dev *rtwdev, bool on)
static int rtw89_mac_power_switch(struct rtw89_dev *rtwdev, bool on)
{
{
#define PWR_ACT 1
#define PWR_ACT 1
+1 −0
Original line number Original line Diff line number Diff line
@@ -799,6 +799,7 @@ bool rtw89_mac_get_txpwr_cr(struct rtw89_dev *rtwdev,
			    enum rtw89_phy_idx phy_idx,
			    enum rtw89_phy_idx phy_idx,
			    u32 reg_base, u32 *cr);
			    u32 reg_base, u32 *cr);
void rtw89_mac_power_mode_change(struct rtw89_dev *rtwdev, bool enter);
void rtw89_mac_power_mode_change(struct rtw89_dev *rtwdev, bool enter);
void rtw89_mac_notify_wake(struct rtw89_dev *rtwdev);
void rtw89_mac_bf_assoc(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif,
void rtw89_mac_bf_assoc(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif,
			struct ieee80211_sta *sta);
			struct ieee80211_sta *sta);
void rtw89_mac_bf_disassoc(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif,
void rtw89_mac_bf_disassoc(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif,
Loading