1*73b01e57SJeff Chen // SPDX-License-Identifier: GPL-2.0-only
2*73b01e57SJeff Chen /*
3*73b01e57SJeff Chen * NXP Wireless LAN device driver: AP specific command handling
4*73b01e57SJeff Chen *
5*73b01e57SJeff Chen * Copyright 2011-2024 NXP
6*73b01e57SJeff Chen */
7*73b01e57SJeff Chen
8*73b01e57SJeff Chen #include "main.h"
9*73b01e57SJeff Chen #include "cmdevt.h"
10*73b01e57SJeff Chen #include "11n.h"
11*73b01e57SJeff Chen #include "11ac.h"
12*73b01e57SJeff Chen #include "11ax.h"
13*73b01e57SJeff Chen
14*73b01e57SJeff Chen /* Parse BSS params and append WPA/WPA2 TLVs to the command buffer. */
15*73b01e57SJeff Chen static void
nxpwifi_uap_bss_wpa(u8 ** tlv_buf,void * cmd_buf,u16 * param_size)16*73b01e57SJeff Chen nxpwifi_uap_bss_wpa(u8 **tlv_buf, void *cmd_buf, u16 *param_size)
17*73b01e57SJeff Chen {
18*73b01e57SJeff Chen struct host_cmd_tlv_pwk_cipher *pwk_cipher;
19*73b01e57SJeff Chen struct host_cmd_tlv_gwk_cipher *gwk_cipher;
20*73b01e57SJeff Chen struct host_cmd_tlv_passphrase *passphrase;
21*73b01e57SJeff Chen struct host_cmd_tlv_akmp *tlv_akmp;
22*73b01e57SJeff Chen struct nxpwifi_uap_bss_param *bss_cfg = cmd_buf;
23*73b01e57SJeff Chen u16 cmd_size = *param_size;
24*73b01e57SJeff Chen u8 *tlv = *tlv_buf;
25*73b01e57SJeff Chen
26*73b01e57SJeff Chen tlv_akmp = (struct host_cmd_tlv_akmp *)tlv;
27*73b01e57SJeff Chen tlv_akmp->header.type = cpu_to_le16(TLV_TYPE_UAP_AKMP);
28*73b01e57SJeff Chen tlv_akmp->header.len = cpu_to_le16(sizeof(struct host_cmd_tlv_akmp) -
29*73b01e57SJeff Chen sizeof(struct nxpwifi_ie_types_header));
30*73b01e57SJeff Chen tlv_akmp->key_mgmt_operation = cpu_to_le16(bss_cfg->key_mgmt_operation);
31*73b01e57SJeff Chen tlv_akmp->key_mgmt = cpu_to_le16(bss_cfg->key_mgmt);
32*73b01e57SJeff Chen cmd_size += sizeof(struct host_cmd_tlv_akmp);
33*73b01e57SJeff Chen tlv += sizeof(struct host_cmd_tlv_akmp);
34*73b01e57SJeff Chen
35*73b01e57SJeff Chen if (bss_cfg->wpa_cfg.pairwise_cipher_wpa & VALID_CIPHER_BITMAP) {
36*73b01e57SJeff Chen pwk_cipher = (struct host_cmd_tlv_pwk_cipher *)tlv;
37*73b01e57SJeff Chen pwk_cipher->header.type = cpu_to_le16(TLV_TYPE_PWK_CIPHER);
38*73b01e57SJeff Chen pwk_cipher->header.len =
39*73b01e57SJeff Chen cpu_to_le16(sizeof(struct host_cmd_tlv_pwk_cipher) -
40*73b01e57SJeff Chen sizeof(struct nxpwifi_ie_types_header));
41*73b01e57SJeff Chen pwk_cipher->proto = cpu_to_le16(PROTOCOL_WPA);
42*73b01e57SJeff Chen pwk_cipher->cipher = bss_cfg->wpa_cfg.pairwise_cipher_wpa;
43*73b01e57SJeff Chen cmd_size += sizeof(struct host_cmd_tlv_pwk_cipher);
44*73b01e57SJeff Chen tlv += sizeof(struct host_cmd_tlv_pwk_cipher);
45*73b01e57SJeff Chen }
46*73b01e57SJeff Chen
47*73b01e57SJeff Chen if (bss_cfg->wpa_cfg.pairwise_cipher_wpa2 & VALID_CIPHER_BITMAP) {
48*73b01e57SJeff Chen pwk_cipher = (struct host_cmd_tlv_pwk_cipher *)tlv;
49*73b01e57SJeff Chen pwk_cipher->header.type = cpu_to_le16(TLV_TYPE_PWK_CIPHER);
50*73b01e57SJeff Chen pwk_cipher->header.len =
51*73b01e57SJeff Chen cpu_to_le16(sizeof(struct host_cmd_tlv_pwk_cipher) -
52*73b01e57SJeff Chen sizeof(struct nxpwifi_ie_types_header));
53*73b01e57SJeff Chen pwk_cipher->proto = cpu_to_le16(PROTOCOL_WPA2);
54*73b01e57SJeff Chen pwk_cipher->cipher = bss_cfg->wpa_cfg.pairwise_cipher_wpa2;
55*73b01e57SJeff Chen cmd_size += sizeof(struct host_cmd_tlv_pwk_cipher);
56*73b01e57SJeff Chen tlv += sizeof(struct host_cmd_tlv_pwk_cipher);
57*73b01e57SJeff Chen }
58*73b01e57SJeff Chen
59*73b01e57SJeff Chen if (bss_cfg->wpa_cfg.group_cipher & VALID_CIPHER_BITMAP) {
60*73b01e57SJeff Chen gwk_cipher = (struct host_cmd_tlv_gwk_cipher *)tlv;
61*73b01e57SJeff Chen gwk_cipher->header.type = cpu_to_le16(TLV_TYPE_GWK_CIPHER);
62*73b01e57SJeff Chen gwk_cipher->header.len =
63*73b01e57SJeff Chen cpu_to_le16(sizeof(struct host_cmd_tlv_gwk_cipher) -
64*73b01e57SJeff Chen sizeof(struct nxpwifi_ie_types_header));
65*73b01e57SJeff Chen gwk_cipher->cipher = bss_cfg->wpa_cfg.group_cipher;
66*73b01e57SJeff Chen cmd_size += sizeof(struct host_cmd_tlv_gwk_cipher);
67*73b01e57SJeff Chen tlv += sizeof(struct host_cmd_tlv_gwk_cipher);
68*73b01e57SJeff Chen }
69*73b01e57SJeff Chen
70*73b01e57SJeff Chen if (bss_cfg->wpa_cfg.length) {
71*73b01e57SJeff Chen passphrase = (struct host_cmd_tlv_passphrase *)tlv;
72*73b01e57SJeff Chen passphrase->header.type =
73*73b01e57SJeff Chen cpu_to_le16(TLV_TYPE_UAP_WPA_PASSPHRASE);
74*73b01e57SJeff Chen passphrase->header.len = cpu_to_le16(bss_cfg->wpa_cfg.length);
75*73b01e57SJeff Chen memcpy(passphrase->passphrase, bss_cfg->wpa_cfg.passphrase,
76*73b01e57SJeff Chen bss_cfg->wpa_cfg.length);
77*73b01e57SJeff Chen cmd_size += sizeof(struct nxpwifi_ie_types_header) +
78*73b01e57SJeff Chen bss_cfg->wpa_cfg.length;
79*73b01e57SJeff Chen tlv += sizeof(struct nxpwifi_ie_types_header) +
80*73b01e57SJeff Chen bss_cfg->wpa_cfg.length;
81*73b01e57SJeff Chen }
82*73b01e57SJeff Chen
83*73b01e57SJeff Chen *param_size = cmd_size;
84*73b01e57SJeff Chen *tlv_buf = tlv;
85*73b01e57SJeff Chen }
86*73b01e57SJeff Chen
87*73b01e57SJeff Chen /* Parse BSS params and append WEP TLVs to the command buffer. */
88*73b01e57SJeff Chen static void
nxpwifi_uap_bss_wep(u8 ** tlv_buf,void * cmd_buf,u16 * param_size)89*73b01e57SJeff Chen nxpwifi_uap_bss_wep(u8 **tlv_buf, void *cmd_buf, u16 *param_size)
90*73b01e57SJeff Chen {
91*73b01e57SJeff Chen struct host_cmd_tlv_wep_key *wep_key;
92*73b01e57SJeff Chen u16 cmd_size = *param_size;
93*73b01e57SJeff Chen int i;
94*73b01e57SJeff Chen u8 *tlv = *tlv_buf;
95*73b01e57SJeff Chen struct nxpwifi_uap_bss_param *bss_cfg = cmd_buf;
96*73b01e57SJeff Chen
97*73b01e57SJeff Chen for (i = 0; i < NUM_WEP_KEYS; i++) {
98*73b01e57SJeff Chen if (bss_cfg->wep_cfg[i].length &&
99*73b01e57SJeff Chen (bss_cfg->wep_cfg[i].length == WLAN_KEY_LEN_WEP40 ||
100*73b01e57SJeff Chen bss_cfg->wep_cfg[i].length == WLAN_KEY_LEN_WEP104)) {
101*73b01e57SJeff Chen wep_key = (struct host_cmd_tlv_wep_key *)tlv;
102*73b01e57SJeff Chen wep_key->header.type =
103*73b01e57SJeff Chen cpu_to_le16(TLV_TYPE_UAP_WEP_KEY);
104*73b01e57SJeff Chen wep_key->header.len =
105*73b01e57SJeff Chen cpu_to_le16(bss_cfg->wep_cfg[i].length + 2);
106*73b01e57SJeff Chen wep_key->key_index = bss_cfg->wep_cfg[i].key_index;
107*73b01e57SJeff Chen wep_key->is_default = bss_cfg->wep_cfg[i].is_default;
108*73b01e57SJeff Chen memcpy(wep_key->key, bss_cfg->wep_cfg[i].key,
109*73b01e57SJeff Chen bss_cfg->wep_cfg[i].length);
110*73b01e57SJeff Chen cmd_size += sizeof(struct nxpwifi_ie_types_header) + 2 +
111*73b01e57SJeff Chen bss_cfg->wep_cfg[i].length;
112*73b01e57SJeff Chen tlv += sizeof(struct nxpwifi_ie_types_header) + 2 +
113*73b01e57SJeff Chen bss_cfg->wep_cfg[i].length;
114*73b01e57SJeff Chen }
115*73b01e57SJeff Chen }
116*73b01e57SJeff Chen
117*73b01e57SJeff Chen *param_size = cmd_size;
118*73b01e57SJeff Chen *tlv_buf = tlv;
119*73b01e57SJeff Chen }
120*73b01e57SJeff Chen
121*73b01e57SJeff Chen /* Parse BSS params and append TLVs to the command buffer. */
nxpwifi_uap_bss_param_prepare(struct nxpwifi_private * priv,u8 * tlv,void * cmd_buf,u16 * param_size)122*73b01e57SJeff Chen static int nxpwifi_uap_bss_param_prepare(struct nxpwifi_private *priv, u8 *tlv,
123*73b01e57SJeff Chen void *cmd_buf, u16 *param_size)
124*73b01e57SJeff Chen {
125*73b01e57SJeff Chen struct host_cmd_tlv_mac_addr *mac_tlv;
126*73b01e57SJeff Chen struct host_cmd_tlv_dtim_period *dtim_period;
127*73b01e57SJeff Chen struct host_cmd_tlv_beacon_period *beacon_period;
128*73b01e57SJeff Chen struct host_cmd_tlv_ssid *ssid;
129*73b01e57SJeff Chen struct host_cmd_tlv_bcast_ssid *bcast_ssid;
130*73b01e57SJeff Chen struct host_cmd_tlv_channel_band *chan_band;
131*73b01e57SJeff Chen struct host_cmd_tlv_frag_threshold *frag_threshold;
132*73b01e57SJeff Chen struct host_cmd_tlv_rts_threshold *rts_threshold;
133*73b01e57SJeff Chen struct host_cmd_tlv_retry_limit *retry_limit;
134*73b01e57SJeff Chen struct host_cmd_tlv_encrypt_protocol *encrypt_protocol;
135*73b01e57SJeff Chen struct host_cmd_tlv_auth_type *auth_type;
136*73b01e57SJeff Chen struct host_cmd_tlv_rates *tlv_rates;
137*73b01e57SJeff Chen struct host_cmd_tlv_ageout_timer *ao_timer, *ps_ao_timer;
138*73b01e57SJeff Chen struct host_cmd_tlv_power_constraint *pwr_ct;
139*73b01e57SJeff Chen struct nxpwifi_ie_types_htcap *htcap;
140*73b01e57SJeff Chen struct nxpwifi_uap_bss_param *bss_cfg = cmd_buf;
141*73b01e57SJeff Chen int i;
142*73b01e57SJeff Chen u16 cmd_size = *param_size;
143*73b01e57SJeff Chen
144*73b01e57SJeff Chen mac_tlv = (struct host_cmd_tlv_mac_addr *)tlv;
145*73b01e57SJeff Chen mac_tlv->header.type = cpu_to_le16(TLV_TYPE_UAP_MAC_ADDRESS);
146*73b01e57SJeff Chen mac_tlv->header.len = cpu_to_le16(ETH_ALEN);
147*73b01e57SJeff Chen memcpy(mac_tlv->mac_addr, bss_cfg->mac_addr, ETH_ALEN);
148*73b01e57SJeff Chen cmd_size += sizeof(struct host_cmd_tlv_mac_addr);
149*73b01e57SJeff Chen tlv += sizeof(struct host_cmd_tlv_mac_addr);
150*73b01e57SJeff Chen
151*73b01e57SJeff Chen if (bss_cfg->ssid.ssid_len) {
152*73b01e57SJeff Chen ssid = (struct host_cmd_tlv_ssid *)tlv;
153*73b01e57SJeff Chen ssid->header.type = cpu_to_le16(TLV_TYPE_UAP_SSID);
154*73b01e57SJeff Chen ssid->header.len = cpu_to_le16((u16)bss_cfg->ssid.ssid_len);
155*73b01e57SJeff Chen memcpy(ssid->ssid, bss_cfg->ssid.ssid, bss_cfg->ssid.ssid_len);
156*73b01e57SJeff Chen cmd_size += sizeof(struct nxpwifi_ie_types_header) +
157*73b01e57SJeff Chen bss_cfg->ssid.ssid_len;
158*73b01e57SJeff Chen tlv += sizeof(struct nxpwifi_ie_types_header) +
159*73b01e57SJeff Chen bss_cfg->ssid.ssid_len;
160*73b01e57SJeff Chen
161*73b01e57SJeff Chen bcast_ssid = (struct host_cmd_tlv_bcast_ssid *)tlv;
162*73b01e57SJeff Chen bcast_ssid->header.type = cpu_to_le16(TLV_TYPE_UAP_BCAST_SSID);
163*73b01e57SJeff Chen bcast_ssid->header.len =
164*73b01e57SJeff Chen cpu_to_le16(sizeof(bcast_ssid->bcast_ctl));
165*73b01e57SJeff Chen bcast_ssid->bcast_ctl = bss_cfg->bcast_ssid_ctl;
166*73b01e57SJeff Chen cmd_size += sizeof(struct host_cmd_tlv_bcast_ssid);
167*73b01e57SJeff Chen tlv += sizeof(struct host_cmd_tlv_bcast_ssid);
168*73b01e57SJeff Chen }
169*73b01e57SJeff Chen if (bss_cfg->rates[0]) {
170*73b01e57SJeff Chen tlv_rates = (struct host_cmd_tlv_rates *)tlv;
171*73b01e57SJeff Chen tlv_rates->header.type = cpu_to_le16(TLV_TYPE_UAP_RATES);
172*73b01e57SJeff Chen
173*73b01e57SJeff Chen for (i = 0; i < NXPWIFI_SUPPORTED_RATES && bss_cfg->rates[i];
174*73b01e57SJeff Chen i++)
175*73b01e57SJeff Chen tlv_rates->rates[i] = bss_cfg->rates[i];
176*73b01e57SJeff Chen
177*73b01e57SJeff Chen tlv_rates->header.len = cpu_to_le16(i);
178*73b01e57SJeff Chen cmd_size += sizeof(struct host_cmd_tlv_rates) + i;
179*73b01e57SJeff Chen tlv += sizeof(struct host_cmd_tlv_rates) + i;
180*73b01e57SJeff Chen }
181*73b01e57SJeff Chen if (bss_cfg->channel &&
182*73b01e57SJeff Chen (((bss_cfg->band_cfg & BIT(0)) == BAND_CONFIG_BG &&
183*73b01e57SJeff Chen bss_cfg->channel <= MAX_CHANNEL_BAND_BG) ||
184*73b01e57SJeff Chen ((bss_cfg->band_cfg & BIT(0)) == BAND_CONFIG_A &&
185*73b01e57SJeff Chen bss_cfg->channel <= MAX_CHANNEL_BAND_A))) {
186*73b01e57SJeff Chen chan_band = (struct host_cmd_tlv_channel_band *)tlv;
187*73b01e57SJeff Chen chan_band->header.type = cpu_to_le16(TLV_TYPE_CHANNELBANDLIST);
188*73b01e57SJeff Chen chan_band->header.len =
189*73b01e57SJeff Chen cpu_to_le16(sizeof(struct host_cmd_tlv_channel_band) -
190*73b01e57SJeff Chen sizeof(struct nxpwifi_ie_types_header));
191*73b01e57SJeff Chen chan_band->band_config = bss_cfg->band_cfg;
192*73b01e57SJeff Chen chan_band->channel = bss_cfg->channel;
193*73b01e57SJeff Chen cmd_size += sizeof(struct host_cmd_tlv_channel_band);
194*73b01e57SJeff Chen tlv += sizeof(struct host_cmd_tlv_channel_band);
195*73b01e57SJeff Chen }
196*73b01e57SJeff Chen if (bss_cfg->beacon_period >= NXPWIFI_BEACON_PERIOD_MIN &&
197*73b01e57SJeff Chen bss_cfg->beacon_period <= NXPWIFI_BEACON_PERIOD_MAX) {
198*73b01e57SJeff Chen beacon_period = (struct host_cmd_tlv_beacon_period *)tlv;
199*73b01e57SJeff Chen beacon_period->header.type =
200*73b01e57SJeff Chen cpu_to_le16(TLV_TYPE_UAP_BEACON_PERIOD);
201*73b01e57SJeff Chen beacon_period->header.len =
202*73b01e57SJeff Chen cpu_to_le16(sizeof(struct host_cmd_tlv_beacon_period) -
203*73b01e57SJeff Chen sizeof(struct nxpwifi_ie_types_header));
204*73b01e57SJeff Chen beacon_period->period = cpu_to_le16(bss_cfg->beacon_period);
205*73b01e57SJeff Chen cmd_size += sizeof(struct host_cmd_tlv_beacon_period);
206*73b01e57SJeff Chen tlv += sizeof(struct host_cmd_tlv_beacon_period);
207*73b01e57SJeff Chen }
208*73b01e57SJeff Chen if (bss_cfg->dtim_period >= NXPWIFI_MIN_DTIM_PERIOD &&
209*73b01e57SJeff Chen bss_cfg->dtim_period <= NXPWIFI_MAX_DTIM_PERIOD) {
210*73b01e57SJeff Chen dtim_period = (struct host_cmd_tlv_dtim_period *)tlv;
211*73b01e57SJeff Chen dtim_period->header.type =
212*73b01e57SJeff Chen cpu_to_le16(TLV_TYPE_UAP_DTIM_PERIOD);
213*73b01e57SJeff Chen dtim_period->header.len =
214*73b01e57SJeff Chen cpu_to_le16(sizeof(struct host_cmd_tlv_dtim_period) -
215*73b01e57SJeff Chen sizeof(struct nxpwifi_ie_types_header));
216*73b01e57SJeff Chen dtim_period->period = bss_cfg->dtim_period;
217*73b01e57SJeff Chen cmd_size += sizeof(struct host_cmd_tlv_dtim_period);
218*73b01e57SJeff Chen tlv += sizeof(struct host_cmd_tlv_dtim_period);
219*73b01e57SJeff Chen }
220*73b01e57SJeff Chen if (bss_cfg->rts_threshold <= NXPWIFI_RTS_THRESHOLD_MAX) {
221*73b01e57SJeff Chen rts_threshold = (struct host_cmd_tlv_rts_threshold *)tlv;
222*73b01e57SJeff Chen rts_threshold->header.type =
223*73b01e57SJeff Chen cpu_to_le16(TLV_TYPE_UAP_RTS_THRESHOLD);
224*73b01e57SJeff Chen rts_threshold->header.len =
225*73b01e57SJeff Chen cpu_to_le16(sizeof(struct host_cmd_tlv_rts_threshold) -
226*73b01e57SJeff Chen sizeof(struct nxpwifi_ie_types_header));
227*73b01e57SJeff Chen rts_threshold->rts_thr = cpu_to_le16(bss_cfg->rts_threshold);
228*73b01e57SJeff Chen cmd_size += sizeof(struct host_cmd_tlv_frag_threshold);
229*73b01e57SJeff Chen tlv += sizeof(struct host_cmd_tlv_frag_threshold);
230*73b01e57SJeff Chen }
231*73b01e57SJeff Chen if (bss_cfg->frag_threshold >= NXPWIFI_FRAG_THRESHOLD_MIN &&
232*73b01e57SJeff Chen bss_cfg->frag_threshold <= NXPWIFI_FRAG_THRESHOLD_MAX) {
233*73b01e57SJeff Chen frag_threshold = (struct host_cmd_tlv_frag_threshold *)tlv;
234*73b01e57SJeff Chen frag_threshold->header.type =
235*73b01e57SJeff Chen cpu_to_le16(TLV_TYPE_UAP_FRAG_THRESHOLD);
236*73b01e57SJeff Chen frag_threshold->header.len =
237*73b01e57SJeff Chen cpu_to_le16(sizeof(struct host_cmd_tlv_frag_threshold) -
238*73b01e57SJeff Chen sizeof(struct nxpwifi_ie_types_header));
239*73b01e57SJeff Chen frag_threshold->frag_thr = cpu_to_le16(bss_cfg->frag_threshold);
240*73b01e57SJeff Chen cmd_size += sizeof(struct host_cmd_tlv_frag_threshold);
241*73b01e57SJeff Chen tlv += sizeof(struct host_cmd_tlv_frag_threshold);
242*73b01e57SJeff Chen }
243*73b01e57SJeff Chen if (bss_cfg->retry_limit <= NXPWIFI_RETRY_LIMIT_MAX) {
244*73b01e57SJeff Chen retry_limit = (struct host_cmd_tlv_retry_limit *)tlv;
245*73b01e57SJeff Chen retry_limit->header.type =
246*73b01e57SJeff Chen cpu_to_le16(TLV_TYPE_UAP_RETRY_LIMIT);
247*73b01e57SJeff Chen retry_limit->header.len =
248*73b01e57SJeff Chen cpu_to_le16(sizeof(struct host_cmd_tlv_retry_limit) -
249*73b01e57SJeff Chen sizeof(struct nxpwifi_ie_types_header));
250*73b01e57SJeff Chen retry_limit->limit = (u8)bss_cfg->retry_limit;
251*73b01e57SJeff Chen cmd_size += sizeof(struct host_cmd_tlv_retry_limit);
252*73b01e57SJeff Chen tlv += sizeof(struct host_cmd_tlv_retry_limit);
253*73b01e57SJeff Chen }
254*73b01e57SJeff Chen if ((bss_cfg->protocol & PROTOCOL_WPA) ||
255*73b01e57SJeff Chen (bss_cfg->protocol & PROTOCOL_WPA2) ||
256*73b01e57SJeff Chen (bss_cfg->protocol & PROTOCOL_EAP))
257*73b01e57SJeff Chen nxpwifi_uap_bss_wpa(&tlv, cmd_buf, &cmd_size);
258*73b01e57SJeff Chen else
259*73b01e57SJeff Chen nxpwifi_uap_bss_wep(&tlv, cmd_buf, &cmd_size);
260*73b01e57SJeff Chen
261*73b01e57SJeff Chen if (bss_cfg->auth_mode <= WLAN_AUTH_SHARED_KEY ||
262*73b01e57SJeff Chen bss_cfg->auth_mode == NXPWIFI_AUTH_MODE_AUTO) {
263*73b01e57SJeff Chen auth_type = (struct host_cmd_tlv_auth_type *)tlv;
264*73b01e57SJeff Chen auth_type->header.type = cpu_to_le16(TLV_TYPE_AUTH_TYPE);
265*73b01e57SJeff Chen auth_type->header.len =
266*73b01e57SJeff Chen cpu_to_le16(sizeof(struct host_cmd_tlv_auth_type) -
267*73b01e57SJeff Chen sizeof(struct nxpwifi_ie_types_header));
268*73b01e57SJeff Chen auth_type->auth_type = (u8)bss_cfg->auth_mode;
269*73b01e57SJeff Chen auth_type->pwe_derivation = 0;
270*73b01e57SJeff Chen auth_type->transition_disable = 0;
271*73b01e57SJeff Chen cmd_size += sizeof(struct host_cmd_tlv_auth_type);
272*73b01e57SJeff Chen tlv += sizeof(struct host_cmd_tlv_auth_type);
273*73b01e57SJeff Chen }
274*73b01e57SJeff Chen if (bss_cfg->protocol) {
275*73b01e57SJeff Chen encrypt_protocol = (struct host_cmd_tlv_encrypt_protocol *)tlv;
276*73b01e57SJeff Chen encrypt_protocol->header.type =
277*73b01e57SJeff Chen cpu_to_le16(TLV_TYPE_UAP_ENCRY_PROTOCOL);
278*73b01e57SJeff Chen encrypt_protocol->header.len =
279*73b01e57SJeff Chen cpu_to_le16(sizeof(struct host_cmd_tlv_encrypt_protocol)
280*73b01e57SJeff Chen - sizeof(struct nxpwifi_ie_types_header));
281*73b01e57SJeff Chen encrypt_protocol->proto = cpu_to_le16(bss_cfg->protocol);
282*73b01e57SJeff Chen cmd_size += sizeof(struct host_cmd_tlv_encrypt_protocol);
283*73b01e57SJeff Chen tlv += sizeof(struct host_cmd_tlv_encrypt_protocol);
284*73b01e57SJeff Chen }
285*73b01e57SJeff Chen
286*73b01e57SJeff Chen if (bss_cfg->ht_cap.cap_info) {
287*73b01e57SJeff Chen htcap = (struct nxpwifi_ie_types_htcap *)tlv;
288*73b01e57SJeff Chen htcap->header.type = cpu_to_le16(WLAN_EID_HT_CAPABILITY);
289*73b01e57SJeff Chen htcap->header.len =
290*73b01e57SJeff Chen cpu_to_le16(sizeof(struct ieee80211_ht_cap));
291*73b01e57SJeff Chen htcap->ht_cap.cap_info = bss_cfg->ht_cap.cap_info;
292*73b01e57SJeff Chen htcap->ht_cap.ampdu_params_info =
293*73b01e57SJeff Chen bss_cfg->ht_cap.ampdu_params_info;
294*73b01e57SJeff Chen memcpy(&htcap->ht_cap.mcs, &bss_cfg->ht_cap.mcs,
295*73b01e57SJeff Chen sizeof(struct ieee80211_mcs_info));
296*73b01e57SJeff Chen htcap->ht_cap.extended_ht_cap_info =
297*73b01e57SJeff Chen bss_cfg->ht_cap.extended_ht_cap_info;
298*73b01e57SJeff Chen htcap->ht_cap.tx_BF_cap_info = bss_cfg->ht_cap.tx_BF_cap_info;
299*73b01e57SJeff Chen htcap->ht_cap.antenna_selection_info =
300*73b01e57SJeff Chen bss_cfg->ht_cap.antenna_selection_info;
301*73b01e57SJeff Chen cmd_size += sizeof(struct nxpwifi_ie_types_htcap);
302*73b01e57SJeff Chen tlv += sizeof(struct nxpwifi_ie_types_htcap);
303*73b01e57SJeff Chen }
304*73b01e57SJeff Chen
305*73b01e57SJeff Chen if (priv->wmm_enabled) {
306*73b01e57SJeff Chen struct nxpwifi_ie_types_wmmcap *wmm_cap;
307*73b01e57SJeff Chen struct nxpwifi_types_wmm_info *fw_wmm;
308*73b01e57SJeff Chen const struct ieee80211_wmm_param_ie *ie;
309*73b01e57SJeff Chen
310*73b01e57SJeff Chen wmm_cap = (struct nxpwifi_ie_types_wmmcap *)tlv;
311*73b01e57SJeff Chen fw_wmm = &wmm_cap->wmm_info;
312*73b01e57SJeff Chen ie = &bss_cfg->wmm_element;
313*73b01e57SJeff Chen
314*73b01e57SJeff Chen wmm_cap->header.type = cpu_to_le16(WLAN_EID_VENDOR_SPECIFIC);
315*73b01e57SJeff Chen wmm_cap->header.len =
316*73b01e57SJeff Chen cpu_to_le16(sizeof(struct nxpwifi_types_wmm_info));
317*73b01e57SJeff Chen
318*73b01e57SJeff Chen /* Map 802.11 WMM IE fields to FW WMM TLV payload */
319*73b01e57SJeff Chen fw_wmm->oui[0] = ie->oui[0];
320*73b01e57SJeff Chen fw_wmm->oui[1] = ie->oui[1];
321*73b01e57SJeff Chen fw_wmm->oui[2] = ie->oui[2];
322*73b01e57SJeff Chen fw_wmm->oui[3] = ie->oui_type;
323*73b01e57SJeff Chen
324*73b01e57SJeff Chen fw_wmm->subtype = ie->oui_subtype;
325*73b01e57SJeff Chen fw_wmm->version = ie->version;
326*73b01e57SJeff Chen fw_wmm->qos_info = ie->qos_info;
327*73b01e57SJeff Chen fw_wmm->reserved = ie->reserved;
328*73b01e57SJeff Chen
329*73b01e57SJeff Chen memcpy(fw_wmm->ac, ie->ac, sizeof(fw_wmm->ac));
330*73b01e57SJeff Chen
331*73b01e57SJeff Chen cmd_size += sizeof(*wmm_cap);
332*73b01e57SJeff Chen tlv += sizeof(*wmm_cap);
333*73b01e57SJeff Chen }
334*73b01e57SJeff Chen
335*73b01e57SJeff Chen if (bss_cfg->sta_ao_timer) {
336*73b01e57SJeff Chen ao_timer = (struct host_cmd_tlv_ageout_timer *)tlv;
337*73b01e57SJeff Chen ao_timer->header.type = cpu_to_le16(TLV_TYPE_UAP_AO_TIMER);
338*73b01e57SJeff Chen ao_timer->header.len = cpu_to_le16(sizeof(*ao_timer) -
339*73b01e57SJeff Chen sizeof(struct nxpwifi_ie_types_header));
340*73b01e57SJeff Chen ao_timer->sta_ao_timer = cpu_to_le32(bss_cfg->sta_ao_timer);
341*73b01e57SJeff Chen cmd_size += sizeof(*ao_timer);
342*73b01e57SJeff Chen tlv += sizeof(*ao_timer);
343*73b01e57SJeff Chen }
344*73b01e57SJeff Chen
345*73b01e57SJeff Chen if (bss_cfg->power_constraint) {
346*73b01e57SJeff Chen pwr_ct = (void *)tlv;
347*73b01e57SJeff Chen pwr_ct->header.type = cpu_to_le16(TLV_TYPE_PWR_CONSTRAINT);
348*73b01e57SJeff Chen pwr_ct->header.len = cpu_to_le16(sizeof(u8));
349*73b01e57SJeff Chen pwr_ct->constraint = bss_cfg->power_constraint;
350*73b01e57SJeff Chen cmd_size += sizeof(*pwr_ct);
351*73b01e57SJeff Chen tlv += sizeof(*pwr_ct);
352*73b01e57SJeff Chen }
353*73b01e57SJeff Chen
354*73b01e57SJeff Chen if (bss_cfg->ps_sta_ao_timer) {
355*73b01e57SJeff Chen ps_ao_timer = (struct host_cmd_tlv_ageout_timer *)tlv;
356*73b01e57SJeff Chen ps_ao_timer->header.type =
357*73b01e57SJeff Chen cpu_to_le16(TLV_TYPE_UAP_PS_AO_TIMER);
358*73b01e57SJeff Chen ps_ao_timer->header.len = cpu_to_le16(sizeof(*ps_ao_timer) -
359*73b01e57SJeff Chen sizeof(struct nxpwifi_ie_types_header));
360*73b01e57SJeff Chen ps_ao_timer->sta_ao_timer =
361*73b01e57SJeff Chen cpu_to_le32(bss_cfg->ps_sta_ao_timer);
362*73b01e57SJeff Chen cmd_size += sizeof(*ps_ao_timer);
363*73b01e57SJeff Chen tlv += sizeof(*ps_ao_timer);
364*73b01e57SJeff Chen }
365*73b01e57SJeff Chen
366*73b01e57SJeff Chen *param_size = cmd_size;
367*73b01e57SJeff Chen
368*73b01e57SJeff Chen return 0;
369*73b01e57SJeff Chen }
370*73b01e57SJeff Chen
371*73b01e57SJeff Chen /* Parse custom IEs and write them to the command buffer. */
nxpwifi_uap_custom_ie_prepare(u8 * tlv,void * cmd_buf,u16 * ie_size)372*73b01e57SJeff Chen static int nxpwifi_uap_custom_ie_prepare(u8 *tlv, void *cmd_buf, u16 *ie_size)
373*73b01e57SJeff Chen {
374*73b01e57SJeff Chen struct nxpwifi_ie_list *ap_ie = cmd_buf;
375*73b01e57SJeff Chen struct nxpwifi_ie_types_header *tlv_ie = (void *)tlv;
376*73b01e57SJeff Chen
377*73b01e57SJeff Chen if (!ap_ie || !ap_ie->len)
378*73b01e57SJeff Chen return -EINVAL;
379*73b01e57SJeff Chen
380*73b01e57SJeff Chen *ie_size += le16_to_cpu(ap_ie->len) +
381*73b01e57SJeff Chen sizeof(struct nxpwifi_ie_types_header);
382*73b01e57SJeff Chen
383*73b01e57SJeff Chen tlv_ie->type = cpu_to_le16(TLV_TYPE_MGMT_IE);
384*73b01e57SJeff Chen tlv_ie->len = ap_ie->len;
385*73b01e57SJeff Chen tlv += sizeof(struct nxpwifi_ie_types_header);
386*73b01e57SJeff Chen
387*73b01e57SJeff Chen memcpy(tlv, ap_ie->ie_list, le16_to_cpu(ap_ie->len));
388*73b01e57SJeff Chen
389*73b01e57SJeff Chen return 0;
390*73b01e57SJeff Chen }
391*73b01e57SJeff Chen
392*73b01e57SJeff Chen static int
nxpwifi_cmd_uap_sys_config(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)393*73b01e57SJeff Chen nxpwifi_cmd_uap_sys_config(struct nxpwifi_private *priv,
394*73b01e57SJeff Chen struct host_cmd_ds_command *cmd,
395*73b01e57SJeff Chen u16 cmd_no, void *data_buf,
396*73b01e57SJeff Chen u16 cmd_action, u32 cmd_type)
397*73b01e57SJeff Chen {
398*73b01e57SJeff Chen u8 *tlv;
399*73b01e57SJeff Chen u16 cmd_size, param_size, ie_size;
400*73b01e57SJeff Chen struct host_cmd_ds_sys_config *sys_cfg;
401*73b01e57SJeff Chen int ret = 0;
402*73b01e57SJeff Chen
403*73b01e57SJeff Chen cmd->command = cpu_to_le16(HOST_CMD_UAP_SYS_CONFIG);
404*73b01e57SJeff Chen cmd_size = (u16)(sizeof(struct host_cmd_ds_sys_config) + S_DS_GEN);
405*73b01e57SJeff Chen sys_cfg = &cmd->params.uap_sys_config;
406*73b01e57SJeff Chen sys_cfg->action = cpu_to_le16(cmd_action);
407*73b01e57SJeff Chen tlv = sys_cfg->tlv;
408*73b01e57SJeff Chen
409*73b01e57SJeff Chen switch (cmd_type) {
410*73b01e57SJeff Chen case UAP_BSS_PARAMS_I:
411*73b01e57SJeff Chen param_size = cmd_size;
412*73b01e57SJeff Chen ret = nxpwifi_uap_bss_param_prepare(priv, tlv, data_buf, ¶m_size);
413*73b01e57SJeff Chen if (ret)
414*73b01e57SJeff Chen return ret;
415*73b01e57SJeff Chen cmd->size = cpu_to_le16(param_size);
416*73b01e57SJeff Chen break;
417*73b01e57SJeff Chen case UAP_CUSTOM_IE_I:
418*73b01e57SJeff Chen ie_size = cmd_size;
419*73b01e57SJeff Chen ret = nxpwifi_uap_custom_ie_prepare(tlv, data_buf, &ie_size);
420*73b01e57SJeff Chen if (ret)
421*73b01e57SJeff Chen return ret;
422*73b01e57SJeff Chen cmd->size = cpu_to_le16(ie_size);
423*73b01e57SJeff Chen break;
424*73b01e57SJeff Chen default:
425*73b01e57SJeff Chen return -EINVAL;
426*73b01e57SJeff Chen }
427*73b01e57SJeff Chen
428*73b01e57SJeff Chen return ret;
429*73b01e57SJeff Chen }
430*73b01e57SJeff Chen
431*73b01e57SJeff Chen static int
nxpwifi_cmd_uap_bss_start(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)432*73b01e57SJeff Chen nxpwifi_cmd_uap_bss_start(struct nxpwifi_private *priv,
433*73b01e57SJeff Chen struct host_cmd_ds_command *cmd,
434*73b01e57SJeff Chen u16 cmd_no, void *data_buf,
435*73b01e57SJeff Chen u16 cmd_action, u32 cmd_type)
436*73b01e57SJeff Chen {
437*73b01e57SJeff Chen struct nxpwifi_ie_types_host_mlme *tlv;
438*73b01e57SJeff Chen int size;
439*73b01e57SJeff Chen
440*73b01e57SJeff Chen cmd->command = cpu_to_le16(HOST_CMD_UAP_BSS_START);
441*73b01e57SJeff Chen size = S_DS_GEN;
442*73b01e57SJeff Chen
443*73b01e57SJeff Chen tlv = (struct nxpwifi_ie_types_host_mlme *)((u8 *)cmd + size);
444*73b01e57SJeff Chen tlv->header.type = cpu_to_le16(TLV_TYPE_HOST_MLME);
445*73b01e57SJeff Chen tlv->header.len = cpu_to_le16(sizeof(tlv->host_mlme));
446*73b01e57SJeff Chen tlv->host_mlme = 1;
447*73b01e57SJeff Chen size += sizeof(struct nxpwifi_ie_types_host_mlme);
448*73b01e57SJeff Chen
449*73b01e57SJeff Chen cmd->size = cpu_to_le16(size);
450*73b01e57SJeff Chen
451*73b01e57SJeff Chen return 0;
452*73b01e57SJeff Chen }
453*73b01e57SJeff Chen
454*73b01e57SJeff Chen static int
nxpwifi_ret_uap_bss_start(struct nxpwifi_private * priv,struct host_cmd_ds_command * resp,u16 cmdresp_no,void * data_buf)455*73b01e57SJeff Chen nxpwifi_ret_uap_bss_start(struct nxpwifi_private *priv,
456*73b01e57SJeff Chen struct host_cmd_ds_command *resp,
457*73b01e57SJeff Chen u16 cmdresp_no,
458*73b01e57SJeff Chen void *data_buf)
459*73b01e57SJeff Chen {
460*73b01e57SJeff Chen struct nxpwifi_adapter *adapter = priv->adapter;
461*73b01e57SJeff Chen
462*73b01e57SJeff Chen adapter->tx_lock_flag = false;
463*73b01e57SJeff Chen adapter->pps_uapsd_mode = false;
464*73b01e57SJeff Chen adapter->delay_null_pkt = false;
465*73b01e57SJeff Chen priv->bss_started = 1;
466*73b01e57SJeff Chen
467*73b01e57SJeff Chen return 0;
468*73b01e57SJeff Chen }
469*73b01e57SJeff Chen
470*73b01e57SJeff Chen static int
nxpwifi_ret_uap_bss_stop(struct nxpwifi_private * priv,struct host_cmd_ds_command * resp,u16 cmdresp_no,void * data_buf)471*73b01e57SJeff Chen nxpwifi_ret_uap_bss_stop(struct nxpwifi_private *priv,
472*73b01e57SJeff Chen struct host_cmd_ds_command *resp,
473*73b01e57SJeff Chen u16 cmdresp_no,
474*73b01e57SJeff Chen void *data_buf)
475*73b01e57SJeff Chen {
476*73b01e57SJeff Chen priv->bss_started = 0;
477*73b01e57SJeff Chen
478*73b01e57SJeff Chen return 0;
479*73b01e57SJeff Chen }
480*73b01e57SJeff Chen
nxpwifi_ret_apcmd_sta_list(struct nxpwifi_private * priv,struct host_cmd_ds_command * resp,u16 cmdresp_no,void * data_buf)481*73b01e57SJeff Chen static int nxpwifi_ret_apcmd_sta_list(struct nxpwifi_private *priv,
482*73b01e57SJeff Chen struct host_cmd_ds_command *resp,
483*73b01e57SJeff Chen u16 cmdresp_no, void *data_buf)
484*73b01e57SJeff Chen {
485*73b01e57SJeff Chen struct host_cmd_ds_sta_list *sta_list = &resp->params.sta_list;
486*73b01e57SJeff Chen struct nxpwifi_ie_types_sta_info *sta_info;
487*73b01e57SJeff Chen struct nxpwifi_sta_node *sta_node;
488*73b01e57SJeff Chen u16 sta_count;
489*73b01e57SJeff Chen u32 resp_size;
490*73b01e57SJeff Chen u32 base;
491*73b01e57SJeff Chen u32 required_size;
492*73b01e57SJeff Chen int i;
493*73b01e57SJeff Chen
494*73b01e57SJeff Chen resp_size = le16_to_cpu(resp->size);
495*73b01e57SJeff Chen sta_count = le16_to_cpu(sta_list->sta_count);
496*73b01e57SJeff Chen
497*73b01e57SJeff Chen /* End of fixed fields before sta_list.tlv[] */
498*73b01e57SJeff Chen base = offsetofend(struct host_cmd_ds_command, params.sta_list.sta_count);
499*73b01e57SJeff Chen
500*73b01e57SJeff Chen /* At least fixed fields must be present */
501*73b01e57SJeff Chen if (resp_size < base)
502*73b01e57SJeff Chen return -EINVAL;
503*73b01e57SJeff Chen
504*73b01e57SJeff Chen required_size = base + sta_count * sizeof(*sta_info);
505*73b01e57SJeff Chen
506*73b01e57SJeff Chen /* Verify firmware did not claim more entries than the buffer holds */
507*73b01e57SJeff Chen if (resp_size < required_size)
508*73b01e57SJeff Chen return -EINVAL;
509*73b01e57SJeff Chen
510*73b01e57SJeff Chen sta_info = (void *)sta_list->tlv;
511*73b01e57SJeff Chen
512*73b01e57SJeff Chen rcu_read_lock();
513*73b01e57SJeff Chen for (i = 0; i < sta_count; i++) {
514*73b01e57SJeff Chen sta_node = nxpwifi_get_sta_entry(priv, sta_info->mac);
515*73b01e57SJeff Chen if (unlikely(!sta_node)) {
516*73b01e57SJeff Chen sta_info++;
517*73b01e57SJeff Chen continue;
518*73b01e57SJeff Chen }
519*73b01e57SJeff Chen
520*73b01e57SJeff Chen sta_node->stats.rssi = sta_info->rssi;
521*73b01e57SJeff Chen sta_info++;
522*73b01e57SJeff Chen }
523*73b01e57SJeff Chen rcu_read_unlock();
524*73b01e57SJeff Chen
525*73b01e57SJeff Chen return 0;
526*73b01e57SJeff Chen }
527*73b01e57SJeff Chen
528*73b01e57SJeff Chen /* Build AP deauth command for the given MAC address. */
nxpwifi_cmd_uap_sta_deauth(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)529*73b01e57SJeff Chen static int nxpwifi_cmd_uap_sta_deauth(struct nxpwifi_private *priv,
530*73b01e57SJeff Chen struct host_cmd_ds_command *cmd,
531*73b01e57SJeff Chen u16 cmd_no, void *data_buf,
532*73b01e57SJeff Chen u16 cmd_action, u32 cmd_type)
533*73b01e57SJeff Chen {
534*73b01e57SJeff Chen struct host_cmd_ds_sta_deauth *sta_deauth = &cmd->params.sta_deauth;
535*73b01e57SJeff Chen u8 *mac = (u8 *)data_buf;
536*73b01e57SJeff Chen
537*73b01e57SJeff Chen cmd->command = cpu_to_le16(HOST_CMD_UAP_STA_DEAUTH);
538*73b01e57SJeff Chen memcpy(sta_deauth->mac, mac, ETH_ALEN);
539*73b01e57SJeff Chen sta_deauth->reason = cpu_to_le16(WLAN_REASON_DEAUTH_LEAVING);
540*73b01e57SJeff Chen
541*73b01e57SJeff Chen cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_sta_deauth) +
542*73b01e57SJeff Chen S_DS_GEN);
543*73b01e57SJeff Chen return 0;
544*73b01e57SJeff Chen }
545*73b01e57SJeff Chen
546*73b01e57SJeff Chen static int
nxpwifi_cmd_uap_chan_report_request(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)547*73b01e57SJeff Chen nxpwifi_cmd_uap_chan_report_request(struct nxpwifi_private *priv,
548*73b01e57SJeff Chen struct host_cmd_ds_command *cmd,
549*73b01e57SJeff Chen u16 cmd_no, void *data_buf,
550*73b01e57SJeff Chen u16 cmd_action, u32 cmd_type)
551*73b01e57SJeff Chen {
552*73b01e57SJeff Chen return nxpwifi_cmd_issue_chan_report_request(priv, cmd, data_buf);
553*73b01e57SJeff Chen }
554*73b01e57SJeff Chen
555*73b01e57SJeff Chen /* Build AP add-station command. */
556*73b01e57SJeff Chen static int
nxpwifi_cmd_uap_add_new_station(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)557*73b01e57SJeff Chen nxpwifi_cmd_uap_add_new_station(struct nxpwifi_private *priv,
558*73b01e57SJeff Chen struct host_cmd_ds_command *cmd,
559*73b01e57SJeff Chen u16 cmd_no, void *data_buf,
560*73b01e57SJeff Chen u16 cmd_action, u32 cmd_type)
561*73b01e57SJeff Chen {
562*73b01e57SJeff Chen struct host_cmd_ds_add_station *new_sta = &cmd->params.sta_info;
563*73b01e57SJeff Chen struct nxpwifi_sta_info *add_sta = (struct nxpwifi_sta_info *)data_buf;
564*73b01e57SJeff Chen struct station_parameters *params = add_sta->params;
565*73b01e57SJeff Chen struct nxpwifi_sta_node *sta_ptr;
566*73b01e57SJeff Chen u16 cmd_size;
567*73b01e57SJeff Chen u8 *pos, *cmd_end;
568*73b01e57SJeff Chen u16 tlv_len;
569*73b01e57SJeff Chen struct nxpwifi_ie_types_sta_flag *sta_flag;
570*73b01e57SJeff Chen int i;
571*73b01e57SJeff Chen
572*73b01e57SJeff Chen cmd->command = cpu_to_le16(HOST_CMD_ADD_NEW_STATION);
573*73b01e57SJeff Chen new_sta->action = cpu_to_le16(cmd_action);
574*73b01e57SJeff Chen cmd_size = sizeof(struct host_cmd_ds_add_station) + S_DS_GEN;
575*73b01e57SJeff Chen
576*73b01e57SJeff Chen if (cmd_action == HOST_ACT_ADD_STA)
577*73b01e57SJeff Chen sta_ptr = nxpwifi_add_sta_entry(priv, add_sta->peer_mac);
578*73b01e57SJeff Chen else
579*73b01e57SJeff Chen sta_ptr = nxpwifi_get_sta_entry_rcu(priv, add_sta->peer_mac);
580*73b01e57SJeff Chen
581*73b01e57SJeff Chen if (!sta_ptr)
582*73b01e57SJeff Chen return -EINVAL;
583*73b01e57SJeff Chen
584*73b01e57SJeff Chen memcpy(new_sta->peer_mac, add_sta->peer_mac, ETH_ALEN);
585*73b01e57SJeff Chen
586*73b01e57SJeff Chen if (cmd_action == HOST_ACT_REMOVE_STA) {
587*73b01e57SJeff Chen cmd->size = cpu_to_le16(cmd_size);
588*73b01e57SJeff Chen return 0;
589*73b01e57SJeff Chen }
590*73b01e57SJeff Chen
591*73b01e57SJeff Chen new_sta->aid = cpu_to_le16(params->aid);
592*73b01e57SJeff Chen new_sta->listen_interval = cpu_to_le32(params->listen_interval);
593*73b01e57SJeff Chen new_sta->cap_info = cpu_to_le16(params->capability);
594*73b01e57SJeff Chen
595*73b01e57SJeff Chen pos = new_sta->tlv;
596*73b01e57SJeff Chen cmd_end = (u8 *)cmd;
597*73b01e57SJeff Chen cmd_end += (NXPWIFI_SIZE_OF_CMD_BUFFER - 1);
598*73b01e57SJeff Chen
599*73b01e57SJeff Chen if (params->sta_flags_set & NL80211_STA_FLAG_WME)
600*73b01e57SJeff Chen sta_ptr->is_wmm_enabled = 1;
601*73b01e57SJeff Chen sta_flag = (struct nxpwifi_ie_types_sta_flag *)pos;
602*73b01e57SJeff Chen sta_flag->header.type = cpu_to_le16(TLV_TYPE_UAP_STA_FLAGS);
603*73b01e57SJeff Chen sta_flag->header.len = cpu_to_le16(sizeof(__le32));
604*73b01e57SJeff Chen sta_flag->sta_flags = cpu_to_le32(params->sta_flags_set);
605*73b01e57SJeff Chen pos += sizeof(struct nxpwifi_ie_types_sta_flag);
606*73b01e57SJeff Chen cmd_size += sizeof(struct nxpwifi_ie_types_sta_flag);
607*73b01e57SJeff Chen
608*73b01e57SJeff Chen if (params->ext_capab_len) {
609*73b01e57SJeff Chen u8 *data = (u8 *)params->ext_capab;
610*73b01e57SJeff Chen u16 len = params->ext_capab_len;
611*73b01e57SJeff Chen
612*73b01e57SJeff Chen tlv_len = nxpwifi_append_data_tlv(WLAN_EID_EXT_CAPABILITY,
613*73b01e57SJeff Chen data, len, pos, cmd_end);
614*73b01e57SJeff Chen if (!tlv_len)
615*73b01e57SJeff Chen return -EINVAL;
616*73b01e57SJeff Chen pos += tlv_len;
617*73b01e57SJeff Chen cmd_size += tlv_len;
618*73b01e57SJeff Chen }
619*73b01e57SJeff Chen
620*73b01e57SJeff Chen if (params->link_sta_params.supported_rates_len) {
621*73b01e57SJeff Chen u8 *data = (u8 *)params->link_sta_params.supported_rates;
622*73b01e57SJeff Chen u16 len = params->link_sta_params.supported_rates_len;
623*73b01e57SJeff Chen
624*73b01e57SJeff Chen tlv_len = nxpwifi_append_data_tlv(WLAN_EID_SUPP_RATES,
625*73b01e57SJeff Chen data, len, pos, cmd_end);
626*73b01e57SJeff Chen if (!tlv_len)
627*73b01e57SJeff Chen return -EINVAL;
628*73b01e57SJeff Chen pos += tlv_len;
629*73b01e57SJeff Chen cmd_size += tlv_len;
630*73b01e57SJeff Chen }
631*73b01e57SJeff Chen
632*73b01e57SJeff Chen if (params->uapsd_queues || params->max_sp) {
633*73b01e57SJeff Chen u8 qos_capability = params->uapsd_queues | (params->max_sp << 5);
634*73b01e57SJeff Chen u8 *data = &qos_capability;
635*73b01e57SJeff Chen u16 len = sizeof(u8);
636*73b01e57SJeff Chen
637*73b01e57SJeff Chen tlv_len = nxpwifi_append_data_tlv(WLAN_EID_QOS_CAPA,
638*73b01e57SJeff Chen data, len, pos, cmd_end);
639*73b01e57SJeff Chen if (!tlv_len)
640*73b01e57SJeff Chen return -EINVAL;
641*73b01e57SJeff Chen pos += tlv_len;
642*73b01e57SJeff Chen cmd_size += tlv_len;
643*73b01e57SJeff Chen sta_ptr->is_wmm_enabled = 1;
644*73b01e57SJeff Chen }
645*73b01e57SJeff Chen
646*73b01e57SJeff Chen if (params->link_sta_params.ht_capa) {
647*73b01e57SJeff Chen u8 *data = (u8 *)params->link_sta_params.ht_capa;
648*73b01e57SJeff Chen u16 len = sizeof(struct ieee80211_ht_cap);
649*73b01e57SJeff Chen
650*73b01e57SJeff Chen tlv_len = nxpwifi_append_data_tlv(WLAN_EID_HT_CAPABILITY,
651*73b01e57SJeff Chen data, len, pos, cmd_end);
652*73b01e57SJeff Chen if (!tlv_len)
653*73b01e57SJeff Chen return -EINVAL;
654*73b01e57SJeff Chen pos += tlv_len;
655*73b01e57SJeff Chen cmd_size += tlv_len;
656*73b01e57SJeff Chen sta_ptr->is_11n_enabled = 1;
657*73b01e57SJeff Chen sta_ptr->max_amsdu =
658*73b01e57SJeff Chen le16_to_cpu(params->link_sta_params.ht_capa->cap_info) &
659*73b01e57SJeff Chen IEEE80211_HT_CAP_MAX_AMSDU ?
660*73b01e57SJeff Chen NXPWIFI_TX_DATA_BUF_SIZE_8K :
661*73b01e57SJeff Chen NXPWIFI_TX_DATA_BUF_SIZE_4K;
662*73b01e57SJeff Chen }
663*73b01e57SJeff Chen
664*73b01e57SJeff Chen if (params->link_sta_params.vht_capa) {
665*73b01e57SJeff Chen u8 *data = (u8 *)params->link_sta_params.vht_capa;
666*73b01e57SJeff Chen u16 len = sizeof(struct ieee80211_vht_cap);
667*73b01e57SJeff Chen
668*73b01e57SJeff Chen tlv_len = nxpwifi_append_data_tlv(WLAN_EID_VHT_CAPABILITY,
669*73b01e57SJeff Chen data, len, pos, cmd_end);
670*73b01e57SJeff Chen if (!tlv_len)
671*73b01e57SJeff Chen return -EINVAL;
672*73b01e57SJeff Chen pos += tlv_len;
673*73b01e57SJeff Chen cmd_size += tlv_len;
674*73b01e57SJeff Chen sta_ptr->is_11ac_enabled = 1;
675*73b01e57SJeff Chen }
676*73b01e57SJeff Chen
677*73b01e57SJeff Chen if (params->link_sta_params.opmode_notif_used) {
678*73b01e57SJeff Chen u8 *data = ¶ms->link_sta_params.opmode_notif;
679*73b01e57SJeff Chen u16 len = sizeof(u8);
680*73b01e57SJeff Chen
681*73b01e57SJeff Chen tlv_len = nxpwifi_append_data_tlv(WLAN_EID_OPMODE_NOTIF,
682*73b01e57SJeff Chen data, len, pos, cmd_end);
683*73b01e57SJeff Chen if (!tlv_len)
684*73b01e57SJeff Chen return -EINVAL;
685*73b01e57SJeff Chen pos += tlv_len;
686*73b01e57SJeff Chen cmd_size += tlv_len;
687*73b01e57SJeff Chen }
688*73b01e57SJeff Chen
689*73b01e57SJeff Chen if (params->link_sta_params.he_capa_len) {
690*73b01e57SJeff Chen u8 *data = (u8 *)params->link_sta_params.he_capa;
691*73b01e57SJeff Chen u16 len = params->link_sta_params.he_capa_len;
692*73b01e57SJeff Chen
693*73b01e57SJeff Chen tlv_len = nxpwifi_append_data_tlv(WLAN_EID_EXT_HE_CAPABILITY,
694*73b01e57SJeff Chen data, len, pos, cmd_end);
695*73b01e57SJeff Chen if (!tlv_len)
696*73b01e57SJeff Chen return -EINVAL;
697*73b01e57SJeff Chen pos += tlv_len;
698*73b01e57SJeff Chen cmd_size += tlv_len;
699*73b01e57SJeff Chen sta_ptr->is_11ax_enabled = 1;
700*73b01e57SJeff Chen }
701*73b01e57SJeff Chen
702*73b01e57SJeff Chen for (i = 0; i < MAX_NUM_TID; i++) {
703*73b01e57SJeff Chen if (sta_ptr->is_11n_enabled || sta_ptr->is_11ax_enabled)
704*73b01e57SJeff Chen sta_ptr->ampdu_sta[i] =
705*73b01e57SJeff Chen priv->aggr_prio_tbl[i].ampdu_user;
706*73b01e57SJeff Chen else
707*73b01e57SJeff Chen sta_ptr->ampdu_sta[i] = BA_STREAM_NOT_ALLOWED;
708*73b01e57SJeff Chen }
709*73b01e57SJeff Chen
710*73b01e57SJeff Chen memset(sta_ptr->rx_seq, 0xff, sizeof(sta_ptr->rx_seq));
711*73b01e57SJeff Chen
712*73b01e57SJeff Chen cmd->size = cpu_to_le16(cmd_size);
713*73b01e57SJeff Chen
714*73b01e57SJeff Chen return 0;
715*73b01e57SJeff Chen }
716*73b01e57SJeff Chen
717*73b01e57SJeff Chen static const struct nxpwifi_cmd_entry cmd_table_uap[] = {
718*73b01e57SJeff Chen {.cmd_no = HOST_CMD_APCMD_SYS_RESET,
719*73b01e57SJeff Chen .prepare_cmd = nxpwifi_cmd_fill_head_only,
720*73b01e57SJeff Chen .cmd_resp = NULL},
721*73b01e57SJeff Chen {.cmd_no = HOST_CMD_UAP_SYS_CONFIG,
722*73b01e57SJeff Chen .prepare_cmd = nxpwifi_cmd_uap_sys_config,
723*73b01e57SJeff Chen .cmd_resp = NULL},
724*73b01e57SJeff Chen {.cmd_no = HOST_CMD_UAP_BSS_START,
725*73b01e57SJeff Chen .prepare_cmd = nxpwifi_cmd_uap_bss_start,
726*73b01e57SJeff Chen .cmd_resp = nxpwifi_ret_uap_bss_start},
727*73b01e57SJeff Chen {.cmd_no = HOST_CMD_UAP_BSS_STOP,
728*73b01e57SJeff Chen .prepare_cmd = nxpwifi_cmd_fill_head_only,
729*73b01e57SJeff Chen .cmd_resp = nxpwifi_ret_uap_bss_stop},
730*73b01e57SJeff Chen {.cmd_no = HOST_CMD_APCMD_STA_LIST,
731*73b01e57SJeff Chen .prepare_cmd = nxpwifi_cmd_fill_head_only,
732*73b01e57SJeff Chen .cmd_resp = nxpwifi_ret_apcmd_sta_list},
733*73b01e57SJeff Chen {.cmd_no = HOST_CMD_UAP_STA_DEAUTH,
734*73b01e57SJeff Chen .prepare_cmd = nxpwifi_cmd_uap_sta_deauth,
735*73b01e57SJeff Chen .cmd_resp = NULL},
736*73b01e57SJeff Chen {.cmd_no = HOST_CMD_CHAN_REPORT_REQUEST,
737*73b01e57SJeff Chen .prepare_cmd = nxpwifi_cmd_uap_chan_report_request,
738*73b01e57SJeff Chen .cmd_resp = NULL},
739*73b01e57SJeff Chen {.cmd_no = HOST_CMD_ADD_NEW_STATION,
740*73b01e57SJeff Chen .prepare_cmd = nxpwifi_cmd_uap_add_new_station,
741*73b01e57SJeff Chen .cmd_resp = NULL},
742*73b01e57SJeff Chen };
743*73b01e57SJeff Chen
744*73b01e57SJeff Chen /* Prepare AP commands and dispatch to per-cmd builders before sending to firmware. */
nxpwifi_uap_prepare_cmd(struct nxpwifi_private * priv,struct cmd_ctrl_node * cmd_node,u16 cmd_action,u32 type)745*73b01e57SJeff Chen int nxpwifi_uap_prepare_cmd(struct nxpwifi_private *priv,
746*73b01e57SJeff Chen struct cmd_ctrl_node *cmd_node,
747*73b01e57SJeff Chen u16 cmd_action, u32 type)
748*73b01e57SJeff Chen {
749*73b01e57SJeff Chen struct nxpwifi_adapter *adapter = priv->adapter;
750*73b01e57SJeff Chen u16 cmd_no = cmd_node->cmd_no;
751*73b01e57SJeff Chen struct host_cmd_ds_command *cmd =
752*73b01e57SJeff Chen (struct host_cmd_ds_command *)cmd_node->skb->data;
753*73b01e57SJeff Chen void *data_buf = cmd_node->data_buf;
754*73b01e57SJeff Chen int i, ret = -EINVAL;
755*73b01e57SJeff Chen
756*73b01e57SJeff Chen for (i = 0; i < ARRAY_SIZE(cmd_table_uap); i++) {
757*73b01e57SJeff Chen if (cmd_no == cmd_table_uap[i].cmd_no) {
758*73b01e57SJeff Chen if (cmd_table_uap[i].prepare_cmd)
759*73b01e57SJeff Chen ret = cmd_table_uap[i].prepare_cmd(priv, cmd,
760*73b01e57SJeff Chen cmd_no,
761*73b01e57SJeff Chen data_buf,
762*73b01e57SJeff Chen cmd_action,
763*73b01e57SJeff Chen type);
764*73b01e57SJeff Chen cmd_node->cmd_resp = cmd_table_uap[i].cmd_resp;
765*73b01e57SJeff Chen break;
766*73b01e57SJeff Chen }
767*73b01e57SJeff Chen }
768*73b01e57SJeff Chen
769*73b01e57SJeff Chen if (i == ARRAY_SIZE(cmd_table_uap))
770*73b01e57SJeff Chen nxpwifi_dbg(adapter, ERROR,
771*73b01e57SJeff Chen "%s: unknown command: %#x\n",
772*73b01e57SJeff Chen __func__, cmd_no);
773*73b01e57SJeff Chen else
774*73b01e57SJeff Chen nxpwifi_dbg(adapter, CMD,
775*73b01e57SJeff Chen "%s: command: %#x\n",
776*73b01e57SJeff Chen __func__, cmd_no);
777*73b01e57SJeff Chen
778*73b01e57SJeff Chen return ret;
779*73b01e57SJeff Chen }
780*73b01e57SJeff Chen
781*73b01e57SJeff Chen /* Translate cfg80211_ap_settings security into bss_config for firmware. */
nxpwifi_set_secure_params(struct nxpwifi_private * priv,struct nxpwifi_uap_bss_param * bss_config,struct cfg80211_ap_settings * params)782*73b01e57SJeff Chen int nxpwifi_set_secure_params(struct nxpwifi_private *priv,
783*73b01e57SJeff Chen struct nxpwifi_uap_bss_param *bss_config,
784*73b01e57SJeff Chen struct cfg80211_ap_settings *params)
785*73b01e57SJeff Chen {
786*73b01e57SJeff Chen int i;
787*73b01e57SJeff Chen struct nxpwifi_wep_key wep_key;
788*73b01e57SJeff Chen
789*73b01e57SJeff Chen if (!params->privacy) {
790*73b01e57SJeff Chen bss_config->protocol = PROTOCOL_NO_SECURITY;
791*73b01e57SJeff Chen bss_config->key_mgmt = KEY_MGMT_NONE;
792*73b01e57SJeff Chen bss_config->wpa_cfg.length = 0;
793*73b01e57SJeff Chen priv->sec_info.wep_enabled = 0;
794*73b01e57SJeff Chen priv->sec_info.wpa_enabled = 0;
795*73b01e57SJeff Chen priv->sec_info.wpa2_enabled = 0;
796*73b01e57SJeff Chen
797*73b01e57SJeff Chen return 0;
798*73b01e57SJeff Chen }
799*73b01e57SJeff Chen
800*73b01e57SJeff Chen switch (params->auth_type) {
801*73b01e57SJeff Chen case NL80211_AUTHTYPE_OPEN_SYSTEM:
802*73b01e57SJeff Chen bss_config->auth_mode = WLAN_AUTH_OPEN;
803*73b01e57SJeff Chen break;
804*73b01e57SJeff Chen case NL80211_AUTHTYPE_SHARED_KEY:
805*73b01e57SJeff Chen bss_config->auth_mode = WLAN_AUTH_SHARED_KEY;
806*73b01e57SJeff Chen break;
807*73b01e57SJeff Chen case NL80211_AUTHTYPE_NETWORK_EAP:
808*73b01e57SJeff Chen bss_config->auth_mode = WLAN_AUTH_LEAP;
809*73b01e57SJeff Chen break;
810*73b01e57SJeff Chen default:
811*73b01e57SJeff Chen bss_config->auth_mode = NXPWIFI_AUTH_MODE_AUTO;
812*73b01e57SJeff Chen break;
813*73b01e57SJeff Chen }
814*73b01e57SJeff Chen
815*73b01e57SJeff Chen bss_config->key_mgmt_operation |= KEY_MGMT_ON_HOST;
816*73b01e57SJeff Chen
817*73b01e57SJeff Chen bss_config->protocol = 0;
818*73b01e57SJeff Chen if (params->crypto.wpa_versions & NL80211_WPA_VERSION_1)
819*73b01e57SJeff Chen bss_config->protocol |= PROTOCOL_WPA;
820*73b01e57SJeff Chen if (params->crypto.wpa_versions & NL80211_WPA_VERSION_2)
821*73b01e57SJeff Chen bss_config->protocol |= PROTOCOL_WPA2;
822*73b01e57SJeff Chen
823*73b01e57SJeff Chen bss_config->key_mgmt = 0;
824*73b01e57SJeff Chen for (i = 0; i < params->crypto.n_akm_suites; i++) {
825*73b01e57SJeff Chen switch (params->crypto.akm_suites[i]) {
826*73b01e57SJeff Chen case WLAN_AKM_SUITE_8021X:
827*73b01e57SJeff Chen bss_config->key_mgmt |= KEY_MGMT_EAP;
828*73b01e57SJeff Chen break;
829*73b01e57SJeff Chen case WLAN_AKM_SUITE_PSK:
830*73b01e57SJeff Chen bss_config->key_mgmt |= KEY_MGMT_PSK;
831*73b01e57SJeff Chen break;
832*73b01e57SJeff Chen case WLAN_AKM_SUITE_PSK_SHA256:
833*73b01e57SJeff Chen bss_config->key_mgmt |= KEY_MGMT_PSK_SHA256;
834*73b01e57SJeff Chen break;
835*73b01e57SJeff Chen case WLAN_AKM_SUITE_OWE:
836*73b01e57SJeff Chen bss_config->key_mgmt |= KEY_MGMT_OWE;
837*73b01e57SJeff Chen break;
838*73b01e57SJeff Chen case WLAN_AKM_SUITE_SAE:
839*73b01e57SJeff Chen bss_config->key_mgmt |= KEY_MGMT_SAE;
840*73b01e57SJeff Chen break;
841*73b01e57SJeff Chen default:
842*73b01e57SJeff Chen break;
843*73b01e57SJeff Chen }
844*73b01e57SJeff Chen }
845*73b01e57SJeff Chen
846*73b01e57SJeff Chen for (i = 0; i < params->crypto.n_ciphers_pairwise; i++) {
847*73b01e57SJeff Chen switch (params->crypto.ciphers_pairwise[i]) {
848*73b01e57SJeff Chen case WLAN_CIPHER_SUITE_WEP40:
849*73b01e57SJeff Chen case WLAN_CIPHER_SUITE_WEP104:
850*73b01e57SJeff Chen break;
851*73b01e57SJeff Chen case WLAN_CIPHER_SUITE_TKIP:
852*73b01e57SJeff Chen if (params->crypto.wpa_versions & NL80211_WPA_VERSION_1)
853*73b01e57SJeff Chen bss_config->wpa_cfg.pairwise_cipher_wpa |=
854*73b01e57SJeff Chen CIPHER_TKIP;
855*73b01e57SJeff Chen if (params->crypto.wpa_versions & NL80211_WPA_VERSION_2)
856*73b01e57SJeff Chen bss_config->wpa_cfg.pairwise_cipher_wpa2 |=
857*73b01e57SJeff Chen CIPHER_TKIP;
858*73b01e57SJeff Chen break;
859*73b01e57SJeff Chen case WLAN_CIPHER_SUITE_CCMP:
860*73b01e57SJeff Chen if (params->crypto.wpa_versions & NL80211_WPA_VERSION_1)
861*73b01e57SJeff Chen bss_config->wpa_cfg.pairwise_cipher_wpa |=
862*73b01e57SJeff Chen CIPHER_AES_CCMP;
863*73b01e57SJeff Chen if (params->crypto.wpa_versions & NL80211_WPA_VERSION_2)
864*73b01e57SJeff Chen bss_config->wpa_cfg.pairwise_cipher_wpa2 |=
865*73b01e57SJeff Chen CIPHER_AES_CCMP;
866*73b01e57SJeff Chen break;
867*73b01e57SJeff Chen default:
868*73b01e57SJeff Chen break;
869*73b01e57SJeff Chen }
870*73b01e57SJeff Chen }
871*73b01e57SJeff Chen
872*73b01e57SJeff Chen switch (params->crypto.cipher_group) {
873*73b01e57SJeff Chen case WLAN_CIPHER_SUITE_WEP40:
874*73b01e57SJeff Chen case WLAN_CIPHER_SUITE_WEP104:
875*73b01e57SJeff Chen if (priv->sec_info.wep_enabled) {
876*73b01e57SJeff Chen bss_config->protocol = PROTOCOL_STATIC_WEP;
877*73b01e57SJeff Chen bss_config->key_mgmt = KEY_MGMT_NONE;
878*73b01e57SJeff Chen bss_config->wpa_cfg.length = 0;
879*73b01e57SJeff Chen
880*73b01e57SJeff Chen for (i = 0; i < NUM_WEP_KEYS; i++) {
881*73b01e57SJeff Chen wep_key = priv->wep_key[i];
882*73b01e57SJeff Chen bss_config->wep_cfg[i].key_index = i;
883*73b01e57SJeff Chen
884*73b01e57SJeff Chen if (priv->wep_key_curr_index == i)
885*73b01e57SJeff Chen bss_config->wep_cfg[i].is_default = 1;
886*73b01e57SJeff Chen else
887*73b01e57SJeff Chen bss_config->wep_cfg[i].is_default = 0;
888*73b01e57SJeff Chen
889*73b01e57SJeff Chen bss_config->wep_cfg[i].length =
890*73b01e57SJeff Chen wep_key.key_length;
891*73b01e57SJeff Chen memcpy(&bss_config->wep_cfg[i].key,
892*73b01e57SJeff Chen &wep_key.key_material,
893*73b01e57SJeff Chen wep_key.key_length);
894*73b01e57SJeff Chen }
895*73b01e57SJeff Chen }
896*73b01e57SJeff Chen break;
897*73b01e57SJeff Chen case WLAN_CIPHER_SUITE_TKIP:
898*73b01e57SJeff Chen bss_config->wpa_cfg.group_cipher = CIPHER_TKIP;
899*73b01e57SJeff Chen break;
900*73b01e57SJeff Chen case WLAN_CIPHER_SUITE_CCMP:
901*73b01e57SJeff Chen bss_config->wpa_cfg.group_cipher = CIPHER_AES_CCMP;
902*73b01e57SJeff Chen break;
903*73b01e57SJeff Chen default:
904*73b01e57SJeff Chen break;
905*73b01e57SJeff Chen }
906*73b01e57SJeff Chen
907*73b01e57SJeff Chen return 0;
908*73b01e57SJeff Chen }
909*73b01e57SJeff Chen
910*73b01e57SJeff Chen /* Update 11n HT params from beacon and fill bss_config. */
911*73b01e57SJeff Chen void
nxpwifi_set_ht_params(struct nxpwifi_private * priv,struct nxpwifi_uap_bss_param * bss_cfg,struct cfg80211_ap_settings * params)912*73b01e57SJeff Chen nxpwifi_set_ht_params(struct nxpwifi_private *priv,
913*73b01e57SJeff Chen struct nxpwifi_uap_bss_param *bss_cfg,
914*73b01e57SJeff Chen struct cfg80211_ap_settings *params)
915*73b01e57SJeff Chen {
916*73b01e57SJeff Chen const u8 *ht_ie;
917*73b01e57SJeff Chen
918*73b01e57SJeff Chen if (!ISSUPP_11NENABLED(priv->adapter->fw_cap_info))
919*73b01e57SJeff Chen return;
920*73b01e57SJeff Chen
921*73b01e57SJeff Chen ht_ie = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, params->beacon.tail,
922*73b01e57SJeff Chen params->beacon.tail_len);
923*73b01e57SJeff Chen if (ht_ie) {
924*73b01e57SJeff Chen memcpy(&bss_cfg->ht_cap, ht_ie + 2,
925*73b01e57SJeff Chen sizeof(struct ieee80211_ht_cap));
926*73b01e57SJeff Chen if (ISSUPP_BEAMFORMING(priv->adapter->hw_dot_11n_dev_cap))
927*73b01e57SJeff Chen bss_cfg->ht_cap.tx_BF_cap_info =
928*73b01e57SJeff Chen cpu_to_le32(NXPWIFI_DEF_11N_TX_BF_CAP);
929*73b01e57SJeff Chen priv->ap_11n_enabled = 1;
930*73b01e57SJeff Chen } else {
931*73b01e57SJeff Chen memset(&bss_cfg->ht_cap, 0, sizeof(struct ieee80211_ht_cap));
932*73b01e57SJeff Chen bss_cfg->ht_cap.cap_info = cpu_to_le16(NXPWIFI_DEF_HT_CAP);
933*73b01e57SJeff Chen bss_cfg->ht_cap.ampdu_params_info = NXPWIFI_DEF_AMPDU;
934*73b01e57SJeff Chen }
935*73b01e57SJeff Chen }
936*73b01e57SJeff Chen
937*73b01e57SJeff Chen /* Update 11ac VHT params from beacon and fill bss_config. */
nxpwifi_set_vht_params(struct nxpwifi_private * priv,struct nxpwifi_uap_bss_param * bss_cfg,struct cfg80211_ap_settings * params)938*73b01e57SJeff Chen void nxpwifi_set_vht_params(struct nxpwifi_private *priv,
939*73b01e57SJeff Chen struct nxpwifi_uap_bss_param *bss_cfg,
940*73b01e57SJeff Chen struct cfg80211_ap_settings *params)
941*73b01e57SJeff Chen {
942*73b01e57SJeff Chen const u8 *vht_ie;
943*73b01e57SJeff Chen
944*73b01e57SJeff Chen vht_ie = cfg80211_find_ie(WLAN_EID_VHT_CAPABILITY, params->beacon.tail,
945*73b01e57SJeff Chen params->beacon.tail_len);
946*73b01e57SJeff Chen if (vht_ie) {
947*73b01e57SJeff Chen memcpy(&bss_cfg->vht_cap, vht_ie + 2,
948*73b01e57SJeff Chen sizeof(struct ieee80211_vht_cap));
949*73b01e57SJeff Chen priv->ap_11ac_enabled = 1;
950*73b01e57SJeff Chen } else {
951*73b01e57SJeff Chen priv->ap_11ac_enabled = 0;
952*73b01e57SJeff Chen }
953*73b01e57SJeff Chen }
954*73b01e57SJeff Chen
955*73b01e57SJeff Chen /* Extract TPC request from beacon and set power_constraint. */
nxpwifi_set_tpc_params(struct nxpwifi_private * priv,struct nxpwifi_uap_bss_param * bss_cfg,struct cfg80211_ap_settings * params)956*73b01e57SJeff Chen void nxpwifi_set_tpc_params(struct nxpwifi_private *priv,
957*73b01e57SJeff Chen struct nxpwifi_uap_bss_param *bss_cfg,
958*73b01e57SJeff Chen struct cfg80211_ap_settings *params)
959*73b01e57SJeff Chen {
960*73b01e57SJeff Chen const u8 *tpc_ie;
961*73b01e57SJeff Chen
962*73b01e57SJeff Chen tpc_ie = cfg80211_find_ie(WLAN_EID_TPC_REQUEST, params->beacon.tail,
963*73b01e57SJeff Chen params->beacon.tail_len);
964*73b01e57SJeff Chen if (tpc_ie)
965*73b01e57SJeff Chen bss_cfg->power_constraint = *(tpc_ie + 2);
966*73b01e57SJeff Chen else
967*73b01e57SJeff Chen bss_cfg->power_constraint = 0;
968*73b01e57SJeff Chen }
969*73b01e57SJeff Chen
970*73b01e57SJeff Chen /* Enable VHT only when VHT IE is present; otherwise disable VHT. */
nxpwifi_set_vht_width(struct nxpwifi_private * priv,enum nl80211_chan_width width,bool ap_11ac_enable)971*73b01e57SJeff Chen void nxpwifi_set_vht_width(struct nxpwifi_private *priv,
972*73b01e57SJeff Chen enum nl80211_chan_width width,
973*73b01e57SJeff Chen bool ap_11ac_enable)
974*73b01e57SJeff Chen {
975*73b01e57SJeff Chen struct nxpwifi_adapter *adapter = priv->adapter;
976*73b01e57SJeff Chen struct nxpwifi_11ac_vht_cfg vht_cfg;
977*73b01e57SJeff Chen
978*73b01e57SJeff Chen vht_cfg.band_config = VHT_CFG_5GHZ;
979*73b01e57SJeff Chen vht_cfg.cap_info = adapter->hw_dot_11ac_dev_cap;
980*73b01e57SJeff Chen
981*73b01e57SJeff Chen if (!ap_11ac_enable) {
982*73b01e57SJeff Chen vht_cfg.mcs_tx_set = DISABLE_VHT_MCS_SET;
983*73b01e57SJeff Chen vht_cfg.mcs_rx_set = DISABLE_VHT_MCS_SET;
984*73b01e57SJeff Chen } else {
985*73b01e57SJeff Chen vht_cfg.mcs_tx_set = DEFAULT_VHT_MCS_SET;
986*73b01e57SJeff Chen vht_cfg.mcs_rx_set = DEFAULT_VHT_MCS_SET;
987*73b01e57SJeff Chen }
988*73b01e57SJeff Chen
989*73b01e57SJeff Chen vht_cfg.misc_config = VHT_CAP_UAP_ONLY;
990*73b01e57SJeff Chen
991*73b01e57SJeff Chen if (ap_11ac_enable && width >= NL80211_CHAN_WIDTH_80)
992*73b01e57SJeff Chen vht_cfg.misc_config |= VHT_BW_80_160_80P80;
993*73b01e57SJeff Chen
994*73b01e57SJeff Chen nxpwifi_send_cmd(priv, HOST_CMD_11AC_CFG,
995*73b01e57SJeff Chen HOST_ACT_GEN_SET, 0, &vht_cfg, true);
996*73b01e57SJeff Chen }
997*73b01e57SJeff Chen
nxpwifi_check_11ax_capability(struct nxpwifi_private * priv,struct nxpwifi_uap_bss_param * bss_cfg,struct cfg80211_ap_settings * params)998*73b01e57SJeff Chen bool nxpwifi_check_11ax_capability(struct nxpwifi_private *priv,
999*73b01e57SJeff Chen struct nxpwifi_uap_bss_param *bss_cfg,
1000*73b01e57SJeff Chen struct cfg80211_ap_settings *params)
1001*73b01e57SJeff Chen {
1002*73b01e57SJeff Chen struct nxpwifi_adapter *adapter = priv->adapter;
1003*73b01e57SJeff Chen u8 band = bss_cfg->band_cfg & BAND_CFG_CHAN_BAND_MASK;
1004*73b01e57SJeff Chen
1005*73b01e57SJeff Chen if (band == BAND_2GHZ &&
1006*73b01e57SJeff Chen !(adapter->fw_bands & BAND_GAX))
1007*73b01e57SJeff Chen return false;
1008*73b01e57SJeff Chen
1009*73b01e57SJeff Chen if (band == BAND_5GHZ &&
1010*73b01e57SJeff Chen !(adapter->fw_bands & BAND_AAX))
1011*73b01e57SJeff Chen return false;
1012*73b01e57SJeff Chen
1013*73b01e57SJeff Chen if (params->he_cap)
1014*73b01e57SJeff Chen return true;
1015*73b01e57SJeff Chen else
1016*73b01e57SJeff Chen return false;
1017*73b01e57SJeff Chen }
1018*73b01e57SJeff Chen
nxpwifi_set_11ax_status(struct nxpwifi_private * priv,struct nxpwifi_uap_bss_param * bss_cfg,struct cfg80211_ap_settings * params)1019*73b01e57SJeff Chen int nxpwifi_set_11ax_status(struct nxpwifi_private *priv,
1020*73b01e57SJeff Chen struct nxpwifi_uap_bss_param *bss_cfg,
1021*73b01e57SJeff Chen struct cfg80211_ap_settings *params)
1022*73b01e57SJeff Chen {
1023*73b01e57SJeff Chen struct nxpwifi_11ax_he_cfg ax_cfg;
1024*73b01e57SJeff Chen u8 band = bss_cfg->band_cfg & BAND_CFG_CHAN_BAND_MASK;
1025*73b01e57SJeff Chen const struct element *he_cap;
1026*73b01e57SJeff Chen int ret;
1027*73b01e57SJeff Chen
1028*73b01e57SJeff Chen if (band == BAND_2GHZ)
1029*73b01e57SJeff Chen ax_cfg.band = BIT(0);
1030*73b01e57SJeff Chen else if (band == BAND_5GHZ)
1031*73b01e57SJeff Chen ax_cfg.band = BIT(1);
1032*73b01e57SJeff Chen else
1033*73b01e57SJeff Chen return -EINVAL;
1034*73b01e57SJeff Chen
1035*73b01e57SJeff Chen ret = nxpwifi_send_cmd(priv, HOST_CMD_11AX_CFG,
1036*73b01e57SJeff Chen HOST_ACT_GEN_GET, 0, &ax_cfg, true);
1037*73b01e57SJeff Chen if (ret)
1038*73b01e57SJeff Chen return ret;
1039*73b01e57SJeff Chen
1040*73b01e57SJeff Chen he_cap = cfg80211_find_ext_elem(WLAN_EID_EXT_HE_CAPABILITY,
1041*73b01e57SJeff Chen params->beacon.tail,
1042*73b01e57SJeff Chen params->beacon.tail_len);
1043*73b01e57SJeff Chen
1044*73b01e57SJeff Chen if (he_cap) {
1045*73b01e57SJeff Chen ax_cfg.he_cap_cfg.id = he_cap->id;
1046*73b01e57SJeff Chen ax_cfg.he_cap_cfg.len = he_cap->datalen;
1047*73b01e57SJeff Chen if (params->twt_responder == 0) {
1048*73b01e57SJeff Chen struct nxpwifi_11ax_he_cap_cfg *he_cap_cfg =
1049*73b01e57SJeff Chen (struct nxpwifi_11ax_he_cap_cfg *)he_cap;
1050*73b01e57SJeff Chen
1051*73b01e57SJeff Chen he_cap_cfg->cap_elem.mac_cap_info[0] &=
1052*73b01e57SJeff Chen ~HE_MAC_CAP_TWT_RESP_SUPPORT;
1053*73b01e57SJeff Chen }
1054*73b01e57SJeff Chen memcpy(ax_cfg.data + 4,
1055*73b01e57SJeff Chen he_cap->data,
1056*73b01e57SJeff Chen he_cap->datalen);
1057*73b01e57SJeff Chen } else {
1058*73b01e57SJeff Chen /* disable */
1059*73b01e57SJeff Chen if (ax_cfg.he_cap_cfg.len &&
1060*73b01e57SJeff Chen ax_cfg.he_cap_cfg.ext_id == WLAN_EID_EXT_HE_CAPABILITY) {
1061*73b01e57SJeff Chen memset(ax_cfg.he_cap_cfg.he_txrx_mcs_support, 0xff,
1062*73b01e57SJeff Chen sizeof(ax_cfg.he_cap_cfg.he_txrx_mcs_support));
1063*73b01e57SJeff Chen }
1064*73b01e57SJeff Chen }
1065*73b01e57SJeff Chen
1066*73b01e57SJeff Chen return nxpwifi_send_cmd(priv, HOST_CMD_11AX_CFG,
1067*73b01e57SJeff Chen HOST_ACT_GEN_SET, 0, &ax_cfg, true);
1068*73b01e57SJeff Chen }
1069*73b01e57SJeff Chen
1070*73b01e57SJeff Chen /* Copy supported rates from beacon into bss_config. */
1071*73b01e57SJeff Chen void
nxpwifi_set_uap_rates(struct nxpwifi_uap_bss_param * bss_cfg,struct cfg80211_ap_settings * params)1072*73b01e57SJeff Chen nxpwifi_set_uap_rates(struct nxpwifi_uap_bss_param *bss_cfg,
1073*73b01e57SJeff Chen struct cfg80211_ap_settings *params)
1074*73b01e57SJeff Chen {
1075*73b01e57SJeff Chen struct element *rate_ie;
1076*73b01e57SJeff Chen int var_offset = offsetof(struct ieee80211_mgmt, u.beacon.variable);
1077*73b01e57SJeff Chen const u8 *var_pos = params->beacon.head + var_offset;
1078*73b01e57SJeff Chen int len = params->beacon.head_len - var_offset;
1079*73b01e57SJeff Chen u8 rate_len = 0;
1080*73b01e57SJeff Chen
1081*73b01e57SJeff Chen rate_ie = (void *)cfg80211_find_ie(WLAN_EID_SUPP_RATES, var_pos, len);
1082*73b01e57SJeff Chen if (rate_ie) {
1083*73b01e57SJeff Chen if (rate_ie->datalen > NXPWIFI_SUPPORTED_RATES)
1084*73b01e57SJeff Chen return;
1085*73b01e57SJeff Chen memcpy(bss_cfg->rates, rate_ie + 1, rate_ie->datalen);
1086*73b01e57SJeff Chen rate_len = rate_ie->datalen;
1087*73b01e57SJeff Chen }
1088*73b01e57SJeff Chen
1089*73b01e57SJeff Chen rate_ie = (void *)cfg80211_find_ie(WLAN_EID_EXT_SUPP_RATES,
1090*73b01e57SJeff Chen params->beacon.tail,
1091*73b01e57SJeff Chen params->beacon.tail_len);
1092*73b01e57SJeff Chen if (rate_ie) {
1093*73b01e57SJeff Chen if (rate_ie->datalen > NXPWIFI_SUPPORTED_RATES - rate_len)
1094*73b01e57SJeff Chen return;
1095*73b01e57SJeff Chen memcpy(bss_cfg->rates + rate_len,
1096*73b01e57SJeff Chen rate_ie + 1, rate_ie->datalen);
1097*73b01e57SJeff Chen }
1098*73b01e57SJeff Chen }
1099*73b01e57SJeff Chen
1100*73b01e57SJeff Chen /*
1101*73b01e57SJeff Chen * Initialize bss_config fields to sentinel values.
1102*73b01e57SJeff Chen * Fields left with sentinel values are treated as unset and will not be
1103*73b01e57SJeff Chen * included in the corresponding firmware command.
1104*73b01e57SJeff Chen */
nxpwifi_set_sys_config_invalid_data(struct nxpwifi_uap_bss_param * config)1105*73b01e57SJeff Chen void nxpwifi_set_sys_config_invalid_data(struct nxpwifi_uap_bss_param *config)
1106*73b01e57SJeff Chen {
1107*73b01e57SJeff Chen config->radio_ctl = __NXPWIFI_RADIO_CTL_MAX;
1108*73b01e57SJeff Chen config->dtim_period = NXPWIFI_INVALID_DTIM_PERIOD;
1109*73b01e57SJeff Chen config->beacon_period = NXPWIFI_INVALID_BEACON_PERIOD;
1110*73b01e57SJeff Chen config->auth_mode = NXPWIFI_AUTH_MODE_AUTO;
1111*73b01e57SJeff Chen config->rts_threshold = NXPWIFI_INVALID_RTS;
1112*73b01e57SJeff Chen config->frag_threshold = NXPWIFI_INVALID_FRAG;
1113*73b01e57SJeff Chen config->retry_limit = NXPWIFI_INVALID_RETRY_LIMI;
1114*73b01e57SJeff Chen }
1115*73b01e57SJeff Chen
1116*73b01e57SJeff Chen /* Parse WMM params from cfg80211_ap_settings and update bss_config. */
1117*73b01e57SJeff Chen void
nxpwifi_set_wmm_params(struct nxpwifi_private * priv,struct nxpwifi_uap_bss_param * bss_cfg,struct cfg80211_ap_settings * params)1118*73b01e57SJeff Chen nxpwifi_set_wmm_params(struct nxpwifi_private *priv,
1119*73b01e57SJeff Chen struct nxpwifi_uap_bss_param *bss_cfg,
1120*73b01e57SJeff Chen struct cfg80211_ap_settings *params)
1121*73b01e57SJeff Chen {
1122*73b01e57SJeff Chen const u8 *vendor_ie;
1123*73b01e57SJeff Chen const struct ieee80211_wmm_param_ie *wmm;
1124*73b01e57SJeff Chen u8 ie_len;
1125*73b01e57SJeff Chen
1126*73b01e57SJeff Chen vendor_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
1127*73b01e57SJeff Chen WLAN_OUI_TYPE_MICROSOFT_WMM,
1128*73b01e57SJeff Chen params->beacon.tail,
1129*73b01e57SJeff Chen params->beacon.tail_len);
1130*73b01e57SJeff Chen if (!vendor_ie)
1131*73b01e57SJeff Chen goto no_wmm;
1132*73b01e57SJeff Chen
1133*73b01e57SJeff Chen ie_len = vendor_ie[1];
1134*73b01e57SJeff Chen
1135*73b01e57SJeff Chen if (ie_len < sizeof(struct ieee80211_wmm_param_ie) - 2)
1136*73b01e57SJeff Chen goto no_wmm;
1137*73b01e57SJeff Chen
1138*73b01e57SJeff Chen wmm = (const struct ieee80211_wmm_param_ie *)vendor_ie;
1139*73b01e57SJeff Chen
1140*73b01e57SJeff Chen if (memcmp(wmm->oui, "\x00\x50\xf2", 3))
1141*73b01e57SJeff Chen goto no_wmm;
1142*73b01e57SJeff Chen
1143*73b01e57SJeff Chen if (wmm->oui_type != WLAN_OUI_TYPE_MICROSOFT_WMM)
1144*73b01e57SJeff Chen goto no_wmm;
1145*73b01e57SJeff Chen
1146*73b01e57SJeff Chen if (wmm->oui_subtype != 1)
1147*73b01e57SJeff Chen goto no_wmm;
1148*73b01e57SJeff Chen
1149*73b01e57SJeff Chen /* Only WMM version 1 is supported */
1150*73b01e57SJeff Chen if (wmm->version != 1)
1151*73b01e57SJeff Chen goto no_wmm;
1152*73b01e57SJeff Chen
1153*73b01e57SJeff Chen memcpy(&bss_cfg->wmm_element, wmm,
1154*73b01e57SJeff Chen sizeof(struct ieee80211_wmm_param_ie));
1155*73b01e57SJeff Chen
1156*73b01e57SJeff Chen priv->wmm_enabled = true;
1157*73b01e57SJeff Chen return;
1158*73b01e57SJeff Chen
1159*73b01e57SJeff Chen no_wmm:
1160*73b01e57SJeff Chen memset(&bss_cfg->wmm_element, 0, sizeof(bss_cfg->wmm_element));
1161*73b01e57SJeff Chen priv->wmm_enabled = false;
1162*73b01e57SJeff Chen }
1163*73b01e57SJeff Chen
1164*73b01e57SJeff Chen /* Enable 11d when country IE is present. */
nxpwifi_config_uap_11d(struct nxpwifi_private * priv,struct cfg80211_beacon_data * beacon_data)1165*73b01e57SJeff Chen void nxpwifi_config_uap_11d(struct nxpwifi_private *priv,
1166*73b01e57SJeff Chen struct cfg80211_beacon_data *beacon_data)
1167*73b01e57SJeff Chen {
1168*73b01e57SJeff Chen enum state_11d_t state_11d;
1169*73b01e57SJeff Chen const u8 *country_ie;
1170*73b01e57SJeff Chen
1171*73b01e57SJeff Chen country_ie = cfg80211_find_ie(WLAN_EID_COUNTRY, beacon_data->tail,
1172*73b01e57SJeff Chen beacon_data->tail_len);
1173*73b01e57SJeff Chen if (country_ie) {
1174*73b01e57SJeff Chen /* Send cmd to FW to enable 11D function */
1175*73b01e57SJeff Chen state_11d = ENABLE_11D;
1176*73b01e57SJeff Chen if (nxpwifi_send_cmd(priv, HOST_CMD_802_11_SNMP_MIB,
1177*73b01e57SJeff Chen HOST_ACT_GEN_SET, DOT11D_I,
1178*73b01e57SJeff Chen &state_11d, true)) {
1179*73b01e57SJeff Chen nxpwifi_dbg(priv->adapter, ERROR,
1180*73b01e57SJeff Chen "11D: failed to enable 11D\n");
1181*73b01e57SJeff Chen }
1182*73b01e57SJeff Chen }
1183*73b01e57SJeff Chen }
1184*73b01e57SJeff Chen
nxpwifi_uap_set_channel(struct nxpwifi_private * priv,struct nxpwifi_uap_bss_param * bss_cfg,struct cfg80211_chan_def chandef)1185*73b01e57SJeff Chen void nxpwifi_uap_set_channel(struct nxpwifi_private *priv,
1186*73b01e57SJeff Chen struct nxpwifi_uap_bss_param *bss_cfg,
1187*73b01e57SJeff Chen struct cfg80211_chan_def chandef)
1188*73b01e57SJeff Chen {
1189*73b01e57SJeff Chen u8 config_bands = 0, old_bands = priv->config_bands;
1190*73b01e57SJeff Chen
1191*73b01e57SJeff Chen priv->bss_chandef = chandef;
1192*73b01e57SJeff Chen
1193*73b01e57SJeff Chen bss_cfg->channel =
1194*73b01e57SJeff Chen ieee80211_frequency_to_channel(chandef.chan->center_freq);
1195*73b01e57SJeff Chen
1196*73b01e57SJeff Chen nxpwifi_convert_chan_to_band_cfg(priv, &bss_cfg->band_cfg, &chandef);
1197*73b01e57SJeff Chen
1198*73b01e57SJeff Chen /* Set appropriate bands */
1199*73b01e57SJeff Chen if (chandef.chan->band == NL80211_BAND_2GHZ) {
1200*73b01e57SJeff Chen config_bands = BAND_B | BAND_G;
1201*73b01e57SJeff Chen if (chandef.width > NL80211_CHAN_WIDTH_20_NOHT)
1202*73b01e57SJeff Chen config_bands |= BAND_GN | BAND_GAX;
1203*73b01e57SJeff Chen } else {
1204*73b01e57SJeff Chen config_bands = BAND_A;
1205*73b01e57SJeff Chen if (chandef.width > NL80211_CHAN_WIDTH_20_NOHT)
1206*73b01e57SJeff Chen config_bands |= BAND_AN;
1207*73b01e57SJeff Chen if (chandef.width > NL80211_CHAN_WIDTH_40)
1208*73b01e57SJeff Chen config_bands |= BAND_AAC | BAND_AAX;
1209*73b01e57SJeff Chen }
1210*73b01e57SJeff Chen
1211*73b01e57SJeff Chen priv->config_bands = config_bands;
1212*73b01e57SJeff Chen
1213*73b01e57SJeff Chen if (old_bands != config_bands) {
1214*73b01e57SJeff Chen if (nxpwifi_band_to_radio_type(priv->config_bands) ==
1215*73b01e57SJeff Chen HOST_SCAN_RADIO_TYPE_BG)
1216*73b01e57SJeff Chen nxpwifi_send_domain_info_cmd_fw(priv->adapter->wiphy,
1217*73b01e57SJeff Chen NL80211_BAND_2GHZ);
1218*73b01e57SJeff Chen else
1219*73b01e57SJeff Chen nxpwifi_send_domain_info_cmd_fw(priv->adapter->wiphy,
1220*73b01e57SJeff Chen NL80211_BAND_5GHZ);
1221*73b01e57SJeff Chen }
1222*73b01e57SJeff Chen }
1223*73b01e57SJeff Chen
nxpwifi_config_start_uap(struct nxpwifi_private * priv,struct nxpwifi_uap_bss_param * bss_cfg)1224*73b01e57SJeff Chen int nxpwifi_config_start_uap(struct nxpwifi_private *priv,
1225*73b01e57SJeff Chen struct nxpwifi_uap_bss_param *bss_cfg)
1226*73b01e57SJeff Chen {
1227*73b01e57SJeff Chen int ret;
1228*73b01e57SJeff Chen
1229*73b01e57SJeff Chen ret = nxpwifi_send_cmd(priv, HOST_CMD_UAP_SYS_CONFIG,
1230*73b01e57SJeff Chen HOST_ACT_GEN_SET,
1231*73b01e57SJeff Chen UAP_BSS_PARAMS_I, bss_cfg, true);
1232*73b01e57SJeff Chen if (ret) {
1233*73b01e57SJeff Chen nxpwifi_dbg(priv->adapter, ERROR,
1234*73b01e57SJeff Chen "Failed to set AP configuration\n");
1235*73b01e57SJeff Chen return ret;
1236*73b01e57SJeff Chen }
1237*73b01e57SJeff Chen
1238*73b01e57SJeff Chen ret = nxpwifi_send_cmd(priv, HOST_CMD_UAP_BSS_START,
1239*73b01e57SJeff Chen HOST_ACT_GEN_SET, 0, NULL, true);
1240*73b01e57SJeff Chen if (ret) {
1241*73b01e57SJeff Chen nxpwifi_dbg(priv->adapter, ERROR,
1242*73b01e57SJeff Chen "Failed to start the BSS\n");
1243*73b01e57SJeff Chen return ret;
1244*73b01e57SJeff Chen }
1245*73b01e57SJeff Chen
1246*73b01e57SJeff Chen if (priv->sec_info.wep_enabled)
1247*73b01e57SJeff Chen priv->curr_pkt_filter |= HOST_ACT_MAC_WEP_ENABLE;
1248*73b01e57SJeff Chen else
1249*73b01e57SJeff Chen priv->curr_pkt_filter &= ~HOST_ACT_MAC_WEP_ENABLE;
1250*73b01e57SJeff Chen
1251*73b01e57SJeff Chen ret = nxpwifi_send_cmd(priv, HOST_CMD_MAC_CONTROL,
1252*73b01e57SJeff Chen HOST_ACT_GEN_SET, 0,
1253*73b01e57SJeff Chen &priv->curr_pkt_filter, true);
1254*73b01e57SJeff Chen
1255*73b01e57SJeff Chen return ret;
1256*73b01e57SJeff Chen }
1257