sta_cmdresp.c 33.2 KB
Newer Older
1 2 3
/*
 * Marvell Wireless LAN device driver: station command response handling
 *
4
 * Copyright (C) 2011-2014, Marvell International Ltd.
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
 *
 * This software file (the "File") is distributed by Marvell International
 * Ltd. under the terms of the GNU General Public License Version 2, June 1991
 * (the "License").  You may use, redistribute and/or modify this File in
 * accordance with the terms and conditions of the License, a copy of which
 * is available by writing to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
 * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
 *
 * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
 * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
 * this warranty disclaimer.
 */

#include "decl.h"
#include "ioctl.h"
#include "util.h"
#include "fw.h"
#include "main.h"
#include "wmm.h"
#include "11n.h"
27
#include "11ac.h"
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44


/*
 * This function handles the command response error case.
 *
 * For scan response error, the function cancels all the pending
 * scan commands and generates an event to inform the applications
 * of the scan completion.
 *
 * For Power Save command failure, we do not retry enter PS
 * command in case of Ad-hoc mode.
 *
 * For all other response errors, the current command buffer is freed
 * and returned to the free command queue.
 */
static void
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 51 52
	unsigned long flags;

	dev_err(adapter->dev, "CMD_RESP: cmd %#x error, result=%#x\n",
53
		resp->command, resp->result);
54 55 56

	if (adapter->curr_cmd->wait_q_enabled)
		adapter->cmd_wait_q.status = -1;
57 58 59

	switch (le16_to_cpu(resp->command)) {
	case HostCmd_CMD_802_11_PS_MODE_ENH:
60
		pm = &resp->params.psmode_enh;
61 62 63
		dev_err(adapter->dev,
			"PS_MODE_ENH cmd failed: result=0x%x action=0x%X\n",
			resp->result, le16_to_cpu(pm->action));
64 65
		/* We do not re-try enter-ps command in ad-hoc mode. */
		if (le16_to_cpu(pm->action) == EN_AUTO_PS &&
66 67
		    (le16_to_cpu(pm->params.ps_bitmap) & BITMAP_STA_PS) &&
		    priv->bss_mode == NL80211_IFTYPE_ADHOC)
68 69
			adapter->ps_mode = MWIFIEX_802_11_POWER_MODE_CAM;

70 71
		break;
	case HostCmd_CMD_802_11_SCAN:
72
	case HostCmd_CMD_802_11_SCAN_EXT:
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
		/* Cancel all pending scan command */
		spin_lock_irqsave(&adapter->scan_pending_q_lock, flags);
		list_for_each_entry_safe(cmd_node, tmp_node,
					 &adapter->scan_pending_q, list) {
			list_del(&cmd_node->list);
			spin_unlock_irqrestore(&adapter->scan_pending_q_lock,
					       flags);
			mwifiex_insert_cmd_to_free_q(adapter, cmd_node);
			spin_lock_irqsave(&adapter->scan_pending_q_lock, flags);
		}
		spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags);

		spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
		adapter->scan_processing = false;
		spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
		break;

	case HostCmd_CMD_MAC_CONTROL:
		break;

	default:
		break;
	}
	/* Handling errors here */
97
	mwifiex_recycle_cmd_node(adapter, adapter->curr_cmd);
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117

	spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
	adapter->curr_cmd = NULL;
	spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
}

/*
 * This function handles the command response of get RSSI info.
 *
 * Handling includes changing the header fields into CPU format
 * and saving the following parameters in driver -
 *      - Last data and beacon RSSI value
 *      - Average data and beacon RSSI value
 *      - Last data and beacon NF value
 *      - Average data and beacon NF value
 *
 * The parameters are send to the application as well, along with
 * calculated SNR values.
 */
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 123
	struct mwifiex_ds_misc_subsc_evt *subsc_evt =
						&priv->async_subsc_evt_storage;
124 125 126 127 128 129 130 131 132 133 134 135 136

	priv->data_rssi_last = le16_to_cpu(rssi_info_rsp->data_rssi_last);
	priv->data_nf_last = le16_to_cpu(rssi_info_rsp->data_nf_last);

	priv->data_rssi_avg = le16_to_cpu(rssi_info_rsp->data_rssi_avg);
	priv->data_nf_avg = le16_to_cpu(rssi_info_rsp->data_nf_avg);

	priv->bcn_rssi_last = le16_to_cpu(rssi_info_rsp->bcn_rssi_last);
	priv->bcn_nf_last = le16_to_cpu(rssi_info_rsp->bcn_nf_last);

	priv->bcn_rssi_avg = le16_to_cpu(rssi_info_rsp->bcn_rssi_avg);
	priv->bcn_nf_avg = le16_to_cpu(rssi_info_rsp->bcn_nf_avg);

137 138 139
	if (priv->subsc_evt_rssi_state == EVENT_HANDLED)
		return 0;

140 141
	memset(subsc_evt, 0x00, sizeof(struct mwifiex_ds_misc_subsc_evt));

142
	/* Resubscribe low and high rssi events with new thresholds */
143 144
	subsc_evt->events = BITMASK_BCN_RSSI_LOW | BITMASK_BCN_RSSI_HIGH;
	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 151
		subsc_evt->bcn_l_rssi_cfg.abs_value = abs(priv->cqm_rssi_thold);
		subsc_evt->bcn_h_rssi_cfg.abs_value = abs(priv->bcn_rssi_avg +
152 153
				priv->cqm_rssi_hyst);
	}
154 155
	subsc_evt->bcn_l_rssi_cfg.evt_freq = 1;
	subsc_evt->bcn_h_rssi_cfg.evt_freq = 1;
