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