forked from mirrors/linux
		
	mac80211: add HE 6 GHz Band Capability element
Construct HE 6 GHz band capability element (IEEE 802.11ax/D6.0, 9.4.2.261) for association request and mesh beacon. The 6 GHz capability information is passed by driver through iftypes caps. Signed-off-by: Rajkumar Manoharan <rmanohar@codeaurora.org> Link: https://lore.kernel.org/r/1589399105-25472-7-git-send-email-rmanohar@codeaurora.org [handle SMPS, adjust for previous patches, reserve SKB space properly, change to handle SKB directly] Link: https://lore.kernel.org/r/20200528213443.643aa8101111.I3f9747c1147480f65445f13eda5c4a5ed4e86757@changeid Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
		
							parent
							
								
									2239521772
								
							
						
					
					
						commit
						24a2042cb2
					
				
					 6 changed files with 65 additions and 1 deletions
				
			
		| 
						 | 
					@ -2177,6 +2177,8 @@ u8 ieee80211_ie_len_he_cap(struct ieee80211_sub_if_data *sdata, u8 iftype);
 | 
				
			||||||
u8 *ieee80211_ie_build_he_cap(u8 *pos,
 | 
					u8 *ieee80211_ie_build_he_cap(u8 *pos,
 | 
				
			||||||
			      const struct ieee80211_sta_he_cap *he_cap,
 | 
								      const struct ieee80211_sta_he_cap *he_cap,
 | 
				
			||||||
			      u8 *end);
 | 
								      u8 *end);
 | 
				
			||||||
 | 
					void ieee80211_ie_build_he_6ghz_cap(struct ieee80211_sub_if_data *sdata,
 | 
				
			||||||
 | 
									    struct sk_buff *skb);
 | 
				
			||||||
u8 *ieee80211_ie_build_he_oper(u8 *pos);
 | 
					u8 *ieee80211_ie_build_he_oper(u8 *pos);
 | 
				
			||||||
int ieee80211_parse_bitrates(struct cfg80211_chan_def *chandef,
 | 
					int ieee80211_parse_bitrates(struct cfg80211_chan_def *chandef,
 | 
				
			||||||
			     const struct ieee80211_supported_band *sband,
 | 
								     const struct ieee80211_supported_band *sband,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -587,6 +587,13 @@ int mesh_add_he_oper_ie(struct ieee80211_sub_if_data *sdata,
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int mesh_add_he_6ghz_cap_ie(struct ieee80211_sub_if_data *sdata,
 | 
				
			||||||
 | 
								    struct sk_buff *skb)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						ieee80211_ie_build_he_6ghz_cap(sdata, skb);
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void ieee80211_mesh_path_timer(struct timer_list *t)
 | 
					static void ieee80211_mesh_path_timer(struct timer_list *t)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct ieee80211_sub_if_data *sdata =
 | 
						struct ieee80211_sub_if_data *sdata =
 | 
				
			||||||
| 
						 | 
					@ -766,6 +773,7 @@ ieee80211_mesh_build_beacon(struct ieee80211_if_mesh *ifmsh)
 | 
				
			||||||
		   2 + sizeof(struct ieee80211_vht_operation) +
 | 
							   2 + sizeof(struct ieee80211_vht_operation) +
 | 
				
			||||||
		   ie_len_he_cap +
 | 
							   ie_len_he_cap +
 | 
				
			||||||
		   2 + 1 + sizeof(struct ieee80211_he_operation) +
 | 
							   2 + 1 + sizeof(struct ieee80211_he_operation) +
 | 
				
			||||||
 | 
							   2 + 1 + sizeof(struct ieee80211_he_6ghz_capa) +
 | 
				
			||||||
		   ifmsh->ie_len;
 | 
							   ifmsh->ie_len;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bcn = kzalloc(sizeof(*bcn) + head_len + tail_len, GFP_KERNEL);
 | 
						bcn = kzalloc(sizeof(*bcn) + head_len + tail_len, GFP_KERNEL);
 | 
				
			||||||
| 
						 | 
					@ -885,6 +893,7 @@ ieee80211_mesh_build_beacon(struct ieee80211_if_mesh *ifmsh)
 | 
				
			||||||
	    mesh_add_vht_oper_ie(sdata, skb) ||
 | 
						    mesh_add_vht_oper_ie(sdata, skb) ||
 | 
				
			||||||
	    mesh_add_he_cap_ie(sdata, skb, ie_len_he_cap) ||
 | 
						    mesh_add_he_cap_ie(sdata, skb, ie_len_he_cap) ||
 | 
				
			||||||
	    mesh_add_he_oper_ie(sdata, skb) ||
 | 
						    mesh_add_he_oper_ie(sdata, skb) ||
 | 
				
			||||||
 | 
						    mesh_add_he_6ghz_cap_ie(sdata, skb) ||
 | 
				
			||||||
	    mesh_add_vendor_ies(sdata, skb))
 | 
						    mesh_add_vendor_ies(sdata, skb))
 | 
				
			||||||
		goto out_free;
 | 
							goto out_free;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -222,6 +222,8 @@ int mesh_add_he_cap_ie(struct ieee80211_sub_if_data *sdata,
 | 
				
			||||||
		       struct sk_buff *skb, u8 ie_len);
 | 
							       struct sk_buff *skb, u8 ie_len);
 | 
				
			||||||