156 157 158

	priv->subsc_evt_rssi_state = EVENT_HANDLED;

159 160
	mwifiex_send_cmd(priv, HostCmd_CMD_802_11_SUBSCRIBE_EVENT,
			 0, 0, subsc_evt, false);
161

162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178
	return 0;
}

/*
 * This function handles the command response of set/get SNMP
 * MIB parameters.
 *
 * Handling includes changing the header fields into CPU format
 * and saving the parameter in driver.
 *
 * The following parameters are supported -
 *      - Fragmentation threshold
 *      - RTS threshold
 *      - Short retry limit
 */
static int mwifiex_ret_802_11_snmp_mib(struct mwifiex_private *priv,
				       struct host_cmd_ds_command *resp,
179
				       u32 *data_buf)
180 181 182 183
{
	struct host_cmd_ds_802_11_snmp_mib *smib = &resp->params.smib;
	u16 oid = le16_to_cpu(smib->oid);
	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 188
		" query_type = %#x, buf size = %#x\n",
		oid, query_type, le16_to_cpu(smib->buf_size));
189
	if (query_type == HostCmd_ACT_GEN_GET) {
190 191 192
		ul_temp = le16_to_cpu(*((__le16 *) (smib->value)));
		if (data_buf)
			*data_buf = ul_temp;
193 194 195
		switch (oid) {
		case FRAG_THRESH_I:
			dev_dbg(priv->adapter->dev,
196
				"info: SNMP_RESP: FragThsd =%u\n", ul_temp);
197 198 199
			break;
		case RTS_THRESH_I:
			dev_dbg(priv->adapter->dev,
200
				"info: SNMP_RESP: RTSThsd =%u\n", ul_temp);
201 202 203
			break;
		case SHORT_RETRY_LIM_I:
			dev_dbg(priv->adapter->dev,
204
				"info: SNMP_RESP: TxRetryCount=%u\n", ul_temp);
205
			break;
206 207 208
		case DTIM_PERIOD_I:
			dev_dbg(priv->adapter->dev,
				"info: SNMP_RESP: DTIM period=%u\n", ul_temp);
209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224
		default:
			break;
		}
	}

	return 0;
}

/*
 * This function handles the command response of get log request
 *
 * Handling includes changing the header fields into CPU format
 * and sending the received parameters to application.
 */
static int mwifiex_ret_get_log(struct mwifiex_private *priv,
			       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 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267
		stats->mcast_tx_frame = le32_to_cpu(get_log->mcast_tx_frame);
		stats->failed = le32_to_cpu(get_log->failed);
		stats->retry = le32_to_cpu(get_log->retry);
		stats->multi_retry = le32_to_cpu(get_log->multi_retry);
		stats->frame_dup = le32_to_cpu(get_log->frame_dup);
		stats->rts_success = le32_to_cpu(get_log->rts_success);
		stats->rts_failure = le32_to_cpu(get_log->rts_failure);
		stats->ack_failure = le32_to_cpu(get_log->ack_failure);
		stats->rx_frag = le32_to_cpu(get_log->rx_frag);
		stats->mcast_rx_frame = le32_to_cpu(get_log->mcast_rx_frame);
		stats->fcs_error = le32_to_cpu(get_log->fcs_error);
		stats->tx_frame = le32_to_cpu(get_log->tx_frame);
		stats->wep_icv_error[0] =
			le32_to_cpu(get_log->wep_icv_err_cnt[0]);
		stats->wep_icv_error[1] =
			le32_to_cpu(get_log->wep_icv_err_cnt[1]);
		stats->wep_icv_error[2] =
			le32_to_cpu(get_log->wep_icv_err_cnt[2]);
		stats->wep_icv_error[3] =
			le32_to_cpu(get_log->wep_icv_err_cnt[3]);
	}

	return 0;
}

/*
 * This function handles the command response of set/get Tx rate
 * configurations.
 *
 * Handling includes changing the header fields into CPU format
 * and saving the following parameters in driver -
 *      - DSSS rate bitmap
 *      - OFDM rate bitmap
 *      - HT MCS rate bitmaps
 *
 * Based on the new rate bitmaps, the function re-evaluates if
 * auto data rate has been activated. If not, it sends another
268
 * query to the firmware to get the current Tx data rate.
269 270
 */
static int mwifiex_ret_tx_rate_cfg(struct mwifiex_private *priv,
271
				   struct host_cmd_ds_command *resp)
