aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless
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 /net/wireless
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>
Diffstat (limited to 'net/wireless')
-rw-r--r--net/wireless/nl80211.c74
1 files changed, 47 insertions, 27 deletions
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) {