Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm...
[sfrench/cifs-2.6.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 rcvd_async_info {
17         u8 *buffer;
18         u32 len;
19 };
20
21 struct set_multicast {
22         bool enabled;
23         u32 cnt;
24         u8 *mc_list;
25 };
26
27 struct del_all_sta {
28         u8 assoc_sta;
29         u8 mac[WILC_MAX_NUM_STA][ETH_ALEN];
30 };
31
32 struct wilc_op_mode {
33         __le32 mode;
34 };
35
36 struct wilc_reg_frame {
37         bool reg;
38         u8 reg_id;
39         __le16 frame_type;
40 } __packed;
41
42 struct wilc_drv_handler {
43         __le32 handler;
44         u8 mode;
45 } __packed;
46
47 struct wilc_wep_key {
48         u8 index;
49         u8 key_len;
50         u8 key[0];
51 } __packed;
52
53 struct wilc_sta_wpa_ptk {
54         u8 mac_addr[ETH_ALEN];
55         u8 key_len;
56         u8 key[0];
57 } __packed;
58
59 struct wilc_ap_wpa_ptk {
60         u8 mac_addr[ETH_ALEN];
61         u8 index;
62         u8 key_len;
63         u8 key[0];
64 } __packed;
65
66 struct wilc_gtk_key {
67         u8 mac_addr[ETH_ALEN];
68         u8 rsc[8];
69         u8 index;
70         u8 key_len;
71         u8 key[0];
72 } __packed;
73
74 union message_body {
75         struct rcvd_net_info net_info;
76         struct rcvd_async_info async_info;
77         struct set_multicast multicast_info;
78         struct remain_ch remain_on_ch;
79         char *data;
80 };
81
82 struct host_if_msg {
83         union message_body body;
84         struct wilc_vif *vif;
85         struct work_struct work;
86         void (*fn)(struct work_struct *ws);
87         struct completion work_comp;
88         bool is_sync;
89 };
90
91 struct join_bss_param {
92         enum bss_types bss_type;
93         u8 dtim_period;
94         u16 beacon_period;
95         u16 cap_info;
96         u8 bssid[6];
97         char ssid[MAX_SSID_LEN];
98         u8 ssid_len;
99         u8 supp_rates[MAX_RATES_SUPPORTED + 1];
100         u8 ht_capable;
101         u8 wmm_cap;
102         u8 uapsd_cap;
103         bool rsn_found;
104         u8 rsn_grp_policy;
105         u8 mode_802_11i;
106         u8 rsn_pcip_policy[3];
107         u8 rsn_auth_policy[3];
108         u8 rsn_cap[2];
109         u32 tsf;
110         u8 noa_enabled;
111         u8 opp_enabled;
112         u8 ct_window;
113         u8 cnt;
114         u8 idx;
115         u8 duration[4];
116         u8 interval[4];
117         u8 start_time[4];
118 };
119
120 static struct host_if_drv *terminated_handle;
121 static struct mutex hif_deinit_lock;
122
123 /* 'msg' should be free by the caller for syc */
124 static struct host_if_msg*
125 wilc_alloc_work(struct wilc_vif *vif, void (*work_fun)(struct work_struct *),
126                 bool is_sync)
127 {
128         struct host_if_msg *msg;
129
130         if (!work_fun)
131                 return ERR_PTR(-EINVAL);
132
133         msg = kzalloc(sizeof(*msg), GFP_ATOMIC);
134         if (!msg)
135                 return ERR_PTR(-ENOMEM);
136         msg->fn = work_fun;
137         msg->vif = vif;
138         msg->is_sync = is_sync;
139         if (is_sync)
140                 init_completion(&msg->work_comp);
141
142         return msg;
143 }
144
145 static int wilc_enqueue_work(struct host_if_msg *msg)
146 {
147         INIT_WORK(&msg->work, msg->fn);
148
149         if (!msg->vif || !msg->vif->wilc || !msg->vif->wilc->hif_workqueue)
150                 return -EINVAL;
151
152         if (!queue_work(msg->vif->wilc->hif_workqueue, &msg->work))
153                 return -EINVAL;
154
155         return 0;
156 }
157
158 /* The idx starts from 0 to (NUM_CONCURRENT_IFC - 1), but 0 index used as
159  * special purpose in wilc device, so we add 1 to the index to starts from 1.
160  * As a result, the returned index will be 1 to NUM_CONCURRENT_IFC.
161  */
162 int wilc_get_vif_idx(struct wilc_vif *vif)
163 {
164         return vif->idx + 1;
165 }
166
167 /* We need to minus 1 from idx which is from wilc device to get real index
168  * of wilc->vif[], because we add 1 when pass to wilc device in the function
169  * wilc_get_vif_idx.
170  * As a result, the index should be between 0 and (NUM_CONCURRENT_IFC - 1).
171  */
172 static struct wilc_vif *wilc_get_vif_from_idx(struct wilc *wilc, int idx)
173 {
174         int index = idx - 1;
175
176         if (index < 0 || index >= WILC_NUM_CONCURRENT_IFC)
177                 return NULL;
178
179         return wilc->vif[index];
180 }
181
182 static int handle_scan_done(struct wilc_vif *vif, enum scan_event evt)
183 {
184         int result = 0;
185         u8 abort_running_scan;
186         struct wid wid;
187         struct host_if_drv *hif_drv = vif->hif_drv;
188         struct user_scan_req *scan_req;
189
190         if (evt == SCAN_EVENT_ABORTED) {
191                 abort_running_scan = 1;
192                 wid.id = WID_ABORT_RUNNING_SCAN;
193                 wid.type = WID_CHAR;
194                 wid.val = (s8 *)&abort_running_scan;
195                 wid.size = sizeof(char);
196
197                 result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
198                                               wilc_get_vif_idx(vif));
199
200                 if (result) {
201                         netdev_err(vif->ndev, "Failed to set abort running\n");
202                         result = -EFAULT;
203                 }
204         }
205
206         if (!hif_drv) {
207                 netdev_err(vif->ndev, "%s: hif driver is NULL\n", __func__);
208                 return result;
209         }
210
211         scan_req = &hif_drv->usr_scan_req;
212         if (scan_req->scan_result) {
213                 scan_req->scan_result(evt, NULL, scan_req->arg, NULL);
214                 scan_req->scan_result = NULL;
215         }
216
217         return result;
218 }
219
220 int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type,
221               u8 *ch_freq_list, u8 ch_list_len, const u8 *ies,
222               size_t ies_len, wilc_scan_result scan_result, void *user_arg,
223               struct hidden_network *hidden_net)
224 {
225         int result = 0;
226         struct wid wid_list[5];
227         u32 index = 0;
228         u32 i;
229         u8 *buffer;
230         u8 valuesize = 0;
231         u8 *hdn_ntwk_wid_val = NULL;
232         struct host_if_drv *hif_drv = vif->hif_drv;
233
234         if (hif_drv->hif_state >= HOST_IF_SCANNING &&
235             hif_drv->hif_state < HOST_IF_CONNECTED) {
236                 netdev_err(vif->ndev, "Already scan\n");
237                 result = -EBUSY;
238                 goto error;
239         }
240
241         if (vif->obtaining_ip || vif->connecting) {
242                 netdev_err(vif->ndev, "Don't do obss scan\n");
243                 result = -EBUSY;
244                 goto error;
245         }
246
247         hif_drv->usr_scan_req.ch_cnt = 0;
248
249         if (hidden_net) {
250                 wid_list[index].id = WID_SSID_PROBE_REQ;
251                 wid_list[index].type = WID_STR;
252
253                 for (i = 0; i < hidden_net->n_ssids; i++)
254                         valuesize += ((hidden_net->net_info[i].ssid_len) + 1);
255                 hdn_ntwk_wid_val = kmalloc(valuesize + 1, GFP_KERNEL);
256                 wid_list[index].val = hdn_ntwk_wid_val;
257                 if (wid_list[index].val) {
258                         buffer = wid_list[index].val;
259
260                         *buffer++ = hidden_net->n_ssids;
261
262                         for (i = 0; i < hidden_net->n_ssids; i++) {
263                                 *buffer++ = hidden_net->net_info[i].ssid_len;
264                                 memcpy(buffer, hidden_net->net_info[i].ssid,
265                                        hidden_net->net_info[i].ssid_len);
266                                 buffer += hidden_net->net_info[i].ssid_len;
267                         }
268
269                         wid_list[index].size = (s32)(valuesize + 1);
270                         index++;
271                 }
272         }
273
274         wid_list[index].id = WID_INFO_ELEMENT_PROBE;
275         wid_list[index].type = WID_BIN_DATA;
276         wid_list[index].val = (s8 *)ies;
277         wid_list[index].size = ies_len;
278         index++;
279
280         wid_list[index].id = WID_SCAN_TYPE;
281         wid_list[index].type = WID_CHAR;
282         wid_list[index].size = sizeof(char);
283         wid_list[index].val = (s8 *)&scan_type;
284         index++;
285
286         wid_list[index].id = WID_SCAN_CHANNEL_LIST;
287         wid_list[index].type = WID_BIN_DATA;
288
289         if (ch_freq_list && ch_list_len > 0) {
290                 for (i = 0; i < ch_list_len; i++) {
291                         if (ch_freq_list[i] > 0)
292                                 ch_freq_list[i] -= 1;
293                 }
294         }
295
296         wid_list[index].val = ch_freq_list;
297         wid_list[index].size = ch_list_len;
298         index++;
299
300         wid_list[index].id = WID_START_SCAN_REQ;
301         wid_list[index].type = WID_CHAR;
302         wid_list[index].size = sizeof(char);
303         wid_list[index].val = (s8 *)&scan_source;
304         index++;
305
306         result = wilc_send_config_pkt(vif, WILC_SET_CFG, wid_list,
307                                       index,
308                                       wilc_get_vif_idx(vif));
309         if (result) {
310                 netdev_err(vif->ndev, "Failed to send scan parameters\n");
311                 goto error;
312         }
313
314         hif_drv->usr_scan_req.scan_result = scan_result;
315         hif_drv->usr_scan_req.arg = user_arg;
316         hif_drv->scan_timer_vif = vif;
317         mod_timer(&hif_drv->scan_timer,
318                   jiffies + msecs_to_jiffies(HOST_IF_SCAN_TIMEOUT));
319
320 error:
321         if (hidden_net) {
322                 kfree(hidden_net->net_info);
323                 kfree(hdn_ntwk_wid_val);
324         }
325
326         return result;
327 }
328
329 static int wilc_send_connect_wid(struct wilc_vif *vif)
330 {
331         int result = 0;
332         struct wid wid_list[8];
333         u32 wid_cnt = 0, dummyval = 0;
334         u8 *cur_byte = NULL;
335         struct host_if_drv *hif_drv = vif->hif_drv;
336         struct user_conn_req *conn_attr = &hif_drv->usr_conn_req;
337         struct join_bss_param *bss_param = hif_drv->usr_conn_req.param;
338
339         wid_list[wid_cnt].id = WID_SUCCESS_FRAME_COUNT;
340         wid_list[wid_cnt].type = WID_INT;
341         wid_list[wid_cnt].size = sizeof(u32);
342         wid_list[wid_cnt].val = (s8 *)(&(dummyval));
343         wid_cnt++;
344
345         wid_list[wid_cnt].id = WID_RECEIVED_FRAGMENT_COUNT;
346         wid_list[wid_cnt].type = WID_INT;
347         wid_list[wid_cnt].size = sizeof(u32);
348         wid_list[wid_cnt].val = (s8 *)(&(dummyval));
349         wid_cnt++;
350
351         wid_list[wid_cnt].id = WID_FAILED_COUNT;
352         wid_list[wid_cnt].type = WID_INT;
353         wid_list[wid_cnt].size = sizeof(u32);
354         wid_list[wid_cnt].val = (s8 *)(&(dummyval));
355         wid_cnt++;
356
357         wid_list[wid_cnt].id = WID_INFO_ELEMENT_ASSOCIATE;
358         wid_list[wid_cnt].type = WID_BIN_DATA;
359         wid_list[wid_cnt].val = conn_attr->ies;
360         wid_list[wid_cnt].size = conn_attr->ies_len;
361         wid_cnt++;
362
363         wid_list[wid_cnt].id = WID_11I_MODE;
364         wid_list[wid_cnt].type = WID_CHAR;
365         wid_list[wid_cnt].size = sizeof(char);
366         wid_list[wid_cnt].val = (s8 *)&conn_attr->security;
367         wid_cnt++;
368
369         wid_list[wid_cnt].id = WID_AUTH_TYPE;
370         wid_list[wid_cnt].type = WID_CHAR;
371         wid_list[wid_cnt].size = sizeof(char);
372         wid_list[wid_cnt].val = (s8 *)&conn_attr->auth_type;
373         wid_cnt++;
374
375         wid_list[wid_cnt].id = WID_JOIN_REQ_EXTENDED;
376         wid_list[wid_cnt].type = WID_STR;
377         wid_list[wid_cnt].size = 112;
378         wid_list[wid_cnt].val = kmalloc(wid_list[wid_cnt].size, GFP_KERNEL);
379
380         if (!wid_list[wid_cnt].val) {
381                 result = -EFAULT;
382                 goto error;
383         }
384
385         cur_byte = wid_list[wid_cnt].val;
386
387         if (conn_attr->ssid) {
388                 memcpy(cur_byte, conn_attr->ssid, conn_attr->ssid_len);
389                 cur_byte[conn_attr->ssid_len] = '\0';
390         }
391         cur_byte += MAX_SSID_LEN;
392         *(cur_byte++) = WILC_FW_BSS_TYPE_INFRA;
393
394         if (conn_attr->ch >= 1 && conn_attr->ch <= 14) {
395                 *(cur_byte++) = conn_attr->ch;
396         } else {
397                 netdev_err(vif->ndev, "Channel out of range\n");
398                 *(cur_byte++) = 0xFF;
399         }
400         put_unaligned_le16(bss_param->cap_info, cur_byte);
401         cur_byte += 2;
402
403         if (conn_attr->bssid)
404                 memcpy(cur_byte, conn_attr->bssid, 6);
405         cur_byte += 6;
406
407         if (conn_attr->bssid)
408                 memcpy(cur_byte, conn_attr->bssid, 6);
409         cur_byte += 6;
410
411         put_unaligned_le16(bss_param->beacon_period, cur_byte);
412         cur_byte += 2;
413         *(cur_byte++)  =  bss_param->dtim_period;
414
415         memcpy(cur_byte, bss_param->supp_rates, MAX_RATES_SUPPORTED + 1);
416         cur_byte += (MAX_RATES_SUPPORTED + 1);
417
418         *(cur_byte++)  =  bss_param->wmm_cap;
419         *(cur_byte++)  = bss_param->uapsd_cap;
420
421         *(cur_byte++)  = bss_param->ht_capable;
422         conn_attr->ht_capable = bss_param->ht_capable;
423
424         *(cur_byte++)  =  bss_param->rsn_found;
425         *(cur_byte++)  =  bss_param->rsn_grp_policy;
426         *(cur_byte++) =  bss_param->mode_802_11i;
427
428         memcpy(cur_byte, bss_param->rsn_pcip_policy,
429                sizeof(bss_param->rsn_pcip_policy));
430         cur_byte += sizeof(bss_param->rsn_pcip_policy);
431
432         memcpy(cur_byte, bss_param->rsn_auth_policy,
433                sizeof(bss_param->rsn_auth_policy));
434         cur_byte += sizeof(bss_param->rsn_auth_policy);
435
436         memcpy(cur_byte, bss_param->rsn_cap, sizeof(bss_param->rsn_cap));
437         cur_byte += sizeof(bss_param->rsn_cap);
438
439         *(cur_byte++) = REAL_JOIN_REQ;
440         *(cur_byte++) = bss_param->noa_enabled;
441
442         if (bss_param->noa_enabled) {
443                 put_unaligned_le32(bss_param->tsf, cur_byte);
444                 cur_byte += 4;
445
446                 *(cur_byte++) = bss_param->opp_enabled;
447                 *(cur_byte++) = bss_param->idx;
448
449                 if (bss_param->opp_enabled)
450                         *(cur_byte++) = bss_param->ct_window;
451
452                 *(cur_byte++) = bss_param->cnt;
453
454                 memcpy(cur_byte, bss_param->duration,
455                        sizeof(bss_param->duration));
456                 cur_byte += sizeof(bss_param->duration);
457
458                 memcpy(cur_byte, bss_param->interval,
459                        sizeof(bss_param->interval));
460                 cur_byte += sizeof(bss_param->interval);
461
462                 memcpy(cur_byte, bss_param->start_time,
463                        sizeof(bss_param->start_time));
464                 cur_byte += sizeof(bss_param->start_time);
465         }
466
467         cur_byte = wid_list[wid_cnt].val;
468         wid_cnt++;
469
470         result = wilc_send_config_pkt(vif, WILC_SET_CFG, wid_list,
471                                       wid_cnt,
472                                       wilc_get_vif_idx(vif));
473         if (result) {
474                 netdev_err(vif->ndev, "failed to send config packet\n");
475                 kfree(cur_byte);
476                 goto error;
477         } else {
478                 hif_drv->hif_state = HOST_IF_WAITING_CONN_RESP;
479         }
480
481         kfree(cur_byte);
482         return 0;
483
484 error:
485
486         kfree(conn_attr->bssid);
487         conn_attr->bssid = NULL;
488
489         kfree(conn_attr->ssid);
490         conn_attr->ssid = NULL;
491
492         kfree(conn_attr->ies);
493         conn_attr->ies = NULL;
494
495         return result;
496 }
497
498 static void handle_connect_timeout(struct work_struct *work)
499 {
500         struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
501         struct wilc_vif *vif = msg->vif;
502         int result;
503         struct connect_info info;
504         struct wid wid;
505         u16 dummy_reason_code = 0;
506         struct host_if_drv *hif_drv = vif->hif_drv;
507
508         if (!hif_drv) {
509                 netdev_err(vif->ndev, "%s: hif driver is NULL\n", __func__);
510                 goto out;
511         }
512
513         hif_drv->hif_state = HOST_IF_IDLE;
514
515         memset(&info, 0, sizeof(struct connect_info));
516
517         if (hif_drv->usr_conn_req.conn_result) {
518                 if (hif_drv->usr_conn_req.bssid) {
519                         memcpy(info.bssid,
520                                hif_drv->usr_conn_req.bssid, 6);
521                 }
522
523                 if (hif_drv->usr_conn_req.ies) {
524                         info.req_ies_len = hif_drv->usr_conn_req.ies_len;
525                         info.req_ies = kmemdup(hif_drv->usr_conn_req.ies,
526                                                hif_drv->usr_conn_req.ies_len,
527                                                GFP_KERNEL);
528                         if (!info.req_ies)
529                                 goto out;
530                 }
531
532                 hif_drv->usr_conn_req.conn_result(CONN_DISCONN_EVENT_CONN_RESP,
533                                                   &info,
534                                                   WILC_MAC_STATUS_DISCONNECTED,
535                                                   NULL,
536                                                   hif_drv->usr_conn_req.arg);
537
538                 kfree(info.req_ies);
539                 info.req_ies = NULL;
540         } else {
541                 netdev_err(vif->ndev, "%s: conn_result is NULL\n", __func__);
542         }
543
544         wid.id = WID_DISCONNECT;
545         wid.type = WID_CHAR;
546         wid.val = (s8 *)&dummy_reason_code;
547         wid.size = sizeof(char);
548
549         result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
550                                       wilc_get_vif_idx(vif));
551         if (result)
552                 netdev_err(vif->ndev, "Failed to send disconnect\n");
553
554         hif_drv->usr_conn_req.ssid_len = 0;
555         kfree(hif_drv->usr_conn_req.ssid);
556         hif_drv->usr_conn_req.ssid = NULL;
557         kfree(hif_drv->usr_conn_req.bssid);
558         hif_drv->usr_conn_req.bssid = NULL;
559         hif_drv->usr_conn_req.ies_len = 0;
560         kfree(hif_drv->usr_conn_req.ies);
561         hif_drv->usr_conn_req.ies = NULL;
562
563 out:
564         kfree(msg);
565 }
566
567 static void host_int_fill_join_bss_param(struct join_bss_param *param, u8 *ies,
568                                          u16 *out_index, u8 *pcipher_tc,
569                                          u8 *auth_total_cnt, u32 tsf_lo,
570                                          u8 *rates_no)
571 {
572         u8 ext_rates_no;
573         u16 offset;
574         u8 pcipher_cnt;
575         u8 auth_cnt;
576         u8 i, j;
577         u16 index = *out_index;
578
579         if (ies[index] == WLAN_EID_SUPP_RATES) {
580                 *rates_no = ies[index + 1];
581                 param->supp_rates[0] = *rates_no;
582                 index += 2;
583
584                 for (i = 0; i < *rates_no; i++)
585                         param->supp_rates[i + 1] = ies[index + i];
586
587                 index += *rates_no;
588         } else if (ies[index] == WLAN_EID_EXT_SUPP_RATES) {
589                 ext_rates_no = ies[index + 1];
590                 if (ext_rates_no > (MAX_RATES_SUPPORTED - *rates_no))
591                         param->supp_rates[0] = MAX_RATES_SUPPORTED;
592                 else
593                         param->supp_rates[0] += ext_rates_no;
594                 index += 2;
595                 for (i = 0; i < (param->supp_rates[0] - *rates_no); i++)
596                         param->supp_rates[*rates_no + i + 1] = ies[index + i];
597
598                 index += ext_rates_no;
599         } else if (ies[index] == WLAN_EID_HT_CAPABILITY) {
600                 param->ht_capable = true;
601                 index += ies[index + 1] + 2;
602         } else if ((ies[index] == WLAN_EID_VENDOR_SPECIFIC) &&
603                    (ies[index + 2] == 0x00) && (ies[index + 3] == 0x50) &&
604                    (ies[index + 4] == 0xF2) && (ies[index + 5] == 0x02) &&
605                    ((ies[index + 6] == 0x00) || (ies[index + 6] == 0x01)) &&
606                    (ies[index + 7] == 0x01)) {
607                 param->wmm_cap = true;
608
609                 if (ies[index + 8] & BIT(7))
610                         param->uapsd_cap = true;
611                 index += ies[index + 1] + 2;
612         } else if ((ies[index] == WLAN_EID_VENDOR_SPECIFIC) &&
613                  (ies[index + 2] == 0x50) && (ies[index + 3] == 0x6f) &&
614                  (ies[index + 4] == 0x9a) &&
615                  (ies[index + 5] == 0x09) && (ies[index + 6] == 0x0c)) {
616                 u16 p2p_cnt;
617
618                 param->tsf = tsf_lo;
619                 param->noa_enabled = 1;
620                 param->idx = ies[index + 9];
621
622                 if (ies[index + 10] & BIT(7)) {
623                         param->opp_enabled = 1;
624                         param->ct_window = ies[index + 10];
625                 } else {
626                         param->opp_enabled = 0;
627                 }
628
629                 param->cnt = ies[index + 11];
630                 p2p_cnt = index + 12;
631
632                 memcpy(param->duration, ies + p2p_cnt, 4);
633                 p2p_cnt += 4;
634
635                 memcpy(param->interval, ies + p2p_cnt, 4);
636                 p2p_cnt += 4;
637
638                 memcpy(param->start_time, ies + p2p_cnt, 4);
639
640                 index += ies[index + 1] + 2;
641         } else if ((ies[index] == WLAN_EID_RSN) ||
642                  ((ies[index] == WLAN_EID_VENDOR_SPECIFIC) &&
643                   (ies[index + 2] == 0x00) &&
644                   (ies[index + 3] == 0x50) && (ies[index + 4] == 0xF2) &&
645                   (ies[index + 5] == 0x01))) {
646                 u16 rsn_idx = index;
647
648                 if (ies[rsn_idx] == WLAN_EID_RSN) {
649                         param->mode_802_11i = 2;
650                 } else {
651                         if (param->mode_802_11i == 0)
652                                 param->mode_802_11i = 1;
653                         rsn_idx += 4;
654                 }
655
656                 rsn_idx += 7;
657                 param->rsn_grp_policy = ies[rsn_idx];
658                 rsn_idx++;
659                 offset = ies[rsn_idx] * 4;
660                 pcipher_cnt = (ies[rsn_idx] > 3) ? 3 : ies[rsn_idx];
661                 rsn_idx += 2;
662
663                 i = *pcipher_tc;
664                 j = 0;
665                 for (; i < (pcipher_cnt + *pcipher_tc) && i < 3; i++, j++) {
666                         u8 *policy =  &param->rsn_pcip_policy[i];
667
668                         *policy = ies[rsn_idx + ((j + 1) * 4) - 1];
669                 }
670
671                 *pcipher_tc += pcipher_cnt;
672                 rsn_idx += offset;
673
674                 offset = ies[rsn_idx] * 4;
675
676                 auth_cnt = (ies[rsn_idx] > 3) ? 3 : ies[rsn_idx];
677                 rsn_idx += 2;
678                 i = *auth_total_cnt;
679                 j = 0;
680                 for (; i < (*auth_total_cnt + auth_cnt); i++, j++) {
681                         u8 *policy =  &param->rsn_auth_policy[i];
682
683                         *policy = ies[rsn_idx + ((j + 1) * 4) - 1];
684                 }
685
686                 *auth_total_cnt += auth_cnt;
687                 rsn_idx += offset;
688
689                 if (ies[index] == WLAN_EID_RSN) {
690                         param->rsn_cap[0] = ies[rsn_idx];
691                         param->rsn_cap[1] = ies[rsn_idx + 1];
692                         rsn_idx += 2;
693                 }
694                 param->rsn_found = true;
695                 index += ies[index + 1] + 2;
696         } else {
697                 index += ies[index + 1] + 2;
698         }
699
700         *out_index = index;
701 }
702
703 static void *host_int_parse_join_bss_param(struct network_info *info)
704 {
705         struct join_bss_param *param;
706         u16 index = 0;
707         u8 rates_no = 0;
708         u8 pcipher_total_cnt = 0;
709         u8 auth_total_cnt = 0;
710
711         param = kzalloc(sizeof(*param), GFP_KERNEL);
712         if (!param)
713                 return NULL;
714
715         param->dtim_period = info->dtim_period;
716         param->beacon_period = info->beacon_period;
717         param->cap_info = info->cap_info;
718         memcpy(param->bssid, info->bssid, 6);
719         memcpy((u8 *)param->ssid, info->ssid, info->ssid_len + 1);
720         param->ssid_len = info->ssid_len;
721         memset(param->rsn_pcip_policy, 0xFF, 3);
722         memset(param->rsn_auth_policy, 0xFF, 3);
723
724         while (index < info->ies_len)
725                 host_int_fill_join_bss_param(param, info->ies, &index,
726                                              &pcipher_total_cnt,
727                                              &auth_total_cnt, info->tsf_lo,
728                                              &rates_no);
729
730         return (void *)param;
731 }
732
733 static inline u8 *get_bssid(struct ieee80211_mgmt *mgmt)
734 {
735         if (ieee80211_has_fromds(mgmt->frame_control))
736                 return mgmt->sa;
737         else if (ieee80211_has_tods(mgmt->frame_control))
738                 return mgmt->da;
739         else
740                 return mgmt->bssid;
741 }
742
743 static s32 wilc_parse_network_info(u8 *msg_buffer,
744                                    struct network_info **ret_network_info)
745 {
746         struct network_info *info;
747         struct ieee80211_mgmt *mgt;
748         u8 *wid_val, *msa, *ies;
749         u16 wid_len, rx_len, ies_len;
750         u8 msg_type;
751         size_t offset;
752         const u8 *ch_elm, *tim_elm, *ssid_elm;
753
754         msg_type = msg_buffer[0];
755         if ('N' != msg_type)
756                 return -EFAULT;
757
758         wid_len = get_unaligned_le16(&msg_buffer[6]);
759         wid_val = &msg_buffer[8];
760
761         info = kzalloc(sizeof(*info), GFP_KERNEL);
762         if (!info)
763                 return -ENOMEM;
764
765         info->rssi = wid_val[0];
766
767         msa = &wid_val[1];
768         mgt = (struct ieee80211_mgmt *)&wid_val[1];
769         rx_len = wid_len - 1;
770
771         if (ieee80211_is_probe_resp(mgt->frame_control)) {
772                 info->cap_info = le16_to_cpu(mgt->u.probe_resp.capab_info);
773                 info->beacon_period = le16_to_cpu(mgt->u.probe_resp.beacon_int);
774                 info->tsf = le64_to_cpu(mgt->u.probe_resp.timestamp);
775                 info->tsf_lo = (u32)info->tsf;
776                 offset = offsetof(struct ieee80211_mgmt, u.probe_resp.variable);
777         } else if (ieee80211_is_beacon(mgt->frame_control)) {
778                 info->cap_info = le16_to_cpu(mgt->u.beacon.capab_info);
779                 info->beacon_period = le16_to_cpu(mgt->u.beacon.beacon_int);
780                 info->tsf = le64_to_cpu(mgt->u.beacon.timestamp);
781                 info->tsf_lo = (u32)info->tsf;
782                 offset = offsetof(struct ieee80211_mgmt, u.beacon.variable);
783         } else {
784                 /* only process probe response and beacon frame */
785                 kfree(info);
786                 return -EIO;
787         }
788
789         ether_addr_copy(info->bssid, get_bssid(mgt));
790
791         ies = mgt->u.beacon.variable;
792         ies_len = rx_len - offset;
793         if (ies_len <= 0) {
794                 kfree(info);
795                 return -EIO;
796         }
797
798         info->ies = kmemdup(ies, ies_len, GFP_KERNEL);
799         if (!info->ies) {
800                 kfree(info);
801                 return -ENOMEM;
802         }
803
804         info->ies_len = ies_len;
805
806         ssid_elm = cfg80211_find_ie(WLAN_EID_SSID, ies, ies_len);
807         if (ssid_elm) {
808                 info->ssid_len = ssid_elm[1];
809                 if (info->ssid_len <= IEEE80211_MAX_SSID_LEN)
810                         memcpy(info->ssid, ssid_elm + 2, info->ssid_len);
811                 else
812                         info->ssid_len = 0;
813         }
814
815         ch_elm = cfg80211_find_ie(WLAN_EID_DS_PARAMS, ies, ies_len);
816         if (ch_elm && ch_elm[1] > 0)
817                 info->ch = ch_elm[2];
818
819         tim_elm = cfg80211_find_ie(WLAN_EID_TIM, ies, ies_len);
820         if (tim_elm && tim_elm[1] >= 2)
821                 info->dtim_period = tim_elm[3];
822
823         *ret_network_info = info;
824
825         return 0;
826 }
827
828 static void handle_rcvd_ntwrk_info(struct work_struct *work)
829 {
830         struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
831         struct wilc_vif *vif = msg->vif;
832         struct rcvd_net_info *rcvd_info = &msg->body.net_info;
833         u32 i;
834         bool found;
835         struct network_info *info = NULL;
836         void *params;
837         struct host_if_drv *hif_drv = vif->hif_drv;
838         struct user_scan_req *scan_req = &hif_drv->usr_scan_req;
839
840         found = true;
841
842         if (!scan_req->scan_result)
843                 goto done;
844
845         wilc_parse_network_info(rcvd_info->buffer, &info);
846         if (!info || !scan_req->scan_result) {
847                 netdev_err(vif->ndev, "%s: info or scan result NULL\n",
848                            __func__);
849                 goto done;
850         }
851
852         for (i = 0; i < scan_req->ch_cnt; i++) {
853                 if (memcmp(scan_req->net_info[i].bssid, info->bssid, 6) == 0) {
854                         if (info->rssi <= scan_req->net_info[i].rssi) {
855                                 goto done;
856                         } else {
857                                 scan_req->net_info[i].rssi = info->rssi;
858                                 found = false;
859                                 break;
860                         }
861                 }
862         }
863
864         if (found) {
865                 if (scan_req->ch_cnt < MAX_NUM_SCANNED_NETWORKS) {
866                         scan_req->net_info[scan_req->ch_cnt].rssi = info->rssi;
867
868                         memcpy(scan_req->net_info[scan_req->ch_cnt].bssid,
869                                info->bssid, 6);
870
871                         scan_req->ch_cnt++;
872
873                         info->new_network = true;
874                         params = host_int_parse_join_bss_param(info);
875
876                         scan_req->scan_result(SCAN_EVENT_NETWORK_FOUND, info,
877                                                scan_req->arg, params);
878                 }
879         } else {
880                 info->new_network = false;
881                 scan_req->scan_result(SCAN_EVENT_NETWORK_FOUND, info,
882                                       scan_req->arg, NULL);
883         }
884
885 done:
886         kfree(rcvd_info->buffer);
887         rcvd_info->buffer = NULL;
888
889         if (info) {
890                 kfree(info->ies);
891                 kfree(info);
892         }
893
894         kfree(msg);
895 }
896
897 static void host_int_get_assoc_res_info(struct wilc_vif *vif,
898                                         u8 *assoc_resp_info,
899                                         u32 max_assoc_resp_info_len,
900                                         u32 *rcvd_assoc_resp_info_len)
901 {
902         int result;
903         struct wid wid;
904
905         wid.id = WID_ASSOC_RES_INFO;
906         wid.type = WID_STR;
907         wid.val = assoc_resp_info;
908         wid.size = max_assoc_resp_info_len;
909
910         result = wilc_send_config_pkt(vif, WILC_GET_CFG, &wid, 1,
911                                       wilc_get_vif_idx(vif));
912         if (result) {
913                 *rcvd_assoc_resp_info_len = 0;
914                 netdev_err(vif->ndev, "Failed to send association response\n");
915                 return;
916         }
917
918         *rcvd_assoc_resp_info_len = wid.size;
919 }
920
921 static inline void host_int_free_user_conn_req(struct host_if_drv *hif_drv)
922 {
923         hif_drv->usr_conn_req.ssid_len = 0;
924         kfree(hif_drv->usr_conn_req.ssid);
925         hif_drv->usr_conn_req.ssid = NULL;
926         kfree(hif_drv->usr_conn_req.bssid);
927         hif_drv->usr_conn_req.bssid = NULL;
928         hif_drv->usr_conn_req.ies_len = 0;
929         kfree(hif_drv->usr_conn_req.ies);
930         hif_drv->usr_conn_req.ies = NULL;
931 }
932
933 static s32 wilc_parse_assoc_resp_info(u8 *buffer, u32 buffer_len,
934                                       struct connect_info *ret_conn_info)
935 {
936         u8 *ies;
937         u16 ies_len;
938         struct assoc_resp *res = (struct assoc_resp *)buffer;
939
940         ret_conn_info->status = le16_to_cpu(res->status_code);
941         if (ret_conn_info->status == WLAN_STATUS_SUCCESS) {
942                 ies = &buffer[sizeof(*res)];
943                 ies_len = buffer_len - sizeof(*res);
944
945                 ret_conn_info->resp_ies = kmemdup(ies, ies_len, GFP_KERNEL);
946                 if (!ret_conn_info->resp_ies)
947                         return -ENOMEM;
948
949                 ret_conn_info->resp_ies_len = ies_len;
950         }
951
952         return 0;
953 }
954
955 static inline void host_int_parse_assoc_resp_info(struct wilc_vif *vif,
956                                                   u8 mac_status)
957 {
958         struct connect_info conn_info;
959         struct host_if_drv *hif_drv = vif->hif_drv;
960
961         memset(&conn_info, 0, sizeof(struct connect_info));
962
963         if (mac_status == WILC_MAC_STATUS_CONNECTED) {
964                 u32 assoc_resp_info_len;
965
966                 memset(hif_drv->assoc_resp, 0, WILC_MAX_ASSOC_RESP_FRAME_SIZE);
967
968                 host_int_get_assoc_res_info(vif, hif_drv->assoc_resp,
969                                             WILC_MAX_ASSOC_RESP_FRAME_SIZE,
970                                             &assoc_resp_info_len);
971
972                 if (assoc_resp_info_len != 0) {
973                         s32 err = 0;
974
975                         err = wilc_parse_assoc_resp_info(hif_drv->assoc_resp,
976                                                          assoc_resp_info_len,
977                                                          &conn_info);
978                         if (err)
979                                 netdev_err(vif->ndev,
980                                            "wilc_parse_assoc_resp_info() returned error %d\n",
981                                            err);
982                 }
983         }
984
985         if (hif_drv->usr_conn_req.bssid) {
986                 memcpy(conn_info.bssid, hif_drv->usr_conn_req.bssid, 6);
987
988                 if (mac_status == WILC_MAC_STATUS_CONNECTED &&
989                     conn_info.status == WLAN_STATUS_SUCCESS) {
990                         memcpy(hif_drv->assoc_bssid,
991                                hif_drv->usr_conn_req.bssid, ETH_ALEN);
992                 }
993         }
994
995         if (hif_drv->usr_conn_req.ies) {
996                 conn_info.req_ies = kmemdup(hif_drv->usr_conn_req.ies,
997                                             hif_drv->usr_conn_req.ies_len,
998                                             GFP_KERNEL);
999                 if (conn_info.req_ies)
1000                         conn_info.req_ies_len = hif_drv->usr_conn_req.ies_len;
1001         }
1002
1003         del_timer(&hif_drv->connect_timer);
1004         hif_drv->usr_conn_req.conn_result(CONN_DISCONN_EVENT_CONN_RESP,
1005                                           &conn_info, mac_status, NULL,
1006                                           hif_drv->usr_conn_req.arg);
1007
1008         if (mac_status == WILC_MAC_STATUS_CONNECTED &&
1009             conn_info.status == WLAN_STATUS_SUCCESS) {
1010                 wilc_set_power_mgmt(vif, 0, 0);
1011
1012                 hif_drv->hif_state = HOST_IF_CONNECTED;
1013
1014                 vif->obtaining_ip = true;
1015                 mod_timer(&vif->during_ip_timer,
1016                           jiffies + msecs_to_jiffies(10000));
1017         } else {
1018                 hif_drv->hif_state = HOST_IF_IDLE;
1019         }
1020
1021         kfree(conn_info.resp_ies);
1022         conn_info.resp_ies = NULL;
1023
1024         kfree(conn_info.req_ies);
1025         conn_info.req_ies = NULL;
1026         host_int_free_user_conn_req(hif_drv);
1027 }
1028
1029 static inline void host_int_handle_disconnect(struct wilc_vif *vif)
1030 {
1031         struct disconnect_info disconn_info;
1032         struct host_if_drv *hif_drv = vif->hif_drv;
1033         wilc_connect_result conn_result = hif_drv->usr_conn_req.conn_result;
1034
1035         memset(&disconn_info, 0, sizeof(struct disconnect_info));
1036
1037         if (hif_drv->usr_scan_req.scan_result) {
1038                 del_timer(&hif_drv->scan_timer);
1039                 handle_scan_done(vif, SCAN_EVENT_ABORTED);
1040         }
1041
1042         disconn_info.reason = 0;
1043         disconn_info.ie = NULL;
1044         disconn_info.ie_len = 0;
1045
1046         if (conn_result) {
1047                 vif->obtaining_ip = false;
1048                 wilc_set_power_mgmt(vif, 0, 0);
1049
1050                 conn_result(CONN_DISCONN_EVENT_DISCONN_NOTIF, NULL, 0,
1051                             &disconn_info, hif_drv->usr_conn_req.arg);
1052         } else {
1053                 netdev_err(vif->ndev, "%s: conn_result is NULL\n", __func__);
1054         }
1055
1056         eth_zero_addr(hif_drv->assoc_bssid);
1057
1058         host_int_free_user_conn_req(hif_drv);
1059         hif_drv->hif_state = HOST_IF_IDLE;
1060 }
1061
1062 static void handle_rcvd_gnrl_async_info(struct work_struct *work)
1063 {
1064         struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
1065         struct wilc_vif *vif = msg->vif;
1066         struct rcvd_async_info *rcvd_info = &msg->body.async_info;
1067         u8 msg_type;
1068         u8 mac_status;
1069         struct host_if_drv *hif_drv = vif->hif_drv;
1070
1071         if (!rcvd_info->buffer) {
1072                 netdev_err(vif->ndev, "%s: buffer is NULL\n", __func__);
1073                 goto free_msg;
1074         }
1075
1076         if (!hif_drv) {
1077                 netdev_err(vif->ndev, "%s: hif driver is NULL\n", __func__);
1078                 goto free_rcvd_info;
1079         }
1080
1081         if (hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP ||
1082             hif_drv->hif_state == HOST_IF_CONNECTED ||
1083             hif_drv->usr_scan_req.scan_result) {
1084                 if (!hif_drv->usr_conn_req.conn_result) {
1085                         netdev_err(vif->ndev, "%s: conn_result is NULL\n",
1086                                    __func__);
1087                         goto free_rcvd_info;
1088                 }
1089
1090                 msg_type = rcvd_info->buffer[0];
1091
1092                 if ('I' != msg_type) {
1093                         netdev_err(vif->ndev, "Received Message incorrect.\n");
1094                         goto free_rcvd_info;
1095                 }
1096
1097                 mac_status  = rcvd_info->buffer[7];
1098                 if (hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP) {
1099                         host_int_parse_assoc_resp_info(vif, mac_status);
1100                 } else if ((mac_status == WILC_MAC_STATUS_DISCONNECTED) &&
1101                            (hif_drv->hif_state == HOST_IF_CONNECTED)) {
1102                         host_int_handle_disconnect(vif);
1103                 } else if ((mac_status == WILC_MAC_STATUS_DISCONNECTED) &&
1104                            (hif_drv->usr_scan_req.scan_result)) {
1105                         del_timer(&hif_drv->scan_timer);
1106                         if (hif_drv->usr_scan_req.scan_result)
1107                                 handle_scan_done(vif, SCAN_EVENT_ABORTED);
1108                 }
1109         }
1110
1111 free_rcvd_info:
1112         kfree(rcvd_info->buffer);
1113         rcvd_info->buffer = NULL;
1114
1115 free_msg:
1116         kfree(msg);
1117 }
1118
1119 int wilc_disconnect(struct wilc_vif *vif)
1120 {
1121         struct wid wid;
1122         struct host_if_drv *hif_drv = vif->hif_drv;
1123         struct disconnect_info disconn_info;
1124         struct user_scan_req *scan_req;
1125         struct user_conn_req *conn_req;
1126         int result;
1127         u16 dummy_reason_code = 0;
1128
1129         wid.id = WID_DISCONNECT;
1130         wid.type = WID_CHAR;
1131         wid.val = (s8 *)&dummy_reason_code;
1132         wid.size = sizeof(char);
1133
1134         vif->obtaining_ip = false;
1135         wilc_set_power_mgmt(vif, 0, 0);
1136
1137         result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
1138                                       wilc_get_vif_idx(vif));
1139         if (result) {
1140                 netdev_err(vif->ndev, "Failed to send dissconect\n");
1141                 return result;
1142         }
1143
1144         memset(&disconn_info, 0, sizeof(struct disconnect_info));
1145
1146         disconn_info.reason = 0;
1147         disconn_info.ie = NULL;
1148         disconn_info.ie_len = 0;
1149         scan_req = &hif_drv->usr_scan_req;
1150         conn_req = &hif_drv->usr_conn_req;
1151
1152         if (scan_req->scan_result) {
1153                 del_timer(&hif_drv->scan_timer);
1154                 scan_req->scan_result(SCAN_EVENT_ABORTED, NULL, scan_req->arg,
1155                                       NULL);
1156                 scan_req->scan_result = NULL;
1157         }
1158
1159         if (conn_req->conn_result) {
1160                 if (hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP)
1161                         del_timer(&hif_drv->connect_timer);
1162
1163                 conn_req->conn_result(CONN_DISCONN_EVENT_DISCONN_NOTIF, NULL,
1164                                       0, &disconn_info, conn_req->arg);
1165         } else {
1166                 netdev_err(vif->ndev, "%s: conn_result is NULL\n", __func__);
1167         }
1168
1169         hif_drv->hif_state = HOST_IF_IDLE;
1170
1171         eth_zero_addr(hif_drv->assoc_bssid);
1172
1173         conn_req->ssid_len = 0;
1174         kfree(conn_req->ssid);
1175         conn_req->ssid = NULL;
1176         kfree(conn_req->bssid);
1177         conn_req->bssid = NULL;
1178         conn_req->ies_len = 0;
1179         kfree(conn_req->ies);
1180         conn_req->ies = NULL;
1181
1182         return 0;
1183 }
1184
1185 void wilc_resolve_disconnect_aberration(struct wilc_vif *vif)
1186 {
1187         if (!vif->hif_drv)
1188                 return;
1189         if (vif->hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP ||
1190             vif->hif_drv->hif_state == HOST_IF_CONNECTING)
1191                 wilc_disconnect(vif);
1192 }
1193
1194 int wilc_get_statistics(struct wilc_vif *vif, struct rf_info *stats)
1195 {
1196         struct wid wid_list[5];
1197         u32 wid_cnt = 0, result;
1198
1199         wid_list[wid_cnt].id = WID_LINKSPEED;
1200         wid_list[wid_cnt].type = WID_CHAR;
1201         wid_list[wid_cnt].size = sizeof(char);
1202         wid_list[wid_cnt].val = (s8 *)&stats->link_speed;
1203         wid_cnt++;
1204
1205         wid_list[wid_cnt].id = WID_RSSI;
1206         wid_list[wid_cnt].type = WID_CHAR;
1207         wid_list[wid_cnt].size = sizeof(char);
1208         wid_list[wid_cnt].val = (s8 *)&stats->rssi;
1209         wid_cnt++;
1210
1211         wid_list[wid_cnt].id = WID_SUCCESS_FRAME_COUNT;
1212         wid_list[wid_cnt].type = WID_INT;
1213         wid_list[wid_cnt].size = sizeof(u32);
1214         wid_list[wid_cnt].val = (s8 *)&stats->tx_cnt;
1215         wid_cnt++;
1216
1217         wid_list[wid_cnt].id = WID_RECEIVED_FRAGMENT_COUNT;
1218         wid_list[wid_cnt].type = WID_INT;
1219         wid_list[wid_cnt].size = sizeof(u32);
1220         wid_list[wid_cnt].val = (s8 *)&stats->rx_cnt;
1221         wid_cnt++;
1222
1223         wid_list[wid_cnt].id = WID_FAILED_COUNT;
1224         wid_list[wid_cnt].type = WID_INT;
1225         wid_list[wid_cnt].size = sizeof(u32);
1226         wid_list[wid_cnt].val = (s8 *)&stats->tx_fail_cnt;
1227         wid_cnt++;
1228
1229         result = wilc_send_config_pkt(vif, WILC_GET_CFG, wid_list,
1230                                       wid_cnt,
1231                                       wilc_get_vif_idx(vif));
1232
1233         if (result) {
1234                 netdev_err(vif->ndev, "Failed to send scan parameters\n");
1235                 return result;
1236         }
1237
1238         if (stats->link_speed > TCP_ACK_FILTER_LINK_SPEED_THRESH &&
1239             stats->link_speed != DEFAULT_LINK_SPEED)
1240                 wilc_enable_tcp_ack_filter(vif, true);
1241         else if (stats->link_speed != DEFAULT_LINK_SPEED)
1242                 wilc_enable_tcp_ack_filter(vif, false);
1243
1244         return result;
1245 }
1246
1247 static void handle_get_statistics(struct work_struct *work)
1248 {
1249         struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
1250         struct wilc_vif *vif = msg->vif;
1251         struct rf_info *stats = (struct rf_info *)msg->body.data;
1252
1253         wilc_get_statistics(vif, stats);
1254
1255         kfree(msg);
1256 }
1257
1258 static void wilc_hif_pack_sta_param(u8 *cur_byte, const u8 *mac,
1259                                     struct station_parameters *params)
1260 {
1261         ether_addr_copy(cur_byte, mac);
1262         cur_byte += ETH_ALEN;
1263
1264         put_unaligned_le16(params->aid, cur_byte);
1265         cur_byte += 2;
1266
1267         *cur_byte++ = params->supported_rates_len;
1268         if (params->supported_rates_len > 0)
1269                 memcpy(cur_byte, params->supported_rates,
1270                        params->supported_rates_len);
1271         cur_byte += params->supported_rates_len;
1272
1273         if (params->ht_capa) {
1274                 *cur_byte++ = true;
1275                 memcpy(cur_byte, &params->ht_capa,
1276                        sizeof(struct ieee80211_ht_cap));
1277         } else {
1278                 *cur_byte++ = false;
1279         }
1280         cur_byte += sizeof(struct ieee80211_ht_cap);
1281
1282         put_unaligned_le16(params->sta_flags_mask, cur_byte);
1283         cur_byte += 2;
1284         put_unaligned_le16(params->sta_flags_set, cur_byte);
1285 }
1286
1287 static int handle_remain_on_chan(struct wilc_vif *vif,
1288                                  struct remain_ch *hif_remain_ch)
1289 {
1290         int result;
1291         u8 remain_on_chan_flag;
1292         struct wid wid;
1293         struct host_if_drv *hif_drv = vif->hif_drv;
1294
1295         if (!hif_drv->remain_on_ch_pending) {
1296                 hif_drv->remain_on_ch.arg = hif_remain_ch->arg;
1297                 hif_drv->remain_on_ch.expired = hif_remain_ch->expired;
1298                 hif_drv->remain_on_ch.ready = hif_remain_ch->ready;
1299                 hif_drv->remain_on_ch.ch = hif_remain_ch->ch;
1300                 hif_drv->remain_on_ch.id = hif_remain_ch->id;
1301         } else {
1302                 hif_remain_ch->ch = hif_drv->remain_on_ch.ch;
1303         }
1304
1305         if (hif_drv->usr_scan_req.scan_result) {
1306                 hif_drv->remain_on_ch_pending = 1;
1307                 result = -EBUSY;
1308                 goto error;
1309         }
1310         if (hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP) {
1311                 result = -EBUSY;
1312                 goto error;
1313         }
1314
1315         if (vif->obtaining_ip || vif->connecting) {
1316                 result = -EBUSY;
1317                 goto error;
1318         }
1319
1320         remain_on_chan_flag = true;
1321         wid.id = WID_REMAIN_ON_CHAN;
1322         wid.type = WID_STR;
1323         wid.size = 2;
1324         wid.val = kmalloc(wid.size, GFP_KERNEL);
1325         if (!wid.val) {
1326                 result = -ENOMEM;
1327                 goto error;
1328         }
1329
1330         wid.val[0] = remain_on_chan_flag;
1331         wid.val[1] = (s8)hif_remain_ch->ch;
1332
1333         result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
1334                                       wilc_get_vif_idx(vif));
1335         kfree(wid.val);
1336         if (result != 0)
1337                 netdev_err(vif->ndev, "Failed to set remain on channel\n");
1338
1339 error:
1340         hif_drv->remain_on_ch_timer_vif = vif;
1341         mod_timer(&hif_drv->remain_on_ch_timer,
1342                   jiffies + msecs_to_jiffies(hif_remain_ch->duration));
1343
1344         if (hif_drv->remain_on_ch.ready)
1345                 hif_drv->remain_on_ch.ready(hif_drv->remain_on_ch.arg);
1346
1347         if (hif_drv->remain_on_ch_pending)
1348                 hif_drv->remain_on_ch_pending = 0;
1349
1350         return result;
1351 }
1352
1353 static void handle_listen_state_expired(struct work_struct *work)
1354 {
1355         struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
1356         struct wilc_vif *vif = msg->vif;
1357         struct remain_ch *hif_remain_ch = &msg->body.remain_on_ch;
1358         u8 remain_on_chan_flag;
1359         struct wid wid;
1360         int result;
1361         struct host_if_drv *hif_drv = vif->hif_drv;
1362         struct wilc_priv *priv = wdev_priv(vif->ndev->ieee80211_ptr);
1363
1364         if (priv->p2p_listen_state) {
1365                 remain_on_chan_flag = false;
1366                 wid.id = WID_REMAIN_ON_CHAN;
1367                 wid.type = WID_STR;
1368                 wid.size = 2;
1369                 wid.val = kmalloc(wid.size, GFP_KERNEL);
1370
1371                 if (!wid.val)
1372                         goto free_msg;
1373
1374                 wid.val[0] = remain_on_chan_flag;
1375                 wid.val[1] = FALSE_FRMWR_CHANNEL;
1376
1377                 result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
1378                                               wilc_get_vif_idx(vif));
1379                 kfree(wid.val);
1380                 if (result != 0) {
1381                         netdev_err(vif->ndev, "Failed to set remain channel\n");
1382                         goto free_msg;
1383                 }
1384
1385                 if (hif_drv->remain_on_ch.expired) {
1386                         hif_drv->remain_on_ch.expired(hif_drv->remain_on_ch.arg,
1387                                                       hif_remain_ch->id);
1388                 }
1389         } else {
1390                 netdev_dbg(vif->ndev, "Not in listen state\n");
1391         }
1392
1393 free_msg:
1394         kfree(msg);
1395 }
1396
1397 static void listen_timer_cb(struct timer_list *t)
1398 {
1399         struct host_if_drv *hif_drv = from_timer(hif_drv, t,
1400                                                       remain_on_ch_timer);
1401         struct wilc_vif *vif = hif_drv->remain_on_ch_timer_vif;
1402         int result;
1403         struct host_if_msg *msg;
1404
1405         del_timer(&vif->hif_drv->remain_on_ch_timer);
1406
1407         msg = wilc_alloc_work(vif, handle_listen_state_expired, false);
1408         if (IS_ERR(msg))
1409                 return;
1410
1411         msg->body.remain_on_ch.id = vif->hif_drv->remain_on_ch.id;
1412
1413         result = wilc_enqueue_work(msg);
1414         if (result) {
1415                 netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__);
1416                 kfree(msg);
1417         }
1418 }
1419
1420 static void handle_set_mcast_filter(struct work_struct *work)
1421 {
1422         struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
1423         struct wilc_vif *vif = msg->vif;
1424         struct set_multicast *hif_set_mc = &msg->body.multicast_info;
1425         int result;
1426         struct wid wid;
1427         u8 *cur_byte;
1428
1429         wid.id = WID_SETUP_MULTICAST_FILTER;
1430         wid.type = WID_BIN;
1431         wid.size = sizeof(struct set_multicast) + (hif_set_mc->cnt * ETH_ALEN);
1432         wid.val = kmalloc(wid.size, GFP_KERNEL);
1433         if (!wid.val)
1434                 goto error;
1435
1436         cur_byte = wid.val;
1437         *cur_byte++ = (hif_set_mc->enabled & 0xFF);
1438         *cur_byte++ = 0;
1439         *cur_byte++ = 0;
1440         *cur_byte++ = 0;
1441
1442         *cur_byte++ = (hif_set_mc->cnt & 0xFF);
1443         *cur_byte++ = ((hif_set_mc->cnt >> 8) & 0xFF);
1444         *cur_byte++ = ((hif_set_mc->cnt >> 16) & 0xFF);
1445         *cur_byte++ = ((hif_set_mc->cnt >> 24) & 0xFF);
1446
1447         if (hif_set_mc->cnt > 0 && hif_set_mc->mc_list)
1448                 memcpy(cur_byte, hif_set_mc->mc_list,
1449                        ((hif_set_mc->cnt) * ETH_ALEN));
1450
1451         result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
1452                                       wilc_get_vif_idx(vif));
1453         if (result)
1454                 netdev_err(vif->ndev, "Failed to send setup multicast\n");
1455
1456 error:
1457         kfree(hif_set_mc->mc_list);
1458         kfree(wid.val);
1459         kfree(msg);
1460 }
1461
1462 static void handle_scan_timer(struct work_struct *work)
1463 {
1464         struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
1465
1466         handle_scan_done(msg->vif, SCAN_EVENT_ABORTED);
1467         kfree(msg);
1468 }
1469
1470 static void handle_scan_complete(struct work_struct *work)
1471 {
1472         struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
1473         struct wilc *wilc = msg->vif->wilc;
1474
1475         del_timer(&msg->vif->hif_drv->scan_timer);
1476
1477         if (!wilc_wlan_get_num_conn_ifcs(wilc))
1478                 wilc_chip_sleep_manually(wilc);
1479
1480         handle_scan_done(msg->vif, SCAN_EVENT_DONE);
1481
1482         if (msg->vif->hif_drv->remain_on_ch_pending)
1483                 handle_remain_on_chan(msg->vif,
1484                                       &msg->vif->hif_drv->remain_on_ch);
1485         kfree(msg);
1486 }
1487
1488 static void timer_scan_cb(struct timer_list *t)
1489 {
1490         struct host_if_drv *hif_drv = from_timer(hif_drv, t, scan_timer);
1491         struct wilc_vif *vif = hif_drv->scan_timer_vif;
1492         struct host_if_msg *msg;
1493         int result;
1494
1495         msg = wilc_alloc_work(vif, handle_scan_timer, false);
1496         if (IS_ERR(msg))
1497                 return;
1498
1499         result = wilc_enqueue_work(msg);
1500         if (result)
1501                 kfree(msg);
1502 }
1503
1504 static void timer_connect_cb(struct timer_list *t)
1505 {
1506         struct host_if_drv *hif_drv = from_timer(hif_drv, t,
1507                                                       connect_timer);
1508         struct wilc_vif *vif = hif_drv->connect_timer_vif;
1509         struct host_if_msg *msg;
1510         int result;
1511
1512         msg = wilc_alloc_work(vif, handle_connect_timeout, false);
1513         if (IS_ERR(msg))
1514                 return;
1515
1516         result = wilc_enqueue_work(msg);
1517         if (result)
1518                 kfree(msg);
1519 }
1520
1521 int wilc_remove_wep_key(struct wilc_vif *vif, u8 index)
1522 {
1523         struct wid wid;
1524         int result;
1525
1526         wid.id = WID_REMOVE_WEP_KEY;
1527         wid.type = WID_STR;
1528         wid.size = sizeof(char);
1529         wid.val = &index;
1530
1531         result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
1532                                       wilc_get_vif_idx(vif));
1533         if (result)
1534                 netdev_err(vif->ndev,
1535                            "Failed to send remove wep key config packet\n");
1536         return result;
1537 }
1538
1539 int wilc_set_wep_default_keyid(struct wilc_vif *vif, u8 index)
1540 {
1541         struct wid wid;
1542         int result;
1543
1544         wid.id = WID_KEY_ID;
1545         wid.type = WID_CHAR;
1546         wid.size = sizeof(char);
1547         wid.val = &index;
1548         result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
1549                                       wilc_get_vif_idx(vif));
1550         if (result)
1551                 netdev_err(vif->ndev,
1552                            "Failed to send wep default key config packet\n");
1553
1554         return result;
1555 }
1556
1557 int wilc_add_wep_key_bss_sta(struct wilc_vif *vif, const u8 *key, u8 len,
1558                              u8 index)
1559 {
1560         struct wid wid;
1561         int result;
1562         struct wilc_wep_key *wep_key;
1563
1564         wid.id = WID_ADD_WEP_KEY;
1565         wid.type = WID_STR;
1566         wid.size = sizeof(*wep_key) + len;
1567         wep_key = kzalloc(wid.size, GFP_KERNEL);
1568         if (!wep_key)
1569                 return -ENOMEM;
1570
1571         wid.val = (u8 *)wep_key;
1572
1573         wep_key->index = index;
1574         wep_key->key_len = len;
1575         memcpy(wep_key->key, key, len);
1576
1577         result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
1578                                       wilc_get_vif_idx(vif));
1579         if (result)
1580                 netdev_err(vif->ndev,
1581                            "Failed to add wep key config packet\n");
1582
1583         kfree(wep_key);
1584         return result;
1585 }
1586
1587 int wilc_add_wep_key_bss_ap(struct wilc_vif *vif, const u8 *key, u8 len,
1588                             u8 index, u8 mode, enum authtype auth_type)
1589 {
1590         struct wid wid_list[3];
1591         int result;
1592         struct wilc_wep_key *wep_key;
1593
1594         wid_list[0].id = WID_11I_MODE;
1595         wid_list[0].type = WID_CHAR;
1596         wid_list[0].size = sizeof(char);
1597         wid_list[0].val = &mode;
1598
1599         wid_list[1].id = WID_AUTH_TYPE;
1600         wid_list[1].type = WID_CHAR;
1601         wid_list[1].size = sizeof(char);
1602         wid_list[1].val = (s8 *)&auth_type;
1603
1604         wid_list[2].id = WID_WEP_KEY_VALUE;
1605         wid_list[2].type = WID_STR;
1606         wid_list[2].size = sizeof(*wep_key) + len;
1607         wep_key = kzalloc(wid_list[2].size, GFP_KERNEL);
1608         if (!wep_key)
1609                 return -ENOMEM;
1610
1611         wid_list[2].val = (u8 *)wep_key;
1612
1613         wep_key->index = index;
1614         wep_key->key_len = len;
1615         memcpy(wep_key->key, key, len);
1616         result = wilc_send_config_pkt(vif, WILC_SET_CFG, wid_list,
1617                                       ARRAY_SIZE(wid_list),
1618                                       wilc_get_vif_idx(vif));
1619         if (result)
1620                 netdev_err(vif->ndev,
1621                            "Failed to add wep ap key config packet\n");
1622
1623         kfree(wep_key);
1624         return result;
1625 }
1626
1627 int wilc_add_ptk(struct wilc_vif *vif, const u8 *ptk, u8 ptk_key_len,
1628                  const u8 *mac_addr, const u8 *rx_mic, const u8 *tx_mic,
1629                  u8 mode, u8 cipher_mode, u8 index)
1630 {
1631         int result = 0;
1632         u8 t_key_len  = ptk_key_len + RX_MIC_KEY_LEN + TX_MIC_KEY_LEN;
1633
1634         if (mode == WILC_AP_MODE) {
1635                 struct wid wid_list[2];
1636                 struct wilc_ap_wpa_ptk *key_buf;
1637
1638                 wid_list[0].id = WID_11I_MODE;
1639                 wid_list[0].type = WID_CHAR;
1640                 wid_list[0].size = sizeof(char);
1641                 wid_list[0].val = (s8 *)&cipher_mode;
1642
1643                 key_buf = kzalloc(sizeof(*key_buf) + t_key_len, GFP_KERNEL);
1644                 if (!key_buf)
1645                         return -ENOMEM;
1646
1647                 ether_addr_copy(key_buf->mac_addr, mac_addr);
1648                 key_buf->index = index;
1649                 key_buf->key_len = t_key_len;
1650                 memcpy(&key_buf->key[0], ptk, ptk_key_len);
1651
1652                 if (rx_mic)
1653                         memcpy(&key_buf->key[ptk_key_len], rx_mic,
1654                                RX_MIC_KEY_LEN);
1655
1656                 if (tx_mic)
1657                         memcpy(&key_buf->key[ptk_key_len + RX_MIC_KEY_LEN],
1658                                tx_mic, TX_MIC_KEY_LEN);
1659
1660                 wid_list[1].id = WID_ADD_PTK;
1661                 wid_list[1].type = WID_STR;
1662                 wid_list[1].size = sizeof(*key_buf) + t_key_len;
1663                 wid_list[1].val = (u8 *)key_buf;
1664                 result = wilc_send_config_pkt(vif, WILC_SET_CFG, wid_list,
1665                                               ARRAY_SIZE(wid_list),
1666                                               wilc_get_vif_idx(vif));
1667                 kfree(key_buf);
1668         } else if (mode == WILC_STATION_MODE) {
1669                 struct wid wid;
1670                 struct wilc_sta_wpa_ptk *key_buf;
1671
1672                 key_buf = kzalloc(sizeof(*key_buf) + t_key_len, GFP_KERNEL);
1673                 if (!key_buf)
1674                         return -ENOMEM;
1675
1676                 ether_addr_copy(key_buf->mac_addr, mac_addr);
1677                 key_buf->key_len = t_key_len;
1678                 memcpy(&key_buf->key[0], ptk, ptk_key_len);
1679
1680                 if (rx_mic)
1681                         memcpy(&key_buf->key[ptk_key_len], rx_mic,
1682                                RX_MIC_KEY_LEN);
1683
1684                 if (tx_mic)
1685                         memcpy(&key_buf->key[ptk_key_len + RX_MIC_KEY_LEN],
1686                                tx_mic, TX_MIC_KEY_LEN);
1687
1688                 wid.id = WID_ADD_PTK;
1689                 wid.type = WID_STR;
1690                 wid.size = sizeof(*key_buf) + t_key_len;
1691                 wid.val = (s8 *)key_buf;
1692                 result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
1693                                               wilc_get_vif_idx(vif));
1694                 kfree(key_buf);
1695         }
1696
1697         return result;
1698 }
1699
1700 int wilc_add_rx_gtk(struct wilc_vif *vif, const u8 *rx_gtk, u8 gtk_key_len,
1701                     u8 index, u32 key_rsc_len, const u8 *key_rsc,
1702                     const u8 *rx_mic, const u8 *tx_mic, u8 mode,
1703                     u8 cipher_mode)
1704 {
1705         int result = 0;
1706         struct wilc_gtk_key *gtk_key;
1707         int t_key_len = gtk_key_len + RX_MIC_KEY_LEN + TX_MIC_KEY_LEN;
1708
1709         gtk_key = kzalloc(sizeof(*gtk_key) + t_key_len, GFP_KERNEL);
1710         if (!gtk_key)
1711                 return -ENOMEM;
1712
1713         /* fill bssid value only in station mode */
1714         if (mode == WILC_STATION_MODE &&
1715             vif->hif_drv->hif_state == HOST_IF_CONNECTED)
1716                 memcpy(gtk_key->mac_addr, vif->hif_drv->assoc_bssid, ETH_ALEN);
1717
1718         if (key_rsc)
1719                 memcpy(gtk_key->rsc, key_rsc, 8);
1720         gtk_key->index = index;
1721         gtk_key->key_len = t_key_len;
1722         memcpy(&gtk_key->key[0], rx_gtk, gtk_key_len);
1723
1724         if (rx_mic)
1725                 memcpy(&gtk_key->key[gtk_key_len], rx_mic, RX_MIC_KEY_LEN);
1726
1727         if (tx_mic)
1728                 memcpy(&gtk_key->key[gtk_key_len + RX_MIC_KEY_LEN],
1729                        tx_mic, TX_MIC_KEY_LEN);
1730
1731         if (mode == WILC_AP_MODE) {
1732                 struct wid wid_list[2];
1733
1734                 wid_list[0].id = WID_11I_MODE;
1735                 wid_list[0].type = WID_CHAR;
1736                 wid_list[0].size = sizeof(char);
1737                 wid_list[0].val = (s8 *)&cipher_mode;
1738
1739                 wid_list[1].id = WID_ADD_RX_GTK;
1740                 wid_list[1].type = WID_STR;
1741                 wid_list[1].size = sizeof(*gtk_key) + t_key_len;
1742                 wid_list[1].val = (u8 *)gtk_key;
1743
1744                 result = wilc_send_config_pkt(vif, WILC_SET_CFG, wid_list,
1745                                               ARRAY_SIZE(wid_list),
1746                                               wilc_get_vif_idx(vif));
1747         } else if (mode == WILC_STATION_MODE) {
1748                 struct wid wid;
1749
1750                 wid.id = WID_ADD_RX_GTK;
1751                 wid.type = WID_STR;
1752                 wid.size = sizeof(*gtk_key) + t_key_len;
1753                 wid.val = (u8 *)gtk_key;
1754                 result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
1755                                               wilc_get_vif_idx(vif));
1756         }
1757
1758         kfree(gtk_key);
1759         return result;
1760 }
1761
1762 int wilc_set_pmkid_info(struct wilc_vif *vif, struct wilc_pmkid_attr *pmkid)
1763 {
1764         struct wid wid;
1765         int result;
1766
1767         wid.id = WID_PMKID_INFO;
1768         wid.type = WID_STR;
1769         wid.size = (pmkid->numpmkid * sizeof(struct wilc_pmkid)) + 1;
1770         wid.val = (u8 *)pmkid;
1771
1772         result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
1773                                       wilc_get_vif_idx(vif));
1774
1775         return result;
1776 }
1777
1778 int wilc_get_mac_address(struct wilc_vif *vif, u8 *mac_addr)
1779 {
1780         int result;
1781         struct wid wid;
1782
1783         wid.id = WID_MAC_ADDR;
1784         wid.type = WID_STR;
1785         wid.size = ETH_ALEN;
1786         wid.val = mac_addr;
1787
1788         result = wilc_send_config_pkt(vif, WILC_GET_CFG, &wid, 1,
1789                                       wilc_get_vif_idx(vif));
1790         if (result)
1791                 netdev_err(vif->ndev, "Failed to get mac address\n");
1792
1793         return result;
1794 }
1795
1796 int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ssid,
1797                       size_t ssid_len, const u8 *ies, size_t ies_len,
1798                       wilc_connect_result connect_result, void *user_arg,
1799                       u8 security, enum authtype auth_type,
1800                       u8 channel, void *join_params)
1801 {
1802         int result;
1803         struct host_if_drv *hif_drv = vif->hif_drv;
1804         struct user_conn_req *con_info = &hif_drv->usr_conn_req;
1805
1806         if (!hif_drv || !connect_result) {
1807                 netdev_err(vif->ndev,
1808                            "%s: hif driver or connect result is NULL",
1809                            __func__);
1810                 return -EFAULT;
1811         }
1812
1813         if (!join_params) {
1814                 netdev_err(vif->ndev, "%s: joinparams is NULL\n", __func__);
1815                 return -EFAULT;
1816         }
1817
1818         if (hif_drv->usr_scan_req.scan_result) {
1819                 netdev_err(vif->ndev, "%s: Scan in progress\n", __func__);
1820                 return -EBUSY;
1821         }
1822
1823         con_info->security = security;
1824         con_info->auth_type = auth_type;
1825         con_info->ch = channel;
1826         con_info->conn_result = connect_result;
1827         con_info->arg = user_arg;
1828         con_info->param = join_params;
1829
1830         if (bssid) {
1831                 con_info->bssid = kmemdup(bssid, 6, GFP_KERNEL);
1832                 if (!con_info->bssid)
1833                         return -ENOMEM;
1834         }
1835
1836         if (ssid) {
1837                 con_info->ssid_len = ssid_len;
1838                 con_info->ssid = kmemdup(ssid, ssid_len, GFP_KERNEL);
1839                 if (!con_info->ssid) {
1840                         result = -ENOMEM;
1841                         goto free_bssid;
1842                 }
1843         }
1844
1845         if (ies) {
1846                 con_info->ies_len = ies_len;
1847                 con_info->ies = kmemdup(ies, ies_len, GFP_KERNEL);
1848                 if (!con_info->ies) {
1849                         result = -ENOMEM;
1850                         goto free_ssid;
1851                 }
1852         }
1853
1854         result = wilc_send_connect_wid(vif);
1855         if (result)
1856                 goto free_ies;
1857
1858         hif_drv->connect_timer_vif = vif;
1859         mod_timer(&hif_drv->connect_timer,
1860                   jiffies + msecs_to_jiffies(HOST_IF_CONNECT_TIMEOUT));
1861
1862         return 0;
1863
1864 free_ies:
1865         kfree(con_info->ies);
1866
1867 free_ssid:
1868         kfree(con_info->ssid);
1869
1870 free_bssid:
1871         kfree(con_info->bssid);
1872
1873         return result;
1874 }
1875
1876 int wilc_set_mac_chnl_num(struct wilc_vif *vif, u8 channel)
1877 {
1878         struct wid wid;
1879         int result;
1880
1881         wid.id = WID_CURRENT_CHANNEL;
1882         wid.type = WID_CHAR;
1883         wid.size = sizeof(char);
1884         wid.val = &channel;
1885
1886         result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
1887                                       wilc_get_vif_idx(vif));
1888         if (result)
1889                 netdev_err(vif->ndev, "Failed to set channel\n");
1890
1891         return result;
1892 }
1893
1894 int wilc_set_wfi_drv_handler(struct wilc_vif *vif, int index, u8 mode,
1895                              u8 ifc_id)
1896 {
1897         struct wid wid;
1898         struct host_if_drv *hif_drv = vif->hif_drv;
1899         int result;
1900         struct wilc_drv_handler drv;
1901
1902         wid.id = WID_SET_DRV_HANDLER;
1903         wid.type = WID_STR;
1904         wid.size = sizeof(drv);
1905         wid.val = (u8 *)&drv;
1906
1907         drv.handler = cpu_to_le32(index);
1908         drv.mode = (ifc_id | (mode << 1));
1909
1910         result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
1911                                       hif_drv->driver_handler_id);
1912         if (result)
1913                 netdev_err(vif->ndev, "Failed to set driver handler\n");
1914
1915         return result;
1916 }
1917
1918 int wilc_set_operation_mode(struct wilc_vif *vif, u32 mode)
1919 {
1920         struct wid wid;
1921         struct wilc_op_mode op_mode;
1922         int result;
1923
1924         wid.id = WID_SET_OPERATION_MODE;
1925         wid.type = WID_INT;
1926         wid.size = sizeof(op_mode);
1927         wid.val = (u8 *)&op_mode;
1928
1929         op_mode.mode = cpu_to_le32(mode);
1930
1931         result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
1932                                       wilc_get_vif_idx(vif));
1933         if (result)
1934                 netdev_err(vif->ndev, "Failed to set operation mode\n");
1935
1936         return result;
1937 }
1938
1939 s32 wilc_get_inactive_time(struct wilc_vif *vif, const u8 *mac, u32 *out_val)
1940 {
1941         struct wid wid;
1942         s32 result;
1943
1944         wid.id = WID_SET_STA_MAC_INACTIVE_TIME;
1945         wid.type = WID_STR;
1946         wid.size = ETH_ALEN;
1947         wid.val = kzalloc(wid.size, GFP_KERNEL);
1948         if (!wid.val)
1949                 return -ENOMEM;
1950
1951         ether_addr_copy(wid.val, mac);
1952         result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
1953                                       wilc_get_vif_idx(vif));
1954         kfree(wid.val);
1955         if (result) {
1956                 netdev_err(vif->ndev, "Failed to set inactive mac\n");
1957                 return result;
1958         }
1959
1960         wid.id = WID_GET_INACTIVE_TIME;
1961         wid.type = WID_INT;
1962         wid.val = (s8 *)out_val;
1963         wid.size = sizeof(u32);
1964         result = wilc_send_config_pkt(vif, WILC_GET_CFG, &wid, 1,
1965                                       wilc_get_vif_idx(vif));
1966         if (result)
1967                 netdev_err(vif->ndev, "Failed to get inactive time\n");
1968
1969         return result;
1970 }
1971
1972 int wilc_get_rssi(struct wilc_vif *vif, s8 *rssi_level)
1973 {
1974         struct wid wid;
1975         int result;
1976
1977         if (!rssi_level) {
1978                 netdev_err(vif->ndev, "%s: RSSI level is NULL\n", __func__);
1979                 return -EFAULT;
1980         }
1981
1982         wid.id = WID_RSSI;
1983         wid.type = WID_CHAR;
1984         wid.size = sizeof(char);
1985         wid.val = rssi_level;
1986         result = wilc_send_config_pkt(vif, WILC_GET_CFG, &wid, 1,
1987                                       wilc_get_vif_idx(vif));
1988         if (result)
1989                 netdev_err(vif->ndev, "Failed to get RSSI value\n");
1990
1991         return result;
1992 }
1993
1994 int wilc_get_stats_async(struct wilc_vif *vif, struct rf_info *stats)
1995 {
1996         int result;
1997         struct host_if_msg *msg;
1998
1999         msg = wilc_alloc_work(vif, handle_get_statistics, false);
2000         if (IS_ERR(msg))
2001                 return PTR_ERR(msg);
2002
2003         msg->body.data = (char *)stats;
2004
2005         result = wilc_enqueue_work(msg);
2006         if (result) {
2007                 netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__);
2008                 kfree(msg);
2009                 return result;
2010         }
2011
2012         return result;
2013 }
2014
2015 int wilc_hif_set_cfg(struct wilc_vif *vif, struct cfg_param_attr *param)
2016 {
2017         struct wid wid_list[4];
2018         int i = 0;
2019         int result;
2020
2021         if (param->flag & WILC_CFG_PARAM_RETRY_SHORT) {
2022                 wid_list[i].id = WID_SHORT_RETRY_LIMIT;
2023                 wid_list[i].val = (s8 *)&param->short_retry_limit;
2024                 wid_list[i].type = WID_SHORT;
2025                 wid_list[i].size = sizeof(u16);
2026                 i++;
2027         }
2028         if (param->flag & WILC_CFG_PARAM_RETRY_LONG) {
2029                 wid_list[i].id = WID_LONG_RETRY_LIMIT;
2030                 wid_list[i].val = (s8 *)&param->long_retry_limit;
2031                 wid_list[i].type = WID_SHORT;
2032                 wid_list[i].size = sizeof(u16);
2033                 i++;
2034         }
2035         if (param->flag & WILC_CFG_PARAM_FRAG_THRESHOLD) {
2036                 wid_list[i].id = WID_FRAG_THRESHOLD;
2037                 wid_list[i].val = (s8 *)&param->frag_threshold;
2038                 wid_list[i].type = WID_SHORT;
2039                 wid_list[i].size = sizeof(u16);
2040                 i++;
2041         }
2042         if (param->flag & WILC_CFG_PARAM_RTS_THRESHOLD) {
2043                 wid_list[i].id = WID_RTS_THRESHOLD;
2044                 wid_list[i].val = (s8 *)&param->rts_threshold;
2045                 wid_list[i].type = WID_SHORT;
2046                 wid_list[i].size = sizeof(u16);
2047                 i++;
2048         }
2049
2050         result = wilc_send_config_pkt(vif, WILC_SET_CFG, wid_list,
2051                                       i, wilc_get_vif_idx(vif));
2052
2053         return result;
2054 }
2055
2056 static void get_periodic_rssi(struct timer_list *t)
2057 {
2058         struct wilc_vif *vif = from_timer(vif, t, periodic_rssi);
2059
2060         if (!vif->hif_drv) {
2061                 netdev_err(vif->ndev, "%s: hif driver is NULL", __func__);
2062                 return;
2063         }
2064
2065         if (vif->hif_drv->hif_state == HOST_IF_CONNECTED)
2066                 wilc_get_stats_async(vif, &vif->periodic_stat);
2067
2068         mod_timer(&vif->periodic_rssi, jiffies + msecs_to_jiffies(5000));
2069 }
2070
2071 int wilc_init(struct net_device *dev, struct host_if_drv **hif_drv_handler)
2072 {
2073         struct host_if_drv *hif_drv;
2074         struct wilc_vif *vif = netdev_priv(dev);
2075         struct wilc *wilc = vif->wilc;
2076         int i;
2077
2078         hif_drv  = kzalloc(sizeof(*hif_drv), GFP_KERNEL);
2079         if (!hif_drv)
2080                 return -ENOMEM;
2081
2082         *hif_drv_handler = hif_drv;
2083         for (i = 0; i < wilc->vif_num; i++)
2084                 if (dev == wilc->vif[i]->ndev) {
2085                         wilc->vif[i]->hif_drv = hif_drv;
2086                         hif_drv->driver_handler_id = i + 1;
2087                         break;
2088                 }
2089
2090         vif->obtaining_ip = false;
2091
2092         if (wilc->clients_count == 0)
2093                 mutex_init(&hif_deinit_lock);
2094
2095         timer_setup(&vif->periodic_rssi, get_periodic_rssi, 0);
2096         mod_timer(&vif->periodic_rssi, jiffies + msecs_to_jiffies(5000));
2097
2098         timer_setup(&hif_drv->scan_timer, timer_scan_cb, 0);
2099         timer_setup(&hif_drv->connect_timer, timer_connect_cb, 0);
2100         timer_setup(&hif_drv->remain_on_ch_timer, listen_timer_cb, 0);
2101
2102         hif_drv->hif_state = HOST_IF_IDLE;
2103
2104         hif_drv->p2p_timeout = 0;
2105
2106         wilc->clients_count++;
2107
2108         return 0;
2109 }
2110
2111 int wilc_deinit(struct wilc_vif *vif)
2112 {
2113         int result = 0;
2114         struct host_if_drv *hif_drv = vif->hif_drv;
2115
2116         if (!hif_drv) {
2117                 netdev_err(vif->ndev, "%s: hif driver is NULL", __func__);
2118                 return -EFAULT;
2119         }
2120
2121         mutex_lock(&hif_deinit_lock);
2122
2123         terminated_handle = hif_drv;
2124
2125         del_timer_sync(&hif_drv->scan_timer);
2126         del_timer_sync(&hif_drv->connect_timer);
2127         del_timer_sync(&vif->periodic_rssi);
2128         del_timer_sync(&hif_drv->remain_on_ch_timer);
2129
2130         wilc_set_wfi_drv_handler(vif, 0, 0, 0);
2131
2132         if (hif_drv->usr_scan_req.scan_result) {
2133                 hif_drv->usr_scan_req.scan_result(SCAN_EVENT_ABORTED, NULL,
2134                                                   hif_drv->usr_scan_req.arg,
2135                                                   NULL);
2136                 hif_drv->usr_scan_req.scan_result = NULL;
2137         }
2138
2139         hif_drv->hif_state = HOST_IF_IDLE;
2140
2141         kfree(hif_drv);
2142
2143         vif->wilc->clients_count--;
2144         terminated_handle = NULL;
2145         mutex_unlock(&hif_deinit_lock);
2146         return result;
2147 }
2148
2149 void wilc_network_info_received(struct wilc *wilc, u8 *buffer, u32 length)
2150 {
2151         int result;
2152         struct host_if_msg *msg;
2153         int id;
2154         struct host_if_drv *hif_drv;
2155         struct wilc_vif *vif;
2156
2157         id = buffer[length - 4];
2158         id |= (buffer[length - 3] << 8);
2159         id |= (buffer[length - 2] << 16);
2160         id |= (buffer[length - 1] << 24);
2161         vif = wilc_get_vif_from_idx(wilc, id);
2162         if (!vif)
2163                 return;
2164         hif_drv = vif->hif_drv;
2165
2166         if (!hif_drv || hif_drv == terminated_handle) {
2167                 netdev_err(vif->ndev, "driver not init[%p]\n", hif_drv);
2168                 return;
2169         }
2170
2171         msg = wilc_alloc_work(vif, handle_rcvd_ntwrk_info, false);
2172         if (IS_ERR(msg))
2173                 return;
2174
2175         msg->body.net_info.len = length;
2176         msg->body.net_info.buffer = kmemdup(buffer, length, GFP_KERNEL);
2177         if (!msg->body.net_info.buffer) {
2178                 kfree(msg);
2179                 return;
2180         }
2181
2182         result = wilc_enqueue_work(msg);
2183         if (result) {
2184                 netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__);
2185                 kfree(msg->body.net_info.buffer);
2186                 kfree(msg);
2187         }
2188 }
2189
2190 void wilc_gnrl_async_info_received(struct wilc *wilc, u8 *buffer, u32 length)
2191 {
2192         int result;
2193         struct host_if_msg *msg;
2194         int id;
2195         struct host_if_drv *hif_drv;
2196         struct wilc_vif *vif;
2197
2198         mutex_lock(&hif_deinit_lock);
2199
2200         id = buffer[length - 4];
2201         id |= (buffer[length - 3] << 8);
2202         id |= (buffer[length - 2] << 16);
2203         id |= (buffer[length - 1] << 24);
2204         vif = wilc_get_vif_from_idx(wilc, id);
2205         if (!vif) {
2206                 mutex_unlock(&hif_deinit_lock);
2207                 return;
2208         }
2209
2210         hif_drv = vif->hif_drv;
2211
2212         if (!hif_drv || hif_drv == terminated_handle) {
2213                 mutex_unlock(&hif_deinit_lock);
2214                 return;
2215         }
2216
2217         if (!hif_drv->usr_conn_req.conn_result) {
2218                 netdev_err(vif->ndev, "%s: conn_result is NULL\n", __func__);
2219                 mutex_unlock(&hif_deinit_lock);
2220                 return;
2221         }
2222
2223         msg = wilc_alloc_work(vif, handle_rcvd_gnrl_async_info, false);
2224         if (IS_ERR(msg)) {
2225                 mutex_unlock(&hif_deinit_lock);
2226                 return;
2227         }
2228
2229         msg->body.async_info.len = length;
2230         msg->body.async_info.buffer = kmemdup(buffer, length, GFP_KERNEL);
2231         if (!msg->body.async_info.buffer) {
2232                 kfree(msg);
2233                 mutex_unlock(&hif_deinit_lock);
2234                 return;
2235         }
2236
2237         result = wilc_enqueue_work(msg);
2238         if (result) {
2239                 netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__);
2240                 kfree(msg->body.async_info.buffer);
2241                 kfree(msg);
2242         }
2243
2244         mutex_unlock(&hif_deinit_lock);
2245 }
2246
2247 void wilc_scan_complete_received(struct wilc *wilc, u8 *buffer, u32 length)
2248 {
2249         int result;
2250         int id;
2251         struct host_if_drv *hif_drv;
2252         struct wilc_vif *vif;
2253
2254         id = buffer[length - 4];
2255         id |= buffer[length - 3] << 8;
2256         id |= buffer[length - 2] << 16;
2257         id |= buffer[length - 1] << 24;
2258         vif = wilc_get_vif_from_idx(wilc, id);
2259         if (!vif)
2260                 return;
2261         hif_drv = vif->hif_drv;
2262
2263         if (!hif_drv || hif_drv == terminated_handle)
2264                 return;
2265
2266         if (hif_drv->usr_scan_req.scan_result) {
2267                 struct host_if_msg *msg;
2268
2269                 msg = wilc_alloc_work(vif, handle_scan_complete, false);
2270                 if (IS_ERR(msg))
2271                         return;
2272
2273                 result = wilc_enqueue_work(msg);
2274                 if (result) {
2275                         netdev_err(vif->ndev, "%s: enqueue work failed\n",
2276                                    __func__);
2277                         kfree(msg);
2278                 }
2279         }
2280 }
2281
2282 int wilc_remain_on_channel(struct wilc_vif *vif, u32 session_id,
2283                            u32 duration, u16 chan,
2284                            wilc_remain_on_chan_expired expired,
2285                            wilc_remain_on_chan_ready ready,
2286                            void *user_arg)
2287 {
2288         struct remain_ch roc;
2289         int result;
2290
2291         roc.ch = chan;
2292         roc.expired = expired;
2293         roc.ready = ready;
2294         roc.arg = user_arg;
2295         roc.duration = duration;
2296         roc.id = session_id;
2297         result = handle_remain_on_chan(vif, &roc);
2298         if (result)
2299                 netdev_err(vif->ndev, "%s: failed to set remain on channel\n",
2300                            __func__);
2301
2302         return result;
2303 }
2304
2305 int wilc_listen_state_expired(struct wilc_vif *vif, u32 session_id)
2306 {
2307         int result;
2308         struct host_if_msg *msg;
2309         struct host_if_drv *hif_drv = vif->hif_drv;
2310
2311         if (!hif_drv) {
2312                 netdev_err(vif->ndev, "%s: hif driver is NULL", __func__);
2313                 return -EFAULT;
2314         }
2315
2316         del_timer(&hif_drv->remain_on_ch_timer);
2317
2318         msg = wilc_alloc_work(vif, handle_listen_state_expired, false);
2319         if (IS_ERR(msg))
2320                 return PTR_ERR(msg);
2321
2322         msg->body.remain_on_ch.id = session_id;
2323
2324         result = wilc_enqueue_work(msg);
2325         if (result) {
2326                 netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__);
2327                 kfree(msg);
2328         }
2329
2330         return result;
2331 }
2332
2333 void wilc_frame_register(struct wilc_vif *vif, u16 frame_type, bool reg)
2334 {
2335         struct wid wid;
2336         int result;
2337         struct wilc_reg_frame reg_frame;
2338
2339         wid.id = WID_REGISTER_FRAME;
2340         wid.type = WID_STR;
2341         wid.size = sizeof(reg_frame);
2342         wid.val = (u8 *)&reg_frame;
2343
2344         memset(&reg_frame, 0x0, sizeof(reg_frame));
2345         reg_frame.reg = reg;
2346
2347         switch (frame_type) {
2348         case IEEE80211_STYPE_ACTION:
2349                 reg_frame.reg_id = WILC_FW_ACTION_FRM_IDX;
2350                 break;
2351
2352         case IEEE80211_STYPE_PROBE_REQ:
2353                 reg_frame.reg_id = WILC_FW_PROBE_REQ_IDX;
2354                 break;
2355
2356         default:
2357                 break;
2358         }
2359         reg_frame.frame_type = cpu_to_le16(frame_type);
2360         result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
2361                                       wilc_get_vif_idx(vif));
2362         if (result)
2363                 netdev_err(vif->ndev, "Failed to frame register\n");
2364 }
2365
2366 int wilc_add_beacon(struct wilc_vif *vif, u32 interval, u32 dtim_period,
2367                     struct cfg80211_beacon_data *params)
2368 {
2369         struct wid wid;
2370         int result;
2371         u8 *cur_byte;
2372
2373         wid.id = WID_ADD_BEACON;
2374         wid.type = WID_BIN;
2375         wid.size = params->head_len + params->tail_len + 16;
2376         wid.val = kzalloc(wid.size, GFP_KERNEL);
2377         if (!wid.val)
2378                 return -ENOMEM;
2379
2380         cur_byte = wid.val;
2381         put_unaligned_le32(interval, cur_byte);
2382         cur_byte += 4;
2383         put_unaligned_le32(dtim_period, cur_byte);
2384         cur_byte += 4;
2385         put_unaligned_le32(params->head_len, cur_byte);
2386         cur_byte += 4;
2387
2388         if (params->head_len > 0)
2389                 memcpy(cur_byte, params->head, params->head_len);
2390         cur_byte += params->head_len;
2391
2392         put_unaligned_le32(params->tail_len, cur_byte);
2393         cur_byte += 4;
2394
2395         if (params->tail_len > 0)
2396                 memcpy(cur_byte, params->tail, params->tail_len);
2397
2398         result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
2399                                       wilc_get_vif_idx(vif));
2400         if (result)
2401                 netdev_err(vif->ndev, "Failed to send add beacon\n");
2402
2403         kfree(wid.val);
2404
2405         return result;
2406 }
2407
2408 int wilc_del_beacon(struct wilc_vif *vif)
2409 {
2410         int result;
2411         struct wid wid;
2412         u8 del_beacon = 0;
2413
2414         wid.id = WID_DEL_BEACON;
2415         wid.type = WID_CHAR;
2416         wid.size = sizeof(char);
2417         wid.val = &del_beacon;
2418
2419         result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
2420                                       wilc_get_vif_idx(vif));
2421         if (result)
2422                 netdev_err(vif->ndev, "Failed to send delete beacon\n");
2423
2424         return result;
2425 }
2426
2427 int wilc_add_station(struct wilc_vif *vif, const u8 *mac,
2428                      struct station_parameters *params)
2429 {
2430         struct wid wid;
2431         int result;
2432         u8 *cur_byte;
2433
2434         wid.id = WID_ADD_STA;
2435         wid.type = WID_BIN;
2436         wid.size = WILC_ADD_STA_LENGTH + params->supported_rates_len;
2437         wid.val = kmalloc(wid.size, GFP_KERNEL);
2438         if (!wid.val)
2439                 return -ENOMEM;
2440
2441         cur_byte = wid.val;
2442         wilc_hif_pack_sta_param(cur_byte, mac, params);
2443
2444         result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
2445                                       wilc_get_vif_idx(vif));
2446         if (result != 0)
2447                 netdev_err(vif->ndev, "Failed to send add station\n");
2448
2449         kfree(wid.val);
2450
2451         return result;
2452 }
2453
2454 int wilc_del_station(struct wilc_vif *vif, const u8 *mac_addr)
2455 {
2456         struct wid wid;
2457         int result;
2458
2459         wid.id = WID_REMOVE_STA;
2460         wid.type = WID_BIN;
2461         wid.size = ETH_ALEN;
2462         wid.val = kzalloc(wid.size, GFP_KERNEL);
2463         if (!wid.val)
2464                 return -ENOMEM;
2465
2466         if (!mac_addr)
2467                 eth_broadcast_addr(wid.val);
2468         else
2469                 ether_addr_copy(wid.val, mac_addr);
2470
2471         result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
2472                                       wilc_get_vif_idx(vif));
2473         if (result)
2474                 netdev_err(vif->ndev, "Failed to del station\n");
2475
2476         kfree(wid.val);
2477
2478         return result;
2479 }
2480
2481 int wilc_del_allstation(struct wilc_vif *vif, u8 mac_addr[][ETH_ALEN])
2482 {
2483         struct wid wid;
2484         int result;
2485         int i;
2486         u8 assoc_sta = 0;
2487         struct del_all_sta del_sta;
2488
2489         memset(&del_sta, 0x0, sizeof(del_sta));
2490         for (i = 0; i < WILC_MAX_NUM_STA; i++) {
2491                 if (!is_zero_ether_addr(mac_addr[i])) {
2492                         assoc_sta++;
2493                         ether_addr_copy(del_sta.mac[i], mac_addr[i]);
2494                 }
2495         }
2496
2497         if (!assoc_sta)
2498                 return 0;
2499
2500         del_sta.assoc_sta = assoc_sta;
2501
2502         wid.id = WID_DEL_ALL_STA;
2503         wid.type = WID_STR;
2504         wid.size = (assoc_sta * ETH_ALEN) + 1;
2505         wid.val = (u8 *)&del_sta;
2506
2507         result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
2508                                       wilc_get_vif_idx(vif));
2509         if (result)
2510                 netdev_err(vif->ndev, "Failed to send delete all station\n");
2511
2512         return result;
2513 }
2514
2515 int wilc_edit_station(struct wilc_vif *vif, const u8 *mac,
2516                       struct station_parameters *params)
2517 {
2518         struct wid wid;
2519         int result;
2520         u8 *cur_byte;
2521
2522         wid.id = WID_EDIT_STA;
2523         wid.type = WID_BIN;
2524         wid.size = WILC_ADD_STA_LENGTH + params->supported_rates_len;
2525         wid.val = kmalloc(wid.size, GFP_KERNEL);
2526         if (!wid.val)
2527                 return -ENOMEM;
2528
2529         cur_byte = wid.val;
2530         wilc_hif_pack_sta_param(cur_byte, mac, params);
2531
2532         result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
2533                                       wilc_get_vif_idx(vif));
2534         if (result)
2535                 netdev_err(vif->ndev, "Failed to send edit station\n");
2536
2537         kfree(wid.val);
2538         return result;
2539 }
2540
2541 int wilc_set_power_mgmt(struct wilc_vif *vif, bool enabled, u32 timeout)
2542 {
2543         struct wid wid;
2544         int result;
2545         s8 power_mode;
2546
2547         if (wilc_wlan_get_num_conn_ifcs(vif->wilc) == 2 && enabled)
2548                 return 0;
2549
2550         if (enabled)
2551                 power_mode = WILC_FW_MIN_FAST_PS;
2552         else
2553                 power_mode = WILC_FW_NO_POWERSAVE;
2554
2555         wid.id = WID_POWER_MANAGEMENT;
2556         wid.val = &power_mode;
2557         wid.size = sizeof(char);
2558         result = wilc_send_config_pkt(vif, WILC_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
2563         return result;
2564 }
2565
2566 int wilc_setup_multicast_filter(struct wilc_vif *vif, bool enabled, u32 count,
2567                                 u8 *mc_list)
2568 {
2569         int result;
2570         struct host_if_msg *msg;
2571
2572         msg = wilc_alloc_work(vif, handle_set_mcast_filter, false);
2573         if (IS_ERR(msg))
2574                 return PTR_ERR(msg);
2575
2576         msg->body.multicast_info.enabled = enabled;
2577         msg->body.multicast_info.cnt = count;
2578         msg->body.multicast_info.mc_list = mc_list;
2579
2580         result = wilc_enqueue_work(msg);
2581         if (result) {
2582                 netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__);
2583                 kfree(msg);
2584         }
2585         return result;
2586 }
2587
2588 int wilc_set_tx_power(struct wilc_vif *vif, u8 tx_power)
2589 {
2590         int ret;
2591         struct wid wid;
2592
2593         wid.id = WID_TX_POWER;
2594         wid.type = WID_CHAR;
2595         wid.val = &tx_power;
2596         wid.size = sizeof(char);
2597
2598         ret = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
2599                                    wilc_get_vif_idx(vif));
2600
2601         return ret;
2602 }
2603
2604 int wilc_get_tx_power(struct wilc_vif *vif, u8 *tx_power)
2605 {
2606         int ret;
2607         struct wid wid;
2608
2609         wid.id = WID_TX_POWER;
2610         wid.type = WID_CHAR;
2611         wid.val = tx_power;
2612         wid.size = sizeof(char);
2613
2614         ret = wilc_send_config_pkt(vif, WILC_GET_CFG, &wid, 1,
2615                                    wilc_get_vif_idx(vif));
2616
2617         return ret;
2618 }