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