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