Commit 0c546fb6 authored by Luca Coelho's avatar Luca Coelho

iwlwifi: mvm: support v2 of the WoWLAN patterns command

Add new definitions for the WoWLAN patterns API version 2 and support
for version 2 of the WoWLAN patterns command without implementing the
new features.  With this commit we only supporting the existing
bitmask pattern match.  Use the new version only if the TLV is set.
Signed-off-by: default avatarLuca Coelho <luciano.coelho@intel.com>
parent 30f24eab
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* Copyright(c) 2015 - 2017 Intel Deutschland GmbH * Copyright(c) 2015 - 2017 Intel Deutschland GmbH
* Copyright(c) 2018 Intel Corporation * Copyright(c) 2018 - 2019 Intel Corporation
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as * it under the terms of version 2 of the GNU General Public License as
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* Copyright(c) 2015 - 2017 Intel Deutschland GmbH * Copyright(c) 2015 - 2017 Intel Deutschland GmbH
* Copyright(c) 2018 Intel Corporation * Copyright(c) 2018 - 2019 Intel Corporation
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
...@@ -214,7 +214,7 @@ struct iwl_proto_offload_cmd_v3_large { ...@@ -214,7 +214,7 @@ struct iwl_proto_offload_cmd_v3_large {
#define IWL_WOWLAN_MIN_PATTERN_LEN 16 #define IWL_WOWLAN_MIN_PATTERN_LEN 16
#define IWL_WOWLAN_MAX_PATTERN_LEN 128 #define IWL_WOWLAN_MAX_PATTERN_LEN 128
struct iwl_wowlan_pattern { struct iwl_wowlan_pattern_v1 {
u8 mask[IWL_WOWLAN_MAX_PATTERN_LEN / 8]; u8 mask[IWL_WOWLAN_MAX_PATTERN_LEN / 8];
u8 pattern[IWL_WOWLAN_MAX_PATTERN_LEN]; u8 pattern[IWL_WOWLAN_MAX_PATTERN_LEN];
u8 mask_size; u8 mask_size;
...@@ -227,7 +227,7 @@ struct iwl_wowlan_pattern { ...@@ -227,7 +227,7 @@ struct iwl_wowlan_pattern {
/** /**
* struct iwl_wowlan_patterns_cmd - WoWLAN wakeup patterns * struct iwl_wowlan_patterns_cmd - WoWLAN wakeup patterns
*/ */
struct iwl_wowlan_patterns_cmd { struct iwl_wowlan_patterns_cmd_v1 {
/** /**
* @n_patterns: number of patterns * @n_patterns: number of patterns
*/ */
...@@ -236,9 +236,129 @@ struct iwl_wowlan_patterns_cmd { ...@@ -236,9 +236,129 @@ struct iwl_wowlan_patterns_cmd {
/** /**
* @patterns: the patterns, array length in @n_patterns * @patterns: the patterns, array length in @n_patterns
*/ */
struct iwl_wowlan_pattern patterns[]; struct iwl_wowlan_pattern_v1 patterns[];
} __packed; /* WOWLAN_PATTERN_ARRAY_API_S_VER_1 */ } __packed; /* WOWLAN_PATTERN_ARRAY_API_S_VER_1 */
#define IPV4_ADDR_SIZE 4
#define IPV6_ADDR_SIZE 16
enum iwl_wowlan_pattern_type {
WOWLAN_PATTERN_TYPE_BITMASK,
WOWLAN_PATTERN_TYPE_IPV4_TCP_SYN,
WOWLAN_PATTERN_TYPE_IPV6_TCP_SYN,
WOWLAN_PATTERN_TYPE_IPV4_TCP_SYN_WILDCARD,
WOWLAN_PATTERN_TYPE_IPV6_TCP_SYN_WILDCARD,
}; /* WOWLAN_PATTERN_TYPE_API_E_VER_1 */
/**
* struct iwl_wowlan_ipv4_tcp_syn - WoWLAN IPv4 TCP SYN pattern data
*/
struct iwl_wowlan_ipv4_tcp_syn {
/**
* @src_addr: source IP address to match
*/
u8 src_addr[IPV4_ADDR_SIZE];
/**
* @dst_addr: destination IP address to match
*/
u8 dst_addr[IPV4_ADDR_SIZE];
/**
* @src_port: source TCP port to match
*/
__le16 src_port;
/**
* @dst_port: destination TCP port to match
*/
__le16 dst_port;
} __packed; /* WOWLAN_IPV4_TCP_SYN_API_S_VER_1 */
/**
* struct iwl_wowlan_ipv6_tcp_syn - WoWLAN Ipv6 TCP SYN pattern data
*/
struct iwl_wowlan_ipv6_tcp_syn {
/**
* @src_addr: source IP address to match
*/
u8 src_addr[IPV6_ADDR_SIZE];
/**
* @dst_addr: destination IP address to match
*/
u8 dst_addr[IPV6_ADDR_SIZE];
/**
* @src_port: source TCP port to match
*/
__le16 src_port;
/**
* @dst_port: destination TCP port to match
*/
__le16 dst_port;
} __packed; /* WOWLAN_IPV6_TCP_SYN_API_S_VER_1 */
/**
* union iwl_wowlan_pattern_data - Data for the different pattern types
*
* If wildcard addresses/ports are to be used, the union can be left
* undefined.
*/
union iwl_wowlan_pattern_data {
/**
* @bitmask: bitmask pattern data
*/
struct iwl_wowlan_pattern_v1 bitmask;
/**
* @ipv4_tcp_syn: IPv4 TCP SYN pattern data
*/
struct iwl_wowlan_ipv4_tcp_syn ipv4_tcp_syn;
/**
* @ipv6_tcp_syn: IPv6 TCP SYN pattern data
*/
struct iwl_wowlan_ipv6_tcp_syn ipv6_tcp_syn;
}; /* WOWLAN_PATTERN_API_U_VER_1 */
/**
* struct iwl_wowlan_pattern_v2 - Pattern entry for the WoWLAN wakeup patterns
*/
struct iwl_wowlan_pattern_v2 {
/**
* @pattern_type: defines the struct type to be used in the union
*/
u8 pattern_type;
/**
* @reserved: reserved for alignment
*/
u8 reserved[3];
/**
* @u: the union containing the match data, or undefined for
* wildcard matches
*/
union iwl_wowlan_pattern_data u;
} __packed; /* WOWLAN_PATTERN_API_S_VER_2 */
/**
* struct iwl_wowlan_patterns_cmd - WoWLAN wakeup patterns command
*/
struct iwl_wowlan_patterns_cmd {
/**
* @n_patterns: number of patterns
*/
__le32 n_patterns;
/**
* @patterns: the patterns, array length in @n_patterns
*/
struct iwl_wowlan_pattern_v2 patterns[];
} __packed; /* WOWLAN_PATTERN_ARRAY_API_S_VER_2 */
enum iwl_wowlan_wakeup_filters { enum iwl_wowlan_wakeup_filters {
IWL_WOWLAN_WAKEUP_MAGIC_PACKET = BIT(0), IWL_WOWLAN_WAKEUP_MAGIC_PACKET = BIT(0),
IWL_WOWLAN_WAKEUP_PATTERN_MATCH = BIT(1), IWL_WOWLAN_WAKEUP_PATTERN_MATCH = BIT(1),
...@@ -383,7 +503,11 @@ enum iwl_wowlan_wakeup_reason { ...@@ -383,7 +503,11 @@ enum iwl_wowlan_wakeup_reason {
IWL_WOWLAN_WAKEUP_BY_D3_WAKEUP_HOST_TIMER = BIT(14), IWL_WOWLAN_WAKEUP_BY_D3_WAKEUP_HOST_TIMER = BIT(14),
IWL_WOWLAN_WAKEUP_BY_RXFRAME_FILTERED_IN = BIT(15), IWL_WOWLAN_WAKEUP_BY_RXFRAME_FILTERED_IN = BIT(15),
IWL_WOWLAN_WAKEUP_BY_BEACON_FILTERED_IN = BIT(16), IWL_WOWLAN_WAKEUP_BY_BEACON_FILTERED_IN = BIT(16),
IWL_WAKEUP_BY_11W_UNPROTECTED_DEAUTH_OR_DISASSOC = BIT(17),
IWL_WAKEUP_BY_PATTERN_IPV4_TCP_SYN = BIT(18),
IWL_WAKEUP_BY_PATTERN_IPV4_TCP_SYN_WILDCARD = BIT(19),
IWL_WAKEUP_BY_PATTERN_IPV6_TCP_SYN = BIT(20),
IWL_WAKEUP_BY_PATTERN_IPV6_TCP_SYN_WILDCARD = BIT(21),
}; /* WOWLAN_WAKE_UP_REASON_API_E_VER_2 */ }; /* WOWLAN_WAKE_UP_REASON_API_E_VER_2 */
struct iwl_wowlan_gtk_status_v1 { struct iwl_wowlan_gtk_status_v1 {
......
...@@ -311,6 +311,7 @@ enum iwl_ucode_tlv_api { ...@@ -311,6 +311,7 @@ enum iwl_ucode_tlv_api {
IWL_UCODE_TLV_API_FTM_NEW_RANGE_REQ = (__force iwl_ucode_tlv_api_t)49, IWL_UCODE_TLV_API_FTM_NEW_RANGE_REQ = (__force iwl_ucode_tlv_api_t)49,
IWL_UCODE_TLV_API_SCAN_OFFLOAD_CHANS = (__force iwl_ucode_tlv_api_t)50, IWL_UCODE_TLV_API_SCAN_OFFLOAD_CHANS = (__force iwl_ucode_tlv_api_t)50,
IWL_UCODE_TLV_API_MBSSID_HE = (__force iwl_ucode_tlv_api_t)52, IWL_UCODE_TLV_API_MBSSID_HE = (__force iwl_ucode_tlv_api_t)52,
IWL_UCODE_TLV_API_WOWLAN_TCP_SYN_WAKE = (__force iwl_ucode_tlv_api_t)53,
IWL_UCODE_TLV_API_FTM_RTT_ACCURACY = (__force iwl_ucode_tlv_api_t)54, IWL_UCODE_TLV_API_FTM_RTT_ACCURACY = (__force iwl_ucode_tlv_api_t)54,
NUM_IWL_UCODE_TLV_API NUM_IWL_UCODE_TLV_API
......
...@@ -385,10 +385,10 @@ static void iwl_mvm_wowlan_program_keys(struct ieee80211_hw *hw, ...@@ -385,10 +385,10 @@ static void iwl_mvm_wowlan_program_keys(struct ieee80211_hw *hw,
} }
} }
static int iwl_mvm_send_patterns(struct iwl_mvm *mvm, static int iwl_mvm_send_patterns_v1(struct iwl_mvm *mvm,
struct cfg80211_wowlan *wowlan) struct cfg80211_wowlan *wowlan)
{ {
struct iwl_wowlan_patterns_cmd *pattern_cmd; struct iwl_wowlan_patterns_cmd_v1 *pattern_cmd;
struct iwl_host_cmd cmd = { struct iwl_host_cmd cmd = {
.id = WOWLAN_PATTERNS, .id = WOWLAN_PATTERNS,
.dataflags[0] = IWL_HCMD_DFL_NOCOPY, .dataflags[0] = IWL_HCMD_DFL_NOCOPY,
...@@ -399,7 +399,7 @@ static int iwl_mvm_send_patterns(struct iwl_mvm *mvm, ...@@ -399,7 +399,7 @@ static int iwl_mvm_send_patterns(struct iwl_mvm *mvm,
return 0; return 0;
cmd.len[0] = sizeof(*pattern_cmd) + cmd.len[0] = sizeof(*pattern_cmd) +
wowlan->n_patterns * sizeof(struct iwl_wowlan_pattern); wowlan->n_patterns * sizeof(struct iwl_wowlan_pattern_v1);
pattern_cmd = kmalloc(cmd.len[0], GFP_KERNEL); pattern_cmd = kmalloc(cmd.len[0], GFP_KERNEL);
if (!pattern_cmd) if (!pattern_cmd)
...@@ -426,6 +426,50 @@ static int iwl_mvm_send_patterns(struct iwl_mvm *mvm, ...@@ -426,6 +426,50 @@ static int iwl_mvm_send_patterns(struct iwl_mvm *mvm,
return err; return err;
} }
static int iwl_mvm_send_patterns(struct iwl_mvm *mvm,
struct cfg80211_wowlan *wowlan)
{
struct iwl_wowlan_patterns_cmd *pattern_cmd;
struct iwl_host_cmd cmd = {
.id = WOWLAN_PATTERNS,
.dataflags[0] = IWL_HCMD_DFL_NOCOPY,
};
int i, err;
if (!wowlan->n_patterns)
return 0;
cmd.len[0] = sizeof(*pattern_cmd) +
wowlan->n_patterns * sizeof(struct iwl_wowlan_pattern_v2);
pattern_cmd = kmalloc(cmd.len[0], GFP_KERNEL);
if (!pattern_cmd)
return -ENOMEM;
pattern_cmd->n_patterns = cpu_to_le32(wowlan->n_patterns);
for (i = 0; i < wowlan->n_patterns; i++) {
int mask_len = DIV_ROUND_UP(wowlan->patterns[i].pattern_len, 8);
pattern_cmd->patterns[i].pattern_type =
WOWLAN_PATTERN_TYPE_BITMASK;
memcpy(&pattern_cmd->patterns[i].u.bitmask.mask,
wowlan->patterns[i].mask, mask_len);
memcpy(&pattern_cmd->patterns[i].u.bitmask.pattern,
wowlan->patterns[i].pattern,
wowlan->patterns[i].pattern_len);
pattern_cmd->patterns[i].u.bitmask.mask_size = mask_len;
pattern_cmd->patterns[i].u.bitmask.pattern_size =
wowlan->patterns[i].pattern_len;
}
cmd.data[0] = pattern_cmd;
err = iwl_mvm_send_cmd(mvm, &cmd);
kfree(pattern_cmd);
return err;
}
static int iwl_mvm_d3_reprogram(struct iwl_mvm *mvm, struct ieee80211_vif *vif, static int iwl_mvm_d3_reprogram(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
struct ieee80211_sta *ap_sta) struct ieee80211_sta *ap_sta)
{ {
...@@ -851,7 +895,11 @@ iwl_mvm_wowlan_config(struct iwl_mvm *mvm, ...@@ -851,7 +895,11 @@ iwl_mvm_wowlan_config(struct iwl_mvm *mvm,
if (ret) if (ret)
return ret; return ret;
if (fw_has_api(&mvm->fw->ucode_capa,
IWL_UCODE_TLV_API_WOWLAN_TCP_SYN_WAKE))
ret = iwl_mvm_send_patterns(mvm, wowlan); ret = iwl_mvm_send_patterns(mvm, wowlan);
else
ret = iwl_mvm_send_patterns_v1(mvm, wowlan);
if (ret) if (ret)
return ret; return ret;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment