From e99dd80c8a183561de891a2cceb5a2bbcf64c88f Mon Sep 17 00:00:00 2001 From: Chin-Yen Lee Date: Mon, 5 Aug 2024 17:00:27 +0800 Subject: [PATCH] wifi: rtw89: wow: add delay option for net-detect The delay option is the period in unit of second for WoWLAN firmware to wait before the first scan. We get the option from cfg80211 and practice it. Another, in some platform, WoWLAN firmware may found configured network and then trigger resume process, before suspend process is completed, lead to the wakeup function failed. So the default value is set one to avoid the issue. Signed-off-by: Chin-Yen Lee Signed-off-by: Ping-Ke Shih Link: https://patch.msgid.link/20240805090028.27768-5-pkshih@realtek.com --- drivers/net/wireless/realtek/rtw89/core.h | 1 + drivers/net/wireless/realtek/rtw89/fw.c | 24 ++++++++++++++++++++--- drivers/net/wireless/realtek/rtw89/fw.h | 3 +++ drivers/net/wireless/realtek/rtw89/wow.c | 2 ++ 4 files changed, 27 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h index f40475a94d11..b42a33b9868a 100644 --- a/drivers/net/wireless/realtek/rtw89/core.h +++ b/drivers/net/wireless/realtek/rtw89/core.h @@ -3677,6 +3677,7 @@ struct rtw89_scan_option { u16 slow_pd; u16 norm_cy; u8 opch_end; + u16 delay; u64 prohib_chan; enum rtw89_phy_idx band; enum rtw89_scan_be_operation operation; diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c index 2a55f47a0ac8..47aa365991c1 100644 --- a/drivers/net/wireless/realtek/rtw89/fw.c +++ b/drivers/net/wireless/realtek/rtw89/fw.c @@ -4808,6 +4808,7 @@ int rtw89_fw_h2c_scan_list_offload_be(struct rtw89_dev *rtwdev, int ch_num, return 0; } +#define RTW89_SCAN_DELAY_TSF_UNIT 104800 int rtw89_fw_h2c_scan_offload_ax(struct rtw89_dev *rtwdev, struct rtw89_scan_option *option, struct rtw89_vif *rtwvif, @@ -4815,10 +4816,12 @@ int rtw89_fw_h2c_scan_offload_ax(struct rtw89_dev *rtwdev, { struct rtw89_wait_info *wait = &rtwdev->mac.fw_ofld_wait; struct rtw89_chan *op = &rtwdev->scan_info.op_chan; + enum rtw89_scan_mode scan_mode = RTW89_SCAN_IMMEDIATE; struct rtw89_h2c_scanofld *h2c; u32 len = sizeof(*h2c); struct sk_buff *skb; unsigned int cond; + u64 tsf = 0; int ret; skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len); @@ -4829,6 +4832,17 @@ int rtw89_fw_h2c_scan_offload_ax(struct rtw89_dev *rtwdev, skb_put(skb, len); h2c = (struct rtw89_h2c_scanofld *)skb->data; + if (option->delay) { + ret = rtw89_mac_port_get_tsf(rtwdev, rtwvif, &tsf); + if (ret) { + rtw89_warn(rtwdev, "NLO failed to get port tsf: %d\n", ret); + scan_mode = RTW89_SCAN_IMMEDIATE; + } else { + scan_mode = RTW89_SCAN_DELAY; + tsf += option->delay * RTW89_SCAN_DELAY_TSF_UNIT; + } + } + h2c->w0 = le32_encode_bits(rtwvif->mac_id, RTW89_H2C_SCANOFLD_W0_MACID) | le32_encode_bits(rtwvif->port, RTW89_H2C_SCANOFLD_W0_PORT_ID) | le32_encode_bits(RTW89_PHY_0, RTW89_H2C_SCANOFLD_W0_BAND) | @@ -4837,8 +4851,7 @@ int rtw89_fw_h2c_scan_offload_ax(struct rtw89_dev *rtwdev, h2c->w1 = le32_encode_bits(true, RTW89_H2C_SCANOFLD_W1_NOTIFY_END) | le32_encode_bits(option->target_ch_mode, RTW89_H2C_SCANOFLD_W1_TARGET_CH_MODE) | - le32_encode_bits(RTW89_SCAN_IMMEDIATE, - RTW89_H2C_SCANOFLD_W1_START_MODE) | + le32_encode_bits(scan_mode, RTW89_H2C_SCANOFLD_W1_START_MODE) | le32_encode_bits(option->repeat, RTW89_H2C_SCANOFLD_W1_SCAN_TYPE); h2c->w2 = le32_encode_bits(option->norm_pd, RTW89_H2C_SCANOFLD_W2_NORM_PD) | @@ -4855,6 +4868,11 @@ int rtw89_fw_h2c_scan_offload_ax(struct rtw89_dev *rtwdev, RTW89_H2C_SCANOFLD_W0_TARGET_CH_BAND); } + h2c->tsf_high = le32_encode_bits(upper_32_bits(tsf), + RTW89_H2C_SCANOFLD_W3_TSF_HIGH); + h2c->tsf_low = le32_encode_bits(lower_32_bits(tsf), + RTW89_H2C_SCANOFLD_W4_TSF_LOW); + rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C, H2C_CAT_MAC, H2C_CL_MAC_FW_OFLD, H2C_FUNC_SCANOFLD, 1, 1, @@ -4972,7 +4990,7 @@ int rtw89_fw_h2c_scan_offload_be(struct rtw89_dev *rtwdev, RTW89_H2C_SCANOFLD_BE_W4_PROBE_5G) | le32_encode_bits(probe_id[NL80211_BAND_6GHZ], RTW89_H2C_SCANOFLD_BE_W4_PROBE_6G) | - le32_encode_bits(0, RTW89_H2C_SCANOFLD_BE_W4_DELAY_START); + le32_encode_bits(option->delay, RTW89_H2C_SCANOFLD_BE_W4_DELAY_START); h2c->w5 = le32_encode_bits(option->mlo_mode, RTW89_H2C_SCANOFLD_BE_W5_MLO_MODE); diff --git a/drivers/net/wireless/realtek/rtw89/fw.h b/drivers/net/wireless/realtek/rtw89/fw.h index d45355e5b2e8..663eda5d0452 100644 --- a/drivers/net/wireless/realtek/rtw89/fw.h +++ b/drivers/net/wireless/realtek/rtw89/fw.h @@ -2107,6 +2107,7 @@ enum rtw89_btc_cxdrvinfo { enum rtw89_scan_mode { RTW89_SCAN_IMMEDIATE, + RTW89_SCAN_DELAY, }; enum rtw89_scan_type { @@ -2686,6 +2687,8 @@ struct rtw89_h2c_scanofld { #define RTW89_H2C_SCANOFLD_W1_PROBE_REQ_PKT_ID GENMASK(31, 24) #define RTW89_H2C_SCANOFLD_W2_NORM_PD GENMASK(15, 0) #define RTW89_H2C_SCANOFLD_W2_SLOW_PD GENMASK(23, 16) +#define RTW89_H2C_SCANOFLD_W3_TSF_HIGH GENMASK(31, 0) +#define RTW89_H2C_SCANOFLD_W4_TSF_LOW GENMASK(31, 0) struct rtw89_h2c_scanofld_be_macc_role { __le32 w0; diff --git a/drivers/net/wireless/realtek/rtw89/wow.c b/drivers/net/wireless/realtek/rtw89/wow.c index 3bf563998ddf..0f0f4beec4d9 100644 --- a/drivers/net/wireless/realtek/rtw89/wow.c +++ b/drivers/net/wireless/realtek/rtw89/wow.c @@ -1458,6 +1458,8 @@ static int rtw89_pno_scan_offload(struct rtw89_dev *rtwdev, bool enable) opt.enable = enable; opt.repeat = RTW89_SCAN_NORMAL; opt.norm_pd = 10; /* in unit of 100ms */ + opt.delay = max(rtw_wow->nd_config->delay, 1); + if (rtwdev->chip->chip_gen == RTW89_CHIP_BE) { opt.operation = enable ? RTW89_SCAN_OP_START : RTW89_SCAN_OP_STOP; opt.scan_mode = RTW89_SCAN_MODE_SA;