File Index
Files and directories
Sign in
FILE

cmdevt.c

File preview with syntax highlighting.

linux-6.19.14/drivers/net/wireless/marvell/mwifiex/cmdevt.c C
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * NXP Wireless LAN device driver: commands and events
   4 *
   5 * Copyright 2011-2020 NXP
   6 */
   7
   8#include <linux/unaligned.h>
   9#include "decl.h"
  10#include "ioctl.h"
  11#include "util.h"
  12#include "fw.h"
  13#include "main.h"
  14#include "wmm.h"
  15#include "11n.h"
  16
  17static void mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter);
  18
  19/*
  20 * This function initializes a command node.
  21 *
  22 * The actual allocation of the node is not done by this function. It only
  23 * initiates a node by filling it with default parameters. Similarly,
  24 * allocation of the different buffers used (IOCTL buffer, data buffer) are
  25 * not done by this function either.
  26 */
  27static void
  28mwifiex_init_cmd_node(struct mwifiex_private *priv,
  29		      struct cmd_ctrl_node *cmd_node,
  30		      u32 cmd_no, void *data_buf, bool sync)
  31{
  32	cmd_node->priv = priv;
  33	cmd_node->cmd_no = cmd_no;
  34
  35	if (sync) {
  36		cmd_node->wait_q_enabled = true;
  37		cmd_node->cmd_wait_q_woken = false;
  38		cmd_node->condition = &cmd_node->cmd_wait_q_woken;
  39	}
  40	cmd_node->data_buf = data_buf;
  41	cmd_node->cmd_skb = cmd_node->skb;
  42}
  43
  44/*
  45 * This function returns a command node from the free queue depending upon
  46 * availability.
  47 */
  48static struct cmd_ctrl_node *
  49mwifiex_get_cmd_node(struct mwifiex_adapter *adapter)
  50{
  51	struct cmd_ctrl_node *cmd_node;
  52
  53	spin_lock_bh(&adapter->cmd_free_q_lock);
  54	if (list_empty(&adapter->cmd_free_q)) {
  55		mwifiex_dbg(adapter, ERROR,
  56			    "GET_CMD_NODE: cmd node not available\n");
  57		spin_unlock_bh(&adapter->cmd_free_q_lock);
  58		return NULL;
  59	}
  60	cmd_node = list_first_entry(&adapter->cmd_free_q,
  61				    struct cmd_ctrl_node, list);
  62	list_del(&cmd_node->list);
  63	spin_unlock_bh(&adapter->cmd_free_q_lock);
  64
  65	return cmd_node;
  66}
  67
  68/*
  69 * This function cleans up a command node.
  70 *
  71 * The function resets the fields including the buffer pointers.
  72 * This function does not try to free the buffers. They must be
  73 * freed before calling this function.
  74 *
  75 * This function will however call the receive completion callback
  76 * in case a response buffer is still available before resetting
  77 * the pointer.
  78 */
  79static void
  80mwifiex_clean_cmd_node(struct mwifiex_adapter *adapter,
  81		       struct cmd_ctrl_node *cmd_node)
  82{
  83	cmd_node->cmd_no = 0;
  84	cmd_node->cmd_flag = 0;
  85	cmd_node->data_buf = NULL;
  86	cmd_node->wait_q_enabled = false;
  87
  88	if (cmd_node->cmd_skb)
  89		skb_trim(cmd_node->cmd_skb, 0);
  90
  91	if (cmd_node->resp_skb) {
  92		adapter->if_ops.cmdrsp_complete(adapter, cmd_node->resp_skb);
  93		cmd_node->resp_skb = NULL;
  94	}
  95}
  96
  97/*
  98 * This function returns a command to the command free queue.
  99 *
 100 * The function also calls the completion callback if required, before
 101 * cleaning the command node and re-inserting it into the free queue.
 102 */
 103static void
 104mwifiex_insert_cmd_to_free_q(struct mwifiex_adapter *adapter,
 105			     struct cmd_ctrl_node *cmd_node)
 106{
 107	if (!cmd_node)
 108		return;
 109
 110	if (cmd_node->wait_q_enabled)
 111		mwifiex_complete_cmd(adapter, cmd_node);
 112	/* Clean the node */
 113	mwifiex_clean_cmd_node(adapter, cmd_node);
 114
 115	/* Insert node into cmd_free_q */
 116	spin_lock_bh(&adapter->cmd_free_q_lock);
 117	list_add_tail(&cmd_node->list, &adapter->cmd_free_q);
 118	spin_unlock_bh(&adapter->cmd_free_q_lock);
 119}
 120
 121/* This function reuses a command node. */
 122void mwifiex_recycle_cmd_node(struct mwifiex_adapter *adapter,
 123			      struct cmd_ctrl_node *cmd_node)
 124{
 125	struct host_cmd_ds_command *host_cmd = (void *)cmd_node->cmd_skb->data;
 126
 127	mwifiex_insert_cmd_to_free_q(adapter, cmd_node);
 128
 129	atomic_dec(&adapter->cmd_pending);
 130	mwifiex_dbg(adapter, CMD,
 131		    "cmd: FREE_CMD: cmd=%#x, cmd_pending=%d\n",
 132		le16_to_cpu(host_cmd->command),
 133		atomic_read(&adapter->cmd_pending));
 134}
 135
 136/*
 137 * This function sends a host command to the firmware.
 138 *
 139 * The function copies the host command into the driver command
 140 * buffer, which will be transferred to the firmware later by the
 141 * main thread.
 142 */
 143static int mwifiex_cmd_host_cmd(struct mwifiex_private *priv,
 144				struct host_cmd_ds_command *cmd,
 145				struct mwifiex_ds_misc_cmd *pcmd_ptr)
 146{
 147	/* Copy the HOST command to command buffer */
 148	memcpy(cmd, pcmd_ptr->cmd, pcmd_ptr->len);
 149	mwifiex_dbg(priv->adapter, CMD,
 150		    "cmd: host cmd size = %d\n", pcmd_ptr->len);
 151	return 0;
 152}
 153
 154/*
 155 * This function downloads a command to the firmware.
 156 *
 157 * The function performs sanity tests, sets the command sequence
 158 * number and size, converts the header fields to CPU format before
 159 * sending. Afterwards, it logs the command ID and action for debugging
 160 * and sets up the command timeout timer.
 161 */
 162static int mwifiex_dnld_cmd_to_fw(struct mwifiex_adapter *adapter,
 163				  struct cmd_ctrl_node *cmd_node)
 164{
 165	int ret;
 166	struct host_cmd_ds_command *host_cmd;
 167	uint16_t cmd_code;
 168	uint16_t cmd_size;
 169
 170	if (!adapter || !cmd_node)
 171		return -1;
 172
 173	host_cmd = (struct host_cmd_ds_command *) (cmd_node->cmd_skb->data);
 174
 175	/* Sanity test */
 176	if (host_cmd->size == 0) {
 177		mwifiex_dbg(adapter, ERROR,
 178			    "DNLD_CMD: host_cmd is null\t"
 179			    "or cmd size is 0, not sending\n");
 180		if (cmd_node->wait_q_enabled)
 181			adapter->cmd_wait_q.status = -1;
 182		mwifiex_recycle_cmd_node(adapter, cmd_node);
 183		return -1;
 184	}
 185
 186	cmd_code = le16_to_cpu(host_cmd->command);
 187	cmd_node->cmd_no = cmd_code;
 188	cmd_size = le16_to_cpu(host_cmd->size);
 189
 190	if (adapter->hw_status == MWIFIEX_HW_STATUS_RESET &&
 191	    cmd_code != HostCmd_CMD_FUNC_SHUTDOWN &&
 192	    cmd_code != HostCmd_CMD_FUNC_INIT) {
 193		mwifiex_dbg(adapter, ERROR,
 194			    "DNLD_CMD: FW in reset state, ignore cmd %#x\n",
 195			cmd_code);
 196		mwifiex_recycle_cmd_node(adapter, cmd_node);
 197		queue_work(adapter->workqueue, &adapter->main_work);
 198		return -1;
 199	}
 200
 201	/* Set command sequence number */
 202	adapter->seq_num++;
 203	host_cmd->seq_num = cpu_to_le16(HostCmd_SET_SEQ_NO_BSS_INFO
 204					(adapter->seq_num,
 205					 cmd_node->priv->bss_num,
 206					 cmd_node->priv->bss_type));
 207
 208	spin_lock_bh(&adapter->mwifiex_cmd_lock);
 209	adapter->curr_cmd = cmd_node;
 210	spin_unlock_bh(&adapter->mwifiex_cmd_lock);
 211
 212	/* Adjust skb length */
 213	if (cmd_node->cmd_skb->len > cmd_size)
 214		/*
 215		 * cmd_size is less than sizeof(struct host_cmd_ds_command).
 216		 * Trim off the unused portion.
 217		 */
 218		skb_trim(cmd_node->cmd_skb, cmd_size);
 219	else if (cmd_node->cmd_skb->len < cmd_size)
 220		/*
 221		 * cmd_size is larger than sizeof(struct host_cmd_ds_command)
 222		 * because we have appended custom IE TLV. Increase skb length
 223		 * accordingly.
 224		 */
 225		skb_put(cmd_node->cmd_skb, cmd_size - cmd_node->cmd_skb->len);
 226
 227	mwifiex_dbg(adapter, CMD,
 228		    "cmd: DNLD_CMD: %#x, act %#x, len %d, seqno %#x\n",
 229		    cmd_code,
 230		    get_unaligned_le16((u8 *)host_cmd + S_DS_GEN),
 231		    cmd_size, le16_to_cpu(host_cmd->seq_num));
 232	mwifiex_dbg_dump(adapter, CMD_D, "cmd buffer:", host_cmd, cmd_size);
 233
 234	if (adapter->iface_type == MWIFIEX_USB) {
 235		skb_push(cmd_node->cmd_skb, MWIFIEX_TYPE_LEN);
 236		put_unaligned_le32(MWIFIEX_USB_TYPE_CMD,
 237				   cmd_node->cmd_skb->data);
 238		adapter->cmd_sent = true;
 239		ret = adapter->if_ops.host_to_card(adapter,
 240						   MWIFIEX_USB_EP_CMD_EVENT,
 241						   cmd_node->cmd_skb, NULL);
 242		skb_pull(cmd_node->cmd_skb, MWIFIEX_TYPE_LEN);
 243		if (ret == -EBUSY)
 244			cmd_node->cmd_skb = NULL;
 245	} else {
 246		skb_push(cmd_node->cmd_skb, adapter->intf_hdr_len);
 247		ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_TYPE_CMD,
 248						   cmd_node->cmd_skb, NULL);
 249		skb_pull(cmd_node->cmd_skb, adapter->intf_hdr_len);
 250	}
 251
 252	if (ret == -1) {
 253		mwifiex_dbg(adapter, ERROR,
 254			    "DNLD_CMD: host to card failed\n");
 255		if (adapter->iface_type == MWIFIEX_USB)
 256			adapter->cmd_sent = false;
 257		if (cmd_node->wait_q_enabled)
 258			adapter->cmd_wait_q.status = -1;
 259		mwifiex_recycle_cmd_node(adapter, adapter->curr_cmd);
 260
 261		spin_lock_bh(&adapter->mwifiex_cmd_lock);
 262		adapter->curr_cmd = NULL;
 263		spin_unlock_bh(&adapter->mwifiex_cmd_lock);
 264
 265		adapter->dbg.num_cmd_host_to_card_failure++;
 266		return -1;
 267	}
 268
 269	/* Save the last command id and action to debug log */
 270	adapter->dbg.last_cmd_index =
 271			(adapter->dbg.last_cmd_index + 1) % DBG_CMD_NUM;
 272	adapter->dbg.last_cmd_id[adapter->dbg.last_cmd_index] = cmd_code;
 273	adapter->dbg.last_cmd_act[adapter->dbg.last_cmd_index] =
 274			get_unaligned_le16((u8 *)host_cmd + S_DS_GEN);
 275
 276	/* Setup the timer after transmit command, except that specific
 277	 * command might not have command response.
 278	 */
 279	if (cmd_code != HostCmd_CMD_FW_DUMP_EVENT)
 280		mod_timer(&adapter->cmd_timer,
 281			  jiffies + msecs_to_jiffies(MWIFIEX_TIMER_10S));
 282
 283	/* Clear BSS_NO_BITS from HostCmd */
 284	cmd_code &= HostCmd_CMD_ID_MASK;
 285
 286	return 0;
 287}
 288
 289/*
 290 * This function downloads a sleep confirm command to the firmware.
 291 *
 292 * The function performs sanity tests, sets the command sequence
 293 * number and size, converts the header fields to CPU format before
 294 * sending.
 295 *
 296 * No responses are needed for sleep confirm command.
 297 */
 298static int mwifiex_dnld_sleep_confirm_cmd(struct mwifiex_adapter *adapter)
 299{
 300	int ret;
 301	struct mwifiex_private *priv;
 302	struct mwifiex_opt_sleep_confirm *sleep_cfm_buf =
 303				(struct mwifiex_opt_sleep_confirm *)
 304						adapter->sleep_cfm->data;
 305	struct sk_buff *sleep_cfm_tmp;
 306
 307	priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);
 308
 309	adapter->seq_num++;
 310	sleep_cfm_buf->seq_num =
 311		cpu_to_le16(HostCmd_SET_SEQ_NO_BSS_INFO
 312					(adapter->seq_num, priv->bss_num,
 313					 priv->bss_type));
 314
 315	mwifiex_dbg(adapter, CMD,
 316		    "cmd: DNLD_CMD: %#x, act %#x, len %d, seqno %#x\n",
 317		le16_to_cpu(sleep_cfm_buf->command),
 318		le16_to_cpu(sleep_cfm_buf->action),
 319		le16_to_cpu(sleep_cfm_buf->size),
 320		le16_to_cpu(sleep_cfm_buf->seq_num));
 321	mwifiex_dbg_dump(adapter, CMD_D, "SLEEP_CFM buffer: ", sleep_cfm_buf,
 322			 le16_to_cpu(sleep_cfm_buf->size));
 323
 324	if (adapter->iface_type == MWIFIEX_USB) {
 325		sleep_cfm_tmp =
 326			dev_alloc_skb(sizeof(struct mwifiex_opt_sleep_confirm)
 327				      + MWIFIEX_TYPE_LEN);
 328		if (!sleep_cfm_tmp) {
 329			mwifiex_dbg(adapter, ERROR,
 330				    "SLEEP_CFM: dev_alloc_skb failed\n");
 331			return -ENOMEM;
 332		}
 333
 334		skb_put(sleep_cfm_tmp, sizeof(struct mwifiex_opt_sleep_confirm)
 335			+ MWIFIEX_TYPE_LEN);
 336		put_unaligned_le32(MWIFIEX_USB_TYPE_CMD, sleep_cfm_tmp->data);
 337		memcpy(sleep_cfm_tmp->data + MWIFIEX_TYPE_LEN,
 338		       adapter->sleep_cfm->data,
 339		       sizeof(struct mwifiex_opt_sleep_confirm));
 340		ret = adapter->if_ops.host_to_card(adapter,
 341						   MWIFIEX_USB_EP_CMD_EVENT,
 342						   sleep_cfm_tmp, NULL);
 343		if (ret != -EBUSY)
 344			dev_kfree_skb_any(sleep_cfm_tmp);
 345	} else {
 346		skb_push(adapter->sleep_cfm, adapter->intf_hdr_len);
 347		ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_TYPE_CMD,
 348						   adapter->sleep_cfm, NULL);
 349		skb_pull(adapter->sleep_cfm, adapter->intf_hdr_len);
 350	}
 351
 352	if (ret == -1) {
 353		mwifiex_dbg(adapter, ERROR, "SLEEP_CFM: failed\n");
 354		adapter->dbg.num_cmd_sleep_cfm_host_to_card_failure++;
 355		return -1;
 356	}
 357
 358	if (!le16_to_cpu(sleep_cfm_buf->resp_ctrl))
 359		/* Response is not needed for sleep confirm command */
 360		adapter->ps_state = PS_STATE_SLEEP;
 361	else
 362		adapter->ps_state = PS_STATE_SLEEP_CFM;
 363
 364	if (!le16_to_cpu(sleep_cfm_buf->resp_ctrl) &&
 365	    (test_bit(MWIFIEX_IS_HS_CONFIGURED, &adapter->work_flags) &&
 366	     !adapter->sleep_period.period)) {
 367		adapter->pm_wakeup_card_req = true;
 368		mwifiex_hs_activated_event(adapter, true);
 369	}
 370
 371	return ret;
 372}
 373
 374/*
 375 * This function allocates the command buffers and links them to
 376 * the command free queue.
 377 *
 378 * The driver uses a pre allocated number of command buffers, which
 379 * are created at driver initializations and freed at driver cleanup.
 380 * Every command needs to obtain a command buffer from this pool before
 381 * it can be issued. The command free queue lists the command buffers
 382 * currently free to use, while the command pending queue lists the
 383 * command buffers already in use and awaiting handling. Command buffers
 384 * are returned to the free queue after use.
 385 */
 386int mwifiex_alloc_cmd_buffer(struct mwifiex_adapter *adapter)
 387{
 388	struct cmd_ctrl_node *cmd_array;
 389	u32 i;
 390
 391	/* Allocate and initialize struct cmd_ctrl_node */
 392	cmd_array = kcalloc(MWIFIEX_NUM_OF_CMD_BUFFER,
 393			    sizeof(struct cmd_ctrl_node), GFP_KERNEL);
 394	if (!cmd_array)
 395		return -ENOMEM;
 396
 397	adapter->cmd_pool = cmd_array;
 398
 399	/* Allocate and initialize command buffers */
 400	for (i = 0; i < MWIFIEX_NUM_OF_CMD_BUFFER; i++) {
 401		cmd_array[i].skb = dev_alloc_skb(MWIFIEX_SIZE_OF_CMD_BUFFER);
 402		if (!cmd_array[i].skb) {
 403			mwifiex_dbg(adapter, ERROR,
 404				    "unable to allocate command buffer\n");
 405			return -ENOMEM;
 406		}
 407	}
 408
 409	for (i = 0; i < MWIFIEX_NUM_OF_CMD_BUFFER; i++)
 410		mwifiex_insert_cmd_to_free_q(adapter, &cmd_array[i]);
 411
 412	return 0;
 413}
 414
 415/*
 416 * This function frees the command buffers.
 417 *
 418 * The function calls the completion callback for all the command
 419 * buffers that still have response buffers associated with them.
 420 */
 421void mwifiex_free_cmd_buffer(struct mwifiex_adapter *adapter)
 422{
 423	struct cmd_ctrl_node *cmd_array;
 424	u32 i;
 425
 426	/* Need to check if cmd pool is allocated or not */
 427	if (!adapter->cmd_pool) {
 428		mwifiex_dbg(adapter, FATAL,
 429			    "info: FREE_CMD_BUF: cmd_pool is null\n");
 430		return;
 431	}
 432
 433	cmd_array = adapter->cmd_pool;
 434
 435	/* Release shared memory buffers */
 436	for (i = 0; i < MWIFIEX_NUM_OF_CMD_BUFFER; i++) {
 437		if (cmd_array[i].skb) {
 438			mwifiex_dbg(adapter, CMD,
 439				    "cmd: free cmd buffer %d\n", i);
 440			dev_kfree_skb_any(cmd_array[i].skb);
 441		}
 442		if (!cmd_array[i].resp_skb)
 443			continue;
 444
 445		if (adapter->iface_type == MWIFIEX_USB)
 446			adapter->if_ops.cmdrsp_complete(adapter,
 447							cmd_array[i].resp_skb);
 448		else
 449			dev_kfree_skb_any(cmd_array[i].resp_skb);
 450	}
 451	/* Release struct cmd_ctrl_node */
 452	if (adapter->cmd_pool) {
 453		mwifiex_dbg(adapter, CMD,
 454			    "cmd: free cmd pool\n");
 455		kfree(adapter->cmd_pool);
 456		adapter->cmd_pool = NULL;
 457	}
 458}
 459
 460/*
 461 * This function handles events generated by firmware.
 462 *
 463 * Event body of events received from firmware are not used (though they are
 464 * saved), only the event ID is used. Some events are re-invoked by
 465 * the driver, with a new event body.
 466 *
 467 * After processing, the function calls the completion callback
 468 * for cleanup.
 469 */
 470int mwifiex_process_event(struct mwifiex_adapter *adapter)
 471{
 472	int ret, i;
 473	struct mwifiex_private *priv;
 474	struct sk_buff *skb = adapter->event_skb;
 475	u32 eventcause;
 476	struct mwifiex_rxinfo *rx_info;
 477
 478	if ((adapter->event_cause & EVENT_ID_MASK) == EVENT_RADAR_DETECTED) {
 479		for (i = 0; i < adapter->priv_num; i++) {
 480			priv = adapter->priv[i];
 481			if (mwifiex_is_11h_active(priv)) {
 482				adapter->event_cause |=
 483					((priv->bss_num & 0xff) << 16) |
 484					((priv->bss_type & 0xff) << 24);
 485				break;
 486			}
 487		}
 488	}
 489
 490	eventcause = adapter->event_cause;
 491
 492	/* Save the last event to debug log */
 493	adapter->dbg.last_event_index =
 494			(adapter->dbg.last_event_index + 1) % DBG_CMD_NUM;
 495	adapter->dbg.last_event[adapter->dbg.last_event_index] =
 496							(u16) eventcause;
 497
 498	/* Get BSS number and corresponding priv */
 499	priv = mwifiex_get_priv_by_id(adapter, EVENT_GET_BSS_NUM(eventcause),
 500				      EVENT_GET_BSS_TYPE(eventcause));
 501	if (!priv)
 502		priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);
 503
 504	/* Clear BSS_NO_BITS from event */
 505	eventcause &= EVENT_ID_MASK;
 506	adapter->event_cause = eventcause;
 507
 508	if (skb) {
 509		rx_info = MWIFIEX_SKB_RXCB(skb);
 510		memset(rx_info, 0, sizeof(*rx_info));
 511		rx_info->bss_num = priv->bss_num;
 512		rx_info->bss_type = priv->bss_type;
 513		mwifiex_dbg_dump(adapter, EVT_D, "Event Buf:",
 514				 skb->data, skb->len);
 515	}
 516
 517	mwifiex_dbg(adapter, EVENT, "EVENT: cause: %#x\n", eventcause);
 518
 519	if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP)
 520		ret = mwifiex_process_uap_event(priv);
 521	else
 522		ret = mwifiex_process_sta_event(priv);
 523
 524	adapter->event_cause = 0;
 525	adapter->event_skb = NULL;
 526	adapter->if_ops.event_complete(adapter, skb);
 527
 528	return ret;
 529}
 530
 531/*
 532 * This function prepares a command and send it to the firmware.
 533 *
 534 * Preparation includes -
 535 *      - Sanity tests to make sure the card is still present or the FW
 536 *        is not reset
 537 *      - Getting a new command node from the command free queue
 538 *      - Initializing the command node for default parameters
 539 *      - Fill up the non-default parameters and buffer pointers
 540 *      - Add the command to pending queue
 541 */
 542int mwifiex_send_cmd(struct mwifiex_private *priv, u16 cmd_no,
 543		     u16 cmd_action, u32 cmd_oid, void *data_buf, bool sync)
 544{
 545	int ret;
 546	struct mwifiex_adapter *adapter = priv->adapter;
 547	struct cmd_ctrl_node *cmd_node;
 548	struct host_cmd_ds_command *cmd_ptr;
 549
 550	if (!adapter) {
 551		pr_err("PREP_CMD: adapter is NULL\n");
 552		return -1;
 553	}
 554
 555	if (test_bit(MWIFIEX_IS_SUSPENDED, &adapter->work_flags)) {
 556		mwifiex_dbg(adapter, ERROR,
 557			    "PREP_CMD: device in suspended state\n");
 558		return -1;
 559	}
 560
 561	if (test_bit(MWIFIEX_IS_HS_ENABLING, &adapter->work_flags) &&
 562	    cmd_no != HostCmd_CMD_802_11_HS_CFG_ENH) {
 563		mwifiex_dbg(adapter, ERROR,
 564			    "PREP_CMD: host entering sleep state\n");
 565		return -1;
 566	}
 567
 568	if (test_bit(MWIFIEX_SURPRISE_REMOVED, &adapter->work_flags)) {
 569		mwifiex_dbg(adapter, ERROR,
 570			    "PREP_CMD: card is removed\n");
 571		return -1;
 572	}
 573
 574	if (test_bit(MWIFIEX_IS_CMD_TIMEDOUT, &adapter->work_flags)) {
 575		mwifiex_dbg(adapter, ERROR,
 576			    "PREP_CMD: FW is in bad state\n");
 577		return -1;
 578	}
 579
 580	if (adapter->hw_status == MWIFIEX_HW_STATUS_RESET) {
 581		if (cmd_no != HostCmd_CMD_FUNC_INIT) {
 582			mwifiex_dbg(adapter, ERROR,
 583				    "PREP_CMD: FW in reset state\n");
 584			return -1;
 585		}
 586	}
 587	/* We don't expect commands in manufacturing mode. They are cooked
 588	 * in application and ready to download buffer is passed to the driver
 589	 */
 590	if (adapter->mfg_mode && cmd_no) {
 591		dev_dbg(adapter->dev, "Ignoring commands in manufacturing mode\n");
 592		return -1;
 593	}
 594
 595	if (priv->adapter->hs_activated_manually &&
 596	    cmd_no != HostCmd_CMD_802_11_HS_CFG_ENH) {
 597		mwifiex_cancel_hs(priv, MWIFIEX_ASYNC_CMD);
 598		priv->adapter->hs_activated_manually = false;
 599	}
 600
 601	/* Get a new command node */
 602	cmd_node = mwifiex_get_cmd_node(adapter);
 603
 604	if (!cmd_node) {
 605		mwifiex_dbg(adapter, ERROR,
 606			    "PREP_CMD: no free cmd node\n");
 607		return -1;
 608	}
 609
 610	/* Initialize the command node */
 611	mwifiex_init_cmd_node(priv, cmd_node, cmd_no, data_buf, sync);
 612
 613	if (!cmd_node->cmd_skb) {
 614		mwifiex_dbg(adapter, ERROR,
 615			    "PREP_CMD: no free cmd buf\n");
 616		return -1;
 617	}
 618
 619	skb_put_zero(cmd_node->cmd_skb, sizeof(struct host_cmd_ds_command));
 620
 621	cmd_ptr = (struct host_cmd_ds_command *) (cmd_node->cmd_skb->data);
 622	cmd_ptr->command = cpu_to_le16(cmd_no);
 623	cmd_ptr->result = 0;
 624
 625	/* Prepare command */
 626	if (cmd_no) {
 627		switch (cmd_no) {
 628		case HostCmd_CMD_UAP_SYS_CONFIG:
 629		case HostCmd_CMD_UAP_BSS_START:
 630		case HostCmd_CMD_UAP_BSS_STOP:
 631		case HostCmd_CMD_UAP_STA_DEAUTH:
 632		case HOST_CMD_APCMD_SYS_RESET:
 633		case HOST_CMD_APCMD_STA_LIST:
 634		case HostCmd_CMD_CHAN_REPORT_REQUEST:
 635		case HostCmd_CMD_ADD_NEW_STATION:
 636			ret = mwifiex_uap_prepare_cmd(priv, cmd_no, cmd_action,
 637						      cmd_oid, data_buf,
 638						      cmd_ptr);
 639			break;
 640		default:
 641			ret = mwifiex_sta_prepare_cmd(priv, cmd_no, cmd_action,
 642						      cmd_oid, data_buf,
 643						      cmd_ptr);
 644			break;
 645		}
 646	} else {
 647		ret = mwifiex_cmd_host_cmd(priv, cmd_ptr, data_buf);
 648		cmd_node->cmd_flag |= CMD_F_HOSTCMD;
 649	}
 650
 651	/* Return error, since the command preparation failed */
 652	if (ret) {
 653		mwifiex_dbg(adapter, ERROR,
 654			    "PREP_CMD: cmd %#x preparation failed\n",
 655			cmd_no);
 656		mwifiex_insert_cmd_to_free_q(adapter, cmd_node);
 657		return -1;
 658	}
 659
 660	/* Send command */
 661	if (cmd_no == HostCmd_CMD_802_11_SCAN ||
 662	    cmd_no == HostCmd_CMD_802_11_SCAN_EXT) {
 663		mwifiex_queue_scan_cmd(priv, cmd_node);
 664	} else {
 665		mwifiex_insert_cmd_to_pending_q(adapter, cmd_node);
 666		queue_work(adapter->workqueue, &adapter->main_work);
 667		if (cmd_node->wait_q_enabled)
 668			ret = mwifiex_wait_queue_complete(adapter, cmd_node);
 669	}
 670
 671	return ret;
 672}
 673
 674/*
 675 * This function queues a command to the command pending queue.
 676 *
 677 * This in effect adds the command to the command list to be executed.
 678 * Exit PS command is handled specially, by placing it always to the
 679 * front of the command queue.
 680 */
 681void
 682mwifiex_insert_cmd_to_pending_q(struct mwifiex_adapter *adapter,
 683				struct cmd_ctrl_node *cmd_node)
 684{
 685	struct host_cmd_ds_command *host_cmd = NULL;
 686	u16 command;
 687	bool add_tail = true;
 688
 689	host_cmd = (struct host_cmd_ds_command *) (cmd_node->cmd_skb->data);
 690	if (!host_cmd) {
 691		mwifiex_dbg(adapter, ERROR, "QUEUE_CMD: host_cmd is NULL\n");
 692		return;
 693	}
 694
 695	command = le16_to_cpu(host_cmd->command);
 696
 697	/* Exit_PS command needs to be queued in the header always. */
 698	if (command == HostCmd_CMD_802_11_PS_MODE_ENH) {
 699		struct host_cmd_ds_802_11_ps_mode_enh *pm =
 700						&host_cmd->params.psmode_enh;
 701		if ((le16_to_cpu(pm->action) == DIS_PS) ||
 702		    (le16_to_cpu(pm->action) == DIS_AUTO_PS)) {
 703			if (adapter->ps_state != PS_STATE_AWAKE)
 704				add_tail = false;
 705		}
 706	}
 707
 708	/* Same with exit host sleep cmd, luckily that can't happen at the same time as EXIT_PS */
 709	if (command == HostCmd_CMD_802_11_HS_CFG_ENH) {
 710		struct host_cmd_ds_802_11_hs_cfg_enh *hs_cfg =
 711			&host_cmd->params.opt_hs_cfg;
 712
 713		if (le16_to_cpu(hs_cfg->action) == HS_ACTIVATE)
 714				add_tail = false;
 715	}
 716
 717	spin_lock_bh(&adapter->cmd_pending_q_lock);
 718	if (add_tail)
 719		list_add_tail(&cmd_node->list, &adapter->cmd_pending_q);
 720	else
 721		list_add(&cmd_node->list, &adapter->cmd_pending_q);
 722	spin_unlock_bh(&adapter->cmd_pending_q_lock);
 723
 724	atomic_inc(&adapter->cmd_pending);
 725	mwifiex_dbg(adapter, CMD,
 726		    "cmd: QUEUE_CMD: cmd=%#x, cmd_pending=%d\n",
 727		command, atomic_read(&adapter->cmd_pending));
 728}
 729
 730/*
 731 * This function executes the next command in command pending queue.
 732 *
 733 * This function will fail if a command is already in processing stage,
 734 * otherwise it will dequeue the first command from the command pending
 735 * queue and send to the firmware.
 736 *
 737 * If the device is currently in host sleep mode, any commands, except the
 738 * host sleep configuration command will de-activate the host sleep. For PS
 739 * mode, the function will put the firmware back to sleep if applicable.
 740 */
 741int mwifiex_exec_next_cmd(struct mwifiex_adapter *adapter)
 742{
 743	struct cmd_ctrl_node *cmd_node;
 744	int ret = 0;
 745	struct host_cmd_ds_command *host_cmd;
 746
 747	/* Check if already in processing */
 748	if (adapter->curr_cmd) {
 749		mwifiex_dbg(adapter, FATAL,
 750			    "EXEC_NEXT_CMD: cmd in processing\n");
 751		return -1;
 752	}
 753
 754	spin_lock_bh(&adapter->mwifiex_cmd_lock);
 755	/* Check if any command is pending */
 756	spin_lock_bh(&adapter->cmd_pending_q_lock);
 757	if (list_empty(&adapter->cmd_pending_q)) {
 758		spin_unlock_bh(&adapter->cmd_pending_q_lock);
 759		spin_unlock_bh(&adapter->mwifiex_cmd_lock);
 760		return 0;
 761	}
 762	cmd_node = list_first_entry(&adapter->cmd_pending_q,
 763				    struct cmd_ctrl_node, list);
 764
 765	host_cmd = (struct host_cmd_ds_command *) (cmd_node->cmd_skb->data);
 766
 767	if (adapter->ps_state != PS_STATE_AWAKE) {
 768		mwifiex_dbg(adapter, ERROR,
 769			    "%s: cannot send cmd in sleep state,\t"
 770			    "this should not happen\n", __func__);
 771		spin_unlock_bh(&adapter->cmd_pending_q_lock);
 772		spin_unlock_bh(&adapter->mwifiex_cmd_lock);
 773		return ret;
 774	}
 775
 776	list_del(&cmd_node->list);
 777	spin_unlock_bh(&adapter->cmd_pending_q_lock);
 778
 779	spin_unlock_bh(&adapter->mwifiex_cmd_lock);
 780	ret = mwifiex_dnld_cmd_to_fw(adapter, cmd_node);
 781
 782	/* Any command sent to the firmware when host is in sleep
 783	 * mode should de-configure host sleep. We should skip the
 784	 * host sleep configuration command itself though
 785	 */
 786	if (host_cmd->command != cpu_to_le16(HostCmd_CMD_802_11_HS_CFG_ENH)) {
 787		if (adapter->hs_activated) {
 788			clear_bit(MWIFIEX_IS_HS_CONFIGURED,
 789				  &adapter->work_flags);
 790			mwifiex_hs_activated_event(adapter, false);
 791		}
 792	}
 793
 794	return ret;
 795}
 796
 797/*
 798 * This function handles the command response.
 799 *
 800 * After processing, the function cleans the command node and puts
 801 * it back to the command free queue.
 802 */
 803int mwifiex_process_cmdresp(struct mwifiex_adapter *adapter)
 804{
 805	struct host_cmd_ds_command *resp;
 806	struct mwifiex_private *priv;
 807	int ret = 0;
 808	uint16_t orig_cmdresp_no;
 809	uint16_t cmdresp_no;
 810	uint16_t cmdresp_result;
 811
 812	if (!adapter->curr_cmd || !adapter->curr_cmd->resp_skb) {
 813		resp = (struct host_cmd_ds_command *) adapter->upld_buf;
 814		mwifiex_dbg(adapter, ERROR,
 815			    "CMD_RESP: NULL curr_cmd, %#x\n",
 816			    le16_to_cpu(resp->command));
 817		return -1;
 818	}
 819
 820	resp = (struct host_cmd_ds_command *)adapter->curr_cmd->resp_skb->data;
 821	orig_cmdresp_no = le16_to_cpu(resp->command);
 822	cmdresp_no = (orig_cmdresp_no & HostCmd_CMD_ID_MASK);
 823
 824	if (adapter->curr_cmd->cmd_no != cmdresp_no) {
 825		mwifiex_dbg(adapter, ERROR,
 826			    "cmdresp error: cmd=0x%x cmd_resp=0x%x\n",
 827			    adapter->curr_cmd->cmd_no, cmdresp_no);
 828		return -1;
 829	}
 830	/* Now we got response from FW, cancel the command timer */
 831	timer_delete_sync(&adapter->cmd_timer);
 832	clear_bit(MWIFIEX_IS_CMD_TIMEDOUT, &adapter->work_flags);
 833
 834	if (adapter->curr_cmd->cmd_flag & CMD_F_HOSTCMD) {
 835		/* Copy original response back to response buffer */
 836		struct mwifiex_ds_misc_cmd *hostcmd;
 837		uint16_t size = le16_to_cpu(resp->size);
 838		mwifiex_dbg(adapter, INFO,
 839			    "info: host cmd resp size = %d\n", size);
 840		size = min_t(u16, size, MWIFIEX_SIZE_OF_CMD_BUFFER);
 841		if (adapter->curr_cmd->data_buf) {
 842			hostcmd = adapter->curr_cmd->data_buf;
 843			hostcmd->len = size;
 844			memcpy(hostcmd->cmd, resp, size);
 845		}
 846	}
 847
 848	/* Get BSS number and corresponding priv */
 849	priv = mwifiex_get_priv_by_id(adapter,
 850			     HostCmd_GET_BSS_NO(le16_to_cpu(resp->seq_num)),
 851			     HostCmd_GET_BSS_TYPE(le16_to_cpu(resp->seq_num)));
 852	if (!priv)
 853		priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);
 854	/* Clear RET_BIT from HostCmd */
 855	resp->command = cpu_to_le16(orig_cmdresp_no & HostCmd_CMD_ID_MASK);
 856
 857	cmdresp_no = le16_to_cpu(resp->command);
 858	cmdresp_result = le16_to_cpu(resp->result);
 859
 860	/* Save the last command response to debug log */
 861	adapter->dbg.last_cmd_resp_index =
 862			(adapter->dbg.last_cmd_resp_index + 1) % DBG_CMD_NUM;
 863	adapter->dbg.last_cmd_resp_id[adapter->dbg.last_cmd_resp_index] =
 864								orig_cmdresp_no;
 865
 866	mwifiex_dbg(adapter, CMD,
 867		    "cmd: CMD_RESP: 0x%x, result %d, len %d, seqno 0x%x\n",
 868		    orig_cmdresp_no, cmdresp_result,
 869		    le16_to_cpu(resp->size), le16_to_cpu(resp->seq_num));
 870	mwifiex_dbg_dump(adapter, CMD_D, "CMD_RESP buffer:", resp,
 871			 le16_to_cpu(resp->size));
 872
 873	if (!(orig_cmdresp_no & HostCmd_RET_BIT)) {
 874		mwifiex_dbg(adapter, ERROR, "CMD_RESP: invalid cmd resp\n");
 875		if (adapter->curr_cmd->wait_q_enabled)
 876			adapter->cmd_wait_q.status = -1;
 877
 878		mwifiex_recycle_cmd_node(adapter, adapter->curr_cmd);
 879		spin_lock_bh(&adapter->mwifiex_cmd_lock);
 880		adapter->curr_cmd = NULL;
 881		spin_unlock_bh(&adapter->mwifiex_cmd_lock);
 882		return -1;
 883	}
 884
 885	if (adapter->curr_cmd->cmd_flag & CMD_F_HOSTCMD) {
 886		adapter->curr_cmd->cmd_flag &= ~CMD_F_HOSTCMD;
 887		if ((cmdresp_result == HostCmd_RESULT_OK) &&
 888		    (cmdresp_no == HostCmd_CMD_802_11_HS_CFG_ENH))
 889			ret = mwifiex_ret_802_11_hs_cfg(priv, resp);
 890	} else {
 891		/* handle response */
 892		ret = mwifiex_process_sta_cmdresp(priv, cmdresp_no, resp);
 893	}
 894
 895	if (adapter->curr_cmd) {
 896		if (adapter->curr_cmd->wait_q_enabled)
 897			adapter->cmd_wait_q.status = ret;
 898
 899		mwifiex_recycle_cmd_node(adapter, adapter->curr_cmd);
 900
 901		spin_lock_bh(&adapter->mwifiex_cmd_lock);
 902		adapter->curr_cmd = NULL;
 903		spin_unlock_bh(&adapter->mwifiex_cmd_lock);
 904	}
 905
 906	return ret;
 907}
 908
 909void mwifiex_process_assoc_resp(struct mwifiex_adapter *adapter)
 910{
 911	struct cfg80211_rx_assoc_resp_data assoc_resp = {
 912		.uapsd_queues = -1,
 913	};
 914	struct mwifiex_private *priv =
 915		mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA);
 916
 917	if (priv->assoc_rsp_size) {
 918		assoc_resp.links[0].bss = priv->req_bss;
 919		assoc_resp.buf = priv->assoc_rsp_buf;
 920		assoc_resp.len = priv->assoc_rsp_size;
 921		wiphy_lock(priv->wdev.wiphy);
 922		cfg80211_rx_assoc_resp(priv->netdev,
 923				       &assoc_resp);
 924		wiphy_unlock(priv->wdev.wiphy);
 925		priv->assoc_rsp_size = 0;
 926	}
 927}
 928
 929/*
 930 * This function handles the timeout of command sending.
 931 *
 932 * It will re-send the same command again.
 933 */
 934void
 935mwifiex_cmd_timeout_func(struct timer_list *t)
 936{
 937	struct mwifiex_adapter *adapter = timer_container_of(adapter, t,
 938						             cmd_timer);
 939	struct cmd_ctrl_node *cmd_node;
 940
 941	set_bit(MWIFIEX_IS_CMD_TIMEDOUT, &adapter->work_flags);
 942	if (!adapter->curr_cmd) {
 943		mwifiex_dbg(adapter, ERROR,
 944			    "cmd: empty curr_cmd\n");
 945		return;
 946	}
 947	cmd_node = adapter->curr_cmd;
 948	if (cmd_node) {
 949		adapter->dbg.timeout_cmd_id =
 950			adapter->dbg.last_cmd_id[adapter->dbg.last_cmd_index];
 951		adapter->dbg.timeout_cmd_act =
 952			adapter->dbg.last_cmd_act[adapter->dbg.last_cmd_index];
 953		mwifiex_dbg(adapter, MSG,
 954			    "%s: Timeout cmd id = %#x, act = %#x\n", __func__,
 955			    adapter->dbg.timeout_cmd_id,
 956			    adapter->dbg.timeout_cmd_act);
 957
 958		mwifiex_dbg(adapter, MSG,
 959			    "num_data_h2c_failure = %d\n",
 960			    adapter->dbg.num_tx_host_to_card_failure);
 961		mwifiex_dbg(adapter, MSG,
 962			    "num_cmd_h2c_failure = %d\n",
 963			    adapter->dbg.num_cmd_host_to_card_failure);
 964
 965		mwifiex_dbg(adapter, MSG,
 966			    "is_cmd_timedout = %d\n",
 967			    test_bit(MWIFIEX_IS_CMD_TIMEDOUT,
 968				     &adapter->work_flags));
 969		mwifiex_dbg(adapter, MSG,
 970			    "num_tx_timeout = %d\n",
 971			    adapter->dbg.num_tx_timeout);
 972
 973		mwifiex_dbg(adapter, MSG,
 974			    "last_cmd_index = %d\n",
 975			    adapter->dbg.last_cmd_index);
 976		mwifiex_dbg(adapter, MSG,
 977			    "last_cmd_id: %*ph\n",
 978			    (int)sizeof(adapter->dbg.last_cmd_id),
 979			    adapter->dbg.last_cmd_id);
 980		mwifiex_dbg(adapter, MSG,
 981			    "last_cmd_act: %*ph\n",
 982			    (int)sizeof(adapter->dbg.last_cmd_act),
 983			    adapter->dbg.last_cmd_act);
 984
 985		mwifiex_dbg(adapter, MSG,
 986			    "last_cmd_resp_index = %d\n",
 987			    adapter->dbg.last_cmd_resp_index);
 988		mwifiex_dbg(adapter, MSG,
 989			    "last_cmd_resp_id: %*ph\n",
 990			    (int)sizeof(adapter->dbg.last_cmd_resp_id),
 991			    adapter->dbg.last_cmd_resp_id);
 992
 993		mwifiex_dbg(adapter, MSG,
 994			    "last_event_index = %d\n",
 995			    adapter->dbg.last_event_index);
 996		mwifiex_dbg(adapter, MSG,
 997			    "last_event: %*ph\n",
 998			    (int)sizeof(adapter->dbg.last_event),
 999			    adapter->dbg.last_event);
1000
1001		mwifiex_dbg(adapter, MSG,
1002			    "data_sent=%d cmd_sent=%d\n",
1003			    adapter->data_sent, adapter->cmd_sent);
1004
1005		mwifiex_dbg(adapter, MSG,
1006			    "ps_mode=%d ps_state=%d\n",
1007			    adapter->ps_mode, adapter->ps_state);
1008
1009		if (cmd_node->wait_q_enabled) {
1010			adapter->cmd_wait_q.status = -ETIMEDOUT;
1011			mwifiex_cancel_pending_ioctl(adapter);
1012		}
1013	}
1014
1015	if (adapter->if_ops.device_dump)
1016		adapter->if_ops.device_dump(adapter);
1017
1018	if (adapter->if_ops.card_reset)
1019		adapter->if_ops.card_reset(adapter);
1020}
1021
1022void
1023mwifiex_cancel_pending_scan_cmd(struct mwifiex_adapter *adapter)
1024{
1025	struct cmd_ctrl_node *cmd_node = NULL, *tmp_node;
1026
1027	/* Cancel all pending scan command */
1028	spin_lock_bh(&adapter->scan_pending_q_lock);
1029	list_for_each_entry_safe(cmd_node, tmp_node,
1030				 &adapter->scan_pending_q, list) {
1031		list_del(&cmd_node->list);
1032		cmd_node->wait_q_enabled = false;
1033		mwifiex_insert_cmd_to_free_q(adapter, cmd_node);
1034	}
1035	spin_unlock_bh(&adapter->scan_pending_q_lock);
1036}
1037
1038/*
1039 * This function cancels all the pending commands.
1040 *
1041 * The current command, all commands in command pending queue and all scan
1042 * commands in scan pending queue are cancelled. All the completion callbacks
1043 * are called with failure status to ensure cleanup.
1044 */
1045void
1046mwifiex_cancel_all_pending_cmd(struct mwifiex_adapter *adapter)
1047{
1048	struct cmd_ctrl_node *cmd_node = NULL, *tmp_node;
1049
1050	spin_lock_bh(&adapter->mwifiex_cmd_lock);
1051	/* Cancel current cmd */
1052	if ((adapter->curr_cmd) && (adapter->curr_cmd->wait_q_enabled)) {
1053		adapter->cmd_wait_q.status = -1;
1054		mwifiex_complete_cmd(adapter, adapter->curr_cmd);
1055		adapter->curr_cmd->wait_q_enabled = false;
1056		/* no recycle probably wait for response */
1057	}
1058	/* Cancel all pending command */
1059	spin_lock_bh(&adapter->cmd_pending_q_lock);
1060	list_for_each_entry_safe(cmd_node, tmp_node,
1061				 &adapter->cmd_pending_q, list) {
1062		list_del(&cmd_node->list);
1063
1064		if (cmd_node->wait_q_enabled)
1065			adapter->cmd_wait_q.status = -1;
1066		mwifiex_recycle_cmd_node(adapter, cmd_node);
1067	}
1068	spin_unlock_bh(&adapter->cmd_pending_q_lock);
1069	spin_unlock_bh(&adapter->mwifiex_cmd_lock);
1070
1071	mwifiex_cancel_scan(adapter);
1072}
1073
1074/*
1075 * This function cancels all pending commands that matches with
1076 * the given IOCTL request.
1077 *
1078 * Both the current command buffer and the pending command queue are
1079 * searched for matching IOCTL request. The completion callback of
1080 * the matched command is called with failure status to ensure cleanup.
1081 * In case of scan commands, all pending commands in scan pending queue
1082 * are cancelled.
1083 */
1084static void
1085mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter)
1086{
1087	struct cmd_ctrl_node *cmd_node = NULL;
1088
1089	if ((adapter->curr_cmd) &&
1090	    (adapter->curr_cmd->wait_q_enabled)) {
1091		spin_lock_bh(&adapter->mwifiex_cmd_lock);
1092		cmd_node = adapter->curr_cmd;
1093		/* setting curr_cmd to NULL is quite dangerous, because
1094		 * mwifiex_process_cmdresp checks curr_cmd to be != NULL
1095		 * at the beginning then relies on it and dereferences
1096		 * it at will
1097		 * this probably works since mwifiex_cmd_timeout_func
1098		 * is the only caller of this function and responses
1099		 * at that point
1100		 */
1101		adapter->curr_cmd = NULL;
1102		spin_unlock_bh(&adapter->mwifiex_cmd_lock);
1103
1104		mwifiex_recycle_cmd_node(adapter, cmd_node);
1105	}
1106
1107	mwifiex_cancel_scan(adapter);
1108}
1109
1110/*
1111 * This function sends the sleep confirm command to firmware, if
1112 * possible.
1113 *
1114 * The sleep confirm command cannot be issued if command response,
1115 * data response or event response is awaiting handling, or if we
1116 * are in the middle of sending a command, or expecting a command
1117 * response.
1118 */
1119void
1120mwifiex_check_ps_cond(struct mwifiex_adapter *adapter)
1121{
1122	if (!adapter->cmd_sent && !atomic_read(&adapter->tx_hw_pending) &&
1123	    !adapter->curr_cmd && !IS_CARD_RX_RCVD(adapter))
1124		mwifiex_dnld_sleep_confirm_cmd(adapter);
1125	else
1126		mwifiex_dbg(adapter, CMD,
1127			    "cmd: Delay Sleep Confirm (%s%s%s%s)\n",
1128			    (adapter->cmd_sent) ? "D" : "",
1129			    atomic_read(&adapter->tx_hw_pending) ? "T" : "",
1130			    (adapter->curr_cmd) ? "C" : "",
1131			    (IS_CARD_RX_RCVD(adapter)) ? "R" : "");
1132}
1133
1134/*
1135 * This function sends a Host Sleep activated event to applications.
1136 *
1137 * This event is generated by the driver, with a blank event body.
1138 */
1139void
1140mwifiex_hs_activated_event(struct mwifiex_adapter *adapter, u8 activated)
1141{
1142	if (activated) {
1143		if (test_bit(MWIFIEX_IS_HS_CONFIGURED,
1144			     &adapter->work_flags)) {
1145			adapter->hs_activated = true;
1146			mwifiex_update_rxreor_flags(adapter,
1147						    RXREOR_FORCE_NO_DROP);
1148			mwifiex_dbg(adapter, EVENT,
1149				    "event: hs_activated\n");
1150			adapter->hs_activate_wait_q_woken = true;
1151			wake_up_interruptible(
1152				&adapter->hs_activate_wait_q);
1153		} else {
1154			mwifiex_dbg(adapter, EVENT,
1155				    "event: HS not configured\n");
1156		}
1157	} else {
1158		mwifiex_dbg(adapter, EVENT,
1159			    "event: hs_deactivated\n");
1160		adapter->hs_activated = false;
1161	}
1162}
1163
1164/*
1165 * This function handles the command response of a Host Sleep configuration
1166 * command.
1167 *
1168 * Handling includes changing the header fields into CPU format
1169 * and setting the current host sleep activation status in driver.
1170 *
1171 * In case host sleep status change, the function generates an event to
1172 * notify the applications.
1173 */
1174int mwifiex_ret_802_11_hs_cfg(struct mwifiex_private *priv,
1175			      struct host_cmd_ds_command *resp)
1176{
1177	struct mwifiex_adapter *adapter = priv->adapter;
1178	struct host_cmd_ds_802_11_hs_cfg_enh *phs_cfg =
1179		&resp->params.opt_hs_cfg;
1180	uint32_t conditions = le32_to_cpu(phs_cfg->params.hs_config.conditions);
1181
1182	if (phs_cfg->action == cpu_to_le16(HS_ACTIVATE) &&
1183	    adapter->iface_type != MWIFIEX_USB) {
1184		mwifiex_hs_activated_event(adapter, true);
1185		return 0;
1186	} else {
1187		mwifiex_dbg(adapter, CMD,
1188			    "cmd: CMD_RESP: HS_CFG cmd reply\t"
1189			    " result=%#x, conditions=0x%x gpio=0x%x gap=0x%x\n",
1190			    resp->result, conditions,
1191			    phs_cfg->params.hs_config.gpio,
1192			    phs_cfg->params.hs_config.gap);
1193	}
1194	if (conditions != HS_CFG_CANCEL) {
1195		set_bit(MWIFIEX_IS_HS_CONFIGURED, &adapter->work_flags);
1196		if (adapter->iface_type == MWIFIEX_USB)
1197			mwifiex_hs_activated_event(adapter, true);
1198	} else {
1199		clear_bit(MWIFIEX_IS_HS_CONFIGURED, &adapter->work_flags);
1200		if (adapter->hs_activated)
1201			mwifiex_hs_activated_event(adapter, false);
1202	}
1203
1204	return 0;
1205}
1206
1207/*
1208 * This function wakes up the adapter and generates a Host Sleep
1209 * cancel event on receiving the power up interrupt.
1210 */
1211void
1212mwifiex_process_hs_config(struct mwifiex_adapter *adapter)
1213{
1214	mwifiex_dbg(adapter, INFO,
1215		    "info: %s: auto cancelling host sleep\t"
1216		    "since there is interrupt from the firmware\n",
1217		    __func__);
1218
1219	adapter->if_ops.wakeup(adapter);
1220
1221	if (adapter->hs_activated_manually) {
1222		mwifiex_cancel_hs(mwifiex_get_priv (adapter, MWIFIEX_BSS_ROLE_ANY),
1223				  MWIFIEX_ASYNC_CMD);
1224		adapter->hs_activated_manually = false;
1225	}
1226
1227	adapter->hs_activated = false;
1228	clear_bit(MWIFIEX_IS_HS_CONFIGURED, &adapter->work_flags);
1229	clear_bit(MWIFIEX_IS_SUSPENDED, &adapter->work_flags);
1230	mwifiex_hs_activated_event(adapter, false);
1231}
1232EXPORT_SYMBOL_GPL(mwifiex_process_hs_config);
1233
1234/*
1235 * This function handles the command response of a sleep confirm command.
1236 *
1237 * The function sets the card state to SLEEP if the response indicates success.
1238 */
1239void
1240mwifiex_process_sleep_confirm_resp(struct mwifiex_adapter *adapter,
1241				   u8 *pbuf, u32 upld_len)
1242{
1243	struct host_cmd_ds_command *cmd = (struct host_cmd_ds_command *) pbuf;
1244	uint16_t result = le16_to_cpu(cmd->result);
1245	uint16_t command = le16_to_cpu(cmd->command);
1246	uint16_t seq_num = le16_to_cpu(cmd->seq_num);
1247
1248	if (!upld_len) {
1249		mwifiex_dbg(adapter, ERROR,
1250			    "%s: cmd size is 0\n", __func__);
1251		return;
1252	}
1253
1254	mwifiex_dbg(adapter, CMD,
1255		    "cmd: CMD_RESP: 0x%x, result %d, len %d, seqno 0x%x\n",
1256		    command, result, le16_to_cpu(cmd->size), seq_num);
1257
1258	/* Update sequence number */
1259	seq_num = HostCmd_GET_SEQ_NO(seq_num);
1260	/* Clear RET_BIT from HostCmd */
1261	command &= HostCmd_CMD_ID_MASK;
1262
1263	if (command != HostCmd_CMD_802_11_PS_MODE_ENH) {
1264		mwifiex_dbg(adapter, ERROR,
1265			    "%s: rcvd unexpected resp for cmd %#x, result = %x\n",
1266			    __func__, command, result);
1267		return;
1268	}
1269
1270	if (result) {
1271		mwifiex_dbg(adapter, ERROR,
1272			    "%s: sleep confirm cmd failed\n",
1273			    __func__);
1274		adapter->pm_wakeup_card_req = false;
1275		adapter->ps_state = PS_STATE_AWAKE;
1276		return;
1277	}
1278	adapter->pm_wakeup_card_req = true;
1279	if (test_bit(MWIFIEX_IS_HS_CONFIGURED, &adapter->work_flags))
1280		mwifiex_hs_activated_event(adapter, true);
1281	adapter->ps_state = PS_STATE_SLEEP;
1282	cmd->command = cpu_to_le16(command);
1283	cmd->seq_num = cpu_to_le16(seq_num);
1284}
1285EXPORT_SYMBOL_GPL(mwifiex_process_sleep_confirm_resp);
1286
1287/*
1288 * This function prepares an enhanced power mode command.
1289 *
1290 * This function can be used to disable power save or to configure
1291 * power save with auto PS or STA PS or auto deep sleep.
1292 *
1293 * Preparation includes -
1294 *      - Setting command ID, action and proper size
1295 *      - Setting Power Save bitmap, PS parameters TLV, PS mode TLV,
1296 *        auto deep sleep TLV (as required)
1297 *      - Ensuring correct endian-ness
1298 */
1299int mwifiex_cmd_enh_power_mode(struct mwifiex_private *priv,
1300			       struct host_cmd_ds_command *cmd,
1301			       u16 cmd_action, uint16_t ps_bitmap,
1302			       struct mwifiex_ds_auto_ds *auto_ds)
1303{
1304	struct host_cmd_ds_802_11_ps_mode_enh *psmode_enh =
1305		&cmd->params.psmode_enh;
1306	u8 *tlv;
1307	u16 cmd_size = 0;
1308
1309	cmd->command = cpu_to_le16(HostCmd_CMD_802_11_PS_MODE_ENH);
1310	if (cmd_action == DIS_AUTO_PS) {
1311		psmode_enh->action = cpu_to_le16(DIS_AUTO_PS);
1312		psmode_enh->params.ps_bitmap = cpu_to_le16(ps_bitmap);
1313		cmd->size = cpu_to_le16(S_DS_GEN + sizeof(psmode_enh->action) +
1314					sizeof(psmode_enh->params.ps_bitmap));
1315	} else if (cmd_action == GET_PS) {
1316		psmode_enh->action = cpu_to_le16(GET_PS);
1317		psmode_enh->params.ps_bitmap = cpu_to_le16(ps_bitmap);
1318		cmd->size = cpu_to_le16(S_DS_GEN + sizeof(psmode_enh->action) +
1319					sizeof(psmode_enh->params.ps_bitmap));
1320	} else if (cmd_action == EN_AUTO_PS) {
1321		psmode_enh->action = cpu_to_le16(EN_AUTO_PS);
1322		psmode_enh->params.ps_bitmap = cpu_to_le16(ps_bitmap);
1323		cmd_size = S_DS_GEN + sizeof(psmode_enh->action) +
1324					sizeof(psmode_enh->params.ps_bitmap);
1325		tlv = (u8 *) cmd + cmd_size;
1326		if (ps_bitmap & BITMAP_STA_PS) {
1327			struct mwifiex_adapter *adapter = priv->adapter;
1328			struct mwifiex_ie_types_ps_param *ps_tlv =
1329				(struct mwifiex_ie_types_ps_param *) tlv;
1330			struct mwifiex_ps_param *ps_mode = &ps_tlv->param;
1331			ps_tlv->header.type = cpu_to_le16(TLV_TYPE_PS_PARAM);
1332			ps_tlv->header.len = cpu_to_le16(sizeof(*ps_tlv) -
1333					sizeof(struct mwifiex_ie_types_header));
1334			cmd_size += sizeof(*ps_tlv);
1335			tlv += sizeof(*ps_tlv);
1336			mwifiex_dbg(priv->adapter, CMD,
1337				    "cmd: PS Command: Enter PS\n");
1338			ps_mode->null_pkt_interval =
1339					cpu_to_le16(adapter->null_pkt_interval);
1340			ps_mode->multiple_dtims =
1341					cpu_to_le16(adapter->multiple_dtim);
1342			ps_mode->bcn_miss_timeout =
1343					cpu_to_le16(adapter->bcn_miss_time_out);
1344			ps_mode->local_listen_interval =
1345				cpu_to_le16(adapter->local_listen_interval);
1346			ps_mode->adhoc_wake_period =
1347				cpu_to_le16(adapter->adhoc_awake_period);
1348			ps_mode->delay_to_ps =
1349					cpu_to_le16(adapter->delay_to_ps);
1350			ps_mode->mode = cpu_to_le16(adapter->enhanced_ps_mode);
1351
1352		}
1353		if (ps_bitmap & BITMAP_AUTO_DS) {
1354			struct mwifiex_ie_types_auto_ds_param *auto_ds_tlv =
1355				(struct mwifiex_ie_types_auto_ds_param *) tlv;
1356			u16 idletime = 0;
1357
1358			auto_ds_tlv->header.type =
1359				cpu_to_le16(TLV_TYPE_AUTO_DS_PARAM);
1360			auto_ds_tlv->header.len =
1361				cpu_to_le16(sizeof(*auto_ds_tlv) -
1362					sizeof(struct mwifiex_ie_types_header));
1363			cmd_size += sizeof(*auto_ds_tlv);
1364			tlv += sizeof(*auto_ds_tlv);
1365			if (auto_ds)
1366				idletime = auto_ds->idle_time;
1367			mwifiex_dbg(priv->adapter, CMD,
1368				    "cmd: PS Command: Enter Auto Deep Sleep\n");
1369			auto_ds_tlv->deep_sleep_timeout = cpu_to_le16(idletime);
1370		}
1371		cmd->size = cpu_to_le16(cmd_size);
1372	}
1373	return 0;
1374}
1375
1376/*
1377 * This function handles the command response of an enhanced power mode
1378 * command.
1379 *
1380 * Handling includes changing the header fields into CPU format
1381 * and setting the current enhanced power mode in driver.
1382 */
1383int mwifiex_ret_enh_power_mode(struct mwifiex_private *priv,
1384			       struct host_cmd_ds_command *resp,
1385			       struct mwifiex_ds_pm_cfg *pm_cfg)
1386{
1387	struct mwifiex_adapter *adapter = priv->adapter;
1388	struct host_cmd_ds_802_11_ps_mode_enh *ps_mode =
1389		&resp->params.psmode_enh;
1390	uint16_t action = le16_to_cpu(ps_mode->action);
1391	uint16_t ps_bitmap = le16_to_cpu(ps_mode->params.ps_bitmap);
1392	uint16_t auto_ps_bitmap =
1393		le16_to_cpu(ps_mode->params.ps_bitmap);
1394
1395	mwifiex_dbg(adapter, INFO,
1396		    "info: %s: PS_MODE cmd reply result=%#x action=%#X\n",
1397		    __func__, resp->result, action);
1398	if (action == EN_AUTO_PS) {
1399		if (auto_ps_bitmap & BITMAP_AUTO_DS) {
1400			mwifiex_dbg(adapter, CMD,
1401				    "cmd: Enabled auto deep sleep\n");
1402			priv->adapter->is_deep_sleep = true;
1403		}
1404		if (auto_ps_bitmap & BITMAP_STA_PS) {
1405			mwifiex_dbg(adapter, CMD,
1406				    "cmd: Enabled STA power save\n");
1407			if (adapter->sleep_period.period)
1408				mwifiex_dbg(adapter, CMD,
1409					    "cmd: set to uapsd/pps mode\n");
1410		}
1411	} else if (action == DIS_AUTO_PS) {
1412		if (ps_bitmap & BITMAP_AUTO_DS) {
1413			priv->adapter->is_deep_sleep = false;
1414			mwifiex_dbg(adapter, CMD,
1415				    "cmd: Disabled auto deep sleep\n");
1416		}
1417		if (ps_bitmap & BITMAP_STA_PS) {
1418			mwifiex_dbg(adapter, CMD,
1419				    "cmd: Disabled STA power save\n");
1420			if (adapter->sleep_period.period) {
1421				adapter->delay_null_pkt = false;
1422				adapter->tx_lock_flag = false;
1423				adapter->pps_uapsd_mode = false;
1424			}
1425		}
1426	} else if (action == GET_PS) {
1427		if (ps_bitmap & BITMAP_STA_PS)
1428			adapter->ps_mode = MWIFIEX_802_11_POWER_MODE_PSP;
1429		else
1430			adapter->ps_mode = MWIFIEX_802_11_POWER_MODE_CAM;
1431
1432		mwifiex_dbg(adapter, CMD,
1433			    "cmd: ps_bitmap=%#x\n", ps_bitmap);
1434
1435		if (pm_cfg) {
1436			/* This section is for get power save mode */
1437			if (ps_bitmap & BITMAP_STA_PS)
1438				pm_cfg->param.ps_mode = 1;
1439			else
1440				pm_cfg->param.ps_mode = 0;
1441		}
1442	}
1443	return 0;
1444}
1445
1446/*
1447 * This function prepares command to get hardware specifications.
1448 *
1449 * Preparation includes -
1450 *      - Setting command ID, action and proper size
1451 *      - Setting permanent address parameter
1452 *      - Ensuring correct endian-ness
1453 */
1454int mwifiex_cmd_get_hw_spec(struct mwifiex_private *priv,
1455			    struct host_cmd_ds_command *cmd)
1456{
1457	struct host_cmd_ds_get_hw_spec *hw_spec = &cmd->params.hw_spec;
1458
1459	cmd->command = cpu_to_le16(HostCmd_CMD_GET_HW_SPEC);
1460	cmd->size =
1461		cpu_to_le16(sizeof(struct host_cmd_ds_get_hw_spec) + S_DS_GEN);
1462	memcpy(hw_spec->permanent_addr, priv->curr_addr, ETH_ALEN);
1463
1464	return 0;
1465}
1466
1467/*
1468 * This function handles the command response of get hardware
1469 * specifications.
1470 *
1471 * Handling includes changing the header fields into CPU format
1472 * and saving/updating the following parameters in driver -
1473 *      - Firmware capability information
1474 *      - Firmware band settings
1475 *      - Ad-hoc start band and channel
1476 *      - Ad-hoc 11n activation status
1477 *      - Firmware release number
1478 *      - Number of antennas
1479 *      - Hardware address
1480 *      - Hardware interface version
1481 *      - Firmware version
1482 *      - Region code
1483 *      - 11n capabilities
1484 *      - MCS support fields
1485 *      - MP end port
1486 */
1487int mwifiex_ret_get_hw_spec(struct mwifiex_private *priv,
1488			    struct host_cmd_ds_command *resp)
1489{
1490	struct host_cmd_ds_get_hw_spec *hw_spec = &resp->params.hw_spec;
1491	struct mwifiex_adapter *adapter = priv->adapter;
1492	struct mwifiex_ie_types_header *tlv;
1493	struct hw_spec_api_rev *api_rev;
1494	struct hw_spec_max_conn *max_conn;
1495	u16 resp_size, api_id;
1496	int i, left_len, parsed_len = 0;
1497
1498	adapter->fw_cap_info = le32_to_cpu(hw_spec->fw_cap_info);
1499
1500	if (IS_SUPPORT_MULTI_BANDS(adapter))
1501		adapter->fw_bands = (u8) GET_FW_DEFAULT_BANDS(adapter);
1502	else
1503		adapter->fw_bands = BAND_B;
1504
1505	adapter->config_bands = adapter->fw_bands;
1506
1507	if (adapter->fw_bands & BAND_A) {
1508		if (adapter->fw_bands & BAND_GN) {
1509			adapter->config_bands |= BAND_AN;
1510			adapter->fw_bands |= BAND_AN;
1511		}
1512		if (adapter->fw_bands & BAND_AN) {
1513			adapter->adhoc_start_band = BAND_A | BAND_AN;
1514			adapter->adhoc_11n_enabled = true;
1515		} else {
1516			adapter->adhoc_start_band = BAND_A;
1517		}
1518		priv->adhoc_channel = DEFAULT_AD_HOC_CHANNEL_A;
1519	} else if (adapter->fw_bands & BAND_GN) {
1520		adapter->adhoc_start_band = BAND_G | BAND_B | BAND_GN;
1521		priv->adhoc_channel = DEFAULT_AD_HOC_CHANNEL;
1522		adapter->adhoc_11n_enabled = true;
1523	} else if (adapter->fw_bands & BAND_G) {
1524		adapter->adhoc_start_band = BAND_G | BAND_B;
1525		priv->adhoc_channel = DEFAULT_AD_HOC_CHANNEL;
1526	} else if (adapter->fw_bands & BAND_B) {
1527		adapter->adhoc_start_band = BAND_B;
1528		priv->adhoc_channel = DEFAULT_AD_HOC_CHANNEL;
1529	}
1530
1531	adapter->fw_release_number = le32_to_cpu(hw_spec->fw_release_number);
1532	adapter->fw_api_ver = (adapter->fw_release_number >> 16) & 0xff;
1533	adapter->number_of_antenna =
1534			le16_to_cpu(hw_spec->number_of_antenna) & 0xf;
1535
1536	if (le32_to_cpu(hw_spec->dot_11ac_dev_cap)) {
1537		adapter->is_hw_11ac_capable = true;
1538
1539		/* Copy 11AC cap */
1540		adapter->hw_dot_11ac_dev_cap =
1541					le32_to_cpu(hw_spec->dot_11ac_dev_cap);
1542		adapter->usr_dot_11ac_dev_cap_bg = adapter->hw_dot_11ac_dev_cap
1543					& ~MWIFIEX_DEF_11AC_CAP_BF_RESET_MASK;
1544		adapter->usr_dot_11ac_dev_cap_a = adapter->hw_dot_11ac_dev_cap
1545					& ~MWIFIEX_DEF_11AC_CAP_BF_RESET_MASK;
1546
1547		/* Copy 11AC mcs */
1548		adapter->hw_dot_11ac_mcs_support =
1549				le32_to_cpu(hw_spec->dot_11ac_mcs_support);
1550		adapter->usr_dot_11ac_mcs_support =
1551					adapter->hw_dot_11ac_mcs_support;
1552	} else {
1553		adapter->is_hw_11ac_capable = false;
1554	}
1555
1556	resp_size = le16_to_cpu(resp->size) - S_DS_GEN;
1557	if (resp_size > sizeof(struct host_cmd_ds_get_hw_spec)) {
1558		/* we have variable HW SPEC information */
1559		left_len = resp_size - sizeof(struct host_cmd_ds_get_hw_spec);
1560		while (left_len > sizeof(struct mwifiex_ie_types_header)) {
1561			tlv = (void *)&hw_spec->tlvs + parsed_len;
1562			switch (le16_to_cpu(tlv->type)) {
1563			case TLV_TYPE_API_REV:
1564				api_rev = (struct hw_spec_api_rev *)tlv;
1565				api_id = le16_to_cpu(api_rev->api_id);
1566				switch (api_id) {
1567				case KEY_API_VER_ID:
1568					adapter->key_api_major_ver =
1569							api_rev->major_ver;
1570					adapter->key_api_minor_ver =
1571							api_rev->minor_ver;
1572					mwifiex_dbg(adapter, INFO,
1573						    "key_api v%d.%d\n",
1574						    adapter->key_api_major_ver,
1575						    adapter->key_api_minor_ver);
1576					break;
1577				case FW_API_VER_ID:
1578					adapter->fw_api_ver =
1579							api_rev->major_ver;
1580					mwifiex_dbg(adapter, INFO,
1581						    "Firmware api version %d.%d\n",
1582						    adapter->fw_api_ver,
1583						    api_rev->minor_ver);
1584					break;
1585				case UAP_FW_API_VER_ID:
1586					mwifiex_dbg(adapter, INFO,
1587						    "uAP api version %d.%d\n",
1588						    api_rev->major_ver,
1589						    api_rev->minor_ver);
1590					break;
1591				case CHANRPT_API_VER_ID:
1592					mwifiex_dbg(adapter, INFO,
1593						    "channel report api version %d.%d\n",
1594						    api_rev->major_ver,
1595						    api_rev->minor_ver);
1596					break;
1597				case FW_HOTFIX_VER_ID:
1598					mwifiex_dbg(adapter, INFO,
1599						    "Firmware hotfix version %d\n",
1600						    api_rev->major_ver);
1601					break;
1602				default:
1603					mwifiex_dbg(adapter, FATAL,
1604						    "Unknown api_id: %d\n",
1605						    api_id);
1606					break;
1607				}
1608				break;
1609			case TLV_TYPE_MAX_CONN:
1610				max_conn = (struct hw_spec_max_conn *)tlv;
1611				adapter->max_p2p_conn = max_conn->max_p2p_conn;
1612				adapter->max_sta_conn = max_conn->max_sta_conn;
1613				mwifiex_dbg(adapter, INFO,
1614					    "max p2p connections: %u\n",
1615					    adapter->max_p2p_conn);
1616				mwifiex_dbg(adapter, INFO,
1617					    "max sta connections: %u\n",
1618					    adapter->max_sta_conn);
1619				break;
1620			default:
1621				mwifiex_dbg(adapter, FATAL,
1622					    "Unknown GET_HW_SPEC TLV type: %#x\n",
1623					    le16_to_cpu(tlv->type));
1624				break;
1625			}
1626			parsed_len += le16_to_cpu(tlv->len) +
1627				      sizeof(struct mwifiex_ie_types_header);
1628			left_len -= le16_to_cpu(tlv->len) +
1629				      sizeof(struct mwifiex_ie_types_header);
1630		}
1631	}
1632
1633	mwifiex_dbg(adapter, INFO,
1634		    "info: GET_HW_SPEC: fw_release_number- %#x\n",
1635		    adapter->fw_release_number);
1636	mwifiex_dbg(adapter, INFO,
1637		    "info: GET_HW_SPEC: permanent addr: %pM\n",
1638		    hw_spec->permanent_addr);
1639	mwifiex_dbg(adapter, INFO,
1640		    "info: GET_HW_SPEC: hw_if_version=%#x version=%#x\n",
1641		    le16_to_cpu(hw_spec->hw_if_version),
1642		    le16_to_cpu(hw_spec->version));
1643
1644	ether_addr_copy(priv->adapter->perm_addr, hw_spec->permanent_addr);
1645	adapter->region_code = le16_to_cpu(hw_spec->region_code);
1646
1647	for (i = 0; i < MWIFIEX_MAX_REGION_CODE; i++)
1648		/* Use the region code to search for the index */
1649		if (adapter->region_code == region_code_index[i])
1650			break;
1651
1652	/* If it's unidentified region code, use the default (world) */
1653	if (i >= MWIFIEX_MAX_REGION_CODE) {
1654		adapter->region_code = 0x00;
1655		mwifiex_dbg(adapter, WARN,
1656			    "cmd: unknown region code, use default (USA)\n");
1657	}
1658
1659	adapter->hw_dot_11n_dev_cap = le32_to_cpu(hw_spec->dot_11n_dev_cap);
1660	adapter->hw_dev_mcs_support = hw_spec->dev_mcs_support;
1661	adapter->user_dev_mcs_support = adapter->hw_dev_mcs_support;
1662
1663	if (adapter->if_ops.update_mp_end_port)
1664		adapter->if_ops.update_mp_end_port(adapter,
1665					le16_to_cpu(hw_spec->mp_end_port));
1666
1667	if (adapter->fw_api_ver == MWIFIEX_FW_V15)
1668		adapter->scan_chan_gap_enabled = true;
1669
1670	if (adapter->key_api_major_ver != KEY_API_VER_MAJOR_V2)
1671		adapter->host_mlme_enabled = false;
1672
1673	mwifiex_dbg(adapter, MSG, "host_mlme: %s, key_api: %d\n",
1674		    adapter->host_mlme_enabled ? "enable" : "disable",
1675		    adapter->key_api_major_ver);
1676
1677	return 0;
1678}
1679
1680/* This function handles the command response of hs wakeup reason
1681 * command.
1682 */
1683int mwifiex_ret_wakeup_reason(struct mwifiex_private *priv,
1684			      struct host_cmd_ds_command *resp,
1685			      struct host_cmd_ds_wakeup_reason *wakeup_reason)
1686{
1687	wakeup_reason->wakeup_reason =
1688		resp->params.hs_wakeup_reason.wakeup_reason;
1689
1690	return 0;
1691}
~/ Read-only file preview.