272 273 274
{
	struct host_cmd_ds_tx_rate_cfg *rate_cfg = &resp->params.tx_rate_cfg;
	struct mwifiex_rate_scope *rate_scope;
275
	struct mwifiex_ie_types_header *head;
276
	u16 tlv, tlv_buf_len, tlv_buf_left;
277 278 279
	u8 *tlv_buf;
	u32 i;

280 281
	tlv_buf = ((u8 *)rate_cfg) + sizeof(struct host_cmd_ds_tx_rate_cfg);
	tlv_buf_left = le16_to_cpu(resp->size) - S_DS_GEN - sizeof(*rate_cfg);
282

283 284 285 286 287 288 289
	while (tlv_buf_left >= sizeof(*head)) {
		head = (struct mwifiex_ie_types_header *)tlv_buf;
		tlv = le16_to_cpu(head->type);
		tlv_buf_len = le16_to_cpu(head->len);

		if (tlv_buf_left < (sizeof(*head) + tlv_buf_len))
			break;
290 291 292 293 294 295 296 297 298 299 300 301 302 303 304

		switch (tlv) {
		case TLV_TYPE_RATE_SCOPE:
			rate_scope = (struct mwifiex_rate_scope *) tlv_buf;
			priv->bitmap_rates[0] =
				le16_to_cpu(rate_scope->hr_dsss_rate_bitmap);
			priv->bitmap_rates[1] =
				le16_to_cpu(rate_scope->ofdm_rate_bitmap);
			for (i = 0;
			     i <
			     sizeof(rate_scope->ht_mcs_rate_bitmap) /
			     sizeof(u16); i++)
				priv->bitmap_rates[2 + i] =
					le16_to_cpu(rate_scope->
						    ht_mcs_rate_bitmap[i]);
305 306 307 308 309 310 311 312 313

			if (priv->adapter->fw_api_ver == MWIFIEX_FW_V15) {
				for (i = 0; i < ARRAY_SIZE(rate_scope->
							   vht_mcs_rate_bitmap);
				     i++)
					priv->bitmap_rates[10 + i] =
					    le16_to_cpu(rate_scope->
							vht_mcs_rate_bitmap[i]);
			}
314 315 316 317
			break;
			/* Add RATE_DROP tlv here */
		}

318 319
		tlv_buf += (sizeof(*head) + tlv_buf_len);
		tlv_buf_left -= (sizeof(*head) + tlv_buf_len);
320 321 322 323 324 325 326
	}

	priv->is_data_rate_auto = mwifiex_is_rate_auto(priv);

	if (priv->is_data_rate_auto)
		priv->data_rate = 0;
	else
327 328
		return mwifiex_send_cmd(priv, HostCmd_CMD_802_11_TX_RATE_QUERY,
					HostCmd_ACT_GEN_GET, 0, NULL, false);
329

330
	return 0;
331 332 333 334 335 336 337 338 339 340
}

/*
 * This function handles the command response of get Tx power level.
 *
 * Handling includes saving the maximum and minimum Tx power levels
 * in driver, as well as sending the values to user.
 */
static int mwifiex_get_power_level(struct mwifiex_private *priv, void *data_buf)
{
341 342 343
	int length, max_power = -1, min_power = -1;
	struct mwifiex_types_power_group *pg_tlv_hdr;
	struct mwifiex_power_group *pg;
344

345 346 347
	if (!data_buf)
		return -1;

348
	pg_tlv_hdr = (struct mwifiex_types_power_group *)((u8 *)data_buf);
349 350
	pg = (struct mwifiex_power_group *)
		((u8 *) pg_tlv_hdr + sizeof(struct mwifiex_types_power_group));
351
	length = le16_to_cpu(pg_tlv_hdr->length);
352 353 354 355 356 357 358 359 360 361

	/* At least one structure required to update power */
	if (length < sizeof(struct mwifiex_power_group))
		return 0;

	max_power = pg->power_max;
	min_power = pg->power_min;
	length -= sizeof(struct mwifiex_power_group);

	while (length >= sizeof(struct mwifiex_power_group)) {
362 363
		pg++;
		if (max_power < pg->power_max)
364 365
			max_power = pg->power_max;

366 367
		if (min_power > pg->power_min)
			min_power = pg->power_min;
368

369 370
		length -= sizeof(struct mwifiex_power_group);
	}
371 372
	priv->min_tx_power_level = (u8) min_power;
	priv->max_tx_power_level = (u8) max_power;
373 374 375 376 377 378 379 380 381 382 383 384

	return 0;
}

/*
 * This function handles the command response of set/get Tx power
 * configurations.
 *
 * Handling includes changing the header fields into CPU format
 * and saving the current Tx power level in driver.
 */
static int mwifiex_ret_tx_power_cfg(struct mwifiex_private *priv,
385
				    struct host_cmd_ds_command *resp)
386 387 388
{
	struct mwifiex_adapter *adapter = priv->adapter;
	struct host_cmd_ds_txpwr_cfg *txp_cfg = &resp->params.txp_cfg;
389 390
	struct mwifiex_types_power_group *pg_tlv_hdr;
	struct mwifiex_power_group *pg;
391
	u16 action = le16_to_cpu(txp_cfg->action);
392
	u16 tlv_buf_left;
393

394 395 396
	pg_tlv_hdr = (struct mwifiex_types_power_group *)
		((u8 *)txp_cfg +
		 sizeof(struct host_cmd_ds_txpwr_cfg));
397

398 399 400
	pg = (struct mwifiex_power_group *)
		((u8 *)pg_tlv_hdr +
		 sizeof(struct mwifiex_types_power_group));
401

402 403 404 405 406 407 408
	tlv_buf_left = le16_to_cpu(resp->size) - S_DS_GEN - sizeof(*txp_cfg);
	if (tlv_buf_left <
			le16_to_cpu(pg_tlv_hdr->length) + sizeof(*pg_tlv_hdr))
		return 0;

	switch (action) {
	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 413 414

		priv->tx_power_level = (u16) pg->power_min;
		break;

415
	case HostCmd_ACT_GEN_SET:
416 417 418 419 420
		if (!le32_to_cpu(txp_cfg->mode))
			break;

		if (pg->power_max == pg->power_min)
			priv->tx_power_level = (u16) pg->power_min;
421 422 423
		break;
	default:
		dev_err(adapter->dev, "CMD_RESP: unknown cmd action %d\n",
424
			action);
425 426 427 428 429 430 431 432 433 434
		return 0;
	}
	dev_dbg(adapter->dev,
		"info: Current TxPower Level = %d, Max Power=%d, Min Power=%d\n",
	       priv->tx_power_level, priv->max_tx_power_level,
	       priv->min_tx_power_level);

	return 0;
}

435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458
/*
 * This function handles the command response of get RF Tx power.
 */
static int mwifiex_ret_rf_tx_power(struct mwifiex_private *priv,
				   struct host_cmd_ds_command *resp)
{
	struct host_cmd_ds_rf_tx_pwr *txp = &resp->params.txp;
	u16 action = le16_to_cpu(txp->action);

	priv->tx_power_level = le16_to_cpu(txp->cur_level);

	if (action == HostCmd_ACT_GEN_GET) {
		priv->max_tx_power_level = txp->max_power;
		priv->min_tx_power_level = txp->min_power;
	}

	dev_dbg(priv->adapter->dev,
		"Current TxPower Level=%d, Max Power=%d, Min Power=%d\n",
		priv->tx_power_level, priv->max_tx_power_level,
		priv->min_tx_power_level);

	return 0;
}

459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485
/*
 * This function handles the command response of set rf antenna
 */
static int mwifiex_ret_rf_antenna(struct mwifiex_private *priv,
				  struct host_cmd_ds_command *resp)
{
	struct host_cmd_ds_rf_ant_mimo *ant_mimo = &resp->params.ant_mimo;
	struct host_cmd_ds_rf_ant_siso *ant_siso = &resp->params.ant_siso;
	struct mwifiex_adapter *adapter = priv->adapter;

	if (adapter->hw_dev_mcs_support == HT_STREAM_2X2)
		dev_dbg(adapter->dev,
			"RF_ANT_RESP: Tx action = 0x%x, Tx Mode = 0x%04x"
			" Rx action = 0x%x, Rx Mode = 0x%04x\n",
			le16_to_cpu(ant_mimo->action_tx),
			le16_to_cpu(ant_mimo->tx_ant_mode),
			le16_to_cpu(ant_mimo->action_rx),
			le16_to_cpu(ant_mimo->rx_ant_mode));
	else
		dev_dbg(adapter->dev,
			"RF_ANT_RESP: action = 0x%x, Mode = 0x%04x\n",
			le16_to_cpu(ant_siso->action),
			le16_to_cpu(ant_siso->ant_mode));

	return 0;
}

486 487 488 489 490 491 492 493 494
/*
 * This function handles the command response of set/get MAC address.
 *
 * Handling includes saving the MAC address in driver.
 */
static int mwifiex_ret_802_11_mac_address(struct mwifiex_private *priv,
					  struct host_cmd_ds_command *resp)
{
	struct host_cmd_ds_802_11_mac_address *cmd_mac_addr =
495
							&resp->params.mac_addr;
496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530

	memcpy(priv->curr_addr, cmd_mac_addr->mac_addr, ETH_ALEN);

	dev_dbg(priv->adapter->dev,
		"info: set mac address: %pM\n", priv->curr_addr);

	return 0;
}

/*
 * This function handles the command response of set/get MAC multicast
 * address.
 */
static int mwifiex_ret_mac_multicast_adr(struct mwifiex_private *priv,
					 struct host_cmd_ds_command *resp)
{
	return 0;
}

/*
 * This function handles the command response of get Tx rate query.
 *
 * Handling includes changing the header fields into CPU format
 * and saving the Tx rate and HT information parameters in driver.
 *
 * Both rate configuration and current data rate can be retrieved
 * with this request.
 */
static int mwifiex_ret_802_11_tx_rate_query(struct mwifiex_private *priv,
					    struct host_cmd_ds_command *resp)
{
	priv->tx_rate = resp->params.tx_rate.tx_rate;
	priv->tx_htinfo = resp->params.tx_rate.ht_info;
	if (!priv->is_data_rate_auto)
		priv->data_rate =
531
			mwifiex_index_to_data_rate(priv, priv->tx_rate,
532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552
						   priv->tx_htinfo);

	return 0;
}

/*
 * This function handles the command response of a deauthenticate
 * command.
 *
 * If the deauthenticated MAC matches the current BSS MAC, the connection
 * state is reset.
 */
static int mwifiex_ret_802_11_deauthenticate(struct mwifiex_private *priv,
					     struct host_cmd_ds_command *resp)
{
	struct mwifiex_adapter *adapter = priv->adapter;

	adapter->dbg.num_cmd_deauth++;
	if (!memcmp(resp->params.deauth.mac_addr,
		    &priv->curr_bss_params.bss_descriptor.mac_address,
		    sizeof(resp->params.deauth.mac_addr)))
553
		mwifiex_reset_connect_state(priv, WLAN_REASON_DEAUTH_LEAVING);
554 555 556 557 558 559 560 561 562 563 564 565

	return 0;
}

/*
 * This function handles the command response of ad-hoc stop.
 *
 * The function resets the connection state in driver.
 */
static int mwifiex_ret_802_11_ad_hoc_stop(struct mwifiex_private *priv,
					  struct host_cmd_ds_command *resp)
{
566
	mwifiex_reset_connect_state(priv, WLAN_REASON_DEAUTH_LEAVING);
567 568 569 570
	return 0;
}

/*
571
 * This function handles the command response of set/get v1 key material.
572 573 574 575
 *
 * Handling includes updating the driver parameters to reflect the
 * changes.
 */
576 577
static int mwifiex_ret_802_11_key_material_v1(struct mwifiex_private *priv,
					      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 585 586 587 588 589 590 591 592 593 594 595 596 597 598
			dev_dbg(priv->adapter->dev, "info: key: GTK is set\n");
			priv->wpa_is_gtk_set = true;
			priv->scan_block = false;
		}
	}

	memset(priv->aes_key.key_param_set.key, 0,
	       sizeof(key->key_param_set.key));
	priv->aes_key.key_param_set.key_len = key->key_param_set.key_len;
	memcpy(priv->aes_key.key_param_set.key, key->key_param_set.key,
	       le16_to_cpu(priv->aes_key.key_param_set.key_len));

	return 0;
}

