Linux-libre 5.7.3-gnu
[librecmc/linux-libre.git] / drivers / staging / wilc1000 / hif.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 "netdev.h"
8
9 #define WILC_HIF_SCAN_TIMEOUT_MS                5000
10 #define WILC_HIF_CONNECT_TIMEOUT_MS             9500
11
12 #define WILC_FALSE_FRMWR_CHANNEL                100
13
14 struct wilc_rcvd_mac_info {
15         u8 status;
16 };
17
18 struct wilc_set_multicast {
19         u32 enabled;
20         u32 cnt;
21         u8 *mc_list;
22 };
23
24 struct wilc_del_all_sta {
25         u8 assoc_sta;
26         u8 mac[WILC_MAX_NUM_STA][ETH_ALEN];
27 };
28
29 union wilc_message_body {
30         struct wilc_rcvd_net_info net_info;
31         struct wilc_rcvd_mac_info mac_info;
32         struct wilc_set_multicast mc_info;
33         struct wilc_remain_ch remain_on_ch;
34         char *data;
35 };
36
37 struct host_if_msg {
38         union wilc_message_body body;
39         struct wilc_vif *vif;
40         struct work_struct work;
41         void (*fn)(struct work_struct *ws);
42         struct completion work_comp;
43         bool is_sync;
44 };
45
46 /* 'msg' should be free by the caller for syc */
47 static struct host_if_msg*
48 wilc_alloc_work(struct wilc_vif *vif, void (*work_fun)(struct work_struct *),
49                 bool is_sync)
50 {
51         struct host_if_msg *msg;
52
53         if (!work_fun)
54                 return ERR_PTR(-EINVAL);
55
56         msg = kzalloc(sizeof(*msg), GFP_ATOMIC);
57         if (!msg)
58                 return ERR_PTR(-ENOMEM);
59         msg->fn = work_fun;
60         msg->vif = vif;
61         msg->is_sync = is_sync;
62         if (is_sync)
63                 init_completion(&msg->work_comp);
64
65         return msg;
66 }
67
68 static int wilc_enqueue_work(struct host_if_msg *msg)
69 {
70         INIT_WORK(&msg->work, msg->fn);
71
72         if (!msg->vif || !msg->vif->wilc || !msg->vif->wilc->hif_workqueue)
73                 return -EINVAL;
74
75         if (!queue_work(msg->vif->wilc->hif_workqueue, &msg->work))
76                 return -EINVAL;
77
78         return 0;
79 }
80
81 /* The idx starts from 0 to (NUM_CONCURRENT_IFC - 1), but 0 index used as
82  * special purpose in wilc device, so we add 1 to the index to starts from 1.
83  * As a result, the returned index will be 1 to NUM_CONCURRENT_IFC.
84  */
85 int wilc_get_vif_idx(struct wilc_vif *vif)
86 {
87         return vif->idx + 1;
88 }
89
90 /* We need to minus 1 from idx which is from wilc device to get real index
91  * of wilc->vif[], because we add 1 when pass to wilc device in the function
92  * wilc_get_vif_idx.
93  * As a result, the index should be between 0 and (NUM_CONCURRENT_IFC - 1).
94  */
95 static struct wilc_vif *wilc_get_vif_from_idx(struct wilc *wilc, int idx)
96 {
97         int index = idx - 1;
98         struct wilc_vif *vif;
99
100         if (index < 0 || index >= WILC_NUM_CONCURRENT_IFC)
101                 return NULL;
102
103         list_for_each_entry_rcu(vif, &wilc->vif_list, list) {
104                 if (vif->idx == index)
105                         return vif;
106         }
107
108         return NULL;
109 }
110
111 static int handle_scan_done(struct wilc_vif *vif, enum scan_event evt)
112 {
113         int result = 0;
114         u8 abort_running_scan;
115         struct wid wid;
116         struct host_if_drv *hif_drv = vif->hif_drv;
117         struct wilc_user_scan_req *scan_req;
118
119         if (evt == SCAN_EVENT_ABORTED) {
120                 abort_running_scan = 1;
121                 wid.id = WID_ABORT_RUNNING_SCAN;
122                 wid.type = WID_CHAR;
123                 wid.val = (s8 *)&abort_running_scan;
124                 wid.size = sizeof(char);
125
126                 result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
127                 if (result) {
128                         netdev_err(vif->ndev, "Failed to set abort running\n");
129                         result = -EFAULT;
130                 }
131         }
132
133         if (!hif_drv) {
134                 netdev_err(vif->ndev, "%s: hif driver is NULL\n", __func__);
135                 return result;
136         }
137
138         scan_req = &hif_drv->usr_scan_req;
139         if (scan_req->scan_result) {
140                 scan_req->scan_result(evt, NULL, scan_req->arg);
141                 scan_req->scan_result = NULL;
142         }
143
144         return result;
145 }
146
147 int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type,
148               u8 *ch_freq_list, u8 ch_list_len,
149               void (*scan_result_fn)(enum scan_event,
150                                      struct wilc_rcvd_net_info *, void *),
151               void *user_arg, struct cfg80211_scan_request *request)
152 {
153         int result = 0;
154         struct wid wid_list[5];
155         u32 index = 0;
156         u32 i, scan_timeout;
157         u8 *buffer;
158         u8 valuesize = 0;
159         u8 *search_ssid_vals = NULL;
160         struct host_if_drv *hif_drv = vif->hif_drv;
161
162         if (hif_drv->hif_state >= HOST_IF_SCANNING &&
163             hif_drv->hif_state < HOST_IF_CONNECTED) {
164                 netdev_err(vif->ndev, "Already scan\n");
165                 result = -EBUSY;
166                 goto error;
167         }
168
169         if (vif->connecting) {
170                 netdev_err(vif->ndev, "Don't do obss scan\n");
171                 result = -EBUSY;
172                 goto error;
173         }
174
175         hif_drv->usr_scan_req.ch_cnt = 0;
176
177         if (request->n_ssids) {
178                 for (i = 0; i < request->n_ssids; i++)
179                         valuesize += ((request->ssids[i].ssid_len) + 1);
180                 search_ssid_vals = kmalloc(valuesize + 1, GFP_KERNEL);
181                 if (search_ssid_vals) {
182                         wid_list[index].id = WID_SSID_PROBE_REQ;
183                         wid_list[index].type = WID_STR;
184                         wid_list[index].val = search_ssid_vals;
185                         buffer = wid_list[index].val;
186
187                         *buffer++ = request->n_ssids;
188
189                         for (i = 0; i < request->n_ssids; i++) {
190                                 *buffer++ = request->ssids[i].ssid_len;
191                                 memcpy(buffer, request->ssids[i].ssid,
192                                        request->ssids[i].ssid_len);
193                                 buffer += request->ssids[i].ssid_len;
194                         }
195                         wid_list[index].size = (s32)(valuesize + 1);
196                         index++;
197                 }
198         }
199
200         wid_list[index].id = WID_INFO_ELEMENT_PROBE;
201         wid_list[index].type = WID_BIN_DATA;
202         wid_list[index].val = (s8 *)request->ie;
203         wid_list[index].size = request->ie_len;
204         index++;
205
206         wid_list[index].id = WID_SCAN_TYPE;
207         wid_list[index].type = WID_CHAR;
208         wid_list[index].size = sizeof(char);
209         wid_list[index].val = (s8 *)&scan_type;
210         index++;
211
212         if (scan_type == WILC_FW_PASSIVE_SCAN && request->duration) {
213                 wid_list[index].id = WID_PASSIVE_SCAN_TIME;
214                 wid_list[index].type = WID_SHORT;
215                 wid_list[index].size = sizeof(u16);
216                 wid_list[index].val = (s8 *)&request->duration;
217                 index++;
218
219                 scan_timeout = (request->duration * ch_list_len) + 500;
220         } else {
221                 scan_timeout = WILC_HIF_SCAN_TIMEOUT_MS;
222         }
223
224         wid_list[index].id = WID_SCAN_CHANNEL_LIST;
225         wid_list[index].type = WID_BIN_DATA;
226
227         if (ch_freq_list && ch_list_len > 0) {
228                 for (i = 0; i < ch_list_len; i++) {
229                         if (ch_freq_list[i] > 0)
230                                 ch_freq_list[i] -= 1;
231                 }
232         }
233
234         wid_list[index].val = ch_freq_list;
235         wid_list[index].size = ch_list_len;
236         index++;
237
238         wid_list[index].id = WID_START_SCAN_REQ;
239         wid_list[index].type = WID_CHAR;
240         wid_list[index].size = sizeof(char);
241         wid_list[index].val = (s8 *)&scan_source;
242         index++;
243
244         hif_drv->usr_scan_req.scan_result = scan_result_fn;
245         hif_drv->usr_scan_req.arg = user_arg;
246
247         result = wilc_send_config_pkt(vif, WILC_SET_CFG, wid_list, index);
248         if (result) {
249                 netdev_err(vif->ndev, "Failed to send scan parameters\n");
250                 goto error;
251         }
252
253         hif_drv->scan_timer_vif = vif;
254         mod_timer(&hif_drv->scan_timer,
255                   jiffies + msecs_to_jiffies(scan_timeout));
256
257 error:
258
259         kfree(search_ssid_vals);
260
261         return result;
262 }
263
264 static int wilc_send_connect_wid(struct wilc_vif *vif)
265 {
266         int result = 0;
267         struct wid wid_list[4];
268         u32 wid_cnt = 0;
269         struct host_if_drv *hif_drv = vif->hif_drv;
270         struct wilc_conn_info *conn_attr = &hif_drv->conn_info;
271         struct wilc_join_bss_param *bss_param = conn_attr->param;
272
273         wid_list[wid_cnt].id = WID_INFO_ELEMENT_ASSOCIATE;
274         wid_list[wid_cnt].type = WID_BIN_DATA;
275         wid_list[wid_cnt].val = conn_attr->req_ies;
276         wid_list[wid_cnt].size = conn_attr->req_ies_len;
277         wid_cnt++;
278
279         wid_list[wid_cnt].id = WID_11I_MODE;
280         wid_list[wid_cnt].type = WID_CHAR;
281         wid_list[wid_cnt].size = sizeof(char);
282         wid_list[wid_cnt].val = (s8 *)&conn_attr->security;
283         wid_cnt++;
284
285         wid_list[wid_cnt].id = WID_AUTH_TYPE;
286         wid_list[wid_cnt].type = WID_CHAR;
287         wid_list[wid_cnt].size = sizeof(char);
288         wid_list[wid_cnt].val = (s8 *)&conn_attr->auth_type;
289         wid_cnt++;
290
291         wid_list[wid_cnt].id = WID_JOIN_REQ_EXTENDED;
292         wid_list[wid_cnt].type = WID_STR;
293         wid_list[wid_cnt].size = sizeof(*bss_param);
294         wid_list[wid_cnt].val = (u8 *)bss_param;
295         wid_cnt++;
296
297         result = wilc_send_config_pkt(vif, WILC_SET_CFG, wid_list, wid_cnt);
298         if (result) {
299                 netdev_err(vif->ndev, "failed to send config packet\n");
300                 goto error;
301         } else {
302                 hif_drv->hif_state = HOST_IF_WAITING_CONN_RESP;
303         }
304
305         return 0;
306
307 error:
308
309         kfree(conn_attr->req_ies);
310         conn_attr->req_ies = NULL;
311
312         return result;
313 }
314
315 static void handle_connect_timeout(struct work_struct *work)
316 {
317         struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
318         struct wilc_vif *vif = msg->vif;
319         int result;
320         struct wid wid;
321         u16 dummy_reason_code = 0;
322         struct host_if_drv *hif_drv = vif->hif_drv;
323
324         if (!hif_drv) {
325                 netdev_err(vif->ndev, "%s: hif driver is NULL\n", __func__);
326                 goto out;
327         }
328
329         hif_drv->hif_state = HOST_IF_IDLE;
330
331         if (hif_drv->conn_info.conn_result) {
332                 hif_drv->conn_info.conn_result(CONN_DISCONN_EVENT_CONN_RESP,
333                                                WILC_MAC_STATUS_DISCONNECTED,
334                                                hif_drv->conn_info.arg);
335
336         } else {
337                 netdev_err(vif->ndev, "%s: conn_result is NULL\n", __func__);
338         }
339
340         wid.id = WID_DISCONNECT;
341         wid.type = WID_CHAR;
342         wid.val = (s8 *)&dummy_reason_code;
343         wid.size = sizeof(char);
344
345         result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
346         if (result)
347                 netdev_err(vif->ndev, "Failed to send disconnect\n");
348
349         hif_drv->conn_info.req_ies_len = 0;
350         kfree(hif_drv->conn_info.req_ies);
351         hif_drv->conn_info.req_ies = NULL;
352
353 out:
354         kfree(msg);
355 }
356
357 void *wilc_parse_join_bss_param(struct cfg80211_bss *bss,
358                                 struct cfg80211_crypto_settings *crypto)
359 {
360         struct wilc_join_bss_param *param;
361         struct ieee80211_p2p_noa_attr noa_attr;
362         u8 rates_len = 0;
363         const u8 *tim_elm, *ssid_elm, *rates_ie, *supp_rates_ie;
364         const u8 *ht_ie, *wpa_ie, *wmm_ie, *rsn_ie;
365         int ret;
366         const struct cfg80211_bss_ies *ies = rcu_dereference(bss->ies);
367
368         param = kzalloc(sizeof(*param), GFP_KERNEL);
369         if (!param)
370                 return NULL;
371
372         param->beacon_period = cpu_to_le16(bss->beacon_interval);
373         param->cap_info = cpu_to_le16(bss->capability);
374         param->bss_type = WILC_FW_BSS_TYPE_INFRA;
375         param->ch = ieee80211_frequency_to_channel(bss->channel->center_freq);
376         ether_addr_copy(param->bssid, bss->bssid);
377
378         ssid_elm = cfg80211_find_ie(WLAN_EID_SSID, ies->data, ies->len);
379         if (ssid_elm) {
380                 if (ssid_elm[1] <= IEEE80211_MAX_SSID_LEN)
381                         memcpy(param->ssid, ssid_elm + 2, ssid_elm[1]);
382         }
383
384         tim_elm = cfg80211_find_ie(WLAN_EID_TIM, ies->data, ies->len);
385         if (tim_elm && tim_elm[1] >= 2)
386                 param->dtim_period = tim_elm[3];
387
388         memset(param->p_suites, 0xFF, 3);
389         memset(param->akm_suites, 0xFF, 3);
390
391         rates_ie = cfg80211_find_ie(WLAN_EID_SUPP_RATES, ies->data, ies->len);
392         if (rates_ie) {
393                 rates_len = rates_ie[1];
394                 if (rates_len > WILC_MAX_RATES_SUPPORTED)
395                         rates_len = WILC_MAX_RATES_SUPPORTED;
396                 param->supp_rates[0] = rates_len;
397                 memcpy(&param->supp_rates[1], rates_ie + 2, rates_len);
398         }
399
400         if (rates_len < WILC_MAX_RATES_SUPPORTED) {
401                 supp_rates_ie = cfg80211_find_ie(WLAN_EID_EXT_SUPP_RATES,
402                                                  ies->data, ies->len);
403                 if (supp_rates_ie) {
404                         u8 ext_rates = supp_rates_ie[1];
405
406                         if (ext_rates > (WILC_MAX_RATES_SUPPORTED - rates_len))
407                                 param->supp_rates[0] = WILC_MAX_RATES_SUPPORTED;
408                         else
409                                 param->supp_rates[0] += ext_rates;
410
411                         memcpy(&param->supp_rates[rates_len + 1],
412                                supp_rates_ie + 2,
413                                (param->supp_rates[0] - rates_len));
414                 }
415         }
416
417         ht_ie = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, ies->data, ies->len);
418         if (ht_ie)
419                 param->ht_capable = true;
420
421         ret = cfg80211_get_p2p_attr(ies->data, ies->len,
422                                     IEEE80211_P2P_ATTR_ABSENCE_NOTICE,
423                                     (u8 *)&noa_attr, sizeof(noa_attr));
424         if (ret > 0) {
425                 param->tsf_lo = cpu_to_le32(ies->tsf);
426                 param->noa_enabled = 1;
427                 param->idx = noa_attr.index;
428                 if (noa_attr.oppps_ctwindow & IEEE80211_P2P_OPPPS_ENABLE_BIT) {
429                         param->opp_enabled = 1;
430                         param->opp_en.ct_window = noa_attr.oppps_ctwindow;
431                         param->opp_en.cnt = noa_attr.desc[0].count;
432                         param->opp_en.duration = noa_attr.desc[0].duration;
433                         param->opp_en.interval = noa_attr.desc[0].interval;
434                         param->opp_en.start_time = noa_attr.desc[0].start_time;
435                 } else {
436                         param->opp_enabled = 0;
437                         param->opp_dis.cnt = noa_attr.desc[0].count;
438                         param->opp_dis.duration = noa_attr.desc[0].duration;
439                         param->opp_dis.interval = noa_attr.desc[0].interval;
440                         param->opp_dis.start_time = noa_attr.desc[0].start_time;
441                 }
442         }
443         wmm_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
444                                          WLAN_OUI_TYPE_MICROSOFT_WMM,
445                                          ies->data, ies->len);
446         if (wmm_ie) {
447                 struct ieee80211_wmm_param_ie *ie;
448
449                 ie = (struct ieee80211_wmm_param_ie *)wmm_ie;
450                 if ((ie->oui_subtype == 0 || ie->oui_subtype == 1) &&
451                     ie->version == 1) {
452                         param->wmm_cap = true;
453                         if (ie->qos_info & BIT(7))
454                                 param->uapsd_cap = true;
455                 }
456         }
457
458         wpa_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
459                                          WLAN_OUI_TYPE_MICROSOFT_WPA,
460                                          ies->data, ies->len);
461         if (wpa_ie) {
462                 param->mode_802_11i = 1;
463                 param->rsn_found = true;
464         }
465
466         rsn_ie = cfg80211_find_ie(WLAN_EID_RSN, ies->data, ies->len);
467         if (rsn_ie) {
468                 int offset = 8;
469
470                 param->mode_802_11i = 2;
471                 param->rsn_found = true;
472                 /* extract RSN capabilities */
473                 offset += (rsn_ie[offset] * 4) + 2;
474                 offset += (rsn_ie[offset] * 4) + 2;
475                 memcpy(param->rsn_cap, &rsn_ie[offset], 2);
476         }
477
478         if (param->rsn_found) {
479                 int i;
480
481                 param->rsn_grp_policy = crypto->cipher_group & 0xFF;
482                 for (i = 0; i < crypto->n_ciphers_pairwise && i < 3; i++)
483                         param->p_suites[i] = crypto->ciphers_pairwise[i] & 0xFF;
484
485                 for (i = 0; i < crypto->n_akm_suites && i < 3; i++)
486                         param->akm_suites[i] = crypto->akm_suites[i] & 0xFF;
487         }
488
489         return (void *)param;
490 }
491
492 static void handle_rcvd_ntwrk_info(struct work_struct *work)
493 {
494         struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
495         struct wilc_rcvd_net_info *rcvd_info = &msg->body.net_info;
496         struct wilc_user_scan_req *scan_req = &msg->vif->hif_drv->usr_scan_req;
497         const u8 *ch_elm;
498         u8 *ies;
499         int ies_len;
500         size_t offset;
501
502         if (ieee80211_is_probe_resp(rcvd_info->mgmt->frame_control))
503                 offset = offsetof(struct ieee80211_mgmt, u.probe_resp.variable);
504         else if (ieee80211_is_beacon(rcvd_info->mgmt->frame_control))
505                 offset = offsetof(struct ieee80211_mgmt, u.beacon.variable);
506         else
507                 goto done;
508
509         ies = rcvd_info->mgmt->u.beacon.variable;
510         ies_len = rcvd_info->frame_len - offset;
511         if (ies_len <= 0)
512                 goto done;
513
514         ch_elm = cfg80211_find_ie(WLAN_EID_DS_PARAMS, ies, ies_len);
515         if (ch_elm && ch_elm[1] > 0)
516                 rcvd_info->ch = ch_elm[2];
517
518         if (scan_req->scan_result)
519                 scan_req->scan_result(SCAN_EVENT_NETWORK_FOUND, rcvd_info,
520                                       scan_req->arg);
521
522 done:
523         kfree(rcvd_info->mgmt);
524         kfree(msg);
525 }
526
527 static void host_int_get_assoc_res_info(struct wilc_vif *vif,
528                                         u8 *assoc_resp_info,
529                                         u32 max_assoc_resp_info_len,
530                                         u32 *rcvd_assoc_resp_info_len)
531 {
532         int result;
533         struct wid wid;
534
535         wid.id = WID_ASSOC_RES_INFO;
536         wid.type = WID_STR;
537         wid.val = assoc_resp_info;
538         wid.size = max_assoc_resp_info_len;
539
540         result = wilc_send_config_pkt(vif, WILC_GET_CFG, &wid, 1);
541         if (result) {
542                 *rcvd_assoc_resp_info_len = 0;
543                 netdev_err(vif->ndev, "Failed to send association response\n");
544                 return;
545         }
546
547         *rcvd_assoc_resp_info_len = wid.size;
548 }
549
550 static s32 wilc_parse_assoc_resp_info(u8 *buffer, u32 buffer_len,
551                                       struct wilc_conn_info *ret_conn_info)
552 {
553         u8 *ies;
554         u16 ies_len;
555         struct wilc_assoc_resp *res = (struct wilc_assoc_resp *)buffer;
556
557         ret_conn_info->status = le16_to_cpu(res->status_code);
558         if (ret_conn_info->status == WLAN_STATUS_SUCCESS) {
559                 ies = &buffer[sizeof(*res)];
560                 ies_len = buffer_len - sizeof(*res);
561
562                 ret_conn_info->resp_ies = kmemdup(ies, ies_len, GFP_KERNEL);
563                 if (!ret_conn_info->resp_ies)
564                         return -ENOMEM;
565
566                 ret_conn_info->resp_ies_len = ies_len;
567         }
568
569         return 0;
570 }
571
572 static inline void host_int_parse_assoc_resp_info(struct wilc_vif *vif,
573                                                   u8 mac_status)
574 {
575         struct host_if_drv *hif_drv = vif->hif_drv;
576         struct wilc_conn_info *conn_info = &hif_drv->conn_info;
577
578         if (mac_status == WILC_MAC_STATUS_CONNECTED) {
579                 u32 assoc_resp_info_len;
580
581                 memset(hif_drv->assoc_resp, 0, WILC_MAX_ASSOC_RESP_FRAME_SIZE);
582
583                 host_int_get_assoc_res_info(vif, hif_drv->assoc_resp,
584                                             WILC_MAX_ASSOC_RESP_FRAME_SIZE,
585                                             &assoc_resp_info_len);
586
587                 if (assoc_resp_info_len != 0) {
588                         s32 err = 0;
589
590                         err = wilc_parse_assoc_resp_info(hif_drv->assoc_resp,
591                                                          assoc_resp_info_len,
592                                                          conn_info);
593                         if (err)
594                                 netdev_err(vif->ndev,
595                                            "wilc_parse_assoc_resp_info() returned error %d\n",
596                                            err);
597                 }
598         }
599
600         del_timer(&hif_drv->connect_timer);
601         conn_info->conn_result(CONN_DISCONN_EVENT_CONN_RESP, mac_status,
602                                hif_drv->conn_info.arg);
603
604         if (mac_status == WILC_MAC_STATUS_CONNECTED &&
605             conn_info->status == WLAN_STATUS_SUCCESS) {
606                 ether_addr_copy(hif_drv->assoc_bssid, conn_info->bssid);
607                 hif_drv->hif_state = HOST_IF_CONNECTED;
608         } else {
609                 hif_drv->hif_state = HOST_IF_IDLE;
610         }
611
612         kfree(conn_info->resp_ies);
613         conn_info->resp_ies = NULL;
614         conn_info->resp_ies_len = 0;
615
616         kfree(conn_info->req_ies);
617         conn_info->req_ies = NULL;
618         conn_info->req_ies_len = 0;
619 }
620
621 static inline void host_int_handle_disconnect(struct wilc_vif *vif)
622 {
623         struct host_if_drv *hif_drv = vif->hif_drv;
624
625         if (hif_drv->usr_scan_req.scan_result) {
626                 del_timer(&hif_drv->scan_timer);
627                 handle_scan_done(vif, SCAN_EVENT_ABORTED);
628         }
629
630         if (hif_drv->conn_info.conn_result)
631                 hif_drv->conn_info.conn_result(CONN_DISCONN_EVENT_DISCONN_NOTIF,
632                                                0, hif_drv->conn_info.arg);
633         else
634                 netdev_err(vif->ndev, "%s: conn_result is NULL\n", __func__);
635
636         eth_zero_addr(hif_drv->assoc_bssid);
637
638         hif_drv->conn_info.req_ies_len = 0;
639         kfree(hif_drv->conn_info.req_ies);
640         hif_drv->conn_info.req_ies = NULL;
641         hif_drv->hif_state = HOST_IF_IDLE;
642 }
643
644 static void handle_rcvd_gnrl_async_info(struct work_struct *work)
645 {
646         struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
647         struct wilc_vif *vif = msg->vif;
648         struct wilc_rcvd_mac_info *mac_info = &msg->body.mac_info;
649         struct host_if_drv *hif_drv = vif->hif_drv;
650
651         if (!hif_drv) {
652                 netdev_err(vif->ndev, "%s: hif driver is NULL\n", __func__);
653                 goto free_msg;
654         }
655
656         if (!hif_drv->conn_info.conn_result) {
657                 netdev_err(vif->ndev, "%s: conn_result is NULL\n", __func__);
658                 goto free_msg;
659         }
660
661         if (hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP) {
662                 host_int_parse_assoc_resp_info(vif, mac_info->status);
663         } else if (mac_info->status == WILC_MAC_STATUS_DISCONNECTED) {
664                 if (hif_drv->hif_state == HOST_IF_CONNECTED) {
665                         host_int_handle_disconnect(vif);
666                 } else if (hif_drv->usr_scan_req.scan_result) {
667                         del_timer(&hif_drv->scan_timer);
668                         handle_scan_done(vif, SCAN_EVENT_ABORTED);
669                 }
670         }
671
672 free_msg:
673         kfree(msg);
674 }
675
676 int wilc_disconnect(struct wilc_vif *vif)
677 {
678         struct wid wid;
679         struct host_if_drv *hif_drv = vif->hif_drv;
680         struct wilc_user_scan_req *scan_req;
681         struct wilc_conn_info *conn_info;
682         int result;
683         u16 dummy_reason_code = 0;
684
685         wid.id = WID_DISCONNECT;
686         wid.type = WID_CHAR;
687         wid.val = (s8 *)&dummy_reason_code;
688         wid.size = sizeof(char);
689
690         result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
691         if (result) {
692                 netdev_err(vif->ndev, "Failed to send disconnect\n");
693                 return result;
694         }
695
696         scan_req = &hif_drv->usr_scan_req;
697         conn_info = &hif_drv->conn_info;
698
699         if (scan_req->scan_result) {
700                 del_timer(&hif_drv->scan_timer);
701                 scan_req->scan_result(SCAN_EVENT_ABORTED, NULL, scan_req->arg);
702                 scan_req->scan_result = NULL;
703         }
704
705         if (conn_info->conn_result) {
706                 if (hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP)
707                         del_timer(&hif_drv->connect_timer);
708
709                 conn_info->conn_result(CONN_DISCONN_EVENT_DISCONN_NOTIF, 0,
710                                        conn_info->arg);
711         } else {
712                 netdev_err(vif->ndev, "%s: conn_result is NULL\n", __func__);
713         }
714
715         hif_drv->hif_state = HOST_IF_IDLE;
716
717         eth_zero_addr(hif_drv->assoc_bssid);
718
719         conn_info->req_ies_len = 0;
720         kfree(conn_info->req_ies);
721         conn_info->req_ies = NULL;
722
723         return 0;
724 }
725
726 int wilc_get_statistics(struct wilc_vif *vif, struct rf_info *stats)
727 {
728         struct wid wid_list[5];
729         u32 wid_cnt = 0, result;
730
731         wid_list[wid_cnt].id = WID_LINKSPEED;
732         wid_list[wid_cnt].type = WID_CHAR;
733         wid_list[wid_cnt].size = sizeof(char);
734         wid_list[wid_cnt].val = (s8 *)&stats->link_speed;
735         wid_cnt++;
736
737         wid_list[wid_cnt].id = WID_RSSI;
738         wid_list[wid_cnt].type = WID_CHAR;
739         wid_list[wid_cnt].size = sizeof(char);
740         wid_list[wid_cnt].val = (s8 *)&stats->rssi;
741         wid_cnt++;
742
743         wid_list[wid_cnt].id = WID_SUCCESS_FRAME_COUNT;
744         wid_list[wid_cnt].type = WID_INT;
745         wid_list[wid_cnt].size = sizeof(u32);
746         wid_list[wid_cnt].val = (s8 *)&stats->tx_cnt;
747         wid_cnt++;
748
749         wid_list[wid_cnt].id = WID_RECEIVED_FRAGMENT_COUNT;
750         wid_list[wid_cnt].type = WID_INT;
751         wid_list[wid_cnt].size = sizeof(u32);
752         wid_list[wid_cnt].val = (s8 *)&stats->rx_cnt;
753         wid_cnt++;
754
755         wid_list[wid_cnt].id = WID_FAILED_COUNT;
756         wid_list[wid_cnt].type = WID_INT;
757         wid_list[wid_cnt].size = sizeof(u32);
758         wid_list[wid_cnt].val = (s8 *)&stats->tx_fail_cnt;
759         wid_cnt++;
760
761         result = wilc_send_config_pkt(vif, WILC_GET_CFG, wid_list, wid_cnt);
762         if (result) {
763                 netdev_err(vif->ndev, "Failed to send scan parameters\n");
764                 return result;
765         }
766
767         if (stats->link_speed > TCP_ACK_FILTER_LINK_SPEED_THRESH &&
768             stats->link_speed != DEFAULT_LINK_SPEED)
769                 wilc_enable_tcp_ack_filter(vif, true);
770         else if (stats->link_speed != DEFAULT_LINK_SPEED)
771                 wilc_enable_tcp_ack_filter(vif, false);
772
773         return result;
774 }
775
776 static void handle_get_statistics(struct work_struct *work)
777 {
778         struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
779         struct wilc_vif *vif = msg->vif;
780         struct rf_info *stats = (struct rf_info *)msg->body.data;
781
782         wilc_get_statistics(vif, stats);
783
784         kfree(msg);
785 }
786
787 static void wilc_hif_pack_sta_param(u8 *cur_byte, const u8 *mac,
788                                     struct station_parameters *params)
789 {
790         ether_addr_copy(cur_byte, mac);
791         cur_byte += ETH_ALEN;
792
793         put_unaligned_le16(params->aid, cur_byte);
794         cur_byte += 2;
795
796         *cur_byte++ = params->supported_rates_len;
797         if (params->supported_rates_len > 0)
798                 memcpy(cur_byte, params->supported_rates,
799                        params->supported_rates_len);
800         cur_byte += params->supported_rates_len;
801
802         if (params->ht_capa) {
803                 *cur_byte++ = true;
804                 memcpy(cur_byte, params->ht_capa,
805                        sizeof(struct ieee80211_ht_cap));
806         } else {
807                 *cur_byte++ = false;
808         }
809         cur_byte += sizeof(struct ieee80211_ht_cap);
810
811         put_unaligned_le16(params->sta_flags_mask, cur_byte);
812         cur_byte += 2;
813         put_unaligned_le16(params->sta_flags_set, cur_byte);
814 }
815
816 static int handle_remain_on_chan(struct wilc_vif *vif,
817                                  struct wilc_remain_ch *hif_remain_ch)
818 {
819         int result;
820         u8 remain_on_chan_flag;
821         struct wid wid;
822         struct host_if_drv *hif_drv = vif->hif_drv;
823
824         if (hif_drv->usr_scan_req.scan_result)
825                 return -EBUSY;
826
827         if (hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP)
828                 return -EBUSY;
829
830         if (vif->connecting)
831                 return -EBUSY;
832
833         remain_on_chan_flag = true;
834         wid.id = WID_REMAIN_ON_CHAN;
835         wid.type = WID_STR;
836         wid.size = 2;
837         wid.val = kmalloc(wid.size, GFP_KERNEL);
838         if (!wid.val)
839                 return -ENOMEM;
840
841         wid.val[0] = remain_on_chan_flag;
842         wid.val[1] = (s8)hif_remain_ch->ch;
843
844         result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
845         kfree(wid.val);
846         if (result)
847                 return -EBUSY;
848
849         hif_drv->remain_on_ch.arg = hif_remain_ch->arg;
850         hif_drv->remain_on_ch.expired = hif_remain_ch->expired;
851         hif_drv->remain_on_ch.ch = hif_remain_ch->ch;
852         hif_drv->remain_on_ch.cookie = hif_remain_ch->cookie;
853         hif_drv->remain_on_ch_timer_vif = vif;
854
855         return 0;
856 }
857
858 static int wilc_handle_roc_expired(struct wilc_vif *vif, u64 cookie)
859 {
860         u8 remain_on_chan_flag;
861         struct wid wid;
862         int result;
863         struct host_if_drv *hif_drv = vif->hif_drv;
864
865         if (vif->priv.p2p_listen_state) {
866                 remain_on_chan_flag = false;
867                 wid.id = WID_REMAIN_ON_CHAN;
868                 wid.type = WID_STR;
869                 wid.size = 2;
870
871                 wid.val = kmalloc(wid.size, GFP_KERNEL);
872                 if (!wid.val)
873                         return -ENOMEM;
874
875                 wid.val[0] = remain_on_chan_flag;
876                 wid.val[1] = WILC_FALSE_FRMWR_CHANNEL;
877
878                 result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
879                 kfree(wid.val);
880                 if (result != 0) {
881                         netdev_err(vif->ndev, "Failed to set remain channel\n");
882                         return -EINVAL;
883                 }
884
885                 if (hif_drv->remain_on_ch.expired) {
886                         hif_drv->remain_on_ch.expired(hif_drv->remain_on_ch.arg,
887                                                       cookie);
888                 }
889         } else {
890                 netdev_dbg(vif->ndev, "Not in listen state\n");
891         }
892
893         return 0;
894 }
895
896 static void wilc_handle_listen_state_expired(struct work_struct *work)
897 {
898         struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
899
900         wilc_handle_roc_expired(msg->vif, msg->body.remain_on_ch.cookie);
901         kfree(msg);
902 }
903
904 static void listen_timer_cb(struct timer_list *t)
905 {
906         struct host_if_drv *hif_drv = from_timer(hif_drv, t,
907                                                       remain_on_ch_timer);
908         struct wilc_vif *vif = hif_drv->remain_on_ch_timer_vif;
909         int result;
910         struct host_if_msg *msg;
911
912         del_timer(&vif->hif_drv->remain_on_ch_timer);
913
914         msg = wilc_alloc_work(vif, wilc_handle_listen_state_expired, false);
915         if (IS_ERR(msg))
916                 return;
917
918         msg->body.remain_on_ch.cookie = vif->hif_drv->remain_on_ch.cookie;
919
920         result = wilc_enqueue_work(msg);
921         if (result) {
922                 netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__);
923                 kfree(msg);
924         }
925 }
926
927 static void handle_set_mcast_filter(struct work_struct *work)
928 {
929         struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
930         struct wilc_vif *vif = msg->vif;
931         struct wilc_set_multicast *set_mc = &msg->body.mc_info;
932         int result;
933         struct wid wid;
934         u8 *cur_byte;
935
936         wid.id = WID_SETUP_MULTICAST_FILTER;
937         wid.type = WID_BIN;
938         wid.size = sizeof(struct wilc_set_multicast) + (set_mc->cnt * ETH_ALEN);
939         wid.val = kmalloc(wid.size, GFP_KERNEL);
940         if (!wid.val)
941                 goto error;
942
943         cur_byte = wid.val;
944         put_unaligned_le32(set_mc->enabled, cur_byte);
945         cur_byte += 4;
946
947         put_unaligned_le32(set_mc->cnt, cur_byte);
948         cur_byte += 4;
949
950         if (set_mc->cnt > 0 && set_mc->mc_list)
951                 memcpy(cur_byte, set_mc->mc_list, set_mc->cnt * ETH_ALEN);
952
953         result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
954         if (result)
955                 netdev_err(vif->ndev, "Failed to send setup multicast\n");
956
957 error:
958         kfree(set_mc->mc_list);
959         kfree(wid.val);
960         kfree(msg);
961 }
962
963 static void handle_scan_timer(struct work_struct *work)
964 {
965         struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
966
967         handle_scan_done(msg->vif, SCAN_EVENT_ABORTED);
968         kfree(msg);
969 }
970
971 static void handle_scan_complete(struct work_struct *work)
972 {
973         struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
974
975         del_timer(&msg->vif->hif_drv->scan_timer);
976
977         handle_scan_done(msg->vif, SCAN_EVENT_DONE);
978
979         kfree(msg);
980 }
981
982 static void timer_scan_cb(struct timer_list *t)
983 {
984         struct host_if_drv *hif_drv = from_timer(hif_drv, t, scan_timer);
985         struct wilc_vif *vif = hif_drv->scan_timer_vif;
986         struct host_if_msg *msg;
987         int result;
988
989         msg = wilc_alloc_work(vif, handle_scan_timer, false);
990         if (IS_ERR(msg))
991                 return;
992
993         result = wilc_enqueue_work(msg);
994         if (result)
995                 kfree(msg);
996 }
997
998 static void timer_connect_cb(struct timer_list *t)
999 {
1000         struct host_if_drv *hif_drv = from_timer(hif_drv, t,
1001                                                       connect_timer);
1002         struct wilc_vif *vif = hif_drv->connect_timer_vif;
1003         struct host_if_msg *msg;
1004         int result;
1005
1006         msg = wilc_alloc_work(vif, handle_connect_timeout, false);
1007         if (IS_ERR(msg))
1008                 return;
1009
1010         result = wilc_enqueue_work(msg);
1011         if (result)
1012                 kfree(msg);
1013 }
1014
1015 int wilc_remove_wep_key(struct wilc_vif *vif, u8 index)
1016 {
1017         struct wid wid;
1018         int result;
1019
1020         wid.id = WID_REMOVE_WEP_KEY;
1021         wid.type = WID_STR;
1022         wid.size = sizeof(char);
1023         wid.val = &index;
1024
1025         result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
1026         if (result)
1027                 netdev_err(vif->ndev,
1028                            "Failed to send remove wep key config packet\n");
1029         return result;
1030 }
1031
1032 int wilc_set_wep_default_keyid(struct wilc_vif *vif, u8 index)
1033 {
1034         struct wid wid;
1035         int result;
1036
1037         wid.id = WID_KEY_ID;
1038         wid.type = WID_CHAR;
1039         wid.size = sizeof(char);
1040         wid.val = &index;
1041         result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
1042         if (result)
1043                 netdev_err(vif->ndev,
1044                            "Failed to send wep default key config packet\n");
1045
1046         return result;
1047 }
1048
1049 int wilc_add_wep_key_bss_sta(struct wilc_vif *vif, const u8 *key, u8 len,
1050                              u8 index)
1051 {
1052         struct wid wid;
1053         int result;
1054         struct wilc_wep_key *wep_key;
1055
1056         wid.id = WID_ADD_WEP_KEY;
1057         wid.type = WID_STR;
1058         wid.size = sizeof(*wep_key) + len;
1059         wep_key = kzalloc(wid.size, GFP_KERNEL);
1060         if (!wep_key)
1061                 return -ENOMEM;
1062
1063         wid.val = (u8 *)wep_key;
1064
1065         wep_key->index = index;
1066         wep_key->key_len = len;
1067         memcpy(wep_key->key, key, len);
1068
1069         result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
1070         if (result)
1071                 netdev_err(vif->ndev,
1072                            "Failed to add wep key config packet\n");
1073
1074         kfree(wep_key);
1075         return result;
1076 }
1077
1078 int wilc_add_wep_key_bss_ap(struct wilc_vif *vif, const u8 *key, u8 len,
1079                             u8 index, u8 mode, enum authtype auth_type)
1080 {
1081         struct wid wid_list[3];
1082         int result;
1083         struct wilc_wep_key *wep_key;
1084
1085         wid_list[0].id = WID_11I_MODE;
1086         wid_list[0].type = WID_CHAR;
1087         wid_list[0].size = sizeof(char);
1088         wid_list[0].val = &mode;
1089
1090         wid_list[1].id = WID_AUTH_TYPE;
1091         wid_list[1].type = WID_CHAR;
1092         wid_list[1].size = sizeof(char);
1093         wid_list[1].val = (s8 *)&auth_type;
1094
1095         wid_list[2].id = WID_WEP_KEY_VALUE;
1096         wid_list[2].type = WID_STR;
1097         wid_list[2].size = sizeof(*wep_key) + len;
1098         wep_key = kzalloc(wid_list[2].size, GFP_KERNEL);
1099         if (!wep_key)
1100                 return -ENOMEM;
1101
1102         wid_list[2].val = (u8 *)wep_key;
1103
1104         wep_key->index = index;
1105         wep_key->key_len = len;
1106         memcpy(wep_key->key, key, len);
1107         result = wilc_send_config_pkt(vif, WILC_SET_CFG, wid_list,
1108                                       ARRAY_SIZE(wid_list));
1109         if (result)
1110                 netdev_err(vif->ndev,
1111                            "Failed to add wep ap key config packet\n");
1112
1113         kfree(wep_key);
1114         return result;
1115 }
1116
1117 int wilc_add_ptk(struct wilc_vif *vif, const u8 *ptk, u8 ptk_key_len,
1118                  const u8 *mac_addr, const u8 *rx_mic, const u8 *tx_mic,
1119                  u8 mode, u8 cipher_mode, u8 index)
1120 {
1121         int result = 0;
1122         u8 t_key_len  = ptk_key_len + WILC_RX_MIC_KEY_LEN + WILC_TX_MIC_KEY_LEN;
1123
1124         if (mode == WILC_AP_MODE) {
1125                 struct wid wid_list[2];
1126                 struct wilc_ap_wpa_ptk *key_buf;
1127
1128                 wid_list[0].id = WID_11I_MODE;
1129                 wid_list[0].type = WID_CHAR;
1130                 wid_list[0].size = sizeof(char);
1131                 wid_list[0].val = (s8 *)&cipher_mode;
1132
1133                 key_buf = kzalloc(sizeof(*key_buf) + t_key_len, GFP_KERNEL);
1134                 if (!key_buf)
1135                         return -ENOMEM;
1136
1137                 ether_addr_copy(key_buf->mac_addr, mac_addr);
1138                 key_buf->index = index;
1139                 key_buf->key_len = t_key_len;
1140                 memcpy(&key_buf->key[0], ptk, ptk_key_len);
1141
1142                 if (rx_mic)
1143                         memcpy(&key_buf->key[ptk_key_len], rx_mic,
1144                                WILC_RX_MIC_KEY_LEN);
1145
1146                 if (tx_mic)
1147                         memcpy(&key_buf->key[ptk_key_len + WILC_RX_MIC_KEY_LEN],
1148                                tx_mic, WILC_TX_MIC_KEY_LEN);
1149
1150                 wid_list[1].id = WID_ADD_PTK;
1151                 wid_list[1].type = WID_STR;
1152                 wid_list[1].size = sizeof(*key_buf) + t_key_len;
1153                 wid_list[1].val = (u8 *)key_buf;
1154                 result = wilc_send_config_pkt(vif, WILC_SET_CFG, wid_list,
1155                                               ARRAY_SIZE(wid_list));
1156                 kfree(key_buf);
1157         } else if (mode == WILC_STATION_MODE) {
1158                 struct wid wid;
1159                 struct wilc_sta_wpa_ptk *key_buf;
1160
1161                 key_buf = kzalloc(sizeof(*key_buf) + t_key_len, GFP_KERNEL);
1162                 if (!key_buf)
1163                         return -ENOMEM;
1164
1165                 ether_addr_copy(key_buf->mac_addr, mac_addr);
1166                 key_buf->key_len = t_key_len;
1167                 memcpy(&key_buf->key[0], ptk, ptk_key_len);
1168
1169                 if (rx_mic)
1170                         memcpy(&key_buf->key[ptk_key_len], rx_mic,
1171                                WILC_RX_MIC_KEY_LEN);
1172
1173                 if (tx_mic)
1174                         memcpy(&key_buf->key[ptk_key_len + WILC_RX_MIC_KEY_LEN],
1175                                tx_mic, WILC_TX_MIC_KEY_LEN);
1176
1177                 wid.id = WID_ADD_PTK;
1178                 wid.type = WID_STR;
1179                 wid.size = sizeof(*key_buf) + t_key_len;
1180                 wid.val = (s8 *)key_buf;
1181                 result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
1182                 kfree(key_buf);
1183         }
1184
1185         return result;
1186 }
1187
1188 int wilc_add_rx_gtk(struct wilc_vif *vif, const u8 *rx_gtk, u8 gtk_key_len,
1189                     u8 index, u32 key_rsc_len, const u8 *key_rsc,
1190                     const u8 *rx_mic, const u8 *tx_mic, u8 mode,
1191                     u8 cipher_mode)
1192 {
1193         int result = 0;
1194         struct wilc_gtk_key *gtk_key;
1195         int t_key_len = gtk_key_len + WILC_RX_MIC_KEY_LEN + WILC_TX_MIC_KEY_LEN;
1196
1197         gtk_key = kzalloc(sizeof(*gtk_key) + t_key_len, GFP_KERNEL);
1198         if (!gtk_key)
1199                 return -ENOMEM;
1200
1201         /* fill bssid value only in station mode */
1202         if (mode == WILC_STATION_MODE &&
1203             vif->hif_drv->hif_state == HOST_IF_CONNECTED)
1204                 memcpy(gtk_key->mac_addr, vif->hif_drv->assoc_bssid, ETH_ALEN);
1205
1206         if (key_rsc)
1207                 memcpy(gtk_key->rsc, key_rsc, 8);
1208         gtk_key->index = index;
1209         gtk_key->key_len = t_key_len;
1210         memcpy(&gtk_key->key[0], rx_gtk, gtk_key_len);
1211
1212         if (rx_mic)
1213                 memcpy(&gtk_key->key[gtk_key_len], rx_mic, WILC_RX_MIC_KEY_LEN);
1214
1215         if (tx_mic)
1216                 memcpy(&gtk_key->key[gtk_key_len + WILC_RX_MIC_KEY_LEN],
1217                        tx_mic, WILC_TX_MIC_KEY_LEN);
1218
1219         if (mode == WILC_AP_MODE) {
1220                 struct wid wid_list[2];
1221
1222                 wid_list[0].id = WID_11I_MODE;
1223                 wid_list[0].type = WID_CHAR;
1224                 wid_list[0].size = sizeof(char);
1225                 wid_list[0].val = (s8 *)&cipher_mode;
1226
1227                 wid_list[1].id = WID_ADD_RX_GTK;
1228                 wid_list[1].type = WID_STR;
1229                 wid_list[1].size = sizeof(*gtk_key) + t_key_len;
1230                 wid_list[1].val = (u8 *)gtk_key;
1231
1232                 result = wilc_send_config_pkt(vif, WILC_SET_CFG, wid_list,
1233                                               ARRAY_SIZE(wid_list));
1234         } else if (mode == WILC_STATION_MODE) {
1235                 struct wid wid;
1236
1237                 wid.id = WID_ADD_RX_GTK;
1238                 wid.type = WID_STR;
1239                 wid.size = sizeof(*gtk_key) + t_key_len;
1240                 wid.val = (u8 *)gtk_key;
1241                 result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
1242         }
1243
1244         kfree(gtk_key);
1245         return result;
1246 }
1247
1248 int wilc_set_pmkid_info(struct wilc_vif *vif, struct wilc_pmkid_attr *pmkid)
1249 {
1250         struct wid wid;
1251
1252         wid.id = WID_PMKID_INFO;
1253         wid.type = WID_STR;
1254         wid.size = (pmkid->numpmkid * sizeof(struct wilc_pmkid)) + 1;
1255         wid.val = (u8 *)pmkid;
1256
1257         return wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
1258 }
1259
1260 int wilc_get_mac_address(struct wilc_vif *vif, u8 *mac_addr)
1261 {
1262         int result;
1263         struct wid wid;
1264
1265         wid.id = WID_MAC_ADDR;
1266         wid.type = WID_STR;
1267         wid.size = ETH_ALEN;
1268         wid.val = mac_addr;
1269
1270         result = wilc_send_config_pkt(vif, WILC_GET_CFG, &wid, 1);
1271         if (result)
1272                 netdev_err(vif->ndev, "Failed to get mac address\n");
1273
1274         return result;
1275 }
1276
1277 int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ies,
1278                       size_t ies_len)
1279 {
1280         int result;
1281         struct host_if_drv *hif_drv = vif->hif_drv;
1282         struct wilc_conn_info *conn_info = &hif_drv->conn_info;
1283
1284         if (bssid)
1285                 ether_addr_copy(conn_info->bssid, bssid);
1286
1287         if (ies) {
1288                 conn_info->req_ies_len = ies_len;
1289                 conn_info->req_ies = kmemdup(ies, ies_len, GFP_KERNEL);
1290                 if (!conn_info->req_ies)
1291                         return -ENOMEM;
1292         }
1293
1294         result = wilc_send_connect_wid(vif);
1295         if (result)
1296                 goto free_ies;
1297
1298         hif_drv->connect_timer_vif = vif;
1299         mod_timer(&hif_drv->connect_timer,
1300                   jiffies + msecs_to_jiffies(WILC_HIF_CONNECT_TIMEOUT_MS));
1301
1302         return 0;
1303
1304 free_ies:
1305         kfree(conn_info->req_ies);
1306
1307         return result;
1308 }
1309
1310 int wilc_set_mac_chnl_num(struct wilc_vif *vif, u8 channel)
1311 {
1312         struct wid wid;
1313         int result;
1314
1315         wid.id = WID_CURRENT_CHANNEL;
1316         wid.type = WID_CHAR;
1317         wid.size = sizeof(char);
1318         wid.val = &channel;
1319
1320         result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
1321         if (result)
1322                 netdev_err(vif->ndev, "Failed to set channel\n");
1323
1324         return result;
1325 }
1326
1327 int wilc_set_operation_mode(struct wilc_vif *vif, int index, u8 mode,
1328                             u8 ifc_id)
1329 {
1330         struct wid wid;
1331         int result;
1332         struct wilc_drv_handler drv;
1333
1334         wid.id = WID_SET_OPERATION_MODE;
1335         wid.type = WID_STR;
1336         wid.size = sizeof(drv);
1337         wid.val = (u8 *)&drv;
1338
1339         drv.handler = cpu_to_le32(index);
1340         drv.mode = (ifc_id | (mode << 1));
1341
1342         result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
1343         if (result)
1344                 netdev_err(vif->ndev, "Failed to set driver handler\n");
1345
1346         return result;
1347 }
1348
1349 s32 wilc_get_inactive_time(struct wilc_vif *vif, const u8 *mac, u32 *out_val)
1350 {
1351         struct wid wid;
1352         s32 result;
1353
1354         wid.id = WID_SET_STA_MAC_INACTIVE_TIME;
1355         wid.type = WID_STR;
1356         wid.size = ETH_ALEN;
1357         wid.val = kzalloc(wid.size, GFP_KERNEL);
1358         if (!wid.val)
1359                 return -ENOMEM;
1360
1361         ether_addr_copy(wid.val, mac);
1362         result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
1363         kfree(wid.val);
1364         if (result) {
1365                 netdev_err(vif->ndev, "Failed to set inactive mac\n");
1366                 return result;
1367         }
1368
1369         wid.id = WID_GET_INACTIVE_TIME;
1370         wid.type = WID_INT;
1371         wid.val = (s8 *)out_val;
1372         wid.size = sizeof(u32);
1373         result = wilc_send_config_pkt(vif, WILC_GET_CFG, &wid, 1);
1374         if (result)
1375                 netdev_err(vif->ndev, "Failed to get inactive time\n");
1376
1377         return result;
1378 }
1379
1380 int wilc_get_rssi(struct wilc_vif *vif, s8 *rssi_level)
1381 {
1382         struct wid wid;
1383         int result;
1384
1385         if (!rssi_level) {
1386                 netdev_err(vif->ndev, "%s: RSSI level is NULL\n", __func__);
1387                 return -EFAULT;
1388         }
1389
1390         wid.id = WID_RSSI;
1391         wid.type = WID_CHAR;
1392         wid.size = sizeof(char);
1393         wid.val = rssi_level;
1394         result = wilc_send_config_pkt(vif, WILC_GET_CFG, &wid, 1);
1395         if (result)
1396                 netdev_err(vif->ndev, "Failed to get RSSI value\n");
1397
1398         return result;
1399 }
1400
1401 static int wilc_get_stats_async(struct wilc_vif *vif, struct rf_info *stats)
1402 {
1403         int result;
1404         struct host_if_msg *msg;
1405
1406         msg = wilc_alloc_work(vif, handle_get_statistics, false);
1407         if (IS_ERR(msg))
1408                 return PTR_ERR(msg);
1409
1410         msg->body.data = (char *)stats;
1411
1412         result = wilc_enqueue_work(msg);
1413         if (result) {
1414                 netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__);
1415                 kfree(msg);
1416                 return result;
1417         }
1418
1419         return result;
1420 }
1421
1422 int wilc_hif_set_cfg(struct wilc_vif *vif, struct cfg_param_attr *param)
1423 {
1424         struct wid wid_list[4];
1425         int i = 0;
1426
1427         if (param->flag & WILC_CFG_PARAM_RETRY_SHORT) {
1428                 wid_list[i].id = WID_SHORT_RETRY_LIMIT;
1429                 wid_list[i].val = (s8 *)&param->short_retry_limit;
1430                 wid_list[i].type = WID_SHORT;
1431                 wid_list[i].size = sizeof(u16);
1432                 i++;
1433         }
1434         if (param->flag & WILC_CFG_PARAM_RETRY_LONG) {
1435                 wid_list[i].id = WID_LONG_RETRY_LIMIT;
1436                 wid_list[i].val = (s8 *)&param->long_retry_limit;
1437                 wid_list[i].type = WID_SHORT;
1438                 wid_list[i].size = sizeof(u16);
1439                 i++;
1440         }
1441         if (param->flag & WILC_CFG_PARAM_FRAG_THRESHOLD) {
1442                 wid_list[i].id = WID_FRAG_THRESHOLD;
1443                 wid_list[i].val = (s8 *)&param->frag_threshold;
1444                 wid_list[i].type = WID_SHORT;
1445                 wid_list[i].size = sizeof(u16);
1446                 i++;
1447         }
1448         if (param->flag & WILC_CFG_PARAM_RTS_THRESHOLD) {
1449                 wid_list[i].id = WID_RTS_THRESHOLD;
1450                 wid_list[i].val = (s8 *)&param->rts_threshold;
1451                 wid_list[i].type = WID_SHORT;
1452                 wid_list[i].size = sizeof(u16);
1453                 i++;
1454         }
1455
1456         return wilc_send_config_pkt(vif, WILC_SET_CFG, wid_list, i);
1457 }
1458
1459 static void get_periodic_rssi(struct timer_list *t)
1460 {
1461         struct wilc_vif *vif = from_timer(vif, t, periodic_rssi);
1462
1463         if (!vif->hif_drv) {
1464                 netdev_err(vif->ndev, "%s: hif driver is NULL", __func__);
1465                 return;
1466         }
1467
1468         if (vif->hif_drv->hif_state == HOST_IF_CONNECTED)
1469                 wilc_get_stats_async(vif, &vif->periodic_stat);
1470
1471         mod_timer(&vif->periodic_rssi, jiffies + msecs_to_jiffies(5000));
1472 }
1473
1474 int wilc_init(struct net_device *dev, struct host_if_drv **hif_drv_handler)
1475 {
1476         struct host_if_drv *hif_drv;
1477         struct wilc_vif *vif = netdev_priv(dev);
1478         struct wilc *wilc = vif->wilc;
1479
1480         hif_drv  = kzalloc(sizeof(*hif_drv), GFP_KERNEL);
1481         if (!hif_drv)
1482                 return -ENOMEM;
1483
1484         *hif_drv_handler = hif_drv;
1485
1486         vif->hif_drv = hif_drv;
1487
1488         if (wilc->clients_count == 0)
1489                 mutex_init(&wilc->deinit_lock);
1490
1491         timer_setup(&vif->periodic_rssi, get_periodic_rssi, 0);
1492         mod_timer(&vif->periodic_rssi, jiffies + msecs_to_jiffies(5000));
1493
1494         timer_setup(&hif_drv->scan_timer, timer_scan_cb, 0);
1495         timer_setup(&hif_drv->connect_timer, timer_connect_cb, 0);
1496         timer_setup(&hif_drv->remain_on_ch_timer, listen_timer_cb, 0);
1497
1498         hif_drv->hif_state = HOST_IF_IDLE;
1499
1500         hif_drv->p2p_timeout = 0;
1501
1502         wilc->clients_count++;
1503
1504         return 0;
1505 }
1506
1507 int wilc_deinit(struct wilc_vif *vif)
1508 {
1509         int result = 0;
1510         struct host_if_drv *hif_drv = vif->hif_drv;
1511
1512         if (!hif_drv) {
1513                 netdev_err(vif->ndev, "%s: hif driver is NULL", __func__);
1514                 return -EFAULT;
1515         }
1516
1517         mutex_lock(&vif->wilc->deinit_lock);
1518
1519         del_timer_sync(&hif_drv->scan_timer);
1520         del_timer_sync(&hif_drv->connect_timer);
1521         del_timer_sync(&vif->periodic_rssi);
1522         del_timer_sync(&hif_drv->remain_on_ch_timer);
1523
1524         if (hif_drv->usr_scan_req.scan_result) {
1525                 hif_drv->usr_scan_req.scan_result(SCAN_EVENT_ABORTED, NULL,
1526                                                   hif_drv->usr_scan_req.arg);
1527                 hif_drv->usr_scan_req.scan_result = NULL;
1528         }
1529
1530         hif_drv->hif_state = HOST_IF_IDLE;
1531
1532         kfree(hif_drv);
1533         vif->hif_drv = NULL;
1534         vif->wilc->clients_count--;
1535         mutex_unlock(&vif->wilc->deinit_lock);
1536         return result;
1537 }
1538
1539 void wilc_network_info_received(struct wilc *wilc, u8 *buffer, u32 length)
1540 {
1541         int result;
1542         struct host_if_msg *msg;
1543         int id;
1544         struct host_if_drv *hif_drv;
1545         struct wilc_vif *vif;
1546
1547         id = get_unaligned_le32(&buffer[length - 4]);
1548         vif = wilc_get_vif_from_idx(wilc, id);
1549         if (!vif)
1550                 return;
1551         hif_drv = vif->hif_drv;
1552
1553         if (!hif_drv) {
1554                 netdev_err(vif->ndev, "driver not init[%p]\n", hif_drv);
1555                 return;
1556         }
1557
1558         msg = wilc_alloc_work(vif, handle_rcvd_ntwrk_info, false);
1559         if (IS_ERR(msg))
1560                 return;
1561
1562         msg->body.net_info.frame_len = get_unaligned_le16(&buffer[6]) - 1;
1563         msg->body.net_info.rssi = buffer[8];
1564         msg->body.net_info.mgmt = kmemdup(&buffer[9],
1565                                           msg->body.net_info.frame_len,
1566                                           GFP_KERNEL);
1567         if (!msg->body.net_info.mgmt) {
1568                 kfree(msg);
1569                 return;
1570         }
1571
1572         result = wilc_enqueue_work(msg);
1573         if (result) {
1574                 netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__);
1575                 kfree(msg->body.net_info.mgmt);
1576                 kfree(msg);
1577         }
1578 }
1579
1580 void wilc_gnrl_async_info_received(struct wilc *wilc, u8 *buffer, u32 length)
1581 {
1582         int result;
1583         struct host_if_msg *msg;
1584         int id;
1585         struct host_if_drv *hif_drv;
1586         struct wilc_vif *vif;
1587
1588         mutex_lock(&wilc->deinit_lock);
1589
1590         id = get_unaligned_le32(&buffer[length - 4]);
1591         vif = wilc_get_vif_from_idx(wilc, id);
1592         if (!vif) {
1593                 mutex_unlock(&wilc->deinit_lock);
1594                 return;
1595         }
1596
1597         hif_drv = vif->hif_drv;
1598
1599         if (!hif_drv) {
1600                 mutex_unlock(&wilc->deinit_lock);
1601                 return;
1602         }
1603
1604         if (!hif_drv->conn_info.conn_result) {
1605                 netdev_err(vif->ndev, "%s: conn_result is NULL\n", __func__);
1606                 mutex_unlock(&wilc->deinit_lock);
1607                 return;
1608         }
1609
1610         msg = wilc_alloc_work(vif, handle_rcvd_gnrl_async_info, false);
1611         if (IS_ERR(msg)) {
1612                 mutex_unlock(&wilc->deinit_lock);
1613                 return;
1614         }
1615
1616         msg->body.mac_info.status = buffer[7];
1617         result = wilc_enqueue_work(msg);
1618         if (result) {
1619                 netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__);
1620                 kfree(msg);
1621         }
1622
1623         mutex_unlock(&wilc->deinit_lock);
1624 }
1625
1626 void wilc_scan_complete_received(struct wilc *wilc, u8 *buffer, u32 length)
1627 {
1628         int result;
1629         int id;
1630         struct host_if_drv *hif_drv;
1631         struct wilc_vif *vif;
1632
1633         id = get_unaligned_le32(&buffer[length - 4]);
1634         vif = wilc_get_vif_from_idx(wilc, id);
1635         if (!vif)
1636                 return;
1637         hif_drv = vif->hif_drv;
1638
1639         if (!hif_drv)
1640                 return;
1641
1642         if (hif_drv->usr_scan_req.scan_result) {
1643                 struct host_if_msg *msg;
1644
1645                 msg = wilc_alloc_work(vif, handle_scan_complete, false);
1646                 if (IS_ERR(msg))
1647                         return;
1648
1649                 result = wilc_enqueue_work(msg);
1650                 if (result) {
1651                         netdev_err(vif->ndev, "%s: enqueue work failed\n",
1652                                    __func__);
1653                         kfree(msg);
1654                 }
1655         }
1656 }
1657
1658 int wilc_remain_on_channel(struct wilc_vif *vif, u64 cookie,
1659                            u32 duration, u16 chan,
1660                            void (*expired)(void *, u64),
1661                            void *user_arg)
1662 {
1663         struct wilc_remain_ch roc;
1664         int result;
1665
1666         roc.ch = chan;
1667         roc.expired = expired;
1668         roc.arg = user_arg;
1669         roc.duration = duration;
1670         roc.cookie = cookie;
1671         result = handle_remain_on_chan(vif, &roc);
1672         if (result)
1673                 netdev_err(vif->ndev, "%s: failed to set remain on channel\n",
1674                            __func__);
1675
1676         return result;
1677 }
1678
1679 int wilc_listen_state_expired(struct wilc_vif *vif, u64 cookie)
1680 {
1681         if (!vif->hif_drv) {
1682                 netdev_err(vif->ndev, "%s: hif driver is NULL", __func__);
1683                 return -EFAULT;
1684         }
1685
1686         del_timer(&vif->hif_drv->remain_on_ch_timer);
1687
1688         return wilc_handle_roc_expired(vif, cookie);
1689 }
1690
1691 void wilc_frame_register(struct wilc_vif *vif, u16 frame_type, bool reg)
1692 {
1693         struct wid wid;
1694         int result;
1695         struct wilc_reg_frame reg_frame;
1696
1697         wid.id = WID_REGISTER_FRAME;
1698         wid.type = WID_STR;
1699         wid.size = sizeof(reg_frame);
1700         wid.val = (u8 *)&reg_frame;
1701
1702         memset(&reg_frame, 0x0, sizeof(reg_frame));
1703
1704         if (reg)
1705                 reg_frame.reg = 1;
1706
1707         switch (frame_type) {
1708         case IEEE80211_STYPE_ACTION:
1709                 reg_frame.reg_id = WILC_FW_ACTION_FRM_IDX;
1710                 break;
1711
1712         case IEEE80211_STYPE_PROBE_REQ:
1713                 reg_frame.reg_id = WILC_FW_PROBE_REQ_IDX;
1714                 break;
1715
1716         default:
1717                 break;
1718         }
1719         reg_frame.frame_type = cpu_to_le16(frame_type);
1720         result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
1721         if (result)
1722                 netdev_err(vif->ndev, "Failed to frame register\n");
1723 }
1724
1725 int wilc_add_beacon(struct wilc_vif *vif, u32 interval, u32 dtim_period,
1726                     struct cfg80211_beacon_data *params)
1727 {
1728         struct wid wid;
1729         int result;
1730         u8 *cur_byte;
1731
1732         wid.id = WID_ADD_BEACON;
1733         wid.type = WID_BIN;
1734         wid.size = params->head_len + params->tail_len + 16;
1735         wid.val = kzalloc(wid.size, GFP_KERNEL);
1736         if (!wid.val)
1737                 return -ENOMEM;
1738
1739         cur_byte = wid.val;
1740         put_unaligned_le32(interval, cur_byte);
1741         cur_byte += 4;
1742         put_unaligned_le32(dtim_period, cur_byte);
1743         cur_byte += 4;
1744         put_unaligned_le32(params->head_len, cur_byte);
1745         cur_byte += 4;
1746
1747         if (params->head_len > 0)
1748                 memcpy(cur_byte, params->head, params->head_len);
1749         cur_byte += params->head_len;
1750
1751         put_unaligned_le32(params->tail_len, cur_byte);
1752         cur_byte += 4;
1753
1754         if (params->tail_len > 0)
1755                 memcpy(cur_byte, params->tail, params->tail_len);
1756
1757         result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
1758         if (result)
1759                 netdev_err(vif->ndev, "Failed to send add beacon\n");
1760
1761         kfree(wid.val);
1762
1763         return result;
1764 }
1765
1766 int wilc_del_beacon(struct wilc_vif *vif)
1767 {
1768         int result;
1769         struct wid wid;
1770         u8 del_beacon = 0;
1771
1772         wid.id = WID_DEL_BEACON;
1773         wid.type = WID_CHAR;
1774         wid.size = sizeof(char);
1775         wid.val = &del_beacon;
1776
1777         result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
1778         if (result)
1779                 netdev_err(vif->ndev, "Failed to send delete beacon\n");
1780
1781         return result;
1782 }
1783
1784 int wilc_add_station(struct wilc_vif *vif, const u8 *mac,
1785                      struct station_parameters *params)
1786 {
1787         struct wid wid;
1788         int result;
1789         u8 *cur_byte;
1790
1791         wid.id = WID_ADD_STA;
1792         wid.type = WID_BIN;
1793         wid.size = WILC_ADD_STA_LENGTH + params->supported_rates_len;
1794         wid.val = kmalloc(wid.size, GFP_KERNEL);
1795         if (!wid.val)
1796                 return -ENOMEM;
1797
1798         cur_byte = wid.val;
1799         wilc_hif_pack_sta_param(cur_byte, mac, params);
1800
1801         result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
1802         if (result != 0)
1803                 netdev_err(vif->ndev, "Failed to send add station\n");
1804
1805         kfree(wid.val);
1806
1807         return result;
1808 }
1809
1810 int wilc_del_station(struct wilc_vif *vif, const u8 *mac_addr)
1811 {
1812         struct wid wid;
1813         int result;
1814
1815         wid.id = WID_REMOVE_STA;
1816         wid.type = WID_BIN;
1817         wid.size = ETH_ALEN;
1818         wid.val = kzalloc(wid.size, GFP_KERNEL);
1819         if (!wid.val)
1820                 return -ENOMEM;
1821
1822         if (!mac_addr)
1823                 eth_broadcast_addr(wid.val);
1824         else
1825                 ether_addr_copy(wid.val, mac_addr);
1826
1827         result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
1828         if (result)
1829                 netdev_err(vif->ndev, "Failed to del station\n");
1830
1831         kfree(wid.val);
1832
1833         return result;
1834 }
1835
1836 int wilc_del_allstation(struct wilc_vif *vif, u8 mac_addr[][ETH_ALEN])
1837 {
1838         struct wid wid;
1839         int result;
1840         int i;
1841         u8 assoc_sta = 0;
1842         struct wilc_del_all_sta del_sta;
1843
1844         memset(&del_sta, 0x0, sizeof(del_sta));
1845         for (i = 0; i < WILC_MAX_NUM_STA; i++) {
1846                 if (!is_zero_ether_addr(mac_addr[i])) {
1847                         assoc_sta++;
1848                         ether_addr_copy(del_sta.mac[i], mac_addr[i]);
1849                 }
1850         }
1851
1852         if (!assoc_sta)
1853                 return 0;
1854
1855         del_sta.assoc_sta = assoc_sta;
1856
1857         wid.id = WID_DEL_ALL_STA;
1858         wid.type = WID_STR;
1859         wid.size = (assoc_sta * ETH_ALEN) + 1;
1860         wid.val = (u8 *)&del_sta;
1861
1862         result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
1863         if (result)
1864                 netdev_err(vif->ndev, "Failed to send delete all station\n");
1865
1866         return result;
1867 }
1868
1869 int wilc_edit_station(struct wilc_vif *vif, const u8 *mac,
1870                       struct station_parameters *params)
1871 {
1872         struct wid wid;
1873         int result;
1874         u8 *cur_byte;
1875
1876         wid.id = WID_EDIT_STA;
1877         wid.type = WID_BIN;
1878         wid.size = WILC_ADD_STA_LENGTH + params->supported_rates_len;
1879         wid.val = kmalloc(wid.size, GFP_KERNEL);
1880         if (!wid.val)
1881                 return -ENOMEM;
1882
1883         cur_byte = wid.val;
1884         wilc_hif_pack_sta_param(cur_byte, mac, params);
1885
1886         result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
1887         if (result)
1888                 netdev_err(vif->ndev, "Failed to send edit station\n");
1889
1890         kfree(wid.val);
1891         return result;
1892 }
1893
1894 int wilc_set_power_mgmt(struct wilc_vif *vif, bool enabled, u32 timeout)
1895 {
1896         struct wid wid;
1897         int result;
1898         s8 power_mode;
1899
1900         if (enabled)
1901                 power_mode = WILC_FW_MIN_FAST_PS;
1902         else
1903                 power_mode = WILC_FW_NO_POWERSAVE;
1904
1905         wid.id = WID_POWER_MANAGEMENT;
1906         wid.val = &power_mode;
1907         wid.size = sizeof(char);
1908         result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
1909         if (result)
1910                 netdev_err(vif->ndev, "Failed to send power management\n");
1911
1912         return result;
1913 }
1914
1915 int wilc_setup_multicast_filter(struct wilc_vif *vif, u32 enabled, u32 count,
1916                                 u8 *mc_list)
1917 {
1918         int result;
1919         struct host_if_msg *msg;
1920
1921         msg = wilc_alloc_work(vif, handle_set_mcast_filter, false);
1922         if (IS_ERR(msg))
1923                 return PTR_ERR(msg);
1924
1925         msg->body.mc_info.enabled = enabled;
1926         msg->body.mc_info.cnt = count;
1927         msg->body.mc_info.mc_list = mc_list;
1928
1929         result = wilc_enqueue_work(msg);
1930         if (result) {
1931                 netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__);
1932                 kfree(msg);
1933         }
1934         return result;
1935 }
1936
1937 int wilc_set_tx_power(struct wilc_vif *vif, u8 tx_power)
1938 {
1939         struct wid wid;
1940
1941         wid.id = WID_TX_POWER;
1942         wid.type = WID_CHAR;
1943         wid.val = &tx_power;
1944         wid.size = sizeof(char);
1945
1946         return wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
1947 }
1948
1949 int wilc_get_tx_power(struct wilc_vif *vif, u8 *tx_power)
1950 {
1951         struct wid wid;
1952
1953         wid.id = WID_TX_POWER;
1954         wid.type = WID_CHAR;
1955         wid.val = tx_power;
1956         wid.size = sizeof(char);
1957
1958         return wilc_send_config_pkt(vif, WILC_GET_CFG, &wid, 1);
1959 }