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