599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637
/*
 * This function handles the command response of set/get v2 key material.
 *
 * Handling includes updating the driver parameters to reflect the
 * changes.
 */
static int mwifiex_ret_802_11_key_material_v2(struct mwifiex_private *priv,
					      struct host_cmd_ds_command *resp)
{
	struct host_cmd_ds_802_11_key_material_v2 *key_v2;
	__le16 len;

	key_v2 = &resp->params.key_material_v2;
	if (le16_to_cpu(key_v2->action) == HostCmd_ACT_GEN_SET) {
		if ((le16_to_cpu(key_v2->key_param_set.key_info) & KEY_MCAST)) {
			dev_dbg(priv->adapter->dev, "info: key: GTK is set\n");
			priv->wpa_is_gtk_set = true;
			priv->scan_block = false;
		}
	}

	if (key_v2->key_param_set.key_type != KEY_TYPE_ID_AES)
		return 0;

	memset(priv->aes_key_v2.key_param_set.key_params.aes.key, 0,
	       WLAN_KEY_LEN_CCMP);
	priv->aes_key_v2.key_param_set.key_params.aes.key_len =
				key_v2->key_param_set.key_params.aes.key_len;
	len = priv->aes_key_v2.key_param_set.key_params.aes.key_len;
	memcpy(priv->aes_key_v2.key_param_set.key_params.aes.key,
	       key_v2->key_param_set.key_params.aes.key, le16_to_cpu(len));

	return 0;
}

/* Wrapper function for processing response of key material command */
static int mwifiex_ret_802_11_key_material(struct mwifiex_private *priv,
					   struct host_cmd_ds_command *resp)
{
638
	if (priv->adapter->key_api_major_ver == KEY_API_VER_MAJOR_V2)
639 640 641 642 643
		return mwifiex_ret_802_11_key_material_v2(priv, resp);
	else
		return mwifiex_ret_802_11_key_material_v1(priv, resp);
}

644 645 646 647 648 649 650 651 652 653
/*
 * This function handles the command response of get 11d domain information.
 */
static int mwifiex_ret_802_11d_domain_info(struct mwifiex_private *priv,
					   struct host_cmd_ds_command *resp)
{
	struct host_cmd_ds_802_11d_domain_info_rsp *domain_info =
		&resp->params.domain_info_resp;
	struct mwifiex_ietypes_domain_param_set *domain = &domain_info->domain;
	u16 action = le16_to_cpu(domain_info->action);
654
	u8 no_of_triplet;
655

656 657 658
	no_of_triplet = (u8) ((le16_to_cpu(domain->header.len)
				- IEEE80211_COUNTRY_STRING_LEN)
			      / sizeof(struct ieee80211_country_ie_triplet));
659

660 661 662
	dev_dbg(priv->adapter->dev,
		"info: 11D Domain Info Resp: no_of_triplet=%d\n",
		no_of_triplet);
663 664 665

	if (no_of_triplet > MWIFIEX_MAX_TRIPLET_802_11D) {
		dev_warn(priv->adapter->dev,
666 667
			 "11D: invalid number of triplets %d returned\n",
			 no_of_triplet);
668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692
		return -1;
	}

	switch (action) {
	case HostCmd_ACT_GEN_SET:  /* Proc Set Action */
		break;
	case HostCmd_ACT_GEN_GET:
		break;
	default:
		dev_err(priv->adapter->dev,
			"11D: invalid action:%d\n", domain_info->action);
		return -1;
	}

	return 0;
}

/*
 * This function handles the command response of get extended version.
 *
 * Handling includes forming the extended version string and sending it
 * to application.
 */
static int mwifiex_ret_ver_ext(struct mwifiex_private *priv,
			       struct host_cmd_ds_command *resp,
693
			       struct host_cmd_ds_version_ext *version_ext)
694 695 696
{
	struct host_cmd_ds_version_ext *ver_ext = &resp->params.verext;

697
	if (version_ext) {
698 699 700 701 702 703 704 705
		version_ext->version_str_sel = ver_ext->version_str_sel;
		memcpy(version_ext->version_str, ver_ext->version_str,
		       sizeof(char) * 128);
		memcpy(priv->version_str, ver_ext->version_str, 128);
	}
	return 0;
}

706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721
/*
 * This function handles the command response of remain on channel.
 */
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)
{
	struct host_cmd_ds_remain_on_chan *resp_cfg = &resp->params.roc_cfg;

	if (roc_cfg)
		memcpy(roc_cfg, resp_cfg, sizeof(*roc_cfg));

	return 0;
}

722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737
/*
 * This function handles the command response of P2P mode cfg.
 */
static int
mwifiex_ret_p2p_mode_cfg(struct mwifiex_private *priv,
			 struct host_cmd_ds_command *resp,
			 void *data_buf)
{
	struct host_cmd_ds_p2p_mode_cfg *mode_cfg = &resp->params.mode_cfg;

	if (data_buf)
		*((u16 *)data_buf) = le16_to_cpu(mode_cfg->mode);

	return 0;
}

738 739 740 741 742 743 744 745 746
/*
 * This function handles the command response of register access.
 *
 * The register value and offset are returned to the user. For EEPROM
 * access, the byte count is also returned.
 */
