1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (c) 2012 - 2018 Microchip Technology Inc., and its subsidiaries.
4  * All rights reserved.
5  */
6 
7 #include "wilc_wfi_netdevice.h"
8 
9 #define HOST_IF_SCAN_TIMEOUT                    4000
10 #define HOST_IF_CONNECT_TIMEOUT                 9500
11 
12 #define FALSE_FRMWR_CHANNEL			100
13 
14 #define REAL_JOIN_REQ				0
15 
16 struct 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 
26 struct host_if_wep_attr {
27 	u8 *key;
28 	u8 key_len;
29 	u8 index;
30 	u8 mode;
31 	enum authtype auth_type;
32 };
33 
34 union 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 
40 struct key_attr {
41 	enum KEY_TYPE type;
42 	u8 action;
43 	union host_if_key_attr attr;
44 };
45 
46 struct 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 
58 struct 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 
72 struct rcvd_async_info {
73 	u8 *buffer;
74 	u32 len;
75 };
76 
77 struct channel_attr {
78 	u8 set_ch;
79 };
80 
81 struct 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 
90 struct set_multicast {
91 	bool enabled;
92 	u32 cnt;
93 };
94 
95 struct del_all_sta {
96 	u8 del_all_sta[MAX_NUM_STA][ETH_ALEN];
97 	u8 assoc_sta;
98 };
99 
100 struct del_sta {
101 	u8 mac_addr[ETH_ALEN];
102 };
103 
104 struct power_mgmt_param {
105 	bool enabled;
106 	u32 timeout;
107 };
108 
109 struct set_ip_addr {
110 	u8 *ip_addr;
111 	u8 idx;
112 };
113 
114 struct sta_inactive_t {
115 	u32 inactive_time;
116 	u8 mac[6];
117 };
118 
119 struct tx_power {
120 	u8 tx_pwr;
121 };
122 
123 union 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 
150 struct 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 
159 struct 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 
188 static struct host_if_drv *terminated_handle;
189 bool wilc_optaining_ip;
190 static u8 p2p_listen_state;
191 static struct workqueue_struct *hif_workqueue;
192 static struct completion hif_driver_comp;
193 static struct mutex hif_deinit_lock;
194 static struct timer_list periodic_rssi;
195 static struct wilc_vif *periodic_rssi_vif;
196 
197 u8 wilc_multicast_mac_addr_list[WILC_MULTICAST_TABLE_SIZE][ETH_ALEN];
198 
199 static u8 rcv_assoc_resp[MAX_ASSOC_RESP_FRAME_SIZE];
200 
201 static u8 set_ip[2][4];
202 static u8 get_ip[2][4];
203 static u32 clients_count;
204 
205 static int host_int_get_ipaddress(struct wilc_vif *vif, u8 *ip_addr, u8 idx);
206 
207 /* 'msg' should be free by the caller for syc */
208 static struct host_if_msg*
wilc_alloc_work(struct wilc_vif * vif,void (* work_fun)(struct work_struct *),bool is_sync)209 wilc_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 
wilc_enqueue_work(struct host_if_msg * msg)229 static 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 /* The idx starts from 0 to (NUM_CONCURRENT_IFC - 1), but 0 index used as
239  * special purpose in wilc device, so we add 1 to the index to starts from 1.
240  * As a result, the returned index will be 1 to NUM_CONCURRENT_IFC.
241  */
wilc_get_vif_idx(struct wilc_vif * vif)242 int wilc_get_vif_idx(struct wilc_vif *vif)
243 {
244 	return vif->idx + 1;
245 }
246 
247 /* We need to minus 1 from idx which is from wilc device to get real index
248  * of wilc->vif[], because we add 1 when pass to wilc device in the function
249  * wilc_get_vif_idx.
250  * As a result, the index should be between 0 and (NUM_CONCURRENT_IFC - 1).
251  */
wilc_get_vif_from_idx(struct wilc * wilc,int idx)252 static 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 
handle_set_channel(struct work_struct * work)262 static 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 
handle_set_wfi_drv_handler(struct work_struct * work)283 static 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 
326 free_msg:
327 	kfree(msg);
328 }
329 
handle_set_operation_mode(struct work_struct * work)330 static 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 
handle_set_ip_address(struct work_struct * work)355 static 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 
handle_get_ip_address(struct work_struct * work)385 static 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 
handle_get_mac_address(struct work_struct * work)413 static 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 	/* free 'msg' data later, in caller */
433 }
434 
handle_cfg_param(struct work_struct * work)435 static 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 *)&param->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 *)&param->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 *)&param->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 *)&param->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 *)&param->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 *)&param->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 *)&param->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 *)&param->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 *)&param->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 *)&param->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 *)&param->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 *)&param->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 *)&param->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 *)&param->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 *)&param->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 *)&param->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 *)&param->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 
726 unlock:
727 	mutex_unlock(&hif_drv->cfg_values_lock);
728 	kfree(msg);
729 }
730 
handle_scan_done(struct wilc_vif * vif,enum scan_event evt)731 static 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 
handle_scan(struct work_struct * work)769 static 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 
867 error:
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 
886 u8 wilc_connected_ssid[6] = {0};
handle_connect(struct work_struct * work)887 static 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 
1107 error:
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 
handle_connect_timeout(struct work_struct * work)1153 static 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 
1220 out:
1221 	kfree(msg);
1222 }
1223 
host_int_fill_join_bss_param(struct join_bss_param * param,u8 * ies,u16 * out_index,u8 * pcipher_tc,u8 * auth_total_cnt,u32 tsf_lo,u8 * rates_no)1224 static 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 =  &param->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 =  &param->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 
host_int_parse_join_bss_param(struct network_info * info)1360 static 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 
handle_rcvd_ntwrk_info(struct work_struct * work)1390 static 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 
1447 done:
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 
host_int_get_assoc_res_info(struct wilc_vif * vif,u8 * assoc_resp_info,u32 max_assoc_resp_info_len,u32 * rcvd_assoc_resp_info_len)1459 static 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 
host_int_free_user_conn_req(struct host_if_drv * hif_drv)1484 static 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 
host_int_parse_assoc_resp_info(struct wilc_vif * vif,u8 mac_status)1496 static 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 
host_int_handle_disconnect(struct wilc_vif * vif)1580 static 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 
handle_rcvd_gnrl_async_info(struct work_struct * work)1613 static 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 
1662 free_rcvd_info:
1663 	kfree(rcvd_info->buffer);
1664 	rcvd_info->buffer = NULL;
1665 
1666 free_msg:
1667 	kfree(msg);
1668 }
1669 
wilc_pmksa_key_copy(struct wilc_vif * vif,struct key_attr * hif_key)1670 static 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 
handle_key(struct work_struct * work)1704 static 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 		}
1792 out_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 		}
1856 out_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 
1911 out_wpa_ptk:
1912 		complete(&msg->work_comp);
1913 		break;
1914 
1915 	case PMKSA:
1916 		result = wilc_pmksa_key_copy(vif, hif_key);
1917 		/*free 'msg', this case it not a sync call*/
1918 		kfree(msg);
1919 		break;
1920 	}
1921 
1922 	if (result)
1923 		netdev_err(vif->ndev, "Failed to send key config packet\n");
1924 
1925 	/* free 'msg' data in caller sync call */
1926 }
1927 
handle_disconnect(struct work_struct * work)1928 static 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 
1996 out:
1997 
1998 	complete(&msg->work_comp);
1999 	/* free 'msg' in caller after receiving completion */
2000 }
2001 
wilc_resolve_disconnect_aberration(struct wilc_vif * vif)2002 void 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 
handle_get_rssi(struct work_struct * work)2011 static 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 	/* free 'msg' data in caller */
2030 }
2031 
handle_get_statistics(struct work_struct * work)2032 static 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 	/* free 'msg' for async command, for sync caller will free it */
2084 	if (msg->is_sync)
2085 		complete(&msg->work_comp);
2086 	else
2087 		kfree(msg);
2088 }
2089 
handle_get_inactive_time(struct work_struct * work)2090 static 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 
2127 out:
2128 	/* free 'msg' data in caller */
2129 	complete(&msg->work_comp);
2130 }
2131 
handle_add_beacon(struct work_struct * work)2132 static 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 
2181 error:
2182 	kfree(wid.val);
2183 	kfree(param->head);
2184 	kfree(param->tail);
2185 	kfree(msg);
2186 }
2187 
handle_del_beacon(struct work_struct * work)2188 static 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 
wilc_hif_pack_sta_param(u8 * buff,struct add_sta_param * param)2208 static 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, &param->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 
handle_add_station(struct work_struct * work)2238 static 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 
2263 error:
2264 	kfree(param->rates);
2265 	kfree(wid.val);
2266 	kfree(msg);
2267 }
2268 
handle_del_all_sta(struct work_struct * work)2269 static 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 
2306 error:
2307 	kfree(wid.val);
2308 
2309 	/* free 'msg' data in caller */
2310 	complete(&msg->work_comp);
2311 }
2312 
handle_del_station(struct work_struct * work)2313 static 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 
2336 error:
2337 	kfree(wid.val);
2338 	kfree(msg);
2339 }
2340 
handle_edit_station(struct work_struct * work)2341 static 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 
2366 error:
2367 	kfree(param->rates);
2368 	kfree(wid.val);
2369 	kfree(msg);
2370 }
2371 
handle_remain_on_chan(struct wilc_vif * vif,struct remain_ch * hif_remain_ch)2372 static 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 
2424 error:
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 
handle_register_frame(struct work_struct * work)2439 static 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 
2468 out:
2469 	kfree(msg);
2470 }
2471 
handle_listen_state_expired(struct work_struct * work)2472 static 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 
2512 free_msg:
2513 	kfree(msg);
2514 }
2515 
listen_timer_cb(struct timer_list * t)2516 static 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 
handle_power_management(struct work_struct * work)2539 static 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 
handle_set_mcast_filter(struct work_struct * work)2565 static 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 
2601 error:
2602 	kfree(wid.val);
2603 	kfree(msg);
2604 }
2605 
handle_set_tx_pwr(struct work_struct * work)2606 static 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 /* Note: 'msg' will be free after using data */
handle_get_tx_pwr(struct work_struct * work)2627 static 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 
handle_scan_timer(struct work_struct * work)2648 static 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 
handle_remain_on_chan_work(struct work_struct * work)2656 static 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 
handle_hif_exit_work(struct work_struct * work)2664 static 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 	/* free 'msg' data in caller */
2669 	complete(&msg->work_comp);
2670 }
2671 
handle_scan_complete(struct work_struct * work)2672 static 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 
timer_scan_cb(struct timer_list * t)2689 static 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 
timer_connect_cb(struct timer_list * t)2705 static 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 
wilc_remove_wep_key(struct wilc_vif * vif,u8 index)2722 int 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 
wilc_set_wep_default_keyid(struct wilc_vif * vif,u8 index)2752 int 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 
wilc_add_wep_key_bss_sta(struct wilc_vif * vif,const u8 * key,u8 len,u8 index)2782 int 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 
2815 free_key:
2816 	kfree(msg->body.key_info.attr.wep.key);
2817 
2818 free_msg:
2819 	kfree(msg);
2820 	return result;
2821 }
2822 
wilc_add_wep_key_bss_ap(struct wilc_vif * vif,const u8 * key,u8 len,u8 index,u8 mode,enum authtype auth_type)2823 int 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 
2858 free_key:
2859 	kfree(msg->body.key_info.attr.wep.key);
2860 
2861 free_msg:
2862 	kfree(msg);
2863 	return result;
2864 }
2865 
wilc_add_ptk(struct wilc_vif * vif,const u8 * ptk,u8 ptk_key_len,const u8 * mac_addr,const u8 * rx_mic,const u8 * tx_mic,u8 mode,u8 cipher_mode,u8 index)2866 int 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 
2924 free_key:
2925 	kfree(msg->body.key_info.attr.wpa.key);
2926 
2927 free_msg:
2928 	kfree(msg);
2929 	return result;
2930 }
2931 
wilc_add_rx_gtk(struct wilc_vif * vif,const u8 * rx_gtk,u8 gtk_key_len,u8 index,u32 key_rsc_len,const u8 * key_rsc,const u8 * rx_mic,const u8 * tx_mic,u8 mode,u8 cipher_mode)2932 int 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 
3002 free_key:
3003 	kfree(msg->body.key_info.attr.wpa.key);
3004 
3005 free_seq:
3006 	kfree(msg->body.key_info.attr.wpa.seq);
3007 
3008 free_msg:
3009 	kfree(msg);
3010 	return result;
3011 }
3012 
wilc_set_pmkid_info(struct wilc_vif * vif,struct host_if_pmkid_attr * pmkid)3013 int 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 
wilc_get_mac_address(struct wilc_vif * vif,u8 * mac_addr)3043 int 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 
wilc_set_join_req(struct wilc_vif * vif,u8 * bssid,const u8 * ssid,size_t ssid_len,const u8 * ies,size_t ies_len,wilc_connect_result connect_result,void * user_arg,u8 security,enum authtype auth_type,u8 channel,void * join_params)3065 int 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 
3138 free_ies:
3139 	kfree(msg->body.con_info.ies);
3140 
3141 free_ssid:
3142 	kfree(msg->body.con_info.ssid);
3143 
3144 free_bssid:
3145 	kfree(msg->body.con_info.bssid);
3146 
3147 free_msg:
3148 	kfree(msg);
3149 	return result;
3150 }
3151 
wilc_disconnect(struct wilc_vif * vif,u16 reason_code)3152 int 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 
wilc_set_mac_chnl_num(struct wilc_vif * vif,u8 channel)3177 int 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 
wilc_set_wfi_drv_handler(struct wilc_vif * vif,int index,u8 mode,u8 ifc_id)3197 int 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 
wilc_set_operation_mode(struct wilc_vif * vif,u32 mode)3220 int 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 
wilc_get_inactive_time(struct wilc_vif * vif,const u8 * mac,u32 * out_val)3239 s32 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 
wilc_get_rssi(struct wilc_vif * vif,s8 * rssi_level)3269 int 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 
3303 int
wilc_get_statistics(struct wilc_vif * vif,struct rf_info * stats,bool is_sync)3304 wilc_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 
wilc_scan(struct wilc_vif * vif,u8 scan_source,u8 scan_type,u8 * ch_freq_list,u8 ch_list_len,const u8 * ies,size_t ies_len,wilc_scan_result scan_result,void * user_arg,struct hidden_network * hidden_network)3330 int 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 
3389 free_ies:
3390 	kfree(scan_info->ies);
3391 
3392 free_freq_list:
3393 	kfree(scan_info->ch_freq_list);
3394 
3395 free_msg:
3396 	kfree(msg);
3397 	return result;
3398 }
3399 
wilc_hif_set_cfg(struct wilc_vif * vif,struct cfg_param_attr * cfg_param)3400 int 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 
get_periodic_rssi(struct timer_list * unused)3424 static 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 
wilc_init(struct net_device * dev,struct host_if_drv ** hif_drv_handler)3439 int 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 
wilc_deinit(struct wilc_vif * vif)3501 int 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 
wilc_network_info_received(struct wilc * wilc,u8 * buffer,u32 length)3556 void 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 
wilc_gnrl_async_info_received(struct wilc * wilc,u8 * buffer,u32 length)3597 void 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 
wilc_scan_complete_received(struct wilc * wilc,u8 * buffer,u32 length)3654 void 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 
wilc_remain_on_channel(struct wilc_vif * vif,u32 session_id,u32 duration,u16 chan,wilc_remain_on_chan_expired expired,wilc_remain_on_chan_ready ready,void * user_arg)3689 int 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 
wilc_listen_state_expired(struct wilc_vif * vif,u32 session_id)3718 int 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 
wilc_frame_register(struct wilc_vif * vif,u16 frame_type,bool reg)3746 int 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 
wilc_add_beacon(struct wilc_vif * vif,u32 interval,u32 dtim_period,u32 head_len,u8 * head,u32 tail_len,u8 * tail)3779 int 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 
3815 error:
3816 	if (result) {
3817 		kfree(beacon_info->head);
3818 		kfree(beacon_info->tail);
3819 		kfree(msg);
3820 	}
3821 
3822 	return result;
3823 }
3824 
wilc_del_beacon(struct wilc_vif * vif)3825 int 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 
wilc_add_station(struct wilc_vif * vif,struct add_sta_param * sta_param)3843 int 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 
wilc_del_station(struct wilc_vif * vif,const u8 * mac_addr)3874 int 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 
wilc_del_allstation(struct wilc_vif * vif,u8 mac_addr[][ETH_ALEN])3899 int 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 
wilc_edit_station(struct wilc_vif * vif,struct add_sta_param * sta_param)3939 int 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 
wilc_set_power_mgmt(struct wilc_vif * vif,bool enabled,u32 timeout)3972 int 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 
wilc_setup_multicast_filter(struct wilc_vif * vif,bool enabled,u32 count)3995 int 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 
wilc_setup_ipaddress(struct wilc_vif * vif,u8 * ip_addr,u8 idx)4016 int 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 
host_int_get_ipaddress(struct wilc_vif * vif,u8 * ip_addr,u8 idx)4037 static 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 
wilc_set_tx_power(struct wilc_vif * vif,u8 tx_power)4058 int 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 
wilc_get_tx_power(struct wilc_vif * vif,u8 * tx_power)4078 int 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 	/* free 'msg' after copying data */
4096 	kfree(msg);
4097 	return ret;
4098 }
4099