diff options
author | Amitkumar Karwar <akarwar@marvell.com> | 2013-02-12 15:16:26 -0500 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2013-02-13 04:09:48 -0500 |
commit | bb92d19983a4b54be3e3b83441a8076d92cd04bc (patch) | |
tree | e53601fab3727ec69137d67729fdf73414182aba /net/wireless | |
parent | 66d575705154525c33ab99b5f9ac2d246c348db6 (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.c | 74 |
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 |
6900 | static 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 | |||
6898 | static int nl80211_get_wowlan(struct sk_buff *skb, struct genl_info *info) | 6933 | static 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) { |