static int mwifiex_ret_reg_access(u16 type, struct host_cmd_ds_command *resp,
				  void *data_buf)
{
747 748
	struct mwifiex_ds_reg_rw *reg_rw;
	struct mwifiex_ds_read_eeprom *eeprom;
749 750 751 752 753 754 755 756 757 758
	union reg {
		struct host_cmd_ds_mac_reg_access *mac;
		struct host_cmd_ds_bbp_reg_access *bbp;
		struct host_cmd_ds_rf_reg_access *rf;
		struct host_cmd_ds_pmic_reg_access *pmic;
		struct host_cmd_ds_802_11_eeprom_access *eeprom;
	} r;

	if (!data_buf)
		return 0;
759

760 761 762 763
	reg_rw = data_buf;
	eeprom = data_buf;
	switch (type) {
	case HostCmd_CMD_MAC_REG_ACCESS:
764
		r.mac = &resp->params.mac_reg;
765 766 767 768
		reg_rw->offset = cpu_to_le32((u32) le16_to_cpu(r.mac->offset));
		reg_rw->value = r.mac->value;
		break;
	case HostCmd_CMD_BBP_REG_ACCESS:
769
		r.bbp = &resp->params.bbp_reg;
770 771 772
		reg_rw->offset = cpu_to_le32((u32) le16_to_cpu(r.bbp->offset));
		reg_rw->value = cpu_to_le32((u32) r.bbp->value);
		break;
773

774
	case HostCmd_CMD_RF_REG_ACCESS:
775
		r.rf = &resp->params.rf_reg;
776 777 778 779
		reg_rw->offset = cpu_to_le32((u32) le16_to_cpu(r.rf->offset));
		reg_rw->value = cpu_to_le32((u32) r.bbp->value);
		break;
	case HostCmd_CMD_PMIC_REG_ACCESS:
780
		r.pmic = &resp->params.pmic_reg;
781 782 783 784
		reg_rw->offset = cpu_to_le32((u32) le16_to_cpu(r.pmic->offset));
		reg_rw->value = cpu_to_le32((u32) r.pmic->value);
		break;
	case HostCmd_CMD_CAU_REG_ACCESS:
785
		r.rf = &resp->params.rf_reg;
786 787 788 789
		reg_rw->offset = cpu_to_le32((u32) le16_to_cpu(r.rf->offset));
		reg_rw->value = cpu_to_le32((u32) r.rf->value);
		break;
	case HostCmd_CMD_802_11_EEPROM_ACCESS:
790
		r.eeprom = &resp->params.eeprom;
791 792 793 794 795
		pr_debug("info: EEPROM read len=%x\n", r.eeprom->byte_count);
		if (le16_to_cpu(eeprom->byte_count) <
		    le16_to_cpu(r.eeprom->byte_count)) {
			eeprom->byte_count = cpu_to_le16(0);
			pr_debug("info: EEPROM read length is too big\n");
796 797
			return -1;
		}
798 799 800 801 802 803 804 805 806
		eeprom->offset = r.eeprom->offset;
		eeprom->byte_count = r.eeprom->byte_count;
		if (le16_to_cpu(eeprom->byte_count) > 0)
			memcpy(&eeprom->value, &r.eeprom->value,
			       le16_to_cpu(r.eeprom->byte_count));

		break;
	default:
		return -1;
807 808 809 810 811 812 813 814 815 816 817 818 819 820 821
	}
	return 0;
}

/*
 * This function handles the command response of get IBSS coalescing status.
 *
 * If the received BSSID is different than the current one, the current BSSID,
 * beacon interval, ATIM window and ERP information are updated, along with
 * changing the ad-hoc state accordingly.
 */
static int mwifiex_ret_ibss_coalescing_status(struct mwifiex_private *priv,
					      struct host_cmd_ds_command *resp)
{
	struct host_cmd_ds_802_11_ibss_status *ibss_coal_resp =
822
					&(resp->params.ibss_coalescing);
823 824 825 826 827 828 829 830

	if (le16_to_cpu(ibss_coal_resp->action) == HostCmd_ACT_GEN_SET)
		return 0;

	dev_dbg(priv->adapter->dev,
		"info: new BSSID %pM\n", ibss_coal_resp->bssid);

	/* If rsp has NULL BSSID, Just return..... No Action */
831
	if (is_zero_ether_addr(ibss_coal_resp->bssid)) {
832 833 834 835 836
		dev_warn(priv->adapter->dev, "new BSSID is NULL\n");
		return 0;
	}

	/* 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 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854
		/* BSSID */
		memcpy(priv->curr_bss_params.bss_descriptor.mac_address,
		       ibss_coal_resp->bssid, ETH_ALEN);

		/* Beacon Interval */
		priv->curr_bss_params.bss_descriptor.beacon_period
			= le16_to_cpu(ibss_coal_resp->beacon_interval);

		/* ERP Information */
		priv->curr_bss_params.bss_descriptor.erp_flags =
			(u8) le16_to_cpu(ibss_coal_resp->use_g_rate_protect);

