aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAmitkumar Karwar <akarwar@marvell.com>2013-02-12 15:16:26 -0500
committerJohannes Berg <johannes.berg@intel.com>2013-02-13 04:09:48 -0500
commitbb92d19983a4b54be3e3b83441a8076d92cd04bc (patch)
treee53601fab3727ec69137d67729fdf73414182aba
parent66d575705154525c33ab99b5f9ac2d246c348db6 (diff)
nl80211: add packet offset information for wowlan pattern
If user knows the location of a wowlan pattern to be matched in Rx packet, he can provide an offset with the pattern. This will help drivers to ignore initial bytes and match the pattern efficiently. Signed-off-by: Amitkumar Karwar <akarwar@marvell.com> Signed-off-by: Bing Zhao <bzhao@marvell.com> [refactor pattern sending] Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-rw-r--r--include/net/cfg80211.h4
-rw-r--r--include/uapi/linux/nl80211.h12
-rw-r--r--net/wireless/nl80211.c74
3 files changed, 60 insertions, 30 deletions
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 77686ca28948..d3a73818e44c 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -1576,6 +1576,7 @@ struct cfg80211_pmksa {
1576 * one bit per byte, in same format as nl80211 1576 * one bit per byte, in same format as nl80211
1577 * @pattern: bytes to match where bitmask is 1 1577 * @pattern: bytes to match where bitmask is 1
1578 * @pattern_len: length of pattern (in bytes) 1578 * @pattern_len: length of pattern (in bytes)
1579 * @pkt_offset: packet offset (in bytes)
1579 * 1580 *
1580 * Internal note: @mask and @pattern are allocated in one chunk of 1581 * Internal note: @mask and @pattern are allocated in one chunk of
1581 * memory, free @mask only! 1582 * memory, free @mask only!
@@ -1583,6 +1584,7 @@ struct cfg80211_pmksa {
1583struct cfg80211_wowlan_trig_pkt_pattern { 1584struct cfg80211_wowlan_trig_pkt_pattern {
1584 u8 *mask, *pattern; 1585 u8 *mask, *pattern;
1585 int pattern_len; 1586 int pattern_len;
1587 int pkt_offset;
1586}; 1588};
1587 1589
1588/** 1590/**
@@ -2290,12 +2292,14 @@ enum wiphy_wowlan_support_flags {
2290 * (see nl80211.h for the pattern definition) 2292 * (see nl80211.h for the pattern definition)
2291 * @pattern_max_len: maximum length of each pattern 2293 * @pattern_max_len: maximum length of each pattern
2292 * @pattern_min_len: minimum length of each pattern 2294 * @pattern_min_len: minimum length of each pattern
2295 * @max_pkt_offset: maximum Rx packet offset
2293 */ 2296 */
2294struct wiphy_wowlan_support { 2297struct wiphy_wowlan_support {
2295 u32 flags; 2298 u32 flags;
2296 int n_patterns; 2299 int n_patterns;
2297 int pattern_max_len; 2300 int pattern_max_len;
2298 int pattern_min_len; 2301 int pattern_min_len;
2302 int max_pkt_offset;
2299}; 2303};
2300 2304
2301/** 2305/**
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index b23321154e8b..eb7b32247ec5 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -2910,6 +2910,8 @@ enum nl80211_tx_power_setting {
2910 * Note that the pattern matching is done as though frames were not 2910 * Note that the pattern matching is done as though frames were not
2911 * 802.11 frames but 802.3 frames, i.e. the frame is fully unpacked 2911 * 802.11 frames but 802.3 frames, i.e. the frame is fully unpacked
2912 * first (including SNAP header unpacking) and then matched. 2912 * first (including SNAP header unpacking) and then matched.
2913 * @NL80211_WOWLAN_PKTPAT_OFFSET: packet offset, pattern is matched after
2914 * these fixed number of bytes of received packet
2913 * @NUM_NL80211_WOWLAN_PKTPAT: number of attributes 2915 * @NUM_NL80211_WOWLAN_PKTPAT: number of attributes
2914 * @MAX_NL80211_WOWLAN_PKTPAT: max attribute number 2916 * @MAX_NL80211_WOWLAN_PKTPAT: max attribute number
2915 */ 2917 */
@@ -2917,6 +2919,7 @@ enum nl80211_wowlan_packet_pattern_attr {
2917 __NL80211_WOWLAN_PKTPAT_INVALID, 2919 __NL80211_WOWLAN_PKTPAT_INVALID,
2918 NL80211_WOWLAN_PKTPAT_MASK, 2920 NL80211_WOWLAN_PKTPAT_MASK,
2919 NL80211_WOWLAN_PKTPAT_PATTERN, 2921 NL80211_WOWLAN_PKTPAT_PATTERN,
2922 NL80211_WOWLAN_PKTPAT_OFFSET,
2920 2923
2921 NUM_NL80211_WOWLAN_PKTPAT, 2924 NUM_NL80211_WOWLAN_PKTPAT,
2922 MAX_NL80211_WOWLAN_PKTPAT = NUM_NL80211_WOWLAN_PKTPAT - 1, 2925 MAX_NL80211_WOWLAN_PKTPAT = NUM_NL80211_WOWLAN_PKTPAT - 1,
@@ -2927,6 +2930,7 @@ enum nl80211_wowlan_packet_pattern_attr {
2927 * @max_patterns: maximum number of patterns supported 2930 * @max_patterns: maximum number of patterns supported
2928 * @min_pattern_len: minimum length of each pattern 2931 * @min_pattern_len: minimum length of each pattern
2929 * @max_pattern_len: maximum length of each pattern 2932 * @max_pattern_len: maximum length of each pattern
2933 * @max_pkt_offset: maximum Rx packet offset
2930 * 2934 *
2931 * This struct is carried in %NL80211_WOWLAN_TRIG_PKT_PATTERN when 2935 * This struct is carried in %NL80211_WOWLAN_TRIG_PKT_PATTERN when
2932 * that is part of %NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED in the 2936 * that is part of %NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED in the
@@ -2936,6 +2940,7 @@ struct nl80211_wowlan_pattern_support {
2936 __u32 max_patterns; 2940 __u32 max_patterns;
2937 __u32 min_pattern_len; 2941 __u32 min_pattern_len;
2938 __u32 max_pattern_len; 2942 __u32 max_pattern_len;
2943 __u32 max_pkt_offset;
2939} __attribute__((packed)); 2944} __attribute__((packed));
2940 2945
2941/** 2946/**
@@ -2951,9 +2956,10 @@ struct nl80211_wowlan_pattern_support {
2951 * @NL80211_WOWLAN_TRIG_PKT_PATTERN: wake up on the specified packet patterns 2956 * @NL80211_WOWLAN_TRIG_PKT_PATTERN: wake up on the specified packet patterns
2952 * which are passed in an array of nested attributes, each nested attribute 2957 * which are passed in an array of nested attributes, each nested attribute
2953 * defining a with attributes from &struct nl80211_wowlan_trig_pkt_pattern. 2958 * defining a with attributes from &struct nl80211_wowlan_trig_pkt_pattern.
2954 * Each pattern defines a wakeup packet. The matching is done on the MSDU, 2959 * Each pattern defines a wakeup packet. Packet offset is associated with
2955 * i.e. as though the packet was an 802.3 packet, so the pattern matching 2960 * each pattern which is used while matching the pattern. The matching is
2956 * is done after the packet is converted to the MSDU. 2961 * done on the MSDU, i.e. as though the packet was an 802.3 packet, so the
2962 * pattern matching is done after the packet is converted to the MSDU.
2957 * 2963 *
2958 * In %NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED, it is a binary attribute 2964 * In %NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED, it is a binary attribute
2959 * carrying a &struct nl80211_wowlan_pattern_support. 2965 * carrying a &struct nl80211_wowlan_pattern_support.
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 93bc63eae076..cc0fad30b8c9 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -1238,6 +1238,8 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 portid, u32 seq, int flag
1238 dev->wiphy.wowlan.pattern_min_len, 1238 dev->wiphy.wowlan.pattern_min_len,
1239 .max_pattern_len = 1239 .max_pattern_len =
1240 dev->wiphy.wowlan.pattern_max_len, 1240 dev->wiphy.wowlan.pattern_max_len,
1241 .max_pkt_offset =
1242 dev->wiphy.wowlan.max_pkt_offset,
1241 }; 1243 };
1242 if (nla_put(msg, NL80211_WOWLAN_TRIG_PKT_PATTERN, 1244 if (nla_put(msg, NL80211_WOWLAN_TRIG_PKT_PATTERN,
1243 sizeof(pat), &pat)) 1245 sizeof(pat), &pat))
@@ -6895,6 +6897,39 @@ static int nl80211_leave_mesh(struct sk_buff *skb, struct genl_info *info)
6895} 6897}
6896 6898
6897#ifdef CONFIG_PM 6899#ifdef CONFIG_PM
6900static int nl80211_send_wowlan_patterns(struct sk_buff *msg,
6901 struct cfg80211_registered_device *rdev)
6902{
6903 struct nlattr *nl_pats, *nl_pat;
6904 int i, pat_len;
6905
6906 if (!rdev->wowlan->n_patterns)
6907 return 0;
6908
6909 nl_pats = nla_nest_start(msg, NL80211_WOWLAN_TRIG_PKT_PATTERN);
6910 if (!nl_pats)
6911 return -ENOBUFS;
6912
6913 for (i = 0; i < rdev->wowlan->n_patterns; i++) {
6914 nl_pat = nla_nest_start(msg, i + 1);
6915 if (!nl_pat)
6916 return -ENOBUFS;
6917 pat_len = rdev->wowlan->patterns[i].pattern_len;
6918 if (nla_put(msg, NL80211_WOWLAN_PKTPAT_MASK,
6919 DIV_ROUND_UP(pat_len, 8),
6920 rdev->wowlan->patterns[i].mask) ||
6921 nla_put(msg, NL80211_WOWLAN_PKTPAT_PATTERN,
6922 pat_len, rdev->wowlan->patterns[i].pattern) ||
6923 nla_put_u32(msg, NL80211_WOWLAN_PKTPAT_OFFSET,
6924 rdev->wowlan->patterns[i].pkt_offset))
6925 return -ENOBUFS;
6926 nla_nest_end(msg, nl_pat);
6927 }
6928 nla_nest_end(msg, nl_pats);
6929
6930 return 0;
6931}
6932
6898static int nl80211_get_wowlan(struct sk_buff *skb, struct genl_info *info) 6933static int nl80211_get_wowlan(struct sk_buff *skb, struct genl_info *info)
6899{ 6934{
6900 struct cfg80211_registered_device *rdev = info->user_ptr[0]; 6935 struct cfg80211_registered_device *rdev = info->user_ptr[0];
@@ -6935,32 +6970,8 @@ static int nl80211_get_wowlan(struct sk_buff *skb, struct genl_info *info)
6935 (rdev->wowlan->rfkill_release && 6970 (rdev->wowlan->rfkill_release &&
6936 nla_put_flag(msg, NL80211_WOWLAN_TRIG_RFKILL_RELEASE))) 6971 nla_put_flag(msg, NL80211_WOWLAN_TRIG_RFKILL_RELEASE)))
6937 goto nla_put_failure; 6972 goto nla_put_failure;
6938 if (rdev->wowlan->n_patterns) { 6973 if (nl80211_send_wowlan_patterns(msg, rdev))
6939 struct nlattr *nl_pats, *nl_pat; 6974 goto nla_put_failure;
6940 int i, pat_len;
6941
6942 nl_pats = nla_nest_start(msg,
6943 NL80211_WOWLAN_TRIG_PKT_PATTERN);
6944 if (!nl_pats)
6945 goto nla_put_failure;
6946
6947 for (i = 0; i < rdev->wowlan->n_patterns; i++) {
6948 nl_pat = nla_nest_start(msg, i + 1);
6949 if (!nl_pat)
6950 goto nla_put_failure;
6951 pat_len = rdev->wowlan->patterns[i].pattern_len;
6952 if (nla_put(msg, NL80211_WOWLAN_PKTPAT_MASK,
6953 DIV_ROUND_UP(pat_len, 8),
6954 rdev->wowlan->patterns[i].mask) ||
6955 nla_put(msg, NL80211_WOWLAN_PKTPAT_PATTERN,
6956 pat_len,
6957 rdev->wowlan->patterns[i].pattern))
6958 goto nla_put_failure;
6959 nla_nest_end(msg, nl_pat);
6960 }
6961 nla_nest_end(msg, nl_pats);
6962 }
6963
6964 nla_nest_end(msg, nl_wowlan); 6975 nla_nest_end(msg, nl_wowlan);
6965 } 6976 }
6966 6977
@@ -7046,7 +7057,7 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info)
7046 if (tb[NL80211_WOWLAN_TRIG_PKT_PATTERN]) { 7057 if (tb[NL80211_WOWLAN_TRIG_PKT_PATTERN]) {
7047 struct nlattr *pat; 7058 struct nlattr *pat;
7048 int n_patterns = 0; 7059 int n_patterns = 0;
7049 int rem, pat_len, mask_len; 7060 int rem, pat_len, mask_len, pkt_offset;
7050 struct nlattr *pat_tb[NUM_NL80211_WOWLAN_PKTPAT]; 7061 struct nlattr *pat_tb[NUM_NL80211_WOWLAN_PKTPAT];
7051 7062
7052 nla_for_each_nested(pat, tb[NL80211_WOWLAN_TRIG_PKT_PATTERN], 7063 nla_for_each_nested(pat, tb[NL80211_WOWLAN_TRIG_PKT_PATTERN],
@@ -7081,6 +7092,15 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info)
7081 pat_len < wowlan->pattern_min_len) 7092 pat_len < wowlan->pattern_min_len)
7082 goto error; 7093 goto error;
7083 7094
7095 if (!pat_tb[NL80211_WOWLAN_PKTPAT_OFFSET])
7096 pkt_offset = 0;
7097 else
7098 pkt_offset = nla_get_u32(
7099 pat_tb[NL80211_WOWLAN_PKTPAT_OFFSET]);
7100 if (pkt_offset > wowlan->max_pkt_offset)
7101 goto error;
7102 new_triggers.patterns[i].pkt_offset = pkt_offset;
7103
7084 new_triggers.patterns[i].mask = 7104 new_triggers.patterns[i].mask =
7085 kmalloc(mask_len + pat_len, GFP_KERNEL); 7105 kmalloc(mask_len + pat_len, GFP_KERNEL);
7086 if (!new_triggers.patterns[i].mask) { 7106 if (!new_triggers.patterns[i].mask) {