1  // SPDX-License-Identifier: GPL-2.0-only
2  /*
3   * NXP Wireless LAN device driver: AP specific command handling
4   *
5   * Copyright 2011-2020 NXP
6   */
7  
8  #include "main.h"
9  #include "11ac.h"
10  #include "11n.h"
11  
12  /* This function parses security related parameters from cfg80211_ap_settings
13   * and sets into FW understandable bss_config structure.
14   */
mwifiex_set_secure_params(struct mwifiex_private * priv,struct mwifiex_uap_bss_param * bss_config,struct cfg80211_ap_settings * params)15  int mwifiex_set_secure_params(struct mwifiex_private *priv,
16  			      struct mwifiex_uap_bss_param *bss_config,
17  			      struct cfg80211_ap_settings *params) {
18  	int i;
19  	struct mwifiex_wep_key wep_key;
20  
21  	if (!params->privacy) {
22  		bss_config->protocol = PROTOCOL_NO_SECURITY;
23  		bss_config->key_mgmt = KEY_MGMT_NONE;
24  		bss_config->wpa_cfg.length = 0;
25  		priv->sec_info.wep_enabled = 0;
26  		priv->sec_info.wpa_enabled = 0;
27  		priv->sec_info.wpa2_enabled = 0;
28  
29  		return 0;
30  	}
31  
32  	switch (params->auth_type) {
33  	case NL80211_AUTHTYPE_OPEN_SYSTEM:
34  		bss_config->auth_mode = WLAN_AUTH_OPEN;
35  		break;
36  	case NL80211_AUTHTYPE_SHARED_KEY:
37  		bss_config->auth_mode = WLAN_AUTH_SHARED_KEY;
38  		break;
39  	case NL80211_AUTHTYPE_NETWORK_EAP:
40  		bss_config->auth_mode = WLAN_AUTH_LEAP;
41  		break;
42  	default:
43  		bss_config->auth_mode = MWIFIEX_AUTH_MODE_AUTO;
44  		break;
45  	}
46  
47  	bss_config->key_mgmt_operation |= KEY_MGMT_ON_HOST;
48  
49  	bss_config->protocol = 0;
50  	if (params->crypto.wpa_versions & NL80211_WPA_VERSION_1)
51  		bss_config->protocol |= PROTOCOL_WPA;
52  	if (params->crypto.wpa_versions & NL80211_WPA_VERSION_2)
53  		bss_config->protocol |= PROTOCOL_WPA2;
54  
55  	bss_config->key_mgmt = 0;
56  	for (i = 0; i < params->crypto.n_akm_suites; i++) {
57  		switch (params->crypto.akm_suites[i]) {
58  		case WLAN_AKM_SUITE_8021X:
59  			bss_config->key_mgmt |= KEY_MGMT_EAP;
60  			break;
61  		case WLAN_AKM_SUITE_PSK:
62  			bss_config->key_mgmt |= KEY_MGMT_PSK;
63  			break;
64  		case WLAN_AKM_SUITE_PSK_SHA256:
65  			bss_config->key_mgmt |= KEY_MGMT_PSK_SHA256;
66  			break;
67  		case WLAN_AKM_SUITE_SAE:
68  			bss_config->key_mgmt |= KEY_MGMT_SAE;
69  			break;
70  		default:
71  			break;
72  		}
73  	}
74  	for (i = 0; i < params->crypto.n_ciphers_pairwise; i++) {
75  		switch (params->crypto.ciphers_pairwise[i]) {
76  		case WLAN_CIPHER_SUITE_WEP40:
77  		case WLAN_CIPHER_SUITE_WEP104:
78  			break;
79  		case WLAN_CIPHER_SUITE_TKIP:
80  			if (params->crypto.wpa_versions & NL80211_WPA_VERSION_1)
81  				bss_config->wpa_cfg.pairwise_cipher_wpa |=
82  								CIPHER_TKIP;
83  			if (params->crypto.wpa_versions & NL80211_WPA_VERSION_2)
84  				bss_config->wpa_cfg.pairwise_cipher_wpa2 |=
85  								CIPHER_TKIP;
86  			break;
87  		case WLAN_CIPHER_SUITE_CCMP:
88  			if (params->crypto.wpa_versions & NL80211_WPA_VERSION_1)
89  				bss_config->wpa_cfg.pairwise_cipher_wpa |=
90  								CIPHER_AES_CCMP;
91  			if (params->crypto.wpa_versions & NL80211_WPA_VERSION_2)
92  				bss_config->wpa_cfg.pairwise_cipher_wpa2 |=
93  								CIPHER_AES_CCMP;
94  			break;
95  		default:
96  			break;
97  		}
98  	}
99  
100  	switch (params->crypto.cipher_group) {
101  	case WLAN_CIPHER_SUITE_WEP40:
102  	case WLAN_CIPHER_SUITE_WEP104:
103  		if (priv->sec_info.wep_enabled) {
104  			bss_config->protocol = PROTOCOL_STATIC_WEP;
105  			bss_config->key_mgmt = KEY_MGMT_NONE;
106  			bss_config->wpa_cfg.length = 0;
107  
108  			for (i = 0; i < NUM_WEP_KEYS; i++) {
109  				wep_key = priv->wep_key[i];
110  				bss_config->wep_cfg[i].key_index = i;
111  
112  				if (priv->wep_key_curr_index == i)
113  					bss_config->wep_cfg[i].is_default = 1;
114  				else
115  					bss_config->wep_cfg[i].is_default = 0;
116  
117  				bss_config->wep_cfg[i].length =
118  							     wep_key.key_length;
119  				memcpy(&bss_config->wep_cfg[i].key,
120  				       &wep_key.key_material,
121  				       wep_key.key_length);
122  			}
123  		}
124  		break;
125  	case WLAN_CIPHER_SUITE_TKIP:
126  		bss_config->wpa_cfg.group_cipher = CIPHER_TKIP;
127  		break;
128  	case WLAN_CIPHER_SUITE_CCMP:
129  		bss_config->wpa_cfg.group_cipher = CIPHER_AES_CCMP;
130  		break;
131  	default:
132  		break;
133  	}
134  
135  	return 0;
136  }
137  
138  /* This function updates 11n related parameters from IE and sets them into
139   * bss_config structure.
140   */
141  void
mwifiex_set_ht_params(struct mwifiex_private * priv,struct mwifiex_uap_bss_param * bss_cfg,struct cfg80211_ap_settings * params)142  mwifiex_set_ht_params(struct mwifiex_private *priv,
143  		      struct mwifiex_uap_bss_param *bss_cfg,
144  		      struct cfg80211_ap_settings *params)
145  {
146  	const u8 *ht_ie;
147  
148  	if (!ISSUPP_11NENABLED(priv->adapter->fw_cap_info))
149  		return;
150  
151  	ht_ie = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, params->beacon.tail,
152  				 params->beacon.tail_len);
153  	if (ht_ie) {
154  		memcpy(&bss_cfg->ht_cap, ht_ie + 2,
155  		       sizeof(struct ieee80211_ht_cap));
156  		priv->ap_11n_enabled = 1;
157  	} else {
158  		memset(&bss_cfg->ht_cap, 0, sizeof(struct ieee80211_ht_cap));
159  		bss_cfg->ht_cap.cap_info = cpu_to_le16(MWIFIEX_DEF_HT_CAP);
160  		bss_cfg->ht_cap.ampdu_params_info = MWIFIEX_DEF_AMPDU;
161  	}
162  
163  	return;
164  }
165  
166  /* This function updates 11ac related parameters from IE
167   * and sets them into bss_config structure.
168   */
mwifiex_set_vht_params(struct mwifiex_private * priv,struct mwifiex_uap_bss_param * bss_cfg,struct cfg80211_ap_settings * params)169  void mwifiex_set_vht_params(struct mwifiex_private *priv,
170  			    struct mwifiex_uap_bss_param *bss_cfg,
171  			    struct cfg80211_ap_settings *params)
172  {
173  	const u8 *vht_ie;
174  
175  	vht_ie = cfg80211_find_ie(WLAN_EID_VHT_CAPABILITY, params->beacon.tail,
176  				  params->beacon.tail_len);
177  	if (vht_ie) {
178  		memcpy(&bss_cfg->vht_cap, vht_ie + 2,
179  		       sizeof(struct ieee80211_vht_cap));
180  		priv->ap_11ac_enabled = 1;
181  	} else {
182  		priv->ap_11ac_enabled = 0;
183  	}
184  
185  	return;
186  }
187  
188  /* This function updates 11ac related parameters from IE
189   * and sets them into bss_config structure.
190   */
mwifiex_set_tpc_params(struct mwifiex_private * priv,struct mwifiex_uap_bss_param * bss_cfg,struct cfg80211_ap_settings * params)191  void mwifiex_set_tpc_params(struct mwifiex_private *priv,
192  			    struct mwifiex_uap_bss_param *bss_cfg,
193  			    struct cfg80211_ap_settings *params)
194  {
195  	const u8 *tpc_ie;
196  
197  	tpc_ie = cfg80211_find_ie(WLAN_EID_TPC_REQUEST, params->beacon.tail,
198  				  params->beacon.tail_len);
199  	if (tpc_ie)
200  		bss_cfg->power_constraint = *(tpc_ie + 2);
201  	else
202  		bss_cfg->power_constraint = 0;
203  }
204  
205  /* Enable VHT only when cfg80211_ap_settings has VHT IE.
206   * Otherwise disable VHT.
207   */
mwifiex_set_vht_width(struct mwifiex_private * priv,enum nl80211_chan_width width,bool ap_11ac_enable)208  void mwifiex_set_vht_width(struct mwifiex_private *priv,
209  			   enum nl80211_chan_width width,
210  			   bool ap_11ac_enable)
211  {
212  	struct mwifiex_adapter *adapter = priv->adapter;
213  	struct mwifiex_11ac_vht_cfg vht_cfg;
214  
215  	vht_cfg.band_config = VHT_CFG_5GHZ;
216  	vht_cfg.cap_info = adapter->hw_dot_11ac_dev_cap;
217  
218  	if (!ap_11ac_enable) {
219  		vht_cfg.mcs_tx_set = DISABLE_VHT_MCS_SET;
220  		vht_cfg.mcs_rx_set = DISABLE_VHT_MCS_SET;
221  	} else {
222  		vht_cfg.mcs_tx_set = DEFAULT_VHT_MCS_SET;
223  		vht_cfg.mcs_rx_set = DEFAULT_VHT_MCS_SET;
224  	}
225  
226  	vht_cfg.misc_config  = VHT_CAP_UAP_ONLY;
227  
228  	if (ap_11ac_enable && width >= NL80211_CHAN_WIDTH_80)
229  		vht_cfg.misc_config |= VHT_BW_80_160_80P80;
230  
231  	mwifiex_send_cmd(priv, HostCmd_CMD_11AC_CFG,
232  			 HostCmd_ACT_GEN_SET, 0, &vht_cfg, true);
233  
234  	return;
235  }
236  
237  /* This function finds supported rates IE from beacon parameter and sets
238   * these rates into bss_config structure.
239   */
240  void
mwifiex_set_uap_rates(struct mwifiex_uap_bss_param * bss_cfg,struct cfg80211_ap_settings * params)241  mwifiex_set_uap_rates(struct mwifiex_uap_bss_param *bss_cfg,
242  		      struct cfg80211_ap_settings *params)
243  {
244  	struct ieee_types_header *rate_ie;
245  	int var_offset = offsetof(struct ieee80211_mgmt, u.beacon.variable);
246  	const u8 *var_pos = params->beacon.head + var_offset;
247  	int len = params->beacon.head_len - var_offset;
248  	u8 rate_len = 0;
249  
250  	rate_ie = (void *)cfg80211_find_ie(WLAN_EID_SUPP_RATES, var_pos, len);
251  	if (rate_ie) {
252  		if (rate_ie->len > MWIFIEX_SUPPORTED_RATES)
253  			return;
254  		memcpy(bss_cfg->rates, rate_ie + 1, rate_ie->len);
255  		rate_len = rate_ie->len;
256  	}
257  
258  	rate_ie = (void *)cfg80211_find_ie(WLAN_EID_EXT_SUPP_RATES,
259  					   params->beacon.tail,
260  					   params->beacon.tail_len);
261  	if (rate_ie) {
262  		if (rate_ie->len > MWIFIEX_SUPPORTED_RATES - rate_len)
263  			return;
264  		memcpy(bss_cfg->rates + rate_len, rate_ie + 1, rate_ie->len);
265  	}
266  
267  	return;
268  }
269  
270  /* This function initializes some of mwifiex_uap_bss_param variables.
271   * This helps FW in ignoring invalid values. These values may or may not
272   * be get updated to valid ones at later stage.
273   */
mwifiex_set_sys_config_invalid_data(struct mwifiex_uap_bss_param * config)274  void mwifiex_set_sys_config_invalid_data(struct mwifiex_uap_bss_param *config)
275  {
276  	config->bcast_ssid_ctl = 0x7F;
277  	config->radio_ctl = 0x7F;
278  	config->dtim_period = 0x7F;
279  	config->beacon_period = 0x7FFF;
280  	config->auth_mode = 0x7F;
281  	config->rts_threshold = 0x7FFF;
282  	config->frag_threshold = 0x7FFF;
283  	config->retry_limit = 0x7F;
284  	config->qos_info = 0xFF;
285  }
286  
287  /* This function parses BSS related parameters from structure
288   * and prepares TLVs specific to WPA/WPA2 security.
289   * These TLVs are appended to command buffer.
290   */
291  static void
mwifiex_uap_bss_wpa(u8 ** tlv_buf,void * cmd_buf,u16 * param_size)292  mwifiex_uap_bss_wpa(u8 **tlv_buf, void *cmd_buf, u16 *param_size)
293  {
294  	struct host_cmd_tlv_pwk_cipher *pwk_cipher;
295  	struct host_cmd_tlv_gwk_cipher *gwk_cipher;
296  	struct host_cmd_tlv_passphrase *passphrase;
297  	struct host_cmd_tlv_akmp *tlv_akmp;
298  	struct mwifiex_uap_bss_param *bss_cfg = cmd_buf;
299  	u16 cmd_size = *param_size;
300  	u8 *tlv = *tlv_buf;
301  
302  	tlv_akmp = (struct host_cmd_tlv_akmp *)tlv;
303  	tlv_akmp->header.type = cpu_to_le16(TLV_TYPE_UAP_AKMP);
304  	tlv_akmp->header.len = cpu_to_le16(sizeof(struct host_cmd_tlv_akmp) -
305  					sizeof(struct mwifiex_ie_types_header));
306  	tlv_akmp->key_mgmt_operation = cpu_to_le16(bss_cfg->key_mgmt_operation);
307  	tlv_akmp->key_mgmt = cpu_to_le16(bss_cfg->key_mgmt);
308  	cmd_size += sizeof(struct host_cmd_tlv_akmp);
309  	tlv += sizeof(struct host_cmd_tlv_akmp);
310  
311  	if (bss_cfg->wpa_cfg.pairwise_cipher_wpa & VALID_CIPHER_BITMAP) {
312  		pwk_cipher = (struct host_cmd_tlv_pwk_cipher *)tlv;
313  		pwk_cipher->header.type = cpu_to_le16(TLV_TYPE_PWK_CIPHER);
314  		pwk_cipher->header.len =
315  			cpu_to_le16(sizeof(struct host_cmd_tlv_pwk_cipher) -
316  				    sizeof(struct mwifiex_ie_types_header));
317  		pwk_cipher->proto = cpu_to_le16(PROTOCOL_WPA);
318  		pwk_cipher->cipher = bss_cfg->wpa_cfg.pairwise_cipher_wpa;
319  		cmd_size += sizeof(struct host_cmd_tlv_pwk_cipher);
320  		tlv += sizeof(struct host_cmd_tlv_pwk_cipher);
321  	}
322  
323  	if (bss_cfg->wpa_cfg.pairwise_cipher_wpa2 & VALID_CIPHER_BITMAP) {
324  		pwk_cipher = (struct host_cmd_tlv_pwk_cipher *)tlv;
325  		pwk_cipher->header.type = cpu_to_le16(TLV_TYPE_PWK_CIPHER);
326  		pwk_cipher->header.len =
327  			cpu_to_le16(sizeof(struct host_cmd_tlv_pwk_cipher) -
328  				    sizeof(struct mwifiex_ie_types_header));
329  		pwk_cipher->proto = cpu_to_le16(PROTOCOL_WPA2);
330  		pwk_cipher->cipher = bss_cfg->wpa_cfg.pairwise_cipher_wpa2;
331  		cmd_size += sizeof(struct host_cmd_tlv_pwk_cipher);
332  		tlv += sizeof(struct host_cmd_tlv_pwk_cipher);
333  	}
334  
335  	if (bss_cfg->wpa_cfg.group_cipher & VALID_CIPHER_BITMAP) {
336  		gwk_cipher = (struct host_cmd_tlv_gwk_cipher *)tlv;
337  		gwk_cipher->header.type = cpu_to_le16(TLV_TYPE_GWK_CIPHER);
338  		gwk_cipher->header.len =
339  			cpu_to_le16(sizeof(struct host_cmd_tlv_gwk_cipher) -
340  				    sizeof(struct mwifiex_ie_types_header));
341  		gwk_cipher->cipher = bss_cfg->wpa_cfg.group_cipher;
342  		cmd_size += sizeof(struct host_cmd_tlv_gwk_cipher);
343  		tlv += sizeof(struct host_cmd_tlv_gwk_cipher);
344  	}
345  
346  	if (bss_cfg->wpa_cfg.length) {
347  		passphrase = (struct host_cmd_tlv_passphrase *)tlv;
348  		passphrase->header.type =
349  				cpu_to_le16(TLV_TYPE_UAP_WPA_PASSPHRASE);
350  		passphrase->header.len = cpu_to_le16(bss_cfg->wpa_cfg.length);
351  		memcpy(passphrase->passphrase, bss_cfg->wpa_cfg.passphrase,
352  		       bss_cfg->wpa_cfg.length);
353  		cmd_size += sizeof(struct mwifiex_ie_types_header) +
354  			    bss_cfg->wpa_cfg.length;
355  		tlv += sizeof(struct mwifiex_ie_types_header) +
356  				bss_cfg->wpa_cfg.length;
357  	}
358  
359  	*param_size = cmd_size;
360  	*tlv_buf = tlv;
361  
362  	return;
363  }
364  
365  /* This function parses WMM related parameters from cfg80211_ap_settings
366   * structure and updates bss_config structure.
367   */
368  void
mwifiex_set_wmm_params(struct mwifiex_private * priv,struct mwifiex_uap_bss_param * bss_cfg,struct cfg80211_ap_settings * params)369  mwifiex_set_wmm_params(struct mwifiex_private *priv,
370  		       struct mwifiex_uap_bss_param *bss_cfg,
371  		       struct cfg80211_ap_settings *params)
372  {
373  	const u8 *vendor_ie;
374  	const u8 *wmm_ie;
375  	static const u8 wmm_oui[] = {0x00, 0x50, 0xf2, 0x02};
376  
377  	vendor_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
378  					    WLAN_OUI_TYPE_MICROSOFT_WMM,
379  					    params->beacon.tail,
380  					    params->beacon.tail_len);
381  	if (vendor_ie) {
382  		wmm_ie = vendor_ie;
383  		if (*(wmm_ie + 1) > sizeof(struct mwifiex_types_wmm_info))
384  			return;
385  		memcpy(&bss_cfg->wmm_info, wmm_ie +
386  		       sizeof(struct ieee_types_header), *(wmm_ie + 1));
387  		priv->wmm_enabled = 1;
388  	} else {
389  		memset(&bss_cfg->wmm_info, 0, sizeof(bss_cfg->wmm_info));
390  		memcpy(&bss_cfg->wmm_info.oui, wmm_oui, sizeof(wmm_oui));
391  		bss_cfg->wmm_info.subtype = MWIFIEX_WMM_SUBTYPE;
392  		bss_cfg->wmm_info.version = MWIFIEX_WMM_VERSION;
393  		priv->wmm_enabled = 0;
394  	}
395  
396  	bss_cfg->qos_info = 0x00;
397  	return;
398  }
399  /* This function parses BSS related parameters from structure
400   * and prepares TLVs specific to WEP encryption.
401   * These TLVs are appended to command buffer.
402   */
403  static void
mwifiex_uap_bss_wep(u8 ** tlv_buf,void * cmd_buf,u16 * param_size)404  mwifiex_uap_bss_wep(u8 **tlv_buf, void *cmd_buf, u16 *param_size)
405  {
406  	struct host_cmd_tlv_wep_key *wep_key;
407  	u16 cmd_size = *param_size;
408  	int i;
409  	u8 *tlv = *tlv_buf;
410  	struct mwifiex_uap_bss_param *bss_cfg = cmd_buf;
411  
412  	for (i = 0; i < NUM_WEP_KEYS; i++) {
413  		if (bss_cfg->wep_cfg[i].length &&
414  		    (bss_cfg->wep_cfg[i].length == WLAN_KEY_LEN_WEP40 ||
415  		     bss_cfg->wep_cfg[i].length == WLAN_KEY_LEN_WEP104)) {
416  			wep_key = (struct host_cmd_tlv_wep_key *)tlv;
417  			wep_key->header.type =
418  				cpu_to_le16(TLV_TYPE_UAP_WEP_KEY);
419  			wep_key->header.len =
420  				cpu_to_le16(bss_cfg->wep_cfg[i].length + 2);
421  			wep_key->key_index = bss_cfg->wep_cfg[i].key_index;
422  			wep_key->is_default = bss_cfg->wep_cfg[i].is_default;
423  			memcpy(wep_key->key, bss_cfg->wep_cfg[i].key,
424  			       bss_cfg->wep_cfg[i].length);
425  			cmd_size += sizeof(struct mwifiex_ie_types_header) + 2 +
426  				    bss_cfg->wep_cfg[i].length;
427  			tlv += sizeof(struct mwifiex_ie_types_header) + 2 +
428  				    bss_cfg->wep_cfg[i].length;
429  		}
430  	}
431  
432  	*param_size = cmd_size;
433  	*tlv_buf = tlv;
434  
435  	return;
436  }
437  
438  /* This function enable 11D if userspace set the country IE.
439   */
mwifiex_config_uap_11d(struct mwifiex_private * priv,struct cfg80211_beacon_data * beacon_data)440  void mwifiex_config_uap_11d(struct mwifiex_private *priv,
441  			    struct cfg80211_beacon_data *beacon_data)
442  {
443  	enum state_11d_t state_11d;
444  	const u8 *country_ie;
445  
446  	country_ie = cfg80211_find_ie(WLAN_EID_COUNTRY, beacon_data->tail,
447  				      beacon_data->tail_len);
448  	if (country_ie) {
449  		/* Send cmd to FW to enable 11D function */
450  		state_11d = ENABLE_11D;
451  		if (mwifiex_send_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB,
452  				     HostCmd_ACT_GEN_SET, DOT11D_I,
453  				     &state_11d, true)) {
454  			mwifiex_dbg(priv->adapter, ERROR,
455  				    "11D: failed to enable 11D\n");
456  		}
457  	}
458  }
459  
460  /* This function parses BSS related parameters from structure
461   * and prepares TLVs. These TLVs are appended to command buffer.
462  */
463  static int
mwifiex_uap_bss_param_prepare(u8 * tlv,void * cmd_buf,u16 * param_size)464  mwifiex_uap_bss_param_prepare(u8 *tlv, void *cmd_buf, u16 *param_size)
465  {
466  	struct host_cmd_tlv_mac_addr *mac_tlv;
467  	struct host_cmd_tlv_dtim_period *dtim_period;
468  	struct host_cmd_tlv_beacon_period *beacon_period;
469  	struct host_cmd_tlv_ssid *ssid;
470  	struct host_cmd_tlv_bcast_ssid *bcast_ssid;
471  	struct host_cmd_tlv_channel_band *chan_band;
472  	struct host_cmd_tlv_frag_threshold *frag_threshold;
473  	struct host_cmd_tlv_rts_threshold *rts_threshold;
474  	struct host_cmd_tlv_retry_limit *retry_limit;
475  	struct host_cmd_tlv_encrypt_protocol *encrypt_protocol;
476  	struct host_cmd_tlv_auth_type *auth_type;
477  	struct host_cmd_tlv_rates *tlv_rates;
478  	struct host_cmd_tlv_ageout_timer *ao_timer, *ps_ao_timer;
479  	struct host_cmd_tlv_power_constraint *pwr_ct;
480  	struct mwifiex_ie_types_htcap *htcap;
481  	struct mwifiex_ie_types_wmmcap *wmm_cap;
482  	struct mwifiex_uap_bss_param *bss_cfg = cmd_buf;
483  	int i;
484  	u16 cmd_size = *param_size;
485  
486  	mac_tlv = (struct host_cmd_tlv_mac_addr *)tlv;
487  	mac_tlv->header.type = cpu_to_le16(TLV_TYPE_UAP_MAC_ADDRESS);
488  	mac_tlv->header.len = cpu_to_le16(ETH_ALEN);
489  	memcpy(mac_tlv->mac_addr, bss_cfg->mac_addr, ETH_ALEN);
490  	cmd_size += sizeof(struct host_cmd_tlv_mac_addr);
491  	tlv += sizeof(struct host_cmd_tlv_mac_addr);
492  
493  	if (bss_cfg->ssid.ssid_len) {
494  		ssid = (struct host_cmd_tlv_ssid *)tlv;
495  		ssid->header.type = cpu_to_le16(TLV_TYPE_UAP_SSID);
496  		ssid->header.len = cpu_to_le16((u16)bss_cfg->ssid.ssid_len);
497  		memcpy(ssid->ssid, bss_cfg->ssid.ssid, bss_cfg->ssid.ssid_len);
498  		cmd_size += sizeof(struct mwifiex_ie_types_header) +
499  			    bss_cfg->ssid.ssid_len;
500  		tlv += sizeof(struct mwifiex_ie_types_header) +
501  				bss_cfg->ssid.ssid_len;
502  
503  		bcast_ssid = (struct host_cmd_tlv_bcast_ssid *)tlv;
504  		bcast_ssid->header.type = cpu_to_le16(TLV_TYPE_UAP_BCAST_SSID);
505  		bcast_ssid->header.len =
506  				cpu_to_le16(sizeof(bcast_ssid->bcast_ctl));
507  		bcast_ssid->bcast_ctl = bss_cfg->bcast_ssid_ctl;
508  		cmd_size += sizeof(struct host_cmd_tlv_bcast_ssid);
509  		tlv += sizeof(struct host_cmd_tlv_bcast_ssid);
510  	}
511  	if (bss_cfg->rates[0]) {
512  		tlv_rates = (struct host_cmd_tlv_rates *)tlv;
513  		tlv_rates->header.type = cpu_to_le16(TLV_TYPE_UAP_RATES);
514  
515  		for (i = 0; i < MWIFIEX_SUPPORTED_RATES && bss_cfg->rates[i];
516  		     i++)
517  			tlv_rates->rates[i] = bss_cfg->rates[i];
518  
519  		tlv_rates->header.len = cpu_to_le16(i);
520  		cmd_size += sizeof(struct host_cmd_tlv_rates) + i;
521  		tlv += sizeof(struct host_cmd_tlv_rates) + i;
522  	}
523  	if (bss_cfg->channel &&
524  	    (((bss_cfg->band_cfg & BIT(0)) == BAND_CONFIG_BG &&
525  	      bss_cfg->channel <= MAX_CHANNEL_BAND_BG) ||
526  	    ((bss_cfg->band_cfg & BIT(0)) == BAND_CONFIG_A &&
527  	     bss_cfg->channel <= MAX_CHANNEL_BAND_A))) {
528  		chan_band = (struct host_cmd_tlv_channel_band *)tlv;
529  		chan_band->header.type = cpu_to_le16(TLV_TYPE_CHANNELBANDLIST);
530  		chan_band->header.len =
531  			cpu_to_le16(sizeof(struct host_cmd_tlv_channel_band) -
532  				    sizeof(struct mwifiex_ie_types_header));
533  		chan_band->band_config = bss_cfg->band_cfg;
534  		chan_band->channel = bss_cfg->channel;
535  		cmd_size += sizeof(struct host_cmd_tlv_channel_band);
536  		tlv += sizeof(struct host_cmd_tlv_channel_band);
537  	}
538  	if (bss_cfg->beacon_period >= MIN_BEACON_PERIOD &&
539  	    bss_cfg->beacon_period <= MAX_BEACON_PERIOD) {
540  		beacon_period = (struct host_cmd_tlv_beacon_period *)tlv;
541  		beacon_period->header.type =
542  					cpu_to_le16(TLV_TYPE_UAP_BEACON_PERIOD);
543  		beacon_period->header.len =
544  			cpu_to_le16(sizeof(struct host_cmd_tlv_beacon_period) -
545  				    sizeof(struct mwifiex_ie_types_header));
546  		beacon_period->period = cpu_to_le16(bss_cfg->beacon_period);
547  		cmd_size += sizeof(struct host_cmd_tlv_beacon_period);
548  		tlv += sizeof(struct host_cmd_tlv_beacon_period);
549  	}
550  	if (bss_cfg->dtim_period >= MIN_DTIM_PERIOD &&
551  	    bss_cfg->dtim_period <= MAX_DTIM_PERIOD) {
552  		dtim_period = (struct host_cmd_tlv_dtim_period *)tlv;
553  		dtim_period->header.type =
554  			cpu_to_le16(TLV_TYPE_UAP_DTIM_PERIOD);
555  		dtim_period->header.len =
556  			cpu_to_le16(sizeof(struct host_cmd_tlv_dtim_period) -
557  				    sizeof(struct mwifiex_ie_types_header));
558  		dtim_period->period = bss_cfg->dtim_period;
559  		cmd_size += sizeof(struct host_cmd_tlv_dtim_period);
560  		tlv += sizeof(struct host_cmd_tlv_dtim_period);
561  	}
562  	if (bss_cfg->rts_threshold <= MWIFIEX_RTS_MAX_VALUE) {
563  		rts_threshold = (struct host_cmd_tlv_rts_threshold *)tlv;
564  		rts_threshold->header.type =
565  					cpu_to_le16(TLV_TYPE_UAP_RTS_THRESHOLD);
566  		rts_threshold->header.len =
567  			cpu_to_le16(sizeof(struct host_cmd_tlv_rts_threshold) -
568  				    sizeof(struct mwifiex_ie_types_header));
569  		rts_threshold->rts_thr = cpu_to_le16(bss_cfg->rts_threshold);
570  		cmd_size += sizeof(struct host_cmd_tlv_frag_threshold);
571  		tlv += sizeof(struct host_cmd_tlv_frag_threshold);
572  	}
573  	if ((bss_cfg->frag_threshold >= MWIFIEX_FRAG_MIN_VALUE) &&
574  	    (bss_cfg->frag_threshold <= MWIFIEX_FRAG_MAX_VALUE)) {
575  		frag_threshold = (struct host_cmd_tlv_frag_threshold *)tlv;
576  		frag_threshold->header.type =
577  				cpu_to_le16(TLV_TYPE_UAP_FRAG_THRESHOLD);
578  		frag_threshold->header.len =
579  			cpu_to_le16(sizeof(struct host_cmd_tlv_frag_threshold) -
580  				    sizeof(struct mwifiex_ie_types_header));
581  		frag_threshold->frag_thr = cpu_to_le16(bss_cfg->frag_threshold);
582  		cmd_size += sizeof(struct host_cmd_tlv_frag_threshold);
583  		tlv += sizeof(struct host_cmd_tlv_frag_threshold);
584  	}
585  	if (bss_cfg->retry_limit <= MWIFIEX_RETRY_LIMIT) {
586  		retry_limit = (struct host_cmd_tlv_retry_limit *)tlv;
587  		retry_limit->header.type =
588  			cpu_to_le16(TLV_TYPE_UAP_RETRY_LIMIT);
589  		retry_limit->header.len =
590  			cpu_to_le16(sizeof(struct host_cmd_tlv_retry_limit) -
591  				    sizeof(struct mwifiex_ie_types_header));
592  		retry_limit->limit = (u8)bss_cfg->retry_limit;
593  		cmd_size += sizeof(struct host_cmd_tlv_retry_limit);
594  		tlv += sizeof(struct host_cmd_tlv_retry_limit);
595  	}
596  	if ((bss_cfg->protocol & PROTOCOL_WPA) ||
597  	    (bss_cfg->protocol & PROTOCOL_WPA2) ||
598  	    (bss_cfg->protocol & PROTOCOL_EAP))
599  		mwifiex_uap_bss_wpa(&tlv, cmd_buf, &cmd_size);
600  	else
601  		mwifiex_uap_bss_wep(&tlv, cmd_buf, &cmd_size);
602  
603  	if ((bss_cfg->auth_mode <= WLAN_AUTH_SHARED_KEY) ||
604  	    (bss_cfg->auth_mode == MWIFIEX_AUTH_MODE_AUTO)) {
605  		auth_type = (struct host_cmd_tlv_auth_type *)tlv;
606  		auth_type->header.type = cpu_to_le16(TLV_TYPE_AUTH_TYPE);
607  		auth_type->header.len =
608  			cpu_to_le16(sizeof(struct host_cmd_tlv_auth_type) -
609  			sizeof(struct mwifiex_ie_types_header));
610  		auth_type->auth_type = (u8)bss_cfg->auth_mode;
611  		cmd_size += sizeof(struct host_cmd_tlv_auth_type);
612  		tlv += sizeof(struct host_cmd_tlv_auth_type);
613  	}
614  	if (bss_cfg->protocol) {
615  		encrypt_protocol = (struct host_cmd_tlv_encrypt_protocol *)tlv;
616  		encrypt_protocol->header.type =
617  			cpu_to_le16(TLV_TYPE_UAP_ENCRY_PROTOCOL);
618  		encrypt_protocol->header.len =
619  			cpu_to_le16(sizeof(struct host_cmd_tlv_encrypt_protocol)
620  			- sizeof(struct mwifiex_ie_types_header));
621  		encrypt_protocol->proto = cpu_to_le16(bss_cfg->protocol);
622  		cmd_size += sizeof(struct host_cmd_tlv_encrypt_protocol);
623  		tlv += sizeof(struct host_cmd_tlv_encrypt_protocol);
624  	}
625  
626  	if (bss_cfg->ht_cap.cap_info) {
627  		htcap = (struct mwifiex_ie_types_htcap *)tlv;
628  		htcap->header.type = cpu_to_le16(WLAN_EID_HT_CAPABILITY);
629  		htcap->header.len =
630  				cpu_to_le16(sizeof(struct ieee80211_ht_cap));
631  		htcap->ht_cap.cap_info = bss_cfg->ht_cap.cap_info;
632  		htcap->ht_cap.ampdu_params_info =
633  					     bss_cfg->ht_cap.ampdu_params_info;
634  		memcpy(&htcap->ht_cap.mcs, &bss_cfg->ht_cap.mcs,
635  		       sizeof(struct ieee80211_mcs_info));
636  		htcap->ht_cap.extended_ht_cap_info =
637  					bss_cfg->ht_cap.extended_ht_cap_info;
638  		htcap->ht_cap.tx_BF_cap_info = bss_cfg->ht_cap.tx_BF_cap_info;
639  		htcap->ht_cap.antenna_selection_info =
640  					bss_cfg->ht_cap.antenna_selection_info;
641  		cmd_size += sizeof(struct mwifiex_ie_types_htcap);
642  		tlv += sizeof(struct mwifiex_ie_types_htcap);
643  	}
644  
645  	if (bss_cfg->wmm_info.qos_info != 0xFF) {
646  		wmm_cap = (struct mwifiex_ie_types_wmmcap *)tlv;
647  		wmm_cap->header.type = cpu_to_le16(WLAN_EID_VENDOR_SPECIFIC);
648  		wmm_cap->header.len = cpu_to_le16(sizeof(wmm_cap->wmm_info));
649  		memcpy(&wmm_cap->wmm_info, &bss_cfg->wmm_info,
650  		       sizeof(wmm_cap->wmm_info));
651  		cmd_size += sizeof(struct mwifiex_ie_types_wmmcap);
652  		tlv += sizeof(struct mwifiex_ie_types_wmmcap);
653  	}
654  
655  	if (bss_cfg->sta_ao_timer) {
656  		ao_timer = (struct host_cmd_tlv_ageout_timer *)tlv;
657  		ao_timer->header.type = cpu_to_le16(TLV_TYPE_UAP_AO_TIMER);
658  		ao_timer->header.len = cpu_to_le16(sizeof(*ao_timer) -
659  					sizeof(struct mwifiex_ie_types_header));
660  		ao_timer->sta_ao_timer = cpu_to_le32(bss_cfg->sta_ao_timer);
661  		cmd_size += sizeof(*ao_timer);
662  		tlv += sizeof(*ao_timer);
663  	}
664  
665  	if (bss_cfg->power_constraint) {
666  		pwr_ct = (void *)tlv;
667  		pwr_ct->header.type = cpu_to_le16(TLV_TYPE_PWR_CONSTRAINT);
668  		pwr_ct->header.len = cpu_to_le16(sizeof(u8));
669  		pwr_ct->constraint = bss_cfg->power_constraint;
670  		cmd_size += sizeof(*pwr_ct);
671  		tlv += sizeof(*pwr_ct);
672  	}
673  
674  	if (bss_cfg->ps_sta_ao_timer) {
675  		ps_ao_timer = (struct host_cmd_tlv_ageout_timer *)tlv;
676  		ps_ao_timer->header.type =
677  				cpu_to_le16(TLV_TYPE_UAP_PS_AO_TIMER);
678  		ps_ao_timer->header.len = cpu_to_le16(sizeof(*ps_ao_timer) -
679  				sizeof(struct mwifiex_ie_types_header));
680  		ps_ao_timer->sta_ao_timer =
681  					cpu_to_le32(bss_cfg->ps_sta_ao_timer);
682  		cmd_size += sizeof(*ps_ao_timer);
683  		tlv += sizeof(*ps_ao_timer);
684  	}
685  
686  	*param_size = cmd_size;
687  
688  	return 0;
689  }
690  
691  /* This function parses custom IEs from IE list and prepares command buffer */
mwifiex_uap_custom_ie_prepare(u8 * tlv,void * cmd_buf,u16 * ie_size)692  static int mwifiex_uap_custom_ie_prepare(u8 *tlv, void *cmd_buf, u16 *ie_size)
693  {
694  	struct mwifiex_ie_list *ap_ie = cmd_buf;
695  	struct mwifiex_ie_types_header *tlv_ie = (void *)tlv;
696  
697  	if (!ap_ie || !ap_ie->len)
698  		return -1;
699  
700  	*ie_size += le16_to_cpu(ap_ie->len) +
701  			sizeof(struct mwifiex_ie_types_header);
702  
703  	tlv_ie->type = cpu_to_le16(TLV_TYPE_MGMT_IE);
704  	tlv_ie->len = ap_ie->len;
705  	tlv += sizeof(struct mwifiex_ie_types_header);
706  
707  	memcpy(tlv, ap_ie->ie_list, le16_to_cpu(ap_ie->len));
708  
709  	return 0;
710  }
711  
712  /* Parse AP config structure and prepare TLV based command structure
713   * to be sent to FW for uAP configuration
714   */
715  static int
mwifiex_cmd_uap_sys_config(struct host_cmd_ds_command * cmd,u16 cmd_action,u32 type,void * cmd_buf)716  mwifiex_cmd_uap_sys_config(struct host_cmd_ds_command *cmd, u16 cmd_action,
717  			   u32 type, void *cmd_buf)
718  {
719  	u8 *tlv;
720  	u16 cmd_size, param_size, ie_size;
721  	struct host_cmd_ds_sys_config *sys_cfg;
722  
723  	cmd->command = cpu_to_le16(HostCmd_CMD_UAP_SYS_CONFIG);
724  	cmd_size = (u16)(sizeof(struct host_cmd_ds_sys_config) + S_DS_GEN);
725  	sys_cfg = (struct host_cmd_ds_sys_config *)&cmd->params.uap_sys_config;
726  	sys_cfg->action = cpu_to_le16(cmd_action);
727  	tlv = sys_cfg->tlv;
728  
729  	switch (type) {
730  	case UAP_BSS_PARAMS_I:
731  		param_size = cmd_size;
732  		if (mwifiex_uap_bss_param_prepare(tlv, cmd_buf, &param_size))
733  			return -1;
734  		cmd->size = cpu_to_le16(param_size);
735  		break;
736  	case UAP_CUSTOM_IE_I:
737  		ie_size = cmd_size;
738  		if (mwifiex_uap_custom_ie_prepare(tlv, cmd_buf, &ie_size))
739  			return -1;
740  		cmd->size = cpu_to_le16(ie_size);
741  		break;
742  	default:
743  		return -1;
744  	}
745  
746  	return 0;
747  }
748  
749  /* This function prepares AP start up command with or without host MLME
750   */
mwifiex_cmd_uap_bss_start(struct mwifiex_private * priv,struct host_cmd_ds_command * cmd)751  static void mwifiex_cmd_uap_bss_start(struct mwifiex_private *priv,
752  				     struct host_cmd_ds_command *cmd)
753  {
754  	struct mwifiex_ie_types_host_mlme *tlv;
755  	int size;
756  
757  	cmd->command = cpu_to_le16(HostCmd_CMD_UAP_BSS_START);
758  	size = S_DS_GEN;
759  
760  	if (priv->adapter->host_mlme_enabled) {
761  		tlv = (struct mwifiex_ie_types_host_mlme *)((u8 *)cmd + size);
762  		tlv->header.type = cpu_to_le16(TLV_TYPE_HOST_MLME);
763  		tlv->header.len = cpu_to_le16(sizeof(tlv->host_mlme));
764  		tlv->host_mlme = 1;
765  		size += sizeof(struct mwifiex_ie_types_host_mlme);
766  	}
767  
768  	cmd->size = cpu_to_le16(size);
769  }
770  
771  /* This function prepares AP specific deauth command with mac supplied in
772   * function parameter.
773   */
mwifiex_cmd_uap_sta_deauth(struct mwifiex_private * priv,struct host_cmd_ds_command * cmd,u8 * mac)774  static int mwifiex_cmd_uap_sta_deauth(struct mwifiex_private *priv,
775  				      struct host_cmd_ds_command *cmd, u8 *mac)
776  {
777  	struct host_cmd_ds_sta_deauth *sta_deauth = &cmd->params.sta_deauth;
778  
779  	cmd->command = cpu_to_le16(HostCmd_CMD_UAP_STA_DEAUTH);
780  	memcpy(sta_deauth->mac, mac, ETH_ALEN);
781  	sta_deauth->reason = cpu_to_le16(WLAN_REASON_DEAUTH_LEAVING);
782  
783  	cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_sta_deauth) +
784  				S_DS_GEN);
785  	return 0;
786  }
787  
788  /* This function prepares AP specific add station command.
789   */
mwifiex_cmd_uap_add_station(struct mwifiex_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_action,void * data_buf)790  static int mwifiex_cmd_uap_add_station(struct mwifiex_private *priv,
791  				       struct host_cmd_ds_command *cmd,
792  				       u16 cmd_action, void *data_buf)
793  {
794  	struct host_cmd_ds_add_station *new_sta = &cmd->params.sta_info;
795  	struct mwifiex_sta_info *add_sta = (struct mwifiex_sta_info *)data_buf;
796  	struct station_parameters *params = add_sta->params;
797  	struct mwifiex_sta_node *sta_ptr;
798  	u8 *pos;
799  	u8 qos_capa;
800  	u16 header_len = sizeof(struct mwifiex_ie_types_header);
801  	u16 tlv_len;
802  	int size;
803  	struct mwifiex_ie_types_data *tlv;
804  	struct mwifiex_ie_types_sta_flag *sta_flag;
805  	int i;
806  
807  	cmd->command = cpu_to_le16(HostCmd_CMD_ADD_NEW_STATION);
808  	new_sta->action = cpu_to_le16(cmd_action);
809  	size = sizeof(struct host_cmd_ds_add_station) + S_DS_GEN;
810  
811  	if (cmd_action == HostCmd_ACT_ADD_STA)
812  		sta_ptr = mwifiex_add_sta_entry(priv, add_sta->peer_mac);
813  	else
814  		sta_ptr = mwifiex_get_sta_entry(priv, add_sta->peer_mac);
815  
816  	if (!sta_ptr)
817  		return -1;
818  
819  	memcpy(new_sta->peer_mac, add_sta->peer_mac, ETH_ALEN);
820  
821  	if (cmd_action == HostCmd_ACT_REMOVE_STA) {
822  		cmd->size = cpu_to_le16(size);
823  		return 0;
824  	}
825  
826  	new_sta->aid = cpu_to_le16(params->aid);
827  	new_sta->listen_interval = cpu_to_le32(params->listen_interval);
828  	new_sta->cap_info = cpu_to_le16(params->capability);
829  
830  	pos = new_sta->tlv;
831  
832  	if (params->sta_flags_set & NL80211_STA_FLAG_WME)
833  		sta_ptr->is_wmm_enabled = 1;
834  	sta_flag = (struct mwifiex_ie_types_sta_flag *)pos;
835  	sta_flag->header.type = cpu_to_le16(TLV_TYPE_UAP_STA_FLAGS);
836  	sta_flag->header.len = cpu_to_le16(sizeof(__le32));
837  	sta_flag->sta_flags = cpu_to_le32(params->sta_flags_set);
838  	pos += sizeof(struct mwifiex_ie_types_sta_flag);
839  	size += sizeof(struct mwifiex_ie_types_sta_flag);
840  
841  	if (params->ext_capab_len) {
842  		tlv = (struct mwifiex_ie_types_data *)pos;
843  		tlv->header.type = cpu_to_le16(WLAN_EID_EXT_CAPABILITY);
844  		tlv_len = params->ext_capab_len;
845  		tlv->header.len = cpu_to_le16(tlv_len);
846  		memcpy(tlv->data, params->ext_capab, tlv_len);
847  		pos += (header_len + tlv_len);
848  		size += (header_len + tlv_len);
849  	}
850  
851  	if (params->link_sta_params.supported_rates_len) {
852  		tlv = (struct mwifiex_ie_types_data *)pos;
853  		tlv->header.type = cpu_to_le16(WLAN_EID_SUPP_RATES);
854  		tlv_len = params->link_sta_params.supported_rates_len;
855  		tlv->header.len = cpu_to_le16(tlv_len);
856  		memcpy(tlv->data,
857  		       params->link_sta_params.supported_rates, tlv_len);
858  		pos += (header_len + tlv_len);
859  		size += (header_len + tlv_len);
860  	}
861  
862  	if (params->uapsd_queues || params->max_sp) {
863  		tlv = (struct mwifiex_ie_types_data *)pos;
864  		tlv->header.type = cpu_to_le16(WLAN_EID_QOS_CAPA);
865  		tlv_len = sizeof(qos_capa);
866  		tlv->header.len = cpu_to_le16(tlv_len);
867  		qos_capa = params->uapsd_queues | (params->max_sp << 5);
868  		memcpy(tlv->data, &qos_capa, tlv_len);
869  		pos += (header_len + tlv_len);
870  		size += (header_len + tlv_len);
871  		sta_ptr->is_wmm_enabled = 1;
872  	}
873  
874  	if (params->link_sta_params.ht_capa) {
875  		tlv = (struct mwifiex_ie_types_data *)pos;
876  		tlv->header.type = cpu_to_le16(WLAN_EID_HT_CAPABILITY);
877  		tlv_len = sizeof(struct ieee80211_ht_cap);
878  		tlv->header.len = cpu_to_le16(tlv_len);
879  		memcpy(tlv->data, params->link_sta_params.ht_capa, tlv_len);
880  		pos += (header_len + tlv_len);
881  		size += (header_len + tlv_len);
882  		sta_ptr->is_11n_enabled = 1;
883  		sta_ptr->max_amsdu =
884  			le16_to_cpu(params->link_sta_params.ht_capa->cap_info) &
885  			IEEE80211_HT_CAP_MAX_AMSDU ?
886  			MWIFIEX_TX_DATA_BUF_SIZE_8K :
887  			MWIFIEX_TX_DATA_BUF_SIZE_4K;
888  	}
889  
890  	if (params->link_sta_params.vht_capa) {
891  		tlv = (struct mwifiex_ie_types_data *)pos;
892  		tlv->header.type = cpu_to_le16(WLAN_EID_VHT_CAPABILITY);
893  		tlv_len = sizeof(struct ieee80211_vht_cap);
894  		tlv->header.len = cpu_to_le16(tlv_len);
895  		memcpy(tlv->data, params->link_sta_params.vht_capa, tlv_len);
896  		pos += (header_len + tlv_len);
897  		size += (header_len + tlv_len);
898  		sta_ptr->is_11ac_enabled = 1;
899  	}
900  
901  	if (params->link_sta_params.opmode_notif_used) {
902  		tlv = (struct mwifiex_ie_types_data *)pos;
903  		tlv->header.type = cpu_to_le16(WLAN_EID_OPMODE_NOTIF);
904  		tlv_len = sizeof(u8);
905  		tlv->header.len = cpu_to_le16(tlv_len);
906  		memcpy(tlv->data, &params->link_sta_params.opmode_notif,
907  		       tlv_len);
908  		pos += (header_len + tlv_len);
909  		size += (header_len + tlv_len);
910  	}
911  
912  	for (i = 0; i < MAX_NUM_TID; i++) {
913  		if (sta_ptr->is_11n_enabled)
914  			sta_ptr->ampdu_sta[i] =
915  				      priv->aggr_prio_tbl[i].ampdu_user;
916  		else
917  			sta_ptr->ampdu_sta[i] = BA_STREAM_NOT_ALLOWED;
918  	}
919  
920  	memset(sta_ptr->rx_seq, 0xff, sizeof(sta_ptr->rx_seq));
921  	cmd->size = cpu_to_le16(size);
922  
923  	return 0;
924  }
925  
926  /* This function prepares the AP specific commands before sending them
927   * to the firmware.
928   * This is a generic function which calls specific command preparation
929   * routines based upon the command number.
930   */
mwifiex_uap_prepare_cmd(struct mwifiex_private * priv,u16 cmd_no,u16 cmd_action,u32 type,void * data_buf,void * cmd_buf)931  int mwifiex_uap_prepare_cmd(struct mwifiex_private *priv, u16 cmd_no,
932  			    u16 cmd_action, u32 type,
933  			    void *data_buf, void *cmd_buf)
934  {
935  	struct host_cmd_ds_command *cmd = cmd_buf;
936  
937  	switch (cmd_no) {
938  	case HostCmd_CMD_UAP_SYS_CONFIG:
939  		if (mwifiex_cmd_uap_sys_config(cmd, cmd_action, type, data_buf))
940  			return -1;
941  		break;
942  	case HostCmd_CMD_UAP_BSS_START:
943  		mwifiex_cmd_uap_bss_start(priv, cmd);
944  		break;
945  	case HostCmd_CMD_UAP_BSS_STOP:
946  	case HOST_CMD_APCMD_SYS_RESET:
947  	case HOST_CMD_APCMD_STA_LIST:
948  		cmd->command = cpu_to_le16(cmd_no);
949  		cmd->size = cpu_to_le16(S_DS_GEN);
950  		break;
951  	case HostCmd_CMD_UAP_STA_DEAUTH:
952  		if (mwifiex_cmd_uap_sta_deauth(priv, cmd, data_buf))
953  			return -1;
954  		break;
955  	case HostCmd_CMD_CHAN_REPORT_REQUEST:
956  		if (mwifiex_cmd_issue_chan_report_request(priv, cmd_buf,
957  							  data_buf))
958  			return -1;
959  		break;
960  	case HostCmd_CMD_ADD_NEW_STATION:
961  		if (mwifiex_cmd_uap_add_station(priv, cmd, cmd_action,
962  						data_buf))
963  			return -1;
964  		break;
965  	default:
966  		mwifiex_dbg(priv->adapter, ERROR,
967  			    "PREP_CMD: unknown cmd %#x\n", cmd_no);
968  		return -1;
969  	}
970  
971  	return 0;
972  }
973  
mwifiex_uap_set_channel(struct mwifiex_private * priv,struct mwifiex_uap_bss_param * bss_cfg,struct cfg80211_chan_def chandef)974  void mwifiex_uap_set_channel(struct mwifiex_private *priv,
975  			     struct mwifiex_uap_bss_param *bss_cfg,
976  			     struct cfg80211_chan_def chandef)
977  {
978  	u8 config_bands = 0, old_bands = priv->adapter->config_bands;
979  
980  	priv->bss_chandef = chandef;
981  
982  	bss_cfg->channel = ieee80211_frequency_to_channel(
983  						     chandef.chan->center_freq);
984  
985  	/* Set appropriate bands */
986  	if (chandef.chan->band == NL80211_BAND_2GHZ) {
987  		bss_cfg->band_cfg = BAND_CONFIG_BG;
988  		config_bands = BAND_B | BAND_G;
989  
990  		if (chandef.width > NL80211_CHAN_WIDTH_20_NOHT)
991  			config_bands |= BAND_GN;
992  	} else {
993  		bss_cfg->band_cfg = BAND_CONFIG_A;
994  		config_bands = BAND_A;
995  
996  		if (chandef.width > NL80211_CHAN_WIDTH_20_NOHT)
997  			config_bands |= BAND_AN;
998  
999  		if (chandef.width > NL80211_CHAN_WIDTH_40)
1000  			config_bands |= BAND_AAC;
1001  	}
1002  
1003  	switch (chandef.width) {
1004  	case NL80211_CHAN_WIDTH_5:
1005  	case NL80211_CHAN_WIDTH_10:
1006  	case NL80211_CHAN_WIDTH_20_NOHT:
1007  	case NL80211_CHAN_WIDTH_20:
1008  		break;
1009  	case NL80211_CHAN_WIDTH_40:
1010  		if (chandef.center_freq1 < chandef.chan->center_freq)
1011  			bss_cfg->band_cfg |= MWIFIEX_SEC_CHAN_BELOW;
1012  		else
1013  			bss_cfg->band_cfg |= MWIFIEX_SEC_CHAN_ABOVE;
1014  		break;
1015  	case NL80211_CHAN_WIDTH_80:
1016  	case NL80211_CHAN_WIDTH_80P80:
1017  	case NL80211_CHAN_WIDTH_160:
1018  		bss_cfg->band_cfg |=
1019  		    mwifiex_get_sec_chan_offset(bss_cfg->channel) << 4;
1020  		break;
1021  	default:
1022  		mwifiex_dbg(priv->adapter,
1023  			    WARN, "Unknown channel width: %d\n",
1024  			    chandef.width);
1025  		break;
1026  	}
1027  
1028  	priv->adapter->config_bands = config_bands;
1029  
1030  	if (old_bands != config_bands) {
1031  		mwifiex_send_domain_info_cmd_fw(priv->adapter->wiphy);
1032  		mwifiex_dnld_txpwr_table(priv);
1033  	}
1034  }
1035  
mwifiex_config_start_uap(struct mwifiex_private * priv,struct mwifiex_uap_bss_param * bss_cfg)1036  int mwifiex_config_start_uap(struct mwifiex_private *priv,
1037  			     struct mwifiex_uap_bss_param *bss_cfg)
1038  {
1039  	if (mwifiex_send_cmd(priv, HostCmd_CMD_UAP_SYS_CONFIG,
1040  			     HostCmd_ACT_GEN_SET,
1041  			     UAP_BSS_PARAMS_I, bss_cfg, true)) {
1042  		mwifiex_dbg(priv->adapter, ERROR,
1043  			    "Failed to set AP configuration\n");
1044  		return -1;
1045  	}
1046  
1047  	if (mwifiex_send_cmd(priv, HostCmd_CMD_UAP_BSS_START,
1048  			     HostCmd_ACT_GEN_SET, 0, NULL, true)) {
1049  		mwifiex_dbg(priv->adapter, ERROR,
1050  			    "Failed to start the BSS\n");
1051  		return -1;
1052  	}
1053  
1054  	if (priv->sec_info.wep_enabled)
1055  		priv->curr_pkt_filter |= HostCmd_ACT_MAC_WEP_ENABLE;
1056  	else
1057  		priv->curr_pkt_filter &= ~HostCmd_ACT_MAC_WEP_ENABLE;
1058  
1059  	if (mwifiex_send_cmd(priv, HostCmd_CMD_MAC_CONTROL,
1060  			     HostCmd_ACT_GEN_SET, 0,
1061  			     &priv->curr_pkt_filter, true))
1062  		return -1;
1063  
1064  	return 0;
1065  }
1066