]> asedeno.scripts.mit.edu Git - linux.git/blob - drivers/staging/wilc1000/host_interface.c
Merge ath-next from git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git
[linux.git] / drivers / staging / wilc1000 / host_interface.c
1 // SPDX-License-Identifier: GPL-2.0
2 #include <linux/slab.h>
3 #include <linux/time.h>
4 #include <linux/kthread.h>
5 #include <linux/delay.h>
6 #include <linux/completion.h>
7 #include <linux/list.h>
8 #include <linux/workqueue.h>
9 #include "host_interface.h"
10 #include <linux/spinlock.h>
11 #include <linux/errno.h>
12 #include "coreconfigurator.h"
13 #include "wilc_wlan.h"
14 #include "wilc_wlan_if.h"
15 #include <linux/etherdevice.h>
16 #include "wilc_wfi_netdevice.h"
17
18 #define HOST_IF_MSG_SCAN                        0
19 #define HOST_IF_MSG_CONNECT                     1
20 #define HOST_IF_MSG_RCVD_GNRL_ASYNC_INFO        2
21 #define HOST_IF_MSG_KEY                         3
22 #define HOST_IF_MSG_RCVD_NTWRK_INFO             4
23 #define HOST_IF_MSG_RCVD_SCAN_COMPLETE          5
24 #define HOST_IF_MSG_CFG_PARAMS                  6
25 #define HOST_IF_MSG_SET_CHANNEL                 7
26 #define HOST_IF_MSG_DISCONNECT                  8
27 #define HOST_IF_MSG_GET_RSSI                    9
28 #define HOST_IF_MSG_ADD_BEACON                  11
29 #define HOST_IF_MSG_DEL_BEACON                  12
30 #define HOST_IF_MSG_ADD_STATION                 13
31 #define HOST_IF_MSG_DEL_STATION                 14
32 #define HOST_IF_MSG_EDIT_STATION                15
33 #define HOST_IF_MSG_SCAN_TIMER_FIRED            16
34 #define HOST_IF_MSG_CONNECT_TIMER_FIRED         17
35 #define HOST_IF_MSG_POWER_MGMT                  18
36 #define HOST_IF_MSG_GET_INACTIVETIME            19
37 #define HOST_IF_MSG_REMAIN_ON_CHAN              20
38 #define HOST_IF_MSG_REGISTER_FRAME              21
39 #define HOST_IF_MSG_LISTEN_TIMER_FIRED          22
40 #define HOST_IF_MSG_SET_WFIDRV_HANDLER          24
41 #define HOST_IF_MSG_GET_MAC_ADDRESS             26
42 #define HOST_IF_MSG_SET_OPERATION_MODE          27
43 #define HOST_IF_MSG_SET_IPADDRESS               28
44 #define HOST_IF_MSG_GET_IPADDRESS               29
45 #define HOST_IF_MSG_GET_STATISTICS              31
46 #define HOST_IF_MSG_SET_MULTICAST_FILTER        32
47 #define HOST_IF_MSG_DEL_BA_SESSION              34
48 #define HOST_IF_MSG_DEL_ALL_STA                 36
49 #define HOST_IF_MSG_SET_TX_POWER                38
50 #define HOST_IF_MSG_GET_TX_POWER                39
51 #define HOST_IF_MSG_EXIT                        100
52
53 #define HOST_IF_SCAN_TIMEOUT                    4000
54 #define HOST_IF_CONNECT_TIMEOUT                 9500
55
56 #define BA_SESSION_DEFAULT_BUFFER_SIZE          16
57 #define BA_SESSION_DEFAULT_TIMEOUT              1000
58 #define BLOCK_ACK_REQ_SIZE                      0x14
59 #define FALSE_FRMWR_CHANNEL                     100
60
61 #define TCP_ACK_FILTER_LINK_SPEED_THRESH        54
62 #define DEFAULT_LINK_SPEED                      72
63
64 struct host_if_wpa_attr {
65         u8 *key;
66         const u8 *mac_addr;
67         u8 *seq;
68         u8 seq_len;
69         u8 index;
70         u8 key_len;
71         u8 mode;
72 };
73
74 struct host_if_wep_attr {
75         u8 *key;
76         u8 key_len;
77         u8 index;
78         u8 mode;
79         enum AUTHTYPE auth_type;
80 };
81
82 union host_if_key_attr {
83         struct host_if_wep_attr wep;
84         struct host_if_wpa_attr wpa;
85         struct host_if_pmkid_attr pmkid;
86 };
87
88 struct key_attr {
89         enum KEY_TYPE type;
90         u8 action;
91         union host_if_key_attr attr;
92 };
93
94 struct scan_attr {
95         u8 src;
96         u8 type;
97         u8 *ch_freq_list;
98         u8 ch_list_len;
99         u8 *ies;
100         size_t ies_len;
101         wilc_scan_result result;
102         void *arg;
103         struct hidden_network hidden_network;
104 };
105
106 struct connect_attr {
107         u8 *bssid;
108         u8 *ssid;
109         size_t ssid_len;
110         u8 *ies;
111         size_t ies_len;
112         u8 security;
113         wilc_connect_result result;
114         void *arg;
115         enum AUTHTYPE auth_type;
116         u8 ch;
117         void *params;
118 };
119
120 struct rcvd_async_info {
121         u8 *buffer;
122         u32 len;
123 };
124
125 struct channel_attr {
126         u8 set_ch;
127 };
128
129 struct beacon_attr {
130         u32 interval;
131         u32 dtim_period;
132         u32 head_len;
133         u8 *head;
134         u32 tail_len;
135         u8 *tail;
136 };
137
138 struct set_multicast {
139         bool enabled;
140         u32 cnt;
141 };
142
143 struct del_all_sta {
144         u8 del_all_sta[MAX_NUM_STA][ETH_ALEN];
145         u8 assoc_sta;
146 };
147
148 struct del_sta {
149         u8 mac_addr[ETH_ALEN];
150 };
151
152 struct power_mgmt_param {
153         bool enabled;
154         u32 timeout;
155 };
156
157 struct set_ip_addr {
158         u8 *ip_addr;
159         u8 idx;
160 };
161
162 struct sta_inactive_t {
163         u8 mac[6];
164 };
165
166 struct tx_power {
167         u8 tx_pwr;
168 };
169
170 union message_body {
171         struct scan_attr scan_info;
172         struct connect_attr con_info;
173         struct rcvd_net_info net_info;
174         struct rcvd_async_info async_info;
175         struct key_attr key_info;
176         struct cfg_param_attr cfg_info;
177         struct channel_attr channel_info;
178         struct beacon_attr beacon_info;
179         struct add_sta_param add_sta_info;
180         struct del_sta del_sta_info;
181         struct add_sta_param edit_sta_info;
182         struct power_mgmt_param pwr_mgmt_info;
183         struct sta_inactive_t mac_info;
184         struct set_ip_addr ip_info;
185         struct drv_handler drv;
186         struct set_multicast multicast_info;
187         struct op_mode mode;
188         struct get_mac_addr get_mac_info;
189         struct ba_session_info session_info;
190         struct remain_ch remain_on_ch;
191         struct reg_frame reg_frame;
192         char *data;
193         struct del_all_sta del_all_sta_info;
194         struct tx_power tx_power;
195 };
196
197 struct host_if_msg {
198         u16 id;
199         union message_body body;
200         struct wilc_vif *vif;
201         struct work_struct work;
202 };
203
204 struct join_bss_param {
205         enum bss_types bss_type;
206         u8 dtim_period;
207         u16 beacon_period;
208         u16 cap_info;
209         u8 bssid[6];
210         char ssid[MAX_SSID_LEN];
211         u8 ssid_len;
212         u8 supp_rates[MAX_RATES_SUPPORTED + 1];
213         u8 ht_capable;
214         u8 wmm_cap;
215         u8 uapsd_cap;
216         bool rsn_found;
217         u8 rsn_grp_policy;
218         u8 mode_802_11i;
219         u8 rsn_pcip_policy[3];
220         u8 rsn_auth_policy[3];
221         u8 rsn_cap[2];
222         u32 tsf;
223         u8 noa_enabled;
224         u8 opp_enabled;
225         u8 ct_window;
226         u8 cnt;
227         u8 idx;
228         u8 duration[4];
229         u8 interval[4];
230         u8 start_time[4];
231 };
232
233 static struct host_if_drv *terminated_handle;
234 bool wilc_optaining_ip;
235 static u8 P2P_LISTEN_STATE;
236 static struct workqueue_struct *hif_workqueue;
237 static struct completion hif_thread_comp;
238 static struct completion hif_driver_comp;
239 static struct completion hif_wait_response;
240 static struct mutex hif_deinit_lock;
241 static struct timer_list periodic_rssi;
242 static struct wilc_vif *periodic_rssi_vif;
243
244 u8 wilc_multicast_mac_addr_list[WILC_MULTICAST_TABLE_SIZE][ETH_ALEN];
245
246 static u8 rcv_assoc_resp[MAX_ASSOC_RESP_FRAME_SIZE];
247
248 static bool scan_while_connected;
249
250 static s8 rssi;
251 static u8 set_ip[2][4];
252 static u8 get_ip[2][4];
253 static u32 inactive_time;
254 static u8 del_beacon;
255 static u32 clients_count;
256
257 #define REAL_JOIN_REQ 0
258 #define FLUSHED_JOIN_REQ 1
259 #define FLUSHED_BYTE_POS 79
260
261 static void *host_int_parse_join_bss_param(struct network_info *info);
262 static int host_int_get_ipaddress(struct wilc_vif *vif, u8 *ip_addr, u8 idx);
263 static s32 handle_scan_done(struct wilc_vif *vif, enum scan_event evt);
264 static void host_if_work(struct work_struct *work);
265
266 /*!
267  *  @author             syounan
268  *  @date               1 Sep 2010
269  *  @note               copied from FLO glue implementatuion
270  *  @version            1.0
271  */
272 static int wilc_enqueue_cmd(struct host_if_msg *msg)
273 {
274         struct host_if_msg *new_msg;
275
276         new_msg = kmemdup(msg, sizeof(*new_msg), GFP_ATOMIC);
277         if (!new_msg)
278                 return -ENOMEM;
279
280         INIT_WORK(&new_msg->work, host_if_work);
281         queue_work(hif_workqueue, &new_msg->work);
282         return 0;
283 }
284
285 /* The u8IfIdx starts from 0 to NUM_CONCURRENT_IFC -1, but 0 index used as
286  * special purpose in wilc device, so we add 1 to the index to starts from 1.
287  * As a result, the returned index will be 1 to NUM_CONCURRENT_IFC.
288  */
289 int wilc_get_vif_idx(struct wilc_vif *vif)
290 {
291         return vif->idx + 1;
292 }
293
294 /* We need to minus 1 from idx which is from wilc device to get real index
295  * of wilc->vif[], because we add 1 when pass to wilc device in the function
296  * wilc_get_vif_idx.
297  * As a result, the index should be between 0 and NUM_CONCURRENT_IFC -1.
298  */
299 static struct wilc_vif *wilc_get_vif_from_idx(struct wilc *wilc, int idx)
300 {
301         int index = idx - 1;
302
303         if (index < 0 || index >= NUM_CONCURRENT_IFC)
304                 return NULL;
305
306         return wilc->vif[index];
307 }
308
309 static void handle_set_channel(struct wilc_vif *vif,
310                                struct channel_attr *hif_set_ch)
311 {
312         int ret = 0;
313         struct wid wid;
314
315         wid.id = (u16)WID_CURRENT_CHANNEL;
316         wid.type = WID_CHAR;
317         wid.val = (char *)&hif_set_ch->set_ch;
318         wid.size = sizeof(char);
319
320         ret = wilc_send_config_pkt(vif, SET_CFG, &wid, 1,
321                                    wilc_get_vif_idx(vif));
322
323         if (ret)
324                 netdev_err(vif->ndev, "Failed to set channel\n");
325 }
326
327 static int handle_set_wfi_drv_handler(struct wilc_vif *vif,
328                                       struct drv_handler *hif_drv_handler)
329 {
330         int ret = 0;
331         struct wid wid;
332         u8 *currbyte, *buffer;
333         struct host_if_drv *hif_drv = NULL;
334
335         if (!vif->hif_drv)
336                 return -EINVAL;
337
338         if (!hif_drv_handler)
339                 return -EINVAL;
340
341         hif_drv = vif->hif_drv;
342
343         buffer = kzalloc(DRV_HANDLER_SIZE, GFP_KERNEL);
344         if (!buffer)
345                 return -ENOMEM;
346
347         currbyte = buffer;
348         *currbyte = hif_drv->driver_handler_id & DRV_HANDLER_MASK;
349         currbyte++;
350         *currbyte = (u32)0 & DRV_HANDLER_MASK;
351         currbyte++;
352         *currbyte = (u32)0 & DRV_HANDLER_MASK;
353         currbyte++;
354         *currbyte = (u32)0 & DRV_HANDLER_MASK;
355         currbyte++;
356         *currbyte = (hif_drv_handler->name | (hif_drv_handler->mode << 1));
357
358         wid.id = (u16)WID_SET_DRV_HANDLER;
359         wid.type = WID_STR;
360         wid.val = (s8 *)buffer;
361         wid.size = DRV_HANDLER_SIZE;
362
363         ret = wilc_send_config_pkt(vif, SET_CFG, &wid, 1,
364                                    hif_drv->driver_handler_id);
365         if (ret) {
366                 netdev_err(vif->ndev, "Failed to set driver handler\n");
367                 complete(&hif_driver_comp);
368                 kfree(buffer);
369                 return ret;
370         }
371         complete(&hif_driver_comp);
372         kfree(buffer);
373         return 0;
374 }
375
376 static void handle_set_operation_mode(struct wilc_vif *vif,
377                                       struct op_mode *hif_op_mode)
378 {
379         int ret = 0;
380         struct wid wid;
381
382         wid.id = (u16)WID_SET_OPERATION_MODE;
383         wid.type = WID_INT;
384         wid.val = (s8 *)&hif_op_mode->mode;
385         wid.size = sizeof(u32);
386
387         ret = wilc_send_config_pkt(vif, SET_CFG, &wid, 1,
388                                    wilc_get_vif_idx(vif));
389
390         if (hif_op_mode->mode == IDLE_MODE)
391                 complete(&hif_driver_comp);
392
393         if (ret)
394                 netdev_err(vif->ndev, "Failed to set driver handler\n");
395 }
396
397 static void handle_set_ip_address(struct wilc_vif *vif, u8 *ip_addr, u8 idx)
398 {
399         int ret = 0;
400         struct wid wid;
401         char firmware_ip_addr[4] = {0};
402
403         if (ip_addr[0] < 192)
404                 ip_addr[0] = 0;
405
406         memcpy(set_ip[idx], ip_addr, IP_ALEN);
407
408         wid.id = (u16)WID_IP_ADDRESS;
409         wid.type = WID_STR;
410         wid.val = ip_addr;
411         wid.size = IP_ALEN;
412
413         ret = wilc_send_config_pkt(vif, SET_CFG, &wid, 1,
414                                    wilc_get_vif_idx(vif));
415
416         host_int_get_ipaddress(vif, firmware_ip_addr, idx);
417
418         if (ret)
419                 netdev_err(vif->ndev, "Failed to set IP address\n");
420 }
421
422 static void handle_get_ip_address(struct wilc_vif *vif, u8 idx)
423 {
424         int ret = 0;
425         struct wid wid;
426
427         wid.id = (u16)WID_IP_ADDRESS;
428         wid.type = WID_STR;
429         wid.val = kmalloc(IP_ALEN, GFP_KERNEL);
430         wid.size = IP_ALEN;
431
432         ret = wilc_send_config_pkt(vif, GET_CFG, &wid, 1,
433                                    wilc_get_vif_idx(vif));
434
435         memcpy(get_ip[idx], wid.val, IP_ALEN);
436
437         kfree(wid.val);
438
439         if (memcmp(get_ip[idx], set_ip[idx], IP_ALEN) != 0)
440                 wilc_setup_ipaddress(vif, set_ip[idx], idx);
441
442         if (ret)
443                 netdev_err(vif->ndev, "Failed to get IP address\n");
444 }
445
446 static void handle_get_mac_address(struct wilc_vif *vif,
447                                    struct get_mac_addr *get_mac_addr)
448 {
449         int ret = 0;
450         struct wid wid;
451
452         wid.id = (u16)WID_MAC_ADDR;
453         wid.type = WID_STR;
454         wid.val = get_mac_addr->mac_addr;
455         wid.size = ETH_ALEN;
456
457         ret = wilc_send_config_pkt(vif, GET_CFG, &wid, 1,
458                                    wilc_get_vif_idx(vif));
459
460         if (ret)
461                 netdev_err(vif->ndev, "Failed to get mac address\n");
462         complete(&hif_wait_response);
463 }
464
465 static void handle_cfg_param(struct wilc_vif *vif, struct cfg_param_attr *param)
466 {
467         int ret = 0;
468         struct wid wid_list[32];
469         struct host_if_drv *hif_drv = vif->hif_drv;
470         int i = 0;
471
472         mutex_lock(&hif_drv->cfg_values_lock);
473
474         if (param->flag & BSS_TYPE) {
475                 u8 bss_type = param->bss_type;
476
477                 if (bss_type < 6) {
478                         wid_list[i].id = WID_BSS_TYPE;
479                         wid_list[i].val = (s8 *)&param->bss_type;
480                         wid_list[i].type = WID_CHAR;
481                         wid_list[i].size = sizeof(char);
482                         hif_drv->cfg_values.bss_type = bss_type;
483                 } else {
484                         netdev_err(vif->ndev, "check value 6 over\n");
485                         goto unlock;
486                 }
487                 i++;
488         }
489         if (param->flag & AUTH_TYPE) {
490                 u8 auth_type = param->auth_type;
491
492                 if (auth_type == 1 || auth_type == 2 || auth_type == 5) {
493                         wid_list[i].id = WID_AUTH_TYPE;
494                         wid_list[i].val = (s8 *)&param->auth_type;
495                         wid_list[i].type = WID_CHAR;
496                         wid_list[i].size = sizeof(char);
497                         hif_drv->cfg_values.auth_type = auth_type;
498                 } else {
499                         netdev_err(vif->ndev, "Impossible value\n");
500                         goto unlock;
501                 }
502                 i++;
503         }
504         if (param->flag & AUTHEN_TIMEOUT) {
505                 if (param->auth_timeout > 0) {
506                         wid_list[i].id = WID_AUTH_TIMEOUT;
507                         wid_list[i].val = (s8 *)&param->auth_timeout;
508                         wid_list[i].type = WID_SHORT;
509                         wid_list[i].size = sizeof(u16);
510                         hif_drv->cfg_values.auth_timeout = param->auth_timeout;
511                 } else {
512                         netdev_err(vif->ndev, "Range(1 ~ 65535) over\n");
513                         goto unlock;
514                 }
515                 i++;
516         }
517         if (param->flag & POWER_MANAGEMENT) {
518                 u8 pm_mode = param->power_mgmt_mode;
519
520                 if (pm_mode < 5) {
521                         wid_list[i].id = WID_POWER_MANAGEMENT;
522                         wid_list[i].val = (s8 *)&param->power_mgmt_mode;
523                         wid_list[i].type = WID_CHAR;
524                         wid_list[i].size = sizeof(char);
525                         hif_drv->cfg_values.power_mgmt_mode = pm_mode;
526                 } else {
527                         netdev_err(vif->ndev, "Invalid power mode\n");
528                         goto unlock;
529                 }
530                 i++;
531         }
532         if (param->flag & RETRY_SHORT) {
533                 u16 retry_limit = param->short_retry_limit;
534
535                 if (retry_limit > 0 && retry_limit < 256) {
536                         wid_list[i].id = WID_SHORT_RETRY_LIMIT;
537                         wid_list[i].val = (s8 *)&param->short_retry_limit;
538                         wid_list[i].type = WID_SHORT;
539                         wid_list[i].size = sizeof(u16);
540                         hif_drv->cfg_values.short_retry_limit = retry_limit;
541                 } else {
542                         netdev_err(vif->ndev, "Range(1~256) over\n");
543                         goto unlock;
544                 }
545                 i++;
546         }
547         if (param->flag & RETRY_LONG) {
548                 u16 limit = param->long_retry_limit;
549
550                 if (limit > 0 && limit < 256) {
551                         wid_list[i].id = WID_LONG_RETRY_LIMIT;
552                         wid_list[i].val = (s8 *)&param->long_retry_limit;
553                         wid_list[i].type = WID_SHORT;
554                         wid_list[i].size = sizeof(u16);
555                         hif_drv->cfg_values.long_retry_limit = limit;
556                 } else {
557                         netdev_err(vif->ndev, "Range(1~256) over\n");
558                         goto unlock;
559                 }
560                 i++;
561         }
562         if (param->flag & FRAG_THRESHOLD) {
563                 u16 frag_th = param->frag_threshold;
564
565                 if (frag_th > 255 && frag_th < 7937) {
566                         wid_list[i].id = WID_FRAG_THRESHOLD;
567                         wid_list[i].val = (s8 *)&param->frag_threshold;
568                         wid_list[i].type = WID_SHORT;
569                         wid_list[i].size = sizeof(u16);
570                         hif_drv->cfg_values.frag_threshold = frag_th;
571                 } else {
572                         netdev_err(vif->ndev, "Threshold Range fail\n");
573                         goto unlock;
574                 }
575                 i++;
576         }
577         if (param->flag & RTS_THRESHOLD) {
578                 u16 rts_th = param->rts_threshold;
579
580                 if (rts_th > 255) {
581                         wid_list[i].id = WID_RTS_THRESHOLD;
582                         wid_list[i].val = (s8 *)&param->rts_threshold;
583                         wid_list[i].type = WID_SHORT;
584                         wid_list[i].size = sizeof(u16);
585                         hif_drv->cfg_values.rts_threshold = rts_th;
586                 } else {
587                         netdev_err(vif->ndev, "Threshold Range fail\n");
588                         goto unlock;
589                 }
590                 i++;
591         }
592         if (param->flag & PREAMBLE) {
593                 u16 preamble_type = param->preamble_type;
594
595                 if (param->preamble_type < 3) {
596                         wid_list[i].id = WID_PREAMBLE;
597                         wid_list[i].val = (s8 *)&param->preamble_type;
598                         wid_list[i].type = WID_CHAR;
599                         wid_list[i].size = sizeof(char);
600                         hif_drv->cfg_values.preamble_type = preamble_type;
601                 } else {
602                         netdev_err(vif->ndev, "Preamle Range(0~2) over\n");
603                         goto unlock;
604                 }
605                 i++;
606         }
607         if (param->flag & SHORT_SLOT_ALLOWED) {
608                 u8 slot_allowed = param->short_slot_allowed;
609
610                 if (slot_allowed < 2) {
611                         wid_list[i].id = WID_SHORT_SLOT_ALLOWED;
612                         wid_list[i].val = (s8 *)&param->short_slot_allowed;
613                         wid_list[i].type = WID_CHAR;
614                         wid_list[i].size = sizeof(char);
615                         hif_drv->cfg_values.short_slot_allowed = slot_allowed;
616                 } else {
617                         netdev_err(vif->ndev, "Short slot(2) over\n");
618                         goto unlock;
619                 }
620                 i++;
621         }
622         if (param->flag & TXOP_PROT_DISABLE) {
623                 u8 prot_disabled = param->txop_prot_disabled;
624
625                 if (param->txop_prot_disabled < 2) {
626                         wid_list[i].id = WID_11N_TXOP_PROT_DISABLE;
627                         wid_list[i].val = (s8 *)&param->txop_prot_disabled;
628                         wid_list[i].type = WID_CHAR;
629                         wid_list[i].size = sizeof(char);
630                         hif_drv->cfg_values.txop_prot_disabled = prot_disabled;
631                 } else {
632                         netdev_err(vif->ndev, "TXOP prot disable\n");
633                         goto unlock;
634                 }
635                 i++;
636         }
637         if (param->flag & BEACON_INTERVAL) {
638                 u16 beacon_interval = param->beacon_interval;
639
640                 if (beacon_interval > 0) {
641                         wid_list[i].id = WID_BEACON_INTERVAL;
642                         wid_list[i].val = (s8 *)&param->beacon_interval;
643                         wid_list[i].type = WID_SHORT;
644                         wid_list[i].size = sizeof(u16);
645                         hif_drv->cfg_values.beacon_interval = beacon_interval;
646                 } else {
647                         netdev_err(vif->ndev, "Beacon interval(1~65535)fail\n");
648                         goto unlock;
649                 }
650                 i++;
651         }
652         if (param->flag & DTIM_PERIOD) {
653                 if (param->dtim_period > 0 && param->dtim_period < 256) {
654                         wid_list[i].id = WID_DTIM_PERIOD;
655                         wid_list[i].val = (s8 *)&param->dtim_period;
656                         wid_list[i].type = WID_CHAR;
657                         wid_list[i].size = sizeof(char);
658                         hif_drv->cfg_values.dtim_period = param->dtim_period;
659                 } else {
660                         netdev_err(vif->ndev, "DTIM range(1~255) fail\n");
661                         goto unlock;
662                 }
663                 i++;
664         }
665         if (param->flag & SITE_SURVEY) {
666                 enum SITESURVEY enabled = param->site_survey_enabled;
667
668                 if (enabled < 3) {
669                         wid_list[i].id = WID_SITE_SURVEY;
670                         wid_list[i].val = (s8 *)&param->site_survey_enabled;
671                         wid_list[i].type = WID_CHAR;
672                         wid_list[i].size = sizeof(char);
673                         hif_drv->cfg_values.site_survey_enabled = enabled;
674                 } else {
675                         netdev_err(vif->ndev, "Site survey disable\n");
676                         goto unlock;
677                 }
678                 i++;
679         }
680         if (param->flag & SITE_SURVEY_SCAN_TIME) {
681                 u16 scan_time = param->site_survey_scan_time;
682
683                 if (scan_time > 0) {
684                         wid_list[i].id = WID_SITE_SURVEY_SCAN_TIME;
685                         wid_list[i].val = (s8 *)&param->site_survey_scan_time;
686                         wid_list[i].type = WID_SHORT;
687                         wid_list[i].size = sizeof(u16);
688                         hif_drv->cfg_values.site_survey_scan_time = scan_time;
689                 } else {
690                         netdev_err(vif->ndev, "Site scan time(1~65535) over\n");
691                         goto unlock;
692                 }
693                 i++;
694         }
695         if (param->flag & ACTIVE_SCANTIME) {
696                 u16 active_scan_time = param->active_scan_time;
697
698                 if (active_scan_time > 0) {
699                         wid_list[i].id = WID_ACTIVE_SCAN_TIME;
700                         wid_list[i].val = (s8 *)&param->active_scan_time;
701                         wid_list[i].type = WID_SHORT;
702                         wid_list[i].size = sizeof(u16);
703                         hif_drv->cfg_values.active_scan_time = active_scan_time;
704                 } else {
705                         netdev_err(vif->ndev, "Active time(1~65535) over\n");
706                         goto unlock;
707                 }
708                 i++;
709         }
710         if (param->flag & PASSIVE_SCANTIME) {
711                 u16 time = param->passive_scan_time;
712
713                 if (time > 0) {
714                         wid_list[i].id = WID_PASSIVE_SCAN_TIME;
715                         wid_list[i].val = (s8 *)&param->passive_scan_time;
716                         wid_list[i].type = WID_SHORT;
717                         wid_list[i].size = sizeof(u16);
718                         hif_drv->cfg_values.passive_scan_time = time;
719                 } else {
720                         netdev_err(vif->ndev, "Passive time(1~65535) over\n");
721                         goto unlock;
722                 }
723                 i++;
724         }
725         if (param->flag & CURRENT_TX_RATE) {
726                 enum CURRENT_TXRATE curr_tx_rate = param->curr_tx_rate;
727
728                 if (curr_tx_rate == AUTORATE || curr_tx_rate == MBPS_1 ||
729                     curr_tx_rate == MBPS_2 || curr_tx_rate == MBPS_5_5 ||
730                     curr_tx_rate == MBPS_11 || curr_tx_rate == MBPS_6 ||
731                     curr_tx_rate == MBPS_9 || curr_tx_rate == MBPS_12 ||
732                     curr_tx_rate == MBPS_18 || curr_tx_rate == MBPS_24 ||
733                     curr_tx_rate == MBPS_36 || curr_tx_rate == MBPS_48 ||
734                     curr_tx_rate == MBPS_54) {
735                         wid_list[i].id = WID_CURRENT_TX_RATE;
736                         wid_list[i].val = (s8 *)&curr_tx_rate;
737                         wid_list[i].type = WID_SHORT;
738                         wid_list[i].size = sizeof(u16);
739                         hif_drv->cfg_values.curr_tx_rate = (u8)curr_tx_rate;
740                 } else {
741                         netdev_err(vif->ndev, "out of TX rate\n");
742                         goto unlock;
743                 }
744                 i++;
745         }
746
747         ret = wilc_send_config_pkt(vif, SET_CFG, wid_list,
748                                    i, wilc_get_vif_idx(vif));
749
750         if (ret)
751                 netdev_err(vif->ndev, "Error in setting CFG params\n");
752
753 unlock:
754         mutex_unlock(&hif_drv->cfg_values_lock);
755 }
756
757 static s32 handle_scan(struct wilc_vif *vif, struct scan_attr *scan_info)
758 {
759         s32 result = 0;
760         struct wid wid_list[5];
761         u32 index = 0;
762         u32 i;
763         u8 *buffer;
764         u8 valuesize = 0;
765         u8 *hdn_ntwk_wid_val = NULL;
766         struct host_if_drv *hif_drv = vif->hif_drv;
767         struct hidden_network *hidden_net = &scan_info->hidden_network;
768
769         hif_drv->usr_scan_req.scan_result = scan_info->result;
770         hif_drv->usr_scan_req.arg = scan_info->arg;
771
772         if (hif_drv->hif_state >= HOST_IF_SCANNING &&
773             hif_drv->hif_state < HOST_IF_CONNECTED) {
774                 netdev_err(vif->ndev, "Already scan\n");
775                 result = -EBUSY;
776                 goto error;
777         }
778
779         if (wilc_optaining_ip || wilc_connecting) {
780                 netdev_err(vif->ndev, "Don't do obss scan\n");
781                 result = -EBUSY;
782                 goto error;
783         }
784
785         hif_drv->usr_scan_req.rcvd_ch_cnt = 0;
786
787         wid_list[index].id = (u16)WID_SSID_PROBE_REQ;
788         wid_list[index].type = WID_STR;
789
790         for (i = 0; i < hidden_net->n_ssids; i++)
791                 valuesize += ((hidden_net->net_info[i].ssid_len) + 1);
792         hdn_ntwk_wid_val = kmalloc(valuesize + 1, GFP_KERNEL);
793         wid_list[index].val = hdn_ntwk_wid_val;
794         if (wid_list[index].val) {
795                 buffer = wid_list[index].val;
796
797                 *buffer++ = hidden_net->n_ssids;
798
799                 for (i = 0; i < hidden_net->n_ssids; i++) {
800                         *buffer++ = hidden_net->net_info[i].ssid_len;
801                         memcpy(buffer, hidden_net->net_info[i].ssid,
802                                hidden_net->net_info[i].ssid_len);
803                         buffer += hidden_net->net_info[i].ssid_len;
804                 }
805
806                 wid_list[index].size = (s32)(valuesize + 1);
807                 index++;
808         }
809
810         wid_list[index].id = WID_INFO_ELEMENT_PROBE;
811         wid_list[index].type = WID_BIN_DATA;
812         wid_list[index].val = scan_info->ies;
813         wid_list[index].size = scan_info->ies_len;
814         index++;
815
816         wid_list[index].id = WID_SCAN_TYPE;
817         wid_list[index].type = WID_CHAR;
818         wid_list[index].size = sizeof(char);
819         wid_list[index].val = (s8 *)&scan_info->type;
820         index++;
821
822         wid_list[index].id = WID_SCAN_CHANNEL_LIST;
823         wid_list[index].type = WID_BIN_DATA;
824
825         if (scan_info->ch_freq_list &&
826             scan_info->ch_list_len > 0) {
827                 int i;
828
829                 for (i = 0; i < scan_info->ch_list_len; i++)    {
830                         if (scan_info->ch_freq_list[i] > 0)
831                                 scan_info->ch_freq_list[i] -= 1;
832                 }
833         }
834
835         wid_list[index].val = scan_info->ch_freq_list;
836         wid_list[index].size = scan_info->ch_list_len;
837         index++;
838
839         wid_list[index].id = WID_START_SCAN_REQ;
840         wid_list[index].type = WID_CHAR;
841         wid_list[index].size = sizeof(char);
842         wid_list[index].val = (s8 *)&scan_info->src;
843         index++;
844
845         if (hif_drv->hif_state == HOST_IF_CONNECTED)
846                 scan_while_connected = true;
847         else if (hif_drv->hif_state == HOST_IF_IDLE)
848                 scan_while_connected = false;
849
850         result = wilc_send_config_pkt(vif, SET_CFG, wid_list,
851                                       index,
852                                       wilc_get_vif_idx(vif));
853
854         if (result)
855                 netdev_err(vif->ndev, "Failed to send scan parameters\n");
856
857 error:
858         if (result) {
859                 del_timer(&hif_drv->scan_timer);
860                 handle_scan_done(vif, SCAN_EVENT_ABORTED);
861         }
862
863         kfree(scan_info->ch_freq_list);
864         scan_info->ch_freq_list = NULL;
865
866         kfree(scan_info->ies);
867         scan_info->ies = NULL;
868         kfree(scan_info->hidden_network.net_info);
869         scan_info->hidden_network.net_info = NULL;
870
871         kfree(hdn_ntwk_wid_val);
872
873         return result;
874 }
875
876 static s32 handle_scan_done(struct wilc_vif *vif, enum scan_event evt)
877 {
878         s32 result = 0;
879         u8 abort_running_scan;
880         struct wid wid;
881         struct host_if_drv *hif_drv = vif->hif_drv;
882         struct user_scan_req *scan_req;
883
884         if (evt == SCAN_EVENT_ABORTED) {
885                 abort_running_scan = 1;
886                 wid.id = (u16)WID_ABORT_RUNNING_SCAN;
887                 wid.type = WID_CHAR;
888                 wid.val = (s8 *)&abort_running_scan;
889                 wid.size = sizeof(char);
890
891                 result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1,
892                                               wilc_get_vif_idx(vif));
893
894                 if (result) {
895                         netdev_err(vif->ndev, "Failed to set abort running\n");
896                         result = -EFAULT;
897                 }
898         }
899
900         if (!hif_drv) {
901                 netdev_err(vif->ndev, "Driver handler is NULL\n");
902                 return result;
903         }
904
905         scan_req = &hif_drv->usr_scan_req;
906         if (scan_req->scan_result) {
907                 scan_req->scan_result(evt, NULL, scan_req->arg, NULL);
908                 scan_req->scan_result = NULL;
909         }
910
911         return result;
912 }
913
914 u8 wilc_connected_ssid[6] = {0};
915 static s32 handle_connect(struct wilc_vif *vif,
916                           struct connect_attr *conn_attr)
917 {
918         s32 result = 0;
919         struct wid wid_list[8];
920         u32 wid_cnt = 0, dummyval = 0;
921         u8 *cur_byte = NULL;
922         struct join_bss_param *bss_param;
923         struct host_if_drv *hif_drv = vif->hif_drv;
924
925         if (memcmp(conn_attr->bssid, wilc_connected_ssid, ETH_ALEN) == 0) {
926                 result = 0;
927                 netdev_err(vif->ndev, "Discard connect request\n");
928                 return result;
929         }
930
931         bss_param = conn_attr->params;
932         if (!bss_param) {
933                 netdev_err(vif->ndev, "Required BSSID not found\n");
934                 result = -ENOENT;
935                 goto error;
936         }
937
938         if (conn_attr->bssid) {
939                 hif_drv->usr_conn_req.bssid = kmemdup(conn_attr->bssid, 6,
940                                                       GFP_KERNEL);
941                 if (!hif_drv->usr_conn_req.bssid) {
942                         result = -ENOMEM;
943                         goto error;
944                 }
945         }
946
947         hif_drv->usr_conn_req.ssid_len = conn_attr->ssid_len;
948         if (conn_attr->ssid) {
949                 hif_drv->usr_conn_req.ssid = kmalloc(conn_attr->ssid_len + 1,
950                                                      GFP_KERNEL);
951                 if (!hif_drv->usr_conn_req.ssid) {
952                         result = -ENOMEM;
953                         goto error;
954                 }
955                 memcpy(hif_drv->usr_conn_req.ssid,
956                        conn_attr->ssid,
957                        conn_attr->ssid_len);
958                 hif_drv->usr_conn_req.ssid[conn_attr->ssid_len] = '\0';
959         }
960
961         hif_drv->usr_conn_req.ies_len = conn_attr->ies_len;
962         if (conn_attr->ies) {
963                 hif_drv->usr_conn_req.ies = kmemdup(conn_attr->ies,
964                                                     conn_attr->ies_len,
965                                                     GFP_KERNEL);
966                 if (!hif_drv->usr_conn_req.ies) {
967                         result = -ENOMEM;
968                         goto error;
969                 }
970         }
971
972         hif_drv->usr_conn_req.security = conn_attr->security;
973         hif_drv->usr_conn_req.auth_type = conn_attr->auth_type;
974         hif_drv->usr_conn_req.conn_result = conn_attr->result;
975         hif_drv->usr_conn_req.arg = conn_attr->arg;
976
977         wid_list[wid_cnt].id = WID_SUCCESS_FRAME_COUNT;
978         wid_list[wid_cnt].type = WID_INT;
979         wid_list[wid_cnt].size = sizeof(u32);
980         wid_list[wid_cnt].val = (s8 *)(&(dummyval));
981         wid_cnt++;
982
983         wid_list[wid_cnt].id = WID_RECEIVED_FRAGMENT_COUNT;
984         wid_list[wid_cnt].type = WID_INT;
985         wid_list[wid_cnt].size = sizeof(u32);
986         wid_list[wid_cnt].val = (s8 *)(&(dummyval));
987         wid_cnt++;
988
989         wid_list[wid_cnt].id = WID_FAILED_COUNT;
990         wid_list[wid_cnt].type = WID_INT;
991         wid_list[wid_cnt].size = sizeof(u32);
992         wid_list[wid_cnt].val = (s8 *)(&(dummyval));
993         wid_cnt++;
994
995         wid_list[wid_cnt].id = WID_INFO_ELEMENT_ASSOCIATE;
996         wid_list[wid_cnt].type = WID_BIN_DATA;
997         wid_list[wid_cnt].val = hif_drv->usr_conn_req.ies;
998         wid_list[wid_cnt].size = hif_drv->usr_conn_req.ies_len;
999         wid_cnt++;
1000
1001         wid_list[wid_cnt].id = (u16)WID_11I_MODE;
1002         wid_list[wid_cnt].type = WID_CHAR;
1003         wid_list[wid_cnt].size = sizeof(char);
1004         wid_list[wid_cnt].val = (s8 *)&hif_drv->usr_conn_req.security;
1005         wid_cnt++;
1006
1007         wid_list[wid_cnt].id = (u16)WID_AUTH_TYPE;
1008         wid_list[wid_cnt].type = WID_CHAR;
1009         wid_list[wid_cnt].size = sizeof(char);
1010         wid_list[wid_cnt].val = (s8 *)&hif_drv->usr_conn_req.auth_type;
1011         wid_cnt++;
1012
1013         wid_list[wid_cnt].id = (u16)WID_JOIN_REQ_EXTENDED;
1014         wid_list[wid_cnt].type = WID_STR;
1015         wid_list[wid_cnt].size = 112;
1016         wid_list[wid_cnt].val = kmalloc(wid_list[wid_cnt].size, GFP_KERNEL);
1017
1018         if (!wid_list[wid_cnt].val) {
1019                 result = -EFAULT;
1020                 goto error;
1021         }
1022
1023         cur_byte = wid_list[wid_cnt].val;
1024
1025         if (conn_attr->ssid) {
1026                 memcpy(cur_byte, conn_attr->ssid, conn_attr->ssid_len);
1027                 cur_byte[conn_attr->ssid_len] = '\0';
1028         }
1029         cur_byte += MAX_SSID_LEN;
1030         *(cur_byte++) = INFRASTRUCTURE;
1031
1032         if (conn_attr->ch >= 1 && conn_attr->ch <= 14) {
1033                 *(cur_byte++) = conn_attr->ch;
1034         } else {
1035                 netdev_err(vif->ndev, "Channel out of range\n");
1036                 *(cur_byte++) = 0xFF;
1037         }
1038         *(cur_byte++)  = (bss_param->cap_info) & 0xFF;
1039         *(cur_byte++)  = ((bss_param->cap_info) >> 8) & 0xFF;
1040
1041         if (conn_attr->bssid)
1042                 memcpy(cur_byte, conn_attr->bssid, 6);
1043         cur_byte += 6;
1044
1045         if (conn_attr->bssid)
1046                 memcpy(cur_byte, conn_attr->bssid, 6);
1047         cur_byte += 6;
1048
1049         *(cur_byte++)  = (bss_param->beacon_period) & 0xFF;
1050         *(cur_byte++)  = ((bss_param->beacon_period) >> 8) & 0xFF;
1051         *(cur_byte++)  =  bss_param->dtim_period;
1052
1053         memcpy(cur_byte, bss_param->supp_rates, MAX_RATES_SUPPORTED + 1);
1054         cur_byte += (MAX_RATES_SUPPORTED + 1);
1055
1056         *(cur_byte++)  =  bss_param->wmm_cap;
1057         *(cur_byte++)  = bss_param->uapsd_cap;
1058
1059         *(cur_byte++)  = bss_param->ht_capable;
1060         hif_drv->usr_conn_req.ht_capable = bss_param->ht_capable;
1061
1062         *(cur_byte++)  =  bss_param->rsn_found;
1063         *(cur_byte++)  =  bss_param->rsn_grp_policy;
1064         *(cur_byte++) =  bss_param->mode_802_11i;
1065
1066         memcpy(cur_byte, bss_param->rsn_pcip_policy,
1067                sizeof(bss_param->rsn_pcip_policy));
1068         cur_byte += sizeof(bss_param->rsn_pcip_policy);
1069
1070         memcpy(cur_byte, bss_param->rsn_auth_policy,
1071                sizeof(bss_param->rsn_auth_policy));
1072         cur_byte += sizeof(bss_param->rsn_auth_policy);
1073
1074         memcpy(cur_byte, bss_param->rsn_cap, sizeof(bss_param->rsn_cap));
1075         cur_byte += sizeof(bss_param->rsn_cap);
1076
1077         *(cur_byte++) = REAL_JOIN_REQ;
1078         *(cur_byte++) = bss_param->noa_enabled;
1079
1080         if (bss_param->noa_enabled) {
1081                 *(cur_byte++) = (bss_param->tsf) & 0xFF;
1082                 *(cur_byte++) = ((bss_param->tsf) >> 8) & 0xFF;
1083                 *(cur_byte++) = ((bss_param->tsf) >> 16) & 0xFF;
1084                 *(cur_byte++) = ((bss_param->tsf) >> 24) & 0xFF;
1085
1086                 *(cur_byte++) = bss_param->opp_enabled;
1087                 *(cur_byte++) = bss_param->idx;
1088
1089                 if (bss_param->opp_enabled)
1090                         *(cur_byte++) = bss_param->ct_window;
1091
1092                 *(cur_byte++) = bss_param->cnt;
1093
1094                 memcpy(cur_byte, bss_param->duration,
1095                        sizeof(bss_param->duration));
1096                 cur_byte += sizeof(bss_param->duration);
1097
1098                 memcpy(cur_byte, bss_param->interval,
1099                        sizeof(bss_param->interval));
1100                 cur_byte += sizeof(bss_param->interval);
1101
1102                 memcpy(cur_byte, bss_param->start_time,
1103                        sizeof(bss_param->start_time));
1104                 cur_byte += sizeof(bss_param->start_time);
1105         }
1106
1107         cur_byte = wid_list[wid_cnt].val;
1108         wid_cnt++;
1109
1110         if (conn_attr->bssid)
1111                 memcpy(wilc_connected_ssid,
1112                        conn_attr->bssid, ETH_ALEN);
1113
1114         result = wilc_send_config_pkt(vif, SET_CFG, wid_list,
1115                                       wid_cnt,
1116                                       wilc_get_vif_idx(vif));
1117         if (result) {
1118                 netdev_err(vif->ndev, "failed to send config packet\n");
1119                 result = -EFAULT;
1120                 goto error;
1121         } else {
1122                 hif_drv->hif_state = HOST_IF_WAITING_CONN_RESP;
1123         }
1124
1125 error:
1126         if (result) {
1127                 struct connect_info conn_info;
1128
1129                 del_timer(&hif_drv->connect_timer);
1130
1131                 memset(&conn_info, 0, sizeof(struct connect_info));
1132
1133                 if (conn_attr->result) {
1134                         if (conn_attr->bssid)
1135                                 memcpy(conn_info.bssid, conn_attr->bssid, 6);
1136
1137                         if (conn_attr->ies) {
1138                                 conn_info.req_ies_len = conn_attr->ies_len;
1139                                 conn_info.req_ies = kmalloc(conn_attr->ies_len,
1140                                                             GFP_KERNEL);
1141                                 memcpy(conn_info.req_ies,
1142                                        conn_attr->ies,
1143                                        conn_attr->ies_len);
1144                         }
1145
1146                         conn_attr->result(CONN_DISCONN_EVENT_CONN_RESP,
1147                                                                &conn_info,
1148                                                                MAC_DISCONNECTED,
1149                                                                NULL,
1150                                                                conn_attr->arg);
1151                         hif_drv->hif_state = HOST_IF_IDLE;
1152                         kfree(conn_info.req_ies);
1153                         conn_info.req_ies = NULL;
1154
1155                 } else {
1156                         netdev_err(vif->ndev, "Connect callback is NULL\n");
1157                 }
1158         }
1159
1160         kfree(conn_attr->bssid);
1161         conn_attr->bssid = NULL;
1162
1163         kfree(conn_attr->ssid);
1164         conn_attr->ssid = NULL;
1165
1166         kfree(conn_attr->ies);
1167         conn_attr->ies = NULL;
1168
1169         kfree(cur_byte);
1170         return result;
1171 }
1172
1173 static s32 handle_connect_timeout(struct wilc_vif *vif)
1174 {
1175         s32 result = 0;
1176         struct connect_info info;
1177         struct wid wid;
1178         u16 dummy_reason_code = 0;
1179         struct host_if_drv *hif_drv = vif->hif_drv;
1180
1181         if (!hif_drv) {
1182                 netdev_err(vif->ndev, "Driver handler is NULL\n");
1183                 return result;
1184         }
1185
1186         hif_drv->hif_state = HOST_IF_IDLE;
1187
1188         scan_while_connected = false;
1189
1190         memset(&info, 0, sizeof(struct connect_info));
1191
1192         if (hif_drv->usr_conn_req.conn_result) {
1193                 if (hif_drv->usr_conn_req.bssid) {
1194                         memcpy(info.bssid,
1195                                hif_drv->usr_conn_req.bssid, 6);
1196                 }
1197
1198                 if (hif_drv->usr_conn_req.ies) {
1199                         info.req_ies_len = hif_drv->usr_conn_req.ies_len;
1200                         info.req_ies = kmalloc(hif_drv->usr_conn_req.ies_len, GFP_KERNEL);
1201                         memcpy(info.req_ies,
1202                                hif_drv->usr_conn_req.ies,
1203                                hif_drv->usr_conn_req.ies_len);
1204                 }
1205
1206                 hif_drv->usr_conn_req.conn_result(CONN_DISCONN_EVENT_CONN_RESP,
1207                                                   &info,
1208                                                   MAC_DISCONNECTED,
1209                                                   NULL,
1210                                                   hif_drv->usr_conn_req.arg);
1211
1212                 kfree(info.req_ies);
1213                 info.req_ies = NULL;
1214         } else {
1215                 netdev_err(vif->ndev, "Connect callback is NULL\n");
1216         }
1217
1218         wid.id = (u16)WID_DISCONNECT;
1219         wid.type = WID_CHAR;
1220         wid.val = (s8 *)&dummy_reason_code;
1221         wid.size = sizeof(char);
1222
1223         result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1,
1224                                       wilc_get_vif_idx(vif));
1225         if (result)
1226                 netdev_err(vif->ndev, "Failed to send disconnect\n");
1227
1228         hif_drv->usr_conn_req.ssid_len = 0;
1229         kfree(hif_drv->usr_conn_req.ssid);
1230         hif_drv->usr_conn_req.ssid = NULL;
1231         kfree(hif_drv->usr_conn_req.bssid);
1232         hif_drv->usr_conn_req.bssid = NULL;
1233         hif_drv->usr_conn_req.ies_len = 0;
1234         kfree(hif_drv->usr_conn_req.ies);
1235         hif_drv->usr_conn_req.ies = NULL;
1236
1237         eth_zero_addr(wilc_connected_ssid);
1238
1239         return result;
1240 }
1241
1242 static s32 handle_rcvd_ntwrk_info(struct wilc_vif *vif,
1243                                   struct rcvd_net_info *rcvd_info)
1244 {
1245         u32 i;
1246         bool found;
1247         s32 result = 0;
1248         struct network_info *info = NULL;
1249         void *params = NULL;
1250         struct host_if_drv *hif_drv = vif->hif_drv;
1251         struct user_scan_req *scan_req = &hif_drv->usr_scan_req;
1252
1253         found = true;
1254
1255         if (!scan_req->scan_result)
1256                 goto done;
1257
1258         wilc_parse_network_info(rcvd_info->buffer, &info);
1259         if (!info || !scan_req->scan_result) {
1260                 netdev_err(vif->ndev, "driver is null\n");
1261                 result = -EINVAL;
1262                 goto done;
1263         }
1264
1265         for (i = 0; i < scan_req->rcvd_ch_cnt; i++) {
1266                 if (memcmp(scan_req->net_info[i].bssid, info->bssid, 6) == 0) {
1267                         if (info->rssi <= scan_req->net_info[i].rssi) {
1268                                 goto done;
1269                         } else {
1270                                 scan_req->net_info[i].rssi = info->rssi;
1271                                 found = false;
1272                                 break;
1273                         }
1274                 }
1275         }
1276
1277         if (found) {
1278                 if (scan_req->rcvd_ch_cnt < MAX_NUM_SCANNED_NETWORKS) {
1279                         scan_req->net_info[scan_req->rcvd_ch_cnt].rssi = info->rssi;
1280
1281                         memcpy(scan_req->net_info[scan_req->rcvd_ch_cnt].bssid,
1282                                info->bssid, 6);
1283
1284                         scan_req->rcvd_ch_cnt++;
1285
1286                         info->new_network = true;
1287                         params = host_int_parse_join_bss_param(info);
1288
1289                         scan_req->scan_result(SCAN_EVENT_NETWORK_FOUND, info,
1290                                                scan_req->arg, params);
1291                 }
1292         } else {
1293                 info->new_network = false;
1294                 scan_req->scan_result(SCAN_EVENT_NETWORK_FOUND, info,
1295                                       scan_req->arg, NULL);
1296         }
1297
1298 done:
1299         kfree(rcvd_info->buffer);
1300         rcvd_info->buffer = NULL;
1301
1302         if (info) {
1303                 kfree(info->ies);
1304                 kfree(info);
1305         }
1306
1307         return result;
1308 }
1309
1310 static s32 host_int_get_assoc_res_info(struct wilc_vif *vif,
1311                                        u8 *assoc_resp_info,
1312                                        u32 max_assoc_resp_info_len,
1313                                        u32 *rcvd_assoc_resp_info_len);
1314
1315 static inline void host_int_free_user_conn_req(struct host_if_drv *hif_drv)
1316 {
1317         hif_drv->usr_conn_req.ssid_len = 0;
1318         kfree(hif_drv->usr_conn_req.ssid);
1319         hif_drv->usr_conn_req.ssid = NULL;
1320         kfree(hif_drv->usr_conn_req.bssid);
1321         hif_drv->usr_conn_req.bssid = NULL;
1322         hif_drv->usr_conn_req.ies_len = 0;
1323         kfree(hif_drv->usr_conn_req.ies);
1324         hif_drv->usr_conn_req.ies = NULL;
1325 }
1326
1327 static inline void host_int_parse_assoc_resp_info(struct wilc_vif *vif,
1328                                                   u8 mac_status)
1329 {
1330         struct connect_resp_info *connect_resp_info = NULL;
1331         struct connect_info conn_info;
1332         struct host_if_drv *hif_drv = vif->hif_drv;
1333
1334         memset(&conn_info, 0, sizeof(struct connect_info));
1335
1336         if (mac_status == MAC_CONNECTED) {
1337                 u32 rcvd_assoc_resp_info_len;
1338
1339                 memset(rcv_assoc_resp, 0, MAX_ASSOC_RESP_FRAME_SIZE);
1340
1341                 host_int_get_assoc_res_info(vif, rcv_assoc_resp,
1342                                             MAX_ASSOC_RESP_FRAME_SIZE,
1343                                             &rcvd_assoc_resp_info_len);
1344
1345                 if (rcvd_assoc_resp_info_len != 0) {
1346                         s32 err = 0;
1347
1348                         err = wilc_parse_assoc_resp_info(rcv_assoc_resp, rcvd_assoc_resp_info_len,
1349                                                          &connect_resp_info);
1350                         if (err) {
1351                                 netdev_err(vif->ndev,
1352                                            "wilc_parse_assoc_resp_info() returned error %d\n",
1353                                            err);
1354                         } else {
1355                                 conn_info.status = connect_resp_info->status;
1356
1357                                 if (conn_info.status == SUCCESSFUL_STATUSCODE &&
1358                                     connect_resp_info->ies) {
1359                                         conn_info.resp_ies = kmemdup(connect_resp_info->ies,
1360                                                                      connect_resp_info->ies_len,
1361                                                                      GFP_KERNEL);
1362                                         if (conn_info.resp_ies)
1363                                                 conn_info.resp_ies_len = connect_resp_info->ies_len;
1364                                 }
1365
1366                                 kfree(connect_resp_info->ies);
1367                                 kfree(connect_resp_info);
1368                         }
1369                 }
1370         }
1371
1372         if (mac_status == MAC_CONNECTED &&
1373             conn_info.status != SUCCESSFUL_STATUSCODE) {
1374                 netdev_err(vif->ndev,
1375                            "Received MAC status is MAC_CONNECTED while the received status code in Asoc Resp is not SUCCESSFUL_STATUSCODE\n");
1376                 eth_zero_addr(wilc_connected_ssid);
1377         } else if (mac_status == MAC_DISCONNECTED)    {
1378                 netdev_err(vif->ndev, "Received MAC status is MAC_DISCONNECTED\n");
1379                 eth_zero_addr(wilc_connected_ssid);
1380         }
1381
1382         if (hif_drv->usr_conn_req.bssid) {
1383                 memcpy(conn_info.bssid, hif_drv->usr_conn_req.bssid, 6);
1384
1385                 if (mac_status == MAC_CONNECTED &&
1386                     conn_info.status == SUCCESSFUL_STATUSCODE) {
1387                         memcpy(hif_drv->assoc_bssid,
1388                                hif_drv->usr_conn_req.bssid, ETH_ALEN);
1389                 }
1390         }
1391
1392         if (hif_drv->usr_conn_req.ies) {
1393                 conn_info.req_ies = kmemdup(hif_drv->usr_conn_req.ies,
1394                                             hif_drv->usr_conn_req.ies_len,
1395                                             GFP_KERNEL);
1396                 if (conn_info.req_ies)
1397                         conn_info.req_ies_len = hif_drv->usr_conn_req.ies_len;
1398         }
1399
1400         del_timer(&hif_drv->connect_timer);
1401         hif_drv->usr_conn_req.conn_result(CONN_DISCONN_EVENT_CONN_RESP,
1402                                           &conn_info, mac_status, NULL,
1403                                           hif_drv->usr_conn_req.arg);
1404
1405         if (mac_status == MAC_CONNECTED &&
1406             conn_info.status == SUCCESSFUL_STATUSCODE) {
1407                 wilc_set_power_mgmt(vif, 0, 0);
1408
1409                 hif_drv->hif_state = HOST_IF_CONNECTED;
1410
1411                 wilc_optaining_ip = true;
1412                 mod_timer(&wilc_during_ip_timer,
1413                           jiffies + msecs_to_jiffies(10000));
1414         } else {
1415                 hif_drv->hif_state = HOST_IF_IDLE;
1416                 scan_while_connected = false;
1417         }
1418
1419         kfree(conn_info.resp_ies);
1420         conn_info.resp_ies = NULL;
1421
1422         kfree(conn_info.req_ies);
1423         conn_info.req_ies = NULL;
1424         host_int_free_user_conn_req(hif_drv);
1425 }
1426
1427 static inline void host_int_handle_disconnect(struct wilc_vif *vif)
1428 {
1429         struct disconnect_info disconn_info;
1430         struct host_if_drv *hif_drv = vif->hif_drv;
1431
1432         memset(&disconn_info, 0, sizeof(struct disconnect_info));
1433
1434         if (hif_drv->usr_scan_req.scan_result) {
1435                 del_timer(&hif_drv->scan_timer);
1436                 handle_scan_done(vif, SCAN_EVENT_ABORTED);
1437         }
1438
1439         disconn_info.reason = 0;
1440         disconn_info.ie = NULL;
1441         disconn_info.ie_len = 0;
1442
1443         if (hif_drv->usr_conn_req.conn_result) {
1444                 wilc_optaining_ip = false;
1445                 wilc_set_power_mgmt(vif, 0, 0);
1446
1447                 hif_drv->usr_conn_req.conn_result(CONN_DISCONN_EVENT_DISCONN_NOTIF,
1448                                                   NULL, 0, &disconn_info,
1449                                                   hif_drv->usr_conn_req.arg);
1450         } else {
1451                 netdev_err(vif->ndev, "Connect result NULL\n");
1452         }
1453
1454         eth_zero_addr(hif_drv->assoc_bssid);
1455
1456         host_int_free_user_conn_req(hif_drv);
1457         hif_drv->hif_state = HOST_IF_IDLE;
1458         scan_while_connected = false;
1459 }
1460
1461 static s32 handle_rcvd_gnrl_async_info(struct wilc_vif *vif,
1462                                        struct rcvd_async_info *rcvd_info)
1463 {
1464         s32 result = 0;
1465         u8 msg_type = 0;
1466         u8 msg_id = 0;
1467         u16 msg_len = 0;
1468         u16 wid_id = (u16)WID_NIL;
1469         u8 wid_len  = 0;
1470         u8 mac_status;
1471         u8 mac_status_reason_code;
1472         u8 mac_status_additional_info;
1473         struct host_if_drv *hif_drv = vif->hif_drv;
1474
1475         if (!rcvd_info->buffer) {
1476                 netdev_err(vif->ndev, "Received buffer is NULL\n");
1477                 return -EINVAL;
1478         }
1479
1480         if (!hif_drv) {
1481                 netdev_err(vif->ndev, "Driver handler is NULL\n");
1482                 kfree(rcvd_info->buffer);
1483                 rcvd_info->buffer = NULL;
1484                 return -ENODEV;
1485         }
1486
1487         if (hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP ||
1488             hif_drv->hif_state == HOST_IF_CONNECTED ||
1489             hif_drv->usr_scan_req.scan_result) {
1490                 if (!hif_drv->usr_conn_req.conn_result) {
1491                         netdev_err(vif->ndev, "driver is null\n");
1492                         kfree(rcvd_info->buffer);
1493                         rcvd_info->buffer = NULL;
1494                         return -EINVAL;
1495                 }
1496
1497                 msg_type = rcvd_info->buffer[0];
1498
1499                 if ('I' != msg_type) {
1500                         netdev_err(vif->ndev, "Received Message incorrect.\n");
1501                         kfree(rcvd_info->buffer);
1502                         rcvd_info->buffer = NULL;
1503                         return -EFAULT;
1504                 }
1505
1506                 msg_id = rcvd_info->buffer[1];
1507                 msg_len = MAKE_WORD16(rcvd_info->buffer[2], rcvd_info->buffer[3]);
1508                 wid_id = MAKE_WORD16(rcvd_info->buffer[4], rcvd_info->buffer[5]);
1509                 wid_len = rcvd_info->buffer[6];
1510                 mac_status  = rcvd_info->buffer[7];
1511                 mac_status_reason_code = rcvd_info->buffer[8];
1512                 mac_status_additional_info = rcvd_info->buffer[9];
1513                 if (hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP) {
1514                         host_int_parse_assoc_resp_info(vif, mac_status);
1515                 } else if ((mac_status == MAC_DISCONNECTED) &&
1516                            (hif_drv->hif_state == HOST_IF_CONNECTED)) {
1517                         host_int_handle_disconnect(vif);
1518                 } else if ((mac_status == MAC_DISCONNECTED) &&
1519                            (hif_drv->usr_scan_req.scan_result)) {
1520                         del_timer(&hif_drv->scan_timer);
1521                         if (hif_drv->usr_scan_req.scan_result)
1522                                 handle_scan_done(vif, SCAN_EVENT_ABORTED);
1523                 }
1524         }
1525
1526         kfree(rcvd_info->buffer);
1527         rcvd_info->buffer = NULL;
1528
1529         return result;
1530 }
1531
1532 static int handle_key(struct wilc_vif *vif, struct key_attr *hif_key)
1533 {
1534         s32 result = 0;
1535         struct wid wid;
1536         struct wid wid_list[5];
1537         u8 i;
1538         u8 *key_buf;
1539         s8 s8idxarray[1];
1540         s8 ret = 0;
1541         struct host_if_drv *hif_drv = vif->hif_drv;
1542
1543         switch (hif_key->type) {
1544         case WEP:
1545
1546                 if (hif_key->action & ADDKEY_AP) {
1547                         wid_list[0].id = (u16)WID_11I_MODE;
1548                         wid_list[0].type = WID_CHAR;
1549                         wid_list[0].size = sizeof(char);
1550                         wid_list[0].val = (s8 *)&hif_key->attr.wep.mode;
1551
1552                         wid_list[1].id = WID_AUTH_TYPE;
1553                         wid_list[1].type = WID_CHAR;
1554                         wid_list[1].size = sizeof(char);
1555                         wid_list[1].val = (s8 *)&hif_key->attr.wep.auth_type;
1556
1557                         key_buf = kmalloc(hif_key->attr.wep.key_len + 2,
1558                                           GFP_KERNEL);
1559                         if (!key_buf)
1560                                 return -ENOMEM;
1561
1562                         key_buf[0] = hif_key->attr.wep.index;
1563                         key_buf[1] = hif_key->attr.wep.key_len;
1564
1565                         memcpy(&key_buf[2], hif_key->attr.wep.key,
1566                                hif_key->attr.wep.key_len);
1567
1568                         kfree(hif_key->attr.wep.key);
1569
1570                         wid_list[2].id = (u16)WID_WEP_KEY_VALUE;
1571                         wid_list[2].type = WID_STR;
1572                         wid_list[2].size = hif_key->attr.wep.key_len + 2;
1573                         wid_list[2].val = (s8 *)key_buf;
1574
1575                         result = wilc_send_config_pkt(vif, SET_CFG,
1576                                                       wid_list, 3,
1577                                                       wilc_get_vif_idx(vif));
1578                         kfree(key_buf);
1579                 } else if (hif_key->action & ADDKEY) {
1580                         key_buf = kmalloc(hif_key->attr.wep.key_len + 2, GFP_KERNEL);
1581                         if (!key_buf)
1582                                 return -ENOMEM;
1583                         key_buf[0] = hif_key->attr.wep.index;
1584                         memcpy(key_buf + 1, &hif_key->attr.wep.key_len, 1);
1585                         memcpy(key_buf + 2, hif_key->attr.wep.key,
1586                                hif_key->attr.wep.key_len);
1587                         kfree(hif_key->attr.wep.key);
1588
1589                         wid.id = (u16)WID_ADD_WEP_KEY;
1590                         wid.type = WID_STR;
1591                         wid.val = (s8 *)key_buf;
1592                         wid.size = hif_key->attr.wep.key_len + 2;
1593
1594                         result = wilc_send_config_pkt(vif, SET_CFG,
1595                                                       &wid, 1,
1596                                                       wilc_get_vif_idx(vif));
1597                         kfree(key_buf);
1598                 } else if (hif_key->action & REMOVEKEY) {
1599                         wid.id = (u16)WID_REMOVE_WEP_KEY;
1600                         wid.type = WID_STR;
1601
1602                         s8idxarray[0] = (s8)hif_key->attr.wep.index;
1603                         wid.val = s8idxarray;
1604                         wid.size = 1;
1605
1606                         result = wilc_send_config_pkt(vif, SET_CFG,
1607                                                       &wid, 1,
1608                                                       wilc_get_vif_idx(vif));
1609                 } else if (hif_key->action & DEFAULTKEY) {
1610                         wid.id = (u16)WID_KEY_ID;
1611                         wid.type = WID_CHAR;
1612                         wid.val = (s8 *)&hif_key->attr.wep.index;
1613                         wid.size = sizeof(char);
1614
1615                         result = wilc_send_config_pkt(vif, SET_CFG,
1616                                                       &wid, 1,
1617                                                       wilc_get_vif_idx(vif));
1618                 }
1619                 complete(&hif_drv->comp_test_key_block);
1620                 break;
1621
1622         case WPA_RX_GTK:
1623                 if (hif_key->action & ADDKEY_AP) {
1624                         key_buf = kzalloc(RX_MIC_KEY_MSG_LEN, GFP_KERNEL);
1625                         if (!key_buf) {
1626                                 ret = -ENOMEM;
1627                                 goto out_wpa_rx_gtk;
1628                         }
1629
1630                         if (hif_key->attr.wpa.seq)
1631                                 memcpy(key_buf + 6, hif_key->attr.wpa.seq, 8);
1632
1633                         memcpy(key_buf + 14, &hif_key->attr.wpa.index, 1);
1634                         memcpy(key_buf + 15, &hif_key->attr.wpa.key_len, 1);
1635                         memcpy(key_buf + 16, hif_key->attr.wpa.key,
1636                                hif_key->attr.wpa.key_len);
1637
1638                         wid_list[0].id = (u16)WID_11I_MODE;
1639                         wid_list[0].type = WID_CHAR;
1640                         wid_list[0].size = sizeof(char);
1641                         wid_list[0].val = (s8 *)&hif_key->attr.wpa.mode;
1642
1643                         wid_list[1].id = (u16)WID_ADD_RX_GTK;
1644                         wid_list[1].type = WID_STR;
1645                         wid_list[1].val = (s8 *)key_buf;
1646                         wid_list[1].size = RX_MIC_KEY_MSG_LEN;
1647
1648                         result = wilc_send_config_pkt(vif, SET_CFG,
1649                                                       wid_list, 2,
1650                                                       wilc_get_vif_idx(vif));
1651
1652                         kfree(key_buf);
1653                         complete(&hif_drv->comp_test_key_block);
1654                 } else if (hif_key->action & ADDKEY) {
1655                         key_buf = kzalloc(RX_MIC_KEY_MSG_LEN, GFP_KERNEL);
1656                         if (!key_buf) {
1657                                 ret = -ENOMEM;
1658                                 goto out_wpa_rx_gtk;
1659                         }
1660
1661                         if (hif_drv->hif_state == HOST_IF_CONNECTED)
1662                                 memcpy(key_buf, hif_drv->assoc_bssid, ETH_ALEN);
1663                         else
1664                                 netdev_err(vif->ndev, "Couldn't handle\n");
1665
1666                         memcpy(key_buf + 6, hif_key->attr.wpa.seq, 8);
1667                         memcpy(key_buf + 14, &hif_key->attr.wpa.index, 1);
1668                         memcpy(key_buf + 15, &hif_key->attr.wpa.key_len, 1);
1669                         memcpy(key_buf + 16, hif_key->attr.wpa.key,
1670                                hif_key->attr.wpa.key_len);
1671
1672                         wid.id = (u16)WID_ADD_RX_GTK;
1673                         wid.type = WID_STR;
1674                         wid.val = (s8 *)key_buf;
1675                         wid.size = RX_MIC_KEY_MSG_LEN;
1676
1677                         result = wilc_send_config_pkt(vif, SET_CFG,
1678                                                       &wid, 1,
1679                                                       wilc_get_vif_idx(vif));
1680
1681                         kfree(key_buf);
1682                         complete(&hif_drv->comp_test_key_block);
1683                 }
1684 out_wpa_rx_gtk:
1685                 kfree(hif_key->attr.wpa.key);
1686                 kfree(hif_key->attr.wpa.seq);
1687                 if (ret)
1688                         return ret;
1689
1690                 break;
1691
1692         case WPA_PTK:
1693                 if (hif_key->action & ADDKEY_AP) {
1694                         key_buf = kmalloc(PTK_KEY_MSG_LEN + 1, GFP_KERNEL);
1695                         if (!key_buf) {
1696                                 ret = -ENOMEM;
1697                                 goto out_wpa_ptk;
1698                         }
1699
1700                         memcpy(key_buf, hif_key->attr.wpa.mac_addr, 6);
1701                         memcpy(key_buf + 6, &hif_key->attr.wpa.index, 1);
1702                         memcpy(key_buf + 7, &hif_key->attr.wpa.key_len, 1);
1703                         memcpy(key_buf + 8, hif_key->attr.wpa.key,
1704                                hif_key->attr.wpa.key_len);
1705
1706                         wid_list[0].id = (u16)WID_11I_MODE;
1707                         wid_list[0].type = WID_CHAR;
1708                         wid_list[0].size = sizeof(char);
1709                         wid_list[0].val = (s8 *)&hif_key->attr.wpa.mode;
1710
1711                         wid_list[1].id = (u16)WID_ADD_PTK;
1712                         wid_list[1].type = WID_STR;
1713                         wid_list[1].val = (s8 *)key_buf;
1714                         wid_list[1].size = PTK_KEY_MSG_LEN + 1;
1715
1716                         result = wilc_send_config_pkt(vif, SET_CFG,
1717                                                       wid_list, 2,
1718                                                       wilc_get_vif_idx(vif));
1719                         kfree(key_buf);
1720                         complete(&hif_drv->comp_test_key_block);
1721                 } else if (hif_key->action & ADDKEY) {
1722                         key_buf = kmalloc(PTK_KEY_MSG_LEN, GFP_KERNEL);
1723                         if (!key_buf) {
1724                                 netdev_err(vif->ndev, "No buffer send PTK\n");
1725                                 ret = -ENOMEM;
1726                                 goto out_wpa_ptk;
1727                         }
1728
1729                         memcpy(key_buf, hif_key->attr.wpa.mac_addr, 6);
1730                         memcpy(key_buf + 6, &hif_key->attr.wpa.key_len, 1);
1731                         memcpy(key_buf + 7, hif_key->attr.wpa.key,
1732                                hif_key->attr.wpa.key_len);
1733
1734                         wid.id = (u16)WID_ADD_PTK;
1735                         wid.type = WID_STR;
1736                         wid.val = (s8 *)key_buf;
1737                         wid.size = PTK_KEY_MSG_LEN;
1738
1739                         result = wilc_send_config_pkt(vif, SET_CFG,
1740                                                       &wid, 1,
1741                                                       wilc_get_vif_idx(vif));
1742                         kfree(key_buf);
1743                         complete(&hif_drv->comp_test_key_block);
1744                 }
1745
1746 out_wpa_ptk:
1747                 kfree(hif_key->attr.wpa.key);
1748                 if (ret)
1749                         return ret;
1750
1751                 break;
1752
1753         case PMKSA:
1754                 key_buf = kmalloc((hif_key->attr.pmkid.numpmkid * PMKSA_KEY_LEN) + 1, GFP_KERNEL);
1755                 if (!key_buf)
1756                         return -ENOMEM;
1757
1758                 key_buf[0] = hif_key->attr.pmkid.numpmkid;
1759
1760                 for (i = 0; i < hif_key->attr.pmkid.numpmkid; i++) {
1761                         memcpy(key_buf + ((PMKSA_KEY_LEN * i) + 1), hif_key->attr.pmkid.pmkidlist[i].bssid, ETH_ALEN);
1762                         memcpy(key_buf + ((PMKSA_KEY_LEN * i) + ETH_ALEN + 1), hif_key->attr.pmkid.pmkidlist[i].pmkid, PMKID_LEN);
1763                 }
1764
1765                 wid.id = (u16)WID_PMKID_INFO;
1766                 wid.type = WID_STR;
1767                 wid.val = (s8 *)key_buf;
1768                 wid.size = (hif_key->attr.pmkid.numpmkid * PMKSA_KEY_LEN) + 1;
1769
1770                 result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1,
1771                                               wilc_get_vif_idx(vif));
1772
1773                 kfree(key_buf);
1774                 break;
1775         }
1776
1777         if (result)
1778                 netdev_err(vif->ndev, "Failed to send key config packet\n");
1779
1780         return result;
1781 }
1782
1783 static void handle_disconnect(struct wilc_vif *vif)
1784 {
1785         struct wid wid;
1786         struct host_if_drv *hif_drv = vif->hif_drv;
1787         struct disconnect_info disconn_info;
1788         struct user_scan_req *scan_req;
1789         struct user_conn_req *conn_req;
1790         s32 result = 0;
1791         u16 dummy_reason_code = 0;
1792
1793         wid.id = (u16)WID_DISCONNECT;
1794         wid.type = WID_CHAR;
1795         wid.val = (s8 *)&dummy_reason_code;
1796         wid.size = sizeof(char);
1797
1798         wilc_optaining_ip = false;
1799         wilc_set_power_mgmt(vif, 0, 0);
1800
1801         eth_zero_addr(wilc_connected_ssid);
1802
1803         result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1,
1804                                       wilc_get_vif_idx(vif));
1805
1806         if (result) {
1807                 netdev_err(vif->ndev, "Failed to send dissconect\n");
1808                 goto out;
1809         }
1810
1811         memset(&disconn_info, 0, sizeof(struct disconnect_info));
1812
1813         disconn_info.reason = 0;
1814         disconn_info.ie = NULL;
1815         disconn_info.ie_len = 0;
1816         scan_req = &hif_drv->usr_scan_req;
1817         conn_req = &hif_drv->usr_conn_req;
1818
1819         if (scan_req->scan_result) {
1820                 del_timer(&hif_drv->scan_timer);
1821                 scan_req->scan_result(SCAN_EVENT_ABORTED, NULL, scan_req->arg,
1822                                       NULL);
1823                 scan_req->scan_result = NULL;
1824         }
1825
1826         if (conn_req->conn_result) {
1827                 if (hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP)
1828                         del_timer(&hif_drv->connect_timer);
1829
1830                 conn_req->conn_result(CONN_DISCONN_EVENT_DISCONN_NOTIF, NULL,
1831                                       0, &disconn_info, conn_req->arg);
1832         } else {
1833                 netdev_err(vif->ndev, "conn_result = NULL\n");
1834         }
1835
1836         scan_while_connected = false;
1837
1838         hif_drv->hif_state = HOST_IF_IDLE;
1839
1840         eth_zero_addr(hif_drv->assoc_bssid);
1841
1842         conn_req->ssid_len = 0;
1843         kfree(conn_req->ssid);
1844         conn_req->ssid = NULL;
1845         kfree(conn_req->bssid);
1846         conn_req->bssid = NULL;
1847         conn_req->ies_len = 0;
1848         kfree(conn_req->ies);
1849         conn_req->ies = NULL;
1850
1851 out:
1852
1853         complete(&hif_drv->comp_test_disconn_block);
1854 }
1855
1856 void wilc_resolve_disconnect_aberration(struct wilc_vif *vif)
1857 {
1858         if (!vif->hif_drv)
1859                 return;
1860         if (vif->hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP ||
1861             vif->hif_drv->hif_state == HOST_IF_CONNECTING)
1862                 wilc_disconnect(vif, 1);
1863 }
1864
1865 static void handle_get_rssi(struct wilc_vif *vif)
1866 {
1867         s32 result = 0;
1868         struct wid wid;
1869
1870         wid.id = (u16)WID_RSSI;
1871         wid.type = WID_CHAR;
1872         wid.val = &rssi;
1873         wid.size = sizeof(char);
1874
1875         result = wilc_send_config_pkt(vif, GET_CFG, &wid, 1,
1876                                       wilc_get_vif_idx(vif));
1877         if (result) {
1878                 netdev_err(vif->ndev, "Failed to get RSSI value\n");
1879                 result = -EFAULT;
1880         }
1881
1882         complete(&vif->hif_drv->comp_get_rssi);
1883 }
1884
1885 static s32 handle_get_statistics(struct wilc_vif *vif,
1886                                  struct rf_info *stats)
1887 {
1888         struct wid wid_list[5];
1889         u32 wid_cnt = 0, result = 0;
1890
1891         wid_list[wid_cnt].id = WID_LINKSPEED;
1892         wid_list[wid_cnt].type = WID_CHAR;
1893         wid_list[wid_cnt].size = sizeof(char);
1894         wid_list[wid_cnt].val = (s8 *)&stats->link_speed;
1895         wid_cnt++;
1896
1897         wid_list[wid_cnt].id = WID_RSSI;
1898         wid_list[wid_cnt].type = WID_CHAR;
1899         wid_list[wid_cnt].size = sizeof(char);
1900         wid_list[wid_cnt].val = (s8 *)&stats->rssi;
1901         wid_cnt++;
1902
1903         wid_list[wid_cnt].id = WID_SUCCESS_FRAME_COUNT;
1904         wid_list[wid_cnt].type = WID_INT;
1905         wid_list[wid_cnt].size = sizeof(u32);
1906         wid_list[wid_cnt].val = (s8 *)&stats->tx_cnt;
1907         wid_cnt++;
1908
1909         wid_list[wid_cnt].id = WID_RECEIVED_FRAGMENT_COUNT;
1910         wid_list[wid_cnt].type = WID_INT;
1911         wid_list[wid_cnt].size = sizeof(u32);
1912         wid_list[wid_cnt].val = (s8 *)&stats->rx_cnt;
1913         wid_cnt++;
1914
1915         wid_list[wid_cnt].id = WID_FAILED_COUNT;
1916         wid_list[wid_cnt].type = WID_INT;
1917         wid_list[wid_cnt].size = sizeof(u32);
1918         wid_list[wid_cnt].val = (s8 *)&stats->tx_fail_cnt;
1919         wid_cnt++;
1920
1921         result = wilc_send_config_pkt(vif, GET_CFG, wid_list,
1922                                       wid_cnt,
1923                                       wilc_get_vif_idx(vif));
1924
1925         if (result)
1926                 netdev_err(vif->ndev, "Failed to send scan parameters\n");
1927
1928         if (stats->link_speed > TCP_ACK_FILTER_LINK_SPEED_THRESH &&
1929             stats->link_speed != DEFAULT_LINK_SPEED)
1930                 wilc_enable_tcp_ack_filter(true);
1931         else if (stats->link_speed != DEFAULT_LINK_SPEED)
1932                 wilc_enable_tcp_ack_filter(false);
1933
1934         if (stats != &vif->wilc->dummy_statistics)
1935                 complete(&hif_wait_response);
1936         return 0;
1937 }
1938
1939 static s32 handle_get_inactive_time(struct wilc_vif *vif,
1940                                     struct sta_inactive_t *hif_sta_inactive)
1941 {
1942         s32 result = 0;
1943         struct wid wid;
1944         struct host_if_drv *hif_drv = vif->hif_drv;
1945
1946         wid.id = (u16)WID_SET_STA_MAC_INACTIVE_TIME;
1947         wid.type = WID_STR;
1948         wid.size = ETH_ALEN;
1949         wid.val = kmalloc(wid.size, GFP_KERNEL);
1950         if (!wid.val)
1951                 return -ENOMEM;
1952
1953         ether_addr_copy(wid.val, hif_sta_inactive->mac);
1954
1955         result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1,
1956                                       wilc_get_vif_idx(vif));
1957         kfree(wid.val);
1958
1959         if (result) {
1960                 netdev_err(vif->ndev, "Failed to SET inactive time\n");
1961                 return -EFAULT;
1962         }
1963
1964         wid.id = (u16)WID_GET_INACTIVE_TIME;
1965         wid.type = WID_INT;
1966         wid.val = (s8 *)&inactive_time;
1967         wid.size = sizeof(u32);
1968
1969         result = wilc_send_config_pkt(vif, GET_CFG, &wid, 1,
1970                                       wilc_get_vif_idx(vif));
1971
1972         if (result) {
1973                 netdev_err(vif->ndev, "Failed to get inactive time\n");
1974                 return -EFAULT;
1975         }
1976
1977         complete(&hif_drv->comp_inactive_time);
1978
1979         return result;
1980 }
1981
1982 static void handle_add_beacon(struct wilc_vif *vif, struct beacon_attr *param)
1983 {
1984         s32 result = 0;
1985         struct wid wid;
1986         u8 *cur_byte;
1987
1988         wid.id = (u16)WID_ADD_BEACON;
1989         wid.type = WID_BIN;
1990         wid.size = param->head_len + param->tail_len + 16;
1991         wid.val = kmalloc(wid.size, GFP_KERNEL);
1992         if (!wid.val)
1993                 goto error;
1994
1995         cur_byte = wid.val;
1996         *cur_byte++ = (param->interval & 0xFF);
1997         *cur_byte++ = ((param->interval >> 8) & 0xFF);
1998         *cur_byte++ = ((param->interval >> 16) & 0xFF);
1999         *cur_byte++ = ((param->interval >> 24) & 0xFF);
2000
2001         *cur_byte++ = (param->dtim_period & 0xFF);
2002         *cur_byte++ = ((param->dtim_period >> 8) & 0xFF);
2003         *cur_byte++ = ((param->dtim_period >> 16) & 0xFF);
2004         *cur_byte++ = ((param->dtim_period >> 24) & 0xFF);
2005
2006         *cur_byte++ = (param->head_len & 0xFF);
2007         *cur_byte++ = ((param->head_len >> 8) & 0xFF);
2008         *cur_byte++ = ((param->head_len >> 16) & 0xFF);
2009         *cur_byte++ = ((param->head_len >> 24) & 0xFF);
2010
2011         memcpy(cur_byte, param->head, param->head_len);
2012         cur_byte += param->head_len;
2013
2014         *cur_byte++ = (param->tail_len & 0xFF);
2015         *cur_byte++ = ((param->tail_len >> 8) & 0xFF);
2016         *cur_byte++ = ((param->tail_len >> 16) & 0xFF);
2017         *cur_byte++ = ((param->tail_len >> 24) & 0xFF);
2018
2019         if (param->tail)
2020                 memcpy(cur_byte, param->tail, param->tail_len);
2021         cur_byte += param->tail_len;
2022
2023         result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1,
2024                                       wilc_get_vif_idx(vif));
2025         if (result)
2026                 netdev_err(vif->ndev, "Failed to send add beacon\n");
2027
2028 error:
2029         kfree(wid.val);
2030         kfree(param->head);
2031         kfree(param->tail);
2032 }
2033
2034 static void handle_del_beacon(struct wilc_vif *vif)
2035 {
2036         s32 result = 0;
2037         struct wid wid;
2038         u8 *cur_byte;
2039
2040         wid.id = (u16)WID_DEL_BEACON;
2041         wid.type = WID_CHAR;
2042         wid.size = sizeof(char);
2043         wid.val = &del_beacon;
2044
2045         if (!wid.val)
2046                 return;
2047
2048         cur_byte = wid.val;
2049
2050         result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1,
2051                                       wilc_get_vif_idx(vif));
2052         if (result)
2053                 netdev_err(vif->ndev, "Failed to send delete beacon\n");
2054 }
2055
2056 static u32 wilc_hif_pack_sta_param(u8 *buff, struct add_sta_param *param)
2057 {
2058         u8 *cur_byte;
2059
2060         cur_byte = buff;
2061
2062         memcpy(cur_byte, param->bssid, ETH_ALEN);
2063         cur_byte +=  ETH_ALEN;
2064
2065         *cur_byte++ = param->aid & 0xFF;
2066         *cur_byte++ = (param->aid >> 8) & 0xFF;
2067
2068         *cur_byte++ = param->rates_len;
2069         if (param->rates_len > 0)
2070                 memcpy(cur_byte, param->rates, param->rates_len);
2071         cur_byte += param->rates_len;
2072
2073         *cur_byte++ = param->ht_supported;
2074         memcpy(cur_byte, &param->ht_capa, sizeof(struct ieee80211_ht_cap));
2075         cur_byte += sizeof(struct ieee80211_ht_cap);
2076
2077         *cur_byte++ = param->flags_mask & 0xFF;
2078         *cur_byte++ = (param->flags_mask >> 8) & 0xFF;
2079
2080         *cur_byte++ = param->flags_set & 0xFF;
2081         *cur_byte++ = (param->flags_set >> 8) & 0xFF;
2082
2083         return cur_byte - buff;
2084 }
2085
2086 static void handle_add_station(struct wilc_vif *vif,
2087                                struct add_sta_param *param)
2088 {
2089         s32 result = 0;
2090         struct wid wid;
2091         u8 *cur_byte;
2092
2093         wid.id = (u16)WID_ADD_STA;
2094         wid.type = WID_BIN;
2095         wid.size = WILC_ADD_STA_LENGTH + param->rates_len;
2096
2097         wid.val = kmalloc(wid.size, GFP_KERNEL);
2098         if (!wid.val)
2099                 goto error;
2100
2101         cur_byte = wid.val;
2102         cur_byte += wilc_hif_pack_sta_param(cur_byte, param);
2103
2104         result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1,
2105                                       wilc_get_vif_idx(vif));
2106         if (result != 0)
2107                 netdev_err(vif->ndev, "Failed to send add station\n");
2108
2109 error:
2110         kfree(param->rates);
2111         kfree(wid.val);
2112 }
2113
2114 static void handle_del_all_sta(struct wilc_vif *vif,
2115                                struct del_all_sta *param)
2116 {
2117         s32 result = 0;
2118         struct wid wid;
2119         u8 *curr_byte;
2120         u8 i;
2121         u8 zero_buff[6] = {0};
2122
2123         wid.id = (u16)WID_DEL_ALL_STA;
2124         wid.type = WID_STR;
2125         wid.size = (param->assoc_sta * ETH_ALEN) + 1;
2126
2127         wid.val = kmalloc((param->assoc_sta * ETH_ALEN) + 1, GFP_KERNEL);
2128         if (!wid.val)
2129                 goto error;
2130
2131         curr_byte = wid.val;
2132
2133         *(curr_byte++) = param->assoc_sta;
2134
2135         for (i = 0; i < MAX_NUM_STA; i++) {
2136                 if (memcmp(param->del_all_sta[i], zero_buff, ETH_ALEN))
2137                         memcpy(curr_byte, param->del_all_sta[i], ETH_ALEN);
2138                 else
2139                         continue;
2140
2141                 curr_byte += ETH_ALEN;
2142         }
2143
2144         result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1,
2145                                       wilc_get_vif_idx(vif));
2146         if (result)
2147                 netdev_err(vif->ndev, "Failed to send add station\n");
2148
2149 error:
2150         kfree(wid.val);
2151
2152         complete(&hif_wait_response);
2153 }
2154
2155 static void handle_del_station(struct wilc_vif *vif, struct del_sta *param)
2156 {
2157         s32 result = 0;
2158         struct wid wid;
2159         u8 *cur_byte;
2160
2161         wid.id = (u16)WID_REMOVE_STA;
2162         wid.type = WID_BIN;
2163         wid.size = ETH_ALEN;
2164
2165         wid.val = kmalloc(wid.size, GFP_KERNEL);
2166         if (!wid.val)
2167                 goto error;
2168
2169         cur_byte = wid.val;
2170
2171         ether_addr_copy(cur_byte, param->mac_addr);
2172
2173         result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1,
2174                                       wilc_get_vif_idx(vif));
2175         if (result)
2176                 netdev_err(vif->ndev, "Failed to send add station\n");
2177
2178 error:
2179         kfree(wid.val);
2180 }
2181
2182 static void handle_edit_station(struct wilc_vif *vif,
2183                                 struct add_sta_param *param)
2184 {
2185         s32 result = 0;
2186         struct wid wid;
2187         u8 *cur_byte;
2188
2189         wid.id = (u16)WID_EDIT_STA;
2190         wid.type = WID_BIN;
2191         wid.size = WILC_ADD_STA_LENGTH + param->rates_len;
2192
2193         wid.val = kmalloc(wid.size, GFP_KERNEL);
2194         if (!wid.val)
2195                 goto error;
2196
2197         cur_byte = wid.val;
2198         cur_byte += wilc_hif_pack_sta_param(cur_byte, param);
2199
2200         result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1,
2201                                       wilc_get_vif_idx(vif));
2202         if (result)
2203                 netdev_err(vif->ndev, "Failed to send edit station\n");
2204
2205 error:
2206         kfree(param->rates);
2207         kfree(wid.val);
2208 }
2209
2210 static int handle_remain_on_chan(struct wilc_vif *vif,
2211                                  struct remain_ch *hif_remain_ch)
2212 {
2213         s32 result = 0;
2214         u8 remain_on_chan_flag;
2215         struct wid wid;
2216         struct host_if_drv *hif_drv = vif->hif_drv;
2217
2218         if (!hif_drv->remain_on_ch_pending) {
2219                 hif_drv->remain_on_ch.arg = hif_remain_ch->arg;
2220                 hif_drv->remain_on_ch.expired = hif_remain_ch->expired;
2221                 hif_drv->remain_on_ch.ready = hif_remain_ch->ready;
2222                 hif_drv->remain_on_ch.ch = hif_remain_ch->ch;
2223                 hif_drv->remain_on_ch.id = hif_remain_ch->id;
2224         } else {
2225                 hif_remain_ch->ch = hif_drv->remain_on_ch.ch;
2226         }
2227
2228         if (hif_drv->usr_scan_req.scan_result) {
2229                 hif_drv->remain_on_ch_pending = 1;
2230                 result = -EBUSY;
2231                 goto error;
2232         }
2233         if (hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP) {
2234                 result = -EBUSY;
2235                 goto error;
2236         }
2237
2238         if (wilc_optaining_ip || wilc_connecting) {
2239                 result = -EBUSY;
2240                 goto error;
2241         }
2242
2243         remain_on_chan_flag = true;
2244         wid.id = (u16)WID_REMAIN_ON_CHAN;
2245         wid.type = WID_STR;
2246         wid.size = 2;
2247         wid.val = kmalloc(wid.size, GFP_KERNEL);
2248         if (!wid.val) {
2249                 result = -ENOMEM;
2250                 goto error;
2251         }
2252
2253         wid.val[0] = remain_on_chan_flag;
2254         wid.val[1] = (s8)hif_remain_ch->ch;
2255
2256         result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1,
2257                                       wilc_get_vif_idx(vif));
2258         kfree(wid.val);
2259         if (result != 0)
2260                 netdev_err(vif->ndev, "Failed to set remain on channel\n");
2261
2262 error:
2263         {
2264                 P2P_LISTEN_STATE = 1;
2265                 hif_drv->remain_on_ch_timer_vif = vif;
2266                 mod_timer(&hif_drv->remain_on_ch_timer,
2267                           jiffies +
2268                           msecs_to_jiffies(hif_remain_ch->duration));
2269
2270                 if (hif_drv->remain_on_ch.ready)
2271                         hif_drv->remain_on_ch.ready(hif_drv->remain_on_ch.arg);
2272
2273                 if (hif_drv->remain_on_ch_pending)
2274                         hif_drv->remain_on_ch_pending = 0;
2275         }
2276
2277         return result;
2278 }
2279
2280 static int handle_register_frame(struct wilc_vif *vif,
2281                                  struct reg_frame *hif_reg_frame)
2282 {
2283         s32 result = 0;
2284         struct wid wid;
2285         u8 *cur_byte;
2286
2287         wid.id = (u16)WID_REGISTER_FRAME;
2288         wid.type = WID_STR;
2289         wid.val = kmalloc(sizeof(u16) + 2, GFP_KERNEL);
2290         if (!wid.val)
2291                 return -ENOMEM;
2292
2293         cur_byte = wid.val;
2294
2295         *cur_byte++ = hif_reg_frame->reg;
2296         *cur_byte++ = hif_reg_frame->reg_id;
2297         memcpy(cur_byte, &hif_reg_frame->frame_type, sizeof(u16));
2298
2299         wid.size = sizeof(u16) + 2;
2300
2301         result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1,
2302                                       wilc_get_vif_idx(vif));
2303         kfree(wid.val);
2304         if (result) {
2305                 netdev_err(vif->ndev, "Failed to frame register\n");
2306                 result = -EINVAL;
2307         }
2308
2309         return result;
2310 }
2311
2312 static u32 handle_listen_state_expired(struct wilc_vif *vif,
2313                                        struct remain_ch *hif_remain_ch)
2314 {
2315         u8 remain_on_chan_flag;
2316         struct wid wid;
2317         s32 result = 0;
2318         struct host_if_drv *hif_drv = vif->hif_drv;
2319
2320         if (P2P_LISTEN_STATE) {
2321                 remain_on_chan_flag = false;
2322                 wid.id = (u16)WID_REMAIN_ON_CHAN;
2323                 wid.type = WID_STR;
2324                 wid.size = 2;
2325                 wid.val = kmalloc(wid.size, GFP_KERNEL);
2326
2327                 if (!wid.val)
2328                         return -ENOMEM;
2329
2330                 wid.val[0] = remain_on_chan_flag;
2331                 wid.val[1] = FALSE_FRMWR_CHANNEL;
2332
2333                 result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1,
2334                                               wilc_get_vif_idx(vif));
2335                 kfree(wid.val);
2336                 if (result != 0) {
2337                         netdev_err(vif->ndev, "Failed to set remain channel\n");
2338                         goto _done_;
2339                 }
2340
2341                 if (hif_drv->remain_on_ch.expired) {
2342                         hif_drv->remain_on_ch.expired(hif_drv->remain_on_ch.arg,
2343                                                       hif_remain_ch->id);
2344                 }
2345                 P2P_LISTEN_STATE = 0;
2346         } else {
2347                 netdev_dbg(vif->ndev, "Not in listen state\n");
2348                 result = -EFAULT;
2349         }
2350
2351 _done_:
2352         return result;
2353 }
2354
2355 static void listen_timer_cb(struct timer_list *t)
2356 {
2357         struct host_if_drv *hif_drv = from_timer(hif_drv, t,
2358                                                       remain_on_ch_timer);
2359         struct wilc_vif *vif = hif_drv->remain_on_ch_timer_vif;
2360         s32 result = 0;
2361         struct host_if_msg msg;
2362
2363         del_timer(&vif->hif_drv->remain_on_ch_timer);
2364
2365         memset(&msg, 0, sizeof(struct host_if_msg));
2366         msg.id = HOST_IF_MSG_LISTEN_TIMER_FIRED;
2367         msg.vif = vif;
2368         msg.body.remain_on_ch.id = vif->hif_drv->remain_on_ch.id;
2369
2370         result = wilc_enqueue_cmd(&msg);
2371         if (result)
2372                 netdev_err(vif->ndev, "wilc_mq_send fail\n");
2373 }
2374
2375 static void handle_power_management(struct wilc_vif *vif,
2376                                     struct power_mgmt_param *pm_param)
2377 {
2378         s32 result = 0;
2379         struct wid wid;
2380         s8 power_mode;
2381
2382         wid.id = (u16)WID_POWER_MANAGEMENT;
2383
2384         if (pm_param->enabled)
2385                 power_mode = MIN_FAST_PS;
2386         else
2387                 power_mode = NO_POWERSAVE;
2388
2389         wid.val = &power_mode;
2390         wid.size = sizeof(char);
2391
2392         result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1,
2393                                       wilc_get_vif_idx(vif));
2394         if (result)
2395                 netdev_err(vif->ndev, "Failed to send power management\n");
2396 }
2397
2398 static void handle_set_mcast_filter(struct wilc_vif *vif,
2399                                     struct set_multicast *hif_set_mc)
2400 {
2401         s32 result = 0;
2402         struct wid wid;
2403         u8 *cur_byte;
2404
2405         wid.id = (u16)WID_SETUP_MULTICAST_FILTER;
2406         wid.type = WID_BIN;
2407         wid.size = sizeof(struct set_multicast) + (hif_set_mc->cnt * ETH_ALEN);
2408         wid.val = kmalloc(wid.size, GFP_KERNEL);
2409         if (!wid.val)
2410                 goto error;
2411
2412         cur_byte = wid.val;
2413         *cur_byte++ = (hif_set_mc->enabled & 0xFF);
2414         *cur_byte++ = 0;
2415         *cur_byte++ = 0;
2416         *cur_byte++ = 0;
2417
2418         *cur_byte++ = (hif_set_mc->cnt & 0xFF);
2419         *cur_byte++ = ((hif_set_mc->cnt >> 8) & 0xFF);
2420         *cur_byte++ = ((hif_set_mc->cnt >> 16) & 0xFF);
2421         *cur_byte++ = ((hif_set_mc->cnt >> 24) & 0xFF);
2422
2423         if (hif_set_mc->cnt > 0)
2424                 memcpy(cur_byte, wilc_multicast_mac_addr_list,
2425                        ((hif_set_mc->cnt) * ETH_ALEN));
2426
2427         result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1,
2428                                       wilc_get_vif_idx(vif));
2429         if (result)
2430                 netdev_err(vif->ndev, "Failed to send setup multicast\n");
2431
2432 error:
2433         kfree(wid.val);
2434 }
2435
2436 static void handle_set_tx_pwr(struct wilc_vif *vif, u8 tx_pwr)
2437 {
2438         int ret;
2439         struct wid wid;
2440
2441         wid.id = (u16)WID_TX_POWER;
2442         wid.type = WID_CHAR;
2443         wid.val = &tx_pwr;
2444         wid.size = sizeof(char);
2445
2446         ret = wilc_send_config_pkt(vif, SET_CFG, &wid, 1,
2447                                    wilc_get_vif_idx(vif));
2448         if (ret)
2449                 netdev_err(vif->ndev, "Failed to set TX PWR\n");
2450 }
2451
2452 static void handle_get_tx_pwr(struct wilc_vif *vif, u8 *tx_pwr)
2453 {
2454         int ret = 0;
2455         struct wid wid;
2456
2457         wid.id = (u16)WID_TX_POWER;
2458         wid.type = WID_CHAR;
2459         wid.val = (s8 *)tx_pwr;
2460         wid.size = sizeof(char);
2461
2462         ret = wilc_send_config_pkt(vif, GET_CFG, &wid, 1,
2463                                    wilc_get_vif_idx(vif));
2464         if (ret)
2465                 netdev_err(vif->ndev, "Failed to get TX PWR\n");
2466
2467         complete(&hif_wait_response);
2468 }
2469
2470 static void host_if_work(struct work_struct *work)
2471 {
2472         struct host_if_msg *msg;
2473         struct wilc *wilc;
2474         int ret = 0;
2475
2476         msg = container_of(work, struct host_if_msg, work);
2477         wilc = msg->vif->wilc;
2478
2479         if (msg->id == HOST_IF_MSG_CONNECT &&
2480             msg->vif->hif_drv->usr_scan_req.scan_result) {
2481                 wilc_enqueue_cmd(msg);
2482                 usleep_range(2 * 1000, 2 * 1000);
2483                 goto free_msg;
2484         }
2485         switch (msg->id) {
2486         case HOST_IF_MSG_SCAN:
2487                 handle_scan(msg->vif, &msg->body.scan_info);
2488                 break;
2489
2490         case HOST_IF_MSG_CONNECT:
2491                 handle_connect(msg->vif, &msg->body.con_info);
2492                 break;
2493
2494         case HOST_IF_MSG_RCVD_NTWRK_INFO:
2495                 handle_rcvd_ntwrk_info(msg->vif, &msg->body.net_info);
2496                 break;
2497
2498         case HOST_IF_MSG_RCVD_GNRL_ASYNC_INFO:
2499                 handle_rcvd_gnrl_async_info(msg->vif,
2500                                             &msg->body.async_info);
2501                 break;
2502
2503         case HOST_IF_MSG_KEY:
2504                 handle_key(msg->vif, &msg->body.key_info);
2505                 break;
2506
2507         case HOST_IF_MSG_CFG_PARAMS:
2508                 handle_cfg_param(msg->vif, &msg->body.cfg_info);
2509                 break;
2510
2511         case HOST_IF_MSG_SET_CHANNEL:
2512                 handle_set_channel(msg->vif, &msg->body.channel_info);
2513                 break;
2514
2515         case HOST_IF_MSG_DISCONNECT:
2516                 handle_disconnect(msg->vif);
2517                 break;
2518
2519         case HOST_IF_MSG_RCVD_SCAN_COMPLETE:
2520                 del_timer(&msg->vif->hif_drv->scan_timer);
2521
2522                 if (!wilc_wlan_get_num_conn_ifcs(wilc))
2523                         wilc_chip_sleep_manually(wilc);
2524
2525                 handle_scan_done(msg->vif, SCAN_EVENT_DONE);
2526
2527                 if (msg->vif->hif_drv->remain_on_ch_pending)
2528                         handle_remain_on_chan(msg->vif,
2529                                               &msg->body.remain_on_ch);
2530
2531                 break;
2532
2533         case HOST_IF_MSG_GET_RSSI:
2534                 handle_get_rssi(msg->vif);
2535                 break;
2536
2537         case HOST_IF_MSG_GET_STATISTICS:
2538                 handle_get_statistics(msg->vif,
2539                                       (struct rf_info *)msg->body.data);
2540                 break;
2541
2542         case HOST_IF_MSG_ADD_BEACON:
2543                 handle_add_beacon(msg->vif, &msg->body.beacon_info);
2544                 break;
2545
2546         case HOST_IF_MSG_DEL_BEACON:
2547                 handle_del_beacon(msg->vif);
2548                 break;
2549
2550         case HOST_IF_MSG_ADD_STATION:
2551                 handle_add_station(msg->vif, &msg->body.add_sta_info);
2552                 break;
2553
2554         case HOST_IF_MSG_DEL_STATION:
2555                 handle_del_station(msg->vif, &msg->body.del_sta_info);
2556                 break;
2557
2558         case HOST_IF_MSG_EDIT_STATION:
2559                 handle_edit_station(msg->vif, &msg->body.edit_sta_info);
2560                 break;
2561
2562         case HOST_IF_MSG_GET_INACTIVETIME:
2563                 handle_get_inactive_time(msg->vif, &msg->body.mac_info);
2564                 break;
2565
2566         case HOST_IF_MSG_SCAN_TIMER_FIRED:
2567                 handle_scan_done(msg->vif, SCAN_EVENT_ABORTED);
2568                 break;
2569
2570         case HOST_IF_MSG_CONNECT_TIMER_FIRED:
2571                 handle_connect_timeout(msg->vif);
2572                 break;
2573
2574         case HOST_IF_MSG_POWER_MGMT:
2575                 handle_power_management(msg->vif,
2576                                         &msg->body.pwr_mgmt_info);
2577                 break;
2578
2579         case HOST_IF_MSG_SET_WFIDRV_HANDLER:
2580                 ret = handle_set_wfi_drv_handler(msg->vif, &msg->body.drv);
2581                 break;
2582
2583         case HOST_IF_MSG_SET_OPERATION_MODE:
2584                 handle_set_operation_mode(msg->vif, &msg->body.mode);
2585                 break;
2586
2587         case HOST_IF_MSG_SET_IPADDRESS:
2588                 handle_set_ip_address(msg->vif,
2589                                       msg->body.ip_info.ip_addr,
2590                                       msg->body.ip_info.idx);
2591                 break;
2592
2593         case HOST_IF_MSG_GET_IPADDRESS:
2594                 handle_get_ip_address(msg->vif, msg->body.ip_info.idx);
2595                 break;
2596
2597         case HOST_IF_MSG_GET_MAC_ADDRESS:
2598                 handle_get_mac_address(msg->vif,
2599                                        &msg->body.get_mac_info);
2600                 break;
2601
2602         case HOST_IF_MSG_REMAIN_ON_CHAN:
2603                 handle_remain_on_chan(msg->vif, &msg->body.remain_on_ch);
2604                 break;
2605
2606         case HOST_IF_MSG_REGISTER_FRAME:
2607                 handle_register_frame(msg->vif, &msg->body.reg_frame);
2608                 break;
2609
2610         case HOST_IF_MSG_LISTEN_TIMER_FIRED:
2611                 handle_listen_state_expired(msg->vif, &msg->body.remain_on_ch);
2612                 break;
2613
2614         case HOST_IF_MSG_SET_MULTICAST_FILTER:
2615                 handle_set_mcast_filter(msg->vif, &msg->body.multicast_info);
2616                 break;
2617
2618         case HOST_IF_MSG_DEL_ALL_STA:
2619                 handle_del_all_sta(msg->vif, &msg->body.del_all_sta_info);
2620                 break;
2621
2622         case HOST_IF_MSG_SET_TX_POWER:
2623                 handle_set_tx_pwr(msg->vif, msg->body.tx_power.tx_pwr);
2624                 break;
2625
2626         case HOST_IF_MSG_GET_TX_POWER:
2627                 handle_get_tx_pwr(msg->vif, &msg->body.tx_power.tx_pwr);
2628                 break;
2629         default:
2630                 netdev_err(msg->vif->ndev, "[Host Interface] undefined\n");
2631                 break;
2632         }
2633 free_msg:
2634         if (ret)
2635                 netdev_err(msg->vif->ndev, "Host cmd %d failed\n", msg->id);
2636         kfree(msg);
2637         complete(&hif_thread_comp);
2638 }
2639
2640 static void timer_scan_cb(struct timer_list *t)
2641 {
2642         struct host_if_drv *hif_drv = from_timer(hif_drv, t, scan_timer);
2643         struct wilc_vif *vif = hif_drv->scan_timer_vif;
2644         struct host_if_msg msg;
2645
2646         memset(&msg, 0, sizeof(struct host_if_msg));
2647         msg.vif = vif;
2648         msg.id = HOST_IF_MSG_SCAN_TIMER_FIRED;
2649
2650         wilc_enqueue_cmd(&msg);
2651 }
2652
2653 static void timer_connect_cb(struct timer_list *t)
2654 {
2655         struct host_if_drv *hif_drv = from_timer(hif_drv, t,
2656                                                       connect_timer);
2657         struct wilc_vif *vif = hif_drv->connect_timer_vif;
2658         struct host_if_msg msg;
2659
2660         memset(&msg, 0, sizeof(struct host_if_msg));
2661         msg.vif = vif;
2662         msg.id = HOST_IF_MSG_CONNECT_TIMER_FIRED;
2663
2664         wilc_enqueue_cmd(&msg);
2665 }
2666
2667 s32 wilc_remove_key(struct host_if_drv *hif_drv, const u8 *sta_addr)
2668 {
2669         struct wid wid;
2670
2671         wid.id = (u16)WID_REMOVE_KEY;
2672         wid.type = WID_STR;
2673         wid.val = (s8 *)sta_addr;
2674         wid.size = 6;
2675
2676         return 0;
2677 }
2678
2679 int wilc_remove_wep_key(struct wilc_vif *vif, u8 index)
2680 {
2681         int result = 0;
2682         struct host_if_msg msg;
2683         struct host_if_drv *hif_drv = vif->hif_drv;
2684
2685         if (!hif_drv) {
2686                 result = -EFAULT;
2687                 netdev_err(vif->ndev, "Failed to send setup multicast\n");
2688                 return result;
2689         }
2690
2691         memset(&msg, 0, sizeof(struct host_if_msg));
2692
2693         msg.id = HOST_IF_MSG_KEY;
2694         msg.body.key_info.type = WEP;
2695         msg.body.key_info.action = REMOVEKEY;
2696         msg.vif = vif;
2697         msg.body.key_info.attr.wep.index = index;
2698
2699         result = wilc_enqueue_cmd(&msg);
2700         if (result)
2701                 netdev_err(vif->ndev, "Request to remove WEP key\n");
2702         else
2703                 wait_for_completion(&hif_drv->comp_test_key_block);
2704
2705         return result;
2706 }
2707
2708 int wilc_set_wep_default_keyid(struct wilc_vif *vif, u8 index)
2709 {
2710         int result = 0;
2711         struct host_if_msg msg;
2712         struct host_if_drv *hif_drv = vif->hif_drv;
2713
2714         if (!hif_drv) {
2715                 result = -EFAULT;
2716                 netdev_err(vif->ndev, "driver is null\n");
2717                 return result;
2718         }
2719
2720         memset(&msg, 0, sizeof(struct host_if_msg));
2721
2722         msg.id = HOST_IF_MSG_KEY;
2723         msg.body.key_info.type = WEP;
2724         msg.body.key_info.action = DEFAULTKEY;
2725         msg.vif = vif;
2726         msg.body.key_info.attr.wep.index = index;
2727
2728         result = wilc_enqueue_cmd(&msg);
2729         if (result)
2730                 netdev_err(vif->ndev, "Default key index\n");
2731         else
2732                 wait_for_completion(&hif_drv->comp_test_key_block);
2733
2734         return result;
2735 }
2736
2737 int wilc_add_wep_key_bss_sta(struct wilc_vif *vif, const u8 *key, u8 len,
2738                              u8 index)
2739 {
2740         int result;
2741         struct host_if_msg msg;
2742         struct host_if_drv *hif_drv = vif->hif_drv;
2743
2744         if (!hif_drv) {
2745                 netdev_err(vif->ndev, "driver is null\n");
2746                 return -EFAULT;
2747         }
2748
2749         memset(&msg, 0, sizeof(struct host_if_msg));
2750
2751         msg.id = HOST_IF_MSG_KEY;
2752         msg.body.key_info.type = WEP;
2753         msg.body.key_info.action = ADDKEY;
2754         msg.vif = vif;
2755         msg.body.key_info.attr.wep.key = kmemdup(key, len, GFP_KERNEL);
2756         if (!msg.body.key_info.attr.wep.key)
2757                 return -ENOMEM;
2758
2759         msg.body.key_info.attr.wep.key_len = len;
2760         msg.body.key_info.attr.wep.index = index;
2761
2762         result = wilc_enqueue_cmd(&msg);
2763         if (result) {
2764                 netdev_err(vif->ndev, "STA - WEP Key\n");
2765                 kfree(msg.body.key_info.attr.wep.key);
2766                 return result;
2767         }
2768
2769         wait_for_completion(&hif_drv->comp_test_key_block);
2770         return 0;
2771 }
2772
2773 int wilc_add_wep_key_bss_ap(struct wilc_vif *vif, const u8 *key, u8 len,
2774                             u8 index, u8 mode, enum AUTHTYPE auth_type)
2775 {
2776         int result;
2777         struct host_if_msg msg;
2778         struct host_if_drv *hif_drv = vif->hif_drv;
2779
2780         if (!hif_drv) {
2781                 netdev_err(vif->ndev, "driver is null\n");
2782                 return -EFAULT;
2783         }
2784
2785         memset(&msg, 0, sizeof(struct host_if_msg));
2786
2787         msg.id = HOST_IF_MSG_KEY;
2788         msg.body.key_info.type = WEP;
2789         msg.body.key_info.action = ADDKEY_AP;
2790         msg.vif = vif;
2791         msg.body.key_info.attr.wep.key = kmemdup(key, len, GFP_KERNEL);
2792         if (!msg.body.key_info.attr.wep.key)
2793                 return -ENOMEM;
2794
2795         msg.body.key_info.attr.wep.key_len = len;
2796         msg.body.key_info.attr.wep.index = index;
2797         msg.body.key_info.attr.wep.mode = mode;
2798         msg.body.key_info.attr.wep.auth_type = auth_type;
2799
2800         result = wilc_enqueue_cmd(&msg);
2801         if (result) {
2802                 netdev_err(vif->ndev, "AP - WEP Key\n");
2803                 kfree(msg.body.key_info.attr.wep.key);
2804                 return result;
2805         }
2806
2807         wait_for_completion(&hif_drv->comp_test_key_block);
2808         return 0;
2809 }
2810
2811 int wilc_add_ptk(struct wilc_vif *vif, const u8 *ptk, u8 ptk_key_len,
2812                  const u8 *mac_addr, const u8 *rx_mic, const u8 *tx_mic,
2813                  u8 mode, u8 cipher_mode, u8 index)
2814 {
2815         int result;
2816         struct host_if_msg msg;
2817         struct host_if_drv *hif_drv = vif->hif_drv;
2818         u8 key_len = ptk_key_len;
2819
2820         if (!hif_drv) {
2821                 netdev_err(vif->ndev, "driver is null\n");
2822                 return -EFAULT;
2823         }
2824
2825         if (rx_mic)
2826                 key_len += RX_MIC_KEY_LEN;
2827
2828         if (tx_mic)
2829                 key_len += TX_MIC_KEY_LEN;
2830
2831         memset(&msg, 0, sizeof(struct host_if_msg));
2832
2833         msg.id = HOST_IF_MSG_KEY;
2834         msg.body.key_info.type = WPA_PTK;
2835         if (mode == AP_MODE) {
2836                 msg.body.key_info.action = ADDKEY_AP;
2837                 msg.body.key_info.attr.wpa.index = index;
2838         }
2839         if (mode == STATION_MODE)
2840                 msg.body.key_info.action = ADDKEY;
2841
2842         msg.body.key_info.attr.wpa.key = kmemdup(ptk, ptk_key_len, GFP_KERNEL);
2843         if (!msg.body.key_info.attr.wpa.key)
2844                 return -ENOMEM;
2845
2846         if (rx_mic)
2847                 memcpy(msg.body.key_info.attr.wpa.key + 16, rx_mic,
2848                        RX_MIC_KEY_LEN);
2849
2850         if (tx_mic)
2851                 memcpy(msg.body.key_info.attr.wpa.key + 24, tx_mic,
2852                        TX_MIC_KEY_LEN);
2853
2854         msg.body.key_info.attr.wpa.key_len = key_len;
2855         msg.body.key_info.attr.wpa.mac_addr = mac_addr;
2856         msg.body.key_info.attr.wpa.mode = cipher_mode;
2857         msg.vif = vif;
2858
2859         result = wilc_enqueue_cmd(&msg);
2860         if (result) {
2861                 netdev_err(vif->ndev, "PTK Key\n");
2862                 kfree(msg.body.key_info.attr.wpa.key);
2863                 return result;
2864         }
2865
2866         wait_for_completion(&hif_drv->comp_test_key_block);
2867         return 0;
2868 }
2869
2870 int wilc_add_rx_gtk(struct wilc_vif *vif, const u8 *rx_gtk, u8 gtk_key_len,
2871                     u8 index, u32 key_rsc_len, const u8 *key_rsc,
2872                     const u8 *rx_mic, const u8 *tx_mic, u8 mode,
2873                     u8 cipher_mode)
2874 {
2875         int result;
2876         struct host_if_msg msg;
2877         struct host_if_drv *hif_drv = vif->hif_drv;
2878         u8 key_len = gtk_key_len;
2879
2880         if (!hif_drv) {
2881                 netdev_err(vif->ndev, "driver is null\n");
2882                 return -EFAULT;
2883         }
2884         memset(&msg, 0, sizeof(struct host_if_msg));
2885
2886         if (rx_mic)
2887                 key_len += RX_MIC_KEY_LEN;
2888
2889         if (tx_mic)
2890                 key_len += TX_MIC_KEY_LEN;
2891
2892         if (key_rsc) {
2893                 msg.body.key_info.attr.wpa.seq = kmemdup(key_rsc,
2894                                                          key_rsc_len,
2895                                                          GFP_KERNEL);
2896                 if (!msg.body.key_info.attr.wpa.seq)
2897                         return -ENOMEM;
2898         }
2899
2900         msg.id = HOST_IF_MSG_KEY;
2901         msg.body.key_info.type = WPA_RX_GTK;
2902         msg.vif = vif;
2903
2904         if (mode == AP_MODE) {
2905                 msg.body.key_info.action = ADDKEY_AP;
2906                 msg.body.key_info.attr.wpa.mode = cipher_mode;
2907         }
2908         if (mode == STATION_MODE)
2909                 msg.body.key_info.action = ADDKEY;
2910
2911         msg.body.key_info.attr.wpa.key = kmemdup(rx_gtk,
2912                                                  key_len,
2913                                                  GFP_KERNEL);
2914         if (!msg.body.key_info.attr.wpa.key) {
2915                 kfree(msg.body.key_info.attr.wpa.seq);
2916                 return -ENOMEM;
2917         }
2918
2919         if (rx_mic)
2920                 memcpy(msg.body.key_info.attr.wpa.key + 16, rx_mic,
2921                        RX_MIC_KEY_LEN);
2922
2923         if (tx_mic)
2924                 memcpy(msg.body.key_info.attr.wpa.key + 24, tx_mic,
2925                        TX_MIC_KEY_LEN);
2926
2927         msg.body.key_info.attr.wpa.index = index;
2928         msg.body.key_info.attr.wpa.key_len = key_len;
2929         msg.body.key_info.attr.wpa.seq_len = key_rsc_len;
2930
2931         result = wilc_enqueue_cmd(&msg);
2932         if (result) {
2933                 netdev_err(vif->ndev, "RX GTK\n");
2934                 kfree(msg.body.key_info.attr.wpa.seq);
2935                 kfree(msg.body.key_info.attr.wpa.key);
2936                 return result;
2937         }
2938
2939         wait_for_completion(&hif_drv->comp_test_key_block);
2940         return 0;
2941 }
2942
2943 int wilc_set_pmkid_info(struct wilc_vif *vif,
2944                         struct host_if_pmkid_attr *pmkid)
2945 {
2946         int result = 0;
2947         struct host_if_msg msg;
2948         int i;
2949
2950         memset(&msg, 0, sizeof(struct host_if_msg));
2951
2952         msg.id = HOST_IF_MSG_KEY;
2953         msg.body.key_info.type = PMKSA;
2954         msg.body.key_info.action = ADDKEY;
2955         msg.vif = vif;
2956
2957         for (i = 0; i < pmkid->numpmkid; i++) {
2958                 memcpy(msg.body.key_info.attr.pmkid.pmkidlist[i].bssid,
2959                        &pmkid->pmkidlist[i].bssid, ETH_ALEN);
2960                 memcpy(msg.body.key_info.attr.pmkid.pmkidlist[i].pmkid,
2961                        &pmkid->pmkidlist[i].pmkid, PMKID_LEN);
2962         }
2963
2964         result = wilc_enqueue_cmd(&msg);
2965         if (result)
2966                 netdev_err(vif->ndev, "PMKID Info\n");
2967
2968         return result;
2969 }
2970
2971 int wilc_get_mac_address(struct wilc_vif *vif, u8 *mac_addr)
2972 {
2973         int result = 0;
2974         struct host_if_msg msg;
2975
2976         memset(&msg, 0, sizeof(struct host_if_msg));
2977
2978         msg.id = HOST_IF_MSG_GET_MAC_ADDRESS;
2979         msg.body.get_mac_info.mac_addr = mac_addr;
2980         msg.vif = vif;
2981
2982         result = wilc_enqueue_cmd(&msg);
2983         if (result) {
2984                 netdev_err(vif->ndev, "Failed to send get mac address\n");
2985                 return -EFAULT;
2986         }
2987
2988         wait_for_completion(&hif_wait_response);
2989         return result;
2990 }
2991
2992 int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ssid,
2993                       size_t ssid_len, const u8 *ies, size_t ies_len,
2994                       wilc_connect_result connect_result, void *user_arg,
2995                       u8 security, enum AUTHTYPE auth_type,
2996                       u8 channel, void *join_params)
2997 {
2998         int result = 0;
2999         struct host_if_msg msg;
3000         struct host_if_drv *hif_drv = vif->hif_drv;
3001
3002         if (!hif_drv || !connect_result) {
3003                 netdev_err(vif->ndev, "Driver is null\n");
3004                 return -EFAULT;
3005         }
3006
3007         if (!join_params) {
3008                 netdev_err(vif->ndev, "Unable to Join - JoinParams is NULL\n");
3009                 return -EFAULT;
3010         }
3011
3012         memset(&msg, 0, sizeof(struct host_if_msg));
3013
3014         msg.id = HOST_IF_MSG_CONNECT;
3015
3016         msg.body.con_info.security = security;
3017         msg.body.con_info.auth_type = auth_type;
3018         msg.body.con_info.ch = channel;
3019         msg.body.con_info.result = connect_result;
3020         msg.body.con_info.arg = user_arg;
3021         msg.body.con_info.params = join_params;
3022         msg.vif = vif;
3023
3024         if (bssid) {
3025                 msg.body.con_info.bssid = kmemdup(bssid, 6, GFP_KERNEL);
3026                 if (!msg.body.con_info.bssid)
3027                         return -ENOMEM;
3028         }
3029
3030         if (ssid) {
3031                 msg.body.con_info.ssid_len = ssid_len;
3032                 msg.body.con_info.ssid = kmemdup(ssid, ssid_len, GFP_KERNEL);
3033                 if (!msg.body.con_info.ssid)
3034                         return -ENOMEM;
3035         }
3036
3037         if (ies) {
3038                 msg.body.con_info.ies_len = ies_len;
3039                 msg.body.con_info.ies = kmemdup(ies, ies_len, GFP_KERNEL);
3040                 if (!msg.body.con_info.ies)
3041                         return -ENOMEM;
3042         }
3043         if (hif_drv->hif_state < HOST_IF_CONNECTING)
3044                 hif_drv->hif_state = HOST_IF_CONNECTING;
3045
3046         result = wilc_enqueue_cmd(&msg);
3047         if (result) {
3048                 netdev_err(vif->ndev, "send message: Set join request\n");
3049                 return -EFAULT;
3050         }
3051
3052         hif_drv->connect_timer_vif = vif;
3053         mod_timer(&hif_drv->connect_timer,
3054                   jiffies + msecs_to_jiffies(HOST_IF_CONNECT_TIMEOUT));
3055
3056         return result;
3057 }
3058
3059 int wilc_disconnect(struct wilc_vif *vif, u16 reason_code)
3060 {
3061         int result = 0;
3062         struct host_if_msg msg;
3063         struct host_if_drv *hif_drv = vif->hif_drv;
3064
3065         if (!hif_drv) {
3066                 netdev_err(vif->ndev, "Driver is null\n");
3067                 return -EFAULT;
3068         }
3069
3070         memset(&msg, 0, sizeof(struct host_if_msg));
3071
3072         msg.id = HOST_IF_MSG_DISCONNECT;
3073         msg.vif = vif;
3074
3075         result = wilc_enqueue_cmd(&msg);
3076         if (result)
3077                 netdev_err(vif->ndev, "Failed to send message: disconnect\n");
3078         else
3079                 wait_for_completion(&hif_drv->comp_test_disconn_block);
3080
3081         return result;
3082 }
3083
3084 static s32 host_int_get_assoc_res_info(struct wilc_vif *vif,
3085                                        u8 *assoc_resp_info,
3086                                        u32 max_assoc_resp_info_len,
3087                                        u32 *rcvd_assoc_resp_info_len)
3088 {
3089         s32 result = 0;
3090         struct wid wid;
3091
3092         wid.id = (u16)WID_ASSOC_RES_INFO;
3093         wid.type = WID_STR;
3094         wid.val = assoc_resp_info;
3095         wid.size = max_assoc_resp_info_len;
3096
3097         result = wilc_send_config_pkt(vif, GET_CFG, &wid, 1,
3098                                       wilc_get_vif_idx(vif));
3099         if (result) {
3100                 *rcvd_assoc_resp_info_len = 0;
3101                 netdev_err(vif->ndev, "Failed to send association response\n");
3102                 return -EINVAL;
3103         }
3104
3105         *rcvd_assoc_resp_info_len = wid.size;
3106         return result;
3107 }
3108
3109 int wilc_set_mac_chnl_num(struct wilc_vif *vif, u8 channel)
3110 {
3111         int result;
3112         struct host_if_msg msg;
3113
3114         memset(&msg, 0, sizeof(struct host_if_msg));
3115         msg.id = HOST_IF_MSG_SET_CHANNEL;
3116         msg.body.channel_info.set_ch = channel;
3117         msg.vif = vif;
3118
3119         result = wilc_enqueue_cmd(&msg);
3120         if (result) {
3121                 netdev_err(vif->ndev, "wilc mq send fail\n");
3122                 return -EINVAL;
3123         }
3124
3125         return 0;
3126 }
3127
3128 int wilc_set_wfi_drv_handler(struct wilc_vif *vif, int index, u8 mode,
3129                              u8 ifc_id)
3130 {
3131         int result = 0;
3132         struct host_if_msg msg;
3133
3134         memset(&msg, 0, sizeof(struct host_if_msg));
3135         msg.id = HOST_IF_MSG_SET_WFIDRV_HANDLER;
3136         msg.body.drv.handler = index;
3137         msg.body.drv.mode = mode;
3138         msg.body.drv.name = ifc_id;
3139         msg.vif = vif;
3140
3141         result = wilc_enqueue_cmd(&msg);
3142         if (result) {
3143                 netdev_err(vif->ndev, "wilc mq send fail\n");
3144                 result = -EINVAL;
3145         }
3146
3147         return result;
3148 }
3149
3150 int wilc_set_operation_mode(struct wilc_vif *vif, u32 mode)
3151 {
3152         int result = 0;
3153         struct host_if_msg msg;
3154
3155         memset(&msg, 0, sizeof(struct host_if_msg));
3156         msg.id = HOST_IF_MSG_SET_OPERATION_MODE;
3157         msg.body.mode.mode = mode;
3158         msg.vif = vif;
3159
3160         result = wilc_enqueue_cmd(&msg);
3161         if (result) {
3162                 netdev_err(vif->ndev, "wilc mq send fail\n");
3163                 result = -EINVAL;
3164         }
3165
3166         return result;
3167 }
3168
3169 s32 wilc_get_inactive_time(struct wilc_vif *vif, const u8 *mac,
3170                            u32 *out_val)
3171 {
3172         s32 result = 0;
3173         struct host_if_msg msg;
3174         struct host_if_drv *hif_drv = vif->hif_drv;
3175
3176         if (!hif_drv) {
3177                 netdev_err(vif->ndev, "driver is null\n");
3178                 return -EFAULT;
3179         }
3180
3181         memset(&msg, 0, sizeof(struct host_if_msg));
3182         memcpy(msg.body.mac_info.mac, mac, ETH_ALEN);
3183
3184         msg.id = HOST_IF_MSG_GET_INACTIVETIME;
3185         msg.vif = vif;
3186
3187         result = wilc_enqueue_cmd(&msg);
3188         if (result)
3189                 netdev_err(vif->ndev, "Failed to send get host ch param\n");
3190         else
3191                 wait_for_completion(&hif_drv->comp_inactive_time);
3192
3193         *out_val = inactive_time;
3194
3195         return result;
3196 }
3197
3198 int wilc_get_rssi(struct wilc_vif *vif, s8 *rssi_level)
3199 {
3200         int result = 0;
3201         struct host_if_msg msg;
3202         struct host_if_drv *hif_drv = vif->hif_drv;
3203
3204         memset(&msg, 0, sizeof(struct host_if_msg));
3205         msg.id = HOST_IF_MSG_GET_RSSI;
3206         msg.vif = vif;
3207
3208         result = wilc_enqueue_cmd(&msg);
3209         if (result) {
3210                 netdev_err(vif->ndev, "Failed to send get host ch param\n");
3211                 return -EFAULT;
3212         }
3213
3214         wait_for_completion(&hif_drv->comp_get_rssi);
3215
3216         if (!rssi_level) {
3217                 netdev_err(vif->ndev, "RSS pointer value is null\n");
3218                 return -EFAULT;
3219         }
3220
3221         *rssi_level = rssi;
3222
3223         return result;
3224 }
3225
3226 int wilc_get_statistics(struct wilc_vif *vif, struct rf_info *stats)
3227 {
3228         int result = 0;
3229         struct host_if_msg msg;
3230
3231         memset(&msg, 0, sizeof(struct host_if_msg));
3232         msg.id = HOST_IF_MSG_GET_STATISTICS;
3233         msg.body.data = (char *)stats;
3234         msg.vif = vif;
3235
3236         result = wilc_enqueue_cmd(&msg);
3237         if (result) {
3238                 netdev_err(vif->ndev, "Failed to send get host channel\n");
3239                 return -EFAULT;
3240         }
3241
3242         if (stats != &vif->wilc->dummy_statistics)
3243                 wait_for_completion(&hif_wait_response);
3244         return result;
3245 }
3246
3247 int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type,
3248               u8 *ch_freq_list, u8 ch_list_len, const u8 *ies,
3249               size_t ies_len, wilc_scan_result scan_result, void *user_arg,
3250               struct hidden_network *hidden_network)
3251 {
3252         int result = 0;
3253         struct host_if_msg msg;
3254         struct scan_attr *scan_info = &msg.body.scan_info;
3255         struct host_if_drv *hif_drv = vif->hif_drv;
3256
3257         if (!hif_drv || !scan_result) {
3258                 netdev_err(vif->ndev, "hif_drv or scan_result = NULL\n");
3259                 return -EFAULT;
3260         }
3261
3262         memset(&msg, 0, sizeof(struct host_if_msg));
3263
3264         msg.id = HOST_IF_MSG_SCAN;
3265
3266         if (hidden_network) {
3267                 scan_info->hidden_network.net_info = hidden_network->net_info;
3268                 scan_info->hidden_network.n_ssids = hidden_network->n_ssids;
3269         }
3270
3271         msg.vif = vif;
3272         scan_info->src = scan_source;
3273         scan_info->type = scan_type;
3274         scan_info->result = scan_result;
3275         scan_info->arg = user_arg;
3276
3277         scan_info->ch_list_len = ch_list_len;
3278         scan_info->ch_freq_list = kmemdup(ch_freq_list,
3279                                           ch_list_len,
3280                                           GFP_KERNEL);
3281         if (!scan_info->ch_freq_list)
3282                 return -ENOMEM;
3283
3284         scan_info->ies_len = ies_len;
3285         scan_info->ies = kmemdup(ies, ies_len, GFP_KERNEL);
3286         if (!scan_info->ies)
3287                 return -ENOMEM;
3288
3289         result = wilc_enqueue_cmd(&msg);
3290         if (result) {
3291                 netdev_err(vif->ndev, "Error in sending message queue\n");
3292                 return -EINVAL;
3293         }
3294
3295         hif_drv->scan_timer_vif = vif;
3296         mod_timer(&hif_drv->scan_timer,
3297                   jiffies + msecs_to_jiffies(HOST_IF_SCAN_TIMEOUT));
3298
3299         return result;
3300 }
3301
3302 int wilc_hif_set_cfg(struct wilc_vif *vif,
3303                      struct cfg_param_attr *cfg_param)
3304 {
3305         struct host_if_msg msg;
3306         struct host_if_drv *hif_drv = vif->hif_drv;
3307
3308         if (!hif_drv) {
3309                 netdev_err(vif->ndev, "hif_drv NULL\n");
3310                 return -EFAULT;
3311         }
3312
3313         memset(&msg, 0, sizeof(struct host_if_msg));
3314         msg.id = HOST_IF_MSG_CFG_PARAMS;
3315         msg.body.cfg_info = *cfg_param;
3316         msg.vif = vif;
3317
3318         return wilc_enqueue_cmd(&msg);
3319 }
3320
3321 static void get_periodic_rssi(struct timer_list *unused)
3322 {
3323         struct wilc_vif *vif = periodic_rssi_vif;
3324
3325         if (!vif->hif_drv) {
3326                 netdev_err(vif->ndev, "Driver handler is NULL\n");
3327                 return;
3328         }
3329
3330         if (vif->hif_drv->hif_state == HOST_IF_CONNECTED)
3331                 wilc_get_statistics(vif, &vif->wilc->dummy_statistics);
3332
3333         mod_timer(&periodic_rssi, jiffies + msecs_to_jiffies(5000));
3334 }
3335
3336 int wilc_init(struct net_device *dev, struct host_if_drv **hif_drv_handler)
3337 {
3338         int result = 0;
3339         struct host_if_drv *hif_drv;
3340         struct wilc_vif *vif;
3341         struct wilc *wilc;
3342         int i;
3343
3344         vif = netdev_priv(dev);
3345         wilc = vif->wilc;
3346
3347         scan_while_connected = false;
3348
3349         init_completion(&hif_wait_response);
3350
3351         hif_drv  = kzalloc(sizeof(*hif_drv), GFP_KERNEL);
3352         if (!hif_drv) {
3353                 result = -ENOMEM;
3354                 goto _fail_;
3355         }
3356         *hif_drv_handler = hif_drv;
3357         for (i = 0; i < wilc->vif_num; i++)
3358                 if (dev == wilc->vif[i]->ndev) {
3359                         wilc->vif[i]->hif_drv = hif_drv;
3360                         hif_drv->driver_handler_id = i + 1;
3361                         break;
3362                 }
3363
3364         wilc_optaining_ip = false;
3365
3366         if (clients_count == 0) {
3367                 init_completion(&hif_thread_comp);
3368                 init_completion(&hif_driver_comp);
3369                 mutex_init(&hif_deinit_lock);
3370         }
3371
3372         init_completion(&hif_drv->comp_test_key_block);
3373         init_completion(&hif_drv->comp_test_disconn_block);
3374         init_completion(&hif_drv->comp_get_rssi);
3375         init_completion(&hif_drv->comp_inactive_time);
3376
3377         if (clients_count == 0) {
3378                 hif_workqueue = create_singlethread_workqueue("WILC_wq");
3379                 if (!hif_workqueue) {
3380                         netdev_err(vif->ndev, "Failed to create workqueue\n");
3381                         result = -ENOMEM;
3382                         goto _fail_;
3383                 }
3384
3385                 periodic_rssi_vif = vif;
3386                 timer_setup(&periodic_rssi, get_periodic_rssi, 0);
3387                 mod_timer(&periodic_rssi, jiffies + msecs_to_jiffies(5000));
3388         }
3389
3390         timer_setup(&hif_drv->scan_timer, timer_scan_cb, 0);
3391         timer_setup(&hif_drv->connect_timer, timer_connect_cb, 0);
3392         timer_setup(&hif_drv->remain_on_ch_timer, listen_timer_cb, 0);
3393
3394         mutex_init(&hif_drv->cfg_values_lock);
3395         mutex_lock(&hif_drv->cfg_values_lock);
3396
3397         hif_drv->hif_state = HOST_IF_IDLE;
3398         hif_drv->cfg_values.site_survey_enabled = SITE_SURVEY_OFF;
3399         hif_drv->cfg_values.scan_source = DEFAULT_SCAN;
3400         hif_drv->cfg_values.active_scan_time = ACTIVE_SCAN_TIME;
3401         hif_drv->cfg_values.passive_scan_time = PASSIVE_SCAN_TIME;
3402         hif_drv->cfg_values.curr_tx_rate = AUTORATE;
3403
3404         hif_drv->p2p_timeout = 0;
3405
3406         mutex_unlock(&hif_drv->cfg_values_lock);
3407
3408         clients_count++;
3409
3410 _fail_:
3411         return result;
3412 }
3413
3414 int wilc_deinit(struct wilc_vif *vif)
3415 {
3416         int result = 0;
3417         struct host_if_msg msg;
3418         struct host_if_drv *hif_drv = vif->hif_drv;
3419
3420         if (!hif_drv)   {
3421                 netdev_err(vif->ndev, "hif_drv = NULL\n");
3422                 return -EFAULT;
3423         }
3424
3425         mutex_lock(&hif_deinit_lock);
3426
3427         terminated_handle = hif_drv;
3428
3429         del_timer_sync(&hif_drv->scan_timer);
3430         del_timer_sync(&hif_drv->connect_timer);
3431         del_timer_sync(&periodic_rssi);
3432         del_timer_sync(&hif_drv->remain_on_ch_timer);
3433
3434         wilc_set_wfi_drv_handler(vif, 0, 0, 0);
3435         wait_for_completion(&hif_driver_comp);
3436
3437         if (hif_drv->usr_scan_req.scan_result) {
3438                 hif_drv->usr_scan_req.scan_result(SCAN_EVENT_ABORTED, NULL,
3439                                                   hif_drv->usr_scan_req.arg,
3440                                                   NULL);
3441                 hif_drv->usr_scan_req.scan_result = NULL;
3442         }
3443
3444         hif_drv->hif_state = HOST_IF_IDLE;
3445
3446         scan_while_connected = false;
3447
3448         memset(&msg, 0, sizeof(struct host_if_msg));
3449
3450         if (clients_count == 1) {
3451                 msg.id = HOST_IF_MSG_EXIT;
3452                 msg.vif = vif;
3453
3454                 result = wilc_enqueue_cmd(&msg);
3455                 if (result != 0)
3456                         netdev_err(vif->ndev, "deinit : Error(%d)\n", result);
3457                 else
3458                         wait_for_completion(&hif_thread_comp);
3459
3460                 destroy_workqueue(hif_workqueue);
3461         }
3462
3463         kfree(hif_drv);
3464
3465         clients_count--;
3466         terminated_handle = NULL;
3467         mutex_unlock(&hif_deinit_lock);
3468         return result;
3469 }
3470
3471 void wilc_network_info_received(struct wilc *wilc, u8 *buffer, u32 length)
3472 {
3473         s32 result = 0;
3474         struct host_if_msg msg;
3475         int id;
3476         struct host_if_drv *hif_drv = NULL;
3477         struct wilc_vif *vif;
3478
3479         id = buffer[length - 4];
3480         id |= (buffer[length - 3] << 8);
3481         id |= (buffer[length - 2] << 16);
3482         id |= (buffer[length - 1] << 24);
3483         vif = wilc_get_vif_from_idx(wilc, id);
3484         if (!vif)
3485                 return;
3486         hif_drv = vif->hif_drv;
3487
3488         if (!hif_drv || hif_drv == terminated_handle)   {
3489                 netdev_err(vif->ndev, "driver not init[%p]\n", hif_drv);
3490                 return;
3491         }
3492
3493         memset(&msg, 0, sizeof(struct host_if_msg));
3494
3495         msg.id = HOST_IF_MSG_RCVD_NTWRK_INFO;
3496         msg.vif = vif;
3497
3498         msg.body.net_info.len = length;
3499         msg.body.net_info.buffer = kmemdup(buffer, length, GFP_KERNEL);
3500         if (!msg.body.net_info.buffer)
3501                 return;
3502
3503         result = wilc_enqueue_cmd(&msg);
3504         if (result) {
3505                 netdev_err(vif->ndev, "message parameters (%d)\n", result);
3506                 kfree(msg.body.net_info.buffer);
3507         }
3508 }
3509
3510 void wilc_gnrl_async_info_received(struct wilc *wilc, u8 *buffer, u32 length)
3511 {
3512         s32 result = 0;
3513         struct host_if_msg msg;
3514         int id;
3515         struct host_if_drv *hif_drv = NULL;
3516         struct wilc_vif *vif;
3517
3518         mutex_lock(&hif_deinit_lock);
3519
3520         id = buffer[length - 4];
3521         id |= (buffer[length - 3] << 8);
3522         id |= (buffer[length - 2] << 16);
3523         id |= (buffer[length - 1] << 24);
3524         vif = wilc_get_vif_from_idx(wilc, id);
3525         if (!vif) {
3526                 mutex_unlock(&hif_deinit_lock);
3527                 return;
3528         }
3529
3530         hif_drv = vif->hif_drv;
3531
3532         if (!hif_drv || hif_drv == terminated_handle) {
3533                 mutex_unlock(&hif_deinit_lock);
3534                 return;
3535         }
3536
3537         if (!hif_drv->usr_conn_req.conn_result) {
3538                 netdev_err(vif->ndev, "there is no current Connect Request\n");
3539                 mutex_unlock(&hif_deinit_lock);
3540                 return;
3541         }
3542
3543         memset(&msg, 0, sizeof(struct host_if_msg));
3544
3545         msg.id = HOST_IF_MSG_RCVD_GNRL_ASYNC_INFO;
3546         msg.vif = vif;
3547
3548         msg.body.async_info.len = length;
3549         msg.body.async_info.buffer = kmemdup(buffer, length, GFP_KERNEL);
3550         if (!msg.body.async_info.buffer) {
3551                 mutex_unlock(&hif_deinit_lock);
3552                 return;
3553         }
3554
3555         result = wilc_enqueue_cmd(&msg);
3556         if (result) {
3557                 netdev_err(vif->ndev, "synchronous info (%d)\n", result);
3558                 kfree(msg.body.async_info.buffer);
3559         }
3560
3561         mutex_unlock(&hif_deinit_lock);
3562 }
3563
3564 void wilc_scan_complete_received(struct wilc *wilc, u8 *buffer, u32 length)
3565 {
3566         s32 result = 0;
3567         struct host_if_msg msg;
3568         int id;
3569         struct host_if_drv *hif_drv = NULL;
3570         struct wilc_vif *vif;
3571
3572         id = buffer[length - 4];
3573         id |= buffer[length - 3] << 8;
3574         id |= buffer[length - 2] << 16;
3575         id |= buffer[length - 1] << 24;
3576         vif = wilc_get_vif_from_idx(wilc, id);
3577         if (!vif)
3578                 return;
3579         hif_drv = vif->hif_drv;
3580
3581         if (!hif_drv || hif_drv == terminated_handle)
3582                 return;
3583
3584         if (hif_drv->usr_scan_req.scan_result) {
3585                 memset(&msg, 0, sizeof(struct host_if_msg));
3586
3587                 msg.id = HOST_IF_MSG_RCVD_SCAN_COMPLETE;
3588                 msg.vif = vif;
3589
3590                 result = wilc_enqueue_cmd(&msg);
3591                 if (result)
3592                         netdev_err(vif->ndev, "complete param (%d)\n", result);
3593         }
3594 }
3595
3596 int wilc_remain_on_channel(struct wilc_vif *vif, u32 session_id,
3597                            u32 duration, u16 chan,
3598                            wilc_remain_on_chan_expired expired,
3599                            wilc_remain_on_chan_ready ready,
3600                            void *user_arg)
3601 {
3602         int result = 0;
3603         struct host_if_msg msg;
3604
3605         memset(&msg, 0, sizeof(struct host_if_msg));
3606
3607         msg.id = HOST_IF_MSG_REMAIN_ON_CHAN;
3608         msg.body.remain_on_ch.ch = chan;
3609         msg.body.remain_on_ch.expired = expired;
3610         msg.body.remain_on_ch.ready = ready;
3611         msg.body.remain_on_ch.arg = user_arg;
3612         msg.body.remain_on_ch.duration = duration;
3613         msg.body.remain_on_ch.id = session_id;
3614         msg.vif = vif;
3615
3616         result = wilc_enqueue_cmd(&msg);
3617         if (result)
3618                 netdev_err(vif->ndev, "wilc mq send fail\n");
3619
3620         return result;
3621 }
3622
3623 int wilc_listen_state_expired(struct wilc_vif *vif, u32 session_id)
3624 {
3625         int result = 0;
3626         struct host_if_msg msg;
3627         struct host_if_drv *hif_drv = vif->hif_drv;
3628
3629         if (!hif_drv) {
3630                 netdev_err(vif->ndev, "driver is null\n");
3631                 return -EFAULT;
3632         }
3633
3634         del_timer(&hif_drv->remain_on_ch_timer);
3635
3636         memset(&msg, 0, sizeof(struct host_if_msg));
3637         msg.id = HOST_IF_MSG_LISTEN_TIMER_FIRED;
3638         msg.vif = vif;
3639         msg.body.remain_on_ch.id = session_id;
3640
3641         result = wilc_enqueue_cmd(&msg);
3642         if (result)
3643                 netdev_err(vif->ndev, "wilc mq send fail\n");
3644
3645         return result;
3646 }
3647
3648 int wilc_frame_register(struct wilc_vif *vif, u16 frame_type, bool reg)
3649 {
3650         int result = 0;
3651         struct host_if_msg msg;
3652
3653         memset(&msg, 0, sizeof(struct host_if_msg));
3654
3655         msg.id = HOST_IF_MSG_REGISTER_FRAME;
3656         switch (frame_type) {
3657         case ACTION:
3658                 msg.body.reg_frame.reg_id = ACTION_FRM_IDX;
3659                 break;
3660
3661         case PROBE_REQ:
3662                 msg.body.reg_frame.reg_id = PROBE_REQ_IDX;
3663                 break;
3664
3665         default:
3666                 break;
3667         }
3668         msg.body.reg_frame.frame_type = frame_type;
3669         msg.body.reg_frame.reg = reg;
3670         msg.vif = vif;
3671
3672         result = wilc_enqueue_cmd(&msg);
3673         if (result)
3674                 netdev_err(vif->ndev, "wilc mq send fail\n");
3675
3676         return result;
3677 }
3678
3679 int wilc_add_beacon(struct wilc_vif *vif, u32 interval, u32 dtim_period,
3680                     u32 head_len, u8 *head, u32 tail_len, u8 *tail)
3681 {
3682         int result = 0;
3683         struct host_if_msg msg;
3684         struct beacon_attr *beacon_info = &msg.body.beacon_info;
3685
3686         memset(&msg, 0, sizeof(struct host_if_msg));
3687
3688         msg.id = HOST_IF_MSG_ADD_BEACON;
3689         msg.vif = vif;
3690         beacon_info->interval = interval;
3691         beacon_info->dtim_period = dtim_period;
3692         beacon_info->head_len = head_len;
3693         beacon_info->head = kmemdup(head, head_len, GFP_KERNEL);
3694         if (!beacon_info->head) {
3695                 result = -ENOMEM;
3696                 goto error;
3697         }
3698         beacon_info->tail_len = tail_len;
3699
3700         if (tail_len > 0) {
3701                 beacon_info->tail = kmemdup(tail, tail_len, GFP_KERNEL);
3702                 if (!beacon_info->tail) {
3703                         result = -ENOMEM;
3704                         goto error;
3705                 }
3706         } else {
3707                 beacon_info->tail = NULL;
3708         }
3709
3710         result = wilc_enqueue_cmd(&msg);
3711         if (result)
3712                 netdev_err(vif->ndev, "wilc mq send fail\n");
3713
3714 error:
3715         if (result) {
3716                 kfree(beacon_info->head);
3717
3718                 kfree(beacon_info->tail);
3719         }
3720
3721         return result;
3722 }
3723
3724 int wilc_del_beacon(struct wilc_vif *vif)
3725 {
3726         int result = 0;
3727         struct host_if_msg msg;
3728
3729         msg.id = HOST_IF_MSG_DEL_BEACON;
3730         msg.vif = vif;
3731
3732         result = wilc_enqueue_cmd(&msg);
3733         if (result)
3734                 netdev_err(vif->ndev, "wilc_mq_send fail\n");
3735
3736         return result;
3737 }
3738
3739 int wilc_add_station(struct wilc_vif *vif, struct add_sta_param *sta_param)
3740 {
3741         int result = 0;
3742         struct host_if_msg msg;
3743         struct add_sta_param *add_sta_info = &msg.body.add_sta_info;
3744
3745         memset(&msg, 0, sizeof(struct host_if_msg));
3746
3747         msg.id = HOST_IF_MSG_ADD_STATION;
3748         msg.vif = vif;
3749
3750         memcpy(add_sta_info, sta_param, sizeof(struct add_sta_param));
3751         if (add_sta_info->rates_len > 0) {
3752                 add_sta_info->rates = kmemdup(sta_param->rates,
3753                                               add_sta_info->rates_len,
3754                                               GFP_KERNEL);
3755                 if (!add_sta_info->rates)
3756                         return -ENOMEM;
3757         }
3758
3759         result = wilc_enqueue_cmd(&msg);
3760         if (result) {
3761                 netdev_err(vif->ndev, "wilc_mq_send fail\n");
3762                 kfree(add_sta_info->rates);
3763         }
3764         return result;
3765 }
3766
3767 int wilc_del_station(struct wilc_vif *vif, const u8 *mac_addr)
3768 {
3769         int result = 0;
3770         struct host_if_msg msg;
3771         struct del_sta *del_sta_info = &msg.body.del_sta_info;
3772
3773         memset(&msg, 0, sizeof(struct host_if_msg));
3774
3775         msg.id = HOST_IF_MSG_DEL_STATION;
3776         msg.vif = vif;
3777
3778         if (!mac_addr)
3779                 eth_broadcast_addr(del_sta_info->mac_addr);
3780         else
3781                 memcpy(del_sta_info->mac_addr, mac_addr, ETH_ALEN);
3782
3783         result = wilc_enqueue_cmd(&msg);
3784         if (result)
3785                 netdev_err(vif->ndev, "wilc_mq_send fail\n");
3786         return result;
3787 }
3788
3789 int wilc_del_allstation(struct wilc_vif *vif, u8 mac_addr[][ETH_ALEN])
3790 {
3791         int result = 0;
3792         struct host_if_msg msg;
3793         struct del_all_sta *del_all_sta_info = &msg.body.del_all_sta_info;
3794         u8 zero_addr[ETH_ALEN] = {0};
3795         int i;
3796         u8 assoc_sta = 0;
3797
3798         memset(&msg, 0, sizeof(struct host_if_msg));
3799
3800         msg.id = HOST_IF_MSG_DEL_ALL_STA;
3801         msg.vif = vif;
3802
3803         for (i = 0; i < MAX_NUM_STA; i++) {
3804                 if (memcmp(mac_addr[i], zero_addr, ETH_ALEN)) {
3805                         memcpy(del_all_sta_info->del_all_sta[i], mac_addr[i],
3806                                ETH_ALEN);
3807                         assoc_sta++;
3808                 }
3809         }
3810         if (!assoc_sta)
3811                 return result;
3812
3813         del_all_sta_info->assoc_sta = assoc_sta;
3814         result = wilc_enqueue_cmd(&msg);
3815
3816         if (result)
3817                 netdev_err(vif->ndev, "wilc_mq_send fail\n");
3818         else
3819                 wait_for_completion(&hif_wait_response);
3820
3821         return result;
3822 }
3823
3824 int wilc_edit_station(struct wilc_vif *vif,
3825                       struct add_sta_param *sta_param)
3826 {
3827         int result = 0;
3828         struct host_if_msg msg;
3829         struct add_sta_param *add_sta_info = &msg.body.add_sta_info;
3830
3831         memset(&msg, 0, sizeof(struct host_if_msg));
3832
3833         msg.id = HOST_IF_MSG_EDIT_STATION;
3834         msg.vif = vif;
3835
3836         memcpy(add_sta_info, sta_param, sizeof(struct add_sta_param));
3837         if (add_sta_info->rates_len > 0) {
3838                 add_sta_info->rates = kmemdup(sta_param->rates,
3839                                               add_sta_info->rates_len,
3840                                               GFP_KERNEL);
3841                 if (!add_sta_info->rates)
3842                         return -ENOMEM;
3843         }
3844
3845         result = wilc_enqueue_cmd(&msg);
3846         if (result) {
3847                 netdev_err(vif->ndev, "wilc_mq_send fail\n");
3848                 kfree(add_sta_info->rates);
3849         }
3850
3851         return result;
3852 }
3853
3854 int wilc_set_power_mgmt(struct wilc_vif *vif, bool enabled, u32 timeout)
3855 {
3856         int result = 0;
3857         struct host_if_msg msg;
3858         struct power_mgmt_param *pwr_mgmt_info = &msg.body.pwr_mgmt_info;
3859
3860         if (wilc_wlan_get_num_conn_ifcs(vif->wilc) == 2 && enabled)
3861                 return 0;
3862
3863         memset(&msg, 0, sizeof(struct host_if_msg));
3864
3865         msg.id = HOST_IF_MSG_POWER_MGMT;
3866         msg.vif = vif;
3867
3868         pwr_mgmt_info->enabled = enabled;
3869         pwr_mgmt_info->timeout = timeout;
3870
3871         result = wilc_enqueue_cmd(&msg);
3872         if (result)
3873                 netdev_err(vif->ndev, "wilc_mq_send fail\n");
3874         return result;
3875 }
3876
3877 int wilc_setup_multicast_filter(struct wilc_vif *vif, bool enabled,
3878                                 u32 count)
3879 {
3880         int result = 0;
3881         struct host_if_msg msg;
3882         struct set_multicast *multicast_filter_param = &msg.body.multicast_info;
3883
3884         memset(&msg, 0, sizeof(struct host_if_msg));
3885
3886         msg.id = HOST_IF_MSG_SET_MULTICAST_FILTER;
3887         msg.vif = vif;
3888
3889         multicast_filter_param->enabled = enabled;
3890         multicast_filter_param->cnt = count;
3891
3892         result = wilc_enqueue_cmd(&msg);
3893         if (result)
3894                 netdev_err(vif->ndev, "wilc_mq_send fail\n");
3895         return result;
3896 }
3897
3898 static void *host_int_parse_join_bss_param(struct network_info *info)
3899 {
3900         struct join_bss_param *param = NULL;
3901         u8 *ies;
3902         u16 ies_len;
3903         u16 index = 0;
3904         u8 rates_no = 0;
3905         u8 ext_rates_no;
3906         u16 offset;
3907         u8 pcipher_cnt;
3908         u8 auth_cnt;
3909         u8 pcipher_total_cnt = 0;
3910         u8 auth_total_cnt = 0;
3911         u8 i, j;
3912
3913         ies = info->ies;
3914         ies_len = info->ies_len;
3915
3916         param = kzalloc(sizeof(*param), GFP_KERNEL);
3917         if (!param)
3918                 return NULL;
3919
3920         param->dtim_period = info->dtim_period;
3921         param->beacon_period = info->beacon_period;
3922         param->cap_info = info->cap_info;
3923         memcpy(param->bssid, info->bssid, 6);
3924         memcpy((u8 *)param->ssid, info->ssid, info->ssid_len + 1);
3925         param->ssid_len = info->ssid_len;
3926         memset(param->rsn_pcip_policy, 0xFF, 3);
3927         memset(param->rsn_auth_policy, 0xFF, 3);
3928
3929         while (index < ies_len) {
3930                 if (ies[index] == SUPP_RATES_IE) {
3931                         rates_no = ies[index + 1];
3932                         param->supp_rates[0] = rates_no;
3933                         index += 2;
3934
3935                         for (i = 0; i < rates_no; i++)
3936                                 param->supp_rates[i + 1] = ies[index + i];
3937
3938                         index += rates_no;
3939                 } else if (ies[index] == EXT_SUPP_RATES_IE) {
3940                         ext_rates_no = ies[index + 1];
3941                         if (ext_rates_no > (MAX_RATES_SUPPORTED - rates_no))
3942                                 param->supp_rates[0] = MAX_RATES_SUPPORTED;
3943                         else
3944                                 param->supp_rates[0] += ext_rates_no;
3945                         index += 2;
3946                         for (i = 0; i < (param->supp_rates[0] - rates_no); i++)
3947                                 param->supp_rates[rates_no + i + 1] = ies[index + i];
3948
3949                         index += ext_rates_no;
3950                 } else if (ies[index] == HT_CAPABILITY_IE) {
3951                         param->ht_capable = true;
3952                         index += ies[index + 1] + 2;
3953                 } else if ((ies[index] == WMM_IE) &&
3954                            (ies[index + 2] == 0x00) && (ies[index + 3] == 0x50) &&
3955                            (ies[index + 4] == 0xF2) &&
3956                            (ies[index + 5] == 0x02) &&
3957                            ((ies[index + 6] == 0x00) || (ies[index + 6] == 0x01)) &&
3958                            (ies[index + 7] == 0x01)) {
3959                         param->wmm_cap = true;
3960
3961                         if (ies[index + 8] & BIT(7))
3962                                 param->uapsd_cap = true;
3963                         index += ies[index + 1] + 2;
3964                 } else if ((ies[index] == P2P_IE) &&
3965                          (ies[index + 2] == 0x50) && (ies[index + 3] == 0x6f) &&
3966                          (ies[index + 4] == 0x9a) &&
3967                          (ies[index + 5] == 0x09) && (ies[index + 6] == 0x0c)) {
3968                         u16 p2p_cnt;
3969
3970                         param->tsf = info->tsf_lo;
3971                         param->noa_enabled = 1;
3972                         param->idx = ies[index + 9];
3973
3974                         if (ies[index + 10] & BIT(7)) {
3975                                 param->opp_enabled = 1;
3976                                 param->ct_window = ies[index + 10];
3977                         } else {
3978                                 param->opp_enabled = 0;
3979                         }
3980
3981                         param->cnt = ies[index + 11];
3982                         p2p_cnt = index + 12;
3983
3984                         memcpy(param->duration, ies + p2p_cnt, 4);
3985                         p2p_cnt += 4;
3986
3987                         memcpy(param->interval, ies + p2p_cnt, 4);
3988                         p2p_cnt += 4;
3989
3990                         memcpy(param->start_time, ies + p2p_cnt, 4);
3991
3992                         index += ies[index + 1] + 2;
3993                 } else if ((ies[index] == RSN_IE) ||
3994                          ((ies[index] == WPA_IE) && (ies[index + 2] == 0x00) &&
3995                           (ies[index + 3] == 0x50) && (ies[index + 4] == 0xF2) &&
3996                           (ies[index + 5] == 0x01)))    {
3997                         u16 rsn_idx = index;
3998
3999                         if (ies[rsn_idx] == RSN_IE)     {
4000                                 param->mode_802_11i = 2;
4001                         } else {
4002                                 if (param->mode_802_11i == 0)
4003                                         param->mode_802_11i = 1;
4004                                 rsn_idx += 4;
4005                         }
4006
4007                         rsn_idx += 7;
4008                         param->rsn_grp_policy = ies[rsn_idx];
4009                         rsn_idx++;
4010                         offset = ies[rsn_idx] * 4;
4011                         pcipher_cnt = (ies[rsn_idx] > 3) ? 3 : ies[rsn_idx];
4012                         rsn_idx += 2;
4013
4014                         for (i = pcipher_total_cnt, j = 0; i < pcipher_cnt + pcipher_total_cnt && i < 3; i++, j++)
4015                                 param->rsn_pcip_policy[i] = ies[rsn_idx + ((j + 1) * 4) - 1];
4016
4017                         pcipher_total_cnt += pcipher_cnt;
4018                         rsn_idx += offset;
4019
4020                         offset = ies[rsn_idx] * 4;
4021
4022                         auth_cnt = (ies[rsn_idx] > 3) ? 3 : ies[rsn_idx];
4023                         rsn_idx += 2;
4024
4025                         for (i = auth_total_cnt, j = 0; i < auth_total_cnt + auth_cnt; i++, j++)
4026                                 param->rsn_auth_policy[i] = ies[rsn_idx + ((j + 1) * 4) - 1];
4027
4028                         auth_total_cnt += auth_cnt;
4029                         rsn_idx += offset;
4030
4031                         if (ies[index] == RSN_IE) {
4032                                 param->rsn_cap[0] = ies[rsn_idx];
4033                                 param->rsn_cap[1] = ies[rsn_idx + 1];
4034                                 rsn_idx += 2;
4035                         }
4036                         param->rsn_found = true;
4037                         index += ies[index + 1] + 2;
4038                 } else {
4039                         index += ies[index + 1] + 2;
4040                 }
4041         }
4042
4043         return (void *)param;
4044 }
4045
4046 int wilc_setup_ipaddress(struct wilc_vif *vif, u8 *ip_addr, u8 idx)
4047 {
4048         int result = 0;
4049         struct host_if_msg msg;
4050
4051         memset(&msg, 0, sizeof(struct host_if_msg));
4052
4053         msg.id = HOST_IF_MSG_SET_IPADDRESS;
4054
4055         msg.body.ip_info.ip_addr = ip_addr;
4056         msg.vif = vif;
4057         msg.body.ip_info.idx = idx;
4058
4059         result = wilc_enqueue_cmd(&msg);
4060         if (result)
4061                 netdev_err(vif->ndev, "wilc_mq_send fail\n");
4062
4063         return result;
4064 }
4065
4066 static int host_int_get_ipaddress(struct wilc_vif *vif, u8 *ip_addr, u8 idx)
4067 {
4068         int result = 0;
4069         struct host_if_msg msg;
4070
4071         memset(&msg, 0, sizeof(struct host_if_msg));
4072
4073         msg.id = HOST_IF_MSG_GET_IPADDRESS;
4074
4075         msg.body.ip_info.ip_addr = ip_addr;
4076         msg.vif = vif;
4077         msg.body.ip_info.idx = idx;
4078
4079         result = wilc_enqueue_cmd(&msg);
4080         if (result)
4081                 netdev_err(vif->ndev, "wilc_mq_send fail\n");
4082
4083         return result;
4084 }
4085
4086 int wilc_set_tx_power(struct wilc_vif *vif, u8 tx_power)
4087 {
4088         int ret = 0;
4089         struct host_if_msg msg;
4090
4091         memset(&msg, 0, sizeof(struct host_if_msg));
4092
4093         msg.id = HOST_IF_MSG_SET_TX_POWER;
4094         msg.body.tx_power.tx_pwr = tx_power;
4095         msg.vif = vif;
4096
4097         ret = wilc_enqueue_cmd(&msg);
4098         if (ret)
4099                 netdev_err(vif->ndev, "wilc_mq_send fail\n");
4100
4101         return ret;
4102 }
4103
4104 int wilc_get_tx_power(struct wilc_vif *vif, u8 *tx_power)
4105 {
4106         int ret = 0;
4107         struct host_if_msg msg;
4108
4109         memset(&msg, 0, sizeof(struct host_if_msg));
4110
4111         msg.id = HOST_IF_MSG_GET_TX_POWER;
4112         msg.vif = vif;
4113
4114         ret = wilc_enqueue_cmd(&msg);
4115         if (ret)
4116                 netdev_err(vif->ndev, "Failed to get TX PWR\n");
4117
4118         wait_for_completion(&hif_wait_response);
4119         *tx_power = msg.body.tx_power.tx_pwr;
4120
4121         return ret;
4122 }