1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2012 - 2018 Microchip Technology Inc., and its subsidiaries.
7 #include "wilc_wfi_netdevice.h"
9 #define WILC_HIF_SCAN_TIMEOUT_MS 4000
10 #define WILC_HIF_CONNECT_TIMEOUT_MS 9500
12 #define WILC_FALSE_FRMWR_CHANNEL 100
13 #define WILC_MAX_RATES_SUPPORTED 12
15 struct wilc_rcvd_mac_info {
19 struct wilc_set_multicast {
25 struct wilc_del_all_sta {
27 u8 mac[WILC_MAX_NUM_STA][ETH_ALEN];
34 struct wilc_reg_frame {
40 struct wilc_drv_handler {
51 struct wilc_sta_wpa_ptk {
52 u8 mac_addr[ETH_ALEN];
57 struct wilc_ap_wpa_ptk {
58 u8 mac_addr[ETH_ALEN];
65 u8 mac_addr[ETH_ALEN];
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;
81 union wilc_message_body body;
83 struct work_struct work;
84 void (*fn)(struct work_struct *ws);
85 struct completion work_comp;
89 struct wilc_noa_opp_enable {
97 struct wilc_noa_opp_disable {
104 struct wilc_join_bss_param {
105 char ssid[IEEE80211_MAX_SSID_LEN];
112 __le16 beacon_period;
114 u8 supp_rates[WILC_MAX_RATES_SUPPORTED + 1];
129 struct wilc_noa_opp_disable opp_dis;
130 struct wilc_noa_opp_enable opp_en;
134 /* 'msg' should be free by the caller for syc */
135 static struct host_if_msg*
136 wilc_alloc_work(struct wilc_vif *vif, void (*work_fun)(struct work_struct *),
139 struct host_if_msg *msg;
142 return ERR_PTR(-EINVAL);
144 msg = kzalloc(sizeof(*msg), GFP_ATOMIC);
146 return ERR_PTR(-ENOMEM);
149 msg->is_sync = is_sync;
151 init_completion(&msg->work_comp);
156 static int wilc_enqueue_work(struct host_if_msg *msg)
158 INIT_WORK(&msg->work, msg->fn);
160 if (!msg->vif || !msg->vif->wilc || !msg->vif->wilc->hif_workqueue)
163 if (!queue_work(msg->vif->wilc->hif_workqueue, &msg->work))
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.
173 int wilc_get_vif_idx(struct wilc_vif *vif)
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
181 * As a result, the index should be between 0 and (NUM_CONCURRENT_IFC - 1).
183 static struct wilc_vif *wilc_get_vif_from_idx(struct wilc *wilc, int idx)
187 if (index < 0 || index >= WILC_NUM_CONCURRENT_IFC)
190 return wilc->vif[index];
193 static int handle_scan_done(struct wilc_vif *vif, enum scan_event evt)
196 u8 abort_running_scan;
198 struct host_if_drv *hif_drv = vif->hif_drv;
199 struct wilc_user_scan_req *scan_req;
201 if (evt == SCAN_EVENT_ABORTED) {
202 abort_running_scan = 1;
203 wid.id = WID_ABORT_RUNNING_SCAN;
205 wid.val = (s8 *)&abort_running_scan;
206 wid.size = sizeof(char);
208 result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
209 wilc_get_vif_idx(vif));
212 netdev_err(vif->ndev, "Failed to set abort running\n");
218 netdev_err(vif->ndev, "%s: hif driver is NULL\n", __func__);
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;
231 int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type,
232 u8 *ch_freq_list, u8 ch_list_len, const u8 *ies, size_t ies_len,
233 void (*scan_result_fn)(enum scan_event,
234 struct wilc_rcvd_net_info *, void *),
235 void *user_arg, struct wilc_probe_ssid *search)
238 struct wid wid_list[5];
243 u8 *search_ssid_vals = NULL;
244 struct host_if_drv *hif_drv = vif->hif_drv;
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");
253 if (vif->obtaining_ip || vif->connecting) {
254 netdev_err(vif->ndev, "Don't do obss scan\n");
259 hif_drv->usr_scan_req.ch_cnt = 0;
262 for (i = 0; i < search->n_ssids; i++)
263 valuesize += ((search->ssid_info[i].ssid_len) + 1);
264 search_ssid_vals = kmalloc(valuesize + 1, GFP_KERNEL);
265 if (search_ssid_vals) {
266 wid_list[index].id = WID_SSID_PROBE_REQ;
267 wid_list[index].type = WID_STR;
268 wid_list[index].val = search_ssid_vals;
269 buffer = wid_list[index].val;
271 *buffer++ = search->n_ssids;
273 for (i = 0; i < search->n_ssids; i++) {
274 *buffer++ = search->ssid_info[i].ssid_len;
275 memcpy(buffer, search->ssid_info[i].ssid,
276 search->ssid_info[i].ssid_len);
277 buffer += search->ssid_info[i].ssid_len;
279 wid_list[index].size = (s32)(valuesize + 1);
284 wid_list[index].id = WID_INFO_ELEMENT_PROBE;
285 wid_list[index].type = WID_BIN_DATA;
286 wid_list[index].val = (s8 *)ies;
287 wid_list[index].size = ies_len;
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;
296 wid_list[index].id = WID_SCAN_CHANNEL_LIST;
297 wid_list[index].type = WID_BIN_DATA;
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;
306 wid_list[index].val = ch_freq_list;
307 wid_list[index].size = ch_list_len;
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;
316 result = wilc_send_config_pkt(vif, WILC_SET_CFG, wid_list,
318 wilc_get_vif_idx(vif));
320 netdev_err(vif->ndev, "Failed to send scan parameters\n");
324 hif_drv->usr_scan_req.scan_result = scan_result_fn;
325 hif_drv->usr_scan_req.arg = user_arg;
326 hif_drv->scan_timer_vif = vif;
327 mod_timer(&hif_drv->scan_timer,
328 jiffies + msecs_to_jiffies(WILC_HIF_SCAN_TIMEOUT_MS));
332 kfree(search->ssid_info);
333 kfree(search_ssid_vals);
339 static int wilc_send_connect_wid(struct wilc_vif *vif)
342 struct wid wid_list[4];
344 struct host_if_drv *hif_drv = vif->hif_drv;
345 struct wilc_conn_info *conn_attr = &hif_drv->conn_info;
346 struct wilc_join_bss_param *bss_param = conn_attr->param;
348 wid_list[wid_cnt].id = WID_INFO_ELEMENT_ASSOCIATE;
349 wid_list[wid_cnt].type = WID_BIN_DATA;
350 wid_list[wid_cnt].val = conn_attr->req_ies;
351 wid_list[wid_cnt].size = conn_attr->req_ies_len;
354 wid_list[wid_cnt].id = WID_11I_MODE;
355 wid_list[wid_cnt].type = WID_CHAR;
356 wid_list[wid_cnt].size = sizeof(char);
357 wid_list[wid_cnt].val = (s8 *)&conn_attr->security;
360 wid_list[wid_cnt].id = WID_AUTH_TYPE;
361 wid_list[wid_cnt].type = WID_CHAR;
362 wid_list[wid_cnt].size = sizeof(char);
363 wid_list[wid_cnt].val = (s8 *)&conn_attr->auth_type;
366 wid_list[wid_cnt].id = WID_JOIN_REQ_EXTENDED;
367 wid_list[wid_cnt].type = WID_STR;
368 wid_list[wid_cnt].size = sizeof(*bss_param);
369 wid_list[wid_cnt].val = (u8 *)bss_param;
372 result = wilc_send_config_pkt(vif, WILC_SET_CFG, wid_list,
374 wilc_get_vif_idx(vif));
376 netdev_err(vif->ndev, "failed to send config packet\n");
379 hif_drv->hif_state = HOST_IF_WAITING_CONN_RESP;
386 kfree(conn_attr->req_ies);
387 conn_attr->req_ies = NULL;
392 static void handle_connect_timeout(struct work_struct *work)
394 struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
395 struct wilc_vif *vif = msg->vif;
398 u16 dummy_reason_code = 0;
399 struct host_if_drv *hif_drv = vif->hif_drv;
402 netdev_err(vif->ndev, "%s: hif driver is NULL\n", __func__);
406 hif_drv->hif_state = HOST_IF_IDLE;
408 if (hif_drv->conn_info.conn_result) {
409 hif_drv->conn_info.conn_result(CONN_DISCONN_EVENT_CONN_RESP,
410 WILC_MAC_STATUS_DISCONNECTED,
411 hif_drv->conn_info.arg);
414 netdev_err(vif->ndev, "%s: conn_result is NULL\n", __func__);
417 wid.id = WID_DISCONNECT;
419 wid.val = (s8 *)&dummy_reason_code;
420 wid.size = sizeof(char);
422 result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
423 wilc_get_vif_idx(vif));
425 netdev_err(vif->ndev, "Failed to send disconnect\n");
427 hif_drv->conn_info.req_ies_len = 0;
428 kfree(hif_drv->conn_info.req_ies);
429 hif_drv->conn_info.req_ies = NULL;
435 void *wilc_parse_join_bss_param(struct cfg80211_bss *bss,
436 struct cfg80211_crypto_settings *crypto)
438 struct wilc_join_bss_param *param;
439 struct ieee80211_p2p_noa_attr noa_attr;
441 const u8 *tim_elm, *ssid_elm, *rates_ie, *supp_rates_ie;
442 const u8 *ht_ie, *wpa_ie, *wmm_ie, *rsn_ie;
444 const struct cfg80211_bss_ies *ies = rcu_dereference(bss->ies);
446 param = kzalloc(sizeof(*param), GFP_KERNEL);
450 param->beacon_period = cpu_to_le16(bss->beacon_interval);
451 param->cap_info = cpu_to_le16(bss->capability);
452 param->bss_type = WILC_FW_BSS_TYPE_INFRA;
453 param->ch = ieee80211_frequency_to_channel(bss->channel->center_freq);
454 ether_addr_copy(param->bssid, bss->bssid);
456 ssid_elm = cfg80211_find_ie(WLAN_EID_SSID, ies->data, ies->len);
458 if (ssid_elm[1] <= IEEE80211_MAX_SSID_LEN)
459 memcpy(param->ssid, ssid_elm + 2, ssid_elm[1]);
462 tim_elm = cfg80211_find_ie(WLAN_EID_TIM, ies->data, ies->len);
463 if (tim_elm && tim_elm[1] >= 2)
464 param->dtim_period = tim_elm[3];
466 memset(param->p_suites, 0xFF, 3);
467 memset(param->akm_suites, 0xFF, 3);
469 rates_ie = cfg80211_find_ie(WLAN_EID_SUPP_RATES, ies->data, ies->len);
471 rates_len = rates_ie[1];
472 param->supp_rates[0] = rates_len;
473 memcpy(¶m->supp_rates[1], rates_ie + 2, rates_len);
476 supp_rates_ie = cfg80211_find_ie(WLAN_EID_EXT_SUPP_RATES, ies->data,
479 if (supp_rates_ie[1] > (WILC_MAX_RATES_SUPPORTED - rates_len))
480 param->supp_rates[0] = WILC_MAX_RATES_SUPPORTED;
482 param->supp_rates[0] += supp_rates_ie[1];
484 memcpy(¶m->supp_rates[rates_len + 1], supp_rates_ie + 2,
485 (param->supp_rates[0] - rates_len));
488 ht_ie = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, ies->data, ies->len);
490 param->ht_capable = true;
492 ret = cfg80211_get_p2p_attr(ies->data, ies->len,
493 IEEE80211_P2P_ATTR_ABSENCE_NOTICE,
494 (u8 *)&noa_attr, sizeof(noa_attr));
496 param->tsf_lo = cpu_to_le32(ies->tsf);
497 param->noa_enabled = 1;
498 param->idx = noa_attr.index;
499 if (noa_attr.oppps_ctwindow & IEEE80211_P2P_OPPPS_ENABLE_BIT) {
500 param->opp_enabled = 1;
501 param->opp_en.ct_window = noa_attr.oppps_ctwindow;
502 param->opp_en.cnt = noa_attr.desc[0].count;
503 param->opp_en.duration = noa_attr.desc[0].duration;
504 param->opp_en.interval = noa_attr.desc[0].interval;
505 param->opp_en.start_time = noa_attr.desc[0].start_time;
507 param->opp_enabled = 0;
508 param->opp_dis.cnt = noa_attr.desc[0].count;
509 param->opp_dis.duration = noa_attr.desc[0].duration;
510 param->opp_dis.interval = noa_attr.desc[0].interval;
511 param->opp_dis.start_time = noa_attr.desc[0].start_time;
514 wmm_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
515 WLAN_OUI_TYPE_MICROSOFT_WMM,
516 ies->data, ies->len);
518 struct ieee80211_wmm_param_ie *ie;
520 ie = (struct ieee80211_wmm_param_ie *)wmm_ie;
521 if ((ie->oui_subtype == 0 || ie->oui_subtype == 1) &&
523 param->wmm_cap = true;
524 if (ie->qos_info & BIT(7))
525 param->uapsd_cap = true;
529 wpa_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
530 WLAN_OUI_TYPE_MICROSOFT_WPA,
531 ies->data, ies->len);
533 param->mode_802_11i = 1;
534 param->rsn_found = true;
537 rsn_ie = cfg80211_find_ie(WLAN_EID_RSN, ies->data, ies->len);
541 param->mode_802_11i = 2;
542 param->rsn_found = true;
543 //extract RSN capabilities
544 offset += (rsn_ie[offset] * 4) + 2;
545 offset += (rsn_ie[offset] * 4) + 2;
546 memcpy(param->rsn_cap, &rsn_ie[offset], 2);
549 if (param->rsn_found) {
552 param->rsn_grp_policy = crypto->cipher_group & 0xFF;
553 for (i = 0; i < crypto->n_ciphers_pairwise && i < 3; i++)
554 param->p_suites[i] = crypto->ciphers_pairwise[i] & 0xFF;
556 for (i = 0; i < crypto->n_akm_suites && i < 3; i++)
557 param->akm_suites[i] = crypto->akm_suites[i] & 0xFF;
560 return (void *)param;
563 static void handle_rcvd_ntwrk_info(struct work_struct *work)
565 struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
566 struct wilc_rcvd_net_info *rcvd_info = &msg->body.net_info;
567 struct wilc_user_scan_req *scan_req = &msg->vif->hif_drv->usr_scan_req;
573 if (ieee80211_is_probe_resp(rcvd_info->mgmt->frame_control))
574 offset = offsetof(struct ieee80211_mgmt, u.probe_resp.variable);
575 else if (ieee80211_is_beacon(rcvd_info->mgmt->frame_control))
576 offset = offsetof(struct ieee80211_mgmt, u.beacon.variable);
580 ies = rcvd_info->mgmt->u.beacon.variable;
581 ies_len = rcvd_info->frame_len - offset;
585 ch_elm = cfg80211_find_ie(WLAN_EID_DS_PARAMS, ies, ies_len);
586 if (ch_elm && ch_elm[1] > 0)
587 rcvd_info->ch = ch_elm[2];
589 if (scan_req->scan_result)
590 scan_req->scan_result(SCAN_EVENT_NETWORK_FOUND, rcvd_info,
594 kfree(rcvd_info->mgmt);
598 static void host_int_get_assoc_res_info(struct wilc_vif *vif,
600 u32 max_assoc_resp_info_len,
601 u32 *rcvd_assoc_resp_info_len)
606 wid.id = WID_ASSOC_RES_INFO;
608 wid.val = assoc_resp_info;
609 wid.size = max_assoc_resp_info_len;
611 result = wilc_send_config_pkt(vif, WILC_GET_CFG, &wid, 1,
612 wilc_get_vif_idx(vif));
614 *rcvd_assoc_resp_info_len = 0;
615 netdev_err(vif->ndev, "Failed to send association response\n");
619 *rcvd_assoc_resp_info_len = wid.size;
622 static s32 wilc_parse_assoc_resp_info(u8 *buffer, u32 buffer_len,
623 struct wilc_conn_info *ret_conn_info)
627 struct assoc_resp *res = (struct assoc_resp *)buffer;
629 ret_conn_info->status = le16_to_cpu(res->status_code);
630 if (ret_conn_info->status == WLAN_STATUS_SUCCESS) {
631 ies = &buffer[sizeof(*res)];
632 ies_len = buffer_len - sizeof(*res);
634 ret_conn_info->resp_ies = kmemdup(ies, ies_len, GFP_KERNEL);
635 if (!ret_conn_info->resp_ies)
638 ret_conn_info->resp_ies_len = ies_len;
644 static inline void host_int_parse_assoc_resp_info(struct wilc_vif *vif,
647 struct host_if_drv *hif_drv = vif->hif_drv;
648 struct wilc_conn_info *conn_info = &hif_drv->conn_info;
650 if (mac_status == WILC_MAC_STATUS_CONNECTED) {
651 u32 assoc_resp_info_len;
653 memset(hif_drv->assoc_resp, 0, WILC_MAX_ASSOC_RESP_FRAME_SIZE);
655 host_int_get_assoc_res_info(vif, hif_drv->assoc_resp,
656 WILC_MAX_ASSOC_RESP_FRAME_SIZE,
657 &assoc_resp_info_len);
659 if (assoc_resp_info_len != 0) {
662 err = wilc_parse_assoc_resp_info(hif_drv->assoc_resp,
666 netdev_err(vif->ndev,
667 "wilc_parse_assoc_resp_info() returned error %d\n",
672 del_timer(&hif_drv->connect_timer);
673 conn_info->conn_result(CONN_DISCONN_EVENT_CONN_RESP, mac_status,
674 hif_drv->conn_info.arg);
676 if (mac_status == WILC_MAC_STATUS_CONNECTED &&
677 conn_info->status == WLAN_STATUS_SUCCESS) {
678 ether_addr_copy(hif_drv->assoc_bssid, conn_info->bssid);
679 wilc_set_power_mgmt(vif, 0, 0);
681 hif_drv->hif_state = HOST_IF_CONNECTED;
683 vif->obtaining_ip = true;
684 mod_timer(&vif->during_ip_timer,
685 jiffies + msecs_to_jiffies(10000));
687 hif_drv->hif_state = HOST_IF_IDLE;
690 kfree(conn_info->resp_ies);
691 conn_info->resp_ies = NULL;
692 conn_info->resp_ies_len = 0;
694 kfree(conn_info->req_ies);
695 conn_info->req_ies = NULL;
696 conn_info->req_ies_len = 0;
699 static inline void host_int_handle_disconnect(struct wilc_vif *vif)
701 struct host_if_drv *hif_drv = vif->hif_drv;
703 if (hif_drv->usr_scan_req.scan_result) {
704 del_timer(&hif_drv->scan_timer);
705 handle_scan_done(vif, SCAN_EVENT_ABORTED);
708 if (hif_drv->conn_info.conn_result) {
709 vif->obtaining_ip = false;
710 wilc_set_power_mgmt(vif, 0, 0);
712 hif_drv->conn_info.conn_result(CONN_DISCONN_EVENT_DISCONN_NOTIF,
713 0, hif_drv->conn_info.arg);
715 netdev_err(vif->ndev, "%s: conn_result is NULL\n", __func__);
718 eth_zero_addr(hif_drv->assoc_bssid);
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;
726 static void handle_rcvd_gnrl_async_info(struct work_struct *work)
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;
734 netdev_err(vif->ndev, "%s: hif driver is NULL\n", __func__);
738 if (!hif_drv->conn_info.conn_result) {
739 netdev_err(vif->ndev, "%s: conn_result is NULL\n", __func__);
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);
758 int wilc_disconnect(struct wilc_vif *vif)
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;
765 u16 dummy_reason_code = 0;
767 wid.id = WID_DISCONNECT;
769 wid.val = (s8 *)&dummy_reason_code;
770 wid.size = sizeof(char);
772 vif->obtaining_ip = false;
773 wilc_set_power_mgmt(vif, 0, 0);
775 result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
776 wilc_get_vif_idx(vif));
778 netdev_err(vif->ndev, "Failed to send dissconect\n");
782 scan_req = &hif_drv->usr_scan_req;
783 conn_info = &hif_drv->conn_info;
785 if (scan_req->scan_result) {
786 del_timer(&hif_drv->scan_timer);
787 scan_req->scan_result(SCAN_EVENT_ABORTED, NULL, scan_req->arg);
788 scan_req->scan_result = NULL;
791 if (conn_info->conn_result) {
792 if (hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP)
793 del_timer(&hif_drv->connect_timer);
795 conn_info->conn_result(CONN_DISCONN_EVENT_DISCONN_NOTIF, 0,
798 netdev_err(vif->ndev, "%s: conn_result is NULL\n", __func__);
801 hif_drv->hif_state = HOST_IF_IDLE;
803 eth_zero_addr(hif_drv->assoc_bssid);
805 conn_info->req_ies_len = 0;
806 kfree(conn_info->req_ies);
807 conn_info->req_ies = NULL;
812 void wilc_resolve_disconnect_aberration(struct wilc_vif *vif)
816 if (vif->hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP ||
817 vif->hif_drv->hif_state == HOST_IF_CONNECTING)
818 wilc_disconnect(vif);
821 int wilc_get_statistics(struct wilc_vif *vif, struct rf_info *stats)
823 struct wid wid_list[5];
824 u32 wid_cnt = 0, result;
826 wid_list[wid_cnt].id = WID_LINKSPEED;
827 wid_list[wid_cnt].type = WID_CHAR;
828 wid_list[wid_cnt].size = sizeof(char);
829 wid_list[wid_cnt].val = (s8 *)&stats->link_speed;
832 wid_list[wid_cnt].id = WID_RSSI;
833 wid_list[wid_cnt].type = WID_CHAR;
834 wid_list[wid_cnt].size = sizeof(char);
835 wid_list[wid_cnt].val = (s8 *)&stats->rssi;
838 wid_list[wid_cnt].id = WID_SUCCESS_FRAME_COUNT;
839 wid_list[wid_cnt].type = WID_INT;
840 wid_list[wid_cnt].size = sizeof(u32);
841 wid_list[wid_cnt].val = (s8 *)&stats->tx_cnt;
844 wid_list[wid_cnt].id = WID_RECEIVED_FRAGMENT_COUNT;
845 wid_list[wid_cnt].type = WID_INT;
846 wid_list[wid_cnt].size = sizeof(u32);
847 wid_list[wid_cnt].val = (s8 *)&stats->rx_cnt;
850 wid_list[wid_cnt].id = WID_FAILED_COUNT;
851 wid_list[wid_cnt].type = WID_INT;
852 wid_list[wid_cnt].size = sizeof(u32);
853 wid_list[wid_cnt].val = (s8 *)&stats->tx_fail_cnt;
856 result = wilc_send_config_pkt(vif, WILC_GET_CFG, wid_list,
858 wilc_get_vif_idx(vif));
861 netdev_err(vif->ndev, "Failed to send scan parameters\n");
865 if (stats->link_speed > TCP_ACK_FILTER_LINK_SPEED_THRESH &&
866 stats->link_speed != DEFAULT_LINK_SPEED)
867 wilc_enable_tcp_ack_filter(vif, true);
868 else if (stats->link_speed != DEFAULT_LINK_SPEED)
869 wilc_enable_tcp_ack_filter(vif, false);
874 static void handle_get_statistics(struct work_struct *work)
876 struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
877 struct wilc_vif *vif = msg->vif;
878 struct rf_info *stats = (struct rf_info *)msg->body.data;
880 wilc_get_statistics(vif, stats);
885 static void wilc_hif_pack_sta_param(u8 *cur_byte, const u8 *mac,
886 struct station_parameters *params)
888 ether_addr_copy(cur_byte, mac);
889 cur_byte += ETH_ALEN;
891 put_unaligned_le16(params->aid, cur_byte);
894 *cur_byte++ = params->supported_rates_len;
895 if (params->supported_rates_len > 0)
896 memcpy(cur_byte, params->supported_rates,
897 params->supported_rates_len);
898 cur_byte += params->supported_rates_len;
900 if (params->ht_capa) {
902 memcpy(cur_byte, ¶ms->ht_capa,
903 sizeof(struct ieee80211_ht_cap));
907 cur_byte += sizeof(struct ieee80211_ht_cap);
909 put_unaligned_le16(params->sta_flags_mask, cur_byte);
911 put_unaligned_le16(params->sta_flags_set, cur_byte);
914 static int handle_remain_on_chan(struct wilc_vif *vif,
915 struct wilc_remain_ch *hif_remain_ch)
918 u8 remain_on_chan_flag;
920 struct host_if_drv *hif_drv = vif->hif_drv;
922 if (hif_drv->usr_scan_req.scan_result)
925 if (hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP)
928 if (vif->obtaining_ip || vif->connecting)
931 remain_on_chan_flag = true;
932 wid.id = WID_REMAIN_ON_CHAN;
935 wid.val = kmalloc(wid.size, GFP_KERNEL);
939 wid.val[0] = remain_on_chan_flag;
940 wid.val[1] = (s8)hif_remain_ch->ch;
942 result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
943 wilc_get_vif_idx(vif));
948 hif_drv->remain_on_ch.arg = hif_remain_ch->arg;
949 hif_drv->remain_on_ch.expired = hif_remain_ch->expired;
950 hif_drv->remain_on_ch.ch = hif_remain_ch->ch;
951 hif_drv->remain_on_ch.cookie = hif_remain_ch->cookie;
952 hif_drv->remain_on_ch_timer_vif = vif;
957 static void handle_listen_state_expired(struct work_struct *work)
959 struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
960 struct wilc_vif *vif = msg->vif;
961 struct wilc_remain_ch *hif_remain_ch = &msg->body.remain_on_ch;
962 u8 remain_on_chan_flag;
965 struct host_if_drv *hif_drv = vif->hif_drv;
966 struct wilc_priv *priv = wdev_priv(vif->ndev->ieee80211_ptr);
968 if (priv->p2p_listen_state) {
969 remain_on_chan_flag = false;
970 wid.id = WID_REMAIN_ON_CHAN;
973 wid.val = kmalloc(wid.size, GFP_KERNEL);
978 wid.val[0] = remain_on_chan_flag;
979 wid.val[1] = WILC_FALSE_FRMWR_CHANNEL;
981 result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
982 wilc_get_vif_idx(vif));
985 netdev_err(vif->ndev, "Failed to set remain channel\n");
989 if (hif_drv->remain_on_ch.expired) {
990 hif_drv->remain_on_ch.expired(hif_drv->remain_on_ch.arg,
991 hif_remain_ch->cookie);
994 netdev_dbg(vif->ndev, "Not in listen state\n");
1001 static void listen_timer_cb(struct timer_list *t)
1003 struct host_if_drv *hif_drv = from_timer(hif_drv, t,
1004 remain_on_ch_timer);
1005 struct wilc_vif *vif = hif_drv->remain_on_ch_timer_vif;
1007 struct host_if_msg *msg;
1009 del_timer(&vif->hif_drv->remain_on_ch_timer);
1011 msg = wilc_alloc_work(vif, handle_listen_state_expired, false);
1015 msg->body.remain_on_ch.cookie = vif->hif_drv->remain_on_ch.cookie;
1017 result = wilc_enqueue_work(msg);
1019 netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__);
1024 static void handle_set_mcast_filter(struct work_struct *work)
1026 struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
1027 struct wilc_vif *vif = msg->vif;
1028 struct wilc_set_multicast *set_mc = &msg->body.mc_info;
1033 wid.id = WID_SETUP_MULTICAST_FILTER;
1035 wid.size = sizeof(struct wilc_set_multicast) + (set_mc->cnt * ETH_ALEN);
1036 wid.val = kmalloc(wid.size, GFP_KERNEL);
1041 put_unaligned_le32(set_mc->enabled, cur_byte);
1044 put_unaligned_le32(set_mc->cnt, cur_byte);
1047 if (set_mc->cnt > 0 && set_mc->mc_list)
1048 memcpy(cur_byte, set_mc->mc_list, set_mc->cnt * ETH_ALEN);
1050 result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
1051 wilc_get_vif_idx(vif));
1053 netdev_err(vif->ndev, "Failed to send setup multicast\n");
1056 kfree(set_mc->mc_list);
1061 static void handle_scan_timer(struct work_struct *work)
1063 struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
1065 handle_scan_done(msg->vif, SCAN_EVENT_ABORTED);
1069 static void handle_scan_complete(struct work_struct *work)
1071 struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
1072 struct wilc *wilc = msg->vif->wilc;
1074 del_timer(&msg->vif->hif_drv->scan_timer);
1076 if (!wilc_wlan_get_num_conn_ifcs(wilc))
1077 wilc_chip_sleep_manually(wilc);
1079 handle_scan_done(msg->vif, SCAN_EVENT_DONE);
1084 static void timer_scan_cb(struct timer_list *t)
1086 struct host_if_drv *hif_drv = from_timer(hif_drv, t, scan_timer);
1087 struct wilc_vif *vif = hif_drv->scan_timer_vif;
1088 struct host_if_msg *msg;
1091 msg = wilc_alloc_work(vif, handle_scan_timer, false);
1095 result = wilc_enqueue_work(msg);
1100 static void timer_connect_cb(struct timer_list *t)
1102 struct host_if_drv *hif_drv = from_timer(hif_drv, t,
1104 struct wilc_vif *vif = hif_drv->connect_timer_vif;
1105 struct host_if_msg *msg;
1108 msg = wilc_alloc_work(vif, handle_connect_timeout, false);
1112 result = wilc_enqueue_work(msg);
1117 int wilc_remove_wep_key(struct wilc_vif *vif, u8 index)
1122 wid.id = WID_REMOVE_WEP_KEY;
1124 wid.size = sizeof(char);
1127 result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
1128 wilc_get_vif_idx(vif));
1130 netdev_err(vif->ndev,
1131 "Failed to send remove wep key config packet\n");
1135 int wilc_set_wep_default_keyid(struct wilc_vif *vif, u8 index)
1140 wid.id = WID_KEY_ID;
1141 wid.type = WID_CHAR;
1142 wid.size = sizeof(char);
1144 result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
1145 wilc_get_vif_idx(vif));
1147 netdev_err(vif->ndev,
1148 "Failed to send wep default key config packet\n");
1153 int wilc_add_wep_key_bss_sta(struct wilc_vif *vif, const u8 *key, u8 len,
1158 struct wilc_wep_key *wep_key;
1160 wid.id = WID_ADD_WEP_KEY;
1162 wid.size = sizeof(*wep_key) + len;
1163 wep_key = kzalloc(wid.size, GFP_KERNEL);
1167 wid.val = (u8 *)wep_key;
1169 wep_key->index = index;
1170 wep_key->key_len = len;
1171 memcpy(wep_key->key, key, len);
1173 result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
1174 wilc_get_vif_idx(vif));
1176 netdev_err(vif->ndev,
1177 "Failed to add wep key config packet\n");
1183 int wilc_add_wep_key_bss_ap(struct wilc_vif *vif, const u8 *key, u8 len,
1184 u8 index, u8 mode, enum authtype auth_type)
1186 struct wid wid_list[3];
1188 struct wilc_wep_key *wep_key;
1190 wid_list[0].id = WID_11I_MODE;
1191 wid_list[0].type = WID_CHAR;
1192 wid_list[0].size = sizeof(char);
1193 wid_list[0].val = &mode;
1195 wid_list[1].id = WID_AUTH_TYPE;
1196 wid_list[1].type = WID_CHAR;
1197 wid_list[1].size = sizeof(char);
1198 wid_list[1].val = (s8 *)&auth_type;
1200 wid_list[2].id = WID_WEP_KEY_VALUE;
1201 wid_list[2].type = WID_STR;
1202 wid_list[2].size = sizeof(*wep_key) + len;
1203 wep_key = kzalloc(wid_list[2].size, GFP_KERNEL);
1207 wid_list[2].val = (u8 *)wep_key;
1209 wep_key->index = index;
1210 wep_key->key_len = len;
1211 memcpy(wep_key->key, key, len);
1212 result = wilc_send_config_pkt(vif, WILC_SET_CFG, wid_list,
1213 ARRAY_SIZE(wid_list),
1214 wilc_get_vif_idx(vif));
1216 netdev_err(vif->ndev,
1217 "Failed to add wep ap key config packet\n");
1223 int wilc_add_ptk(struct wilc_vif *vif, const u8 *ptk, u8 ptk_key_len,
1224 const u8 *mac_addr, const u8 *rx_mic, const u8 *tx_mic,
1225 u8 mode, u8 cipher_mode, u8 index)
1228 u8 t_key_len = ptk_key_len + WILC_RX_MIC_KEY_LEN + WILC_TX_MIC_KEY_LEN;
1230 if (mode == WILC_AP_MODE) {
1231 struct wid wid_list[2];
1232 struct wilc_ap_wpa_ptk *key_buf;
1234 wid_list[0].id = WID_11I_MODE;
1235 wid_list[0].type = WID_CHAR;
1236 wid_list[0].size = sizeof(char);
1237 wid_list[0].val = (s8 *)&cipher_mode;
1239 key_buf = kzalloc(sizeof(*key_buf) + t_key_len, GFP_KERNEL);
1243 ether_addr_copy(key_buf->mac_addr, mac_addr);
1244 key_buf->index = index;
1245 key_buf->key_len = t_key_len;
1246 memcpy(&key_buf->key[0], ptk, ptk_key_len);
1249 memcpy(&key_buf->key[ptk_key_len], rx_mic,
1250 WILC_RX_MIC_KEY_LEN);
1253 memcpy(&key_buf->key[ptk_key_len + WILC_RX_MIC_KEY_LEN],
1254 tx_mic, WILC_TX_MIC_KEY_LEN);
1256 wid_list[1].id = WID_ADD_PTK;
1257 wid_list[1].type = WID_STR;
1258 wid_list[1].size = sizeof(*key_buf) + t_key_len;
1259 wid_list[1].val = (u8 *)key_buf;
1260 result = wilc_send_config_pkt(vif, WILC_SET_CFG, wid_list,
1261 ARRAY_SIZE(wid_list),
1262 wilc_get_vif_idx(vif));
1264 } else if (mode == WILC_STATION_MODE) {
1266 struct wilc_sta_wpa_ptk *key_buf;
1268 key_buf = kzalloc(sizeof(*key_buf) + t_key_len, GFP_KERNEL);
1272 ether_addr_copy(key_buf->mac_addr, mac_addr);
1273 key_buf->key_len = t_key_len;
1274 memcpy(&key_buf->key[0], ptk, ptk_key_len);
1277 memcpy(&key_buf->key[ptk_key_len], rx_mic,
1278 WILC_RX_MIC_KEY_LEN);
1281 memcpy(&key_buf->key[ptk_key_len + WILC_RX_MIC_KEY_LEN],
1282 tx_mic, WILC_TX_MIC_KEY_LEN);
1284 wid.id = WID_ADD_PTK;
1286 wid.size = sizeof(*key_buf) + t_key_len;
1287 wid.val = (s8 *)key_buf;
1288 result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
1289 wilc_get_vif_idx(vif));
1296 int wilc_add_rx_gtk(struct wilc_vif *vif, const u8 *rx_gtk, u8 gtk_key_len,
1297 u8 index, u32 key_rsc_len, const u8 *key_rsc,
1298 const u8 *rx_mic, const u8 *tx_mic, u8 mode,
1302 struct wilc_gtk_key *gtk_key;
1303 int t_key_len = gtk_key_len + WILC_RX_MIC_KEY_LEN + WILC_TX_MIC_KEY_LEN;
1305 gtk_key = kzalloc(sizeof(*gtk_key) + t_key_len, GFP_KERNEL);
1309 /* fill bssid value only in station mode */
1310 if (mode == WILC_STATION_MODE &&
1311 vif->hif_drv->hif_state == HOST_IF_CONNECTED)
1312 memcpy(gtk_key->mac_addr, vif->hif_drv->assoc_bssid, ETH_ALEN);
1315 memcpy(gtk_key->rsc, key_rsc, 8);
1316 gtk_key->index = index;
1317 gtk_key->key_len = t_key_len;
1318 memcpy(>k_key->key[0], rx_gtk, gtk_key_len);
1321 memcpy(>k_key->key[gtk_key_len], rx_mic, WILC_RX_MIC_KEY_LEN);
1324 memcpy(>k_key->key[gtk_key_len + WILC_RX_MIC_KEY_LEN],
1325 tx_mic, WILC_TX_MIC_KEY_LEN);
1327 if (mode == WILC_AP_MODE) {
1328 struct wid wid_list[2];
1330 wid_list[0].id = WID_11I_MODE;
1331 wid_list[0].type = WID_CHAR;
1332 wid_list[0].size = sizeof(char);
1333 wid_list[0].val = (s8 *)&cipher_mode;
1335 wid_list[1].id = WID_ADD_RX_GTK;
1336 wid_list[1].type = WID_STR;
1337 wid_list[1].size = sizeof(*gtk_key) + t_key_len;
1338 wid_list[1].val = (u8 *)gtk_key;
1340 result = wilc_send_config_pkt(vif, WILC_SET_CFG, wid_list,
1341 ARRAY_SIZE(wid_list),
1342 wilc_get_vif_idx(vif));
1343 } else if (mode == WILC_STATION_MODE) {
1346 wid.id = WID_ADD_RX_GTK;
1348 wid.size = sizeof(*gtk_key) + t_key_len;
1349 wid.val = (u8 *)gtk_key;
1350 result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
1351 wilc_get_vif_idx(vif));
1358 int wilc_set_pmkid_info(struct wilc_vif *vif, struct wilc_pmkid_attr *pmkid)
1363 wid.id = WID_PMKID_INFO;
1365 wid.size = (pmkid->numpmkid * sizeof(struct wilc_pmkid)) + 1;
1366 wid.val = (u8 *)pmkid;
1368 result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
1369 wilc_get_vif_idx(vif));
1374 int wilc_get_mac_address(struct wilc_vif *vif, u8 *mac_addr)
1379 wid.id = WID_MAC_ADDR;
1381 wid.size = ETH_ALEN;
1384 result = wilc_send_config_pkt(vif, WILC_GET_CFG, &wid, 1,
1385 wilc_get_vif_idx(vif));
1387 netdev_err(vif->ndev, "Failed to get mac address\n");
1392 int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ies,
1396 struct host_if_drv *hif_drv = vif->hif_drv;
1397 struct wilc_conn_info *conn_info = &hif_drv->conn_info;
1400 ether_addr_copy(conn_info->bssid, bssid);
1403 conn_info->req_ies_len = ies_len;
1404 conn_info->req_ies = kmemdup(ies, ies_len, GFP_KERNEL);
1405 if (!conn_info->req_ies) {
1411 result = wilc_send_connect_wid(vif);
1415 hif_drv->connect_timer_vif = vif;
1416 mod_timer(&hif_drv->connect_timer,
1417 jiffies + msecs_to_jiffies(WILC_HIF_CONNECT_TIMEOUT_MS));
1422 kfree(conn_info->req_ies);
1427 int wilc_set_mac_chnl_num(struct wilc_vif *vif, u8 channel)
1432 wid.id = WID_CURRENT_CHANNEL;
1433 wid.type = WID_CHAR;
1434 wid.size = sizeof(char);
1437 result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
1438 wilc_get_vif_idx(vif));
1440 netdev_err(vif->ndev, "Failed to set channel\n");
1445 int wilc_set_wfi_drv_handler(struct wilc_vif *vif, int index, u8 mode,
1449 struct host_if_drv *hif_drv = vif->hif_drv;
1451 struct wilc_drv_handler drv;
1456 wid.id = WID_SET_DRV_HANDLER;
1458 wid.size = sizeof(drv);
1459 wid.val = (u8 *)&drv;
1461 drv.handler = cpu_to_le32(index);
1462 drv.mode = (ifc_id | (mode << 1));
1464 result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
1465 hif_drv->driver_handler_id);
1467 netdev_err(vif->ndev, "Failed to set driver handler\n");
1472 int wilc_set_operation_mode(struct wilc_vif *vif, u32 mode)
1475 struct wilc_op_mode op_mode;
1478 wid.id = WID_SET_OPERATION_MODE;
1480 wid.size = sizeof(op_mode);
1481 wid.val = (u8 *)&op_mode;
1483 op_mode.mode = cpu_to_le32(mode);
1485 result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
1486 wilc_get_vif_idx(vif));
1488 netdev_err(vif->ndev, "Failed to set operation mode\n");
1493 s32 wilc_get_inactive_time(struct wilc_vif *vif, const u8 *mac, u32 *out_val)
1498 wid.id = WID_SET_STA_MAC_INACTIVE_TIME;
1500 wid.size = ETH_ALEN;
1501 wid.val = kzalloc(wid.size, GFP_KERNEL);
1505 ether_addr_copy(wid.val, mac);
1506 result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
1507 wilc_get_vif_idx(vif));
1510 netdev_err(vif->ndev, "Failed to set inactive mac\n");
1514 wid.id = WID_GET_INACTIVE_TIME;
1516 wid.val = (s8 *)out_val;
1517 wid.size = sizeof(u32);
1518 result = wilc_send_config_pkt(vif, WILC_GET_CFG, &wid, 1,
1519 wilc_get_vif_idx(vif));
1521 netdev_err(vif->ndev, "Failed to get inactive time\n");
1526 int wilc_get_rssi(struct wilc_vif *vif, s8 *rssi_level)
1532 netdev_err(vif->ndev, "%s: RSSI level is NULL\n", __func__);
1537 wid.type = WID_CHAR;
1538 wid.size = sizeof(char);
1539 wid.val = rssi_level;
1540 result = wilc_send_config_pkt(vif, WILC_GET_CFG, &wid, 1,
1541 wilc_get_vif_idx(vif));
1543 netdev_err(vif->ndev, "Failed to get RSSI value\n");
1548 static int wilc_get_stats_async(struct wilc_vif *vif, struct rf_info *stats)
1551 struct host_if_msg *msg;
1553 msg = wilc_alloc_work(vif, handle_get_statistics, false);
1555 return PTR_ERR(msg);
1557 msg->body.data = (char *)stats;
1559 result = wilc_enqueue_work(msg);
1561 netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__);
1569 int wilc_hif_set_cfg(struct wilc_vif *vif, struct cfg_param_attr *param)
1571 struct wid wid_list[4];
1575 if (param->flag & WILC_CFG_PARAM_RETRY_SHORT) {
1576 wid_list[i].id = WID_SHORT_RETRY_LIMIT;
1577 wid_list[i].val = (s8 *)¶m->short_retry_limit;
1578 wid_list[i].type = WID_SHORT;
1579 wid_list[i].size = sizeof(u16);
1582 if (param->flag & WILC_CFG_PARAM_RETRY_LONG) {
1583 wid_list[i].id = WID_LONG_RETRY_LIMIT;
1584 wid_list[i].val = (s8 *)¶m->long_retry_limit;
1585 wid_list[i].type = WID_SHORT;
1586 wid_list[i].size = sizeof(u16);
1589 if (param->flag & WILC_CFG_PARAM_FRAG_THRESHOLD) {
1590 wid_list[i].id = WID_FRAG_THRESHOLD;
1591 wid_list[i].val = (s8 *)¶m->frag_threshold;
1592 wid_list[i].type = WID_SHORT;
1593 wid_list[i].size = sizeof(u16);
1596 if (param->flag & WILC_CFG_PARAM_RTS_THRESHOLD) {
1597 wid_list[i].id = WID_RTS_THRESHOLD;
1598 wid_list[i].val = (s8 *)¶m->rts_threshold;
1599 wid_list[i].type = WID_SHORT;
1600 wid_list[i].size = sizeof(u16);
1604 result = wilc_send_config_pkt(vif, WILC_SET_CFG, wid_list,
1605 i, wilc_get_vif_idx(vif));
1610 static void get_periodic_rssi(struct timer_list *t)
1612 struct wilc_vif *vif = from_timer(vif, t, periodic_rssi);
1614 if (!vif->hif_drv) {
1615 netdev_err(vif->ndev, "%s: hif driver is NULL", __func__);
1619 if (vif->hif_drv->hif_state == HOST_IF_CONNECTED)
1620 wilc_get_stats_async(vif, &vif->periodic_stat);
1622 mod_timer(&vif->periodic_rssi, jiffies + msecs_to_jiffies(5000));
1625 int wilc_init(struct net_device *dev, struct host_if_drv **hif_drv_handler)
1627 struct host_if_drv *hif_drv;
1628 struct wilc_vif *vif = netdev_priv(dev);
1629 struct wilc *wilc = vif->wilc;
1632 hif_drv = kzalloc(sizeof(*hif_drv), GFP_KERNEL);
1636 *hif_drv_handler = hif_drv;
1637 for (i = 0; i < wilc->vif_num; i++)
1638 if (dev == wilc->vif[i]->ndev) {
1639 wilc->vif[i]->hif_drv = hif_drv;
1640 hif_drv->driver_handler_id = i + 1;
1644 vif->obtaining_ip = false;
1646 if (wilc->clients_count == 0)
1647 mutex_init(&wilc->deinit_lock);
1649 timer_setup(&vif->periodic_rssi, get_periodic_rssi, 0);
1650 mod_timer(&vif->periodic_rssi, jiffies + msecs_to_jiffies(5000));
1652 timer_setup(&hif_drv->scan_timer, timer_scan_cb, 0);
1653 timer_setup(&hif_drv->connect_timer, timer_connect_cb, 0);
1654 timer_setup(&hif_drv->remain_on_ch_timer, listen_timer_cb, 0);
1656 hif_drv->hif_state = HOST_IF_IDLE;
1658 hif_drv->p2p_timeout = 0;
1660 wilc->clients_count++;
1665 int wilc_deinit(struct wilc_vif *vif)
1668 struct host_if_drv *hif_drv = vif->hif_drv;
1671 netdev_err(vif->ndev, "%s: hif driver is NULL", __func__);
1675 mutex_lock(&vif->wilc->deinit_lock);
1677 del_timer_sync(&hif_drv->scan_timer);
1678 del_timer_sync(&hif_drv->connect_timer);
1679 del_timer_sync(&vif->periodic_rssi);
1680 del_timer_sync(&hif_drv->remain_on_ch_timer);
1682 wilc_set_wfi_drv_handler(vif, 0, 0, 0);
1684 if (hif_drv->usr_scan_req.scan_result) {
1685 hif_drv->usr_scan_req.scan_result(SCAN_EVENT_ABORTED, NULL,
1686 hif_drv->usr_scan_req.arg);
1687 hif_drv->usr_scan_req.scan_result = NULL;
1690 hif_drv->hif_state = HOST_IF_IDLE;
1693 vif->hif_drv = NULL;
1694 vif->wilc->clients_count--;
1695 mutex_unlock(&vif->wilc->deinit_lock);
1699 void wilc_network_info_received(struct wilc *wilc, u8 *buffer, u32 length)
1702 struct host_if_msg *msg;
1704 struct host_if_drv *hif_drv;
1705 struct wilc_vif *vif;
1707 id = get_unaligned_le32(&buffer[length - 4]);
1708 vif = wilc_get_vif_from_idx(wilc, id);
1711 hif_drv = vif->hif_drv;
1714 netdev_err(vif->ndev, "driver not init[%p]\n", hif_drv);
1718 msg = wilc_alloc_work(vif, handle_rcvd_ntwrk_info, false);
1722 msg->body.net_info.frame_len = get_unaligned_le16(&buffer[6]) - 1;
1723 msg->body.net_info.rssi = buffer[8];
1724 msg->body.net_info.mgmt = kmemdup(&buffer[9],
1725 msg->body.net_info.frame_len,
1727 if (!msg->body.net_info.mgmt) {
1732 result = wilc_enqueue_work(msg);
1734 netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__);
1735 kfree(msg->body.net_info.mgmt);
1740 void wilc_gnrl_async_info_received(struct wilc *wilc, u8 *buffer, u32 length)
1743 struct host_if_msg *msg;
1745 struct host_if_drv *hif_drv;
1746 struct wilc_vif *vif;
1748 mutex_lock(&wilc->deinit_lock);
1750 id = get_unaligned_le32(&buffer[length - 4]);
1751 vif = wilc_get_vif_from_idx(wilc, id);
1753 mutex_unlock(&wilc->deinit_lock);
1757 hif_drv = vif->hif_drv;
1760 mutex_unlock(&wilc->deinit_lock);
1764 if (!hif_drv->conn_info.conn_result) {
1765 netdev_err(vif->ndev, "%s: conn_result is NULL\n", __func__);
1766 mutex_unlock(&wilc->deinit_lock);
1770 msg = wilc_alloc_work(vif, handle_rcvd_gnrl_async_info, false);
1772 mutex_unlock(&wilc->deinit_lock);
1776 msg->body.mac_info.status = buffer[7];
1777 result = wilc_enqueue_work(msg);
1779 netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__);
1783 mutex_unlock(&wilc->deinit_lock);
1786 void wilc_scan_complete_received(struct wilc *wilc, u8 *buffer, u32 length)
1790 struct host_if_drv *hif_drv;
1791 struct wilc_vif *vif;
1793 id = get_unaligned_le32(&buffer[length - 4]);
1794 vif = wilc_get_vif_from_idx(wilc, id);
1797 hif_drv = vif->hif_drv;
1802 if (hif_drv->usr_scan_req.scan_result) {
1803 struct host_if_msg *msg;
1805 msg = wilc_alloc_work(vif, handle_scan_complete, false);
1809 result = wilc_enqueue_work(msg);
1811 netdev_err(vif->ndev, "%s: enqueue work failed\n",
1818 int wilc_remain_on_channel(struct wilc_vif *vif, u64 cookie,
1819 u32 duration, u16 chan,
1820 void (*expired)(void *, u64),
1823 struct wilc_remain_ch roc;
1827 roc.expired = expired;
1829 roc.duration = duration;
1830 roc.cookie = cookie;
1831 result = handle_remain_on_chan(vif, &roc);
1833 netdev_err(vif->ndev, "%s: failed to set remain on channel\n",
1839 int wilc_listen_state_expired(struct wilc_vif *vif, u64 cookie)
1842 struct host_if_msg *msg;
1843 struct host_if_drv *hif_drv = vif->hif_drv;
1846 netdev_err(vif->ndev, "%s: hif driver is NULL", __func__);
1850 del_timer(&hif_drv->remain_on_ch_timer);
1852 msg = wilc_alloc_work(vif, handle_listen_state_expired, false);
1854 return PTR_ERR(msg);
1856 msg->body.remain_on_ch.cookie = cookie;
1858 result = wilc_enqueue_work(msg);
1860 netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__);
1867 void wilc_frame_register(struct wilc_vif *vif, u16 frame_type, bool reg)
1871 struct wilc_reg_frame reg_frame;
1873 wid.id = WID_REGISTER_FRAME;
1875 wid.size = sizeof(reg_frame);
1876 wid.val = (u8 *)®_frame;
1878 memset(®_frame, 0x0, sizeof(reg_frame));
1879 reg_frame.reg = reg;
1881 switch (frame_type) {
1882 case IEEE80211_STYPE_ACTION:
1883 reg_frame.reg_id = WILC_FW_ACTION_FRM_IDX;
1886 case IEEE80211_STYPE_PROBE_REQ:
1887 reg_frame.reg_id = WILC_FW_PROBE_REQ_IDX;
1893 reg_frame.frame_type = cpu_to_le16(frame_type);
1894 result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
1895 wilc_get_vif_idx(vif));
1897 netdev_err(vif->ndev, "Failed to frame register\n");
1900 int wilc_add_beacon(struct wilc_vif *vif, u32 interval, u32 dtim_period,
1901 struct cfg80211_beacon_data *params)
1907 wid.id = WID_ADD_BEACON;
1909 wid.size = params->head_len + params->tail_len + 16;
1910 wid.val = kzalloc(wid.size, GFP_KERNEL);
1915 put_unaligned_le32(interval, cur_byte);
1917 put_unaligned_le32(dtim_period, cur_byte);
1919 put_unaligned_le32(params->head_len, cur_byte);
1922 if (params->head_len > 0)
1923 memcpy(cur_byte, params->head, params->head_len);
1924 cur_byte += params->head_len;
1926 put_unaligned_le32(params->tail_len, cur_byte);
1929 if (params->tail_len > 0)
1930 memcpy(cur_byte, params->tail, params->tail_len);
1932 result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
1933 wilc_get_vif_idx(vif));
1935 netdev_err(vif->ndev, "Failed to send add beacon\n");
1942 int wilc_del_beacon(struct wilc_vif *vif)
1948 wid.id = WID_DEL_BEACON;
1949 wid.type = WID_CHAR;
1950 wid.size = sizeof(char);
1951 wid.val = &del_beacon;
1953 result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
1954 wilc_get_vif_idx(vif));
1956 netdev_err(vif->ndev, "Failed to send delete beacon\n");
1961 int wilc_add_station(struct wilc_vif *vif, const u8 *mac,
1962 struct station_parameters *params)
1968 wid.id = WID_ADD_STA;
1970 wid.size = WILC_ADD_STA_LENGTH + params->supported_rates_len;
1971 wid.val = kmalloc(wid.size, GFP_KERNEL);
1976 wilc_hif_pack_sta_param(cur_byte, mac, params);
1978 result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
1979 wilc_get_vif_idx(vif));
1981 netdev_err(vif->ndev, "Failed to send add station\n");
1988 int wilc_del_station(struct wilc_vif *vif, const u8 *mac_addr)
1993 wid.id = WID_REMOVE_STA;
1995 wid.size = ETH_ALEN;
1996 wid.val = kzalloc(wid.size, GFP_KERNEL);
2001 eth_broadcast_addr(wid.val);
2003 ether_addr_copy(wid.val, mac_addr);
2005 result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
2006 wilc_get_vif_idx(vif));
2008 netdev_err(vif->ndev, "Failed to del station\n");
2015 int wilc_del_allstation(struct wilc_vif *vif, u8 mac_addr[][ETH_ALEN])
2021 struct wilc_del_all_sta del_sta;
2023 memset(&del_sta, 0x0, sizeof(del_sta));
2024 for (i = 0; i < WILC_MAX_NUM_STA; i++) {
2025 if (!is_zero_ether_addr(mac_addr[i])) {
2027 ether_addr_copy(del_sta.mac[i], mac_addr[i]);
2034 del_sta.assoc_sta = assoc_sta;
2036 wid.id = WID_DEL_ALL_STA;
2038 wid.size = (assoc_sta * ETH_ALEN) + 1;
2039 wid.val = (u8 *)&del_sta;
2041 result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
2042 wilc_get_vif_idx(vif));
2044 netdev_err(vif->ndev, "Failed to send delete all station\n");
2049 int wilc_edit_station(struct wilc_vif *vif, const u8 *mac,
2050 struct station_parameters *params)
2056 wid.id = WID_EDIT_STA;
2058 wid.size = WILC_ADD_STA_LENGTH + params->supported_rates_len;
2059 wid.val = kmalloc(wid.size, GFP_KERNEL);
2064 wilc_hif_pack_sta_param(cur_byte, mac, params);
2066 result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
2067 wilc_get_vif_idx(vif));
2069 netdev_err(vif->ndev, "Failed to send edit station\n");
2075 int wilc_set_power_mgmt(struct wilc_vif *vif, bool enabled, u32 timeout)
2081 if (wilc_wlan_get_num_conn_ifcs(vif->wilc) == 2 && enabled)
2085 power_mode = WILC_FW_MIN_FAST_PS;
2087 power_mode = WILC_FW_NO_POWERSAVE;
2089 wid.id = WID_POWER_MANAGEMENT;
2090 wid.val = &power_mode;
2091 wid.size = sizeof(char);
2092 result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
2093 wilc_get_vif_idx(vif));
2095 netdev_err(vif->ndev, "Failed to send power management\n");
2100 int wilc_setup_multicast_filter(struct wilc_vif *vif, u32 enabled, u32 count,
2104 struct host_if_msg *msg;
2106 msg = wilc_alloc_work(vif, handle_set_mcast_filter, false);
2108 return PTR_ERR(msg);
2110 msg->body.mc_info.enabled = enabled;
2111 msg->body.mc_info.cnt = count;
2112 msg->body.mc_info.mc_list = mc_list;
2114 result = wilc_enqueue_work(msg);
2116 netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__);
2122 int wilc_set_tx_power(struct wilc_vif *vif, u8 tx_power)
2127 wid.id = WID_TX_POWER;
2128 wid.type = WID_CHAR;
2129 wid.val = &tx_power;
2130 wid.size = sizeof(char);
2132 ret = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
2133 wilc_get_vif_idx(vif));
2138 int wilc_get_tx_power(struct wilc_vif *vif, u8 *tx_power)
2143 wid.id = WID_TX_POWER;
2144 wid.type = WID_CHAR;
2146 wid.size = sizeof(char);
2148 ret = wilc_send_config_pkt(vif, WILC_GET_CFG, &wid, 1,
2149 wilc_get_vif_idx(vif));