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.
Unified · Split
| @@ -1576,6 +1576,7 @@ struct cfg80211_pmksa { · 1575 unmodified lines | |||
| 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 { · 1 unmodified line | |||
| 1583 | struct cfg80211_wowlan_trig_pkt_pattern { | 1584 | struct 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 { · 701 unmodified lines | |||
| 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 | */ |
| 2294 | struct wiphy_wowlan_support { | 2297 | struct 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 | /** |
| @@ -2910,6 +2910,8 @@ enum nl80211_tx_power_setting { · 2909 unmodified lines | |||
| 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 { · 1 unmodified line | |||
| 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 { · 4 unmodified lines | |||
| 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 { · 3 unmodified lines | |||
| 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 { · 9 unmodified lines | |||
| 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. |
| @@ -1238,6 +1238,8 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 portid, u32 seq, int flag · 1237 unmodified lines | |||
| 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) · 5651 unmodified lines | |||
| 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) · 34 unmodified lines | |||
| 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) · 79 unmodified lines | |||
| 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) · 28 unmodified lines | |||
| 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) { |