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