• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Marvell Wireless LAN device driver: station command response handling
3  *
4  * Copyright (C) 2011-2014, Marvell International Ltd.
5  *
6  * This software file (the "File") is distributed by Marvell International
7  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
8  * (the "License").  You may use, redistribute and/or modify this File in
9  * accordance with the terms and conditions of the License, a copy of which
10  * is available by writing to the Free Software Foundation, Inc.,
11  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
12  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
13  *
14  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
16  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
17  * this warranty disclaimer.
18  */
19 
20 #include "decl.h"
21 #include "ioctl.h"
22 #include "util.h"
23 #include "fw.h"
24 #include "main.h"
25 #include "wmm.h"
26 #include "11n.h"
27 #include "11ac.h"
28 
29 
30 /*
31  * This function handles the command response error case.
32  *
33  * For scan response error, the function cancels all the pending
34  * scan commands and generates an event to inform the applications
35  * of the scan completion.
36  *
37  * For Power Save command failure, we do not retry enter PS
38  * command in case of Ad-hoc mode.
39  *
40  * For all other response errors, the current command buffer is freed
41  * and returned to the free command queue.
42  */
43 static void
mwifiex_process_cmdresp_error(struct mwifiex_private * priv,struct host_cmd_ds_command * resp)44 mwifiex_process_cmdresp_error(struct mwifiex_private *priv,
45 			      struct host_cmd_ds_command *resp)
46 {
47 	struct cmd_ctrl_node *cmd_node = NULL, *tmp_node;
48 	struct mwifiex_adapter *adapter = priv->adapter;
49 	struct host_cmd_ds_802_11_ps_mode_enh *pm;
50 	unsigned long flags;
51 
52 	dev_err(adapter->dev, "CMD_RESP: cmd %#x error, result=%#x\n",
53 		resp->command, resp->result);
54 
55 	if (adapter->curr_cmd->wait_q_enabled)
56 		adapter->cmd_wait_q.status = -1;
57 
58 	switch (le16_to_cpu(resp->command)) {
59 	case HostCmd_CMD_802_11_PS_MODE_ENH:
60 		pm = &resp->params.psmode_enh;
61 		dev_err(adapter->dev,
62 			"PS_MODE_ENH cmd failed: result=0x%x action=0x%X\n",
63 			resp->result, le16_to_cpu(pm->action));
64 		/* We do not re-try enter-ps command in ad-hoc mode. */
65 		if (le16_to_cpu(pm->action) == EN_AUTO_PS &&
66 		    (le16_to_cpu(pm->params.ps_bitmap) & BITMAP_STA_PS) &&
67 		    priv->bss_mode == NL80211_IFTYPE_ADHOC)
68 			adapter->ps_mode = MWIFIEX_802_11_POWER_MODE_CAM;
69 
70 		break;
71 	case HostCmd_CMD_802_11_SCAN:
72 	case HostCmd_CMD_802_11_SCAN_EXT:
73 		/* Cancel all pending scan command */
74 		spin_lock_irqsave(&adapter->scan_pending_q_lock, flags);
75 		list_for_each_entry_safe(cmd_node, tmp_node,
76 					 &adapter->scan_pending_q, list) {
77 			list_del(&cmd_node->list);
78 			spin_unlock_irqrestore(&adapter->scan_pending_q_lock,
79 					       flags);
80 			mwifiex_insert_cmd_to_free_q(adapter, cmd_node);
81 			spin_lock_irqsave(&adapter->scan_pending_q_lock, flags);
82 		}
83 		spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags);
84 
85 		spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
86 		adapter->scan_processing = false;
87 		spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
88 		break;
89 
90 	case HostCmd_CMD_MAC_CONTROL:
91 		break;
92 
93 	default:
94 		break;
95 	}
96 	/* Handling errors here */
97 	mwifiex_recycle_cmd_node(adapter, adapter->curr_cmd);
98 
99 	spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
100 	adapter->curr_cmd = NULL;
101 	spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
102 }
103 
104 /*
105  * This function handles the command response of get RSSI info.
106  *
107  * Handling includes changing the header fields into CPU format
108  * and saving the following parameters in driver -
109  *      - Last data and beacon RSSI value
110  *      - Average data and beacon RSSI value
111  *      - Last data and beacon NF value
112  *      - Average data and beacon NF value
113  *
114  * The parameters are send to the application as well, along with
115  * calculated SNR values.
116  */
mwifiex_ret_802_11_rssi_info(struct mwifiex_private * priv,struct host_cmd_ds_command * resp)117 static int mwifiex_ret_802_11_rssi_info(struct mwifiex_private *priv,
118 					struct host_cmd_ds_command *resp)
119 {
120 	struct host_cmd_ds_802_11_rssi_info_rsp *rssi_info_rsp =
121 						&resp->params.rssi_info_rsp;
122 	struct mwifiex_ds_misc_subsc_evt *subsc_evt =
123 						&priv->async_subsc_evt_storage;
124 
125 	priv->data_rssi_last = le16_to_cpu(rssi_info_rsp->data_rssi_last);
126 	priv->data_nf_last = le16_to_cpu(rssi_info_rsp->data_nf_last);
127 
128 	priv->data_rssi_avg = le16_to_cpu(rssi_info_rsp->data_rssi_avg);
129 	priv->data_nf_avg = le16_to_cpu(rssi_info_rsp->data_nf_avg);
130 
131 	priv->bcn_rssi_last = le16_to_cpu(rssi_info_rsp->bcn_rssi_last);
132 	priv->bcn_nf_last = le16_to_cpu(rssi_info_rsp->bcn_nf_last);
133 
134 	priv->bcn_rssi_avg = le16_to_cpu(rssi_info_rsp->bcn_rssi_avg);
135 	priv->bcn_nf_avg = le16_to_cpu(rssi_info_rsp->bcn_nf_avg);
136 
137 	if (priv->subsc_evt_rssi_state == EVENT_HANDLED)
138 		return 0;
139 
140 	memset(subsc_evt, 0x00, sizeof(struct mwifiex_ds_misc_subsc_evt));
141 
142 	/* Resubscribe low and high rssi events with new thresholds */
143 	subsc_evt->events = BITMASK_BCN_RSSI_LOW | BITMASK_BCN_RSSI_HIGH;
144 	subsc_evt->action = HostCmd_ACT_BITWISE_SET;
145 	if (priv->subsc_evt_rssi_state == RSSI_LOW_RECVD) {
146 		subsc_evt->bcn_l_rssi_cfg.abs_value = abs(priv->bcn_rssi_avg -
147 				priv->cqm_rssi_hyst);
148 		subsc_evt->bcn_h_rssi_cfg.abs_value = abs(priv->cqm_rssi_thold);
149 	} else if (priv->subsc_evt_rssi_state == RSSI_HIGH_RECVD) {
150 		subsc_evt->bcn_l_rssi_cfg.abs_value = abs(priv->cqm_rssi_thold);
151 		subsc_evt->bcn_h_rssi_cfg.abs_value = abs(priv->bcn_rssi_avg +
152 				priv->cqm_rssi_hyst);
153 	}
154 	subsc_evt->bcn_l_rssi_cfg.evt_freq = 1;
155 	subsc_evt->bcn_h_rssi_cfg.evt_freq = 1;
156 
157 	priv->subsc_evt_rssi_state = EVENT_HANDLED;
158 
159 	mwifiex_send_cmd(priv, HostCmd_CMD_802_11_SUBSCRIBE_EVENT,
160 			 0, 0, subsc_evt, false);
161 
162 	return 0;
163 }
164 
165 /*
166  * This function handles the command response of set/get SNMP
167  * MIB parameters.
168  *
169  * Handling includes changing the header fields into CPU format
170  * and saving the parameter in driver.
171  *
172  * The following parameters are supported -
173  *      - Fragmentation threshold
174  *      - RTS threshold
175  *      - Short retry limit
176  */
mwifiex_ret_802_11_snmp_mib(struct mwifiex_private * priv,struct host_cmd_ds_command * resp,u32 * data_buf)177 static int mwifiex_ret_802_11_snmp_mib(struct mwifiex_private *priv,
178 				       struct host_cmd_ds_command *resp,
179 				       u32 *data_buf)
180 {
181 	struct host_cmd_ds_802_11_snmp_mib *smib = &resp->params.smib;
182 	u16 oid = le16_to_cpu(smib->oid);
183 	u16 query_type = le16_to_cpu(smib->query_type);
184 	u32 ul_temp;
185 
186 	dev_dbg(priv->adapter->dev, "info: SNMP_RESP: oid value = %#x,"
187 		" query_type = %#x, buf size = %#x\n",
188 		oid, query_type, le16_to_cpu(smib->buf_size));
189 	if (query_type == HostCmd_ACT_GEN_GET) {
190 		ul_temp = le16_to_cpu(*((__le16 *) (smib->value)));
191 		if (data_buf)
192 			*data_buf = ul_temp;
193 		switch (oid) {
194 		case FRAG_THRESH_I:
195 			dev_dbg(priv->adapter->dev,
196 				"info: SNMP_RESP: FragThsd =%u\n", ul_temp);
197 			break;
198 		case RTS_THRESH_I:
199 			dev_dbg(priv->adapter->dev,
200 				"info: SNMP_RESP: RTSThsd =%u\n", ul_temp);
201 			break;
202 		case SHORT_RETRY_LIM_I:
203 			dev_dbg(priv->adapter->dev,
204 				"info: SNMP_RESP: TxRetryCount=%u\n", ul_temp);
205 			break;
206 		case DTIM_PERIOD_I:
207 			dev_dbg(priv->adapter->dev,
208 				"info: SNMP_RESP: DTIM period=%u\n", ul_temp);
209 		default:
210 			break;
211 		}
212 	}
213 
214 	return 0;
215 }
216 
217 /*
218  * This function handles the command response of get log request
219  *
220  * Handling includes changing the header fields into CPU format
221  * and sending the received parameters to application.
222  */
mwifiex_ret_get_log(struct mwifiex_private * priv,struct host_cmd_ds_command * resp,struct mwifiex_ds_get_stats * stats)223 static int mwifiex_ret_get_log(struct mwifiex_private *priv,
224 			       struct host_cmd_ds_command *resp,
225 			       struct mwifiex_ds_get_stats *stats)
226 {
227 	struct host_cmd_ds_802_11_get_log *get_log =
228 		&resp->params.get_log;
229 
230 	if (stats) {
231 		stats->mcast_tx_frame = le32_to_cpu(get_log->mcast_tx_frame);
232 		stats->failed = le32_to_cpu(get_log->failed);
233 		stats->retry = le32_to_cpu(get_log->retry);
234 		stats->multi_retry = le32_to_cpu(get_log->multi_retry);
235 		stats->frame_dup = le32_to_cpu(get_log->frame_dup);
236 		stats->rts_success = le32_to_cpu(get_log->rts_success);
237 		stats->rts_failure = le32_to_cpu(get_log->rts_failure);
238 		stats->ack_failure = le32_to_cpu(get_log->ack_failure);
239 		stats->rx_frag = le32_to_cpu(get_log->rx_frag);
240 		stats->mcast_rx_frame = le32_to_cpu(get_log->mcast_rx_frame);
241 		stats->fcs_error = le32_to_cpu(get_log->fcs_error);
242 		stats->tx_frame = le32_to_cpu(get_log->tx_frame);
243 		stats->wep_icv_error[0] =
244 			le32_to_cpu(get_log->wep_icv_err_cnt[0]);
245 		stats->wep_icv_error[1] =
246 			le32_to_cpu(get_log->wep_icv_err_cnt[1]);
247 		stats->wep_icv_error[2] =
248 			le32_to_cpu(get_log->wep_icv_err_cnt[2]);
249 		stats->wep_icv_error[3] =
250 			le32_to_cpu(get_log->wep_icv_err_cnt[3]);
251 	}
252 
253 	return 0;
254 }
255 
256 /*
257  * This function handles the command response of set/get Tx rate
258  * configurations.
259  *
260  * Handling includes changing the header fields into CPU format
261  * and saving the following parameters in driver -
262  *      - DSSS rate bitmap
263  *      - OFDM rate bitmap
264  *      - HT MCS rate bitmaps
265  *
266  * Based on the new rate bitmaps, the function re-evaluates if
267  * auto data rate has been activated. If not, it sends another
268  * query to the firmware to get the current Tx data rate.
269  */
mwifiex_ret_tx_rate_cfg(struct mwifiex_private * priv,struct host_cmd_ds_command * resp)270 static int mwifiex_ret_tx_rate_cfg(struct mwifiex_private *priv,
271 				   struct host_cmd_ds_command *resp)
272 {
273 	struct host_cmd_ds_tx_rate_cfg *rate_cfg = &resp->params.tx_rate_cfg;
274 	struct mwifiex_rate_scope *rate_scope;
275 	struct mwifiex_ie_types_header *head;
276 	u16 tlv, tlv_buf_len, tlv_buf_left;
277 	u8 *tlv_buf;
278 	u32 i;
279 
280 	tlv_buf = ((u8 *)rate_cfg) + sizeof(struct host_cmd_ds_tx_rate_cfg);
281 	tlv_buf_left = le16_to_cpu(resp->size) - S_DS_GEN - sizeof(*rate_cfg);
282 
283 	while (tlv_buf_left >= sizeof(*head)) {
284 		head = (struct mwifiex_ie_types_header *)tlv_buf;
285 		tlv = le16_to_cpu(head->type);
286 		tlv_buf_len = le16_to_cpu(head->len);
287 
288 		if (tlv_buf_left < (sizeof(*head) + tlv_buf_len))
289 			break;
290 
291 		switch (tlv) {
292 		case TLV_TYPE_RATE_SCOPE:
293 			rate_scope = (struct mwifiex_rate_scope *) tlv_buf;
294 			priv->bitmap_rates[0] =
295 				le16_to_cpu(rate_scope->hr_dsss_rate_bitmap);
296 			priv->bitmap_rates[1] =
297 				le16_to_cpu(rate_scope->ofdm_rate_bitmap);
298 			for (i = 0;
299 			     i <
300 			     sizeof(rate_scope->ht_mcs_rate_bitmap) /
301 			     sizeof(u16); i++)
302 				priv->bitmap_rates[2 + i] =
303 					le16_to_cpu(rate_scope->
304 						    ht_mcs_rate_bitmap[i]);
305 
306 			if (priv->adapter->fw_api_ver == MWIFIEX_FW_V15) {
307 				for (i = 0; i < ARRAY_SIZE(rate_scope->
308 							   vht_mcs_rate_bitmap);
309 				     i++)
310 					priv->bitmap_rates[10 + i] =
311 					    le16_to_cpu(rate_scope->
312 							vht_mcs_rate_bitmap[i]);
313 			}
314 			break;
315 			/* Add RATE_DROP tlv here */
316 		}
317 
318 		tlv_buf += (sizeof(*head) + tlv_buf_len);
319 		tlv_buf_left -= (sizeof(*head) + tlv_buf_len);
320 	}
321 
322 	priv->is_data_rate_auto = mwifiex_is_rate_auto(priv);
323 
324 	if (priv->is_data_rate_auto)
325 		priv->data_rate = 0;
326 	else
327 		return mwifiex_send_cmd(priv, HostCmd_CMD_802_11_TX_RATE_QUERY,
328 					HostCmd_ACT_GEN_GET, 0, NULL, false);
329 
330 	return 0;
331 }
332 
333 /*
334  * This function handles the command response of get Tx power level.
335  *
336  * Handling includes saving the maximum and minimum Tx power levels
337  * in driver, as well as sending the values to user.
338  */
mwifiex_get_power_level(struct mwifiex_private * priv,void * data_buf)339 static int mwifiex_get_power_level(struct mwifiex_private *priv, void *data_buf)
340 {
341 	int length, max_power = -1, min_power = -1;
342 	struct mwifiex_types_power_group *pg_tlv_hdr;
343 	struct mwifiex_power_group *pg;
344 
345 	if (!data_buf)
346 		return -1;
347 
348 	pg_tlv_hdr = (struct mwifiex_types_power_group *)((u8 *)data_buf);
349 	pg = (struct mwifiex_power_group *)
350 		((u8 *) pg_tlv_hdr + sizeof(struct mwifiex_types_power_group));
351 	length = le16_to_cpu(pg_tlv_hdr->length);
352 
353 	/* At least one structure required to update power */
354 	if (length < sizeof(struct mwifiex_power_group))
355 		return 0;
356 
357 	max_power = pg->power_max;
358 	min_power = pg->power_min;
359 	length -= sizeof(struct mwifiex_power_group);
360 
361 	while (length >= sizeof(struct mwifiex_power_group)) {
362 		pg++;
363 		if (max_power < pg->power_max)
364 			max_power = pg->power_max;
365 
366 		if (min_power > pg->power_min)
367 			min_power = pg->power_min;
368 
369 		length -= sizeof(struct mwifiex_power_group);
370 	}
371 	priv->min_tx_power_level = (u8) min_power;
372 	priv->max_tx_power_level = (u8) max_power;
373 
374 	return 0;
375 }
376 
377 /*
378  * This function handles the command response of set/get Tx power
379  * configurations.
380  *
381  * Handling includes changing the header fields into CPU format
382  * and saving the current Tx power level in driver.
383  */
mwifiex_ret_tx_power_cfg(struct mwifiex_private * priv,struct host_cmd_ds_command * resp)384 static int mwifiex_ret_tx_power_cfg(struct mwifiex_private *priv,
385 				    struct host_cmd_ds_command *resp)
386 {
387 	struct mwifiex_adapter *adapter = priv->adapter;
388 	struct host_cmd_ds_txpwr_cfg *txp_cfg = &resp->params.txp_cfg;
389 	struct mwifiex_types_power_group *pg_tlv_hdr;
390 	struct mwifiex_power_group *pg;
391 	u16 action = le16_to_cpu(txp_cfg->action);
392 	u16 tlv_buf_left;
393 
394 	pg_tlv_hdr = (struct mwifiex_types_power_group *)
395 		((u8 *)txp_cfg +
396 		 sizeof(struct host_cmd_ds_txpwr_cfg));
397 
398 	pg = (struct mwifiex_power_group *)
399 		((u8 *)pg_tlv_hdr +
400 		 sizeof(struct mwifiex_types_power_group));
401 
402 	tlv_buf_left = le16_to_cpu(resp->size) - S_DS_GEN - sizeof(*txp_cfg);
403 	if (tlv_buf_left <
404 			le16_to_cpu(pg_tlv_hdr->length) + sizeof(*pg_tlv_hdr))
405 		return 0;
406 
407 	switch (action) {
408 	case HostCmd_ACT_GEN_GET:
409 		if (adapter->hw_status == MWIFIEX_HW_STATUS_INITIALIZING)
410 			mwifiex_get_power_level(priv, pg_tlv_hdr);
411 
412 		priv->tx_power_level = (u16) pg->power_min;
413 		break;
414 
415 	case HostCmd_ACT_GEN_SET:
416 		if (!le32_to_cpu(txp_cfg->mode))
417 			break;
418 
419 		if (pg->power_max == pg->power_min)
420 			priv->tx_power_level = (u16) pg->power_min;
421 		break;
422 	default:
423 		dev_err(adapter->dev, "CMD_RESP: unknown cmd action %d\n",
424 			action);
425 		return 0;
426 	}
427 	dev_dbg(adapter->dev,
428 		"info: Current TxPower Level = %d, Max Power=%d, Min Power=%d\n",
429 	       priv->tx_power_level, priv->max_tx_power_level,
430 	       priv->min_tx_power_level);
431 
432 	return 0;
433 }
434 
435 /*
436  * This function handles the command response of get RF Tx power.
437  */
mwifiex_ret_rf_tx_power(struct mwifiex_private * priv,struct host_cmd_ds_command * resp)438 static int mwifiex_ret_rf_tx_power(struct mwifiex_private *priv,
439 				   struct host_cmd_ds_command *resp)
440 {
441 	struct host_cmd_ds_rf_tx_pwr *txp = &resp->params.txp;
442 	u16 action = le16_to_cpu(txp->action);
443 
444 	priv->tx_power_level = le16_to_cpu(txp->cur_level);
445 
446 	if (action == HostCmd_ACT_GEN_GET) {
447 		priv->max_tx_power_level = txp->max_power;
448 		priv->min_tx_power_level = txp->min_power;
449 	}
450 
451 	dev_dbg(priv->adapter->dev,
452 		"Current TxPower Level=%d, Max Power=%d, Min Power=%d\n",
453 		priv->tx_power_level, priv->max_tx_power_level,
454 		priv->min_tx_power_level);
455 
456 	return 0;
457 }
458 
459 /*
460  * This function handles the command response of set rf antenna
461  */
mwifiex_ret_rf_antenna(struct mwifiex_private * priv,struct host_cmd_ds_command * resp)462 static int mwifiex_ret_rf_antenna(struct mwifiex_private *priv,
463 				  struct host_cmd_ds_command *resp)
464 {
465 	struct host_cmd_ds_rf_ant_mimo *ant_mimo = &resp->params.ant_mimo;
466 	struct host_cmd_ds_rf_ant_siso *ant_siso = &resp->params.ant_siso;
467 	struct mwifiex_adapter *adapter = priv->adapter;
468 
469 	if (adapter->hw_dev_mcs_support == HT_STREAM_2X2)
470 		dev_dbg(adapter->dev,
471 			"RF_ANT_RESP: Tx action = 0x%x, Tx Mode = 0x%04x"
472 			" Rx action = 0x%x, Rx Mode = 0x%04x\n",
473 			le16_to_cpu(ant_mimo->action_tx),
474 			le16_to_cpu(ant_mimo->tx_ant_mode),
475 			le16_to_cpu(ant_mimo->action_rx),
476 			le16_to_cpu(ant_mimo->rx_ant_mode));
477 	else
478 		dev_dbg(adapter->dev,
479 			"RF_ANT_RESP: action = 0x%x, Mode = 0x%04x\n",
480 			le16_to_cpu(ant_siso->action),
481 			le16_to_cpu(ant_siso->ant_mode));
482 
483 	return 0;
484 }
485 
486 /*
487  * This function handles the command response of set/get MAC address.
488  *
489  * Handling includes saving the MAC address in driver.
490  */
mwifiex_ret_802_11_mac_address(struct mwifiex_private * priv,struct host_cmd_ds_command * resp)491 static int mwifiex_ret_802_11_mac_address(struct mwifiex_private *priv,
492 					  struct host_cmd_ds_command *resp)
493 {
494 	struct host_cmd_ds_802_11_mac_address *cmd_mac_addr =
495 							&resp->params.mac_addr;
496 
497 	memcpy(priv->curr_addr, cmd_mac_addr->mac_addr, ETH_ALEN);
498 
499 	dev_dbg(priv->adapter->dev,
500 		"info: set mac address: %pM\n", priv->curr_addr);
501 
502 	return 0;
503 }
504 
505 /*
506  * This function handles the command response of set/get MAC multicast
507  * address.
508  */
mwifiex_ret_mac_multicast_adr(struct mwifiex_private * priv,struct host_cmd_ds_command * resp)509 static int mwifiex_ret_mac_multicast_adr(struct mwifiex_private *priv,
510 					 struct host_cmd_ds_command *resp)
511 {
512 	return 0;
513 }
514 
515 /*
516  * This function handles the command response of get Tx rate query.
517  *
518  * Handling includes changing the header fields into CPU format
519  * and saving the Tx rate and HT information parameters in driver.
520  *
521  * Both rate configuration and current data rate can be retrieved
522  * with this request.
523  */
mwifiex_ret_802_11_tx_rate_query(struct mwifiex_private * priv,struct host_cmd_ds_command * resp)524 static int mwifiex_ret_802_11_tx_rate_query(struct mwifiex_private *priv,
525 					    struct host_cmd_ds_command *resp)
526 {
527 	priv->tx_rate = resp->params.tx_rate.tx_rate;
528 	priv->tx_htinfo = resp->params.tx_rate.ht_info;
529 	if (!priv->is_data_rate_auto)
530 		priv->data_rate =
531 			mwifiex_index_to_data_rate(priv, priv->tx_rate,
532 						   priv->tx_htinfo);
533 
534 	return 0;
535 }
536 
537 /*
538  * This function handles the command response of a deauthenticate
539  * command.
540  *
541  * If the deauthenticated MAC matches the current BSS MAC, the connection
542  * state is reset.
543  */
mwifiex_ret_802_11_deauthenticate(struct mwifiex_private * priv,struct host_cmd_ds_command * resp)544 static int mwifiex_ret_802_11_deauthenticate(struct mwifiex_private *priv,
545 					     struct host_cmd_ds_command *resp)
546 {
547 	struct mwifiex_adapter *adapter = priv->adapter;
548 
549 	adapter->dbg.num_cmd_deauth++;
550 	if (!memcmp(resp->params.deauth.mac_addr,
551 		    &priv->curr_bss_params.bss_descriptor.mac_address,
552 		    sizeof(resp->params.deauth.mac_addr)))
553 		mwifiex_reset_connect_state(priv, WLAN_REASON_DEAUTH_LEAVING);
554 
555 	return 0;
556 }
557 
558 /*
559  * This function handles the command response of ad-hoc stop.
560  *
561  * The function resets the connection state in driver.
562  */
mwifiex_ret_802_11_ad_hoc_stop(struct mwifiex_private * priv,struct host_cmd_ds_command * resp)563 static int mwifiex_ret_802_11_ad_hoc_stop(struct mwifiex_private *priv,
564 					  struct host_cmd_ds_command *resp)
565 {
566 	mwifiex_reset_connect_state(priv, WLAN_REASON_DEAUTH_LEAVING);
567 	return 0;
568 }
569 
570 /*
571  * This function handles the command response of set/get v1 key material.
572  *
573  * Handling includes updating the driver parameters to reflect the
574  * changes.
575  */
mwifiex_ret_802_11_key_material_v1(struct mwifiex_private * priv,struct host_cmd_ds_command * resp)576 static int mwifiex_ret_802_11_key_material_v1(struct mwifiex_private *priv,
577 					      struct host_cmd_ds_command *resp)
578 {
579 	struct host_cmd_ds_802_11_key_material *key =
580 						&resp->params.key_material;
581 
582 	if (le16_to_cpu(key->action) == HostCmd_ACT_GEN_SET) {
583 		if ((le16_to_cpu(key->key_param_set.key_info) & KEY_MCAST)) {
584 			dev_dbg(priv->adapter->dev, "info: key: GTK is set\n");
585 			priv->wpa_is_gtk_set = true;
586 			priv->scan_block = false;
587 		}
588 	}
589 
590 	memset(priv->aes_key.key_param_set.key, 0,
591 	       sizeof(key->key_param_set.key));
592 	priv->aes_key.key_param_set.key_len = key->key_param_set.key_len;
593 	memcpy(priv->aes_key.key_param_set.key, key->key_param_set.key,
594 	       le16_to_cpu(priv->aes_key.key_param_set.key_len));
595 
596 	return 0;
597 }
598 
599 /*
600  * This function handles the command response of set/get v2 key material.
601  *
602  * Handling includes updating the driver parameters to reflect the
603  * changes.
604  */
mwifiex_ret_802_11_key_material_v2(struct mwifiex_private * priv,struct host_cmd_ds_command * resp)605 static int mwifiex_ret_802_11_key_material_v2(struct mwifiex_private *priv,
606 					      struct host_cmd_ds_command *resp)
607 {
608 	struct host_cmd_ds_802_11_key_material_v2 *key_v2;
609 	__le16 len;
610 
611 	key_v2 = &resp->params.key_material_v2;
612 	if (le16_to_cpu(key_v2->action) == HostCmd_ACT_GEN_SET) {
613 		if ((le16_to_cpu(key_v2->key_param_set.key_info) & KEY_MCAST)) {
614 			dev_dbg(priv->adapter->dev, "info: key: GTK is set\n");
615 			priv->wpa_is_gtk_set = true;
616 			priv->scan_block = false;
617 		}
618 	}
619 
620 	if (key_v2->key_param_set.key_type != KEY_TYPE_ID_AES)
621 		return 0;
622 
623 	memset(priv->aes_key_v2.key_param_set.key_params.aes.key, 0,
624 	       WLAN_KEY_LEN_CCMP);
625 	priv->aes_key_v2.key_param_set.key_params.aes.key_len =
626 				key_v2->key_param_set.key_params.aes.key_len;
627 	len = priv->aes_key_v2.key_param_set.key_params.aes.key_len;
628 	memcpy(priv->aes_key_v2.key_param_set.key_params.aes.key,
629 	       key_v2->key_param_set.key_params.aes.key, le16_to_cpu(len));
630 
631 	return 0;
632 }
633 
634 /* Wrapper function for processing response of key material command */
mwifiex_ret_802_11_key_material(struct mwifiex_private * priv,struct host_cmd_ds_command * resp)635 static int mwifiex_ret_802_11_key_material(struct mwifiex_private *priv,
636 					   struct host_cmd_ds_command *resp)
637 {
638 	if (priv->adapter->key_api_major_ver == KEY_API_VER_MAJOR_V2)
639 		return mwifiex_ret_802_11_key_material_v2(priv, resp);
640 	else
641 		return mwifiex_ret_802_11_key_material_v1(priv, resp);
642 }
643 
644 /*
645  * This function handles the command response of get 11d domain information.
646  */
mwifiex_ret_802_11d_domain_info(struct mwifiex_private * priv,struct host_cmd_ds_command * resp)647 static int mwifiex_ret_802_11d_domain_info(struct mwifiex_private *priv,
648 					   struct host_cmd_ds_command *resp)
649 {
650 	struct host_cmd_ds_802_11d_domain_info_rsp *domain_info =
651 		&resp->params.domain_info_resp;
652 	struct mwifiex_ietypes_domain_param_set *domain = &domain_info->domain;
653 	u16 action = le16_to_cpu(domain_info->action);
654 	u8 no_of_triplet;
655 
656 	no_of_triplet = (u8) ((le16_to_cpu(domain->header.len)
657 				- IEEE80211_COUNTRY_STRING_LEN)
658 			      / sizeof(struct ieee80211_country_ie_triplet));
659 
660 	dev_dbg(priv->adapter->dev,
661 		"info: 11D Domain Info Resp: no_of_triplet=%d\n",
662 		no_of_triplet);
663 
664 	if (no_of_triplet > MWIFIEX_MAX_TRIPLET_802_11D) {
665 		dev_warn(priv->adapter->dev,
666 			 "11D: invalid number of triplets %d returned\n",
667 			 no_of_triplet);
668 		return -1;
669 	}
670 
671 	switch (action) {
672 	case HostCmd_ACT_GEN_SET:  /* Proc Set Action */
673 		break;
674 	case HostCmd_ACT_GEN_GET:
675 		break;
676 	default:
677 		dev_err(priv->adapter->dev,
678 			"11D: invalid action:%d\n", domain_info->action);
679 		return -1;
680 	}
681 
682 	return 0;
683 }
684 
685 /*
686  * This function handles the command response of get extended version.
687  *
688  * Handling includes forming the extended version string and sending it
689  * to application.
690  */
mwifiex_ret_ver_ext(struct mwifiex_private * priv,struct host_cmd_ds_command * resp,struct host_cmd_ds_version_ext * version_ext)691 static int mwifiex_ret_ver_ext(struct mwifiex_private *priv,
692 			       struct host_cmd_ds_command *resp,
693 			       struct host_cmd_ds_version_ext *version_ext)
694 {
695 	struct host_cmd_ds_version_ext *ver_ext = &resp->params.verext;
696 
697 	if (version_ext) {
698 		version_ext->version_str_sel = ver_ext->version_str_sel;
699 		memcpy(version_ext->version_str, ver_ext->version_str,
700 		       sizeof(char) * 128);
701 		memcpy(priv->version_str, ver_ext->version_str, 128);
702 	}
703 	return 0;
704 }
705 
706 /*
707  * This function handles the command response of remain on channel.
708  */
709 static int
mwifiex_ret_remain_on_chan(struct mwifiex_private * priv,struct host_cmd_ds_command * resp,struct host_cmd_ds_remain_on_chan * roc_cfg)710 mwifiex_ret_remain_on_chan(struct mwifiex_private *priv,
711 			   struct host_cmd_ds_command *resp,
712 			   struct host_cmd_ds_remain_on_chan *roc_cfg)
713 {
714 	struct host_cmd_ds_remain_on_chan *resp_cfg = &resp->params.roc_cfg;
715 
716 	if (roc_cfg)
717 		memcpy(roc_cfg, resp_cfg, sizeof(*roc_cfg));
718 
719 	return 0;
720 }
721 
722 /*
723  * This function handles the command response of P2P mode cfg.
724  */
725 static int
mwifiex_ret_p2p_mode_cfg(struct mwifiex_private * priv,struct host_cmd_ds_command * resp,void * data_buf)726 mwifiex_ret_p2p_mode_cfg(struct mwifiex_private *priv,
727 			 struct host_cmd_ds_command *resp,
728 			 void *data_buf)
729 {
730 	struct host_cmd_ds_p2p_mode_cfg *mode_cfg = &resp->params.mode_cfg;
731 
732 	if (data_buf)
733 		*((u16 *)data_buf) = le16_to_cpu(mode_cfg->mode);
734 
735 	return 0;
736 }
737 
738 /*
739  * This function handles the command response of register access.
740  *
741  * The register value and offset are returned to the user. For EEPROM
742  * access, the byte count is also returned.
743  */
mwifiex_ret_reg_access(u16 type,struct host_cmd_ds_command * resp,void * data_buf)744 static int mwifiex_ret_reg_access(u16 type, struct host_cmd_ds_command *resp,
745 				  void *data_buf)
746 {
747 	struct mwifiex_ds_reg_rw *reg_rw;
748 	struct mwifiex_ds_read_eeprom *eeprom;
749 	union reg {
750 		struct host_cmd_ds_mac_reg_access *mac;
751 		struct host_cmd_ds_bbp_reg_access *bbp;
752 		struct host_cmd_ds_rf_reg_access *rf;
753 		struct host_cmd_ds_pmic_reg_access *pmic;
754 		struct host_cmd_ds_802_11_eeprom_access *eeprom;
755 	} r;
756 
757 	if (!data_buf)
758 		return 0;
759 
760 	reg_rw = data_buf;
761 	eeprom = data_buf;
762 	switch (type) {
763 	case HostCmd_CMD_MAC_REG_ACCESS:
764 		r.mac = &resp->params.mac_reg;
765 		reg_rw->offset = cpu_to_le32((u32) le16_to_cpu(r.mac->offset));
766 		reg_rw->value = r.mac->value;
767 		break;
768 	case HostCmd_CMD_BBP_REG_ACCESS:
769 		r.bbp = &resp->params.bbp_reg;
770 		reg_rw->offset = cpu_to_le32((u32) le16_to_cpu(r.bbp->offset));
771 		reg_rw->value = cpu_to_le32((u32) r.bbp->value);
772 		break;
773 
774 	case HostCmd_CMD_RF_REG_ACCESS:
775 		r.rf = &resp->params.rf_reg;
776 		reg_rw->offset = cpu_to_le32((u32) le16_to_cpu(r.rf->offset));
777 		reg_rw->value = cpu_to_le32((u32) r.bbp->value);
778 		break;
779 	case HostCmd_CMD_PMIC_REG_ACCESS:
780 		r.pmic = &resp->params.pmic_reg;
781 		reg_rw->offset = cpu_to_le32((u32) le16_to_cpu(r.pmic->offset));
782 		reg_rw->value = cpu_to_le32((u32) r.pmic->value);
783 		break;
784 	case HostCmd_CMD_CAU_REG_ACCESS:
785 		r.rf = &resp->params.rf_reg;
786 		reg_rw->offset = cpu_to_le32((u32) le16_to_cpu(r.rf->offset));
787 		reg_rw->value = cpu_to_le32((u32) r.rf->value);
788 		break;
789 	case HostCmd_CMD_802_11_EEPROM_ACCESS:
790 		r.eeprom = &resp->params.eeprom;
791 		pr_debug("info: EEPROM read len=%x\n", r.eeprom->byte_count);
792 		if (le16_to_cpu(eeprom->byte_count) <
793 		    le16_to_cpu(r.eeprom->byte_count)) {
794 			eeprom->byte_count = cpu_to_le16(0);
795 			pr_debug("info: EEPROM read length is too big\n");
796 			return -1;
797 		}
798 		eeprom->offset = r.eeprom->offset;
799 		eeprom->byte_count = r.eeprom->byte_count;
800 		if (le16_to_cpu(eeprom->byte_count) > 0)
801 			memcpy(&eeprom->value, &r.eeprom->value,
802 			       le16_to_cpu(r.eeprom->byte_count));
803 
804 		break;
805 	default:
806 		return -1;
807 	}
808 	return 0;
809 }
810 
811 /*
812  * This function handles the command response of get IBSS coalescing status.
813  *
814  * If the received BSSID is different than the current one, the current BSSID,
815  * beacon interval, ATIM window and ERP information are updated, along with
816  * changing the ad-hoc state accordingly.
817  */
mwifiex_ret_ibss_coalescing_status(struct mwifiex_private * priv,struct host_cmd_ds_command * resp)818 static int mwifiex_ret_ibss_coalescing_status(struct mwifiex_private *priv,
819 					      struct host_cmd_ds_command *resp)
820 {
821 	struct host_cmd_ds_802_11_ibss_status *ibss_coal_resp =
822 					&(resp->params.ibss_coalescing);
823 
824 	if (le16_to_cpu(ibss_coal_resp->action) == HostCmd_ACT_GEN_SET)
825 		return 0;
826 
827 	dev_dbg(priv->adapter->dev,
828 		"info: new BSSID %pM\n", ibss_coal_resp->bssid);
829 
830 	/* If rsp has NULL BSSID, Just return..... No Action */
831 	if (is_zero_ether_addr(ibss_coal_resp->bssid)) {
832 		dev_warn(priv->adapter->dev, "new BSSID is NULL\n");
833 		return 0;
834 	}
835 
836 	/* If BSSID is diff, modify current BSS parameters */
837 	if (!ether_addr_equal(priv->curr_bss_params.bss_descriptor.mac_address, ibss_coal_resp->bssid)) {
838 		/* BSSID */
839 		memcpy(priv->curr_bss_params.bss_descriptor.mac_address,
840 		       ibss_coal_resp->bssid, ETH_ALEN);
841 
842 		/* Beacon Interval */
843 		priv->curr_bss_params.bss_descriptor.beacon_period
844 			= le16_to_cpu(ibss_coal_resp->beacon_interval);
845 
846 		/* ERP Information */
847 		priv->curr_bss_params.bss_descriptor.erp_flags =
848 			(u8) le16_to_cpu(ibss_coal_resp->use_g_rate_protect);
849 
850 		priv->adhoc_state = ADHOC_COALESCED;
851 	}
852 
853 	return 0;
854 }
mwifiex_ret_tdls_oper(struct mwifiex_private * priv,struct host_cmd_ds_command * resp)855 static int mwifiex_ret_tdls_oper(struct mwifiex_private *priv,
856 				 struct host_cmd_ds_command *resp)
857 {
858 	struct host_cmd_ds_tdls_oper *cmd_tdls_oper = &resp->params.tdls_oper;
859 	u16 reason = le16_to_cpu(cmd_tdls_oper->reason);
860 	u16 action = le16_to_cpu(cmd_tdls_oper->tdls_action);
861 	struct mwifiex_sta_node *node =
862 			   mwifiex_get_sta_entry(priv, cmd_tdls_oper->peer_mac);
863 
864 	switch (action) {
865 	case ACT_TDLS_DELETE:
866 		if (reason) {
867 			if (!node || reason == TDLS_ERR_LINK_NONEXISTENT)
868 				dev_dbg(priv->adapter->dev,
869 					"TDLS link delete for %pM failed: reason %d\n",
870 					cmd_tdls_oper->peer_mac, reason);
871 			else
872 				dev_err(priv->adapter->dev,
873 					"TDLS link delete for %pM failed: reason %d\n",
874 					cmd_tdls_oper->peer_mac, reason);
875 		} else {
876 			dev_dbg(priv->adapter->dev,
877 				"TDLS link delete for %pM successful\n",
878 				cmd_tdls_oper->peer_mac);
879 		}
880 		break;
881 	case ACT_TDLS_CREATE:
882 		if (reason) {
883 			dev_err(priv->adapter->dev,
884 				"TDLS link creation for %pM failed: reason %d",
885 				cmd_tdls_oper->peer_mac, reason);
886 			if (node && reason != TDLS_ERR_LINK_EXISTS)
887 				node->tdls_status = TDLS_SETUP_FAILURE;
888 		} else {
889 			dev_dbg(priv->adapter->dev,
890 				"TDLS link creation for %pM successful",
891 				cmd_tdls_oper->peer_mac);
892 		}
893 		break;
894 	case ACT_TDLS_CONFIG:
895 		if (reason) {
896 			dev_err(priv->adapter->dev,
897 				"TDLS link config for %pM failed, reason %d\n",
898 				cmd_tdls_oper->peer_mac, reason);
899 			if (node)
900 				node->tdls_status = TDLS_SETUP_FAILURE;
901 		} else {
902 			dev_dbg(priv->adapter->dev,
903 				"TDLS link config for %pM successful\n",
904 				cmd_tdls_oper->peer_mac);
905 		}
906 		break;
907 	default:
908 		dev_err(priv->adapter->dev,
909 			"Unknown TDLS command action response %d", action);
910 		return -1;
911 	}
912 
913 	return 0;
914 }
915 /*
916  * This function handles the command response for subscribe event command.
917  */
mwifiex_ret_subsc_evt(struct mwifiex_private * priv,struct host_cmd_ds_command * resp)918 static int mwifiex_ret_subsc_evt(struct mwifiex_private *priv,
919 				 struct host_cmd_ds_command *resp)
920 {
921 	struct host_cmd_ds_802_11_subsc_evt *cmd_sub_event =
922 		&resp->params.subsc_evt;
923 
924 	/* For every subscribe event command (Get/Set/Clear), FW reports the
925 	 * current set of subscribed events*/
926 	dev_dbg(priv->adapter->dev, "Bitmap of currently subscribed events: %16x\n",
927 		le16_to_cpu(cmd_sub_event->events));
928 
929 	return 0;
930 }
931 
932 /* This function handles the command response of set_cfg_data */
mwifiex_ret_cfg_data(struct mwifiex_private * priv,struct host_cmd_ds_command * resp)933 static int mwifiex_ret_cfg_data(struct mwifiex_private *priv,
934 				struct host_cmd_ds_command *resp)
935 {
936 	if (resp->result != HostCmd_RESULT_OK) {
937 		dev_err(priv->adapter->dev, "Cal data cmd resp failed\n");
938 		return -1;
939 	}
940 
941 	return 0;
942 }
943 
944 /*
945  * This function handles the command responses.
946  *
947  * This is a generic function, which calls command specific
948  * response handlers based on the command ID.
949  */
mwifiex_process_sta_cmdresp(struct mwifiex_private * priv,u16 cmdresp_no,struct host_cmd_ds_command * resp)950 int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, u16 cmdresp_no,
951 				struct host_cmd_ds_command *resp)
952 {
953 	int ret = 0;
954 	struct mwifiex_adapter *adapter = priv->adapter;
955 	void *data_buf = adapter->curr_cmd->data_buf;
956 
957 	/* If the command is not successful, cleanup and return failure */
958 	if (resp->result != HostCmd_RESULT_OK) {
959 		mwifiex_process_cmdresp_error(priv, resp);
960 		return -1;
961 	}
962 	/* Command successful, handle response */
963 	switch (cmdresp_no) {
964 	case HostCmd_CMD_GET_HW_SPEC:
965 		ret = mwifiex_ret_get_hw_spec(priv, resp);
966 		break;
967 	case HostCmd_CMD_CFG_DATA:
968 		ret = mwifiex_ret_cfg_data(priv, resp);
969 		break;
970 	case HostCmd_CMD_MAC_CONTROL:
971 		break;
972 	case HostCmd_CMD_802_11_MAC_ADDRESS:
973 		ret = mwifiex_ret_802_11_mac_address(priv, resp);
974 		break;
975 	case HostCmd_CMD_MAC_MULTICAST_ADR:
976 		ret = mwifiex_ret_mac_multicast_adr(priv, resp);
977 		break;
978 	case HostCmd_CMD_TX_RATE_CFG:
979 		ret = mwifiex_ret_tx_rate_cfg(priv, resp);
980 		break;
981 	case HostCmd_CMD_802_11_SCAN:
982 		ret = mwifiex_ret_802_11_scan(priv, resp);
983 		adapter->curr_cmd->wait_q_enabled = false;
984 		break;
985 	case HostCmd_CMD_802_11_SCAN_EXT:
986 		ret = mwifiex_ret_802_11_scan_ext(priv);
987 		adapter->curr_cmd->wait_q_enabled = false;
988 		break;
989 	case HostCmd_CMD_802_11_BG_SCAN_QUERY:
990 		ret = mwifiex_ret_802_11_scan(priv, resp);
991 		dev_dbg(adapter->dev,
992 			"info: CMD_RESP: BG_SCAN result is ready!\n");
993 		break;
994 	case HostCmd_CMD_TXPWR_CFG:
995 		ret = mwifiex_ret_tx_power_cfg(priv, resp);
996 		break;
997 	case HostCmd_CMD_RF_TX_PWR:
998 		ret = mwifiex_ret_rf_tx_power(priv, resp);
999 		break;
1000 	case HostCmd_CMD_RF_ANTENNA:
1001 		ret = mwifiex_ret_rf_antenna(priv, resp);
1002 		break;
1003 	case HostCmd_CMD_802_11_PS_MODE_ENH:
1004 		ret = mwifiex_ret_enh_power_mode(priv, resp, data_buf);
1005 		break;
1006 	case HostCmd_CMD_802_11_HS_CFG_ENH:
1007 		ret = mwifiex_ret_802_11_hs_cfg(priv, resp);
1008 		break;
1009 	case HostCmd_CMD_802_11_ASSOCIATE:
1010 		ret = mwifiex_ret_802_11_associate(priv, resp);
1011 		break;
1012 	case HostCmd_CMD_802_11_DEAUTHENTICATE:
1013 		ret = mwifiex_ret_802_11_deauthenticate(priv, resp);
1014 		break;
1015 	case HostCmd_CMD_802_11_AD_HOC_START:
1016 	case HostCmd_CMD_802_11_AD_HOC_JOIN:
1017 		ret = mwifiex_ret_802_11_ad_hoc(priv, resp);
1018 		break;
1019 	case HostCmd_CMD_802_11_AD_HOC_STOP:
1020 		ret = mwifiex_ret_802_11_ad_hoc_stop(priv, resp);
1021 		break;
1022 	case HostCmd_CMD_802_11_GET_LOG:
1023 		ret = mwifiex_ret_get_log(priv, resp, data_buf);
1024 		break;
1025 	case HostCmd_CMD_RSSI_INFO:
1026 		ret = mwifiex_ret_802_11_rssi_info(priv, resp);
1027 		break;
1028 	case HostCmd_CMD_802_11_SNMP_MIB:
1029 		ret = mwifiex_ret_802_11_snmp_mib(priv, resp, data_buf);
1030 		break;
1031 	case HostCmd_CMD_802_11_TX_RATE_QUERY:
1032 		ret = mwifiex_ret_802_11_tx_rate_query(priv, resp);
1033 		break;
1034 	case HostCmd_CMD_VERSION_EXT:
1035 		ret = mwifiex_ret_ver_ext(priv, resp, data_buf);
1036 		break;
1037 	case HostCmd_CMD_REMAIN_ON_CHAN:
1038 		ret = mwifiex_ret_remain_on_chan(priv, resp, data_buf);
1039 		break;
1040 	case HostCmd_CMD_11AC_CFG:
1041 		break;
1042 	case HostCmd_CMD_P2P_MODE_CFG:
1043 		ret = mwifiex_ret_p2p_mode_cfg(priv, resp, data_buf);
1044 		break;
1045 	case HostCmd_CMD_MGMT_FRAME_REG:
1046 	case HostCmd_CMD_FUNC_INIT:
1047 	case HostCmd_CMD_FUNC_SHUTDOWN:
1048 		break;
1049 	case HostCmd_CMD_802_11_KEY_MATERIAL:
1050 		ret = mwifiex_ret_802_11_key_material(priv, resp);
1051 		break;
1052 	case HostCmd_CMD_802_11D_DOMAIN_INFO:
1053 		ret = mwifiex_ret_802_11d_domain_info(priv, resp);
1054 		break;
1055 	case HostCmd_CMD_11N_ADDBA_REQ:
1056 		ret = mwifiex_ret_11n_addba_req(priv, resp);
1057 		break;
1058 	case HostCmd_CMD_11N_DELBA:
1059 		ret = mwifiex_ret_11n_delba(priv, resp);
1060 		break;
1061 	case HostCmd_CMD_11N_ADDBA_RSP:
1062 		ret = mwifiex_ret_11n_addba_resp(priv, resp);
1063 		break;
1064 	case HostCmd_CMD_RECONFIGURE_TX_BUFF:
1065 		adapter->tx_buf_size = (u16) le16_to_cpu(resp->params.
1066 							     tx_buf.buff_size);
1067 		adapter->tx_buf_size = (adapter->tx_buf_size
1068 					/ MWIFIEX_SDIO_BLOCK_SIZE)
1069 				       * MWIFIEX_SDIO_BLOCK_SIZE;
1070 		adapter->curr_tx_buf_size = adapter->tx_buf_size;
1071 		dev_dbg(adapter->dev, "cmd: curr_tx_buf_size=%d\n",
1072 			adapter->curr_tx_buf_size);
1073 
1074 		if (adapter->if_ops.update_mp_end_port)
1075 			adapter->if_ops.update_mp_end_port(adapter,
1076 				le16_to_cpu(resp->params.tx_buf.mp_end_port));
1077 		break;
1078 	case HostCmd_CMD_AMSDU_AGGR_CTRL:
1079 		break;
1080 	case HostCmd_CMD_WMM_GET_STATUS:
1081 		ret = mwifiex_ret_wmm_get_status(priv, resp);
1082 		break;
1083 	case HostCmd_CMD_802_11_IBSS_COALESCING_STATUS:
1084 		ret = mwifiex_ret_ibss_coalescing_status(priv, resp);
1085 		break;
1086 	case HostCmd_CMD_MAC_REG_ACCESS:
1087 	case HostCmd_CMD_BBP_REG_ACCESS:
1088 	case HostCmd_CMD_RF_REG_ACCESS:
1089 	case HostCmd_CMD_PMIC_REG_ACCESS:
1090 	case HostCmd_CMD_CAU_REG_ACCESS:
1091 	case HostCmd_CMD_802_11_EEPROM_ACCESS:
1092 		ret = mwifiex_ret_reg_access(cmdresp_no, resp, data_buf);
1093 		break;
1094 	case HostCmd_CMD_SET_BSS_MODE:
1095 		break;
1096 	case HostCmd_CMD_11N_CFG:
1097 		break;
1098 	case HostCmd_CMD_PCIE_DESC_DETAILS:
1099 		break;
1100 	case HostCmd_CMD_802_11_SUBSCRIBE_EVENT:
1101 		ret = mwifiex_ret_subsc_evt(priv, resp);
1102 		break;
1103 	case HostCmd_CMD_UAP_SYS_CONFIG:
1104 		break;
1105 	case HostCmd_CMD_UAP_BSS_START:
1106 		priv->bss_started = 1;
1107 		break;
1108 	case HostCmd_CMD_UAP_BSS_STOP:
1109 		priv->bss_started = 0;
1110 		break;
1111 	case HostCmd_CMD_UAP_STA_DEAUTH:
1112 		break;
1113 	case HostCmd_CMD_MEF_CFG:
1114 		break;
1115 	case HostCmd_CMD_COALESCE_CFG:
1116 		break;
1117 	case HostCmd_CMD_TDLS_OPER:
1118 		ret = mwifiex_ret_tdls_oper(priv, resp);
1119 		break;
1120 	default:
1121 		dev_err(adapter->dev, "CMD_RESP: unknown cmd response %#x\n",
1122 			resp->command);
1123 		break;
1124 	}
1125 
1126 	return ret;
1127 }
1128