mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-10 15:58:47 +00:00
wifi: rtw89: wow: implement PS mode for net-detect
When net-detect is enabled, WoWLAN firmware will periodically scan until beacon or probe response of configured networks are received. To reduce power consumption, the FW-IPS mode is implemented to keep WiFi chip in idle mode between each scan. The FW-IPS is controlled by WoWLAN firmware to turn of some critical electrical components, and is different from the original IPS mode which most electrical components are turned off. Signed-off-by: Chin-Yen Lee <timlee@realtek.com> Signed-off-by: Ping-Ke Shih <pkshih@realtek.com> Link: https://patch.msgid.link/20240805090028.27768-3-pkshih@realtek.com
This commit is contained in:
parent
45ae0e8cf8
commit
0f683c2cf6
@ -6856,7 +6856,43 @@ hdr:
|
||||
goto fail;
|
||||
}
|
||||
return 0;
|
||||
fail:
|
||||
dev_kfree_skb_any(skb);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int rtw89_fw_h2c_fwips(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
|
||||
bool enable)
|
||||
{
|
||||
struct rtw89_h2c_fwips *h2c;
|
||||
u32 len = sizeof(*h2c);
|
||||
struct sk_buff *skb;
|
||||
int ret;
|
||||
|
||||
skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len);
|
||||
if (!skb) {
|
||||
rtw89_err(rtwdev, "failed to alloc skb for fw ips\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
skb_put(skb, len);
|
||||
h2c = (struct rtw89_h2c_fwips *)skb->data;
|
||||
|
||||
h2c->w0 = le32_encode_bits(rtwvif->mac_id, RTW89_H2C_FW_IPS_W0_MACID) |
|
||||
le32_encode_bits(enable, RTW89_H2C_FW_IPS_W0_ENABLE);
|
||||
|
||||
rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
|
||||
H2C_CAT_MAC,
|
||||
H2C_CL_MAC_PS,
|
||||
H2C_FUNC_IPS_CFG, 0, 1,
|
||||
len);
|
||||
|
||||
ret = rtw89_h2c_tx(rtwdev, skb, false);
|
||||
if (ret) {
|
||||
rtw89_err(rtwdev, "failed to send h2c\n");
|
||||
goto fail;
|
||||
}
|
||||
return 0;
|
||||
fail:
|
||||
dev_kfree_skb_any(skb);
|
||||
|
||||
|
@ -2748,6 +2748,13 @@ struct rtw89_h2c_scanofld_be {
|
||||
#define RTW89_H2C_SCANOFLD_BE_W9_SIZE_MACC GENMASK(15, 8)
|
||||
#define RTW89_H2C_SCANOFLD_BE_W9_SIZE_OP GENMASK(23, 16)
|
||||
|
||||
struct rtw89_h2c_fwips {
|
||||
__le32 w0;
|
||||
} __packed;
|
||||
|
||||
#define RTW89_H2C_FW_IPS_W0_MACID GENMASK(7, 0)
|
||||
#define RTW89_H2C_FW_IPS_W0_ENABLE BIT(8)
|
||||
|
||||
static inline void RTW89_SET_FWCMD_P2P_MACID(void *cmd, u32 val)
|
||||
{
|
||||
le32p_replace_bits((__le32 *)cmd, val, GENMASK(7, 0));
|
||||
@ -3965,6 +3972,7 @@ enum rtw89_wow_h2c_func {
|
||||
#define H2C_CL_MAC_PS 0x2
|
||||
#define H2C_FUNC_MAC_LPS_PARM 0x0
|
||||
#define H2C_FUNC_P2P_ACT 0x1
|
||||
#define H2C_FUNC_IPS_CFG 0x3
|
||||
|
||||
/* CLASS 3 - FW download */
|
||||
#define H2C_CL_MAC_FWDL 0x3
|
||||
@ -4446,6 +4454,8 @@ int rtw89_fw_h2c_lps_parm(struct rtw89_dev *rtwdev,
|
||||
struct rtw89_lps_parm *lps_param);
|
||||
int rtw89_fw_h2c_lps_ch_info(struct rtw89_dev *rtwdev,
|
||||
struct rtw89_vif *rtwvif);
|
||||
int rtw89_fw_h2c_fwips(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
|
||||
bool enable);
|
||||
struct sk_buff *rtw89_fw_h2c_alloc_skb_with_hdr(struct rtw89_dev *rtwdev, u32 len);
|
||||
struct sk_buff *rtw89_fw_h2c_alloc_skb_no_hdr(struct rtw89_dev *rtwdev, u32 len);
|
||||
int rtw89_fw_msg_reg(struct rtw89_dev *rtwdev,
|
||||
|
@ -687,17 +687,30 @@ static void rtw89_wow_enter_deep_ps(struct rtw89_dev *rtwdev)
|
||||
__rtw89_enter_ps_mode(rtwdev, rtwvif);
|
||||
}
|
||||
|
||||
static void rtw89_wow_enter_lps(struct rtw89_dev *rtwdev)
|
||||
static void rtw89_wow_enter_ps(struct rtw89_dev *rtwdev)
|
||||
{
|
||||
struct ieee80211_vif *wow_vif = rtwdev->wow.wow_vif;
|
||||
struct rtw89_vif *rtwvif = (struct rtw89_vif *)wow_vif->drv_priv;
|
||||
|
||||
rtw89_enter_lps(rtwdev, rtwvif, false);
|
||||
if (rtw89_wow_mgd_linked(rtwdev))
|
||||
rtw89_enter_lps(rtwdev, rtwvif, false);
|
||||
else if (rtw89_wow_no_link(rtwdev))
|
||||
rtw89_fw_h2c_fwips(rtwdev, rtwvif, true);
|
||||
}
|
||||
|
||||
static void rtw89_wow_leave_lps(struct rtw89_dev *rtwdev)
|
||||
static void rtw89_wow_leave_ps(struct rtw89_dev *rtwdev, bool enable_wow)
|
||||
{
|
||||
rtw89_leave_lps(rtwdev);
|
||||
struct ieee80211_vif *wow_vif = rtwdev->wow.wow_vif;
|
||||
struct rtw89_vif *rtwvif = (struct rtw89_vif *)wow_vif->drv_priv;
|
||||
|
||||
if (rtw89_wow_mgd_linked(rtwdev)) {
|
||||
rtw89_leave_lps(rtwdev);
|
||||
} else if (rtw89_wow_no_link(rtwdev)) {
|
||||
if (enable_wow)
|
||||
rtw89_leave_ips(rtwdev);
|
||||
else
|
||||
rtw89_fw_h2c_fwips(rtwdev, rtwvif, false);
|
||||
}
|
||||
}
|
||||
|
||||
static int rtw89_wow_config_mac(struct rtw89_dev *rtwdev, bool enable_wow)
|
||||
@ -1430,7 +1443,7 @@ static int rtw89_wow_enable(struct rtw89_dev *rtwdev)
|
||||
goto out;
|
||||
}
|
||||
|
||||
rtw89_wow_enter_lps(rtwdev);
|
||||
rtw89_wow_enter_ps(rtwdev);
|
||||
|
||||
ret = rtw89_wow_enable_trx_post(rtwdev);
|
||||
if (ret) {
|
||||
@ -1455,7 +1468,7 @@ static int rtw89_wow_disable(struct rtw89_dev *rtwdev)
|
||||
goto out;
|
||||
}
|
||||
|
||||
rtw89_wow_leave_lps(rtwdev);
|
||||
rtw89_wow_leave_ps(rtwdev, false);
|
||||
|
||||
ret = rtw89_wow_fw_stop(rtwdev);
|
||||
if (ret) {
|
||||
@ -1480,6 +1493,12 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void rtw89_wow_restore_ps(struct rtw89_dev *rtwdev)
|
||||
{
|
||||
if (rtw89_wow_no_link(rtwdev))
|
||||
rtw89_enter_ips(rtwdev);
|
||||
}
|
||||
|
||||
int rtw89_wow_resume(struct rtw89_dev *rtwdev)
|
||||
{
|
||||
int ret;
|
||||
@ -1504,6 +1523,7 @@ int rtw89_wow_resume(struct rtw89_dev *rtwdev)
|
||||
if (ret)
|
||||
rtw89_err(rtwdev, "failed to disable wow\n");
|
||||
|
||||
rtw89_wow_restore_ps(rtwdev);
|
||||
out:
|
||||
rtw89_wow_clear_wakeups(rtwdev);
|
||||
return ret;
|
||||
@ -1519,7 +1539,7 @@ int rtw89_wow_suspend(struct rtw89_dev *rtwdev, struct cfg80211_wowlan *wowlan)
|
||||
return ret;
|
||||
}
|
||||
|
||||
rtw89_wow_leave_lps(rtwdev);
|
||||
rtw89_wow_leave_ps(rtwdev, true);
|
||||
|
||||
ret = rtw89_wow_enable(rtwdev);
|
||||
if (ret) {
|
||||
|
@ -95,6 +95,22 @@ static inline int rtw89_wow_get_sec_hdr_len(struct rtw89_dev *rtwdev)
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static inline bool rtw89_wow_mgd_linked(struct rtw89_dev *rtwdev)
|
||||
{
|
||||
struct ieee80211_vif *wow_vif = rtwdev->wow.wow_vif;
|
||||
struct rtw89_vif *rtwvif = (struct rtw89_vif *)wow_vif->drv_priv;
|
||||
|
||||
return rtwvif->net_type == RTW89_NET_TYPE_INFRA;
|
||||
}
|
||||
|
||||
static inline bool rtw89_wow_no_link(struct rtw89_dev *rtwdev)
|
||||
{
|
||||
struct ieee80211_vif *wow_vif = rtwdev->wow.wow_vif;
|
||||
struct rtw89_vif *rtwvif = (struct rtw89_vif *)wow_vif->drv_priv;
|
||||
|
||||
return rtwvif->net_type == RTW89_NET_TYPE_NO_LINK;
|
||||
}
|
||||
|
||||
int rtw89_wow_suspend(struct rtw89_dev *rtwdev, struct cfg80211_wowlan *wowlan);
|
||||
int rtw89_wow_resume(struct rtw89_dev *rtwdev);
|
||||
void rtw89_wow_parse_akm(struct rtw89_dev *rtwdev, struct sk_buff *skb);
|
||||
|
Loading…
x
Reference in New Issue
Block a user