int mesh_add_he_oper_ie(struct ieee80211_sub_if_data *sdata,
 | 
					int mesh_add_he_oper_ie(struct ieee80211_sub_if_data *sdata,
 | 
				
			||||||
			struct sk_buff *skb);
 | 
								struct sk_buff *skb);
 | 
				
			||||||
 | 
					int mesh_add_he_6ghz_cap_ie(struct ieee80211_sub_if_data *sdata,
 | 
				
			||||||
 | 
								    struct sk_buff *skb);
 | 
				
			||||||
void mesh_rmc_free(struct ieee80211_sub_if_data *sdata);
 | 
					void mesh_rmc_free(struct ieee80211_sub_if_data *sdata);
 | 
				
			||||||
int mesh_rmc_init(struct ieee80211_sub_if_data *sdata);
 | 
					int mesh_rmc_init(struct ieee80211_sub_if_data *sdata);
 | 
				
			||||||
void ieee80211s_init(void);
 | 
					void ieee80211s_init(void);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -238,6 +238,7 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,
 | 
				
			||||||
			    2 + sizeof(struct ieee80211_vht_operation) +
 | 
								    2 + sizeof(struct ieee80211_vht_operation) +
 | 
				
			||||||
			    ie_len_he_cap +
 | 
								    ie_len_he_cap +
 | 
				
			||||||
			    2 + 1 + sizeof(struct ieee80211_he_operation) +
 | 
								    2 + 1 + sizeof(struct ieee80211_he_operation) +
 | 
				
			||||||
 | 
								    2 + 1 + sizeof(struct ieee80211_he_6ghz_capa) +
 | 
				
			||||||
			    2 + 8 + /* peering IE */
 | 
								    2 + 8 + /* peering IE */
 | 
				
			||||||
			    sdata->u.mesh.ie_len);
 | 
								    sdata->u.mesh.ie_len);
 | 
				
			||||||
	if (!skb)
 | 
						if (!skb)
 | 
				
			||||||
