Commit 27e117e4 authored by Yan-Hsuan Chuang's avatar Yan-Hsuan Chuang Committed by Kalle Valo
Browse files

rtw88: add deep power save support



Deep power save allows firmware/hardware to operate in a
lower power state. And the deep power save mode depends on
LPS mode. So, before entering deep PS, driver must first
enter LPS mode.

Under Deep PS, most of hardware functions are shutdown,
driver will not be able to read/write registers and transfer
data to the device. Hence TX path must be protected by each
interface. Take PCI for example, DMA engine should be idle,
and no nore activities on the PCI bus.

If driver wants to operate on the device, such as register
read/write, it must first acquire the mutex lock and wake
up from Deep PS, otherwise the behavior is undefined.

Signed-off-by: default avatarYan-Hsuan Chuang <yhchuang@realtek.com>
Signed-off-by: default avatarKalle Valo <kvalo@codeaurora.org>
parent 37ba5de2
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@ enum rtw_debug_mask {
	RTW_DBG_RFK		= 0x00000080,
	RTW_DBG_REGD		= 0x00000100,
	RTW_DBG_DEBUGFS		= 0x00000200,
	RTW_DBG_PS		= 0x00000400,

	RTW_DBG_ALL		= 0xffffffff
};
+6 −0
Original line number Diff line number Diff line
@@ -13,6 +13,7 @@ struct rtw_hci_ops {
	int (*setup)(struct rtw_dev *rtwdev);
	int (*start)(struct rtw_dev *rtwdev);
	void (*stop)(struct rtw_dev *rtwdev);
	void (*deep_ps)(struct rtw_dev *rtwdev, bool enter);

	int (*write_data_rsvd_page)(struct rtw_dev *rtwdev, u8 *buf, u32 size);
	int (*write_data_h2c)(struct rtw_dev *rtwdev, u8 *buf, u32 size);
@@ -47,6 +48,11 @@ static inline void rtw_hci_stop(struct rtw_dev *rtwdev)
	rtwdev->hci.ops->stop(rtwdev);
}

static inline void rtw_hci_deep_ps(struct rtw_dev *rtwdev, bool enter)
{
	rtwdev->hci.ops->deep_ps(rtwdev, enter);
}

static inline int
rtw_hci_write_data_rsvd_page(struct rtw_dev *rtwdev, u8 *buf, u32 size)
{
+14 −0
Original line number Diff line number Diff line
@@ -60,6 +60,8 @@ static int rtw_ops_config(struct ieee80211_hw *hw, u32 changed)

	mutex_lock(&rtwdev->mutex);

	rtw_leave_lps_deep(rtwdev);

	if (changed & IEEE80211_CONF_CHANGE_IDLE) {
		if (hw->conf.flags & IEEE80211_CONF_IDLE) {
			rtw_enter_ips(rtwdev);
@@ -139,6 +141,8 @@ static int rtw_ops_add_interface(struct ieee80211_hw *hw,

	mutex_lock(&rtwdev->mutex);

	rtw_leave_lps_deep(rtwdev);

	switch (vif->type) {
	case NL80211_IFTYPE_AP:
	case NL80211_IFTYPE_MESH_POINT:
@@ -181,6 +185,8 @@ static void rtw_ops_remove_interface(struct ieee80211_hw *hw,

	mutex_lock(&rtwdev->mutex);

	rtw_leave_lps_deep(rtwdev);

	eth_zero_addr(rtwvif->mac_addr);
	config |= PORT_SET_MAC_ADDR;
	rtwvif->net_type = RTW_NET_NO_LINK;
@@ -204,6 +210,8 @@ static void rtw_ops_configure_filter(struct ieee80211_hw *hw,

	mutex_lock(&rtwdev->mutex);

	rtw_leave_lps_deep(rtwdev);

	if (changed_flags & FIF_ALLMULTI) {
		if (*new_flags & FIF_ALLMULTI)
			rtwdev->hal.rcr |= BIT_AM | BIT_AB;
@@ -249,6 +257,8 @@ static void rtw_ops_bss_info_changed(struct ieee80211_hw *hw,

	mutex_lock(&rtwdev->mutex);

	rtw_leave_lps_deep(rtwdev);

	if (changed & BSS_CHANGED_ASSOC) {
		struct rtw_chip_info *chip = rtwdev->chip;
		enum rtw_net_type net_type;
@@ -266,6 +276,7 @@ static void rtw_ops_bss_info_changed(struct ieee80211_hw *hw,
			rtw_send_rsvd_page_h2c(rtwdev);
			rtw_coex_media_status_notify(rtwdev, conf->assoc);
		} else {
			rtw_leave_lps(rtwdev);
			net_type = RTW_NET_NO_LINK;
			rtwvif->aid = 0;
			rtw_reset_rsvd_page(rtwdev);
@@ -397,6 +408,8 @@ static int rtw_ops_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,

	mutex_lock(&rtwdev->mutex);

	rtw_leave_lps_deep(rtwdev);

	if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) {
		hw_key_idx = rtw_sec_get_free_cam(sec);
	} else {
@@ -508,6 +521,7 @@ static void rtw_ops_mgd_prepare_tx(struct ieee80211_hw *hw,
	struct rtw_dev *rtwdev = hw->priv;

	mutex_lock(&rtwdev->mutex);
	rtw_leave_lps_deep(rtwdev);
	rtw_coex_connect_notify(rtwdev, COEX_ASSOCIATE_START);
	mutex_unlock(&rtwdev->mutex);
}
+1 −0
Original line number Diff line number Diff line
@@ -922,6 +922,7 @@ static int rtw_chip_parameter_setup(struct rtw_dev *rtwdev)
	switch (rtw_hci_type(rtwdev)) {
	case RTW_HCI_TYPE_PCIE:
		rtwdev->hci.rpwm_addr = 0x03d9;
		rtwdev->hci.cpwm_addr = 0x03da;
		break;
	default:
		rtw_err(rtwdev, "unsupported hci type\n");
+2 −0
Original line number Diff line number Diff line
@@ -50,6 +50,7 @@ struct rtw_hci {
	enum rtw_hci_type type;

	u32 rpwm_addr;
	u32 cpwm_addr;

	u8 bulkout_num;
};
@@ -309,6 +310,7 @@ enum rtw_flags {
	RTW_FLAG_SCANNING,
	RTW_FLAG_INACTIVE_PS,
	RTW_FLAG_LEISURE_PS,
	RTW_FLAG_LEISURE_PS_DEEP,
	RTW_FLAG_DIG_DISABLE,
	RTW_FLAG_BUSY_TRAFFIC,

Loading