		priv->adhoc_state = ADHOC_COALESCED;
	}

	return 0;
}
855 856 857 858 859 860
static int mwifiex_ret_tdls_oper(struct mwifiex_private *priv,
				 struct host_cmd_ds_command *resp)
{
	struct host_cmd_ds_tdls_oper *cmd_tdls_oper = &resp->params.tdls_oper;
	u16 reason = le16_to_cpu(cmd_tdls_oper->reason);
	u16 action = le16_to_cpu(cmd_tdls_oper->tdls_action);
861 862
	struct mwifiex_sta_node *node =
			   mwifiex_get_sta_entry(priv, cmd_tdls_oper->peer_mac);
863

864 865
	switch (action) {
	case ACT_TDLS_DELETE:
866 867 868 869 870 871 872 873 874 875
		if (reason) {
			if (!node || reason == TDLS_ERR_LINK_NONEXISTENT)
				dev_dbg(priv->adapter->dev,
					"TDLS link delete for %pM failed: reason %d\n",
					cmd_tdls_oper->peer_mac, reason);
			else
				dev_err(priv->adapter->dev,
					"TDLS link delete for %pM failed: reason %d\n",
					cmd_tdls_oper->peer_mac, reason);
		} 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 882 883 884 885 886 887 888 889 890 891 892 893
	case ACT_TDLS_CREATE:
		if (reason) {
			dev_err(priv->adapter->dev,
				"TDLS link creation for %pM failed: reason %d",
				cmd_tdls_oper->peer_mac, reason);
			if (node && reason != TDLS_ERR_LINK_EXISTS)
				node->tdls_status = TDLS_SETUP_FAILURE;
		} else {
			dev_dbg(priv->adapter->dev,
				"TDLS link creation for %pM successful",
				cmd_tdls_oper->peer_mac);
		}
		break;
894 895 896 897 898 899 900 901 902 903 904 905 906
	case ACT_TDLS_CONFIG:
		if (reason) {
			dev_err(priv->adapter->dev,
				"TDLS link config for %pM failed, reason %d\n",
				cmd_tdls_oper->peer_mac, reason);
			if (node)
				node->tdls_status = TDLS_SETUP_FAILURE;
		} else {
			dev_dbg(priv->adapter->dev,
				"TDLS link config for %pM successful\n",
				cmd_tdls_oper->peer_mac);
		}
		break;
907 908
	default:
		dev_err(priv->adapter->dev,
909
			"Unknown TDLS command action response %d", action);
910 911 912 913 914
		return -1;
	}

	return 0;
}
915 916 917 918
/*
 * This function handles the command response for subscribe event command.
 */
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 925 926 927 928 929 930 931

	/* For every subscribe event command (Get/Set/Clear), FW reports the
	 * current set of subscribed events*/
	dev_dbg(priv->adapter->dev, "Bitmap of currently subscribed events: %16x\n",
		le16_to_cpu(cmd_sub_event->events));

	return 0;
}

932 933 934 935 936 937 938 939 940 941 942 943
/* This function handles the command response of set_cfg_data */
static int mwifiex_ret_cfg_data(struct mwifiex_private *priv,
				struct host_cmd_ds_command *resp)
{
	if (resp->result != HostCmd_RESULT_OK) {
		dev_err(priv->adapter->dev, "Cal data cmd resp failed\n");
		return -1;
	}

	return 0;
}

944 945 946 947 948 949
/*
 * This function handles the command responses.
 *
 * This is a generic function, which calls command specific
 * response handlers based on the command ID.
 */
950 951
int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, u16 cmdresp_no,
				struct host_cmd_ds_command *resp)