| 
						 | 
					@ -328,7 +329,8 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,
 | 
				
			||||||
		    mesh_add_vht_cap_ie(sdata, skb) ||
 | 
							    mesh_add_vht_cap_ie(sdata, skb) ||
 | 
				
			||||||
		    mesh_add_vht_oper_ie(sdata, skb) ||
 | 
							    mesh_add_vht_oper_ie(sdata, skb) ||
 | 
				
			||||||
		    mesh_add_he_cap_ie(sdata, skb, ie_len_he_cap) ||
 | 
							    mesh_add_he_cap_ie(sdata, skb, ie_len_he_cap) ||
 | 
				
			||||||
		    mesh_add_he_oper_ie(sdata, skb))
 | 
							    mesh_add_he_oper_ie(sdata, skb) ||
 | 
				
			||||||
 | 
							    mesh_add_he_6ghz_cap_ie(sdata, skb))
 | 
				
			||||||
			goto free;
 | 
								goto free;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -658,6 +658,8 @@ static void ieee80211_add_he_ie(struct ieee80211_sub_if_data *sdata,
 | 
				
			||||||
				      he_cap->he_cap_elem.phy_cap_info);
 | 
									      he_cap->he_cap_elem.phy_cap_info);
 | 
				
			||||||
	pos = skb_put(skb, he_cap_size);
 | 
						pos = skb_put(skb, he_cap_size);
 | 
				
			||||||
	ieee80211_ie_build_he_cap(pos, he_cap, pos + he_cap_size);
 | 
						ieee80211_ie_build_he_cap(pos, he_cap, pos + he_cap_size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ieee80211_ie_build_he_6ghz_cap(sdata, skb);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
 | 
					static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
 | 
				
			||||||
| 
						 | 
					@ -731,6 +733,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
 | 
				
			||||||
			2 + 1 + sizeof(struct ieee80211_he_cap_elem) + /* HE */
 | 
								2 + 1 + sizeof(struct ieee80211_he_cap_elem) + /* HE */
 | 
				
			||||||
				sizeof(struct ieee80211_he_mcs_nss_supp) +
 | 
									sizeof(struct ieee80211_he_mcs_nss_supp) +
 | 
				
			||||||
				IEEE80211_HE_PPE_THRES_MAX_LEN +
 | 
									IEEE80211_HE_PPE_THRES_MAX_LEN +
 | 
				
			||||||
 | 
								2 + 1 + sizeof(struct ieee80211_he_6ghz_capa) +
 | 
				
			||||||
			assoc_data->ie_len + /* extra IEs */
 | 
								assoc_data->ie_len + /* extra IEs */
 | 
				
			||||||
			(assoc_data->fils_kek_len ? 16 /* AES-SIV */ : 0) +
 | 
								(assoc_data->fils_kek_len ? 16 /* AES-SIV */ : 0) +
 | 
				
			||||||
			9, /* WMM */
 | 
								9, /* WMM */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2839,6 +2839,52 @@ u8 *ieee80211_ie_build_he_cap(u8 *pos,
 | 
				
			||||||
	return pos;
 | 
						return pos;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ieee80211_ie_build_he_6ghz_cap(struct ieee80211_sub_if_data *sdata,
 | 
				
			||||||
 | 
									    struct sk_buff *skb)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct ieee80211_supported_band *sband;
 | 
				
			||||||
 | 
						const struct ieee80211_sband_iftype_data *iftd;
 | 
				
			||||||
 | 
						enum nl80211_iftype iftype = ieee80211_vif_type_p2p(&sdata->vif);
 | 
				
			||||||
 | 
						u8 *pos;
 | 
				
			||||||
 | 
						u16 cap;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sband = ieee80211_get_sband(sdata);
 | 
				
			||||||
 | 
						if (!sband)
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						iftd = ieee80211_get_sband_iftype_data(sband, iftype);
 | 
				
			||||||
 | 
						if (WARN_ON(!iftd))
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						cap = le16_to_cpu(iftd->he_6ghz_capa.capa);
 | 
				
			||||||
 | 
						cap &= ~IEEE80211_HE_6GHZ_CAP_SM_PS;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch (sdata->smps_mode) {
 | 
				
			||||||
 | 
						case IEEE80211_SMPS_AUTOMATIC:
 | 
				
			||||||
 | 
						case IEEE80211_SMPS_NUM_MODES:
 | 
				
			||||||
 | 
							WARN_ON(1);
 | 
				
			||||||
 | 
							/* fall through */
 | 
				
			||||||
 | 
						case IEEE80211_SMPS_OFF:
 | 
				
			||||||
 | 
							cap |= u16_encode_bits(WLAN_HT_CAP_SM_PS_DISABLED,
 | 
				
			||||||
 | 
									       IEEE80211_HE_6GHZ_CAP_SM_PS);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case IEEE80211_SMPS_STATIC:
 | 
				
			||||||
 | 
							cap |= u16_encode_bits(WLAN_HT_CAP_SM_PS_STATIC,
 | 
				
			||||||
 | 
									       IEEE80211_HE_6GHZ_CAP_SM_PS);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case IEEE80211_SMPS_DYNAMIC:
 | 
				
			||||||
 | 
							cap |= u16_encode_bits(WLAN_HT_CAP_SM_PS_DYNAMIC,
 | 
				
			||||||
 | 
									       IEEE80211_HE_6GHZ_CAP_SM_PS);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pos = skb_put(skb, 2 + 1 + sizeof(cap));
 | 
				
			||||||
 | 
						*pos++ = WLAN_EID_EXTENSION;
 | 
				
			||||||
 | 
						*pos++ = 1 + sizeof(cap);
 | 
				
			||||||
 | 
						*pos++ = WLAN_EID_EXT_HE_6GHZ_CAPA;
 | 
				
			||||||
 | 
						put_unaligned_le16(cap, pos);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
u8 *ieee80211_ie_build_ht_oper(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap,
 | 
					u8 *ieee80211_ie_build_ht_oper(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap,
 | 
				
			||||||
			       const struct cfg80211_chan_def *chandef,
 | 
								       const struct cfg80211_chan_def *chandef,
 | 
				
			||||||
			       u16 prot_mode, bool rifs_mode)
 | 
								       u16 prot_mode, bool rifs_mode)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue