1
2
3
4
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
15struct wilc_rcvd_mac_info {
16 u8 status;
17};
18
19struct wilc_set_multicast {
20 u32 enabled;
21 u32 cnt;
22 u8 *mc_list;
23};
24
25struct wilc_del_all_sta {
26 u8 assoc_sta;
27 u8 mac[WILC_MAX_NUM_STA][ETH_ALEN];
28};
29
30struct wilc_op_mode {
31 __le32 mode;
32};
33
34struct wilc_reg_frame {
35 bool reg;
36 u8 reg_id;
37 __le16 frame_type;
38} __packed;
39
40struct wilc_drv_handler {
41 __le32 handler;
42 u8 mode;
43} __packed;
44
45struct wilc_wep_key {
46 u8 index;
47 u8 key_len;
48 u8 key[0];
49} __packed;
50
51struct wilc_sta_wpa_ptk {
52 u8 mac_addr[ETH_ALEN];
53 u8 key_len;
54 u8 key[0];
55} __packed;
56
57struct wilc_ap_wpa_ptk {
58 u8 mac_addr[ETH_ALEN];
59 u8 index;
60 u8 key_len;
61 u8 key[0];
62} __packed;
63
64struct 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
72union 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
80struct 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
89struct wilc_noa_opp_enable {
90 u8 ct_window;
91 u8 cnt;
92 __le32 duration;
93 __le32 interval;
94 __le32 start_time;
95} __packed;
96
97struct wilc_noa_opp_disable {
98 u8 cnt;
99 __le32 duration;
100 __le32 interval;
101 __le32 start_time;
102} __packed;
103
104struct 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
135static struct host_if_msg*
136wilc_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
156static 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
170
171
172
173int wilc_get_vif_idx(struct wilc_vif *vif)
174{
175 return vif->idx + 1;
176}
177
178
179
180
181
182
183static 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
193static 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
231int 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
330error:
331 if (search) {
332 kfree(search->ssid_info);
333 kfree(search_ssid_vals);
334 }
335
336 return result;
337}
338
339static 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
384error:
385
386 kfree(conn_attr->req_ies);
387 conn_attr->req_ies = NULL;
388
389 return result;
390}
391
392static 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
431out:
432 kfree(msg);
433}
434
435void *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(¶m->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(¶m->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
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
563static 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
593done:
594 kfree(rcvd_info->mgmt);
595 kfree(msg);
596}
597
598static 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
622static 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
644static 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
699static 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
726static 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
754free_msg:
755 kfree(msg);
756}
757
758int 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
812void 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
821int 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
874static 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
885static 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, ¶ms->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
914static 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
957static 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
997free_msg:
998 kfree(msg);
999}
1000
1001static 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
1024static 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
1055error:
1056 kfree(set_mc->mc_list);
1057 kfree(wid.val);
1058 kfree(msg);
1059}
1060
1061static 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
1069static 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
1084static 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
1100static 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
1117int 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
1135int 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
1153int 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
1183int 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
1223int 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
1296int 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
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(>k_key->key[0], rx_gtk, gtk_key_len);
1319
1320 if (rx_mic)
1321 memcpy(>k_key->key[gtk_key_len], rx_mic, WILC_RX_MIC_KEY_LEN);
1322
1323 if (tx_mic)
1324 memcpy(>k_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
1358int 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
1374int 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
1392int 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
1421free_ies:
1422 kfree(conn_info->req_ies);
1423
1424 return result;
1425}
1426
1427int 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
1445int 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
1472int 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
1493s32 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
1526int 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
1548static 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
1569int 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 *)¶m->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 *)¶m->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 *)¶m->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 *)¶m->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
1610static 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
1625int 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
1665int 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
1699void 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
1740void 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
1786void 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
1818int 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
1839int 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
1867void 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 *)®_frame;
1877
1878 memset(®_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
1900int 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
1942int 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
1961int 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
1988int 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
2015int 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
2049int 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
2075int 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
2100int 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
2122int 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
2138int 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}
2153