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