@@ -13,6 +13,7 @@
#include "debug.h"
#include "util.h"
#include "wow.h"
+#include "ps.h"
static void rtw_fw_c2h_cmd_handle_ext(struct rtw_dev *rtwdev,
struct sk_buff *skb)
@@ -631,7 +632,7 @@ void rtw_fw_set_nlo_info(struct rtw_dev *rtwdev, bool enable)
SET_NLO_FUN_EN(h2c_pkt, enable);
if (enable) {
- if (rtw_fw_lps_deep_mode)
+ if (rtw_get_lps_deep_mode(rtwdev) != LPS_DEEP_MODE_NONE)
SET_NLO_PS_32K(h2c_pkt, enable);
SET_NLO_IGNORE_SECURITY(h2c_pkt, enable);
SET_NLO_LOC_NLO_INFO(h2c_pkt, loc_nlo);
@@ -519,7 +519,7 @@ static int rtw_ops_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
}
/* download new cam settings for PG to backup */
- if (rtw_fw_lps_deep_mode == LPS_DEEP_MODE_PG)
+ if (rtw_get_lps_deep_mode(rtwdev) == LPS_DEEP_MODE_PG)
rtw_fw_download_rsvd_page(rtwdev);
out:
@@ -16,17 +16,17 @@
#include "debug.h"
#include "bf.h"
-unsigned int rtw_fw_lps_deep_mode;
-EXPORT_SYMBOL(rtw_fw_lps_deep_mode);
+bool rtw_disable_lps_deep_mode;
+EXPORT_SYMBOL(rtw_disable_lps_deep_mode);
bool rtw_bf_support = true;
unsigned int rtw_debug_mask;
EXPORT_SYMBOL(rtw_debug_mask);
-module_param_named(lps_deep_mode, rtw_fw_lps_deep_mode, uint, 0644);
+module_param_named(disable_lps_deep, rtw_disable_lps_deep_mode, bool, 0644);
module_param_named(support_bf, rtw_bf_support, bool, 0644);
module_param_named(debug_mask, rtw_debug_mask, uint, 0644);
-MODULE_PARM_DESC(lps_deep_mode, "Deeper PS mode. If 0, deep PS is disabled");
+MODULE_PARM_DESC(disable_lps_deep, "Set Y to disable Deep PS");
MODULE_PARM_DESC(support_bf, "Set Y to enable beamformee support");
MODULE_PARM_DESC(debug_mask, "Debugging mask");
@@ -1023,6 +1023,26 @@ static int rtw_wait_firmware_completion(struct rtw_dev *rtwdev)
return 0;
}
+static enum rtw_lps_deep_mode rtw_update_lps_deep_mode(struct rtw_dev *rtwdev,
+ struct rtw_fw_state *fw)
+{
+ struct rtw_chip_info *chip = rtwdev->chip;
+
+ if (rtw_disable_lps_deep_mode || !chip->lps_deep_mode_supported ||
+ !fw->feature)
+ return LPS_DEEP_MODE_NONE;
+
+ if ((chip->lps_deep_mode_supported & BIT(LPS_DEEP_MODE_PG)) &&
+ (fw->feature & FW_FEATURE_PG))
+ return LPS_DEEP_MODE_PG;
+
+ if ((chip->lps_deep_mode_supported & BIT(LPS_DEEP_MODE_LCLK)) &&
+ (fw->feature & FW_FEATURE_LCLK))
+ return LPS_DEEP_MODE_LCLK;
+
+ return LPS_DEEP_MODE_NONE;
+}
+
static int rtw_power_on(struct rtw_dev *rtwdev)
{
struct rtw_chip_info *chip = rtwdev->chip;
@@ -1097,6 +1117,9 @@ int rtw_core_start(struct rtw_dev *rtwdev)
rtw_sec_enable_sec_engine(rtwdev);
+ rtwdev->lps_conf.deep_mode = rtw_update_lps_deep_mode(rtwdev, &rtwdev->fw);
+ rtwdev->lps_conf.wow_deep_mode = rtw_update_lps_deep_mode(rtwdev, &rtwdev->wow_fw);
+
/* rcr reset after powered on */
rtw_write32(rtwdev, REG_RCR, rtwdev->hal.rcr);
@@ -1657,10 +1680,6 @@ int rtw_core_init(struct rtw_dev *rtwdev)
rtwdev->sec.total_cam_num = 32;
rtwdev->hal.current_channel = 1;
set_bit(RTW_BC_MC_MACID, rtwdev->mac_id_map);
- if (!(BIT(rtw_fw_lps_deep_mode) & chip->lps_deep_mode_supported))
- rtwdev->lps_conf.deep_mode = LPS_DEEP_MODE_NONE;
- else
- rtwdev->lps_conf.deep_mode = rtw_fw_lps_deep_mode;
rtw_stats_init(rtwdev);
@@ -1685,6 +1704,7 @@ int rtw_core_init(struct rtw_dev *rtwdev)
return ret;
}
}
+
return 0;
}
EXPORT_SYMBOL(rtw_core_init);
@@ -37,7 +37,7 @@
#define RTW_TP_SHIFT 18 /* bytes/2s --> Mbps */
extern bool rtw_bf_support;
-extern unsigned int rtw_fw_lps_deep_mode;
+extern bool rtw_disable_lps_deep_mode;
extern unsigned int rtw_debug_mask;
extern const struct ieee80211_ops rtw_ops;
@@ -664,6 +664,7 @@ enum rtw_pwr_state {
struct rtw_lps_conf {
enum rtw_lps_mode mode;
enum rtw_lps_deep_mode deep_mode;
+ enum rtw_lps_deep_mode wow_deep_mode;
enum rtw_pwr_state state;
u8 awake_interval;
u8 rlbm;
@@ -77,7 +77,7 @@ void rtw_power_mode_change(struct rtw_dev *rtwdev, bool enter)
request ^= request | BIT_RPWM_TOGGLE;
if (enter) {
request |= POWER_MODE_LCLK;
- if (rtw_fw_lps_deep_mode == LPS_DEEP_MODE_PG)
+ if (rtw_get_lps_deep_mode(rtwdev) == LPS_DEEP_MODE_PG)
request |= POWER_MODE_PG;
}
/* Each request require an ack from firmware */
@@ -195,9 +195,17 @@ static void rtw_leave_lps_core(struct rtw_dev *rtwdev)
rtw_coex_lps_notify(rtwdev, COEX_LPS_DISABLE);
}
+enum rtw_lps_deep_mode rtw_get_lps_deep_mode(struct rtw_dev *rtwdev)
+{
+ if (test_bit(RTW_FLAG_WOWLAN, rtwdev->flags))
+ return rtwdev->lps_conf.wow_deep_mode;
+ else
+ return rtwdev->lps_conf.deep_mode;
+}
+
static void __rtw_enter_lps_deep(struct rtw_dev *rtwdev)
{
- if (rtwdev->lps_conf.deep_mode == LPS_DEEP_MODE_NONE)
+ if (rtw_get_lps_deep_mode(rtwdev) == LPS_DEEP_MODE_NONE)
return;
if (!test_bit(RTW_FLAG_LEISURE_PS, rtwdev->flags)) {
@@ -206,7 +214,7 @@ static void __rtw_enter_lps_deep(struct rtw_dev *rtwdev)
return;
}
- if (rtw_fw_lps_deep_mode == LPS_DEEP_MODE_PG)
+ if (rtw_get_lps_deep_mode(rtwdev) == LPS_DEEP_MODE_PG)
rtw_fw_set_pg_info(rtwdev);
rtw_hci_deep_ps(rtwdev, true);
@@ -21,5 +21,5 @@ void rtw_power_mode_change(struct rtw_dev *rtwdev, bool enter);
void rtw_enter_lps(struct rtw_dev *rtwdev, u8 port_id);
void rtw_leave_lps(struct rtw_dev *rtwdev);
void rtw_leave_lps_deep(struct rtw_dev *rtwdev);
-
+enum rtw_lps_deep_mode rtw_get_lps_deep_mode(struct rtw_dev *rtwdev);
#endif
@@ -555,7 +555,7 @@ static int rtw_wow_leave_no_link_ps(struct rtw_dev *rtwdev)
int ret = 0;
if (test_bit(RTW_FLAG_WOWLAN, rtwdev->flags)) {
- if (rtw_fw_lps_deep_mode)
+ if (rtw_get_lps_deep_mode(rtwdev) != LPS_DEEP_MODE_NONE)
rtw_leave_lps_deep(rtwdev);
} else {
if (test_bit(RTW_FLAG_INACTIVE_PS, rtwdev->flags)) {
@@ -616,7 +616,8 @@ static int rtw_wow_enter_ps(struct rtw_dev *rtwdev)
if (rtw_wow_mgd_linked(rtwdev))
ret = rtw_wow_enter_linked_ps(rtwdev);
- else if (rtw_wow_no_link(rtwdev) && rtw_fw_lps_deep_mode)
+ else if (rtw_wow_no_link(rtwdev) &&
+ rtw_get_lps_deep_mode(rtwdev) != LPS_DEEP_MODE_NONE)
ret = rtw_wow_enter_no_link_ps(rtwdev);
return ret;