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>
This commit is contained in:
		
							parent
							
								
									66d5757051
								
							
						
					
					
						commit
						bb92d19983
					
				| @ -1576,6 +1576,7 @@ struct cfg80211_pmksa { | ||||
|  *	one bit per byte, in same format as nl80211 | ||||
|  * @pattern: bytes to match where bitmask is 1 | ||||
|  * @pattern_len: length of pattern (in bytes) | ||||
|  * @pkt_offset: packet offset (in bytes) | ||||
|  * | ||||
|  * Internal note: @mask and @pattern are allocated in one chunk of | ||||
|  * memory, free @mask only! | ||||
| @ -1583,6 +1584,7 @@ struct cfg80211_pmksa { | ||||
| struct cfg80211_wowlan_trig_pkt_pattern { | ||||
| 	u8 *mask, *pattern; | ||||
| 	int pattern_len; | ||||
| 	int pkt_offset; | ||||
| }; | ||||
| 
 | ||||
| /**
 | ||||
| @ -2290,12 +2292,14 @@ enum wiphy_wowlan_support_flags { | ||||
|  *	(see nl80211.h for the pattern definition) | ||||
|  * @pattern_max_len: maximum length of each pattern | ||||
|  * @pattern_min_len: minimum length of each pattern | ||||
|  * @max_pkt_offset: maximum Rx packet offset | ||||
|  */ | ||||
| struct wiphy_wowlan_support { | ||||
| 	u32 flags; | ||||
| 	int n_patterns; | ||||
| 	int pattern_max_len; | ||||
| 	int pattern_min_len; | ||||
| 	int max_pkt_offset; | ||||
| }; | ||||
| 
 | ||||
| /**
 | ||||
|  | ||||
| @ -2910,6 +2910,8 @@ enum nl80211_tx_power_setting { | ||||
|  *	Note that the pattern matching is done as though frames were not | ||||
|  *	802.11 frames but 802.3 frames, i.e. the frame is fully unpacked | ||||
|  *	first (including SNAP header unpacking) and then matched. | ||||
|  * @NL80211_WOWLAN_PKTPAT_OFFSET: packet offset, pattern is matched after | ||||
|  *	these fixed number of bytes of received packet | ||||
|  * @NUM_NL80211_WOWLAN_PKTPAT: number of attributes | ||||
|  * @MAX_NL80211_WOWLAN_PKTPAT: max attribute number | ||||
|  */ | ||||
| @ -2917,6 +2919,7 @@ enum nl80211_wowlan_packet_pattern_attr { | ||||
| 	__NL80211_WOWLAN_PKTPAT_INVALID, | ||||
| 	NL80211_WOWLAN_PKTPAT_MASK, | ||||
| 	NL80211_WOWLAN_PKTPAT_PATTERN, | ||||
| 	NL80211_WOWLAN_PKTPAT_OFFSET, | ||||
| 
 | ||||
| 	NUM_NL80211_WOWLAN_PKTPAT, | ||||
| 	MAX_NL80211_WOWLAN_PKTPAT = NUM_NL80211_WOWLAN_PKTPAT - 1, | ||||
| @ -2927,6 +2930,7 @@ enum nl80211_wowlan_packet_pattern_attr { | ||||
|  * @max_patterns: maximum number of patterns supported | ||||
|  * @min_pattern_len: minimum length of each pattern | ||||
|  * @max_pattern_len: maximum length of each pattern | ||||
|  * @max_pkt_offset: maximum Rx packet offset | ||||
|  * | ||||
|  * This struct is carried in %NL80211_WOWLAN_TRIG_PKT_PATTERN when | ||||
|  * that is part of %NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED in the | ||||
| @ -2936,6 +2940,7 @@ struct nl80211_wowlan_pattern_support { | ||||
| 	__u32 max_patterns; | ||||
| 	__u32 min_pattern_len; | ||||
| 	__u32 max_pattern_len; | ||||
| 	__u32 max_pkt_offset; | ||||
| } __attribute__((packed)); | ||||
| 
 | ||||
| /**
 | ||||
| @ -2951,9 +2956,10 @@ struct nl80211_wowlan_pattern_support { | ||||
|  * @NL80211_WOWLAN_TRIG_PKT_PATTERN: wake up on the specified packet patterns | ||||
|  *	which are passed in an array of nested attributes, each nested attribute | ||||
|  *	defining a with attributes from &struct nl80211_wowlan_trig_pkt_pattern. | ||||
|  *	Each pattern defines a wakeup packet. The matching is done on the MSDU, | ||||
|  *	i.e. as though the packet was an 802.3 packet, so the pattern matching | ||||
|  *	is done after the packet is converted to the MSDU. | ||||
|  *	Each pattern defines a wakeup packet. Packet offset is associated with | ||||
|  *	each pattern which is used while matching the pattern. The matching is | ||||
|  *	done on the MSDU, i.e. as though the packet was an 802.3 packet, so the | ||||
|  *	pattern matching is done after the packet is converted to the MSDU. | ||||
|  * | ||||
|  *	In %NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED, it is a binary attribute | ||||
|  *	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 | ||||
| 					dev->wiphy.wowlan.pattern_min_len, | ||||
| 				.max_pattern_len = | ||||
| 					dev->wiphy.wowlan.pattern_max_len, | ||||
| 				.max_pkt_offset = | ||||
| 					dev->wiphy.wowlan.max_pkt_offset, | ||||
| 			}; | ||||
| 			if (nla_put(msg, NL80211_WOWLAN_TRIG_PKT_PATTERN, | ||||
| 				    sizeof(pat), &pat)) | ||||
| @ -6895,6 +6897,39 @@ static int nl80211_leave_mesh(struct sk_buff *skb, struct genl_info *info) | ||||
| } | ||||
| 
 | ||||
| #ifdef CONFIG_PM | ||||
| static int nl80211_send_wowlan_patterns(struct sk_buff *msg, | ||||
| 					struct cfg80211_registered_device *rdev) | ||||
| { | ||||
| 	struct nlattr *nl_pats, *nl_pat; | ||||
| 	int i, pat_len; | ||||
| 
 | ||||
| 	if (!rdev->wowlan->n_patterns) | ||||
| 		return 0; | ||||
| 
 | ||||
| 	nl_pats = nla_nest_start(msg, NL80211_WOWLAN_TRIG_PKT_PATTERN); | ||||
| 	if (!nl_pats) | ||||
| 		return -ENOBUFS; | ||||
| 
 | ||||
| 	for (i = 0; i < rdev->wowlan->n_patterns; i++) { | ||||
| 		nl_pat = nla_nest_start(msg, i + 1); | ||||
| 		if (!nl_pat) | ||||
| 			return -ENOBUFS; | ||||
| 		pat_len = rdev->wowlan->patterns[i].pattern_len; | ||||
| 		if (nla_put(msg, NL80211_WOWLAN_PKTPAT_MASK, | ||||
| 			    DIV_ROUND_UP(pat_len, 8), | ||||
| 			    rdev->wowlan->patterns[i].mask) || | ||||
| 		    nla_put(msg, NL80211_WOWLAN_PKTPAT_PATTERN, | ||||
| 			    pat_len, rdev->wowlan->patterns[i].pattern) || | ||||
| 		    nla_put_u32(msg, NL80211_WOWLAN_PKTPAT_OFFSET, | ||||
| 				rdev->wowlan->patterns[i].pkt_offset)) | ||||
| 			return -ENOBUFS; | ||||
| 		nla_nest_end(msg, nl_pat); | ||||
| 	} | ||||
| 	nla_nest_end(msg, nl_pats); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int nl80211_get_wowlan(struct sk_buff *skb, struct genl_info *info) | ||||
| { | ||||
| 	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) | ||||
| 		    (rdev->wowlan->rfkill_release && | ||||
| 		     nla_put_flag(msg, NL80211_WOWLAN_TRIG_RFKILL_RELEASE))) | ||||
| 			goto nla_put_failure; | ||||
| 		if (rdev->wowlan->n_patterns) { | ||||
| 			struct nlattr *nl_pats, *nl_pat; | ||||
| 			int i, pat_len; | ||||
| 
 | ||||
| 			nl_pats = nla_nest_start(msg, | ||||
| 					NL80211_WOWLAN_TRIG_PKT_PATTERN); | ||||
| 			if (!nl_pats) | ||||
| 				goto nla_put_failure; | ||||
| 
 | ||||
| 			for (i = 0; i < rdev->wowlan->n_patterns; i++) { | ||||
| 				nl_pat = nla_nest_start(msg, i + 1); | ||||
| 				if (!nl_pat) | ||||
| 					goto nla_put_failure; | ||||
| 				pat_len = rdev->wowlan->patterns[i].pattern_len; | ||||
| 				if (nla_put(msg, NL80211_WOWLAN_PKTPAT_MASK, | ||||
| 					    DIV_ROUND_UP(pat_len, 8), | ||||
| 					    rdev->wowlan->patterns[i].mask) || | ||||
| 				    nla_put(msg, NL80211_WOWLAN_PKTPAT_PATTERN, | ||||
| 					    pat_len, | ||||
| 					    rdev->wowlan->patterns[i].pattern)) | ||||
| 					goto nla_put_failure; | ||||
| 				nla_nest_end(msg, nl_pat); | ||||
| 			} | ||||
| 			nla_nest_end(msg, nl_pats); | ||||
| 		} | ||||
| 
 | ||||
| 		if (nl80211_send_wowlan_patterns(msg, rdev)) | ||||
| 			goto nla_put_failure; | ||||
| 		nla_nest_end(msg, nl_wowlan); | ||||
| 	} | ||||
| 
 | ||||
| @ -7046,7 +7057,7 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info) | ||||
| 	if (tb[NL80211_WOWLAN_TRIG_PKT_PATTERN]) { | ||||
| 		struct nlattr *pat; | ||||
| 		int n_patterns = 0; | ||||
| 		int rem, pat_len, mask_len; | ||||
| 		int rem, pat_len, mask_len, pkt_offset; | ||||
| 		struct nlattr *pat_tb[NUM_NL80211_WOWLAN_PKTPAT]; | ||||
| 
 | ||||
| 		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) | ||||
| 			    pat_len < wowlan->pattern_min_len) | ||||
| 				goto error; | ||||
| 
 | ||||
| 			if (!pat_tb[NL80211_WOWLAN_PKTPAT_OFFSET]) | ||||
| 				pkt_offset = 0; | ||||
| 			else | ||||
| 				pkt_offset = nla_get_u32( | ||||
| 					pat_tb[NL80211_WOWLAN_PKTPAT_OFFSET]); | ||||
| 			if (pkt_offset > wowlan->max_pkt_offset) | ||||
| 				goto error; | ||||
| 			new_triggers.patterns[i].pkt_offset = pkt_offset; | ||||
| 
 | ||||
| 			new_triggers.patterns[i].mask = | ||||
| 				kmalloc(mask_len + pat_len, GFP_KERNEL); | ||||
| 			if (!new_triggers.patterns[i].mask) { | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user