Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

wifi: rtw89: add related H2C for WoWLAN mode

In this patch we define some H2C, which will be called during suspend
flow, to enable WoWLAN function provided by WoWLAN firmware.

These H2C includes keep alive used to send null packet to AP periodically
to avoid being disconnected by AP, disconnect detection used to configure
how we check if AP is offline, wake up control used to decide which WiFi
events could trigger resume flow, and global control used to enable WoWLAN
function.

Signed-off-by: Chin-Yen Lee <timlee@realtek.com>
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
Signed-off-by: Kalle Valo <kvalo@kernel.org>
Link: https://lore.kernel.org/r/20221027052707.14605-6-pkshih@realtek.com

authored by

Chin-Yen Lee and committed by
Kalle Valo
ee88d748 41d56769

+419
+30
drivers/net/wireless/realtek/rtw89/core.h
··· 477 477 RTW89_REGD_NUM, 478 478 }; 479 479 480 + enum rtw89_fw_pkt_ofld_type { 481 + RTW89_PKT_OFLD_TYPE_PROBE_RSP = 0, 482 + RTW89_PKT_OFLD_TYPE_PS_POLL = 1, 483 + RTW89_PKT_OFLD_TYPE_NULL_DATA = 2, 484 + RTW89_PKT_OFLD_TYPE_QOS_NULL = 3, 485 + RTW89_PKT_OFLD_TYPE_CTS2SELF = 4, 486 + RTW89_PKT_OFLD_TYPE_ARP_RSP = 5, 487 + RTW89_PKT_OFLD_TYPE_NDP = 6, 488 + RTW89_PKT_OFLD_TYPE_EAPOL_KEY = 7, 489 + RTW89_PKT_OFLD_TYPE_SA_QUERY = 8, 490 + RTW89_PKT_OFLD_TYPE_PROBE_REQ = 12, 491 + RTW89_PKT_OFLD_TYPE_NUM, 492 + }; 493 + 480 494 struct rtw89_txpwr_byrate { 481 495 s8 cck[RTW89_RATE_CCK_MAX]; 482 496 s8 ofdm[RTW89_RATE_OFDM_MAX]; ··· 648 634 RTW89_SC_20_LOW3X = 8, 649 635 RTW89_SC_40_UPPER = 9, 650 636 RTW89_SC_40_LOWER = 10, 637 + }; 638 + 639 + enum rtw89_wow_flags { 640 + RTW89_WOW_FLAG_EN_MAGIC_PKT, 641 + RTW89_WOW_FLAG_EN_REKEY_PKT, 642 + RTW89_WOW_FLAG_EN_DISCONNECT, 643 + RTW89_WOW_FLAG_NUM, 651 644 }; 652 645 653 646 struct rtw89_chan { ··· 3474 3453 s8 comp[RF_PATH_MAX][RTW89_SUBBAND_NR]; /* S(8, 0) */ 3475 3454 }; 3476 3455 3456 + struct rtw89_wow_param { 3457 + struct ieee80211_vif *wow_vif; 3458 + DECLARE_BITMAP(flags, RTW89_WOW_FLAG_NUM); 3459 + u8 pattern_cnt; 3460 + struct list_head pkt_list; 3461 + }; 3462 + 3477 3463 struct rtw89_dev { 3478 3464 struct ieee80211_hw *hw; 3479 3465 struct device *dev; ··· 3568 3540 struct rtw89_btc btc; 3569 3541 enum rtw89_ps_mode ps_mode; 3570 3542 bool lps_enabled; 3543 + 3544 + struct rtw89_wow_param wow; 3571 3545 3572 3546 /* napi structure */ 3573 3547 struct net_device netdev;
+229
drivers/net/wireless/realtek/rtw89/fw.c
··· 869 869 return ret; 870 870 } 871 871 872 + static int rtw89_fw_h2c_add_wow_fw_ofld(struct rtw89_dev *rtwdev, 873 + struct rtw89_vif *rtwvif, 874 + enum rtw89_fw_pkt_ofld_type type, 875 + u8 *id) 876 + { 877 + struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); 878 + struct rtw89_wow_param *rtw_wow = &rtwdev->wow; 879 + struct rtw89_pktofld_info *info; 880 + struct sk_buff *skb; 881 + int ret; 882 + 883 + info = kzalloc(sizeof(*info), GFP_KERNEL); 884 + if (!info) 885 + return -ENOMEM; 886 + 887 + switch (type) { 888 + case RTW89_PKT_OFLD_TYPE_PS_POLL: 889 + skb = ieee80211_pspoll_get(rtwdev->hw, vif); 890 + break; 891 + case RTW89_PKT_OFLD_TYPE_PROBE_RSP: 892 + skb = ieee80211_proberesp_get(rtwdev->hw, vif); 893 + break; 894 + case RTW89_PKT_OFLD_TYPE_NULL_DATA: 895 + skb = ieee80211_nullfunc_get(rtwdev->hw, vif, -1, false); 896 + break; 897 + case RTW89_PKT_OFLD_TYPE_QOS_NULL: 898 + skb = ieee80211_nullfunc_get(rtwdev->hw, vif, -1, true); 899 + break; 900 + default: 901 + goto err; 902 + } 903 + 904 + if (!skb) 905 + goto err; 906 + 907 + list_add_tail(&info->list, &rtw_wow->pkt_list); 908 + ret = rtw89_fw_h2c_add_pkt_offload(rtwdev, &info->id, skb); 909 + kfree_skb(skb); 910 + 911 + if (ret) 912 + return ret; 913 + 914 + *id = info->id; 915 + return 0; 916 + 917 + err: 918 + kfree(info); 919 + return -ENOMEM; 920 + } 921 + 872 922 #define H2C_GENERAL_PKT_LEN 6 873 923 #define H2C_GENERAL_PKT_ID_UND 0xff 874 924 int rtw89_fw_h2c_general_pkt(struct rtw89_dev *rtwdev, u8 macid) ··· 2991 2941 2992 2942 fail: 2993 2943 dev_kfree_skb_any(skb); 2944 + return ret; 2945 + } 2946 + 2947 + #define H2C_KEEP_ALIVE_LEN 4 2948 + int rtw89_fw_h2c_keep_alive(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, 2949 + bool enable) 2950 + { 2951 + struct sk_buff *skb; 2952 + u8 pkt_id = 0; 2953 + int ret; 2954 + 2955 + if (enable) { 2956 + ret = rtw89_fw_h2c_add_wow_fw_ofld(rtwdev, rtwvif, 2957 + RTW89_PKT_OFLD_TYPE_NULL_DATA, &pkt_id); 2958 + if (ret) 2959 + return -EPERM; 2960 + } 2961 + 2962 + skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_KEEP_ALIVE_LEN); 2963 + if (!skb) { 2964 + rtw89_err(rtwdev, "failed to alloc skb for keep alive\n"); 2965 + return -ENOMEM; 2966 + } 2967 + 2968 + skb_put(skb, H2C_KEEP_ALIVE_LEN); 2969 + 2970 + RTW89_SET_KEEP_ALIVE_ENABLE(skb->data, enable); 2971 + RTW89_SET_KEEP_ALIVE_PKT_NULL_ID(skb->data, pkt_id); 2972 + RTW89_SET_KEEP_ALIVE_PERIOD(skb->data, 5); 2973 + RTW89_SET_KEEP_ALIVE_MACID(skb->data, rtwvif->mac_id); 2974 + 2975 + rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C, 2976 + H2C_CAT_MAC, 2977 + H2C_CL_MAC_WOW, 2978 + H2C_FUNC_KEEP_ALIVE, 0, 1, 2979 + H2C_KEEP_ALIVE_LEN); 2980 + 2981 + ret = rtw89_h2c_tx(rtwdev, skb, false); 2982 + if (ret) { 2983 + rtw89_err(rtwdev, "failed to send h2c\n"); 2984 + goto fail; 2985 + } 2986 + 2987 + return 0; 2988 + 2989 + fail: 2990 + dev_kfree_skb_any(skb); 2991 + 2992 + return ret; 2993 + } 2994 + 2995 + #define H2C_DISCONNECT_DETECT_LEN 8 2996 + int rtw89_fw_h2c_disconnect_detect(struct rtw89_dev *rtwdev, 2997 + struct rtw89_vif *rtwvif, bool enable) 2998 + { 2999 + struct rtw89_wow_param *rtw_wow = &rtwdev->wow; 3000 + struct sk_buff *skb; 3001 + u8 macid = rtwvif->mac_id; 3002 + int ret; 3003 + 3004 + skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_DISCONNECT_DETECT_LEN); 3005 + if (!skb) { 3006 + rtw89_err(rtwdev, "failed to alloc skb for keep alive\n"); 3007 + return -ENOMEM; 3008 + } 3009 + 3010 + skb_put(skb, H2C_DISCONNECT_DETECT_LEN); 3011 + 3012 + if (test_bit(RTW89_WOW_FLAG_EN_DISCONNECT, rtw_wow->flags)) { 3013 + RTW89_SET_DISCONNECT_DETECT_ENABLE(skb->data, enable); 3014 + RTW89_SET_DISCONNECT_DETECT_DISCONNECT(skb->data, !enable); 3015 + RTW89_SET_DISCONNECT_DETECT_MAC_ID(skb->data, macid); 3016 + RTW89_SET_DISCONNECT_DETECT_CHECK_PERIOD(skb->data, 100); 3017 + RTW89_SET_DISCONNECT_DETECT_TRY_PKT_COUNT(skb->data, 5); 3018 + } 3019 + 3020 + rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C, 3021 + H2C_CAT_MAC, 3022 + H2C_CL_MAC_WOW, 3023 + H2C_FUNC_DISCONNECT_DETECT, 0, 1, 3024 + H2C_DISCONNECT_DETECT_LEN); 3025 + 3026 + ret = rtw89_h2c_tx(rtwdev, skb, false); 3027 + if (ret) { 3028 + rtw89_err(rtwdev, "failed to send h2c\n"); 3029 + goto fail; 3030 + } 3031 + 3032 + return 0; 3033 + 3034 + fail: 3035 + dev_kfree_skb_any(skb); 3036 + 3037 + return ret; 3038 + } 3039 + 3040 + #define H2C_WOW_GLOBAL_LEN 8 3041 + int rtw89_fw_h2c_wow_global(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, 3042 + bool enable) 3043 + { 3044 + struct sk_buff *skb; 3045 + u8 macid = rtwvif->mac_id; 3046 + int ret; 3047 + 3048 + skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_WOW_GLOBAL_LEN); 3049 + if (!skb) { 3050 + rtw89_err(rtwdev, "failed to alloc skb for keep alive\n"); 3051 + return -ENOMEM; 3052 + } 3053 + 3054 + skb_put(skb, H2C_WOW_GLOBAL_LEN); 3055 + 3056 + RTW89_SET_WOW_GLOBAL_ENABLE(skb->data, enable); 3057 + RTW89_SET_WOW_GLOBAL_MAC_ID(skb->data, macid); 3058 + 3059 + rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C, 3060 + H2C_CAT_MAC, 3061 + H2C_CL_MAC_WOW, 3062 + H2C_FUNC_WOW_GLOBAL, 0, 1, 3063 + H2C_WOW_GLOBAL_LEN); 3064 + 3065 + ret = rtw89_h2c_tx(rtwdev, skb, false); 3066 + if (ret) { 3067 + rtw89_err(rtwdev, "failed to send h2c\n"); 3068 + goto fail; 3069 + } 3070 + 3071 + return 0; 3072 + 3073 + fail: 3074 + dev_kfree_skb_any(skb); 3075 + 3076 + return ret; 3077 + } 3078 + 3079 + #define H2C_WAKEUP_CTRL_LEN 4 3080 + int rtw89_fw_h2c_wow_wakeup_ctrl(struct rtw89_dev *rtwdev, 3081 + struct rtw89_vif *rtwvif, 3082 + bool enable) 3083 + { 3084 + struct rtw89_wow_param *rtw_wow = &rtwdev->wow; 3085 + struct sk_buff *skb; 3086 + u8 macid = rtwvif->mac_id; 3087 + int ret; 3088 + 3089 + skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_WAKEUP_CTRL_LEN); 3090 + if (!skb) { 3091 + rtw89_err(rtwdev, "failed to alloc skb for keep alive\n"); 3092 + return -ENOMEM; 3093 + } 3094 + 3095 + skb_put(skb, H2C_WAKEUP_CTRL_LEN); 3096 + 3097 + if (rtw_wow->pattern_cnt) 3098 + RTW89_SET_WOW_WAKEUP_CTRL_PATTERN_MATCH_ENABLE(skb->data, enable); 3099 + if (test_bit(RTW89_WOW_FLAG_EN_MAGIC_PKT, rtw_wow->flags)) 3100 + RTW89_SET_WOW_WAKEUP_CTRL_MAGIC_ENABLE(skb->data, enable); 3101 + if (test_bit(RTW89_WOW_FLAG_EN_DISCONNECT, rtw_wow->flags)) 3102 + RTW89_SET_WOW_WAKEUP_CTRL_DEAUTH_ENABLE(skb->data, enable); 3103 + 3104 + RTW89_SET_WOW_WAKEUP_CTRL_MAC_ID(skb->data, macid); 3105 + 3106 + rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C, 3107 + H2C_CAT_MAC, 3108 + H2C_CL_MAC_WOW, 3109 + H2C_FUNC_WAKEUP_CTRL, 0, 1, 3110 + H2C_WAKEUP_CTRL_LEN); 3111 + 3112 + ret = rtw89_h2c_tx(rtwdev, skb, false); 3113 + if (ret) { 3114 + rtw89_err(rtwdev, "failed to send h2c\n"); 3115 + goto fail; 3116 + } 3117 + 3118 + return 0; 3119 + 3120 + fail: 3121 + dev_kfree_skb_any(skb); 3122 + 2994 3123 return ret; 2995 3124 }
+160
drivers/net/wireless/realtek/rtw89/fw.h
··· 1893 1893 le32p_replace_bits((__le32 *)cmd + 5, val, GENMASK(31, 0)); 1894 1894 } 1895 1895 1896 + static inline void RTW89_SET_KEEP_ALIVE_ENABLE(void *h2c, u32 val) 1897 + { 1898 + le32p_replace_bits((__le32 *)h2c, val, GENMASK(1, 0)); 1899 + } 1900 + 1901 + static inline void RTW89_SET_KEEP_ALIVE_PKT_NULL_ID(void *h2c, u32 val) 1902 + { 1903 + le32p_replace_bits((__le32 *)h2c, val, GENMASK(15, 8)); 1904 + } 1905 + 1906 + static inline void RTW89_SET_KEEP_ALIVE_PERIOD(void *h2c, u32 val) 1907 + { 1908 + le32p_replace_bits((__le32 *)h2c, val, GENMASK(24, 16)); 1909 + } 1910 + 1911 + static inline void RTW89_SET_KEEP_ALIVE_MACID(void *h2c, u32 val) 1912 + { 1913 + le32p_replace_bits((__le32 *)h2c, val, GENMASK(31, 24)); 1914 + } 1915 + 1916 + static inline void RTW89_SET_DISCONNECT_DETECT_ENABLE(void *h2c, u32 val) 1917 + { 1918 + le32p_replace_bits((__le32 *)h2c, val, BIT(0)); 1919 + } 1920 + 1921 + static inline void RTW89_SET_DISCONNECT_DETECT_TRYOK_BCNFAIL_COUNT_EN(void *h2c, u32 val) 1922 + { 1923 + le32p_replace_bits((__le32 *)h2c, val, BIT(1)); 1924 + } 1925 + 1926 + static inline void RTW89_SET_DISCONNECT_DETECT_DISCONNECT(void *h2c, u32 val) 1927 + { 1928 + le32p_replace_bits((__le32 *)h2c, val, BIT(2)); 1929 + } 1930 + 1931 + static inline void RTW89_SET_DISCONNECT_DETECT_MAC_ID(void *h2c, u32 val) 1932 + { 1933 + le32p_replace_bits((__le32 *)h2c, val, GENMASK(15, 8)); 1934 + } 1935 + 1936 + static inline void RTW89_SET_DISCONNECT_DETECT_CHECK_PERIOD(void *h2c, u32 val) 1937 + { 1938 + le32p_replace_bits((__le32 *)h2c, val, GENMASK(23, 16)); 1939 + } 1940 + 1941 + static inline void RTW89_SET_DISCONNECT_DETECT_TRY_PKT_COUNT(void *h2c, u32 val) 1942 + { 1943 + le32p_replace_bits((__le32 *)h2c, val, GENMASK(31, 24)); 1944 + } 1945 + 1946 + static inline void RTW89_SET_DISCONNECT_DETECT_TRYOK_BCNFAIL_COUNT_LIMIT(void *h2c, u32 val) 1947 + { 1948 + le32p_replace_bits((__le32 *)(h2c) + 1, val, GENMASK(7, 0)); 1949 + } 1950 + 1951 + static inline void RTW89_SET_WOW_GLOBAL_ENABLE(void *h2c, u32 val) 1952 + { 1953 + le32p_replace_bits((__le32 *)h2c, val, BIT(0)); 1954 + } 1955 + 1956 + static inline void RTW89_SET_WOW_GLOBAL_DROP_ALL_PKT(void *h2c, u32 val) 1957 + { 1958 + le32p_replace_bits((__le32 *)h2c, val, BIT(1)); 1959 + } 1960 + 1961 + static inline void RTW89_SET_WOW_GLOBAL_RX_PARSE_AFTER_WAKE(void *h2c, u32 val) 1962 + { 1963 + le32p_replace_bits((__le32 *)h2c, val, BIT(2)); 1964 + } 1965 + 1966 + static inline void RTW89_SET_WOW_GLOBAL_WAKE_BAR_PULLED(void *h2c, u32 val) 1967 + { 1968 + le32p_replace_bits((__le32 *)h2c, val, BIT(3)); 1969 + } 1970 + 1971 + static inline void RTW89_SET_WOW_GLOBAL_MAC_ID(void *h2c, u32 val) 1972 + { 1973 + le32p_replace_bits((__le32 *)h2c, val, GENMASK(15, 8)); 1974 + } 1975 + 1976 + static inline void RTW89_SET_WOW_GLOBAL_PAIRWISE_SEC_ALGO(void *h2c, u32 val) 1977 + { 1978 + le32p_replace_bits((__le32 *)h2c, val, GENMASK(23, 16)); 1979 + } 1980 + 1981 + static inline void RTW89_SET_WOW_GLOBAL_GROUP_SEC_ALGO(void *h2c, u32 val) 1982 + { 1983 + le32p_replace_bits((__le32 *)h2c, val, GENMASK(31, 24)); 1984 + } 1985 + 1986 + static inline void RTW89_SET_WOW_GLOBAL_REMOTECTRL_INFO_CONTENT(void *h2c, u32 val) 1987 + { 1988 + le32p_replace_bits((__le32 *)(h2c) + 1, val, GENMASK(31, 0)); 1989 + } 1990 + 1991 + static inline void RTW89_SET_WOW_WAKEUP_CTRL_PATTERN_MATCH_ENABLE(void *h2c, u32 val) 1992 + { 1993 + le32p_replace_bits((__le32 *)h2c, val, BIT(0)); 1994 + } 1995 + 1996 + static inline void RTW89_SET_WOW_WAKEUP_CTRL_MAGIC_ENABLE(void *h2c, u32 val) 1997 + { 1998 + le32p_replace_bits((__le32 *)h2c, val, BIT(1)); 1999 + } 2000 + 2001 + static inline void RTW89_SET_WOW_WAKEUP_CTRL_HW_UNICAST_ENABLE(void *h2c, u32 val) 2002 + { 2003 + le32p_replace_bits((__le32 *)h2c, val, BIT(2)); 2004 + } 2005 + 2006 + static inline void RTW89_SET_WOW_WAKEUP_CTRL_FW_UNICAST_ENABLE(void *h2c, u32 val) 2007 + { 2008 + le32p_replace_bits((__le32 *)h2c, val, BIT(3)); 2009 + } 2010 + 2011 + static inline void RTW89_SET_WOW_WAKEUP_CTRL_DEAUTH_ENABLE(void *h2c, u32 val) 2012 + { 2013 + le32p_replace_bits((__le32 *)h2c, val, BIT(4)); 2014 + } 2015 + 2016 + static inline void RTW89_SET_WOW_WAKEUP_CTRL_REKEYP_ENABLE(void *h2c, u32 val) 2017 + { 2018 + le32p_replace_bits((__le32 *)h2c, val, BIT(5)); 2019 + } 2020 + 2021 + static inline void RTW89_SET_WOW_WAKEUP_CTRL_EAP_ENABLE(void *h2c, u32 val) 2022 + { 2023 + le32p_replace_bits((__le32 *)h2c, val, BIT(6)); 2024 + } 2025 + 2026 + static inline void RTW89_SET_WOW_WAKEUP_CTRL_ALL_DATA_ENABLE(void *h2c, u32 val) 2027 + { 2028 + le32p_replace_bits((__le32 *)h2c, val, BIT(7)); 2029 + } 2030 + 2031 + static inline void RTW89_SET_WOW_WAKEUP_CTRL_MAC_ID(void *h2c, u32 val) 2032 + { 2033 + le32p_replace_bits((__le32 *)h2c, val, GENMASK(31, 24)); 2034 + } 2035 + 1896 2036 enum rtw89_btc_btf_h2c_class { 1897 2037 BTFC_SET = 0x10, 1898 2038 BTFC_GET = 0x11, ··· 2849 2709 #define H2C_FUNC_LOG_CFG 0x0 2850 2710 #define H2C_FUNC_MAC_GENERAL_PKT 0x1 2851 2711 2712 + /* CLASS 1 - WOW */ 2713 + #define H2C_CL_MAC_WOW 0x1 2714 + #define H2C_FUNC_KEEP_ALIVE 0x0 2715 + #define H2C_FUNC_DISCONNECT_DETECT 0x1 2716 + #define H2C_FUNC_WOW_GLOBAL 0x2 2717 + #define H2C_FUNC_WAKEUP_CTRL 0x8 2718 + #define H2C_FUNC_WOW_CAM_UPD 0xC 2719 + 2852 2720 /* CLASS 2 - PS */ 2853 2721 #define H2C_CL_MAC_PS 0x2 2854 2722 #define H2C_FUNC_MAC_LPS_PARM 0x0 ··· 3026 2878 u8 act, u8 noa_id); 3027 2879 int rtw89_fw_h2c_tsf32_toggle(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, 3028 2880 bool en); 2881 + int rtw89_fw_h2c_wow_global(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, 2882 + bool enable); 2883 + int rtw89_fw_h2c_wow_wakeup_ctrl(struct rtw89_dev *rtwdev, 2884 + struct rtw89_vif *rtwvif, bool enable); 2885 + int rtw89_fw_h2c_keep_alive(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, 2886 + bool enable); 2887 + int rtw89_fw_h2c_disconnect_detect(struct rtw89_dev *rtwdev, 2888 + struct rtw89_vif *rtwvif, bool enable); 2889 + int rtw89_fw_h2c_wow_global(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, 2890 + bool enable); 2891 + int rtw89_fw_h2c_wow_wakeup_ctrl(struct rtw89_dev *rtwdev, 2892 + struct rtw89_vif *rtwvif, bool enable); 3029 2893 3030 2894 static inline void rtw89_fw_h2c_init_ba_cam(struct rtw89_dev *rtwdev) 3031 2895 {