952 953 954 955 956 957 958
{
	int ret = 0;
	struct mwifiex_adapter *adapter = priv->adapter;
	void *data_buf = adapter->curr_cmd->data_buf;

	/* If the command is not successful, cleanup and return failure */
	if (resp->result != HostCmd_RESULT_OK) {
959
		mwifiex_process_cmdresp_error(priv, resp);
960 961 962 963 964 965 966
		return -1;
	}
	/* Command successful, handle response */
	switch (cmdresp_no) {
	case HostCmd_CMD_GET_HW_SPEC:
		ret = mwifiex_ret_get_hw_spec(priv, resp);
		break;
967 968 969
	case HostCmd_CMD_CFG_DATA:
		ret = mwifiex_ret_cfg_data(priv, resp);
		break;
970 971 972 973 974 975 976 977 978
	case HostCmd_CMD_MAC_CONTROL:
		break;
	case HostCmd_CMD_802_11_MAC_ADDRESS:
		ret = mwifiex_ret_802_11_mac_address(priv, resp);
		break;
	case HostCmd_CMD_MAC_MULTICAST_ADR:
		ret = mwifiex_ret_mac_multicast_adr(priv, resp);
		break;
	case HostCmd_CMD_TX_RATE_CFG:
979
		ret = mwifiex_ret_tx_rate_cfg(priv, resp);
980 981
		break;
	case HostCmd_CMD_802_11_SCAN:
982 983
		ret = mwifiex_ret_802_11_scan(priv, resp);
		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, resp);
987 988
		adapter->curr_cmd->wait_q_enabled = false;
		break;
989
	case HostCmd_CMD_802_11_BG_SCAN_QUERY:
990
		ret = mwifiex_ret_802_11_scan(priv, resp);
991 992 993 994
		dev_dbg(adapter->dev,
			"info: CMD_RESP: BG_SCAN result is ready!\n");
		break;
	case HostCmd_CMD_TXPWR_CFG:
995
		ret = mwifiex_ret_tx_power_cfg(priv, resp);
996
		break;
997 998 999
	case HostCmd_CMD_RF_TX_PWR:
		ret = mwifiex_ret_rf_tx_power(priv, resp);
		break;
1000 1001 1002
	case HostCmd_CMD_RF_ANTENNA:
		ret = mwifiex_ret_rf_antenna(priv, resp);
		break;
1003 1004 1005 1006 1007 1008 1009
	case HostCmd_CMD_802_11_PS_MODE_ENH:
		ret = mwifiex_ret_enh_power_mode(priv, resp, data_buf);
		break;
	case HostCmd_CMD_802_11_HS_CFG_ENH:
		ret = mwifiex_ret_802_11_hs_cfg(priv, resp);
		break;
	case HostCmd_CMD_802_11_ASSOCIATE:
1010
		ret = mwifiex_ret_802_11_associate(priv, resp);
1011 1012 1013 1014 1015 1016
		break;
	case HostCmd_CMD_802_11_DEAUTHENTICATE:
		ret = mwifiex_ret_802_11_deauthenticate(priv, resp);
		break;
	case HostCmd_CMD_802_11_AD_HOC_START:
	case HostCmd_CMD_802_11_AD_HOC_JOIN:
1017
		ret = mwifiex_ret_802_11_ad_hoc(priv, resp);
1018 1019 1020 1021 1022 1023 1024 1025
		break;
	case HostCmd_CMD_802_11_AD_HOC_STOP:
		ret = mwifiex_ret_802_11_ad_hoc_stop(priv, resp);
		break;
	case HostCmd_CMD_802_11_GET_LOG:
		ret = mwifiex_ret_get_log(priv, resp, data_buf);
		break;
	case HostCmd_CMD_RSSI_INFO:
1026
		ret = mwifiex_ret_802_11_rssi_info(priv, resp);
1027 1028 1029 1030 1031 1032 1033 1034 1035 1036
		break;
	case HostCmd_CMD_802_11_SNMP_MIB:
		ret = mwifiex_ret_802_11_snmp_mib(priv, resp, data_buf);
		break;
	case HostCmd_CMD_802_11_TX_RATE_QUERY:
		ret = mwifiex_ret_802_11_tx_rate_query(priv, resp);
		break;
	case HostCmd_CMD_VERSION_EXT:
		ret = mwifiex_ret_ver_ext(priv, resp, data_buf);
		break;
1037 1038 1039
	case HostCmd_CMD_REMAIN_ON_CHAN:
		ret = mwifiex_ret_remain_on_chan(priv, resp, data_buf);
		break;
1040 1041
	case HostCmd_CMD_11AC_CFG:
		break;
1042 1043 1044
	case HostCmd_CMD_P2P_MODE_CFG:
		ret = mwifiex_ret_p2p_mode_cfg(priv, resp, data_buf);
		break;
1045
	case HostCmd_CMD_MGMT_FRAME_REG:
1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066
	case HostCmd_CMD_FUNC_INIT:
	case HostCmd_CMD_FUNC_SHUTDOWN:
		break;
	case HostCmd_CMD_802_11_KEY_MATERIAL:
		ret = mwifiex_ret_802_11_key_material(priv, resp);
		break;
	case HostCmd_CMD_802_11D_DOMAIN_INFO:
		ret = mwifiex_ret_802_11d_domain_info(priv, resp);
		break;
	case HostCmd_CMD_11N_ADDBA_REQ:
		ret = mwifiex_ret_11n_addba_req(priv, resp);
		break;
	case HostCmd_CMD_11N_DELBA:
		ret = mwifiex_ret_11n_delba(priv, resp);
		break;
	case HostCmd_CMD_11N_ADDBA_RSP:
		ret = mwifiex_ret_11n_addba_resp(priv, resp);
		break;
	case HostCmd_CMD_RECONFIGURE_TX_BUFF:
		adapter->tx_buf_size = (u16) le16_to_cpu(resp->params.
							     tx_buf.buff_size);
1067 1068 1069
		adapter->tx_buf_size = (adapter->tx_buf_size
					/ MWIFIEX_SDIO_BLOCK_SIZE)
				       * MWIFIEX_SDIO_BLOCK_SIZE;
1070
		adapter->curr_tx_buf_size = adapter->tx_buf_size;
Bing Zhao's avatar
Bing Zhao committed
1071 1072
		dev_dbg(adapter->dev, "cmd: curr_tx_buf_size=%d\n",
			adapter->curr_tx_buf_size);
1073 1074 1075

		if (adapter->if_ops.update_mp_end_port)
			adapter->if_ops.update_mp_end_port(adapter,
1076
				le16_to_cpu(resp->params.tx_buf.mp_end_port));
1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097
		break;
	case HostCmd_CMD_AMSDU_AGGR_CTRL:
		break;
	case HostCmd_CMD_WMM_GET_STATUS:
		ret = mwifiex_ret_wmm_get_status(priv, resp);
		break;
	case HostCmd_CMD_802_11_IBSS_COALESCING_STATUS:
		ret = mwifiex_ret_ibss_coalescing_status(priv, resp);
		break;
	case HostCmd_CMD_MAC_REG_ACCESS:
	case HostCmd_CMD_BBP_REG_ACCESS:
	case HostCmd_CMD_RF_REG_ACCESS:
	case HostCmd_CMD_PMIC_REG_ACCESS:
	case HostCmd_CMD_CAU_REG_ACCESS:
	case HostCmd_CMD_802_11_EEPROM_ACCESS:
		ret = mwifiex_ret_reg_access(cmdresp_no, resp, data_buf);
		break;
	case HostCmd_CMD_SET_BSS_MODE:
		break;
	case HostCmd_CMD_11N_CFG:
		break;
1098 1099
	case HostCmd_CMD_PCIE_DESC_DETAILS:
		break;
1100
	case HostCmd_CMD_802_11_SUBSCRIBE_EVENT:
1101
		ret = mwifiex_ret_subsc_evt(priv, resp);
1102
		break;
1103 1104 1105 1106 1107 1108 1109 1110
	case HostCmd_CMD_UAP_SYS_CONFIG:
		break;
	case HostCmd_CMD_UAP_BSS_START:
		priv->bss_started = 1;
		break;
	case HostCmd_CMD_UAP_BSS_STOP:
		priv->bss_started = 0;
		break;
1111 1112
	case HostCmd_CMD_UAP_STA_DEAUTH:
		break;
1113 1114
	case HostCmd_CMD_MEF_CFG:
		break;
1115 1116
	case HostCmd_CMD_COALESCE_CFG:
		break;
1117 1118 1119
	case HostCmd_CMD_TDLS_OPER:
		ret = mwifiex_ret_tdls_oper(priv, resp);
		break;
1120 1121
	default:
		dev_err(adapter->dev, "CMD_RESP: unknown cmd response %#x\n",
1122
			resp->command);
1123 1124 1125 1126 1127
		break;
	}

	return ret;
}