xref: /linux/drivers/net/wireless/nxp/nxpwifi/sta_cmd.c (revision 91ec2035134982b98fab0609a9fd8480e8217dc1)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * nxpwifi: station command handling
4  *
5  * Copyright 2011-2024 NXP
6  */
7 
8 #include "cfg.h"
9 #include "util.h"
10 #include "fw.h"
11 #include "main.h"
12 #include "cmdevt.h"
13 #include "wmm.h"
14 #include "11n.h"
15 #include "11ac.h"
16 #include "11ax.h"
17 
18 static bool disable_auto_ds;
19 
20 static int
nxpwifi_cmd_sta_get_hw_spec(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)21 nxpwifi_cmd_sta_get_hw_spec(struct nxpwifi_private *priv,
22 			    struct host_cmd_ds_command *cmd,
23 			    u16 cmd_no, void *data_buf,
24 			    u16 cmd_action, u32 cmd_type)
25 {
26 	struct host_cmd_ds_get_hw_spec *hw_spec = &cmd->params.hw_spec;
27 
28 	cmd->command = cpu_to_le16(HOST_CMD_GET_HW_SPEC);
29 	cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_get_hw_spec) +
30 				S_DS_GEN);
31 	memcpy(hw_spec->permanent_addr, priv->curr_addr, ETH_ALEN);
32 
33 	return 0;
34 }
35 
36 static int
nxpwifi_ret_sta_get_hw_spec(struct nxpwifi_private * priv,struct host_cmd_ds_command * resp,u16 cmdresp_no,void * data_buf)37 nxpwifi_ret_sta_get_hw_spec(struct nxpwifi_private *priv,
38 			    struct host_cmd_ds_command *resp,
39 			    u16 cmdresp_no,
40 			    void *data_buf)
41 {
42 	struct host_cmd_ds_get_hw_spec *hw_spec = &resp->params.hw_spec;
43 	struct nxpwifi_adapter *adapter = priv->adapter;
44 	struct nxpwifi_ie_types_header *tlv;
45 	struct hw_spec_api_rev *api_rev;
46 	struct hw_spec_max_conn *max_conn;
47 	struct hw_spec_extension *hw_he_cap;
48 	struct hw_spec_fw_cap_info *fw_cap;
49 	struct hw_spec_secure_boot_uuid *sb_uuid;
50 	u16 resp_size, api_id;
51 	int i, left_len, parsed_len = 0;
52 
53 	adapter->fw_cap_info = le32_to_cpu(hw_spec->fw_cap_info);
54 
55 	if (IS_SUPPORT_MULTI_BANDS(adapter))
56 		adapter->fw_bands = GET_FW_DEFAULT_BANDS(adapter);
57 	else
58 		adapter->fw_bands = BAND_B;
59 
60 	if ((adapter->fw_bands & BAND_A) && (adapter->fw_bands & BAND_GN))
61 		adapter->fw_bands |= BAND_AN;
62 	if (!(adapter->fw_bands & BAND_G) && (adapter->fw_bands & BAND_GN))
63 		adapter->fw_bands &= ~BAND_GN;
64 
65 	adapter->fw_release_number = le32_to_cpu(hw_spec->fw_release_number);
66 	adapter->fw_api_ver = (adapter->fw_release_number >> 16) & 0xff;
67 	adapter->number_of_antenna =
68 		le16_to_cpu(hw_spec->number_of_antenna) & 0xf;
69 
70 	if (le32_to_cpu(hw_spec->dot_11ac_dev_cap)) {
71 		adapter->is_hw_11ac_capable = true;
72 
73 		/* Copy 11AC cap */
74 		adapter->hw_dot_11ac_dev_cap =
75 			le32_to_cpu(hw_spec->dot_11ac_dev_cap);
76 		adapter->usr_dot_11ac_dev_cap_bg = adapter->hw_dot_11ac_dev_cap
77 			& ~NXPWIFI_DEF_11AC_CAP_BF_RESET_MASK;
78 		adapter->usr_dot_11ac_dev_cap_a = adapter->hw_dot_11ac_dev_cap
79 			& ~NXPWIFI_DEF_11AC_CAP_BF_RESET_MASK;
80 
81 		/* Copy 11AC mcs */
82 		adapter->hw_dot_11ac_mcs_support =
83 			le32_to_cpu(hw_spec->dot_11ac_mcs_support);
84 		adapter->usr_dot_11ac_mcs_support =
85 			adapter->hw_dot_11ac_mcs_support;
86 	} else {
87 		adapter->is_hw_11ac_capable = false;
88 	}
89 
90 	resp_size = le16_to_cpu(resp->size) - S_DS_GEN;
91 	if (resp_size > sizeof(struct host_cmd_ds_get_hw_spec)) {
92 		/* we have variable HW SPEC information */
93 		left_len = resp_size - sizeof(struct host_cmd_ds_get_hw_spec);
94 		while (left_len > sizeof(struct nxpwifi_ie_types_header)) {
95 			tlv = (void *)&hw_spec->tlv + parsed_len;
96 			switch (le16_to_cpu(tlv->type)) {
97 			case TLV_TYPE_API_REV:
98 				api_rev = (struct hw_spec_api_rev *)tlv;
99 				api_id = le16_to_cpu(api_rev->api_id);
100 				switch (api_id) {
101 				case KEY_API_VER_ID:
102 					adapter->key_api_major_ver =
103 						api_rev->major_ver;
104 					adapter->key_api_minor_ver =
105 						api_rev->minor_ver;
106 					nxpwifi_dbg(adapter, INFO,
107 						    "key_api v%d.%d\n",
108 						    adapter->key_api_major_ver,
109 						    adapter->key_api_minor_ver);
110 					break;
111 				case FW_API_VER_ID:
112 					adapter->fw_api_ver =
113 						api_rev->major_ver;
114 					nxpwifi_dbg(adapter, MSG,
115 						    "Firmware api version %d.%d\n",
116 						    adapter->fw_api_ver,
117 						    api_rev->minor_ver);
118 					break;
119 				case UAP_FW_API_VER_ID:
120 					nxpwifi_dbg(adapter, INFO,
121 						    "uAP api version %d.%d\n",
122 						    api_rev->major_ver,
123 						    api_rev->minor_ver);
124 					break;
125 				case CHANRPT_API_VER_ID:
126 					nxpwifi_dbg(adapter, INFO,
127 						    "channel report api version %d.%d\n",
128 						    api_rev->major_ver,
129 						    api_rev->minor_ver);
130 					break;
131 				case FW_HOTFIX_VER_ID:
132 					adapter->fw_hotfix_ver =
133 						api_rev->major_ver;
134 					nxpwifi_dbg(adapter, INFO,
135 						    "Firmware hotfix version %d\n",
136 						    api_rev->major_ver);
137 					break;
138 				default:
139 					nxpwifi_dbg(adapter, FATAL,
140 						    "Unknown api_id: %d\n",
141 						    api_id);
142 					break;
143 				}
144 				break;
145 			case TLV_TYPE_MAX_CONN:
146 				max_conn = (struct hw_spec_max_conn *)tlv;
147 				adapter->max_sta_conn = max_conn->max_sta_conn;
148 				nxpwifi_dbg(adapter, INFO,
149 					    "max sta connections: %u\n",
150 					    adapter->max_sta_conn);
151 				break;
152 			case TLV_TYPE_EXTENSION_ID:
153 				hw_he_cap = (struct hw_spec_extension *)tlv;
154 				if (hw_he_cap->ext_id ==
155 				    WLAN_EID_EXT_HE_CAPABILITY)
156 					nxpwifi_update_11ax_cap(adapter, hw_he_cap);
157 				break;
158 			case TLV_TYPE_FW_CAP_INFO:
159 				fw_cap = (struct hw_spec_fw_cap_info *)tlv;
160 				adapter->fw_cap_info =
161 					le32_to_cpu(fw_cap->fw_cap_info);
162 				adapter->fw_cap_ext =
163 					le32_to_cpu(fw_cap->fw_cap_ext);
164 				nxpwifi_dbg(adapter, INFO,
165 					    "fw_cap_info:%#x fw_cap_ext:%#x\n",
166 					    adapter->fw_cap_info,
167 					    adapter->fw_cap_ext);
168 				break;
169 			case TLV_TYPE_SECURE_BOOT_UUID:
170 				sb_uuid = (struct hw_spec_secure_boot_uuid *)tlv;
171 				adapter->uuid_lo =
172 					le64_to_cpu(sb_uuid->uuid_lo);
173 				adapter->uuid_hi =
174 					le64_to_cpu(sb_uuid->uuid_hi);
175 				nxpwifi_dbg(adapter, INFO,
176 					    "uuid: %#llx%#llx\n",
177 					    adapter->uuid_lo, adapter->uuid_hi);
178 				break;
179 			default:
180 				nxpwifi_dbg(adapter, FATAL,
181 					    "Unknown GET_HW_SPEC TLV type: %#x\n",
182 					    le16_to_cpu(tlv->type));
183 				break;
184 			}
185 			parsed_len += le16_to_cpu(tlv->len) +
186 				      sizeof(struct nxpwifi_ie_types_header);
187 			left_len -= le16_to_cpu(tlv->len) +
188 				      sizeof(struct nxpwifi_ie_types_header);
189 		}
190 	}
191 
192 	if (adapter->key_api_major_ver < KEY_API_VER_MAJOR_V2)
193 		return -EOPNOTSUPP;
194 
195 	nxpwifi_dbg(adapter, INFO,
196 		    "info: GET_HW_SPEC: fw_release_number- %#x\n",
197 		    adapter->fw_release_number);
198 	nxpwifi_dbg(adapter, INFO,
199 		    "info: GET_HW_SPEC: permanent addr: %pM\n",
200 		    hw_spec->permanent_addr);
201 	nxpwifi_dbg(adapter, INFO,
202 		    "info: GET_HW_SPEC: hw_if_version=%#x version=%#x\n",
203 		    le16_to_cpu(hw_spec->hw_if_version),
204 		    le16_to_cpu(hw_spec->version));
205 
206 	ether_addr_copy(priv->adapter->perm_addr, hw_spec->permanent_addr);
207 	adapter->region_code = le16_to_cpu(hw_spec->region_code);
208 
209 	/* If it's unidentified region code, use the default (USA/FCC) */
210 	if (!nxpwifi_is_valid_region_code(adapter->region_code)) {
211 		nxpwifi_dbg(adapter, WARN,
212 				    "cmd: unknown region code %#x, use default (USA/%#x)\n",
213 				    adapter->region_code, NXPWIFI_DEFAULT_REGION_CODE);
214 		adapter->region_code = NXPWIFI_DEFAULT_REGION_CODE;
215 	}
216 
217 	adapter->hw_dot_11n_dev_cap = le32_to_cpu(hw_spec->dot_11n_dev_cap);
218 	adapter->hw_dev_mcs_support = hw_spec->dev_mcs_support;
219 	adapter->hw_mpdu_density = GET_MPDU_DENSITY(le32_to_cpu(hw_spec->hw_dev_cap));
220 	adapter->user_dev_mcs_support = adapter->hw_dev_mcs_support;
221 	adapter->user_htstream = adapter->hw_dev_mcs_support;
222 	if (adapter->fw_bands & BAND_A)
223 		adapter->user_htstream |= (adapter->user_htstream << 8);
224 
225 	if (adapter->if_ops.update_mp_end_port) {
226 		u16 mp_end_port;
227 
228 		mp_end_port = le16_to_cpu(hw_spec->mp_end_port);
229 		adapter->if_ops.update_mp_end_port(adapter, mp_end_port);
230 	}
231 
232 	if (adapter->fw_api_ver == NXPWIFI_FW_V15)
233 		adapter->scan_chan_gap_enabled = true;
234 
235 	for (i = 0; i < adapter->priv_num; i++)
236 		adapter->priv[i]->config_bands = adapter->fw_bands;
237 
238 	return 0;
239 }
240 
241 static int
nxpwifi_cmd_sta_802_11_scan(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)242 nxpwifi_cmd_sta_802_11_scan(struct nxpwifi_private *priv,
243 			    struct host_cmd_ds_command *cmd,
244 			    u16 cmd_no, void *data_buf,
245 			    u16 cmd_action, u32 cmd_type)
246 {
247 	return nxpwifi_cmd_802_11_scan(cmd, data_buf);
248 }
249 
250 static int
nxpwifi_ret_sta_802_11_scan(struct nxpwifi_private * priv,struct host_cmd_ds_command * resp,u16 cmdresp_no,void * data_buf)251 nxpwifi_ret_sta_802_11_scan(struct nxpwifi_private *priv,
252 			    struct host_cmd_ds_command *resp,
253 			    u16 cmdresp_no,
254 			    void *data_buf)
255 {
256 	struct nxpwifi_adapter *adapter = priv->adapter;
257 	int ret;
258 
259 	ret = nxpwifi_ret_802_11_scan(priv, resp);
260 	adapter->curr_cmd->wait_q_enabled = false;
261 
262 	return ret;
263 }
264 
265 static int
nxpwifi_cmd_sta_802_11_get_log(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)266 nxpwifi_cmd_sta_802_11_get_log(struct nxpwifi_private *priv,
267 			       struct host_cmd_ds_command *cmd,
268 			       u16 cmd_no, void *data_buf,
269 			       u16 cmd_action, u32 cmd_type)
270 {
271 	cmd->command = cpu_to_le16(HOST_CMD_802_11_GET_LOG);
272 	cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_802_11_get_log) +
273 				S_DS_GEN);
274 
275 	return 0;
276 }
277 
278 static int
nxpwifi_ret_sta_802_11_get_log(struct nxpwifi_private * priv,struct host_cmd_ds_command * resp,u16 cmdresp_no,void * data_buf)279 nxpwifi_ret_sta_802_11_get_log(struct nxpwifi_private *priv,
280 			       struct host_cmd_ds_command *resp,
281 			       u16 cmdresp_no,
282 			       void *data_buf)
283 {
284 	struct host_cmd_ds_802_11_get_log *get_log =
285 		&resp->params.get_log;
286 	struct nxpwifi_ds_get_stats *stats =
287 		(struct nxpwifi_ds_get_stats *)data_buf;
288 
289 	if (stats) {
290 		stats->mcast_tx_frame = le32_to_cpu(get_log->mcast_tx_frame);
291 		stats->failed = le32_to_cpu(get_log->failed);
292 		stats->retry = le32_to_cpu(get_log->retry);
293 		stats->multi_retry = le32_to_cpu(get_log->multi_retry);
294 		stats->frame_dup = le32_to_cpu(get_log->frame_dup);
295 		stats->rts_success = le32_to_cpu(get_log->rts_success);
296 		stats->rts_failure = le32_to_cpu(get_log->rts_failure);
297 		stats->ack_failure = le32_to_cpu(get_log->ack_failure);
298 		stats->rx_frag = le32_to_cpu(get_log->rx_frag);
299 		stats->mcast_rx_frame = le32_to_cpu(get_log->mcast_rx_frame);
300 		stats->fcs_error = le32_to_cpu(get_log->fcs_error);
301 		stats->tx_frame = le32_to_cpu(get_log->tx_frame);
302 		stats->wep_icv_error[0] =
303 			le32_to_cpu(get_log->wep_icv_err_cnt[0]);
304 		stats->wep_icv_error[1] =
305 			le32_to_cpu(get_log->wep_icv_err_cnt[1]);
306 		stats->wep_icv_error[2] =
307 			le32_to_cpu(get_log->wep_icv_err_cnt[2]);
308 		stats->wep_icv_error[3] =
309 			le32_to_cpu(get_log->wep_icv_err_cnt[3]);
310 		stats->bcn_rcv_cnt = le32_to_cpu(get_log->bcn_rcv_cnt);
311 		stats->bcn_miss_cnt = le32_to_cpu(get_log->bcn_miss_cnt);
312 	}
313 
314 	return 0;
315 }
316 
317 static int
nxpwifi_cmd_sta_mac_multicast_adr(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)318 nxpwifi_cmd_sta_mac_multicast_adr(struct nxpwifi_private *priv,
319 				  struct host_cmd_ds_command *cmd,
320 				  u16 cmd_no, void *data_buf,
321 				  u16 cmd_action, u32 cmd_type)
322 {
323 	struct host_cmd_ds_mac_multicast_adr *mcast_addr = &cmd->params.mc_addr;
324 	struct nxpwifi_multicast_list *mcast_list =
325 		(struct nxpwifi_multicast_list *)data_buf;
326 
327 	cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_mac_multicast_adr) +
328 				S_DS_GEN);
329 	cmd->command = cpu_to_le16(HOST_CMD_MAC_MULTICAST_ADR);
330 
331 	mcast_addr->action = cpu_to_le16(cmd_action);
332 	mcast_addr->num_of_adrs =
333 		cpu_to_le16((u16)mcast_list->num_multicast_addr);
334 	memcpy(mcast_addr->mac_list, mcast_list->mac_list,
335 	       mcast_list->num_multicast_addr * ETH_ALEN);
336 
337 	return 0;
338 }
339 
340 static int
nxpwifi_cmd_sta_802_11_associate(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)341 nxpwifi_cmd_sta_802_11_associate(struct nxpwifi_private *priv,
342 				 struct host_cmd_ds_command *cmd,
343 				 u16 cmd_no, void *data_buf,
344 				 u16 cmd_action, u32 cmd_type)
345 {
346 	return nxpwifi_cmd_802_11_associate(priv, cmd, data_buf);
347 }
348 
349 static int
nxpwifi_ret_sta_802_11_associate(struct nxpwifi_private * priv,struct host_cmd_ds_command * resp,u16 cmdresp_no,void * data_buf)350 nxpwifi_ret_sta_802_11_associate(struct nxpwifi_private *priv,
351 				 struct host_cmd_ds_command *resp,
352 				 u16 cmdresp_no,
353 				 void *data_buf)
354 {
355 	return nxpwifi_ret_802_11_associate(priv, resp);
356 }
357 
358 static int
nxpwifi_cmd_sta_802_11_snmp_mib(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)359 nxpwifi_cmd_sta_802_11_snmp_mib(struct nxpwifi_private *priv,
360 				struct host_cmd_ds_command *cmd,
361 				u16 cmd_no, void *data_buf,
362 				u16 cmd_action, u32 cmd_type)
363 {
364 	struct host_cmd_ds_802_11_snmp_mib *snmp_mib = &cmd->params.smib;
365 	u16 *ul_temp = (u16 *)data_buf;
366 
367 	nxpwifi_dbg(priv->adapter, CMD,
368 		    "cmd: SNMP_CMD: cmd_oid = 0x%x\n", cmd_type);
369 	cmd->command = cpu_to_le16(HOST_CMD_802_11_SNMP_MIB);
370 	cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_802_11_snmp_mib)
371 				+ S_DS_GEN);
372 
373 	snmp_mib->oid = cpu_to_le16((u16)cmd_type);
374 	if (cmd_action == HOST_ACT_GEN_GET) {
375 		snmp_mib->query_type = cpu_to_le16(HOST_ACT_GEN_GET);
376 		snmp_mib->buf_size = cpu_to_le16(MAX_SNMP_BUF_SIZE);
377 		le16_unaligned_add_cpu(&cmd->size, MAX_SNMP_BUF_SIZE);
378 	} else if (cmd_action == HOST_ACT_GEN_SET) {
379 		snmp_mib->query_type = cpu_to_le16(HOST_ACT_GEN_SET);
380 		snmp_mib->buf_size = cpu_to_le16(sizeof(u16));
381 		put_unaligned_le16(*ul_temp, snmp_mib->value);
382 		le16_unaligned_add_cpu(&cmd->size, sizeof(u16));
383 	}
384 
385 	nxpwifi_dbg(priv->adapter, CMD,
386 		    "cmd: SNMP_CMD: Action=0x%x, OID=0x%x,\t"
387 		    "OIDSize=0x%x, Value=0x%x\n",
388 		    cmd_action, cmd_type, le16_to_cpu(snmp_mib->buf_size),
389 		    get_unaligned_le16(snmp_mib->value));
390 
391 	return 0;
392 }
393 
394 static int
nxpwifi_ret_sta_802_11_snmp_mib(struct nxpwifi_private * priv,struct host_cmd_ds_command * resp,u16 cmdresp_no,void * data_buf)395 nxpwifi_ret_sta_802_11_snmp_mib(struct nxpwifi_private *priv,
396 				struct host_cmd_ds_command *resp,
397 				u16 cmdresp_no,
398 				void *data_buf)
399 {
400 	struct host_cmd_ds_802_11_snmp_mib *smib = &resp->params.smib;
401 	u16 oid = le16_to_cpu(smib->oid);
402 	u16 query_type = le16_to_cpu(smib->query_type);
403 	u32 ul_temp;
404 
405 	nxpwifi_dbg(priv->adapter, INFO,
406 		    "info: SNMP_RESP: oid value = %#x,\t"
407 		    "query_type = %#x, buf size = %#x\n",
408 		    oid, query_type, le16_to_cpu(smib->buf_size));
409 	if (query_type == HOST_ACT_GEN_GET) {
410 		ul_temp = get_unaligned_le16(smib->value);
411 		if (data_buf)
412 			*(u32 *)data_buf = ul_temp;
413 		switch (oid) {
414 		case FRAG_THRESH_I:
415 			nxpwifi_dbg(priv->adapter, INFO,
416 				    "info: SNMP_RESP: FragThsd =%u\n",
417 				    ul_temp);
418 			break;
419 		case RTS_THRESH_I:
420 			nxpwifi_dbg(priv->adapter, INFO,
421 				    "info: SNMP_RESP: RTSThsd =%u\n",
422 				    ul_temp);
423 			break;
424 		case SHORT_RETRY_LIM_I:
425 			nxpwifi_dbg(priv->adapter, INFO,
426 				    "info: SNMP_RESP: TxRetryCount=%u\n",
427 				    ul_temp);
428 			break;
429 		case DTIM_PERIOD_I:
430 			nxpwifi_dbg(priv->adapter, INFO,
431 				    "info: SNMP_RESP: DTIM period=%u\n",
432 				    ul_temp);
433 			break;
434 		default:
435 			break;
436 		}
437 	}
438 
439 	return 0;
440 }
441 
nxpwifi_cmd_sta_reg_access(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)442 static int nxpwifi_cmd_sta_reg_access(struct nxpwifi_private *priv,
443 				      struct host_cmd_ds_command *cmd,
444 				      u16 cmd_no, void *data_buf,
445 				      u16 cmd_action, u32 cmd_type)
446 {
447 	struct nxpwifi_ds_reg_rw *reg_rw = data_buf;
448 
449 	cmd->command = cpu_to_le16(cmd_no);
450 
451 	switch (cmd_no) {
452 	case HOST_CMD_MAC_REG_ACCESS:
453 	{
454 		struct host_cmd_ds_mac_reg_access *mac_reg;
455 
456 		cmd->size = cpu_to_le16(sizeof(*mac_reg) + S_DS_GEN);
457 		mac_reg = &cmd->params.mac_reg;
458 		mac_reg->action = cpu_to_le16(cmd_action);
459 		mac_reg->offset = cpu_to_le16((u16)reg_rw->offset);
460 		mac_reg->value = cpu_to_le32(reg_rw->value);
461 		break;
462 	}
463 	case HOST_CMD_BBP_REG_ACCESS:
464 	{
465 		struct host_cmd_ds_bbp_reg_access *bbp_reg;
466 
467 		cmd->size = cpu_to_le16(sizeof(*bbp_reg) + S_DS_GEN);
468 		bbp_reg = &cmd->params.bbp_reg;
469 		bbp_reg->action = cpu_to_le16(cmd_action);
470 		bbp_reg->offset = cpu_to_le16((u16)reg_rw->offset);
471 		bbp_reg->value = (u8)reg_rw->value;
472 		break;
473 	}
474 	case HOST_CMD_RF_REG_ACCESS:
475 	{
476 		struct host_cmd_ds_rf_reg_access *rf_reg;
477 
478 		cmd->size = cpu_to_le16(sizeof(*rf_reg) + S_DS_GEN);
479 		rf_reg = &cmd->params.rf_reg;
480 		rf_reg->action = cpu_to_le16(cmd_action);
481 		rf_reg->offset = cpu_to_le16((u16)reg_rw->offset);
482 		rf_reg->value = (u8)reg_rw->value;
483 		break;
484 	}
485 	case HOST_CMD_PMIC_REG_ACCESS:
486 	{
487 		struct host_cmd_ds_pmic_reg_access *pmic_reg;
488 
489 		cmd->size = cpu_to_le16(sizeof(*pmic_reg) + S_DS_GEN);
490 		pmic_reg = &cmd->params.pmic_reg;
491 		pmic_reg->action = cpu_to_le16(cmd_action);
492 		pmic_reg->offset = cpu_to_le16((u16)reg_rw->offset);
493 		pmic_reg->value = (u8)reg_rw->value;
494 		break;
495 	}
496 	case HOST_CMD_CAU_REG_ACCESS:
497 	{
498 		struct host_cmd_ds_rf_reg_access *cau_reg;
499 
500 		cmd->size = cpu_to_le16(sizeof(*cau_reg) + S_DS_GEN);
501 		cau_reg = &cmd->params.rf_reg;
502 		cau_reg->action = cpu_to_le16(cmd_action);
503 		cau_reg->offset = cpu_to_le16((u16)reg_rw->offset);
504 		cau_reg->value = (u8)reg_rw->value;
505 		break;
506 	}
507 	case HOST_CMD_802_11_EEPROM_ACCESS:
508 	{
509 		struct nxpwifi_ds_read_eeprom *rd_eeprom = data_buf;
510 		struct host_cmd_ds_802_11_eeprom_access *cmd_eeprom =
511 			&cmd->params.eeprom;
512 
513 		cmd->size = cpu_to_le16(sizeof(*cmd_eeprom) + S_DS_GEN);
514 		cmd_eeprom->action = cpu_to_le16(cmd_action);
515 		cmd_eeprom->offset = cpu_to_le16(rd_eeprom->offset);
516 		cmd_eeprom->byte_count = cpu_to_le16(rd_eeprom->byte_count);
517 		cmd_eeprom->value = 0;
518 		break;
519 	}
520 	default:
521 		return -EINVAL;
522 	}
523 
524 	return 0;
525 }
526 
527 static int
nxpwifi_ret_sta_reg_access(struct nxpwifi_private * priv,struct host_cmd_ds_command * resp,u16 cmdresp_no,void * data_buf)528 nxpwifi_ret_sta_reg_access(struct nxpwifi_private *priv,
529 			   struct host_cmd_ds_command *resp,
530 			   u16 cmdresp_no,
531 			   void *data_buf)
532 {
533 	struct nxpwifi_ds_reg_rw *reg_rw;
534 	struct nxpwifi_ds_read_eeprom *eeprom;
535 	union reg {
536 		struct host_cmd_ds_mac_reg_access *mac;
537 		struct host_cmd_ds_bbp_reg_access *bbp;
538 		struct host_cmd_ds_rf_reg_access *rf;
539 		struct host_cmd_ds_pmic_reg_access *pmic;
540 		struct host_cmd_ds_802_11_eeprom_access *eeprom;
541 	} r;
542 
543 	if (!data_buf)
544 		return 0;
545 
546 	reg_rw = data_buf;
547 	eeprom = data_buf;
548 	switch (cmdresp_no) {
549 	case HOST_CMD_MAC_REG_ACCESS:
550 		r.mac = &resp->params.mac_reg;
551 		reg_rw->offset = (u32)le16_to_cpu(r.mac->offset);
552 		reg_rw->value = le32_to_cpu(r.mac->value);
553 		break;
554 	case HOST_CMD_BBP_REG_ACCESS:
555 		r.bbp = &resp->params.bbp_reg;
556 		reg_rw->offset = (u32)le16_to_cpu(r.bbp->offset);
557 		reg_rw->value = (u32)r.bbp->value;
558 		break;
559 
560 	case HOST_CMD_RF_REG_ACCESS:
561 		r.rf = &resp->params.rf_reg;
562 		reg_rw->offset = (u32)le16_to_cpu(r.rf->offset);
563 		reg_rw->value = (u32)r.bbp->value;
564 		break;
565 	case HOST_CMD_PMIC_REG_ACCESS:
566 		r.pmic = &resp->params.pmic_reg;
567 		reg_rw->offset = (u32)le16_to_cpu(r.pmic->offset);
568 		reg_rw->value = (u32)r.pmic->value;
569 		break;
570 	case HOST_CMD_CAU_REG_ACCESS:
571 		r.rf = &resp->params.rf_reg;
572 		reg_rw->offset = (u32)le16_to_cpu(r.rf->offset);
573 		reg_rw->value = (u32)r.rf->value;
574 		break;
575 	case HOST_CMD_802_11_EEPROM_ACCESS:
576 		r.eeprom = &resp->params.eeprom;
577 		pr_debug("info: EEPROM read len=%x\n",
578 			 le16_to_cpu(r.eeprom->byte_count));
579 		if (eeprom->byte_count < le16_to_cpu(r.eeprom->byte_count)) {
580 			eeprom->byte_count = 0;
581 			pr_debug("info: EEPROM read length is too big\n");
582 			return -ENOMEM;
583 		}
584 		eeprom->offset = le16_to_cpu(r.eeprom->offset);
585 		eeprom->byte_count = le16_to_cpu(r.eeprom->byte_count);
586 		if (eeprom->byte_count > 0)
587 			memcpy(&eeprom->value, &r.eeprom->value,
588 			       min((u16)MAX_EEPROM_DATA, eeprom->byte_count));
589 		break;
590 	default:
591 		return -EINVAL;
592 	}
593 	return 0;
594 }
595 
596 static int
nxpwifi_cmd_sta_rf_tx_pwr(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)597 nxpwifi_cmd_sta_rf_tx_pwr(struct nxpwifi_private *priv,
598 			  struct host_cmd_ds_command *cmd,
599 			  u16 cmd_no, void *data_buf,
600 			  u16 cmd_action, u32 cmd_type)
601 {
602 	struct host_cmd_ds_rf_tx_pwr *txp = &cmd->params.txp;
603 
604 	cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_rf_tx_pwr)
605 				+ S_DS_GEN);
606 	cmd->command = cpu_to_le16(HOST_CMD_RF_TX_PWR);
607 	txp->action = cpu_to_le16(cmd_action);
608 
609 	return 0;
610 }
611 
612 static int
nxpwifi_ret_sta_rf_tx_pwr(struct nxpwifi_private * priv,struct host_cmd_ds_command * resp,u16 cmdresp_no,void * data_buf)613 nxpwifi_ret_sta_rf_tx_pwr(struct nxpwifi_private *priv,
614 			  struct host_cmd_ds_command *resp,
615 			  u16 cmdresp_no,
616 			  void *data_buf)
617 {
618 	struct host_cmd_ds_rf_tx_pwr *txp = &resp->params.txp;
619 	u16 action = le16_to_cpu(txp->action);
620 
621 	priv->tx_power_level = le16_to_cpu(txp->cur_level);
622 
623 	if (action == HOST_ACT_GEN_GET) {
624 		priv->max_tx_power_level = txp->max_power;
625 		priv->min_tx_power_level = txp->min_power;
626 	}
627 
628 	nxpwifi_dbg(priv->adapter, INFO,
629 		    "Current TxPower Level=%d, Max Power=%d, Min Power=%d\n",
630 		    priv->tx_power_level, priv->max_tx_power_level,
631 		    priv->min_tx_power_level);
632 
633 	return 0;
634 }
635 
636 static int
nxpwifi_cmd_sta_rf_antenna(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)637 nxpwifi_cmd_sta_rf_antenna(struct nxpwifi_private *priv,
638 			   struct host_cmd_ds_command *cmd,
639 			   u16 cmd_no, void *data_buf,
640 			   u16 cmd_action, u32 cmd_type)
641 {
642 	struct host_cmd_ds_rf_ant_mimo *ant_mimo = &cmd->params.ant_mimo;
643 	struct host_cmd_ds_rf_ant_siso *ant_siso = &cmd->params.ant_siso;
644 	struct nxpwifi_ds_ant_cfg *ant_cfg =
645 		(struct nxpwifi_ds_ant_cfg *)data_buf;
646 
647 	cmd->command = cpu_to_le16(HOST_CMD_RF_ANTENNA);
648 
649 	switch (cmd_action) {
650 	case HOST_ACT_GEN_SET:
651 		if (priv->adapter->hw_dev_mcs_support == HT_STREAM_2X2) {
652 			cmd->size = cpu_to_le16(sizeof(struct
653 						host_cmd_ds_rf_ant_mimo)
654 						+ S_DS_GEN);
655 			ant_mimo->action_tx = cpu_to_le16(HOST_ACT_SET_TX);
656 			ant_mimo->tx_ant_mode =
657 				cpu_to_le16((u16)ant_cfg->tx_ant);
658 			ant_mimo->action_rx = cpu_to_le16(HOST_ACT_SET_RX);
659 			ant_mimo->rx_ant_mode =
660 				cpu_to_le16((u16)ant_cfg->rx_ant);
661 		} else {
662 			cmd->size = cpu_to_le16(sizeof(struct
663 						host_cmd_ds_rf_ant_siso) +
664 						S_DS_GEN);
665 			ant_siso->action = cpu_to_le16(HOST_ACT_SET_BOTH);
666 			ant_siso->ant_mode = cpu_to_le16((u16)ant_cfg->tx_ant);
667 		}
668 		break;
669 	case HOST_ACT_GEN_GET:
670 		if (priv->adapter->hw_dev_mcs_support == HT_STREAM_2X2) {
671 			cmd->size = cpu_to_le16(sizeof(struct
672 						host_cmd_ds_rf_ant_mimo) +
673 						S_DS_GEN);
674 			ant_mimo->action_tx = cpu_to_le16(HOST_ACT_GET_TX);
675 			ant_mimo->action_rx = cpu_to_le16(HOST_ACT_GET_RX);
676 		} else {
677 			cmd->size = cpu_to_le16(sizeof(struct
678 						host_cmd_ds_rf_ant_siso) +
679 						S_DS_GEN);
680 			ant_siso->action = cpu_to_le16(HOST_ACT_GET_BOTH);
681 		}
682 		break;
683 	}
684 	return 0;
685 }
686 
687 static int
nxpwifi_ret_sta_rf_antenna(struct nxpwifi_private * priv,struct host_cmd_ds_command * resp,u16 cmdresp_no,void * data_buf)688 nxpwifi_ret_sta_rf_antenna(struct nxpwifi_private *priv,
689 			   struct host_cmd_ds_command *resp,
690 			   u16 cmdresp_no,
691 			   void *data_buf)
692 {
693 	struct host_cmd_ds_rf_ant_mimo *ant_mimo = &resp->params.ant_mimo;
694 	struct host_cmd_ds_rf_ant_siso *ant_siso = &resp->params.ant_siso;
695 	struct nxpwifi_adapter *adapter = priv->adapter;
696 
697 	if (adapter->hw_dev_mcs_support == HT_STREAM_2X2) {
698 		priv->tx_ant = le16_to_cpu(ant_mimo->tx_ant_mode);
699 		priv->rx_ant = le16_to_cpu(ant_mimo->rx_ant_mode);
700 		nxpwifi_dbg(adapter, INFO,
701 			    "RF_ANT_RESP: Tx action = 0x%x, Tx Mode = 0x%04x\t"
702 			    "Rx action = 0x%x, Rx Mode = 0x%04x\n",
703 			    le16_to_cpu(ant_mimo->action_tx),
704 			    le16_to_cpu(ant_mimo->tx_ant_mode),
705 			    le16_to_cpu(ant_mimo->action_rx),
706 			    le16_to_cpu(ant_mimo->rx_ant_mode));
707 	} else {
708 		priv->tx_ant = le16_to_cpu(ant_siso->ant_mode);
709 		priv->rx_ant = le16_to_cpu(ant_siso->ant_mode);
710 		nxpwifi_dbg(adapter, INFO,
711 			    "RF_ANT_RESP: action = 0x%x, Mode = 0x%04x\n",
712 			    le16_to_cpu(ant_siso->action),
713 			    le16_to_cpu(ant_siso->ant_mode));
714 	}
715 	return 0;
716 }
717 
718 static int
nxpwifi_cmd_sta_802_11_deauthenticate(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)719 nxpwifi_cmd_sta_802_11_deauthenticate(struct nxpwifi_private *priv,
720 				      struct host_cmd_ds_command *cmd,
721 				      u16 cmd_no, void *data_buf,
722 				      u16 cmd_action, u32 cmd_type)
723 {
724 	struct host_cmd_ds_802_11_deauthenticate *deauth = &cmd->params.deauth;
725 	u8 *mac = (u8 *)data_buf;
726 
727 	cmd->command = cpu_to_le16(HOST_CMD_802_11_DEAUTHENTICATE);
728 	cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_802_11_deauthenticate)
729 				+ S_DS_GEN);
730 
731 	/* Set AP MAC address */
732 	memcpy(deauth->mac_addr, mac, ETH_ALEN);
733 
734 	nxpwifi_dbg(priv->adapter, CMD, "cmd: Deauth: %pM\n", deauth->mac_addr);
735 
736 	deauth->reason_code = cpu_to_le16(WLAN_REASON_DEAUTH_LEAVING);
737 
738 	return 0;
739 }
740 
741 static int
nxpwifi_ret_sta_802_11_deauthenticate(struct nxpwifi_private * priv,struct host_cmd_ds_command * resp,u16 cmdresp_no,void * data_buf)742 nxpwifi_ret_sta_802_11_deauthenticate(struct nxpwifi_private *priv,
743 				      struct host_cmd_ds_command *resp,
744 				      u16 cmdresp_no,
745 				      void *data_buf)
746 {
747 	struct nxpwifi_adapter *adapter = priv->adapter;
748 
749 	adapter->dbg.num_cmd_deauth++;
750 	if (!memcmp(resp->params.deauth.mac_addr,
751 		    &priv->curr_bss_params.bss_descriptor.mac_address,
752 		    sizeof(resp->params.deauth.mac_addr)))
753 		nxpwifi_reset_connect_state(priv, WLAN_REASON_DEAUTH_LEAVING,
754 					    false);
755 
756 	return 0;
757 }
758 
759 static int
nxpwifi_cmd_sta_mac_control(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)760 nxpwifi_cmd_sta_mac_control(struct nxpwifi_private *priv,
761 			    struct host_cmd_ds_command *cmd,
762 			    u16 cmd_no, void *data_buf,
763 			    u16 cmd_action, u32 cmd_type)
764 {
765 	struct host_cmd_ds_mac_control *mac_ctrl = &cmd->params.mac_ctrl;
766 	u32 *action = (u32 *)data_buf;
767 
768 	if (cmd_action != HOST_ACT_GEN_SET) {
769 		nxpwifi_dbg(priv->adapter, ERROR,
770 			    "mac_control: only support set cmd\n");
771 		return -EINVAL;
772 	}
773 
774 	cmd->command = cpu_to_le16(HOST_CMD_MAC_CONTROL);
775 	cmd->size =
776 		cpu_to_le16(sizeof(struct host_cmd_ds_mac_control) + S_DS_GEN);
777 	mac_ctrl->action = cpu_to_le32(*action);
778 
779 	return 0;
780 }
781 
782 static int
nxpwifi_cmd_sta_802_11_mac_address(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)783 nxpwifi_cmd_sta_802_11_mac_address(struct nxpwifi_private *priv,
784 				   struct host_cmd_ds_command *cmd,
785 				   u16 cmd_no, void *data_buf,
786 				   u16 cmd_action, u32 cmd_type)
787 {
788 	cmd->command = cpu_to_le16(HOST_CMD_802_11_MAC_ADDRESS);
789 	cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_802_11_mac_address) +
790 				S_DS_GEN);
791 	cmd->result = 0;
792 
793 	cmd->params.mac_addr.action = cpu_to_le16(cmd_action);
794 
795 	if (cmd_action == HOST_ACT_GEN_SET)
796 		memcpy(cmd->params.mac_addr.mac_addr, priv->curr_addr,
797 		       ETH_ALEN);
798 
799 	return 0;
800 }
801 
802 static int
nxpwifi_ret_sta_802_11_mac_address(struct nxpwifi_private * priv,struct host_cmd_ds_command * resp,u16 cmdresp_no,void * data_buf)803 nxpwifi_ret_sta_802_11_mac_address(struct nxpwifi_private *priv,
804 				   struct host_cmd_ds_command *resp,
805 				   u16 cmdresp_no,
806 				   void *data_buf)
807 {
808 	struct host_cmd_ds_802_11_mac_address *cmd_mac_addr;
809 
810 	cmd_mac_addr = &resp->params.mac_addr;
811 
812 	memcpy(priv->curr_addr, cmd_mac_addr->mac_addr, ETH_ALEN);
813 
814 	nxpwifi_dbg(priv->adapter, INFO,
815 		    "info: set mac address: %pM\n", priv->curr_addr);
816 
817 	return 0;
818 }
819 
820 static int
nxpwifi_cmd_sta_802_11d_domain_info(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)821 nxpwifi_cmd_sta_802_11d_domain_info(struct nxpwifi_private *priv,
822 				    struct host_cmd_ds_command *cmd,
823 				    u16 cmd_no, void *data_buf,
824 				    u16 cmd_action, u32 cmd_type)
825 {
826 	struct nxpwifi_adapter *adapter = priv->adapter;
827 	struct host_cmd_ds_802_11d_domain_info *domain_info =
828 		&cmd->params.domain_info;
829 	struct nxpwifi_ietypes_domain_param_set *domain =
830 		&domain_info->domain;
831 	struct nxpwifi_ietypes_domain_code *domain_code;
832 	u8 no_of_triplet = adapter->domain_reg.no_of_triplet;
833 	int triplet_size;
834 
835 	nxpwifi_dbg(adapter, INFO,
836 		    "info: 11D: no_of_triplet=0x%x\n", no_of_triplet);
837 
838 	cmd->command = cpu_to_le16(HOST_CMD_802_11D_DOMAIN_INFO);
839 	cmd->size = cpu_to_le16(S_DS_GEN);
840 	domain_info->action = cpu_to_le16(cmd_action);
841 	le16_unaligned_add_cpu(&cmd->size, sizeof(domain_info->action));
842 
843 	if (cmd_action == HOST_ACT_GEN_GET)
844 		return 0;
845 
846 	triplet_size = no_of_triplet *
847 		sizeof(struct ieee80211_country_ie_triplet);
848 
849 	domain->header.type = cpu_to_le16(WLAN_EID_COUNTRY);
850 	domain->header.len =
851 		cpu_to_le16(sizeof(domain->country_code) + triplet_size);
852 	memcpy(domain->country_code, adapter->domain_reg.country_code,
853 	       sizeof(domain->country_code));
854 	if (no_of_triplet)
855 		memcpy(domain->triplet, adapter->domain_reg.triplet,
856 		       triplet_size);
857 	le16_unaligned_add_cpu(&cmd->size, sizeof(*domain) + triplet_size);
858 
859 	domain_code = (struct nxpwifi_ietypes_domain_code *)((u8 *)cmd +
860 		le16_to_cpu(cmd->size));
861 	domain_code->header.type = cpu_to_le16(TLV_TYPE_REGION_DOMAIN_CODE);
862 	domain_code->header.len =
863 		cpu_to_le16(sizeof(*domain_code) -
864 		sizeof(struct nxpwifi_ie_types_header));
865 	le16_unaligned_add_cpu(&cmd->size, sizeof(*domain_code));
866 
867 	return 0;
868 }
869 
870 static int
nxpwifi_ret_sta_802_11d_domain_info(struct nxpwifi_private * priv,struct host_cmd_ds_command * resp,u16 cmdresp_no,void * data_buf)871 nxpwifi_ret_sta_802_11d_domain_info(struct nxpwifi_private *priv,
872 				    struct host_cmd_ds_command *resp,
873 				    u16 cmdresp_no,
874 				    void *data_buf)
875 {
876 	struct host_cmd_ds_802_11d_domain_info_rsp *domain_info =
877 		&resp->params.domain_info_resp;
878 	struct nxpwifi_ietypes_domain_param_set *domain = &domain_info->domain;
879 	u16 action = le16_to_cpu(domain_info->action);
880 	u8 no_of_triplet;
881 
882 	no_of_triplet = (u8)((le16_to_cpu(domain->header.len)
883 			     - IEEE80211_COUNTRY_STRING_LEN)
884 			     / sizeof(struct ieee80211_country_ie_triplet));
885 
886 	nxpwifi_dbg(priv->adapter, INFO,
887 		    "info: 11D Domain Info Resp: no_of_triplet=%d\n",
888 		    no_of_triplet);
889 
890 	if (no_of_triplet > NXPWIFI_MAX_TRIPLET_802_11D) {
891 		nxpwifi_dbg(priv->adapter, FATAL,
892 			    "11D: invalid number of triplets %d returned\n",
893 			    no_of_triplet);
894 		return -EINVAL;
895 	}
896 
897 	switch (action) {
898 	case HOST_ACT_GEN_SET:  /* Proc Set Action */
899 		break;
900 	case HOST_ACT_GEN_GET:
901 		break;
902 	default:
903 		nxpwifi_dbg(priv->adapter, ERROR,
904 			    "11D: invalid action:%d\n", domain_info->action);
905 		return -EINVAL;
906 	}
907 
908 	return 0;
909 }
910 
nxpwifi_set_aes_key(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,struct nxpwifi_ds_encrypt_key * enc_key,struct host_cmd_ds_802_11_key_material * km)911 static int nxpwifi_set_aes_key(struct nxpwifi_private *priv,
912 			       struct host_cmd_ds_command *cmd,
913 			       struct nxpwifi_ds_encrypt_key *enc_key,
914 			       struct host_cmd_ds_802_11_key_material *km)
915 {
916 	struct nxpwifi_adapter *adapter = priv->adapter;
917 	u16 size, len = KEY_PARAMS_FIXED_LEN;
918 	u8 key_type, key_type_igtk;
919 
920 	if (enc_key->key_len == WLAN_KEY_LEN_CCMP) {
921 		key_type = KEY_TYPE_ID_AES;
922 		key_type_igtk = KEY_TYPE_ID_AES_CMAC;
923 	} else {
924 		key_type = KEY_TYPE_ID_GCMP_256;
925 		key_type_igtk = KEY_TYPE_ID_BIP_GMAC_256;
926 	}
927 
928 	if (enc_key->is_igtk_key) {
929 		km->key_param_set.key_info &= cpu_to_le16(~KEY_MCAST);
930 		km->key_param_set.key_info |= cpu_to_le16(KEY_IGTK);
931 		km->key_param_set.key_type = key_type_igtk;
932 		if (enc_key->key_len == WLAN_KEY_LEN_CCMP) {
933 			nxpwifi_dbg(adapter, INFO,
934 				    "%s: Set CMAC AES Key\n", __func__);
935 			if (enc_key->is_rx_seq_valid)
936 				memcpy(km->key_param_set.key_params.cmac_aes.ipn,
937 				       enc_key->pn, enc_key->pn_len);
938 			km->key_param_set.key_params.cmac_aes.key_len =
939 				cpu_to_le16(enc_key->key_len);
940 			memcpy(km->key_param_set.key_params.cmac_aes.key,
941 			       enc_key->key_material, enc_key->key_len);
942 			len += sizeof(struct nxpwifi_cmac_aes_param);
943 		} else {
944 			nxpwifi_dbg(adapter, INFO,
945 				    "%s: Set GMAC AES Key\n", __func__);
946 			if (enc_key->is_rx_seq_valid)
947 				memcpy(km->key_param_set.key_params.gmac_aes.ipn,
948 				       enc_key->pn, enc_key->pn_len);
949 			km->key_param_set.key_params.gmac_aes.key_len =
950 				cpu_to_le16(enc_key->key_len);
951 			memcpy(km->key_param_set.key_params.gmac_aes.key,
952 			       enc_key->key_material, enc_key->key_len);
953 			len += sizeof(struct nxpwifi_gmac_aes_param);
954 		}
955 	} else if (enc_key->is_igtk_def_key) {
956 		nxpwifi_dbg(adapter, INFO,
957 			    "%s: Set CMAC default Key index\n", __func__);
958 		km->key_param_set.key_type = key_type_igtk;
959 		km->key_param_set.key_idx = enc_key->key_index & KEY_INDEX_MASK;
960 	} else {
961 		nxpwifi_dbg(adapter, INFO,
962 			    "%s: Set AES Key\n", __func__);
963 		if (enc_key->is_rx_seq_valid)
964 			memcpy(km->key_param_set.key_params.aes.pn,
965 			       enc_key->pn, enc_key->pn_len);
966 		km->key_param_set.key_type = key_type;
967 		km->key_param_set.key_params.aes.key_len =
968 					  cpu_to_le16(enc_key->key_len);
969 		memcpy(km->key_param_set.key_params.aes.key,
970 		       enc_key->key_material, enc_key->key_len);
971 		len += sizeof(struct nxpwifi_aes_param);
972 	}
973 
974 	km->key_param_set.len = cpu_to_le16(len);
975 	size = len + sizeof(struct nxpwifi_ie_types_header) +
976 	       sizeof(km->action) + S_DS_GEN;
977 	cmd->size = cpu_to_le16(size);
978 
979 	return 0;
980 }
981 
982 static int
nxpwifi_cmd_sta_802_11_key_material(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)983 nxpwifi_cmd_sta_802_11_key_material(struct nxpwifi_private *priv,
984 				    struct host_cmd_ds_command *cmd,
985 				    u16 cmd_no, void *data_buf,
986 				    u16 cmd_action, u32 cmd_type)
987 {
988 	struct nxpwifi_adapter *adapter = priv->adapter;
989 	struct nxpwifi_ds_encrypt_key *enc_key =
990 		(struct nxpwifi_ds_encrypt_key *)data_buf;
991 	u8 *mac = enc_key->mac_addr;
992 	u16 key_info, len = KEY_PARAMS_FIXED_LEN;
993 	struct host_cmd_ds_802_11_key_material *km =
994 		&cmd->params.key_material;
995 
996 	cmd->command = cpu_to_le16(HOST_CMD_802_11_KEY_MATERIAL);
997 	km->action = cpu_to_le16(cmd_action);
998 
999 	if (cmd_action == HOST_ACT_GEN_GET) {
1000 		nxpwifi_dbg(adapter, INFO, "%s: Get key\n", __func__);
1001 		km->key_param_set.key_idx =
1002 			enc_key->key_index & KEY_INDEX_MASK;
1003 		km->key_param_set.type = cpu_to_le16(TLV_TYPE_KEY_PARAM_V2);
1004 		km->key_param_set.len = cpu_to_le16(KEY_PARAMS_FIXED_LEN);
1005 		ether_addr_copy(km->key_param_set.mac_addr, mac);
1006 
1007 		if (enc_key->key_index & NXPWIFI_KEY_INDEX_UNICAST)
1008 			key_info = KEY_UNICAST;
1009 		else
1010 			key_info = KEY_MCAST;
1011 
1012 		if (enc_key->is_igtk_key)
1013 			key_info |= KEY_IGTK;
1014 
1015 		km->key_param_set.key_info = cpu_to_le16(key_info);
1016 
1017 		cmd->size = cpu_to_le16(sizeof(struct nxpwifi_ie_types_header) +
1018 					S_DS_GEN + KEY_PARAMS_FIXED_LEN +
1019 					sizeof(km->action));
1020 		return 0;
1021 	}
1022 
1023 	memset(&km->key_param_set, 0,
1024 	       sizeof(struct nxpwifi_ie_type_key_param_set));
1025 
1026 	if (enc_key->key_disable) {
1027 		nxpwifi_dbg(adapter, INFO, "%s: Remove key\n", __func__);
1028 		km->action = cpu_to_le16(HOST_ACT_GEN_REMOVE);
1029 		km->key_param_set.type = cpu_to_le16(TLV_TYPE_KEY_PARAM_V2);
1030 		km->key_param_set.len = cpu_to_le16(KEY_PARAMS_FIXED_LEN);
1031 		km->key_param_set.key_idx = enc_key->key_index & KEY_INDEX_MASK;
1032 		key_info = KEY_MCAST | KEY_UNICAST;
1033 		km->key_param_set.key_info = cpu_to_le16(key_info);
1034 		ether_addr_copy(km->key_param_set.mac_addr, mac);
1035 		cmd->size = cpu_to_le16(sizeof(struct nxpwifi_ie_types_header) +
1036 					S_DS_GEN + KEY_PARAMS_FIXED_LEN +
1037 					sizeof(km->action));
1038 		return 0;
1039 	}
1040 
1041 	km->action = cpu_to_le16(HOST_ACT_GEN_SET);
1042 	km->key_param_set.key_idx = enc_key->key_index & KEY_INDEX_MASK;
1043 	km->key_param_set.type = cpu_to_le16(TLV_TYPE_KEY_PARAM_V2);
1044 	key_info = KEY_ENABLED;
1045 	ether_addr_copy(km->key_param_set.mac_addr, mac);
1046 
1047 	if (enc_key->key_len <= WLAN_KEY_LEN_WEP104) {
1048 		nxpwifi_dbg(adapter, INFO, "%s: Set WEP Key\n", __func__);
1049 		len += sizeof(struct nxpwifi_wep_param);
1050 		km->key_param_set.len = cpu_to_le16(len);
1051 		km->key_param_set.key_type = KEY_TYPE_ID_WEP;
1052 
1053 		if (GET_BSS_ROLE(priv) == NXPWIFI_BSS_ROLE_UAP) {
1054 			key_info |= KEY_MCAST | KEY_UNICAST;
1055 		} else {
1056 			if (enc_key->is_current_wep_key) {
1057 				key_info |= KEY_MCAST | KEY_UNICAST;
1058 				if (km->key_param_set.key_idx ==
1059 				    (priv->wep_key_curr_index & KEY_INDEX_MASK))
1060 					key_info |= KEY_DEFAULT;
1061 			} else {
1062 				if (is_broadcast_ether_addr(mac))
1063 					key_info |= KEY_MCAST;
1064 				else
1065 					key_info |= KEY_UNICAST | KEY_DEFAULT;
1066 			}
1067 		}
1068 		km->key_param_set.key_info = cpu_to_le16(key_info);
1069 
1070 		km->key_param_set.key_params.wep.key_len =
1071 						  cpu_to_le16(enc_key->key_len);
1072 		memcpy(km->key_param_set.key_params.wep.key,
1073 		       enc_key->key_material, enc_key->key_len);
1074 
1075 		cmd->size = cpu_to_le16(sizeof(struct nxpwifi_ie_types_header) +
1076 					len + sizeof(km->action) + S_DS_GEN);
1077 		return 0;
1078 	}
1079 
1080 	if (is_broadcast_ether_addr(mac))
1081 		key_info |= KEY_MCAST | KEY_RX_KEY;
1082 	else
1083 		key_info |= KEY_UNICAST | KEY_TX_KEY | KEY_RX_KEY;
1084 
1085 	/* Enable default key for WPA/WPA2 */
1086 	if (!priv->wpa_is_gtk_set)
1087 		key_info |= KEY_DEFAULT;
1088 
1089 	km->key_param_set.key_info = cpu_to_le16(key_info);
1090 
1091 	if (enc_key->key_cipher != WLAN_CIPHER_SUITE_TKIP &&
1092 	    enc_key->key_len >= WLAN_KEY_LEN_CCMP)
1093 		return nxpwifi_set_aes_key(priv, cmd, enc_key, km);
1094 
1095 	if (enc_key->key_len == WLAN_KEY_LEN_TKIP) {
1096 		nxpwifi_dbg(adapter, INFO,
1097 			    "%s: Set TKIP Key\n", __func__);
1098 		if (enc_key->is_rx_seq_valid)
1099 			memcpy(km->key_param_set.key_params.tkip.pn,
1100 			       enc_key->pn, enc_key->pn_len);
1101 		km->key_param_set.key_type = KEY_TYPE_ID_TKIP;
1102 		km->key_param_set.key_params.tkip.key_len =
1103 						cpu_to_le16(enc_key->key_len);
1104 		memcpy(km->key_param_set.key_params.tkip.key,
1105 		       enc_key->key_material, enc_key->key_len);
1106 
1107 		len += sizeof(struct nxpwifi_tkip_param);
1108 		km->key_param_set.len = cpu_to_le16(len);
1109 		cmd->size = cpu_to_le16(sizeof(struct nxpwifi_ie_types_header) +
1110 					len + sizeof(km->action) + S_DS_GEN);
1111 	}
1112 
1113 	return 0;
1114 }
1115 
1116 static int
nxpwifi_ret_sta_802_11_key_material(struct nxpwifi_private * priv,struct host_cmd_ds_command * resp,u16 cmdresp_no,void * data_buf)1117 nxpwifi_ret_sta_802_11_key_material(struct nxpwifi_private *priv,
1118 				    struct host_cmd_ds_command *resp,
1119 				    u16 cmdresp_no,
1120 				    void *data_buf)
1121 {
1122 	struct host_cmd_ds_802_11_key_material *key;
1123 	int len;
1124 
1125 	key = &resp->params.key_material;
1126 
1127 	len = le16_to_cpu(key->key_param_set.key_params.aes.key_len);
1128 	if (len > sizeof(key->key_param_set.key_params.aes.key))
1129 		return -EINVAL;
1130 
1131 	if (le16_to_cpu(key->action) == HOST_ACT_GEN_SET) {
1132 		if ((le16_to_cpu(key->key_param_set.key_info) & KEY_MCAST)) {
1133 			nxpwifi_dbg(priv->adapter, INFO,
1134 				    "info: key: GTK is set\n");
1135 			priv->wpa_is_gtk_set = true;
1136 			priv->scan_block = false;
1137 			priv->port_open = true;
1138 		}
1139 	}
1140 
1141 	if (key->key_param_set.key_type != KEY_TYPE_ID_AES &&
1142 	    key->key_param_set.key_type != KEY_TYPE_ID_GCMP_256)
1143 		return 0;
1144 
1145 	memset(priv->aes_key.key_param_set.key_params.aes.key, 0,
1146 	       sizeof(key->key_param_set.key_params.aes.key));
1147 	priv->aes_key.key_param_set.key_params.aes.key_len = cpu_to_le16(len);
1148 	memcpy(priv->aes_key.key_param_set.key_params.aes.key,
1149 	       key->key_param_set.key_params.aes.key, len);
1150 
1151 	return 0;
1152 }
1153 
1154 static int
nxpwifi_cmd_sta_802_11_bg_scan_config(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)1155 nxpwifi_cmd_sta_802_11_bg_scan_config(struct nxpwifi_private *priv,
1156 				      struct host_cmd_ds_command *cmd,
1157 				      u16 cmd_no, void *data_buf,
1158 				      u16 cmd_action, u32 cmd_type)
1159 {
1160 	return nxpwifi_cmd_802_11_bg_scan_config(priv, cmd, data_buf);
1161 }
1162 
1163 static int
nxpwifi_cmd_sta_802_11_bg_scan_query(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)1164 nxpwifi_cmd_sta_802_11_bg_scan_query(struct nxpwifi_private *priv,
1165 				     struct host_cmd_ds_command *cmd,
1166 				     u16 cmd_no, void *data_buf,
1167 				     u16 cmd_action, u32 cmd_type)
1168 {
1169 	return nxpwifi_cmd_802_11_bg_scan_query(cmd);
1170 }
1171 
1172 static int
nxpwifi_ret_sta_802_11_bg_scan_query(struct nxpwifi_private * priv,struct host_cmd_ds_command * resp,u16 cmdresp_no,void * data_buf)1173 nxpwifi_ret_sta_802_11_bg_scan_query(struct nxpwifi_private *priv,
1174 				     struct host_cmd_ds_command *resp,
1175 				     u16 cmdresp_no,
1176 				     void *data_buf)
1177 {
1178 	struct nxpwifi_adapter *adapter = priv->adapter;
1179 	int ret;
1180 
1181 	ret = nxpwifi_ret_802_11_scan(priv, resp);
1182 	cfg80211_sched_scan_results(priv->wdev.wiphy, 0);
1183 	nxpwifi_dbg(adapter, CMD,
1184 		    "info: CMD_RESP: BG_SCAN result is ready!\n");
1185 
1186 	return ret;
1187 }
1188 
1189 static int
nxpwifi_cmd_sta_wmm_get_status(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)1190 nxpwifi_cmd_sta_wmm_get_status(struct nxpwifi_private *priv,
1191 			       struct host_cmd_ds_command *cmd,
1192 			       u16 cmd_no, void *data_buf,
1193 			       u16 cmd_action, u32 cmd_type)
1194 {
1195 	cmd->command = cpu_to_le16(HOST_CMD_WMM_GET_STATUS);
1196 	cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_wmm_get_status) +
1197 				S_DS_GEN);
1198 
1199 	return 0;
1200 }
1201 
1202 static int
nxpwifi_ret_sta_wmm_get_status(struct nxpwifi_private * priv,struct host_cmd_ds_command * resp,u16 cmdresp_no,void * data_buf)1203 nxpwifi_ret_sta_wmm_get_status(struct nxpwifi_private *priv,
1204 			       struct host_cmd_ds_command *resp,
1205 			       u16 cmdresp_no,
1206 			       void *data_buf)
1207 {
1208 	return nxpwifi_ret_wmm_get_status(priv, resp);
1209 }
1210 
1211 static int
nxpwifi_cmd_sta_802_11_subsc_evt(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)1212 nxpwifi_cmd_sta_802_11_subsc_evt(struct nxpwifi_private *priv,
1213 				 struct host_cmd_ds_command *cmd,
1214 				 u16 cmd_no, void *data_buf,
1215 				 u16 cmd_action, u32 cmd_type)
1216 {
1217 	struct host_cmd_ds_802_11_subsc_evt *subsc_evt = &cmd->params.subsc_evt;
1218 	struct nxpwifi_ds_misc_subsc_evt *subsc_evt_cfg =
1219 		(struct nxpwifi_ds_misc_subsc_evt *)data_buf;
1220 	struct nxpwifi_ie_types_rssi_threshold *rssi_tlv;
1221 	u16 event_bitmap;
1222 	u8 *pos;
1223 
1224 	cmd->command = cpu_to_le16(HOST_CMD_802_11_SUBSCRIBE_EVENT);
1225 	cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_802_11_subsc_evt) +
1226 				S_DS_GEN);
1227 
1228 	subsc_evt->action = cpu_to_le16(subsc_evt_cfg->action);
1229 	nxpwifi_dbg(priv->adapter, CMD,
1230 		    "cmd: action: %d\n", subsc_evt_cfg->action);
1231 
1232 	/* For query requests, no configuration TLV structures are to be added. */
1233 	if (subsc_evt_cfg->action == HOST_ACT_GEN_GET)
1234 		return 0;
1235 
1236 	subsc_evt->events = cpu_to_le16(subsc_evt_cfg->events);
1237 
1238 	event_bitmap = subsc_evt_cfg->events;
1239 	nxpwifi_dbg(priv->adapter, CMD, "cmd: event bitmap : %16x\n",
1240 		    event_bitmap);
1241 
1242 	if ((subsc_evt_cfg->action == HOST_ACT_BITWISE_CLR ||
1243 	     subsc_evt_cfg->action == HOST_ACT_BITWISE_SET) &&
1244 	    event_bitmap == 0) {
1245 		nxpwifi_dbg(priv->adapter, ERROR,
1246 			    "Error: No event specified\t"
1247 			    "for bitwise action type\n");
1248 		return -EINVAL;
1249 	}
1250 
1251 	/*
1252 	 * Append TLV structures for each of the specified events for
1253 	 * subscribing or re-configuring. This is not required for
1254 	 * bitwise unsubscribing request.
1255 	 */
1256 	if (subsc_evt_cfg->action == HOST_ACT_BITWISE_CLR)
1257 		return 0;
1258 
1259 	pos = ((u8 *)subsc_evt) +
1260 			sizeof(struct host_cmd_ds_802_11_subsc_evt);
1261 
1262 	if (event_bitmap & BITMASK_BCN_RSSI_LOW) {
1263 		rssi_tlv = (struct nxpwifi_ie_types_rssi_threshold *)pos;
1264 
1265 		rssi_tlv->header.type = cpu_to_le16(TLV_TYPE_RSSI_LOW);
1266 		rssi_tlv->header.len =
1267 		    cpu_to_le16(sizeof(struct nxpwifi_ie_types_rssi_threshold) -
1268 				sizeof(struct nxpwifi_ie_types_header));
1269 		rssi_tlv->abs_value = subsc_evt_cfg->bcn_l_rssi_cfg.abs_value;
1270 		rssi_tlv->evt_freq = subsc_evt_cfg->bcn_l_rssi_cfg.evt_freq;
1271 
1272 		nxpwifi_dbg(priv->adapter, EVENT,
1273 			    "Cfg Beacon Low Rssi event,\t"
1274 			    "RSSI:-%d dBm, Freq:%d\n",
1275 			    subsc_evt_cfg->bcn_l_rssi_cfg.abs_value,
1276 			    subsc_evt_cfg->bcn_l_rssi_cfg.evt_freq);
1277 
1278 		pos += sizeof(struct nxpwifi_ie_types_rssi_threshold);
1279 		le16_unaligned_add_cpu
1280 		(&cmd->size,
1281 		 sizeof(struct nxpwifi_ie_types_rssi_threshold));
1282 	}
1283 
1284 	if (event_bitmap & BITMASK_BCN_RSSI_HIGH) {
1285 		rssi_tlv = (struct nxpwifi_ie_types_rssi_threshold *)pos;
1286 
1287 		rssi_tlv->header.type = cpu_to_le16(TLV_TYPE_RSSI_HIGH);
1288 		rssi_tlv->header.len =
1289 		    cpu_to_le16(sizeof(struct nxpwifi_ie_types_rssi_threshold) -
1290 				sizeof(struct nxpwifi_ie_types_header));
1291 		rssi_tlv->abs_value = subsc_evt_cfg->bcn_h_rssi_cfg.abs_value;
1292 		rssi_tlv->evt_freq = subsc_evt_cfg->bcn_h_rssi_cfg.evt_freq;
1293 
1294 		nxpwifi_dbg(priv->adapter, EVENT,
1295 			    "Cfg Beacon High Rssi event,\t"
1296 			    "RSSI:-%d dBm, Freq:%d\n",
1297 			    subsc_evt_cfg->bcn_h_rssi_cfg.abs_value,
1298 			    subsc_evt_cfg->bcn_h_rssi_cfg.evt_freq);
1299 
1300 		pos += sizeof(struct nxpwifi_ie_types_rssi_threshold);
1301 		le16_unaligned_add_cpu
1302 		(&cmd->size,
1303 		 sizeof(struct nxpwifi_ie_types_rssi_threshold));
1304 	}
1305 
1306 	return 0;
1307 }
1308 
1309 static int
nxpwifi_ret_sta_subsc_evt(struct nxpwifi_private * priv,struct host_cmd_ds_command * resp,u16 cmdresp_no,void * data_buf)1310 nxpwifi_ret_sta_subsc_evt(struct nxpwifi_private *priv,
1311 			  struct host_cmd_ds_command *resp,
1312 			  u16 cmdresp_no,
1313 			  void *data_buf)
1314 {
1315 	struct host_cmd_ds_802_11_subsc_evt *cmd_sub_event =
1316 		&resp->params.subsc_evt;
1317 
1318 	/*
1319 	 * For every subscribe event command (Get/Set/Clear), FW reports the current
1320 	 * set of subscribed events
1321 	 */
1322 	nxpwifi_dbg(priv->adapter, EVENT,
1323 		    "Bitmap of currently subscribed events: %16x\n",
1324 		    le16_to_cpu(cmd_sub_event->events));
1325 
1326 	return 0;
1327 }
1328 
1329 static int
nxpwifi_cmd_sta_802_11_tx_rate_query(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)1330 nxpwifi_cmd_sta_802_11_tx_rate_query(struct nxpwifi_private *priv,
1331 				     struct host_cmd_ds_command *cmd,
1332 				     u16 cmd_no, void *data_buf,
1333 				     u16 cmd_action, u32 cmd_type)
1334 {
1335 	cmd->command = cpu_to_le16(HOST_CMD_802_11_TX_RATE_QUERY);
1336 	cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_tx_rate_query) +
1337 				S_DS_GEN);
1338 	priv->tx_rate = 0;
1339 
1340 	return 0;
1341 }
1342 
1343 static int
nxpwifi_ret_sta_802_11_tx_rate_query(struct nxpwifi_private * priv,struct host_cmd_ds_command * resp,u16 cmdresp_no,void * data_buf)1344 nxpwifi_ret_sta_802_11_tx_rate_query(struct nxpwifi_private *priv,
1345 				     struct host_cmd_ds_command *resp,
1346 				     u16 cmdresp_no,
1347 				     void *data_buf)
1348 {
1349 	priv->tx_rate = resp->params.tx_rate.tx_rate;
1350 	priv->tx_htinfo = resp->params.tx_rate.ht_info;
1351 	if (!priv->is_data_rate_auto)
1352 		priv->data_rate =
1353 			nxpwifi_index_to_data_rate(priv, priv->tx_rate,
1354 						   priv->tx_htinfo);
1355 
1356 	return 0;
1357 }
1358 
1359 static int
nxpwifi_cmd_sta_mem_access(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)1360 nxpwifi_cmd_sta_mem_access(struct nxpwifi_private *priv,
1361 			   struct host_cmd_ds_command *cmd,
1362 			   u16 cmd_no, void *data_buf,
1363 			   u16 cmd_action, u32 cmd_type)
1364 {
1365 	struct nxpwifi_ds_mem_rw *mem_rw =
1366 		(struct nxpwifi_ds_mem_rw *)data_buf;
1367 	struct host_cmd_ds_mem_access *mem_access = (void *)&cmd->params.mem;
1368 
1369 	cmd->command = cpu_to_le16(HOST_CMD_MEM_ACCESS);
1370 	cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_mem_access) +
1371 				S_DS_GEN);
1372 
1373 	mem_access->action = cpu_to_le16(cmd_action);
1374 	mem_access->addr = cpu_to_le32(mem_rw->addr);
1375 	mem_access->value = cpu_to_le32(mem_rw->value);
1376 
1377 	return 0;
1378 }
1379 
1380 static int
nxpwifi_ret_sta_mem_access(struct nxpwifi_private * priv,struct host_cmd_ds_command * resp,u16 cmdresp_no,void * data_buf)1381 nxpwifi_ret_sta_mem_access(struct nxpwifi_private *priv,
1382 			   struct host_cmd_ds_command *resp,
1383 			   u16 cmdresp_no,
1384 			   void *data_buf)
1385 {
1386 	struct host_cmd_ds_mem_access *mem = (void *)&resp->params.mem;
1387 
1388 	priv->mem_rw.addr = le32_to_cpu(mem->addr);
1389 	priv->mem_rw.value = le32_to_cpu(mem->value);
1390 
1391 	return 0;
1392 }
1393 
nxpwifi_parse_cal_cfg(u8 * src,size_t len,u8 * dst)1394 static u32 nxpwifi_parse_cal_cfg(u8 *src, size_t len, u8 *dst)
1395 {
1396 	u8 *s = src, *d = dst;
1397 
1398 	while (s - src < len) {
1399 		if (*s && (isspace(*s) || *s == '\t')) {
1400 			s++;
1401 			continue;
1402 		}
1403 		if (isxdigit(*s)) {
1404 			if (kstrtou8(s, 16, d))
1405 				return 0;
1406 			d++;
1407 			s += 2;
1408 		} else {
1409 			s++;
1410 		}
1411 	}
1412 
1413 	return d - dst;
1414 }
1415 
1416 static int
nxpwifi_cmd_sta_cfg_data(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)1417 nxpwifi_cmd_sta_cfg_data(struct nxpwifi_private *priv,
1418 			 struct host_cmd_ds_command *cmd,
1419 			 u16 cmd_no, void *data_buf,
1420 			 u16 cmd_action, u32 cmd_type)
1421 {
1422 	struct nxpwifi_adapter *adapter = priv->adapter;
1423 	u32 len;
1424 	u8 *data = (u8 *)cmd + S_DS_GEN;
1425 
1426 	if (adapter->cal_data->data && adapter->cal_data->size > 0) {
1427 		len = nxpwifi_parse_cal_cfg((u8 *)adapter->cal_data->data,
1428 					    adapter->cal_data->size, data);
1429 		nxpwifi_dbg(adapter, INFO,
1430 			    "download cfg_data from config file\n");
1431 	} else {
1432 		return -EINVAL;
1433 	}
1434 
1435 	cmd->command = cpu_to_le16(HOST_CMD_CFG_DATA);
1436 	cmd->size = cpu_to_le16(S_DS_GEN + len);
1437 
1438 	return 0;
1439 }
1440 
1441 static int
nxpwifi_ret_sta_cfg_data(struct nxpwifi_private * priv,struct host_cmd_ds_command * resp,u16 cmdresp_no,void * data_buf)1442 nxpwifi_ret_sta_cfg_data(struct nxpwifi_private *priv,
1443 			 struct host_cmd_ds_command *resp,
1444 			 u16 cmdresp_no,
1445 			 void *data_buf)
1446 {
1447 	if (resp->result != HOST_RESULT_OK) {
1448 		nxpwifi_dbg(priv->adapter, ERROR, "Cal data cmd resp failed\n");
1449 		return -EINVAL;
1450 	}
1451 
1452 	return 0;
1453 }
1454 
1455 static int
nxpwifi_cmd_sta_ver_ext(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)1456 nxpwifi_cmd_sta_ver_ext(struct nxpwifi_private *priv,
1457 			struct host_cmd_ds_command *cmd,
1458 			u16 cmd_no, void *data_buf,
1459 			u16 cmd_action, u32 cmd_type)
1460 {
1461 	cmd->command = cpu_to_le16(cmd_no);
1462 	cmd->params.verext.version_str_sel =
1463 		(u8)(get_unaligned((u32 *)data_buf));
1464 	memcpy(&cmd->params, data_buf, sizeof(struct host_cmd_ds_version_ext));
1465 	cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_version_ext) +
1466 				S_DS_GEN);
1467 
1468 	return 0;
1469 }
1470 
1471 static int
nxpwifi_ret_sta_ver_ext(struct nxpwifi_private * priv,struct host_cmd_ds_command * resp,u16 cmdresp_no,void * data_buf)1472 nxpwifi_ret_sta_ver_ext(struct nxpwifi_private *priv,
1473 			struct host_cmd_ds_command *resp,
1474 			u16 cmdresp_no,
1475 			void *data_buf)
1476 {
1477 	struct host_cmd_ds_version_ext *ver_ext = &resp->params.verext;
1478 	struct host_cmd_ds_version_ext *version_ext =
1479 		(struct host_cmd_ds_version_ext *)data_buf;
1480 
1481 	if (test_and_clear_bit(NXPWIFI_IS_REQUESTING_FW_VEREXT, &priv->adapter->work_flags)) {
1482 		if (strncmp(ver_ext->version_str, "ChipRev:20, BB:9b(10.00), RF:40(21)",
1483 			    NXPWIFI_VERSION_STR_LENGTH) == 0) {
1484 			struct nxpwifi_ds_auto_ds auto_ds = {
1485 				.auto_ds = DEEP_SLEEP_OFF,
1486 			};
1487 
1488 			nxpwifi_dbg(priv->adapter, MSG,
1489 				    "Bad HW revision detected, disabling deep sleep\n");
1490 
1491 			if (nxpwifi_send_cmd(priv, HOST_CMD_802_11_PS_MODE_ENH,
1492 					     DIS_AUTO_PS, BITMAP_AUTO_DS, &auto_ds, false)) {
1493 				nxpwifi_dbg(priv->adapter, MSG,
1494 					    "Disabling deep sleep failed.\n");
1495 			}
1496 		}
1497 
1498 		return 0;
1499 	}
1500 
1501 	if (version_ext) {
1502 		version_ext->version_str_sel = ver_ext->version_str_sel;
1503 		memcpy(version_ext->version_str, ver_ext->version_str,
1504 		       NXPWIFI_VERSION_STR_LENGTH);
1505 		memcpy(priv->version_str, ver_ext->version_str,
1506 		       NXPWIFI_VERSION_STR_LENGTH);
1507 
1508 		/* Ensure the version string from the firmware is 0-terminated */
1509 		priv->version_str[NXPWIFI_VERSION_STR_LENGTH - 1] = '\0';
1510 	}
1511 	return 0;
1512 }
1513 
1514 static int
nxpwifi_cmd_append_rpn_expression(struct nxpwifi_private * priv,struct nxpwifi_mef_entry * mef_entry,u8 ** buffer)1515 nxpwifi_cmd_append_rpn_expression(struct nxpwifi_private *priv,
1516 				  struct nxpwifi_mef_entry *mef_entry,
1517 				  u8 **buffer)
1518 {
1519 	struct nxpwifi_mef_filter *filter = mef_entry->filter;
1520 	int i, byte_len;
1521 	u8 *stack_ptr = *buffer;
1522 
1523 	for (i = 0; i < NXPWIFI_MEF_MAX_FILTERS; i++) {
1524 		filter = &mef_entry->filter[i];
1525 		if (!filter->filt_type)
1526 			break;
1527 		put_unaligned_le32((u32)filter->repeat, stack_ptr);
1528 		stack_ptr += 4;
1529 		*stack_ptr = TYPE_DNUM;
1530 		stack_ptr += 1;
1531 
1532 		byte_len = filter->byte_seq[NXPWIFI_MEF_MAX_BYTESEQ];
1533 		memcpy(stack_ptr, filter->byte_seq, byte_len);
1534 		stack_ptr += byte_len;
1535 		*stack_ptr = byte_len;
1536 		stack_ptr += 1;
1537 		*stack_ptr = TYPE_BYTESEQ;
1538 		stack_ptr += 1;
1539 		put_unaligned_le32((u32)filter->offset, stack_ptr);
1540 		stack_ptr += 4;
1541 		*stack_ptr = TYPE_DNUM;
1542 		stack_ptr += 1;
1543 
1544 		*stack_ptr = filter->filt_type;
1545 		stack_ptr += 1;
1546 
1547 		if (filter->filt_action) {
1548 			*stack_ptr = filter->filt_action;
1549 			stack_ptr += 1;
1550 		}
1551 
1552 		if (stack_ptr - *buffer > STACK_NBYTES)
1553 			return -ENOMEM;
1554 	}
1555 
1556 	*buffer = stack_ptr;
1557 	return 0;
1558 }
1559 
1560 static int
nxpwifi_cmd_sta_mef_cfg(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)1561 nxpwifi_cmd_sta_mef_cfg(struct nxpwifi_private *priv,
1562 			struct host_cmd_ds_command *cmd,
1563 			u16 cmd_no, void *data_buf,
1564 			u16 cmd_action, u32 cmd_type)
1565 {
1566 	struct host_cmd_ds_mef_cfg *mef_cfg = &cmd->params.mef_cfg;
1567 	struct nxpwifi_ds_mef_cfg *mef =
1568 		(struct nxpwifi_ds_mef_cfg *)data_buf;
1569 	struct nxpwifi_fw_mef_entry *mef_entry = NULL;
1570 	u8 *pos = (u8 *)mef_cfg;
1571 	u16 i;
1572 	int ret = 0;
1573 
1574 	cmd->command = cpu_to_le16(HOST_CMD_MEF_CFG);
1575 
1576 	mef_cfg->criteria = cpu_to_le32(mef->criteria);
1577 	mef_cfg->num_entries = cpu_to_le16(mef->num_entries);
1578 	pos += sizeof(*mef_cfg);
1579 
1580 	for (i = 0; i < mef->num_entries; i++) {
1581 		mef_entry = (struct nxpwifi_fw_mef_entry *)pos;
1582 		mef_entry->mode = mef->mef_entry[i].mode;
1583 		mef_entry->action = mef->mef_entry[i].action;
1584 		pos += sizeof(*mef_entry);
1585 
1586 		ret = nxpwifi_cmd_append_rpn_expression(priv,
1587 							&mef->mef_entry[i],
1588 							&pos);
1589 		if (ret)
1590 			return ret;
1591 
1592 		mef_entry->exprsize =
1593 			cpu_to_le16(pos - mef_entry->expr);
1594 	}
1595 	cmd->size = cpu_to_le16((u16)(pos - (u8 *)mef_cfg) + S_DS_GEN);
1596 
1597 	return ret;
1598 }
1599 
1600 static int
nxpwifi_cmd_sta_802_11_rssi_info(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)1601 nxpwifi_cmd_sta_802_11_rssi_info(struct nxpwifi_private *priv,
1602 				 struct host_cmd_ds_command *cmd,
1603 				 u16 cmd_no, void *data_buf,
1604 				 u16 cmd_action, u32 cmd_type)
1605 {
1606 	cmd->command = cpu_to_le16(HOST_CMD_RSSI_INFO);
1607 	cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_802_11_rssi_info) +
1608 				S_DS_GEN);
1609 	cmd->params.rssi_info.action = cpu_to_le16(cmd_action);
1610 	cmd->params.rssi_info.ndata = cpu_to_le16(priv->data_avg_factor);
1611 	cmd->params.rssi_info.nbcn = cpu_to_le16(priv->bcn_avg_factor);
1612 
1613 	/* Reset SNR/NF/RSSI values in private structure */
1614 	priv->data_rssi_last = 0;
1615 	priv->data_nf_last = 0;
1616 	priv->data_rssi_avg = 0;
1617 	priv->data_nf_avg = 0;
1618 	priv->bcn_rssi_last = 0;
1619 	priv->bcn_nf_last = 0;
1620 	priv->bcn_rssi_avg = 0;
1621 	priv->bcn_nf_avg = 0;
1622 
1623 	return 0;
1624 }
1625 
1626 static int
nxpwifi_ret_sta_802_11_rssi_info(struct nxpwifi_private * priv,struct host_cmd_ds_command * resp,u16 cmdresp_no,void * data_buf)1627 nxpwifi_ret_sta_802_11_rssi_info(struct nxpwifi_private *priv,
1628 				 struct host_cmd_ds_command *resp,
1629 				 u16 cmdresp_no,
1630 				 void *data_buf)
1631 {
1632 	struct host_cmd_ds_802_11_rssi_info_rsp *rssi_info_rsp =
1633 		&resp->params.rssi_info_rsp;
1634 	struct nxpwifi_ds_misc_subsc_evt *subsc_evt =
1635 		&priv->async_subsc_evt_storage;
1636 
1637 	priv->data_rssi_last = le16_to_cpu(rssi_info_rsp->data_rssi_last);
1638 	priv->data_nf_last = le16_to_cpu(rssi_info_rsp->data_nf_last);
1639 
1640 	priv->data_rssi_avg = le16_to_cpu(rssi_info_rsp->data_rssi_avg);
1641 	priv->data_nf_avg = le16_to_cpu(rssi_info_rsp->data_nf_avg);
1642 
1643 	priv->bcn_rssi_last = le16_to_cpu(rssi_info_rsp->bcn_rssi_last);
1644 	priv->bcn_nf_last = le16_to_cpu(rssi_info_rsp->bcn_nf_last);
1645 
1646 	priv->bcn_rssi_avg = le16_to_cpu(rssi_info_rsp->bcn_rssi_avg);
1647 	priv->bcn_nf_avg = le16_to_cpu(rssi_info_rsp->bcn_nf_avg);
1648 
1649 	if (priv->subsc_evt_rssi_state == EVENT_HANDLED)
1650 		return 0;
1651 
1652 	memset(subsc_evt, 0x00, sizeof(struct nxpwifi_ds_misc_subsc_evt));
1653 
1654 	/* Resubscribe low and high rssi events with new thresholds */
1655 	subsc_evt->events = BITMASK_BCN_RSSI_LOW | BITMASK_BCN_RSSI_HIGH;
1656 	subsc_evt->action = HOST_ACT_BITWISE_SET;
1657 	if (priv->subsc_evt_rssi_state == RSSI_LOW_RECVD) {
1658 		subsc_evt->bcn_l_rssi_cfg.abs_value = abs(priv->bcn_rssi_avg -
1659 				priv->cqm_rssi_hyst);
1660 		subsc_evt->bcn_h_rssi_cfg.abs_value = abs(priv->cqm_rssi_thold);
1661 	} else if (priv->subsc_evt_rssi_state == RSSI_HIGH_RECVD) {
1662 		subsc_evt->bcn_l_rssi_cfg.abs_value = abs(priv->cqm_rssi_thold);
1663 		subsc_evt->bcn_h_rssi_cfg.abs_value = abs(priv->bcn_rssi_avg +
1664 				priv->cqm_rssi_hyst);
1665 	}
1666 	subsc_evt->bcn_l_rssi_cfg.evt_freq = 1;
1667 	subsc_evt->bcn_h_rssi_cfg.evt_freq = 1;
1668 
1669 	priv->subsc_evt_rssi_state = EVENT_HANDLED;
1670 
1671 	nxpwifi_send_cmd(priv, HOST_CMD_802_11_SUBSCRIBE_EVENT,
1672 			 0, 0, subsc_evt, false);
1673 
1674 	return 0;
1675 }
1676 
1677 static int
nxpwifi_cmd_sta_func_init(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)1678 nxpwifi_cmd_sta_func_init(struct nxpwifi_private *priv,
1679 			  struct host_cmd_ds_command *cmd,
1680 			  u16 cmd_no, void *data_buf,
1681 			  u16 cmd_action, u32 cmd_type)
1682 {
1683 	if (priv->adapter->hw_status == NXPWIFI_HW_STATUS_RESET)
1684 		priv->adapter->hw_status = NXPWIFI_HW_STATUS_READY;
1685 	cmd->command = cpu_to_le16(cmd_no);
1686 	cmd->size = cpu_to_le16(S_DS_GEN);
1687 
1688 	return 0;
1689 }
1690 
1691 static int
nxpwifi_cmd_sta_func_shutdown(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)1692 nxpwifi_cmd_sta_func_shutdown(struct nxpwifi_private *priv,
1693 			      struct host_cmd_ds_command *cmd,
1694 			      u16 cmd_no, void *data_buf,
1695 			      u16 cmd_action, u32 cmd_type)
1696 {
1697 	priv->adapter->hw_status = NXPWIFI_HW_STATUS_RESET;
1698 	cmd->command = cpu_to_le16(cmd_no);
1699 	cmd->size = cpu_to_le16(S_DS_GEN);
1700 
1701 	return 0;
1702 }
1703 
1704 static int
nxpwifi_cmd_sta_11n_cfg(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)1705 nxpwifi_cmd_sta_11n_cfg(struct nxpwifi_private *priv,
1706 			struct host_cmd_ds_command *cmd,
1707 			u16 cmd_no, void *data_buf,
1708 			u16 cmd_action, u32 cmd_type)
1709 {
1710 	return nxpwifi_cmd_11n_cfg(priv, cmd, cmd_action, data_buf);
1711 }
1712 
1713 static int
nxpwifi_cmd_sta_11n_addba_req(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)1714 nxpwifi_cmd_sta_11n_addba_req(struct nxpwifi_private *priv,
1715 			      struct host_cmd_ds_command *cmd,
1716 			      u16 cmd_no, void *data_buf,
1717 			      u16 cmd_action, u32 cmd_type)
1718 {
1719 	return nxpwifi_cmd_11n_addba_req(cmd, data_buf);
1720 }
1721 
1722 static int
nxpwifi_ret_sta_11n_addba_req(struct nxpwifi_private * priv,struct host_cmd_ds_command * resp,u16 cmdresp_no,void * data_buf)1723 nxpwifi_ret_sta_11n_addba_req(struct nxpwifi_private *priv,
1724 			      struct host_cmd_ds_command *resp,
1725 			      u16 cmdresp_no,
1726 			      void *data_buf)
1727 {
1728 	return nxpwifi_ret_11n_addba_req(priv, resp);
1729 }
1730 
1731 static int
nxpwifi_cmd_sta_11n_addba_rsp(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)1732 nxpwifi_cmd_sta_11n_addba_rsp(struct nxpwifi_private *priv,
1733 			      struct host_cmd_ds_command *cmd,
1734 			      u16 cmd_no, void *data_buf,
1735 			      u16 cmd_action, u32 cmd_type)
1736 {
1737 	return nxpwifi_cmd_11n_addba_rsp_gen(priv, cmd, data_buf);
1738 }
1739 
1740 static int
nxpwifi_ret_sta_11n_addba_rsp(struct nxpwifi_private * priv,struct host_cmd_ds_command * resp,u16 cmdresp_no,void * data_buf)1741 nxpwifi_ret_sta_11n_addba_rsp(struct nxpwifi_private *priv,
1742 			      struct host_cmd_ds_command *resp,
1743 			      u16 cmdresp_no,
1744 			      void *data_buf)
1745 {
1746 	return nxpwifi_ret_11n_addba_resp(priv, resp);
1747 }
1748 
1749 static int
nxpwifi_cmd_sta_11n_delba(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)1750 nxpwifi_cmd_sta_11n_delba(struct nxpwifi_private *priv,
1751 			  struct host_cmd_ds_command *cmd,
1752 			  u16 cmd_no, void *data_buf,
1753 			  u16 cmd_action, u32 cmd_type)
1754 {
1755 	return nxpwifi_cmd_11n_delba(cmd, data_buf);
1756 }
1757 
1758 static int
nxpwifi_ret_sta_11n_delba(struct nxpwifi_private * priv,struct host_cmd_ds_command * resp,u16 cmdresp_no,void * data_buf)1759 nxpwifi_ret_sta_11n_delba(struct nxpwifi_private *priv,
1760 			  struct host_cmd_ds_command *resp,
1761 			  u16 cmdresp_no,
1762 			  void *data_buf)
1763 {
1764 	return nxpwifi_ret_11n_delba(priv, resp);
1765 }
1766 
1767 static int
nxpwifi_cmd_sta_tx_power_cfg(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)1768 nxpwifi_cmd_sta_tx_power_cfg(struct nxpwifi_private *priv,
1769 			     struct host_cmd_ds_command *cmd,
1770 			     u16 cmd_no, void *data_buf,
1771 			     u16 cmd_action, u32 cmd_type)
1772 {
1773 	struct nxpwifi_types_power_group *pg_tlv;
1774 	struct host_cmd_ds_txpwr_cfg *cmd_txp_cfg = &cmd->params.txp_cfg;
1775 	struct host_cmd_ds_txpwr_cfg *txp =
1776 		(struct host_cmd_ds_txpwr_cfg *)data_buf;
1777 
1778 	cmd->command = cpu_to_le16(HOST_CMD_TXPWR_CFG);
1779 	cmd->size =
1780 		cpu_to_le16(S_DS_GEN + sizeof(struct host_cmd_ds_txpwr_cfg));
1781 	switch (cmd_action) {
1782 	case HOST_ACT_GEN_SET:
1783 		if (txp->mode) {
1784 			pg_tlv = (struct nxpwifi_types_power_group
1785 				  *)((unsigned long)txp +
1786 				     sizeof(struct host_cmd_ds_txpwr_cfg));
1787 			memmove(cmd_txp_cfg, txp,
1788 				sizeof(struct host_cmd_ds_txpwr_cfg) +
1789 				sizeof(struct nxpwifi_types_power_group) +
1790 				le16_to_cpu(pg_tlv->length));
1791 
1792 			pg_tlv = (struct nxpwifi_types_power_group *)((u8 *)
1793 				  cmd_txp_cfg +
1794 				  sizeof(struct host_cmd_ds_txpwr_cfg));
1795 			cmd->size = cpu_to_le16(le16_to_cpu(cmd->size) +
1796 				  sizeof(struct nxpwifi_types_power_group) +
1797 				  le16_to_cpu(pg_tlv->length));
1798 		} else {
1799 			memmove(cmd_txp_cfg, txp, sizeof(*txp));
1800 		}
1801 		cmd_txp_cfg->action = cpu_to_le16(cmd_action);
1802 		break;
1803 	case HOST_ACT_GEN_GET:
1804 		cmd_txp_cfg->action = cpu_to_le16(cmd_action);
1805 		break;
1806 	}
1807 
1808 	return 0;
1809 }
1810 
nxpwifi_get_power_level(struct nxpwifi_private * priv,void * data_buf)1811 static int nxpwifi_get_power_level(struct nxpwifi_private *priv, void *data_buf)
1812 {
1813 	int length, max_power = -1, min_power = -1;
1814 	struct nxpwifi_types_power_group *pg_tlv_hdr;
1815 	struct nxpwifi_power_group *pg;
1816 
1817 	if (!data_buf)
1818 		return -ENOMEM;
1819 
1820 	pg_tlv_hdr = (struct nxpwifi_types_power_group *)((u8 *)data_buf);
1821 	pg = (struct nxpwifi_power_group *)
1822 		((u8 *)pg_tlv_hdr + sizeof(struct nxpwifi_types_power_group));
1823 	length = le16_to_cpu(pg_tlv_hdr->length);
1824 
1825 	/* At least one structure required to update power */
1826 	if (length < sizeof(struct nxpwifi_power_group))
1827 		return 0;
1828 
1829 	max_power = pg->power_max;
1830 	min_power = pg->power_min;
1831 	length -= sizeof(struct nxpwifi_power_group);
1832 
1833 	while (length >= sizeof(struct nxpwifi_power_group)) {
1834 		pg++;
1835 		if (max_power < pg->power_max)
1836 			max_power = pg->power_max;
1837 
1838 		if (min_power > pg->power_min)
1839 			min_power = pg->power_min;
1840 
1841 		length -= sizeof(struct nxpwifi_power_group);
1842 	}
1843 	priv->min_tx_power_level = (u8)min_power;
1844 	priv->max_tx_power_level = (u8)max_power;
1845 
1846 	return 0;
1847 }
1848 
1849 static int
nxpwifi_ret_sta_tx_power_cfg(struct nxpwifi_private * priv,struct host_cmd_ds_command * resp,u16 cmdresp_no,void * data_buf)1850 nxpwifi_ret_sta_tx_power_cfg(struct nxpwifi_private *priv,
1851 			     struct host_cmd_ds_command *resp,
1852 			     u16 cmdresp_no,
1853 			     void *data_buf)
1854 {
1855 	struct nxpwifi_adapter *adapter = priv->adapter;
1856 	struct host_cmd_ds_txpwr_cfg *txp_cfg = &resp->params.txp_cfg;
1857 	struct nxpwifi_types_power_group *pg_tlv_hdr;
1858 	struct nxpwifi_power_group *pg;
1859 	u16 action = le16_to_cpu(txp_cfg->action);
1860 	u16 tlv_buf_left;
1861 
1862 	pg_tlv_hdr = (struct nxpwifi_types_power_group *)
1863 		((u8 *)txp_cfg +
1864 		 sizeof(struct host_cmd_ds_txpwr_cfg));
1865 
1866 	pg = (struct nxpwifi_power_group *)
1867 		((u8 *)pg_tlv_hdr +
1868 		 sizeof(struct nxpwifi_types_power_group));
1869 
1870 	tlv_buf_left = le16_to_cpu(resp->size) - S_DS_GEN - sizeof(*txp_cfg);
1871 	if (tlv_buf_left <
1872 			le16_to_cpu(pg_tlv_hdr->length) + sizeof(*pg_tlv_hdr))
1873 		return 0;
1874 
1875 	switch (action) {
1876 	case HOST_ACT_GEN_GET:
1877 		if (adapter->hw_status == NXPWIFI_HW_STATUS_INITIALIZING)
1878 			nxpwifi_get_power_level(priv, pg_tlv_hdr);
1879 
1880 		priv->tx_power_level = (u16)pg->power_min;
1881 		break;
1882 
1883 	case HOST_ACT_GEN_SET:
1884 		if (!le32_to_cpu(txp_cfg->mode))
1885 			break;
1886 
1887 		if (pg->power_max == pg->power_min)
1888 			priv->tx_power_level = (u16)pg->power_min;
1889 		break;
1890 	default:
1891 		nxpwifi_dbg(adapter, ERROR,
1892 			    "CMD_RESP: unknown cmd action %d\n",
1893 			    action);
1894 		return 0;
1895 	}
1896 	nxpwifi_dbg(adapter, INFO,
1897 		    "info: Current TxPower Level = %d, Max Power=%d, Min Power=%d\n",
1898 		    priv->tx_power_level, priv->max_tx_power_level,
1899 		    priv->min_tx_power_level);
1900 
1901 	return 0;
1902 }
1903 
1904 static int
nxpwifi_cmd_sta_tx_rate_cfg(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)1905 nxpwifi_cmd_sta_tx_rate_cfg(struct nxpwifi_private *priv,
1906 			    struct host_cmd_ds_command *cmd,
1907 			    u16 cmd_no, void *data_buf,
1908 			    u16 cmd_action, u32 cmd_type)
1909 {
1910 	struct host_cmd_ds_tx_rate_cfg *rate_cfg = &cmd->params.tx_rate_cfg;
1911 	u16 *pbitmap_rates = (u16 *)data_buf;
1912 	struct nxpwifi_rate_scope *rate_scope;
1913 	struct nxpwifi_rate_drop_pattern *rate_drop;
1914 	u32 i;
1915 
1916 	cmd->command = cpu_to_le16(HOST_CMD_TX_RATE_CFG);
1917 
1918 	rate_cfg->action = cpu_to_le16(cmd_action);
1919 	rate_cfg->cfg_index = 0;
1920 
1921 	rate_scope = (struct nxpwifi_rate_scope *)((u8 *)rate_cfg +
1922 		      sizeof(struct host_cmd_ds_tx_rate_cfg));
1923 	rate_scope->type = cpu_to_le16(TLV_TYPE_RATE_SCOPE);
1924 	rate_scope->length = cpu_to_le16
1925 		(sizeof(*rate_scope) - sizeof(struct nxpwifi_ie_types_header));
1926 	if (pbitmap_rates) {
1927 		rate_scope->hr_dsss_rate_bitmap = cpu_to_le16(pbitmap_rates[0]);
1928 		rate_scope->ofdm_rate_bitmap = cpu_to_le16(pbitmap_rates[1]);
1929 		for (i = 0; i < ARRAY_SIZE(rate_scope->ht_mcs_rate_bitmap); i++)
1930 			rate_scope->ht_mcs_rate_bitmap[i] =
1931 				cpu_to_le16(pbitmap_rates[2 + i]);
1932 		if (priv->adapter->fw_api_ver == NXPWIFI_FW_V15) {
1933 			for (i = 0;
1934 			     i < ARRAY_SIZE(rate_scope->vht_mcs_rate_bitmap);
1935 			     i++)
1936 				rate_scope->vht_mcs_rate_bitmap[i] =
1937 					cpu_to_le16(pbitmap_rates[10 + i]);
1938 		}
1939 	} else {
1940 		rate_scope->hr_dsss_rate_bitmap =
1941 			cpu_to_le16(priv->bitmap_rates[0]);
1942 		rate_scope->ofdm_rate_bitmap =
1943 			cpu_to_le16(priv->bitmap_rates[1]);
1944 		for (i = 0; i < ARRAY_SIZE(rate_scope->ht_mcs_rate_bitmap); i++)
1945 			rate_scope->ht_mcs_rate_bitmap[i] =
1946 				cpu_to_le16(priv->bitmap_rates[2 + i]);
1947 		if (priv->adapter->fw_api_ver == NXPWIFI_FW_V15) {
1948 			for (i = 0;
1949 			     i < ARRAY_SIZE(rate_scope->vht_mcs_rate_bitmap);
1950 			     i++)
1951 				rate_scope->vht_mcs_rate_bitmap[i] =
1952 					cpu_to_le16(priv->bitmap_rates[10 + i]);
1953 		}
1954 	}
1955 
1956 	rate_drop = (struct nxpwifi_rate_drop_pattern *)((u8 *)rate_scope +
1957 					     sizeof(struct nxpwifi_rate_scope));
1958 	rate_drop->type = cpu_to_le16(TLV_TYPE_RATE_DROP_CONTROL);
1959 	rate_drop->length = cpu_to_le16(sizeof(rate_drop->rate_drop_mode));
1960 	rate_drop->rate_drop_mode = 0;
1961 
1962 	cmd->size =
1963 		cpu_to_le16(S_DS_GEN + sizeof(struct host_cmd_ds_tx_rate_cfg) +
1964 			    sizeof(struct nxpwifi_rate_scope) +
1965 			    sizeof(struct nxpwifi_rate_drop_pattern));
1966 
1967 	return 0;
1968 }
1969 
nxpwifi_ret_rate_scope(struct nxpwifi_private * priv,u8 * tlv_buf)1970 static void nxpwifi_ret_rate_scope(struct nxpwifi_private *priv, u8 *tlv_buf)
1971 {
1972 	struct nxpwifi_rate_scope *rate_scope;
1973 	int i;
1974 
1975 	rate_scope = (struct nxpwifi_rate_scope *)tlv_buf;
1976 	priv->bitmap_rates[0] =
1977 		le16_to_cpu(rate_scope->hr_dsss_rate_bitmap);
1978 	priv->bitmap_rates[1] =
1979 		le16_to_cpu(rate_scope->ofdm_rate_bitmap);
1980 	for (i = 0; i < ARRAY_SIZE(rate_scope->ht_mcs_rate_bitmap); i++)
1981 		priv->bitmap_rates[2 + i] =
1982 			le16_to_cpu(rate_scope->ht_mcs_rate_bitmap[i]);
1983 
1984 	if (priv->adapter->fw_api_ver == NXPWIFI_FW_V15) {
1985 		for (i = 0; i < ARRAY_SIZE(rate_scope->vht_mcs_rate_bitmap);
1986 		     i++)
1987 			priv->bitmap_rates[10 + i] =
1988 				le16_to_cpu(rate_scope->vht_mcs_rate_bitmap[i]);
1989 	}
1990 }
1991 
1992 static int
nxpwifi_ret_sta_tx_rate_cfg(struct nxpwifi_private * priv,struct host_cmd_ds_command * resp,u16 cmdresp_no,void * data_buf)1993 nxpwifi_ret_sta_tx_rate_cfg(struct nxpwifi_private *priv,
1994 			    struct host_cmd_ds_command *resp,
1995 			    u16 cmdresp_no,
1996 			    void *data_buf)
1997 {
1998 	struct host_cmd_ds_tx_rate_cfg *rate_cfg = &resp->params.tx_rate_cfg;
1999 	struct nxpwifi_ie_types_header *head;
2000 	u16 tlv, tlv_buf_len, tlv_buf_left;
2001 	u8 *tlv_buf;
2002 
2003 	tlv_buf = ((u8 *)rate_cfg) + sizeof(struct host_cmd_ds_tx_rate_cfg);
2004 	tlv_buf_left = le16_to_cpu(resp->size) - S_DS_GEN - sizeof(*rate_cfg);
2005 
2006 	while (tlv_buf_left >= sizeof(*head)) {
2007 		head = (struct nxpwifi_ie_types_header *)tlv_buf;
2008 		tlv = le16_to_cpu(head->type);
2009 		tlv_buf_len = le16_to_cpu(head->len);
2010 
2011 		if (tlv_buf_left < (sizeof(*head) + tlv_buf_len))
2012 			break;
2013 
2014 		switch (tlv) {
2015 		case TLV_TYPE_RATE_SCOPE:
2016 			nxpwifi_ret_rate_scope(priv, tlv_buf);
2017 			break;
2018 			/* Add RATE_DROP tlv here */
2019 		}
2020 
2021 		tlv_buf += (sizeof(*head) + tlv_buf_len);
2022 		tlv_buf_left -= (sizeof(*head) + tlv_buf_len);
2023 	}
2024 
2025 	priv->is_data_rate_auto = nxpwifi_is_rate_auto(priv);
2026 
2027 	if (priv->is_data_rate_auto)
2028 		priv->data_rate = 0;
2029 	else
2030 		return nxpwifi_send_cmd(priv, HOST_CMD_802_11_TX_RATE_QUERY,
2031 					HOST_ACT_GEN_GET, 0, NULL, false);
2032 
2033 	return 0;
2034 }
2035 
2036 static int
nxpwifi_cmd_sta_reconfigure_rx_buff(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)2037 nxpwifi_cmd_sta_reconfigure_rx_buff(struct nxpwifi_private *priv,
2038 				    struct host_cmd_ds_command *cmd,
2039 				    u16 cmd_no, void *data_buf,
2040 				    u16 cmd_action, u32 cmd_type)
2041 {
2042 	return nxpwifi_cmd_recfg_tx_buf(priv, cmd, cmd_action, data_buf);
2043 }
2044 
2045 static int
nxpwifi_ret_sta_reconfigure_rx_buff(struct nxpwifi_private * priv,struct host_cmd_ds_command * resp,u16 cmdresp_no,void * data_buf)2046 nxpwifi_ret_sta_reconfigure_rx_buff(struct nxpwifi_private *priv,
2047 				    struct host_cmd_ds_command *resp,
2048 				    u16 cmdresp_no,
2049 				    void *data_buf)
2050 {
2051 	struct nxpwifi_adapter *adapter = priv->adapter;
2052 
2053 	if (0xffff != (u16)le16_to_cpu(resp->params.tx_buf.buff_size)) {
2054 		adapter->tx_buf_size =
2055 			(u16)le16_to_cpu(resp->params.tx_buf.buff_size);
2056 		adapter->tx_buf_size =
2057 			(adapter->tx_buf_size / NXPWIFI_SDIO_BLOCK_SIZE) *
2058 			NXPWIFI_SDIO_BLOCK_SIZE;
2059 		adapter->curr_tx_buf_size = adapter->tx_buf_size;
2060 		nxpwifi_dbg(adapter, CMD, "cmd: curr_tx_buf_size=%d\n",
2061 			    adapter->curr_tx_buf_size);
2062 
2063 		if (adapter->if_ops.update_mp_end_port) {
2064 			u16 mp_end_port;
2065 
2066 			mp_end_port =
2067 				le16_to_cpu(resp->params.tx_buf.mp_end_port);
2068 			adapter->if_ops.update_mp_end_port(adapter,
2069 							   mp_end_port);
2070 		}
2071 	}
2072 
2073 	return 0;
2074 }
2075 
2076 static int
nxpwifi_cmd_sta_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)2077 nxpwifi_cmd_sta_chan_report_request(struct nxpwifi_private *priv,
2078 				    struct host_cmd_ds_command *cmd,
2079 				    u16 cmd_no, void *data_buf,
2080 				    u16 cmd_action, u32 cmd_type)
2081 {
2082 	return nxpwifi_cmd_issue_chan_report_request(priv, cmd, data_buf);
2083 }
2084 
2085 static int
nxpwifi_cmd_sta_amsdu_aggr_ctrl(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)2086 nxpwifi_cmd_sta_amsdu_aggr_ctrl(struct nxpwifi_private *priv,
2087 				struct host_cmd_ds_command *cmd,
2088 				u16 cmd_no, void *data_buf,
2089 				u16 cmd_action, u32 cmd_type)
2090 {
2091 	return nxpwifi_cmd_amsdu_aggr_ctrl(cmd, cmd_action, data_buf);
2092 }
2093 
2094 static int
nxpwifi_cmd_sta_robust_coex(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)2095 nxpwifi_cmd_sta_robust_coex(struct nxpwifi_private *priv,
2096 			    struct host_cmd_ds_command *cmd,
2097 			    u16 cmd_no, void *data_buf,
2098 			    u16 cmd_action, u32 cmd_type)
2099 {
2100 	struct host_cmd_ds_robust_coex *coex = &cmd->params.coex;
2101 	bool *is_timeshare = (bool *)data_buf;
2102 	struct nxpwifi_ie_types_robust_coex *coex_tlv;
2103 
2104 	cmd->command = cpu_to_le16(HOST_CMD_ROBUST_COEX);
2105 	cmd->size = cpu_to_le16(sizeof(*coex) + sizeof(*coex_tlv) + S_DS_GEN);
2106 
2107 	coex->action = cpu_to_le16(cmd_action);
2108 	coex_tlv = (struct nxpwifi_ie_types_robust_coex *)
2109 				((u8 *)coex + sizeof(*coex));
2110 	coex_tlv->header.type = cpu_to_le16(TLV_TYPE_ROBUST_COEX);
2111 	coex_tlv->header.len = cpu_to_le16(sizeof(coex_tlv->mode));
2112 
2113 	if (coex->action == HOST_ACT_GEN_GET)
2114 		return 0;
2115 
2116 	if (*is_timeshare)
2117 		coex_tlv->mode = cpu_to_le32(NXPWIFI_COEX_MODE_TIMESHARE);
2118 	else
2119 		coex_tlv->mode = cpu_to_le32(NXPWIFI_COEX_MODE_SPATIAL);
2120 
2121 	return 0;
2122 }
2123 
2124 static int
nxpwifi_ret_sta_robust_coex(struct nxpwifi_private * priv,struct host_cmd_ds_command * resp,u16 cmdresp_no,void * data_buf)2125 nxpwifi_ret_sta_robust_coex(struct nxpwifi_private *priv,
2126 			    struct host_cmd_ds_command *resp,
2127 			    u16 cmdresp_no,
2128 			    void *data_buf)
2129 {
2130 	struct host_cmd_ds_robust_coex *coex = &resp->params.coex;
2131 	bool *is_timeshare = (bool *)data_buf;
2132 	struct nxpwifi_ie_types_robust_coex *coex_tlv;
2133 	u16 action = le16_to_cpu(coex->action);
2134 	u32 mode;
2135 
2136 	if (!is_timeshare)
2137 		return 0;
2138 
2139 	coex_tlv = (struct nxpwifi_ie_types_robust_coex
2140 		    *)((u8 *)coex + sizeof(struct host_cmd_ds_robust_coex));
2141 	if (action == HOST_ACT_GEN_GET) {
2142 		mode = le32_to_cpu(coex_tlv->mode);
2143 		if (mode == NXPWIFI_COEX_MODE_TIMESHARE)
2144 			*is_timeshare = true;
2145 		else
2146 			*is_timeshare = false;
2147 	}
2148 
2149 	return 0;
2150 }
2151 
2152 static int
nxpwifi_cmd_sta_enh_power_mode(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)2153 nxpwifi_cmd_sta_enh_power_mode(struct nxpwifi_private *priv,
2154 			       struct host_cmd_ds_command *cmd,
2155 			       u16 cmd_no, void *data_buf,
2156 			       u16 cmd_action, u32 cmd_type)
2157 {
2158 	struct host_cmd_ds_802_11_ps_mode_enh *psmode_enh =
2159 		&cmd->params.psmode_enh;
2160 	u16 ps_bitmap = (u16)cmd_type;
2161 	struct nxpwifi_ds_auto_ds *auto_ds =
2162 		(struct nxpwifi_ds_auto_ds *)data_buf;
2163 	u8 *tlv;
2164 	u16 cmd_size = 0;
2165 
2166 	cmd->command = cpu_to_le16(HOST_CMD_802_11_PS_MODE_ENH);
2167 	if (cmd_action == DIS_AUTO_PS) {
2168 		psmode_enh->action = cpu_to_le16(DIS_AUTO_PS);
2169 		psmode_enh->params.ps_bitmap = cpu_to_le16(ps_bitmap);
2170 		cmd->size = cpu_to_le16(S_DS_GEN + sizeof(psmode_enh->action) +
2171 					sizeof(psmode_enh->params.ps_bitmap));
2172 	} else if (cmd_action == GET_PS) {
2173 		psmode_enh->action = cpu_to_le16(GET_PS);
2174 		psmode_enh->params.ps_bitmap = cpu_to_le16(ps_bitmap);
2175 		cmd->size = cpu_to_le16(S_DS_GEN + sizeof(psmode_enh->action) +
2176 					sizeof(psmode_enh->params.ps_bitmap));
2177 	} else if (cmd_action == EN_AUTO_PS) {
2178 		psmode_enh->action = cpu_to_le16(EN_AUTO_PS);
2179 		psmode_enh->params.ps_bitmap = cpu_to_le16(ps_bitmap);
2180 		cmd_size = S_DS_GEN + sizeof(psmode_enh->action) +
2181 					sizeof(psmode_enh->params.ps_bitmap);
2182 		tlv = (u8 *)cmd + cmd_size;
2183 		if (ps_bitmap & BITMAP_STA_PS) {
2184 			struct nxpwifi_adapter *adapter = priv->adapter;
2185 			struct nxpwifi_ie_types_ps_param *ps_tlv =
2186 				(struct nxpwifi_ie_types_ps_param *)tlv;
2187 			struct nxpwifi_ps_param *ps_mode = &ps_tlv->param;
2188 
2189 			ps_tlv->header.type = cpu_to_le16(TLV_TYPE_PS_PARAM);
2190 			ps_tlv->header.len = cpu_to_le16(sizeof(*ps_tlv) -
2191 					sizeof(struct nxpwifi_ie_types_header));
2192 			cmd_size += sizeof(*ps_tlv);
2193 			tlv += sizeof(*ps_tlv);
2194 			nxpwifi_dbg(priv->adapter, CMD,
2195 				    "cmd: PS Command: Enter PS\n");
2196 			ps_mode->null_pkt_interval =
2197 					cpu_to_le16(adapter->null_pkt_interval);
2198 			ps_mode->multiple_dtims =
2199 					cpu_to_le16(adapter->multiple_dtim);
2200 			ps_mode->bcn_miss_timeout =
2201 					cpu_to_le16(adapter->bcn_miss_time_out);
2202 			ps_mode->local_listen_interval =
2203 				cpu_to_le16(adapter->local_listen_interval);
2204 			ps_mode->delay_to_ps =
2205 					cpu_to_le16(adapter->delay_to_ps);
2206 			ps_mode->mode = cpu_to_le16(adapter->enhanced_ps_mode);
2207 		}
2208 		if (ps_bitmap & BITMAP_AUTO_DS) {
2209 			struct nxpwifi_ie_types_auto_ds_param *auto_ds_tlv =
2210 				(struct nxpwifi_ie_types_auto_ds_param *)tlv;
2211 			u16 idletime = 0;
2212 
2213 			auto_ds_tlv->header.type =
2214 				cpu_to_le16(TLV_TYPE_AUTO_DS_PARAM);
2215 			auto_ds_tlv->header.len =
2216 				cpu_to_le16(sizeof(*auto_ds_tlv) -
2217 					sizeof(struct nxpwifi_ie_types_header));
2218 			cmd_size += sizeof(*auto_ds_tlv);
2219 			tlv += sizeof(*auto_ds_tlv);
2220 			if (auto_ds)
2221 				idletime = auto_ds->idle_time;
2222 			nxpwifi_dbg(priv->adapter, CMD,
2223 				    "cmd: PS Command: Enter Auto Deep Sleep\n");
2224 			auto_ds_tlv->deep_sleep_timeout = cpu_to_le16(idletime);
2225 		}
2226 		cmd->size = cpu_to_le16(cmd_size);
2227 	}
2228 	return 0;
2229 }
2230 
2231 static int
nxpwifi_ret_sta_enh_power_mode(struct nxpwifi_private * priv,struct host_cmd_ds_command * resp,u16 cmdresp_no,void * data_buf)2232 nxpwifi_ret_sta_enh_power_mode(struct nxpwifi_private *priv,
2233 			       struct host_cmd_ds_command *resp,
2234 			       u16 cmdresp_no,
2235 			       void *data_buf)
2236 {
2237 	struct nxpwifi_adapter *adapter = priv->adapter;
2238 	struct host_cmd_ds_802_11_ps_mode_enh *ps_mode =
2239 		&resp->params.psmode_enh;
2240 	struct nxpwifi_ds_pm_cfg *pm_cfg =
2241 		(struct nxpwifi_ds_pm_cfg *)data_buf;
2242 	u16 action = le16_to_cpu(ps_mode->action);
2243 	u16 ps_bitmap = le16_to_cpu(ps_mode->params.ps_bitmap);
2244 	u16 auto_ps_bitmap =
2245 		le16_to_cpu(ps_mode->params.ps_bitmap);
2246 
2247 	nxpwifi_dbg(adapter, INFO,
2248 		    "info: %s: PS_MODE cmd reply result=%#x action=%#X\n",
2249 		    __func__, resp->result, action);
2250 	if (action == EN_AUTO_PS) {
2251 		if (auto_ps_bitmap & BITMAP_AUTO_DS) {
2252 			nxpwifi_dbg(adapter, CMD,
2253 				    "cmd: Enabled auto deep sleep\n");
2254 			priv->adapter->is_deep_sleep = true;
2255 		}
2256 		if (auto_ps_bitmap & BITMAP_STA_PS) {
2257 			nxpwifi_dbg(adapter, CMD,
2258 				    "cmd: Enabled STA power save\n");
2259 			if (adapter->sleep_period.period)
2260 				nxpwifi_dbg(adapter, CMD,
2261 					    "cmd: set to uapsd/pps mode\n");
2262 		}
2263 	} else if (action == DIS_AUTO_PS) {
2264 		if (ps_bitmap & BITMAP_AUTO_DS) {
2265 			priv->adapter->is_deep_sleep = false;
2266 			nxpwifi_dbg(adapter, CMD,
2267 				    "cmd: Disabled auto deep sleep\n");
2268 		}
2269 		if (ps_bitmap & BITMAP_STA_PS) {
2270 			nxpwifi_dbg(adapter, CMD,
2271 				    "cmd: Disabled STA power save\n");
2272 			if (adapter->sleep_period.period) {
2273 				adapter->delay_null_pkt = false;
2274 				adapter->tx_lock_flag = false;
2275 				adapter->pps_uapsd_mode = false;
2276 			}
2277 		}
2278 	} else if (action == GET_PS) {
2279 		if (ps_bitmap & BITMAP_STA_PS)
2280 			adapter->ps_mode = NXPWIFI_802_11_POWER_MODE_PSP;
2281 		else
2282 			adapter->ps_mode = NXPWIFI_802_11_POWER_MODE_CAM;
2283 
2284 		nxpwifi_dbg(adapter, CMD,
2285 			    "cmd: ps_bitmap=%#x\n", ps_bitmap);
2286 
2287 		if (pm_cfg) {
2288 			/* This section is for get power save mode */
2289 			if (ps_bitmap & BITMAP_STA_PS)
2290 				pm_cfg->param.ps_mode = 1;
2291 			else
2292 				pm_cfg->param.ps_mode = 0;
2293 		}
2294 	}
2295 	return 0;
2296 }
2297 
2298 static int
nxpwifi_cmd_sta_802_11_hs_cfg(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)2299 nxpwifi_cmd_sta_802_11_hs_cfg(struct nxpwifi_private *priv,
2300 			      struct host_cmd_ds_command *cmd,
2301 			      u16 cmd_no, void *data_buf,
2302 			      u16 cmd_action, u32 cmd_type)
2303 {
2304 	struct nxpwifi_adapter *adapter = priv->adapter;
2305 	struct host_cmd_ds_802_11_hs_cfg_enh *hs_cfg = &cmd->params.opt_hs_cfg;
2306 	struct nxpwifi_hs_config_param *hscfg_param =
2307 		(struct nxpwifi_hs_config_param *)data_buf;
2308 	u8 *tlv = (u8 *)hs_cfg + sizeof(struct host_cmd_ds_802_11_hs_cfg_enh);
2309 	struct nxpwifi_ps_param_in_hs *psparam_tlv = NULL;
2310 	bool hs_activate = false;
2311 	u16 size;
2312 
2313 	if (!hscfg_param)
2314 		/* New Activate command */
2315 		hs_activate = true;
2316 	cmd->command = cpu_to_le16(HOST_CMD_802_11_HS_CFG_ENH);
2317 
2318 	if (!hs_activate &&
2319 	    hscfg_param->conditions != cpu_to_le32(HS_CFG_CANCEL) &&
2320 	    (adapter->arp_filter_size > 0 &&
2321 	     adapter->arp_filter_size <= ARP_FILTER_MAX_BUF_SIZE)) {
2322 		nxpwifi_dbg(adapter, CMD,
2323 			    "cmd: Attach %d bytes ArpFilter to HSCfg cmd\n",
2324 			    adapter->arp_filter_size);
2325 		memcpy(((u8 *)hs_cfg) +
2326 		       sizeof(struct host_cmd_ds_802_11_hs_cfg_enh),
2327 		       adapter->arp_filter, adapter->arp_filter_size);
2328 		size = adapter->arp_filter_size +
2329 			sizeof(struct host_cmd_ds_802_11_hs_cfg_enh)
2330 			+ S_DS_GEN;
2331 		tlv = (u8 *)hs_cfg
2332 			+ sizeof(struct host_cmd_ds_802_11_hs_cfg_enh)
2333 			+ adapter->arp_filter_size;
2334 	} else {
2335 		size = S_DS_GEN + sizeof(struct host_cmd_ds_802_11_hs_cfg_enh);
2336 	}
2337 	if (hs_activate) {
2338 		hs_cfg->action = cpu_to_le16(HS_ACTIVATE);
2339 		hs_cfg->params.hs_activate.resp_ctrl = cpu_to_le16(RESP_NEEDED);
2340 
2341 		adapter->hs_activated_manually = true;
2342 		nxpwifi_dbg(priv->adapter, CMD,
2343 			    "cmd: Activating host sleep manually\n");
2344 	} else {
2345 		hs_cfg->action = cpu_to_le16(HS_CONFIGURE);
2346 		hs_cfg->params.hs_config.conditions = hscfg_param->conditions;
2347 		hs_cfg->params.hs_config.gpio = hscfg_param->gpio;
2348 		hs_cfg->params.hs_config.gap = hscfg_param->gap;
2349 
2350 		size += sizeof(struct nxpwifi_ps_param_in_hs);
2351 		psparam_tlv = (struct nxpwifi_ps_param_in_hs *)tlv;
2352 		psparam_tlv->header.type =
2353 			cpu_to_le16(TLV_TYPE_PS_PARAMS_IN_HS);
2354 		psparam_tlv->header.len =
2355 			cpu_to_le16(sizeof(struct nxpwifi_ps_param_in_hs)
2356 				- sizeof(struct nxpwifi_ie_types_header));
2357 		psparam_tlv->hs_wake_int = cpu_to_le32(HS_DEF_WAKE_INTERVAL);
2358 		psparam_tlv->hs_inact_timeout =
2359 			cpu_to_le32(HS_DEF_INACTIVITY_TIMEOUT);
2360 
2361 		nxpwifi_dbg(adapter, CMD,
2362 			    "cmd: HS_CFG_CMD: condition:0x%x gpio:0x%x gap:0x%x\n",
2363 			    hs_cfg->params.hs_config.conditions,
2364 			    hs_cfg->params.hs_config.gpio,
2365 			    hs_cfg->params.hs_config.gap);
2366 	}
2367 	cmd->size = cpu_to_le16(size);
2368 
2369 	return 0;
2370 }
2371 
2372 static int
nxpwifi_ret_sta_802_11_hs_cfg(struct nxpwifi_private * priv,struct host_cmd_ds_command * resp,u16 cmdresp_no,void * data_buf)2373 nxpwifi_ret_sta_802_11_hs_cfg(struct nxpwifi_private *priv,
2374 			      struct host_cmd_ds_command *resp,
2375 			      u16 cmdresp_no,
2376 			      void *data_buf)
2377 {
2378 	return nxpwifi_ret_802_11_hs_cfg(priv, resp);
2379 }
2380 
2381 static int
nxpwifi_cmd_sta_set_bss_mode(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)2382 nxpwifi_cmd_sta_set_bss_mode(struct nxpwifi_private *priv,
2383 			     struct host_cmd_ds_command *cmd,
2384 			     u16 cmd_no, void *data_buf,
2385 			     u16 cmd_action, u32 cmd_type)
2386 {
2387 	cmd->command = cpu_to_le16(cmd_no);
2388 	if (priv->bss_mode == NL80211_IFTYPE_STATION)
2389 		cmd->params.bss_mode.con_type = CONNECTION_TYPE_INFRA;
2390 	else if (priv->bss_mode == NL80211_IFTYPE_AP)
2391 		cmd->params.bss_mode.con_type = CONNECTION_TYPE_AP;
2392 	cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_set_bss_mode) +
2393 				S_DS_GEN);
2394 
2395 	return 0;
2396 }
2397 
2398 static int
nxpwifi_cmd_sta_802_11_net_monitor(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)2399 nxpwifi_cmd_sta_802_11_net_monitor(struct nxpwifi_private *priv,
2400 				   struct host_cmd_ds_command *cmd,
2401 				   u16 cmd_no, void *data_buf,
2402 				   u16 cmd_action, u32 cmd_type)
2403 {
2404 	struct nxpwifi_802_11_net_monitor *net_mon;
2405 	struct host_cmd_ds_802_11_net_monitor *cmd_net_mon =
2406 		&cmd->params.net_mon;
2407 	struct chan_band_param *chan_band = NULL;
2408 	u8 sec_chan_offset = 0;
2409 	u32 bw_offset = 0;
2410 
2411 	net_mon = (struct nxpwifi_802_11_net_monitor *)data_buf;
2412 
2413 	cmd->size = cpu_to_le16(S_DS_GEN +
2414 				sizeof(struct host_cmd_ds_802_11_net_monitor) +
2415 				sizeof(struct chan_band_param));
2416 	cmd->command = cpu_to_le16(cmd_no);
2417 	cmd_net_mon->action = cpu_to_le16(cmd_action);
2418 
2419 	if (cmd_action == HOST_ACT_GEN_SET) {
2420 		if (net_mon->enable_net_mon) {
2421 			cmd_net_mon->enable_net_mon = cpu_to_le16(0x1);
2422 			cmd_net_mon->filter_flag = cpu_to_le16((u16)
2423 			net_mon->filter_flag);
2424 		}
2425 
2426 		if (net_mon->enable_net_mon && net_mon->channel) {
2427 			chan_band = &cmd_net_mon->monitor_chan.chan_band_param[0];
2428 			cmd_net_mon->monitor_chan.header.type =
2429 				cpu_to_le16(TLV_TYPE_CHANNELBANDLIST);
2430 			cmd_net_mon->monitor_chan.header.len =
2431 				cpu_to_le16(sizeof(struct chan_band_param));
2432 			chan_band->chan_number = (u8)net_mon->channel;
2433 			chan_band->band_cfg.chan_band =
2434 				nxpwifi_band_to_radio_type((u16)net_mon->band);
2435 
2436 			if (net_mon->band & BAND_GN ||
2437 			    net_mon->band & BAND_AN ||
2438 			    net_mon->band & BAND_GAC ||
2439 			    net_mon->band & BAND_AAC) {
2440 				bw_offset = net_mon->chan_bandwidth;
2441 				if (bw_offset == CHANNEL_BW_40MHZ_ABOVE) {
2442 					chan_band->band_cfg.chan_2O_ffset =
2443 						NXPWIFI_SEC_CHAN_ABOVE;
2444 					chan_band->band_cfg.chan_width =
2445 						CHAN_BW_40MHZ;
2446 				} else if (bw_offset == CHANNEL_BW_40MHZ_BELOW) {
2447 					chan_band->band_cfg.chan_2O_ffset =
2448 						NXPWIFI_SEC_CHAN_BELOW;
2449 					chan_band->band_cfg.chan_width =
2450 						CHAN_BW_40MHZ;
2451 				} else if (bw_offset == CHANNEL_BW_80MHZ) {
2452 					sec_chan_offset =
2453 						nxpwifi_get_sec_chan_offset(net_mon->channel);
2454 					if (sec_chan_offset == NXPWIFI_SEC_CHAN_ABOVE)
2455 						chan_band->band_cfg.chan_2O_ffset =
2456 							NXPWIFI_SEC_CHAN_ABOVE;
2457 					else if (sec_chan_offset == NXPWIFI_SEC_CHAN_BELOW)
2458 						chan_band->band_cfg.chan_2O_ffset =
2459 							NXPWIFI_SEC_CHAN_BELOW;
2460 					chan_band->band_cfg.chan_width = CHAN_BW_80MHZ;
2461 				}
2462 			}
2463 		}
2464 	}
2465 	return 0;
2466 }
2467 
2468 static int
nxpwifi_ret_sta_802_11_net_monitor(struct nxpwifi_private * priv,struct host_cmd_ds_command * resp,u16 cmdresp_no,void * data_buf)2469 nxpwifi_ret_sta_802_11_net_monitor(struct nxpwifi_private *priv,
2470 				   struct host_cmd_ds_command *resp,
2471 				   u16 cmdresp_no,
2472 				   void *data_buf)
2473 {
2474 	struct host_cmd_ds_802_11_net_monitor *cmd_net_mon = &resp->params.net_mon;
2475 
2476 	nxpwifi_dbg(priv->adapter, CMD,
2477 		    "cmd: NET_MONITOR_CMD: action: %d, enable: %d, flag: %d ch: %d band: %d bw: %d offset: %d\n",
2478 		    le16_to_cpu(cmd_net_mon->action),
2479 		    le16_to_cpu(cmd_net_mon->enable_net_mon),
2480 		    le16_to_cpu(cmd_net_mon->filter_flag),
2481 		    cmd_net_mon->monitor_chan.chan_band_param[0].chan_number,
2482 		    cmd_net_mon->monitor_chan.chan_band_param[0].band_cfg.chan_band,
2483 		    cmd_net_mon->monitor_chan.chan_band_param[0].band_cfg.chan_width,
2484 		    cmd_net_mon->monitor_chan.chan_band_param[0].band_cfg.chan_2O_ffset);
2485 	priv->adapter->enable_net_mon = le16_to_cpu(cmd_net_mon->enable_net_mon);
2486 	return 0;
2487 }
2488 
2489 static int
nxpwifi_cmd_sta_802_11_scan_ext(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)2490 nxpwifi_cmd_sta_802_11_scan_ext(struct nxpwifi_private *priv,
2491 				struct host_cmd_ds_command *cmd,
2492 				u16 cmd_no, void *data_buf,
2493 				u16 cmd_action, u32 cmd_type)
2494 {
2495 	return nxpwifi_cmd_802_11_scan_ext(priv, cmd, data_buf);
2496 }
2497 
2498 static int
nxpwifi_ret_sta_802_11_scan_ext(struct nxpwifi_private * priv,struct host_cmd_ds_command * resp,u16 cmdresp_no,void * data_buf)2499 nxpwifi_ret_sta_802_11_scan_ext(struct nxpwifi_private *priv,
2500 				struct host_cmd_ds_command *resp,
2501 				u16 cmdresp_no,
2502 				void *data_buf)
2503 {
2504 	struct nxpwifi_adapter *adapter = priv->adapter;
2505 	int ret;
2506 
2507 	ret = nxpwifi_ret_802_11_scan_ext(priv, resp);
2508 	adapter->curr_cmd->wait_q_enabled = false;
2509 
2510 	return ret;
2511 }
2512 
2513 static int
nxpwifi_cmd_sta_coalesce_cfg(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)2514 nxpwifi_cmd_sta_coalesce_cfg(struct nxpwifi_private *priv,
2515 			     struct host_cmd_ds_command *cmd,
2516 			     u16 cmd_no, void *data_buf,
2517 			     u16 cmd_action, u32 cmd_type)
2518 {
2519 	struct host_cmd_ds_coalesce_cfg *coalesce_cfg =
2520 		&cmd->params.coalesce_cfg;
2521 	struct nxpwifi_ds_coalesce_cfg *cfg =
2522 		(struct nxpwifi_ds_coalesce_cfg *)data_buf;
2523 	struct coalesce_filt_field_param *param;
2524 	u16 cnt, idx, length;
2525 	struct coalesce_receive_filt_rule *rule;
2526 
2527 	cmd->command = cpu_to_le16(HOST_CMD_COALESCE_CFG);
2528 	cmd->size = cpu_to_le16(S_DS_GEN);
2529 
2530 	coalesce_cfg->action = cpu_to_le16(cmd_action);
2531 	coalesce_cfg->num_of_rules = cpu_to_le16(cfg->num_of_rules);
2532 	rule = (void *)coalesce_cfg->rule_data;
2533 
2534 	for (cnt = 0; cnt < cfg->num_of_rules; cnt++) {
2535 		rule->header.type = cpu_to_le16(TLV_TYPE_COALESCE_RULE);
2536 		rule->max_coalescing_delay =
2537 			cpu_to_le16(cfg->rule[cnt].max_coalescing_delay);
2538 		rule->pkt_type = cfg->rule[cnt].pkt_type;
2539 		rule->num_of_fields = cfg->rule[cnt].num_of_fields;
2540 
2541 		length = 0;
2542 
2543 		param = rule->params;
2544 		for (idx = 0; idx < cfg->rule[cnt].num_of_fields; idx++) {
2545 			param->operation = cfg->rule[cnt].params[idx].operation;
2546 			param->operand_len =
2547 					cfg->rule[cnt].params[idx].operand_len;
2548 			param->offset =
2549 				cpu_to_le16(cfg->rule[cnt].params[idx].offset);
2550 			memcpy(param->operand_byte_stream,
2551 			       cfg->rule[cnt].params[idx].operand_byte_stream,
2552 			       param->operand_len);
2553 
2554 			length += sizeof(struct coalesce_filt_field_param);
2555 
2556 			param++;
2557 		}
2558 
2559 		/*
2560 		 * Total rule length is sizeof max_coalescing_delay(u16),
2561 		 * num_of_fields(u8), pkt_type(u8) and total length of the all
2562 		 * params
2563 		 */
2564 		rule->header.len = cpu_to_le16(length + sizeof(u16) +
2565 					       sizeof(u8) + sizeof(u8));
2566 
2567 		/* Add the rule length to the command size */
2568 		le16_unaligned_add_cpu(&cmd->size,
2569 				       le16_to_cpu(rule->header.len) +
2570 				       sizeof(struct nxpwifi_ie_types_header));
2571 
2572 		rule = (void *)((u8 *)rule->params + length);
2573 	}
2574 
2575 	/* Add sizeof action, num_of_rules to total command length */
2576 	le16_unaligned_add_cpu(&cmd->size, sizeof(u16) + sizeof(u16));
2577 
2578 	return 0;
2579 }
2580 
2581 static int
nxpwifi_cmd_sta_mgmt_frame_reg(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)2582 nxpwifi_cmd_sta_mgmt_frame_reg(struct nxpwifi_private *priv,
2583 			       struct host_cmd_ds_command *cmd,
2584 			       u16 cmd_no, void *data_buf,
2585 			       u16 cmd_action, u32 cmd_type)
2586 {
2587 	cmd->command = cpu_to_le16(cmd_no);
2588 	cmd->params.reg_mask.action = cpu_to_le16(cmd_action);
2589 	cmd->params.reg_mask.mask =
2590 		cpu_to_le32(get_unaligned((u32 *)data_buf));
2591 	cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_mgmt_frame_reg) +
2592 				S_DS_GEN);
2593 
2594 	return 0;
2595 }
2596 
2597 static int
nxpwifi_cmd_sta_remain_on_chan(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)2598 nxpwifi_cmd_sta_remain_on_chan(struct nxpwifi_private *priv,
2599 			       struct host_cmd_ds_command *cmd,
2600 			       u16 cmd_no, void *data_buf,
2601 			       u16 cmd_action, u32 cmd_type)
2602 {
2603 	cmd->command = cpu_to_le16(cmd_no);
2604 	memcpy(&cmd->params, data_buf,
2605 	       sizeof(struct host_cmd_ds_remain_on_chan));
2606 	cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_remain_on_chan) +
2607 				S_DS_GEN);
2608 
2609 	return 0;
2610 }
2611 
2612 static int
nxpwifi_ret_sta_remain_on_chan(struct nxpwifi_private * priv,struct host_cmd_ds_command * resp,u16 cmdresp_no,void * data_buf)2613 nxpwifi_ret_sta_remain_on_chan(struct nxpwifi_private *priv,
2614 			       struct host_cmd_ds_command *resp,
2615 			       u16 cmdresp_no,
2616 			       void *data_buf)
2617 {
2618 	struct host_cmd_ds_remain_on_chan *resp_cfg = &resp->params.roc_cfg;
2619 	struct host_cmd_ds_remain_on_chan *roc_cfg =
2620 		(struct host_cmd_ds_remain_on_chan *)data_buf;
2621 
2622 	if (roc_cfg)
2623 		memcpy(roc_cfg, resp_cfg, sizeof(*roc_cfg));
2624 
2625 	return 0;
2626 }
2627 
2628 static int
nxpwifi_cmd_sta_gtk_rekey_offload(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)2629 nxpwifi_cmd_sta_gtk_rekey_offload(struct nxpwifi_private *priv,
2630 				  struct host_cmd_ds_command *cmd,
2631 				  u16 cmd_no, void *data_buf,
2632 				  u16 cmd_action, u32 cmd_type)
2633 {
2634 	struct host_cmd_ds_gtk_rekey_params *rekey = &cmd->params.rekey;
2635 	struct cfg80211_gtk_rekey_data *data =
2636 		(struct cfg80211_gtk_rekey_data *)data_buf;
2637 	u64 rekey_ctr;
2638 
2639 	cmd->command = cpu_to_le16(HOST_CMD_GTK_REKEY_OFFLOAD_CFG);
2640 	cmd->size = cpu_to_le16(sizeof(*rekey) + S_DS_GEN);
2641 
2642 	rekey->action = cpu_to_le16(cmd_action);
2643 	if (cmd_action == HOST_ACT_GEN_SET) {
2644 		memcpy(rekey->kek, data->kek, NL80211_KEK_LEN);
2645 		memcpy(rekey->kck, data->kck, NL80211_KCK_LEN);
2646 		rekey_ctr = be64_to_cpup((__be64 *)data->replay_ctr);
2647 		rekey->replay_ctr_low = cpu_to_le32((u32)rekey_ctr);
2648 		rekey->replay_ctr_high =
2649 			cpu_to_le32((u32)((u64)rekey_ctr >> 32));
2650 	}
2651 
2652 	return 0;
2653 }
2654 
2655 static int
nxpwifi_cmd_sta_11ac_cfg(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)2656 nxpwifi_cmd_sta_11ac_cfg(struct nxpwifi_private *priv,
2657 			 struct host_cmd_ds_command *cmd,
2658 			 u16 cmd_no, void *data_buf,
2659 			 u16 cmd_action, u32 cmd_type)
2660 {
2661 	return nxpwifi_cmd_11ac_cfg(priv, cmd, cmd_action, data_buf);
2662 }
2663 
2664 static int
nxpwifi_cmd_sta_hs_wakeup_reason(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)2665 nxpwifi_cmd_sta_hs_wakeup_reason(struct nxpwifi_private *priv,
2666 				 struct host_cmd_ds_command *cmd,
2667 				 u16 cmd_no, void *data_buf,
2668 				 u16 cmd_action, u32 cmd_type)
2669 {
2670 	cmd->command = cpu_to_le16(HOST_CMD_HS_WAKEUP_REASON);
2671 	cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_wakeup_reason) +
2672 				S_DS_GEN);
2673 
2674 	return 0;
2675 }
2676 
2677 static int
nxpwifi_ret_sta_hs_wakeup_reason(struct nxpwifi_private * priv,struct host_cmd_ds_command * resp,u16 cmdresp_no,void * data_buf)2678 nxpwifi_ret_sta_hs_wakeup_reason(struct nxpwifi_private *priv,
2679 				 struct host_cmd_ds_command *resp,
2680 				 u16 cmdresp_no,
2681 				 void *data_buf)
2682 {
2683 	struct host_cmd_ds_wakeup_reason *wakeup_reason =
2684 		(struct host_cmd_ds_wakeup_reason *)data_buf;
2685 
2686 	if (!wakeup_reason)
2687 		return 0;
2688 
2689 	wakeup_reason->wakeup_reason =
2690 		resp->params.hs_wakeup_reason.wakeup_reason;
2691 
2692 	return 0;
2693 }
2694 
2695 static int
nxpwifi_cmd_sta_mc_policy(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)2696 nxpwifi_cmd_sta_mc_policy(struct nxpwifi_private *priv,
2697 			  struct host_cmd_ds_command *cmd,
2698 			  u16 cmd_no, void *data_buf,
2699 			  u16 cmd_action, u32 cmd_type)
2700 {
2701 	struct host_cmd_ds_multi_chan_policy *mc_pol = &cmd->params.mc_policy;
2702 	const u16 *drcs_info = data_buf;
2703 
2704 	mc_pol->action = cpu_to_le16(cmd_action);
2705 	mc_pol->policy = cpu_to_le16(*drcs_info);
2706 	cmd->command = cpu_to_le16(HOST_CMD_MC_POLICY);
2707 	cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_multi_chan_policy) +
2708 				S_DS_GEN);
2709 	return 0;
2710 }
2711 
2712 static int
nxpwifi_cmd_sta_sdio_rx_aggr_cfg(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)2713 nxpwifi_cmd_sta_sdio_rx_aggr_cfg(struct nxpwifi_private *priv,
2714 				 struct host_cmd_ds_command *cmd,
2715 				 u16 cmd_no, void *data_buf,
2716 				 u16 cmd_action, u32 cmd_type)
2717 {
2718 	struct host_cmd_sdio_sp_rx_aggr_cfg *cfg =
2719 					&cmd->params.sdio_rx_aggr_cfg;
2720 
2721 	cmd->command = cpu_to_le16(HOST_CMD_SDIO_SP_RX_AGGR_CFG);
2722 	cmd->size =
2723 		cpu_to_le16(sizeof(struct host_cmd_sdio_sp_rx_aggr_cfg) +
2724 			    S_DS_GEN);
2725 	cfg->action = cmd_action;
2726 	if (cmd_action == HOST_ACT_GEN_SET)
2727 		cfg->enable = *(u8 *)data_buf;
2728 
2729 	return 0;
2730 }
2731 
2732 static int
nxpwifi_ret_sta_sdio_rx_aggr_cfg(struct nxpwifi_private * priv,struct host_cmd_ds_command * resp,u16 cmdresp_no,void * data_buf)2733 nxpwifi_ret_sta_sdio_rx_aggr_cfg(struct nxpwifi_private *priv,
2734 				 struct host_cmd_ds_command *resp,
2735 				 u16 cmdresp_no,
2736 				 void *data_buf)
2737 {
2738 	struct nxpwifi_adapter *adapter = priv->adapter;
2739 	struct host_cmd_sdio_sp_rx_aggr_cfg *cfg =
2740 				&resp->params.sdio_rx_aggr_cfg;
2741 
2742 	adapter->sdio_rx_aggr_enable = cfg->enable;
2743 	adapter->sdio_rx_block_size = le16_to_cpu(cfg->block_size);
2744 
2745 	return 0;
2746 }
2747 
2748 static int
nxpwifi_cmd_sta_get_chan_info(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)2749 nxpwifi_cmd_sta_get_chan_info(struct nxpwifi_private *priv,
2750 			      struct host_cmd_ds_command *cmd,
2751 			      u16 cmd_no, void *data_buf,
2752 			      u16 cmd_action, u32 cmd_type)
2753 {
2754 	struct host_cmd_ds_sta_configure *sta_cfg_cmd = &cmd->params.sta_cfg;
2755 	struct host_cmd_tlv_channel_band *tlv_band_channel =
2756 	(struct host_cmd_tlv_channel_band *)sta_cfg_cmd->tlv_buffer;
2757 
2758 	cmd->command = cpu_to_le16(HOST_CMD_STA_CONFIGURE);
2759 	cmd->size = cpu_to_le16(sizeof(*sta_cfg_cmd) +
2760 				sizeof(*tlv_band_channel) + S_DS_GEN);
2761 	sta_cfg_cmd->action = cpu_to_le16(cmd_action);
2762 	memset(tlv_band_channel, 0, sizeof(*tlv_band_channel));
2763 	tlv_band_channel->header.type = cpu_to_le16(TLV_TYPE_CHANNELBANDLIST);
2764 	tlv_band_channel->header.len  = cpu_to_le16(sizeof(*tlv_band_channel) -
2765 					sizeof(struct nxpwifi_ie_types_header));
2766 
2767 	return 0;
2768 }
2769 
2770 static int
nxpwifi_ret_sta_get_chan_info(struct nxpwifi_private * priv,struct host_cmd_ds_command * resp,u16 cmdresp_no,void * data_buf)2771 nxpwifi_ret_sta_get_chan_info(struct nxpwifi_private *priv,
2772 			      struct host_cmd_ds_command *resp,
2773 			      u16 cmdresp_no,
2774 			      void *data_buf)
2775 {
2776 	struct host_cmd_ds_sta_configure *sta_cfg_cmd = &resp->params.sta_cfg;
2777 	struct nxpwifi_channel_band *channel_band =
2778 		(struct nxpwifi_channel_band *)data_buf;
2779 	struct host_cmd_tlv_channel_band *tlv_band_channel;
2780 
2781 	if (!channel_band)
2782 		return 0;
2783 
2784 	tlv_band_channel =
2785 	(struct host_cmd_tlv_channel_band *)sta_cfg_cmd->tlv_buffer;
2786 	memcpy(&channel_band->band_config, &tlv_band_channel->band_config,
2787 	       sizeof(struct nxpwifi_band_config));
2788 	channel_band->channel = tlv_band_channel->channel;
2789 
2790 	return 0;
2791 }
2792 
2793 static int
nxpwifi_cmd_sta_chan_region_cfg(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)2794 nxpwifi_cmd_sta_chan_region_cfg(struct nxpwifi_private *priv,
2795 				struct host_cmd_ds_command *cmd,
2796 				u16 cmd_no, void *data_buf,
2797 				u16 cmd_action, u32 cmd_type)
2798 {
2799 	struct host_cmd_ds_chan_region_cfg *reg = &cmd->params.reg_cfg;
2800 
2801 	cmd->command = cpu_to_le16(HOST_CMD_CHAN_REGION_CFG);
2802 	cmd->size = cpu_to_le16(sizeof(*reg) + S_DS_GEN);
2803 
2804 	if (cmd_action == HOST_ACT_GEN_GET)
2805 		reg->action = cpu_to_le16(cmd_action);
2806 
2807 	return 0;
2808 }
2809 
2810 static struct ieee80211_regdomain *
nxpwifi_create_custom_regdomain(struct nxpwifi_private * priv,u8 * buf,u16 buf_len)2811 nxpwifi_create_custom_regdomain(struct nxpwifi_private *priv,
2812 				u8 *buf, u16 buf_len)
2813 {
2814 	u16 num_chan = buf_len / 2;
2815 	struct ieee80211_regdomain *regd;
2816 	struct ieee80211_reg_rule *rule;
2817 	bool new_rule;
2818 	int idx, freq, prev_freq = 0;
2819 	u32 bw, prev_bw = 0;
2820 	u8 chflags, prev_chflags = 0, valid_rules = 0;
2821 
2822 	if (WARN_ON_ONCE(num_chan > NL80211_MAX_SUPP_REG_RULES))
2823 		return ERR_PTR(-EINVAL);
2824 
2825 	regd = kzalloc_flex(*regd, reg_rules, num_chan, GFP_KERNEL);
2826 	if (!regd)
2827 		return ERR_PTR(-ENOMEM);
2828 
2829 	for (idx = 0; idx < num_chan; idx++) {
2830 		u8 chan;
2831 		enum nl80211_band band;
2832 
2833 		chan = *buf++;
2834 		if (!chan) {
2835 			kfree(regd);
2836 			return NULL;
2837 		}
2838 		chflags = *buf++;
2839 		band = (chan <= 14) ? NL80211_BAND_2GHZ : NL80211_BAND_5GHZ;
2840 		freq = ieee80211_channel_to_frequency(chan, band);
2841 		new_rule = false;
2842 
2843 		if (chflags & NXPWIFI_CHANNEL_DISABLED)
2844 			continue;
2845 
2846 		if (band == NL80211_BAND_5GHZ) {
2847 			if (!(chflags & NXPWIFI_CHANNEL_NOHT80))
2848 				bw = MHZ_TO_KHZ(80);
2849 			else if (!(chflags & NXPWIFI_CHANNEL_NOHT40))
2850 				bw = MHZ_TO_KHZ(40);
2851 			else
2852 				bw = MHZ_TO_KHZ(20);
2853 		} else {
2854 			if (!(chflags & NXPWIFI_CHANNEL_NOHT40))
2855 				bw = MHZ_TO_KHZ(40);
2856 			else
2857 				bw = MHZ_TO_KHZ(20);
2858 		}
2859 
2860 		if (idx == 0 || prev_chflags != chflags || prev_bw != bw ||
2861 		    freq - prev_freq > 20) {
2862 			valid_rules++;
2863 			new_rule = true;
2864 		}
2865 
2866 		rule = &regd->reg_rules[valid_rules - 1];
2867 
2868 		rule->freq_range.end_freq_khz = MHZ_TO_KHZ(freq + 10);
2869 
2870 		prev_chflags = chflags;
2871 		prev_freq = freq;
2872 		prev_bw = bw;
2873 
2874 		if (!new_rule)
2875 			continue;
2876 
2877 		rule->freq_range.start_freq_khz = MHZ_TO_KHZ(freq - 10);
2878 		rule->power_rule.max_eirp = DBM_TO_MBM(19);
2879 
2880 		if (chflags & NXPWIFI_CHANNEL_PASSIVE)
2881 			rule->flags = NL80211_RRF_NO_IR;
2882 
2883 		if (chflags & NXPWIFI_CHANNEL_DFS)
2884 			rule->flags = NL80211_RRF_DFS;
2885 
2886 		rule->freq_range.max_bandwidth_khz = bw;
2887 	}
2888 
2889 	regd->n_reg_rules = valid_rules;
2890 	regd->alpha2[0] = '9';
2891 	regd->alpha2[1] = '9';
2892 
2893 	return regd;
2894 }
2895 
2896 static int
nxpwifi_ret_sta_chan_region_cfg(struct nxpwifi_private * priv,struct host_cmd_ds_command * resp,u16 cmdresp_no,void * data_buf)2897 nxpwifi_ret_sta_chan_region_cfg(struct nxpwifi_private *priv,
2898 				struct host_cmd_ds_command *resp,
2899 				u16 cmdresp_no,
2900 				void *data_buf)
2901 {
2902 	struct host_cmd_ds_chan_region_cfg *reg = &resp->params.reg_cfg;
2903 	u16 action = le16_to_cpu(reg->action);
2904 	u16 tlv, tlv_buf_len, tlv_buf_left;
2905 	struct nxpwifi_ie_types_header *head;
2906 	struct ieee80211_regdomain *regd;
2907 	u8 *tlv_buf;
2908 
2909 	if (action != HOST_ACT_GEN_GET)
2910 		return 0;
2911 
2912 	tlv_buf = (u8 *)reg + sizeof(*reg);
2913 	tlv_buf_left = le16_to_cpu(resp->size) - S_DS_GEN - sizeof(*reg);
2914 
2915 	while (tlv_buf_left >= sizeof(*head)) {
2916 		head = (struct nxpwifi_ie_types_header *)tlv_buf;
2917 		tlv = le16_to_cpu(head->type);
2918 		tlv_buf_len = le16_to_cpu(head->len);
2919 
2920 		if (tlv_buf_left < (sizeof(*head) + tlv_buf_len))
2921 			break;
2922 
2923 		switch (tlv) {
2924 		case TLV_TYPE_CHAN_ATTR_CFG:
2925 			nxpwifi_dbg_dump(priv->adapter, CMD_D, "CHAN:",
2926 					 (u8 *)head + sizeof(*head),
2927 					 tlv_buf_len);
2928 			regd = nxpwifi_create_custom_regdomain(priv, (u8 *)head
2929 							       + sizeof(*head),
2930 							       tlv_buf_len);
2931 			if (!IS_ERR(regd))
2932 				priv->adapter->regd = regd;
2933 			break;
2934 		}
2935 
2936 		tlv_buf += (sizeof(*head) + tlv_buf_len);
2937 		tlv_buf_left -= (sizeof(*head) + tlv_buf_len);
2938 	}
2939 
2940 	return 0;
2941 }
2942 
2943 static int
nxpwifi_cmd_sta_pkt_aggr_ctrl(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)2944 nxpwifi_cmd_sta_pkt_aggr_ctrl(struct nxpwifi_private *priv,
2945 			      struct host_cmd_ds_command *cmd,
2946 			      u16 cmd_no, void *data_buf,
2947 			      u16 cmd_action, u32 cmd_type)
2948 {
2949 	cmd->command = cpu_to_le16(cmd_no);
2950 	cmd->params.pkt_aggr_ctrl.action = cpu_to_le16(cmd_action);
2951 	cmd->params.pkt_aggr_ctrl.enable = cpu_to_le16(*(u16 *)data_buf);
2952 	cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_pkt_aggr_ctrl) +
2953 				S_DS_GEN);
2954 
2955 	return 0;
2956 }
2957 
2958 static int
nxpwifi_ret_sta_pkt_aggr_ctrl(struct nxpwifi_private * priv,struct host_cmd_ds_command * resp,u16 cmdresp_no,void * data_buf)2959 nxpwifi_ret_sta_pkt_aggr_ctrl(struct nxpwifi_private *priv,
2960 			      struct host_cmd_ds_command *resp,
2961 			      u16 cmdresp_no,
2962 			      void *data_buf)
2963 {
2964 	struct host_cmd_ds_pkt_aggr_ctrl *pkt_aggr_ctrl =
2965 					&resp->params.pkt_aggr_ctrl;
2966 	struct nxpwifi_adapter *adapter = priv->adapter;
2967 
2968 	adapter->bus_aggr.enable = le16_to_cpu(pkt_aggr_ctrl->enable);
2969 	if (adapter->bus_aggr.enable)
2970 		adapter->intf_hdr_len = INTF_HEADER_LEN;
2971 	adapter->bus_aggr.mode = NXPWIFI_BUS_AGGR_MODE_LEN_V2;
2972 	adapter->bus_aggr.tx_aggr_max_size =
2973 		le16_to_cpu(pkt_aggr_ctrl->tx_aggr_max_size);
2974 	adapter->bus_aggr.tx_aggr_max_num =
2975 		le16_to_cpu(pkt_aggr_ctrl->tx_aggr_max_num);
2976 	adapter->bus_aggr.tx_aggr_align =
2977 		le16_to_cpu(pkt_aggr_ctrl->tx_aggr_align);
2978 
2979 	return 0;
2980 }
2981 
2982 static int
nxpwifi_cmd_sta_11ax_cfg(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)2983 nxpwifi_cmd_sta_11ax_cfg(struct nxpwifi_private *priv,
2984 			 struct host_cmd_ds_command *cmd,
2985 			 u16 cmd_no, void *data_buf,
2986 			 u16 cmd_action, u32 cmd_type)
2987 {
2988 	return nxpwifi_cmd_11ax_cfg(priv, cmd, cmd_action, data_buf);
2989 }
2990 
2991 static int
nxpwifi_ret_sta_11ax_cfg(struct nxpwifi_private * priv,struct host_cmd_ds_command * resp,u16 cmdresp_no,void * data_buf)2992 nxpwifi_ret_sta_11ax_cfg(struct nxpwifi_private *priv,
2993 			 struct host_cmd_ds_command *resp,
2994 			 u16 cmdresp_no,
2995 			 void *data_buf)
2996 {
2997 	return nxpwifi_ret_11ax_cfg(priv, resp, data_buf);
2998 }
2999 
3000 static int
nxpwifi_cmd_sta_11ax_cmd(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)3001 nxpwifi_cmd_sta_11ax_cmd(struct nxpwifi_private *priv,
3002 			 struct host_cmd_ds_command *cmd,
3003 			 u16 cmd_no, void *data_buf,
3004 			 u16 cmd_action, u32 cmd_type)
3005 {
3006 	return nxpwifi_cmd_11ax_cmd(priv, cmd, cmd_action, data_buf);
3007 }
3008 
3009 static int
nxpwifi_ret_sta_11ax_cmd(struct nxpwifi_private * priv,struct host_cmd_ds_command * resp,u16 cmdresp_no,void * data_buf)3010 nxpwifi_ret_sta_11ax_cmd(struct nxpwifi_private *priv,
3011 			 struct host_cmd_ds_command *resp,
3012 			 u16 cmdresp_no,
3013 			 void *data_buf)
3014 {
3015 	return nxpwifi_ret_11ax_cmd(priv, resp, data_buf);
3016 }
3017 
3018 static int
nxpwifi_cmd_sta_twt_cfg(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)3019 nxpwifi_cmd_sta_twt_cfg(struct nxpwifi_private *priv,
3020 			struct host_cmd_ds_command *cmd,
3021 			u16 cmd_no, void *data_buf,
3022 			u16 cmd_action, u32 cmd_type)
3023 {
3024 	return nxpwifi_cmd_twt_cfg(priv, cmd, cmd_action, data_buf);
3025 }
3026 
3027 static int
nxpwifi_ret_sta_twt_cfg(struct nxpwifi_private * priv,struct host_cmd_ds_command * resp,u16 cmdresp_no,void * data_buf)3028 nxpwifi_ret_sta_twt_cfg(struct nxpwifi_private *priv,
3029 			struct host_cmd_ds_command *resp,
3030 			u16 cmdresp_no,
3031 			void *data_buf)
3032 {
3033 	return nxpwifi_ret_twt_cfg(priv, resp, data_buf);
3034 }
3035 
3036 static const struct nxpwifi_cmd_entry cmd_table_sta[] = {
3037 	{.cmd_no = HOST_CMD_GET_HW_SPEC,
3038 	.prepare_cmd = nxpwifi_cmd_sta_get_hw_spec,
3039 	.cmd_resp = nxpwifi_ret_sta_get_hw_spec},
3040 	{.cmd_no = HOST_CMD_802_11_SCAN,
3041 	.prepare_cmd = nxpwifi_cmd_sta_802_11_scan,
3042 	.cmd_resp = nxpwifi_ret_sta_802_11_scan},
3043 	{.cmd_no = HOST_CMD_802_11_GET_LOG,
3044 	.prepare_cmd = nxpwifi_cmd_sta_802_11_get_log,
3045 	.cmd_resp = nxpwifi_ret_sta_802_11_get_log},
3046 	{.cmd_no = HOST_CMD_MAC_MULTICAST_ADR,
3047 	.prepare_cmd = nxpwifi_cmd_sta_mac_multicast_adr,
3048 	.cmd_resp = NULL},
3049 	{.cmd_no = HOST_CMD_802_11_ASSOCIATE,
3050 	.prepare_cmd = nxpwifi_cmd_sta_802_11_associate,
3051 	.cmd_resp = nxpwifi_ret_sta_802_11_associate},
3052 	{.cmd_no = HOST_CMD_802_11_SNMP_MIB,
3053 	.prepare_cmd = nxpwifi_cmd_sta_802_11_snmp_mib,
3054 	.cmd_resp = nxpwifi_ret_sta_802_11_snmp_mib},
3055 	{.cmd_no = HOST_CMD_MAC_REG_ACCESS,
3056 	.prepare_cmd = nxpwifi_cmd_sta_reg_access,
3057 	.cmd_resp = nxpwifi_ret_sta_reg_access},
3058 	{.cmd_no = HOST_CMD_BBP_REG_ACCESS,
3059 	.prepare_cmd = nxpwifi_cmd_sta_reg_access,
3060 	.cmd_resp = nxpwifi_ret_sta_reg_access},
3061 	{.cmd_no = HOST_CMD_RF_REG_ACCESS,
3062 	.prepare_cmd = nxpwifi_cmd_sta_reg_access,
3063 	.cmd_resp = nxpwifi_ret_sta_reg_access},
3064 	{.cmd_no = HOST_CMD_RF_TX_PWR,
3065 	.prepare_cmd = nxpwifi_cmd_sta_rf_tx_pwr,
3066 	.cmd_resp = nxpwifi_ret_sta_rf_tx_pwr},
3067 	{.cmd_no = HOST_CMD_RF_ANTENNA,
3068 	.prepare_cmd = nxpwifi_cmd_sta_rf_antenna,
3069 	.cmd_resp = nxpwifi_ret_sta_rf_antenna},
3070 	{.cmd_no = HOST_CMD_802_11_DEAUTHENTICATE,
3071 	.prepare_cmd = nxpwifi_cmd_sta_802_11_deauthenticate,
3072 	.cmd_resp = nxpwifi_ret_sta_802_11_deauthenticate},
3073 	{.cmd_no = HOST_CMD_MAC_CONTROL,
3074 	.prepare_cmd = nxpwifi_cmd_sta_mac_control,
3075 	.cmd_resp = NULL},
3076 	{.cmd_no = HOST_CMD_802_11_MAC_ADDRESS,
3077 	.prepare_cmd = nxpwifi_cmd_sta_802_11_mac_address,
3078 	.cmd_resp = nxpwifi_ret_sta_802_11_mac_address},
3079 	{.cmd_no = HOST_CMD_802_11_EEPROM_ACCESS,
3080 	.prepare_cmd = nxpwifi_cmd_sta_reg_access,
3081 	.cmd_resp = nxpwifi_ret_sta_reg_access},
3082 	{.cmd_no = HOST_CMD_802_11D_DOMAIN_INFO,
3083 	.prepare_cmd = nxpwifi_cmd_sta_802_11d_domain_info,
3084 	.cmd_resp = nxpwifi_ret_sta_802_11d_domain_info},
3085 	{.cmd_no = HOST_CMD_802_11_KEY_MATERIAL,
3086 	.prepare_cmd = nxpwifi_cmd_sta_802_11_key_material,
3087 	.cmd_resp = nxpwifi_ret_sta_802_11_key_material},
3088 	{.cmd_no = HOST_CMD_802_11_BG_SCAN_CONFIG,
3089 	.prepare_cmd = nxpwifi_cmd_sta_802_11_bg_scan_config,
3090 	.cmd_resp = NULL},
3091 	{.cmd_no = HOST_CMD_802_11_BG_SCAN_QUERY,
3092 	.prepare_cmd = nxpwifi_cmd_sta_802_11_bg_scan_query,
3093 	.cmd_resp = nxpwifi_ret_sta_802_11_bg_scan_query},
3094 	{.cmd_no = HOST_CMD_WMM_GET_STATUS,
3095 	.prepare_cmd = nxpwifi_cmd_sta_wmm_get_status,
3096 	.cmd_resp = nxpwifi_ret_sta_wmm_get_status},
3097 	{.cmd_no = HOST_CMD_802_11_SUBSCRIBE_EVENT,
3098 	.prepare_cmd = nxpwifi_cmd_sta_802_11_subsc_evt,
3099 	.cmd_resp = nxpwifi_ret_sta_subsc_evt},
3100 	{.cmd_no = HOST_CMD_802_11_TX_RATE_QUERY,
3101 	.prepare_cmd = nxpwifi_cmd_sta_802_11_tx_rate_query,
3102 	.cmd_resp = nxpwifi_ret_sta_802_11_tx_rate_query},
3103 	{.cmd_no = HOST_CMD_MEM_ACCESS,
3104 	.prepare_cmd = nxpwifi_cmd_sta_mem_access,
3105 	.cmd_resp = nxpwifi_ret_sta_mem_access},
3106 	{.cmd_no = HOST_CMD_CFG_DATA,
3107 	.prepare_cmd = nxpwifi_cmd_sta_cfg_data,
3108 	.cmd_resp = nxpwifi_ret_sta_cfg_data},
3109 	{.cmd_no = HOST_CMD_VERSION_EXT,
3110 	.prepare_cmd = nxpwifi_cmd_sta_ver_ext,
3111 	.cmd_resp = nxpwifi_ret_sta_ver_ext},
3112 	{.cmd_no = HOST_CMD_MEF_CFG,
3113 	.prepare_cmd = nxpwifi_cmd_sta_mef_cfg,
3114 	.cmd_resp = NULL},
3115 	{.cmd_no = HOST_CMD_RSSI_INFO,
3116 	.prepare_cmd = nxpwifi_cmd_sta_802_11_rssi_info,
3117 	.cmd_resp = nxpwifi_ret_sta_802_11_rssi_info},
3118 	{.cmd_no = HOST_CMD_FUNC_INIT,
3119 	.prepare_cmd = nxpwifi_cmd_sta_func_init,
3120 	.cmd_resp = NULL},
3121 	{.cmd_no = HOST_CMD_FUNC_SHUTDOWN,
3122 	.prepare_cmd = nxpwifi_cmd_sta_func_shutdown,
3123 	.cmd_resp = NULL},
3124 	{.cmd_no = HOST_CMD_PMIC_REG_ACCESS,
3125 	.prepare_cmd = nxpwifi_cmd_sta_reg_access,
3126 	.cmd_resp = nxpwifi_ret_sta_reg_access},
3127 	{.cmd_no = HOST_CMD_11N_CFG,
3128 	.prepare_cmd = nxpwifi_cmd_sta_11n_cfg,
3129 	.cmd_resp = NULL},
3130 	{.cmd_no = HOST_CMD_11N_ADDBA_REQ,
3131 	.prepare_cmd = nxpwifi_cmd_sta_11n_addba_req,
3132 	.cmd_resp = nxpwifi_ret_sta_11n_addba_req},
3133 	{.cmd_no = HOST_CMD_11N_ADDBA_RSP,
3134 	.prepare_cmd = nxpwifi_cmd_sta_11n_addba_rsp,
3135 	.cmd_resp = nxpwifi_ret_sta_11n_addba_rsp},
3136 	{.cmd_no = HOST_CMD_11N_DELBA,
3137 	.prepare_cmd = nxpwifi_cmd_sta_11n_delba,
3138 	.cmd_resp = nxpwifi_ret_sta_11n_delba},
3139 	{.cmd_no = HOST_CMD_TXPWR_CFG,
3140 	.prepare_cmd = nxpwifi_cmd_sta_tx_power_cfg,
3141 	.cmd_resp = nxpwifi_ret_sta_tx_power_cfg},
3142 	{.cmd_no = HOST_CMD_TX_RATE_CFG,
3143 	.prepare_cmd = nxpwifi_cmd_sta_tx_rate_cfg,
3144 	.cmd_resp = nxpwifi_ret_sta_tx_rate_cfg},
3145 	{.cmd_no = HOST_CMD_RECONFIGURE_TX_BUFF,
3146 	.prepare_cmd = nxpwifi_cmd_sta_reconfigure_rx_buff,
3147 	.cmd_resp = nxpwifi_ret_sta_reconfigure_rx_buff},
3148 	{.cmd_no = HOST_CMD_CHAN_REPORT_REQUEST,
3149 	.prepare_cmd = nxpwifi_cmd_sta_chan_report_request,
3150 	.cmd_resp = NULL},
3151 	{.cmd_no = HOST_CMD_AMSDU_AGGR_CTRL,
3152 	.prepare_cmd = nxpwifi_cmd_sta_amsdu_aggr_ctrl,
3153 	.cmd_resp = NULL},
3154 	{.cmd_no = HOST_CMD_ROBUST_COEX,
3155 	.prepare_cmd = nxpwifi_cmd_sta_robust_coex,
3156 	.cmd_resp = nxpwifi_ret_sta_robust_coex},
3157 	{.cmd_no = HOST_CMD_802_11_PS_MODE_ENH,
3158 	.prepare_cmd = nxpwifi_cmd_sta_enh_power_mode,
3159 	.cmd_resp = nxpwifi_ret_sta_enh_power_mode},
3160 	{.cmd_no = HOST_CMD_802_11_HS_CFG_ENH,
3161 	.prepare_cmd = nxpwifi_cmd_sta_802_11_hs_cfg,
3162 	.cmd_resp = nxpwifi_ret_sta_802_11_hs_cfg},
3163 	{.cmd_no = HOST_CMD_CAU_REG_ACCESS,
3164 	.prepare_cmd = nxpwifi_cmd_sta_reg_access,
3165 	.cmd_resp = nxpwifi_ret_sta_reg_access},
3166 	{.cmd_no = HOST_CMD_SET_BSS_MODE,
3167 	.prepare_cmd = nxpwifi_cmd_sta_set_bss_mode,
3168 	.cmd_resp = NULL},
3169 	{.cmd_no = HOST_CMD_802_11_NET_MONITOR,
3170 	.prepare_cmd = nxpwifi_cmd_sta_802_11_net_monitor,
3171 	.cmd_resp = nxpwifi_ret_sta_802_11_net_monitor},
3172 	{.cmd_no = HOST_CMD_802_11_SCAN_EXT,
3173 	.prepare_cmd = nxpwifi_cmd_sta_802_11_scan_ext,
3174 	.cmd_resp = nxpwifi_ret_sta_802_11_scan_ext},
3175 	{.cmd_no = HOST_CMD_COALESCE_CFG,
3176 	.prepare_cmd = nxpwifi_cmd_sta_coalesce_cfg,
3177 	.cmd_resp = NULL},
3178 	{.cmd_no = HOST_CMD_MGMT_FRAME_REG,
3179 	.prepare_cmd = nxpwifi_cmd_sta_mgmt_frame_reg,
3180 	.cmd_resp = NULL},
3181 	{.cmd_no = HOST_CMD_REMAIN_ON_CHAN,
3182 	.prepare_cmd = nxpwifi_cmd_sta_remain_on_chan,
3183 	.cmd_resp = nxpwifi_ret_sta_remain_on_chan},
3184 	{.cmd_no = HOST_CMD_GTK_REKEY_OFFLOAD_CFG,
3185 	.prepare_cmd = nxpwifi_cmd_sta_gtk_rekey_offload,
3186 	.cmd_resp = NULL},
3187 	{.cmd_no = HOST_CMD_11AC_CFG,
3188 	.prepare_cmd = nxpwifi_cmd_sta_11ac_cfg,
3189 	.cmd_resp = NULL},
3190 	{.cmd_no = HOST_CMD_HS_WAKEUP_REASON,
3191 	.prepare_cmd = nxpwifi_cmd_sta_hs_wakeup_reason,
3192 	.cmd_resp = nxpwifi_ret_sta_hs_wakeup_reason},
3193 	{.cmd_no = HOST_CMD_MC_POLICY,
3194 	.prepare_cmd = nxpwifi_cmd_sta_mc_policy,
3195 	.cmd_resp = NULL},
3196 	{.cmd_no = HOST_CMD_FW_DUMP_EVENT,
3197 	.prepare_cmd = nxpwifi_cmd_fill_head_only,
3198 	.cmd_resp = NULL},
3199 	{.cmd_no = HOST_CMD_SDIO_SP_RX_AGGR_CFG,
3200 	.prepare_cmd = nxpwifi_cmd_sta_sdio_rx_aggr_cfg,
3201 	.cmd_resp = nxpwifi_ret_sta_sdio_rx_aggr_cfg},
3202 	{.cmd_no = HOST_CMD_STA_CONFIGURE,
3203 	.prepare_cmd = nxpwifi_cmd_sta_get_chan_info,
3204 	.cmd_resp = nxpwifi_ret_sta_get_chan_info},
3205 	{.cmd_no = HOST_CMD_CHAN_REGION_CFG,
3206 	.prepare_cmd = nxpwifi_cmd_sta_chan_region_cfg,
3207 	.cmd_resp = nxpwifi_ret_sta_chan_region_cfg},
3208 	{.cmd_no = HOST_CMD_PACKET_AGGR_CTRL,
3209 	.prepare_cmd = nxpwifi_cmd_sta_pkt_aggr_ctrl,
3210 	.cmd_resp = nxpwifi_ret_sta_pkt_aggr_ctrl},
3211 	{.cmd_no = HOST_CMD_11AX_CFG,
3212 	.prepare_cmd = nxpwifi_cmd_sta_11ax_cfg,
3213 	.cmd_resp = nxpwifi_ret_sta_11ax_cfg},
3214 	{.cmd_no = HOST_CMD_11AX_CMD,
3215 	.prepare_cmd = nxpwifi_cmd_sta_11ax_cmd,
3216 	.cmd_resp = nxpwifi_ret_sta_11ax_cmd},
3217 	{.cmd_no = HOST_CMD_TWT_CFG,
3218 	.prepare_cmd = nxpwifi_cmd_sta_twt_cfg,
3219 	.cmd_resp = nxpwifi_ret_sta_twt_cfg},
3220 };
3221 
3222 /*
3223  * Prepare a command before sending it to firmware by invoking the
3224  * appropriate handler based on the command ID.
3225  */
nxpwifi_sta_prepare_cmd(struct nxpwifi_private * priv,struct cmd_ctrl_node * cmd_node,u16 cmd_action,u32 cmd_oid)3226 int nxpwifi_sta_prepare_cmd(struct nxpwifi_private *priv,
3227 			    struct cmd_ctrl_node *cmd_node,
3228 			    u16 cmd_action, u32 cmd_oid)
3229 
3230 {
3231 	struct nxpwifi_adapter *adapter = priv->adapter;
3232 	u16 cmd_no = cmd_node->cmd_no;
3233 	struct host_cmd_ds_command *cmd =
3234 		(struct host_cmd_ds_command *)cmd_node->skb->data;
3235 	void *data_buf = cmd_node->data_buf;
3236 	int i, ret = -EINVAL;
3237 
3238 	for (i = 0; i < ARRAY_SIZE(cmd_table_sta); i++) {
3239 		if (cmd_no == cmd_table_sta[i].cmd_no) {
3240 			if (cmd_table_sta[i].prepare_cmd)
3241 				ret = cmd_table_sta[i].prepare_cmd(priv, cmd,
3242 								   cmd_no,
3243 								   data_buf,
3244 								   cmd_action,
3245 								   cmd_oid);
3246 			cmd_node->cmd_resp = cmd_table_sta[i].cmd_resp;
3247 			break;
3248 		}
3249 	}
3250 
3251 	if (i == ARRAY_SIZE(cmd_table_sta))
3252 		nxpwifi_dbg(adapter, ERROR,
3253 			    "%s: unknown command: %#x\n",
3254 			    __func__, cmd_no);
3255 	else
3256 		nxpwifi_dbg(adapter, CMD,
3257 			    "%s: command: %#x\n",
3258 			    __func__, cmd_no);
3259 
3260 	return ret;
3261 }
3262 
3263 /*
3264  * Initialize firmware after download or during virtual interface
3265  * reinitialization to bring the device to a working state.
3266  */
nxpwifi_sta_init_cmd(struct nxpwifi_private * priv,u8 first_sta,bool init)3267 int nxpwifi_sta_init_cmd(struct nxpwifi_private *priv, u8 first_sta, bool init)
3268 {
3269 	struct nxpwifi_adapter *adapter = priv->adapter;
3270 	int ret;
3271 	struct nxpwifi_ds_11n_amsdu_aggr_ctrl amsdu_aggr_ctrl;
3272 	struct nxpwifi_ds_auto_ds auto_ds;
3273 	enum state_11d_t state_11d;
3274 	struct nxpwifi_ds_11n_tx_cfg tx_cfg;
3275 	u8 sdio_sp_rx_aggr_enable;
3276 
3277 	if (first_sta) {
3278 		ret = nxpwifi_send_cmd(priv, HOST_CMD_FUNC_INIT,
3279 				       HOST_ACT_GEN_SET, 0, NULL, true);
3280 		if (ret)
3281 			return ret;
3282 
3283 		if (adapter->cal_data)
3284 			nxpwifi_send_cmd(priv, HOST_CMD_CFG_DATA,
3285 					 HOST_ACT_GEN_SET, 0, NULL, true);
3286 
3287 		/* Read MAC address from HW */
3288 		ret = nxpwifi_send_cmd(priv, HOST_CMD_GET_HW_SPEC,
3289 				       HOST_ACT_GEN_GET, 0, NULL, true);
3290 		if (ret)
3291 			return ret;
3292 
3293 		/* * Set SDIO Single Port RX Aggr Info */
3294 		if (priv->adapter->iface_type == NXPWIFI_SDIO &&
3295 		    ISSUPP_SDIO_SPA_ENABLED(priv->adapter->fw_cap_info) &&
3296 		    !priv->adapter->host_disable_sdio_rx_aggr) {
3297 			sdio_sp_rx_aggr_enable = true;
3298 			ret = nxpwifi_send_cmd(priv,
3299 					       HOST_CMD_SDIO_SP_RX_AGGR_CFG,
3300 					       HOST_ACT_GEN_SET, 0,
3301 					       &sdio_sp_rx_aggr_enable,
3302 					       true);
3303 			if (ret) {
3304 				nxpwifi_dbg(priv->adapter, ERROR,
3305 					    "error while enabling SP aggregation..disable it");
3306 				adapter->sdio_rx_aggr_enable = false;
3307 			}
3308 		}
3309 
3310 		/* Reconfigure tx buf size */
3311 		ret = nxpwifi_send_cmd(priv, HOST_CMD_RECONFIGURE_TX_BUFF,
3312 				       HOST_ACT_GEN_SET, 0,
3313 				       &priv->adapter->tx_buf_size, true);
3314 		if (ret)
3315 			return ret;
3316 
3317 		if (priv->bss_type != NXPWIFI_BSS_TYPE_UAP) {
3318 			/* Enable IEEE PS by default */
3319 			priv->adapter->ps_mode = NXPWIFI_802_11_POWER_MODE_PSP;
3320 			ret = nxpwifi_send_cmd(priv,
3321 					       HOST_CMD_802_11_PS_MODE_ENH,
3322 					       EN_AUTO_PS, BITMAP_STA_PS, NULL,
3323 					       true);
3324 			if (ret)
3325 				return ret;
3326 		}
3327 
3328 		nxpwifi_send_cmd(priv, HOST_CMD_CHAN_REGION_CFG,
3329 				 HOST_ACT_GEN_GET, 0, NULL, true);
3330 	}
3331 
3332 	/* get tx rate */
3333 	ret = nxpwifi_send_cmd(priv, HOST_CMD_TX_RATE_CFG,
3334 			       HOST_ACT_GEN_GET, 0, NULL, true);
3335 	if (ret)
3336 		return ret;
3337 	priv->data_rate = 0;
3338 
3339 	/* get tx power */
3340 	ret = nxpwifi_send_cmd(priv, HOST_CMD_RF_TX_PWR,
3341 			       HOST_ACT_GEN_GET, 0, NULL, true);
3342 	if (ret)
3343 		return ret;
3344 
3345 	memset(&amsdu_aggr_ctrl, 0, sizeof(amsdu_aggr_ctrl));
3346 	amsdu_aggr_ctrl.enable = true;
3347 	/* Send request to firmware */
3348 	ret = nxpwifi_send_cmd(priv, HOST_CMD_AMSDU_AGGR_CTRL,
3349 			       HOST_ACT_GEN_SET, 0,
3350 			       &amsdu_aggr_ctrl, true);
3351 	if (ret)
3352 		return ret;
3353 	/* MAC Control must be the last command in init_fw */
3354 	/* set MAC Control */
3355 	ret = nxpwifi_send_cmd(priv, HOST_CMD_MAC_CONTROL,
3356 			       HOST_ACT_GEN_SET, 0,
3357 			       &priv->curr_pkt_filter, true);
3358 	if (ret)
3359 		return ret;
3360 
3361 	if (!disable_auto_ds && first_sta &&
3362 	    priv->bss_type != NXPWIFI_BSS_TYPE_UAP) {
3363 		/* Enable auto deep sleep */
3364 		auto_ds.auto_ds = DEEP_SLEEP_ON;
3365 		auto_ds.idle_time = DEEP_SLEEP_IDLE_TIME;
3366 		ret = nxpwifi_send_cmd(priv, HOST_CMD_802_11_PS_MODE_ENH,
3367 				       EN_AUTO_PS, BITMAP_AUTO_DS,
3368 				       &auto_ds, true);
3369 		if (ret)
3370 			return ret;
3371 	}
3372 
3373 	if (priv->bss_type != NXPWIFI_BSS_TYPE_UAP) {
3374 		/* Send cmd to FW to enable/disable 11D function */
3375 		state_11d = ENABLE_11D;
3376 		ret = nxpwifi_send_cmd(priv, HOST_CMD_802_11_SNMP_MIB,
3377 				       HOST_ACT_GEN_SET, DOT11D_I,
3378 				       &state_11d, true);
3379 		if (ret)
3380 			nxpwifi_dbg(priv->adapter, ERROR,
3381 				    "11D: failed to enable 11D\n");
3382 	}
3383 
3384 	/*
3385 	 * Send cmd to FW to configure 11n specific configuration
3386 	 * (Short GI, Channel BW, Green field support etc.) for transmit
3387 	 */
3388 	tx_cfg.tx_htcap = NXPWIFI_FW_DEF_HTTXCFG;
3389 	ret = nxpwifi_send_cmd(priv, HOST_CMD_11N_CFG,
3390 			       HOST_ACT_GEN_SET, 0, &tx_cfg, true);
3391 
3392 	return ret;
3393 }
3394