1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2012 - 2018 Microchip Technology Inc., and its subsidiaries.
9 #define WILC_HIF_SCAN_TIMEOUT_MS 5000
10 #define WILC_HIF_CONNECT_TIMEOUT_MS 9500
12 #define WILC_FALSE_FRMWR_CHANNEL 100
14 #define WILC_SCAN_WID_LIST_SIZE 6
16 struct wilc_rcvd_mac_info
{
20 struct wilc_set_multicast
{
26 struct host_if_wowlan_trigger
{
30 struct wilc_del_all_sta
{
32 u8 mac
[WILC_MAX_NUM_STA
][ETH_ALEN
];
35 union wilc_message_body
{
36 struct wilc_rcvd_net_info net_info
;
37 struct wilc_rcvd_mac_info mac_info
;
38 struct wilc_set_multicast mc_info
;
39 struct wilc_remain_ch remain_on_ch
;
41 struct host_if_wowlan_trigger wow_trigger
;
45 union wilc_message_body body
;
47 struct work_struct work
;
48 void (*fn
)(struct work_struct
*ws
);
49 struct completion work_comp
;
53 /* 'msg' should be free by the caller for syc */
54 static struct host_if_msg
*
55 wilc_alloc_work(struct wilc_vif
*vif
, void (*work_fun
)(struct work_struct
*),
58 struct host_if_msg
*msg
;
61 return ERR_PTR(-EINVAL
);
63 msg
= kzalloc(sizeof(*msg
), GFP_ATOMIC
);
65 return ERR_PTR(-ENOMEM
);
68 msg
->is_sync
= is_sync
;
70 init_completion(&msg
->work_comp
);
75 static int wilc_enqueue_work(struct host_if_msg
*msg
)
77 INIT_WORK(&msg
->work
, msg
->fn
);
79 if (!msg
->vif
|| !msg
->vif
->wilc
|| !msg
->vif
->wilc
->hif_workqueue
)
82 if (!queue_work(msg
->vif
->wilc
->hif_workqueue
, &msg
->work
))
88 /* The idx starts from 0 to (NUM_CONCURRENT_IFC - 1), but 0 index used as
89 * special purpose in wilc device, so we add 1 to the index to starts from 1.
90 * As a result, the returned index will be 1 to NUM_CONCURRENT_IFC.
92 int wilc_get_vif_idx(struct wilc_vif
*vif
)
97 /* We need to minus 1 from idx which is from wilc device to get real index
98 * of wilc->vif[], because we add 1 when pass to wilc device in the function
100 * As a result, the index should be between 0 and (NUM_CONCURRENT_IFC - 1).
102 static struct wilc_vif
*wilc_get_vif_from_idx(struct wilc
*wilc
, int idx
)
105 struct wilc_vif
*vif
;
107 if (index
< 0 || index
>= WILC_NUM_CONCURRENT_IFC
)
110 wilc_for_each_vif(wilc
, vif
) {
111 if (vif
->idx
== index
)
118 static int handle_scan_done(struct wilc_vif
*vif
, enum scan_event evt
)
121 u8 abort_running_scan
;
123 struct host_if_drv
*hif_drv
= vif
->hif_drv
;
124 struct wilc_user_scan_req
*scan_req
;
126 if (evt
== SCAN_EVENT_ABORTED
) {
127 abort_running_scan
= 1;
128 wid
.id
= WID_ABORT_RUNNING_SCAN
;
130 wid
.val
= (s8
*)&abort_running_scan
;
131 wid
.size
= sizeof(char);
133 result
= wilc_send_config_pkt(vif
, WILC_SET_CFG
, &wid
, 1);
135 netdev_err(vif
->ndev
, "Failed to set abort running\n");
141 netdev_err(vif
->ndev
, "%s: hif driver is NULL\n", __func__
);
145 scan_req
= &hif_drv
->usr_scan_req
;
146 if (scan_req
->scan_result
) {
147 scan_req
->scan_result(evt
, NULL
, scan_req
->priv
);
148 scan_req
->scan_result
= NULL
;
154 int wilc_scan(struct wilc_vif
*vif
, u8 scan_source
,
155 u8 scan_type
, u8
*ch_freq_list
,
156 void (*scan_result_fn
)(enum scan_event
,
157 struct wilc_rcvd_net_info
*,
159 struct cfg80211_scan_request
*request
)
162 struct wid wid_list
[WILC_SCAN_WID_LIST_SIZE
];
167 u8
*search_ssid_vals
= NULL
;
168 const u8 ch_list_len
= request
->n_channels
;
169 struct host_if_drv
*hif_drv
= vif
->hif_drv
;
171 if (hif_drv
->hif_state
>= HOST_IF_SCANNING
&&
172 hif_drv
->hif_state
< HOST_IF_CONNECTED
) {
173 netdev_err(vif
->ndev
, "Already scan\n");
178 if (vif
->connecting
) {
179 netdev_err(vif
->ndev
, "Don't do obss scan\n");
184 hif_drv
->usr_scan_req
.ch_cnt
= 0;
186 if (request
->n_ssids
) {
187 for (i
= 0; i
< request
->n_ssids
; i
++)
188 valuesize
+= ((request
->ssids
[i
].ssid_len
) + 1);
189 search_ssid_vals
= kmalloc(valuesize
+ 1, GFP_KERNEL
);
190 if (search_ssid_vals
) {
191 wid_list
[index
].id
= WID_SSID_PROBE_REQ
;
192 wid_list
[index
].type
= WID_STR
;
193 wid_list
[index
].val
= search_ssid_vals
;
194 buffer
= wid_list
[index
].val
;
196 *buffer
++ = request
->n_ssids
;
198 for (i
= 0; i
< request
->n_ssids
; i
++) {
199 *buffer
++ = request
->ssids
[i
].ssid_len
;
200 memcpy(buffer
, request
->ssids
[i
].ssid
,
201 request
->ssids
[i
].ssid_len
);
202 buffer
+= request
->ssids
[i
].ssid_len
;
204 wid_list
[index
].size
= (s32
)(valuesize
+ 1);
209 wid_list
[index
].id
= WID_INFO_ELEMENT_PROBE
;
210 wid_list
[index
].type
= WID_BIN_DATA
;
211 wid_list
[index
].val
= (s8
*)request
->ie
;
212 wid_list
[index
].size
= request
->ie_len
;
215 wid_list
[index
].id
= WID_SCAN_TYPE
;
216 wid_list
[index
].type
= WID_CHAR
;
217 wid_list
[index
].size
= sizeof(char);
218 wid_list
[index
].val
= (s8
*)&scan_type
;
221 if (scan_type
== WILC_FW_PASSIVE_SCAN
&& request
->duration
) {
222 wid_list
[index
].id
= WID_PASSIVE_SCAN_TIME
;
223 wid_list
[index
].type
= WID_SHORT
;
224 wid_list
[index
].size
= sizeof(u16
);
225 wid_list
[index
].val
= (s8
*)&request
->duration
;
228 scan_timeout
= (request
->duration
* ch_list_len
) + 500;
230 scan_timeout
= WILC_HIF_SCAN_TIMEOUT_MS
;
233 wid_list
[index
].id
= WID_SCAN_CHANNEL_LIST
;
234 wid_list
[index
].type
= WID_BIN_DATA
;
236 if (ch_freq_list
&& ch_list_len
> 0) {
237 for (i
= 0; i
< ch_list_len
; i
++) {
238 if (ch_freq_list
[i
] > 0)
239 ch_freq_list
[i
] -= 1;
243 wid_list
[index
].val
= ch_freq_list
;
244 wid_list
[index
].size
= ch_list_len
;
247 wid_list
[index
].id
= WID_START_SCAN_REQ
;
248 wid_list
[index
].type
= WID_CHAR
;
249 wid_list
[index
].size
= sizeof(char);
250 wid_list
[index
].val
= (s8
*)&scan_source
;
253 hif_drv
->usr_scan_req
.scan_result
= scan_result_fn
;
254 hif_drv
->usr_scan_req
.priv
= &vif
->priv
;
256 result
= wilc_send_config_pkt(vif
, WILC_SET_CFG
, wid_list
, index
);
258 netdev_err(vif
->ndev
, "Failed to send scan parameters\n");
262 hif_drv
->scan_timer_vif
= vif
;
263 mod_timer(&hif_drv
->scan_timer
,
264 jiffies
+ msecs_to_jiffies(scan_timeout
));
268 kfree(search_ssid_vals
);
273 static int wilc_send_connect_wid(struct wilc_vif
*vif
)
276 struct wid wid_list
[5];
278 struct host_if_drv
*hif_drv
= vif
->hif_drv
;
279 struct wilc_conn_info
*conn_attr
= &hif_drv
->conn_info
;
280 struct wilc_join_bss_param
*bss_param
= conn_attr
->param
;
283 wid_list
[wid_cnt
].id
= WID_SET_MFP
;
284 wid_list
[wid_cnt
].type
= WID_CHAR
;
285 wid_list
[wid_cnt
].size
= sizeof(char);
286 wid_list
[wid_cnt
].val
= (s8
*)&conn_attr
->mfp_type
;
289 wid_list
[wid_cnt
].id
= WID_INFO_ELEMENT_ASSOCIATE
;
290 wid_list
[wid_cnt
].type
= WID_BIN_DATA
;
291 wid_list
[wid_cnt
].val
= conn_attr
->req_ies
;
292 wid_list
[wid_cnt
].size
= conn_attr
->req_ies_len
;
295 wid_list
[wid_cnt
].id
= WID_11I_MODE
;
296 wid_list
[wid_cnt
].type
= WID_CHAR
;
297 wid_list
[wid_cnt
].size
= sizeof(char);
298 wid_list
[wid_cnt
].val
= (s8
*)&conn_attr
->security
;
301 wid_list
[wid_cnt
].id
= WID_AUTH_TYPE
;
302 wid_list
[wid_cnt
].type
= WID_CHAR
;
303 wid_list
[wid_cnt
].size
= sizeof(char);
304 wid_list
[wid_cnt
].val
= (s8
*)&conn_attr
->auth_type
;
307 wid_list
[wid_cnt
].id
= WID_JOIN_REQ_EXTENDED
;
308 wid_list
[wid_cnt
].type
= WID_STR
;
309 wid_list
[wid_cnt
].size
= sizeof(*bss_param
);
310 wid_list
[wid_cnt
].val
= (u8
*)bss_param
;
313 result
= wilc_send_config_pkt(vif
, WILC_SET_CFG
, wid_list
, wid_cnt
);
315 netdev_err(vif
->ndev
, "failed to send config packet\n");
318 if (conn_attr
->auth_type
== WILC_FW_AUTH_SAE
)
319 hif_drv
->hif_state
= HOST_IF_EXTERNAL_AUTH
;
321 hif_drv
->hif_state
= HOST_IF_WAITING_CONN_RESP
;
328 kfree(conn_attr
->req_ies
);
329 conn_attr
->req_ies
= NULL
;
334 static void handle_connect_timeout(struct work_struct
*work
)
336 struct host_if_msg
*msg
= container_of(work
, struct host_if_msg
, work
);
337 struct wilc_vif
*vif
= msg
->vif
;
340 u16 dummy_reason_code
= 0;
341 struct host_if_drv
*hif_drv
= vif
->hif_drv
;
344 netdev_err(vif
->ndev
, "%s: hif driver is NULL\n", __func__
);
348 hif_drv
->hif_state
= HOST_IF_IDLE
;
350 if (hif_drv
->conn_info
.conn_result
) {
351 hif_drv
->conn_info
.conn_result(CONN_DISCONN_EVENT_CONN_RESP
,
352 WILC_MAC_STATUS_DISCONNECTED
,
353 hif_drv
->conn_info
.priv
);
356 netdev_err(vif
->ndev
, "%s: conn_result is NULL\n", __func__
);
359 wid
.id
= WID_DISCONNECT
;
361 wid
.val
= (s8
*)&dummy_reason_code
;
362 wid
.size
= sizeof(char);
364 result
= wilc_send_config_pkt(vif
, WILC_SET_CFG
, &wid
, 1);
366 netdev_err(vif
->ndev
, "Failed to send disconnect\n");
368 hif_drv
->conn_info
.req_ies_len
= 0;
369 kfree(hif_drv
->conn_info
.req_ies
);
370 hif_drv
->conn_info
.req_ies
= NULL
;
376 struct wilc_join_bss_param
*
377 wilc_parse_join_bss_param(struct cfg80211_bss
*bss
,
378 struct cfg80211_crypto_settings
*crypto
)
380 const u8
*ies_data
, *tim_elm
, *ssid_elm
, *rates_ie
, *supp_rates_ie
;
381 const u8
*ht_ie
, *wpa_ie
, *wmm_ie
, *rsn_ie
;
382 struct ieee80211_p2p_noa_attr noa_attr
;
383 const struct cfg80211_bss_ies
*ies
;
384 struct wilc_join_bss_param
*param
;
390 param
= kzalloc(sizeof(*param
), GFP_KERNEL
);
395 ies
= rcu_dereference(bss
->ies
);
396 ies_data
= kmemdup(ies
->data
, ies
->len
, GFP_ATOMIC
);
406 param
->beacon_period
= cpu_to_le16(bss
->beacon_interval
);
407 param
->cap_info
= cpu_to_le16(bss
->capability
);
408 param
->bss_type
= WILC_FW_BSS_TYPE_INFRA
;
409 param
->ch
= ieee80211_frequency_to_channel(bss
->channel
->center_freq
);
410 ether_addr_copy(param
->bssid
, bss
->bssid
);
412 ssid_elm
= cfg80211_find_ie(WLAN_EID_SSID
, ies_data
, ies_len
);
414 if (ssid_elm
[1] <= IEEE80211_MAX_SSID_LEN
)
415 memcpy(param
->ssid
, ssid_elm
+ 2, ssid_elm
[1]);
418 tim_elm
= cfg80211_find_ie(WLAN_EID_TIM
, ies_data
, ies_len
);
419 if (tim_elm
&& tim_elm
[1] >= 2)
420 param
->dtim_period
= tim_elm
[3];
422 memset(param
->p_suites
, 0xFF, 3);
423 memset(param
->akm_suites
, 0xFF, 3);
425 rates_ie
= cfg80211_find_ie(WLAN_EID_SUPP_RATES
, ies_data
, ies_len
);
427 rates_len
= rates_ie
[1];
428 if (rates_len
> WILC_MAX_RATES_SUPPORTED
)
429 rates_len
= WILC_MAX_RATES_SUPPORTED
;
430 param
->supp_rates
[0] = rates_len
;
431 memcpy(¶m
->supp_rates
[1], rates_ie
+ 2, rates_len
);
434 if (rates_len
< WILC_MAX_RATES_SUPPORTED
) {
435 supp_rates_ie
= cfg80211_find_ie(WLAN_EID_EXT_SUPP_RATES
,
438 u8 ext_rates
= supp_rates_ie
[1];
440 if (ext_rates
> (WILC_MAX_RATES_SUPPORTED
- rates_len
))
441 param
->supp_rates
[0] = WILC_MAX_RATES_SUPPORTED
;
443 param
->supp_rates
[0] += ext_rates
;
445 memcpy(¶m
->supp_rates
[rates_len
+ 1],
447 (param
->supp_rates
[0] - rates_len
));
451 ht_ie
= cfg80211_find_ie(WLAN_EID_HT_CAPABILITY
, ies_data
, ies_len
);
453 param
->ht_capable
= true;
455 ret
= cfg80211_get_p2p_attr(ies_data
, ies_len
,
456 IEEE80211_P2P_ATTR_ABSENCE_NOTICE
,
457 (u8
*)&noa_attr
, sizeof(noa_attr
));
459 param
->tsf_lo
= cpu_to_le32(ies_tsf
);
460 param
->noa_enabled
= 1;
461 param
->idx
= noa_attr
.index
;
462 if (noa_attr
.oppps_ctwindow
& IEEE80211_P2P_OPPPS_ENABLE_BIT
) {
463 param
->opp_enabled
= 1;
464 param
->opp_en
.ct_window
= noa_attr
.oppps_ctwindow
;
465 param
->opp_en
.cnt
= noa_attr
.desc
[0].count
;
466 param
->opp_en
.duration
= noa_attr
.desc
[0].duration
;
467 param
->opp_en
.interval
= noa_attr
.desc
[0].interval
;
468 param
->opp_en
.start_time
= noa_attr
.desc
[0].start_time
;
470 param
->opp_enabled
= 0;
471 param
->opp_dis
.cnt
= noa_attr
.desc
[0].count
;
472 param
->opp_dis
.duration
= noa_attr
.desc
[0].duration
;
473 param
->opp_dis
.interval
= noa_attr
.desc
[0].interval
;
474 param
->opp_dis
.start_time
= noa_attr
.desc
[0].start_time
;
477 wmm_ie
= cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT
,
478 WLAN_OUI_TYPE_MICROSOFT_WMM
,
481 struct ieee80211_wmm_param_ie
*ie
;
483 ie
= (struct ieee80211_wmm_param_ie
*)wmm_ie
;
484 if ((ie
->oui_subtype
== 0 || ie
->oui_subtype
== 1) &&
486 param
->wmm_cap
= true;
487 if (ie
->qos_info
& BIT(7))
488 param
->uapsd_cap
= true;
492 wpa_ie
= cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT
,
493 WLAN_OUI_TYPE_MICROSOFT_WPA
,
496 param
->mode_802_11i
= 1;
497 param
->rsn_found
= true;
500 rsn_ie
= cfg80211_find_ie(WLAN_EID_RSN
, ies_data
, ies_len
);
502 int rsn_ie_len
= sizeof(struct element
) + rsn_ie
[1];
505 param
->mode_802_11i
= 2;
506 param
->rsn_found
= true;
508 /* extract RSN capabilities */
509 if (offset
< rsn_ie_len
) {
510 /* skip over pairwise suites */
511 offset
+= (rsn_ie
[offset
] * 4) + 2;
513 if (offset
< rsn_ie_len
) {
514 /* skip over authentication suites */
515 offset
+= (rsn_ie
[offset
] * 4) + 2;
517 if (offset
+ 1 < rsn_ie_len
)
518 memcpy(param
->rsn_cap
, &rsn_ie
[offset
], 2);
523 if (param
->rsn_found
) {
526 param
->rsn_grp_policy
= crypto
->cipher_group
& 0xFF;
527 for (i
= 0; i
< crypto
->n_ciphers_pairwise
&& i
< 3; i
++)
528 param
->p_suites
[i
] = crypto
->ciphers_pairwise
[i
] & 0xFF;
530 for (i
= 0; i
< crypto
->n_akm_suites
&& i
< 3; i
++)
531 param
->akm_suites
[i
] = crypto
->akm_suites
[i
] & 0xFF;
535 return (void *)param
;
538 static void handle_rcvd_ntwrk_info(struct work_struct
*work
)
540 struct host_if_msg
*msg
= container_of(work
, struct host_if_msg
, work
);
541 struct wilc_rcvd_net_info
*rcvd_info
= &msg
->body
.net_info
;
542 struct wilc_user_scan_req
*scan_req
= &msg
->vif
->hif_drv
->usr_scan_req
;
548 if (ieee80211_is_probe_resp(rcvd_info
->mgmt
->frame_control
))
549 offset
= offsetof(struct ieee80211_mgmt
, u
.probe_resp
.variable
);
550 else if (ieee80211_is_beacon(rcvd_info
->mgmt
->frame_control
))
551 offset
= offsetof(struct ieee80211_mgmt
, u
.beacon
.variable
);
555 ies
= rcvd_info
->mgmt
->u
.beacon
.variable
;
556 ies_len
= rcvd_info
->frame_len
- offset
;
560 ch_elm
= cfg80211_find_ie(WLAN_EID_DS_PARAMS
, ies
, ies_len
);
561 if (ch_elm
&& ch_elm
[1] > 0)
562 rcvd_info
->ch
= ch_elm
[2];
564 if (scan_req
->scan_result
)
565 scan_req
->scan_result(SCAN_EVENT_NETWORK_FOUND
, rcvd_info
,
569 kfree(rcvd_info
->mgmt
);
573 static void host_int_get_assoc_res_info(struct wilc_vif
*vif
,
575 u32 max_assoc_resp_info_len
,
576 u32
*rcvd_assoc_resp_info_len
)
581 wid
.id
= WID_ASSOC_RES_INFO
;
583 wid
.val
= assoc_resp_info
;
584 wid
.size
= max_assoc_resp_info_len
;
586 result
= wilc_send_config_pkt(vif
, WILC_GET_CFG
, &wid
, 1);
588 *rcvd_assoc_resp_info_len
= 0;
589 netdev_err(vif
->ndev
, "Failed to send association response\n");
593 *rcvd_assoc_resp_info_len
= wid
.size
;
596 static s32
wilc_parse_assoc_resp_info(u8
*buffer
, u32 buffer_len
,
597 struct wilc_conn_info
*ret_conn_info
)
601 struct wilc_assoc_resp
*res
= (struct wilc_assoc_resp
*)buffer
;
603 ret_conn_info
->status
= le16_to_cpu(res
->status_code
);
604 if (ret_conn_info
->status
== WLAN_STATUS_SUCCESS
) {
605 ies
= &buffer
[sizeof(*res
)];
606 ies_len
= buffer_len
- sizeof(*res
);
608 ret_conn_info
->resp_ies
= kmemdup(ies
, ies_len
, GFP_KERNEL
);
609 if (!ret_conn_info
->resp_ies
)
612 ret_conn_info
->resp_ies_len
= ies_len
;
618 static inline void host_int_parse_assoc_resp_info(struct wilc_vif
*vif
,
621 struct host_if_drv
*hif_drv
= vif
->hif_drv
;
622 struct wilc_conn_info
*conn_info
= &hif_drv
->conn_info
;
624 if (mac_status
== WILC_MAC_STATUS_CONNECTED
) {
625 u32 assoc_resp_info_len
;
627 memset(hif_drv
->assoc_resp
, 0, WILC_MAX_ASSOC_RESP_FRAME_SIZE
);
629 host_int_get_assoc_res_info(vif
, hif_drv
->assoc_resp
,
630 WILC_MAX_ASSOC_RESP_FRAME_SIZE
,
631 &assoc_resp_info_len
);
633 if (assoc_resp_info_len
!= 0) {
636 err
= wilc_parse_assoc_resp_info(hif_drv
->assoc_resp
,
640 netdev_err(vif
->ndev
,
641 "wilc_parse_assoc_resp_info() returned error %d\n",
646 del_timer(&hif_drv
->connect_timer
);
647 conn_info
->conn_result(CONN_DISCONN_EVENT_CONN_RESP
, mac_status
,
648 hif_drv
->conn_info
.priv
);
650 if (mac_status
== WILC_MAC_STATUS_CONNECTED
&&
651 conn_info
->status
== WLAN_STATUS_SUCCESS
) {
652 ether_addr_copy(hif_drv
->assoc_bssid
, conn_info
->bssid
);
653 hif_drv
->hif_state
= HOST_IF_CONNECTED
;
655 hif_drv
->hif_state
= HOST_IF_IDLE
;
658 kfree(conn_info
->resp_ies
);
659 conn_info
->resp_ies
= NULL
;
660 conn_info
->resp_ies_len
= 0;
662 kfree(conn_info
->req_ies
);
663 conn_info
->req_ies
= NULL
;
664 conn_info
->req_ies_len
= 0;
667 void wilc_handle_disconnect(struct wilc_vif
*vif
)
669 struct host_if_drv
*hif_drv
= vif
->hif_drv
;
671 if (hif_drv
->usr_scan_req
.scan_result
) {
672 del_timer(&hif_drv
->scan_timer
);
673 handle_scan_done(vif
, SCAN_EVENT_ABORTED
);
676 if (hif_drv
->conn_info
.conn_result
)
677 hif_drv
->conn_info
.conn_result(CONN_DISCONN_EVENT_DISCONN_NOTIF
,
678 0, hif_drv
->conn_info
.priv
);
680 eth_zero_addr(hif_drv
->assoc_bssid
);
682 hif_drv
->conn_info
.req_ies_len
= 0;
683 kfree(hif_drv
->conn_info
.req_ies
);
684 hif_drv
->conn_info
.req_ies
= NULL
;
685 hif_drv
->hif_state
= HOST_IF_IDLE
;
688 static void handle_rcvd_gnrl_async_info(struct work_struct
*work
)
690 struct host_if_msg
*msg
= container_of(work
, struct host_if_msg
, work
);
691 struct wilc_vif
*vif
= msg
->vif
;
692 struct wilc_rcvd_mac_info
*mac_info
= &msg
->body
.mac_info
;
693 struct host_if_drv
*hif_drv
= vif
->hif_drv
;
696 netdev_err(vif
->ndev
, "%s: hif driver is NULL\n", __func__
);
700 if (!hif_drv
->conn_info
.conn_result
) {
701 netdev_err(vif
->ndev
, "%s: conn_result is NULL\n", __func__
);
706 if (hif_drv
->hif_state
== HOST_IF_EXTERNAL_AUTH
) {
707 cfg80211_external_auth_request(vif
->ndev
, &vif
->auth
,
709 hif_drv
->hif_state
= HOST_IF_WAITING_CONN_RESP
;
710 } else if (hif_drv
->hif_state
== HOST_IF_WAITING_CONN_RESP
) {
711 host_int_parse_assoc_resp_info(vif
, mac_info
->status
);
712 } else if (mac_info
->status
== WILC_MAC_STATUS_DISCONNECTED
) {
713 if (hif_drv
->hif_state
== HOST_IF_CONNECTED
) {
714 wilc_handle_disconnect(vif
);
715 } else if (hif_drv
->usr_scan_req
.scan_result
) {
716 del_timer(&hif_drv
->scan_timer
);
717 handle_scan_done(vif
, SCAN_EVENT_ABORTED
);
725 int wilc_disconnect(struct wilc_vif
*vif
)
728 struct host_if_drv
*hif_drv
= vif
->hif_drv
;
729 struct wilc_user_scan_req
*scan_req
;
730 struct wilc_conn_info
*conn_info
;
732 u16 dummy_reason_code
= 0;
734 wid
.id
= WID_DISCONNECT
;
736 wid
.val
= (s8
*)&dummy_reason_code
;
737 wid
.size
= sizeof(char);
739 result
= wilc_send_config_pkt(vif
, WILC_SET_CFG
, &wid
, 1);
741 netdev_err(vif
->ndev
, "Failed to send disconnect\n");
745 scan_req
= &hif_drv
->usr_scan_req
;
746 conn_info
= &hif_drv
->conn_info
;
748 if (scan_req
->scan_result
) {
749 del_timer(&hif_drv
->scan_timer
);
750 scan_req
->scan_result(SCAN_EVENT_ABORTED
, NULL
, scan_req
->priv
);
751 scan_req
->scan_result
= NULL
;
754 if (conn_info
->conn_result
) {
755 if (hif_drv
->hif_state
== HOST_IF_WAITING_CONN_RESP
||
756 hif_drv
->hif_state
== HOST_IF_EXTERNAL_AUTH
)
757 del_timer(&hif_drv
->connect_timer
);
759 conn_info
->conn_result(CONN_DISCONN_EVENT_DISCONN_NOTIF
, 0,
762 netdev_err(vif
->ndev
, "%s: conn_result is NULL\n", __func__
);
765 hif_drv
->hif_state
= HOST_IF_IDLE
;
767 eth_zero_addr(hif_drv
->assoc_bssid
);
769 conn_info
->req_ies_len
= 0;
770 kfree(conn_info
->req_ies
);
771 conn_info
->req_ies
= NULL
;
776 int wilc_get_statistics(struct wilc_vif
*vif
, struct rf_info
*stats
)
778 struct wid wid_list
[5];
779 u32 wid_cnt
= 0, result
;
781 wid_list
[wid_cnt
].id
= WID_LINKSPEED
;
782 wid_list
[wid_cnt
].type
= WID_CHAR
;
783 wid_list
[wid_cnt
].size
= sizeof(char);
784 wid_list
[wid_cnt
].val
= (s8
*)&stats
->link_speed
;
787 wid_list
[wid_cnt
].id
= WID_RSSI
;
788 wid_list
[wid_cnt
].type
= WID_CHAR
;
789 wid_list
[wid_cnt
].size
= sizeof(char);
790 wid_list
[wid_cnt
].val
= (s8
*)&stats
->rssi
;
793 wid_list
[wid_cnt
].id
= WID_SUCCESS_FRAME_COUNT
;
794 wid_list
[wid_cnt
].type
= WID_INT
;
795 wid_list
[wid_cnt
].size
= sizeof(u32
);
796 wid_list
[wid_cnt
].val
= (s8
*)&stats
->tx_cnt
;
799 wid_list
[wid_cnt
].id
= WID_RECEIVED_FRAGMENT_COUNT
;
800 wid_list
[wid_cnt
].type
= WID_INT
;
801 wid_list
[wid_cnt
].size
= sizeof(u32
);
802 wid_list
[wid_cnt
].val
= (s8
*)&stats
->rx_cnt
;
805 wid_list
[wid_cnt
].id
= WID_FAILED_COUNT
;
806 wid_list
[wid_cnt
].type
= WID_INT
;
807 wid_list
[wid_cnt
].size
= sizeof(u32
);
808 wid_list
[wid_cnt
].val
= (s8
*)&stats
->tx_fail_cnt
;
811 result
= wilc_send_config_pkt(vif
, WILC_GET_CFG
, wid_list
, wid_cnt
);
813 netdev_err(vif
->ndev
, "Failed to send scan parameters\n");
817 if (stats
->link_speed
> TCP_ACK_FILTER_LINK_SPEED_THRESH
&&
818 stats
->link_speed
!= DEFAULT_LINK_SPEED
)
819 wilc_enable_tcp_ack_filter(vif
, true);
820 else if (stats
->link_speed
!= DEFAULT_LINK_SPEED
)
821 wilc_enable_tcp_ack_filter(vif
, false);
826 static void handle_get_statistics(struct work_struct
*work
)
828 struct host_if_msg
*msg
= container_of(work
, struct host_if_msg
, work
);
829 struct wilc_vif
*vif
= msg
->vif
;
830 struct rf_info
*stats
= (struct rf_info
*)msg
->body
.data
;
832 wilc_get_statistics(vif
, stats
);
837 static void wilc_hif_pack_sta_param(u8
*cur_byte
, const u8
*mac
,
838 struct station_parameters
*params
)
840 ether_addr_copy(cur_byte
, mac
);
841 cur_byte
+= ETH_ALEN
;
843 put_unaligned_le16(params
->aid
, cur_byte
);
846 *cur_byte
++ = params
->link_sta_params
.supported_rates_len
;
847 if (params
->link_sta_params
.supported_rates_len
> 0)
848 memcpy(cur_byte
, params
->link_sta_params
.supported_rates
,
849 params
->link_sta_params
.supported_rates_len
);
850 cur_byte
+= params
->link_sta_params
.supported_rates_len
;
852 if (params
->link_sta_params
.ht_capa
) {
854 memcpy(cur_byte
, params
->link_sta_params
.ht_capa
,
855 sizeof(struct ieee80211_ht_cap
));
859 cur_byte
+= sizeof(struct ieee80211_ht_cap
);
861 put_unaligned_le16(params
->sta_flags_mask
, cur_byte
);
863 put_unaligned_le16(params
->sta_flags_set
, cur_byte
);
866 static int handle_remain_on_chan(struct wilc_vif
*vif
,
867 struct wilc_remain_ch
*hif_remain_ch
)
870 u8 remain_on_chan_flag
;
872 struct host_if_drv
*hif_drv
= vif
->hif_drv
;
874 if (hif_drv
->usr_scan_req
.scan_result
)
877 if (hif_drv
->hif_state
== HOST_IF_WAITING_CONN_RESP
)
883 remain_on_chan_flag
= true;
884 wid
.id
= WID_REMAIN_ON_CHAN
;
887 wid
.val
= kmalloc(wid
.size
, GFP_KERNEL
);
891 wid
.val
[0] = remain_on_chan_flag
;
892 wid
.val
[1] = (s8
)hif_remain_ch
->ch
;
894 result
= wilc_send_config_pkt(vif
, WILC_SET_CFG
, &wid
, 1);
899 hif_drv
->remain_on_ch
.vif
= hif_remain_ch
->vif
;
900 hif_drv
->remain_on_ch
.expired
= hif_remain_ch
->expired
;
901 hif_drv
->remain_on_ch
.ch
= hif_remain_ch
->ch
;
902 hif_drv
->remain_on_ch
.cookie
= hif_remain_ch
->cookie
;
903 hif_drv
->remain_on_ch_timer_vif
= vif
;
908 static int wilc_handle_roc_expired(struct wilc_vif
*vif
, u64 cookie
)
910 u8 remain_on_chan_flag
;
913 struct host_if_drv
*hif_drv
= vif
->hif_drv
;
915 if (vif
->priv
.p2p_listen_state
) {
916 remain_on_chan_flag
= false;
917 wid
.id
= WID_REMAIN_ON_CHAN
;
921 wid
.val
= kmalloc(wid
.size
, GFP_KERNEL
);
925 wid
.val
[0] = remain_on_chan_flag
;
926 wid
.val
[1] = WILC_FALSE_FRMWR_CHANNEL
;
928 result
= wilc_send_config_pkt(vif
, WILC_SET_CFG
, &wid
, 1);
931 netdev_err(vif
->ndev
, "Failed to set remain channel\n");
935 if (hif_drv
->remain_on_ch
.expired
) {
936 hif_drv
->remain_on_ch
.expired(hif_drv
->remain_on_ch
.vif
,
940 netdev_dbg(vif
->ndev
, "Not in listen state\n");
946 static void wilc_handle_listen_state_expired(struct work_struct
*work
)
948 struct host_if_msg
*msg
= container_of(work
, struct host_if_msg
, work
);
950 wilc_handle_roc_expired(msg
->vif
, msg
->body
.remain_on_ch
.cookie
);
954 static void listen_timer_cb(struct timer_list
*t
)
956 struct host_if_drv
*hif_drv
= from_timer(hif_drv
, t
,
958 struct wilc_vif
*vif
= hif_drv
->remain_on_ch_timer_vif
;
960 struct host_if_msg
*msg
;
962 del_timer(&vif
->hif_drv
->remain_on_ch_timer
);
964 msg
= wilc_alloc_work(vif
, wilc_handle_listen_state_expired
, false);
968 msg
->body
.remain_on_ch
.cookie
= vif
->hif_drv
->remain_on_ch
.cookie
;
970 result
= wilc_enqueue_work(msg
);
972 netdev_err(vif
->ndev
, "%s: enqueue work failed\n", __func__
);
977 static void handle_set_mcast_filter(struct work_struct
*work
)
979 struct host_if_msg
*msg
= container_of(work
, struct host_if_msg
, work
);
980 struct wilc_vif
*vif
= msg
->vif
;
981 struct wilc_set_multicast
*set_mc
= &msg
->body
.mc_info
;
986 wid
.id
= WID_SETUP_MULTICAST_FILTER
;
988 wid
.size
= sizeof(struct wilc_set_multicast
) + (set_mc
->cnt
* ETH_ALEN
);
989 wid
.val
= kmalloc(wid
.size
, GFP_KERNEL
);
994 put_unaligned_le32(set_mc
->enabled
, cur_byte
);
997 put_unaligned_le32(set_mc
->cnt
, cur_byte
);
1000 if (set_mc
->cnt
> 0 && set_mc
->mc_list
)
1001 memcpy(cur_byte
, set_mc
->mc_list
, set_mc
->cnt
* ETH_ALEN
);
1003 result
= wilc_send_config_pkt(vif
, WILC_SET_CFG
, &wid
, 1);
1005 netdev_err(vif
->ndev
, "Failed to send setup multicast\n");
1008 kfree(set_mc
->mc_list
);
1013 void wilc_set_wowlan_trigger(struct wilc_vif
*vif
, bool enabled
)
1017 u8 wowlan_trigger
= 0;
1022 wid
.id
= WID_WOWLAN_TRIGGER
;
1023 wid
.type
= WID_CHAR
;
1024 wid
.val
= &wowlan_trigger
;
1025 wid
.size
= sizeof(char);
1027 ret
= wilc_send_config_pkt(vif
, WILC_SET_CFG
, &wid
, 1);
1029 pr_err("Failed to send wowlan trigger config packet\n");
1032 int wilc_set_external_auth_param(struct wilc_vif
*vif
,
1033 struct cfg80211_external_auth_params
*auth
)
1037 struct wilc_external_auth_param
*param
;
1039 wid
.id
= WID_EXTERNAL_AUTH_PARAM
;
1040 wid
.type
= WID_BIN_DATA
;
1041 wid
.size
= sizeof(*param
);
1042 param
= kzalloc(sizeof(*param
), GFP_KERNEL
);
1046 wid
.val
= (u8
*)param
;
1047 param
->action
= auth
->action
;
1048 ether_addr_copy(param
->bssid
, auth
->bssid
);
1049 memcpy(param
->ssid
, auth
->ssid
.ssid
, auth
->ssid
.ssid_len
);
1050 param
->ssid_len
= auth
->ssid
.ssid_len
;
1051 ret
= wilc_send_config_pkt(vif
, WILC_SET_CFG
, &wid
, 1);
1057 static void handle_scan_timer(struct work_struct
*work
)
1059 struct host_if_msg
*msg
= container_of(work
, struct host_if_msg
, work
);
1061 handle_scan_done(msg
->vif
, SCAN_EVENT_ABORTED
);
1065 static void handle_scan_complete(struct work_struct
*work
)
1067 struct host_if_msg
*msg
= container_of(work
, struct host_if_msg
, work
);
1069 del_timer(&msg
->vif
->hif_drv
->scan_timer
);
1071 handle_scan_done(msg
->vif
, SCAN_EVENT_DONE
);
1076 static void timer_scan_cb(struct timer_list
*t
)
1078 struct host_if_drv
*hif_drv
= from_timer(hif_drv
, t
, scan_timer
);
1079 struct wilc_vif
*vif
= hif_drv
->scan_timer_vif
;
1080 struct host_if_msg
*msg
;
1083 msg
= wilc_alloc_work(vif
, handle_scan_timer
, false);
1087 result
= wilc_enqueue_work(msg
);
1092 static void timer_connect_cb(struct timer_list
*t
)
1094 struct host_if_drv
*hif_drv
= from_timer(hif_drv
, t
,
1096 struct wilc_vif
*vif
= hif_drv
->connect_timer_vif
;
1097 struct host_if_msg
*msg
;
1100 msg
= wilc_alloc_work(vif
, handle_connect_timeout
, false);
1104 result
= wilc_enqueue_work(msg
);
1109 int wilc_add_ptk(struct wilc_vif
*vif
, const u8
*ptk
, u8 ptk_key_len
,
1110 const u8
*mac_addr
, const u8
*rx_mic
, const u8
*tx_mic
,
1111 u8 mode
, u8 cipher_mode
, u8 index
)
1114 u8 t_key_len
= ptk_key_len
+ WILC_RX_MIC_KEY_LEN
+ WILC_TX_MIC_KEY_LEN
;
1116 if (mode
== WILC_AP_MODE
) {
1117 struct wid wid_list
[2];
1118 struct wilc_ap_wpa_ptk
*key_buf
;
1120 wid_list
[0].id
= WID_11I_MODE
;
1121 wid_list
[0].type
= WID_CHAR
;
1122 wid_list
[0].size
= sizeof(char);
1123 wid_list
[0].val
= (s8
*)&cipher_mode
;
1125 key_buf
= kzalloc(sizeof(*key_buf
) + t_key_len
, GFP_KERNEL
);
1129 ether_addr_copy(key_buf
->mac_addr
, mac_addr
);
1130 key_buf
->index
= index
;
1131 key_buf
->key_len
= t_key_len
;
1132 memcpy(&key_buf
->key
[0], ptk
, ptk_key_len
);
1135 memcpy(&key_buf
->key
[ptk_key_len
], rx_mic
,
1136 WILC_RX_MIC_KEY_LEN
);
1139 memcpy(&key_buf
->key
[ptk_key_len
+ WILC_RX_MIC_KEY_LEN
],
1140 tx_mic
, WILC_TX_MIC_KEY_LEN
);
1142 wid_list
[1].id
= WID_ADD_PTK
;
1143 wid_list
[1].type
= WID_STR
;
1144 wid_list
[1].size
= sizeof(*key_buf
) + t_key_len
;
1145 wid_list
[1].val
= (u8
*)key_buf
;
1146 result
= wilc_send_config_pkt(vif
, WILC_SET_CFG
, wid_list
,
1147 ARRAY_SIZE(wid_list
));
1149 } else if (mode
== WILC_STATION_MODE
) {
1151 struct wilc_sta_wpa_ptk
*key_buf
;
1153 key_buf
= kzalloc(sizeof(*key_buf
) + t_key_len
, GFP_KERNEL
);
1157 ether_addr_copy(key_buf
->mac_addr
, mac_addr
);
1158 key_buf
->key_len
= t_key_len
;
1159 memcpy(&key_buf
->key
[0], ptk
, ptk_key_len
);
1162 memcpy(&key_buf
->key
[ptk_key_len
], rx_mic
,
1163 WILC_RX_MIC_KEY_LEN
);
1166 memcpy(&key_buf
->key
[ptk_key_len
+ WILC_RX_MIC_KEY_LEN
],
1167 tx_mic
, WILC_TX_MIC_KEY_LEN
);
1169 wid
.id
= WID_ADD_PTK
;
1171 wid
.size
= sizeof(*key_buf
) + t_key_len
;
1172 wid
.val
= (s8
*)key_buf
;
1173 result
= wilc_send_config_pkt(vif
, WILC_SET_CFG
, &wid
, 1);
1180 int wilc_add_igtk(struct wilc_vif
*vif
, const u8
*igtk
, u8 igtk_key_len
,
1181 const u8
*pn
, u8 pn_len
, const u8
*mac_addr
, u8 mode
, u8 index
)
1184 u8 t_key_len
= igtk_key_len
;
1186 struct wilc_wpa_igtk
*key_buf
;
1188 key_buf
= kzalloc(sizeof(*key_buf
) + t_key_len
, GFP_KERNEL
);
1192 key_buf
->index
= index
;
1194 memcpy(&key_buf
->pn
[0], pn
, pn_len
);
1195 key_buf
->pn_len
= pn_len
;
1197 memcpy(&key_buf
->key
[0], igtk
, igtk_key_len
);
1198 key_buf
->key_len
= t_key_len
;
1200 wid
.id
= WID_ADD_IGTK
;
1202 wid
.size
= sizeof(*key_buf
) + t_key_len
;
1203 wid
.val
= (s8
*)key_buf
;
1204 result
= wilc_send_config_pkt(vif
, WILC_SET_CFG
, &wid
, 1);
1210 int wilc_add_rx_gtk(struct wilc_vif
*vif
, const u8
*rx_gtk
, u8 gtk_key_len
,
1211 u8 index
, u32 key_rsc_len
, const u8
*key_rsc
,
1212 const u8
*rx_mic
, const u8
*tx_mic
, u8 mode
,
1216 struct wilc_gtk_key
*gtk_key
;
1217 int t_key_len
= gtk_key_len
+ WILC_RX_MIC_KEY_LEN
+ WILC_TX_MIC_KEY_LEN
;
1219 gtk_key
= kzalloc(sizeof(*gtk_key
) + t_key_len
, GFP_KERNEL
);
1223 /* fill bssid value only in station mode */
1224 if (mode
== WILC_STATION_MODE
&&
1225 vif
->hif_drv
->hif_state
== HOST_IF_CONNECTED
)
1226 memcpy(gtk_key
->mac_addr
, vif
->hif_drv
->assoc_bssid
, ETH_ALEN
);
1229 memcpy(gtk_key
->rsc
, key_rsc
, 8);
1230 gtk_key
->index
= index
;
1231 gtk_key
->key_len
= t_key_len
;
1232 memcpy(>k_key
->key
[0], rx_gtk
, gtk_key_len
);
1235 memcpy(>k_key
->key
[gtk_key_len
], rx_mic
, WILC_RX_MIC_KEY_LEN
);
1238 memcpy(>k_key
->key
[gtk_key_len
+ WILC_RX_MIC_KEY_LEN
],
1239 tx_mic
, WILC_TX_MIC_KEY_LEN
);
1241 if (mode
== WILC_AP_MODE
) {
1242 struct wid wid_list
[2];
1244 wid_list
[0].id
= WID_11I_MODE
;
1245 wid_list
[0].type
= WID_CHAR
;
1246 wid_list
[0].size
= sizeof(char);
1247 wid_list
[0].val
= (s8
*)&cipher_mode
;
1249 wid_list
[1].id
= WID_ADD_RX_GTK
;
1250 wid_list
[1].type
= WID_STR
;
1251 wid_list
[1].size
= sizeof(*gtk_key
) + t_key_len
;
1252 wid_list
[1].val
= (u8
*)gtk_key
;
1254 result
= wilc_send_config_pkt(vif
, WILC_SET_CFG
, wid_list
,
1255 ARRAY_SIZE(wid_list
));
1256 } else if (mode
== WILC_STATION_MODE
) {
1259 wid
.id
= WID_ADD_RX_GTK
;
1261 wid
.size
= sizeof(*gtk_key
) + t_key_len
;
1262 wid
.val
= (u8
*)gtk_key
;
1263 result
= wilc_send_config_pkt(vif
, WILC_SET_CFG
, &wid
, 1);
1270 int wilc_set_pmkid_info(struct wilc_vif
*vif
, struct wilc_pmkid_attr
*pmkid
)
1274 wid
.id
= WID_PMKID_INFO
;
1276 wid
.size
= (pmkid
->numpmkid
* sizeof(struct wilc_pmkid
)) + 1;
1277 wid
.val
= (u8
*)pmkid
;
1279 return wilc_send_config_pkt(vif
, WILC_SET_CFG
, &wid
, 1);
1282 int wilc_get_mac_address(struct wilc_vif
*vif
, u8
*mac_addr
)
1287 wid
.id
= WID_MAC_ADDR
;
1289 wid
.size
= ETH_ALEN
;
1292 result
= wilc_send_config_pkt(vif
, WILC_GET_CFG
, &wid
, 1);
1294 netdev_err(vif
->ndev
, "Failed to get mac address\n");
1299 int wilc_set_mac_address(struct wilc_vif
*vif
, const u8
*mac_addr
)
1304 wid
.id
= WID_MAC_ADDR
;
1306 wid
.size
= ETH_ALEN
;
1307 wid
.val
= (u8
*)mac_addr
;
1309 result
= wilc_send_config_pkt(vif
, WILC_SET_CFG
, &wid
, 1);
1311 netdev_err(vif
->ndev
, "Failed to set mac address\n");
1316 int wilc_set_join_req(struct wilc_vif
*vif
, u8
*bssid
, const u8
*ies
,
1320 struct host_if_drv
*hif_drv
= vif
->hif_drv
;
1321 struct wilc_conn_info
*conn_info
= &hif_drv
->conn_info
;
1324 ether_addr_copy(conn_info
->bssid
, bssid
);
1327 conn_info
->req_ies_len
= ies_len
;
1328 conn_info
->req_ies
= kmemdup(ies
, ies_len
, GFP_KERNEL
);
1329 if (!conn_info
->req_ies
)
1333 result
= wilc_send_connect_wid(vif
);
1337 hif_drv
->connect_timer_vif
= vif
;
1338 mod_timer(&hif_drv
->connect_timer
,
1339 jiffies
+ msecs_to_jiffies(WILC_HIF_CONNECT_TIMEOUT_MS
));
1344 kfree(conn_info
->req_ies
);
1349 int wilc_set_mac_chnl_num(struct wilc_vif
*vif
, u8 channel
)
1354 wid
.id
= WID_CURRENT_CHANNEL
;
1355 wid
.type
= WID_CHAR
;
1356 wid
.size
= sizeof(char);
1359 result
= wilc_send_config_pkt(vif
, WILC_SET_CFG
, &wid
, 1);
1361 netdev_err(vif
->ndev
, "Failed to set channel\n");
1366 int wilc_set_operation_mode(struct wilc_vif
*vif
, int index
, u8 mode
,
1371 struct wilc_drv_handler drv
;
1373 wid
.id
= WID_SET_OPERATION_MODE
;
1375 wid
.size
= sizeof(drv
);
1376 wid
.val
= (u8
*)&drv
;
1378 drv
.handler
= cpu_to_le32(index
);
1379 drv
.mode
= (ifc_id
| (mode
<< 1));
1381 result
= wilc_send_config_pkt(vif
, WILC_SET_CFG
, &wid
, 1);
1383 netdev_err(vif
->ndev
, "Failed to set driver handler\n");
1388 s32
wilc_get_inactive_time(struct wilc_vif
*vif
, const u8
*mac
, u32
*out_val
)
1393 wid
.id
= WID_SET_STA_MAC_INACTIVE_TIME
;
1395 wid
.size
= ETH_ALEN
;
1396 wid
.val
= kzalloc(wid
.size
, GFP_KERNEL
);
1400 ether_addr_copy(wid
.val
, mac
);
1401 result
= wilc_send_config_pkt(vif
, WILC_SET_CFG
, &wid
, 1);
1404 netdev_err(vif
->ndev
, "Failed to set inactive mac\n");
1408 wid
.id
= WID_GET_INACTIVE_TIME
;
1410 wid
.val
= (s8
*)out_val
;
1411 wid
.size
= sizeof(u32
);
1412 result
= wilc_send_config_pkt(vif
, WILC_GET_CFG
, &wid
, 1);
1414 netdev_err(vif
->ndev
, "Failed to get inactive time\n");
1419 int wilc_get_rssi(struct wilc_vif
*vif
, s8
*rssi_level
)
1425 netdev_err(vif
->ndev
, "%s: RSSI level is NULL\n", __func__
);
1430 wid
.type
= WID_CHAR
;
1431 wid
.size
= sizeof(char);
1432 wid
.val
= rssi_level
;
1433 result
= wilc_send_config_pkt(vif
, WILC_GET_CFG
, &wid
, 1);
1435 netdev_err(vif
->ndev
, "Failed to get RSSI value\n");
1440 static int wilc_get_stats_async(struct wilc_vif
*vif
, struct rf_info
*stats
)
1443 struct host_if_msg
*msg
;
1445 msg
= wilc_alloc_work(vif
, handle_get_statistics
, false);
1447 return PTR_ERR(msg
);
1449 msg
->body
.data
= (char *)stats
;
1451 result
= wilc_enqueue_work(msg
);
1453 netdev_err(vif
->ndev
, "%s: enqueue work failed\n", __func__
);
1461 int wilc_hif_set_cfg(struct wilc_vif
*vif
, struct cfg_param_attr
*param
)
1463 struct wid wid_list
[4];
1466 if (param
->flag
& WILC_CFG_PARAM_RETRY_SHORT
) {
1467 wid_list
[i
].id
= WID_SHORT_RETRY_LIMIT
;
1468 wid_list
[i
].val
= (s8
*)¶m
->short_retry_limit
;
1469 wid_list
[i
].type
= WID_SHORT
;
1470 wid_list
[i
].size
= sizeof(u16
);
1473 if (param
->flag
& WILC_CFG_PARAM_RETRY_LONG
) {
1474 wid_list
[i
].id
= WID_LONG_RETRY_LIMIT
;
1475 wid_list
[i
].val
= (s8
*)¶m
->long_retry_limit
;
1476 wid_list
[i
].type
= WID_SHORT
;
1477 wid_list
[i
].size
= sizeof(u16
);
1480 if (param
->flag
& WILC_CFG_PARAM_FRAG_THRESHOLD
) {
1481 wid_list
[i
].id
= WID_FRAG_THRESHOLD
;
1482 wid_list
[i
].val
= (s8
*)¶m
->frag_threshold
;
1483 wid_list
[i
].type
= WID_SHORT
;
1484 wid_list
[i
].size
= sizeof(u16
);
1487 if (param
->flag
& WILC_CFG_PARAM_RTS_THRESHOLD
) {
1488 wid_list
[i
].id
= WID_RTS_THRESHOLD
;
1489 wid_list
[i
].val
= (s8
*)¶m
->rts_threshold
;
1490 wid_list
[i
].type
= WID_SHORT
;
1491 wid_list
[i
].size
= sizeof(u16
);
1495 return wilc_send_config_pkt(vif
, WILC_SET_CFG
, wid_list
, i
);
1498 static void get_periodic_rssi(struct timer_list
*t
)
1500 struct wilc_vif
*vif
= from_timer(vif
, t
, periodic_rssi
);
1502 if (!vif
->hif_drv
) {
1503 netdev_err(vif
->ndev
, "%s: hif driver is NULL", __func__
);
1507 if (vif
->hif_drv
->hif_state
== HOST_IF_CONNECTED
)
1508 wilc_get_stats_async(vif
, &vif
->periodic_stat
);
1510 mod_timer(&vif
->periodic_rssi
, jiffies
+ msecs_to_jiffies(5000));
1513 int wilc_init(struct net_device
*dev
, struct host_if_drv
**hif_drv_handler
)
1515 struct host_if_drv
*hif_drv
;
1516 struct wilc_vif
*vif
= netdev_priv(dev
);
1518 hif_drv
= kzalloc(sizeof(*hif_drv
), GFP_KERNEL
);
1522 *hif_drv_handler
= hif_drv
;
1524 vif
->hif_drv
= hif_drv
;
1526 timer_setup(&vif
->periodic_rssi
, get_periodic_rssi
, 0);
1527 mod_timer(&vif
->periodic_rssi
, jiffies
+ msecs_to_jiffies(5000));
1529 timer_setup(&hif_drv
->scan_timer
, timer_scan_cb
, 0);
1530 timer_setup(&hif_drv
->connect_timer
, timer_connect_cb
, 0);
1531 timer_setup(&hif_drv
->remain_on_ch_timer
, listen_timer_cb
, 0);
1533 hif_drv
->hif_state
= HOST_IF_IDLE
;
1535 hif_drv
->p2p_timeout
= 0;
1540 int wilc_deinit(struct wilc_vif
*vif
)
1543 struct host_if_drv
*hif_drv
= vif
->hif_drv
;
1546 netdev_err(vif
->ndev
, "%s: hif driver is NULL", __func__
);
1550 mutex_lock(&vif
->wilc
->deinit_lock
);
1552 timer_shutdown_sync(&hif_drv
->scan_timer
);
1553 timer_shutdown_sync(&hif_drv
->connect_timer
);
1554 del_timer_sync(&vif
->periodic_rssi
);
1555 timer_shutdown_sync(&hif_drv
->remain_on_ch_timer
);
1557 if (hif_drv
->usr_scan_req
.scan_result
) {
1558 hif_drv
->usr_scan_req
.scan_result(SCAN_EVENT_ABORTED
, NULL
,
1559 hif_drv
->usr_scan_req
.priv
);
1560 hif_drv
->usr_scan_req
.scan_result
= NULL
;
1563 hif_drv
->hif_state
= HOST_IF_IDLE
;
1566 vif
->hif_drv
= NULL
;
1567 mutex_unlock(&vif
->wilc
->deinit_lock
);
1571 void wilc_network_info_received(struct wilc
*wilc
, u8
*buffer
, u32 length
)
1573 struct host_if_drv
*hif_drv
;
1574 struct host_if_msg
*msg
;
1575 struct wilc_vif
*vif
;
1580 id
= get_unaligned_le32(&buffer
[length
- 4]);
1581 srcu_idx
= srcu_read_lock(&wilc
->srcu
);
1582 vif
= wilc_get_vif_from_idx(wilc
, id
);
1586 hif_drv
= vif
->hif_drv
;
1588 netdev_err(vif
->ndev
, "driver not init[%p]\n", hif_drv
);
1592 msg
= wilc_alloc_work(vif
, handle_rcvd_ntwrk_info
, false);
1596 msg
->body
.net_info
.frame_len
= get_unaligned_le16(&buffer
[6]) - 1;
1597 msg
->body
.net_info
.rssi
= buffer
[8];
1598 msg
->body
.net_info
.mgmt
= kmemdup(&buffer
[9],
1599 msg
->body
.net_info
.frame_len
,
1601 if (!msg
->body
.net_info
.mgmt
) {
1606 result
= wilc_enqueue_work(msg
);
1608 netdev_err(vif
->ndev
, "%s: enqueue work failed\n", __func__
);
1609 kfree(msg
->body
.net_info
.mgmt
);
1613 srcu_read_unlock(&wilc
->srcu
, srcu_idx
);
1616 void wilc_gnrl_async_info_received(struct wilc
*wilc
, u8
*buffer
, u32 length
)
1618 struct host_if_drv
*hif_drv
;
1619 struct host_if_msg
*msg
;
1620 struct wilc_vif
*vif
;
1625 mutex_lock(&wilc
->deinit_lock
);
1627 id
= get_unaligned_le32(&buffer
[length
- 4]);
1628 srcu_idx
= srcu_read_lock(&wilc
->srcu
);
1629 vif
= wilc_get_vif_from_idx(wilc
, id
);
1633 hif_drv
= vif
->hif_drv
;
1639 if (!hif_drv
->conn_info
.conn_result
) {
1640 netdev_err(vif
->ndev
, "%s: conn_result is NULL\n", __func__
);
1644 msg
= wilc_alloc_work(vif
, handle_rcvd_gnrl_async_info
, false);
1648 msg
->body
.mac_info
.status
= buffer
[7];
1649 result
= wilc_enqueue_work(msg
);
1651 netdev_err(vif
->ndev
, "%s: enqueue work failed\n", __func__
);
1655 srcu_read_unlock(&wilc
->srcu
, srcu_idx
);
1656 mutex_unlock(&wilc
->deinit_lock
);
1659 void wilc_scan_complete_received(struct wilc
*wilc
, u8
*buffer
, u32 length
)
1661 struct host_if_drv
*hif_drv
;
1662 struct wilc_vif
*vif
;
1667 id
= get_unaligned_le32(&buffer
[length
- 4]);
1668 srcu_idx
= srcu_read_lock(&wilc
->srcu
);
1669 vif
= wilc_get_vif_from_idx(wilc
, id
);
1673 hif_drv
= vif
->hif_drv
;
1678 if (hif_drv
->usr_scan_req
.scan_result
) {
1679 struct host_if_msg
*msg
;
1681 msg
= wilc_alloc_work(vif
, handle_scan_complete
, false);
1685 result
= wilc_enqueue_work(msg
);
1687 netdev_err(vif
->ndev
, "%s: enqueue work failed\n",
1693 srcu_read_unlock(&wilc
->srcu
, srcu_idx
);
1696 int wilc_remain_on_channel(struct wilc_vif
*vif
, u64 cookie
, u16 chan
,
1697 void (*expired
)(struct wilc_vif
*, u64
))
1699 struct wilc_remain_ch roc
;
1703 roc
.expired
= expired
;
1705 roc
.cookie
= cookie
;
1706 result
= handle_remain_on_chan(vif
, &roc
);
1708 netdev_err(vif
->ndev
, "%s: failed to set remain on channel\n",
1714 int wilc_listen_state_expired(struct wilc_vif
*vif
, u64 cookie
)
1716 if (!vif
->hif_drv
) {
1717 netdev_err(vif
->ndev
, "%s: hif driver is NULL", __func__
);
1721 del_timer(&vif
->hif_drv
->remain_on_ch_timer
);
1723 return wilc_handle_roc_expired(vif
, cookie
);
1726 void wilc_frame_register(struct wilc_vif
*vif
, u16 frame_type
, bool reg
)
1730 struct wilc_reg_frame reg_frame
;
1732 wid
.id
= WID_REGISTER_FRAME
;
1734 wid
.size
= sizeof(reg_frame
);
1735 wid
.val
= (u8
*)®_frame
;
1737 memset(®_frame
, 0x0, sizeof(reg_frame
));
1742 switch (frame_type
) {
1743 case IEEE80211_STYPE_ACTION
:
1744 reg_frame
.reg_id
= WILC_FW_ACTION_FRM_IDX
;
1747 case IEEE80211_STYPE_PROBE_REQ
:
1748 reg_frame
.reg_id
= WILC_FW_PROBE_REQ_IDX
;
1751 case IEEE80211_STYPE_AUTH
:
1752 reg_frame
.reg_id
= WILC_FW_AUTH_REQ_IDX
;
1758 reg_frame
.frame_type
= cpu_to_le16(frame_type
);
1759 result
= wilc_send_config_pkt(vif
, WILC_SET_CFG
, &wid
, 1);
1761 netdev_err(vif
->ndev
, "Failed to frame register\n");
1764 int wilc_add_beacon(struct wilc_vif
*vif
, u32 interval
, u32 dtim_period
,
1765 struct cfg80211_beacon_data
*params
)
1771 wid
.id
= WID_ADD_BEACON
;
1773 wid
.size
= params
->head_len
+ params
->tail_len
+ 16;
1774 wid
.val
= kzalloc(wid
.size
, GFP_KERNEL
);
1779 put_unaligned_le32(interval
, cur_byte
);
1781 put_unaligned_le32(dtim_period
, cur_byte
);
1783 put_unaligned_le32(params
->head_len
, cur_byte
);
1786 if (params
->head_len
> 0)
1787 memcpy(cur_byte
, params
->head
, params
->head_len
);
1788 cur_byte
+= params
->head_len
;
1790 put_unaligned_le32(params
->tail_len
, cur_byte
);
1793 if (params
->tail_len
> 0)
1794 memcpy(cur_byte
, params
->tail
, params
->tail_len
);
1796 result
= wilc_send_config_pkt(vif
, WILC_SET_CFG
, &wid
, 1);
1798 netdev_err(vif
->ndev
, "Failed to send add beacon\n");
1805 int wilc_del_beacon(struct wilc_vif
*vif
)
1811 wid
.id
= WID_DEL_BEACON
;
1812 wid
.type
= WID_CHAR
;
1813 wid
.size
= sizeof(char);
1814 wid
.val
= &del_beacon
;
1816 result
= wilc_send_config_pkt(vif
, WILC_SET_CFG
, &wid
, 1);
1818 netdev_err(vif
->ndev
, "Failed to send delete beacon\n");
1823 int wilc_add_station(struct wilc_vif
*vif
, const u8
*mac
,
1824 struct station_parameters
*params
)
1830 wid
.id
= WID_ADD_STA
;
1832 wid
.size
= WILC_ADD_STA_LENGTH
+
1833 params
->link_sta_params
.supported_rates_len
;
1834 wid
.val
= kmalloc(wid
.size
, GFP_KERNEL
);
1839 wilc_hif_pack_sta_param(cur_byte
, mac
, params
);
1841 result
= wilc_send_config_pkt(vif
, WILC_SET_CFG
, &wid
, 1);
1843 netdev_err(vif
->ndev
, "Failed to send add station\n");
1850 int wilc_del_station(struct wilc_vif
*vif
, const u8
*mac_addr
)
1855 wid
.id
= WID_REMOVE_STA
;
1857 wid
.size
= ETH_ALEN
;
1858 wid
.val
= kzalloc(wid
.size
, GFP_KERNEL
);
1863 eth_broadcast_addr(wid
.val
);
1865 ether_addr_copy(wid
.val
, mac_addr
);
1867 result
= wilc_send_config_pkt(vif
, WILC_SET_CFG
, &wid
, 1);
1869 netdev_err(vif
->ndev
, "Failed to del station\n");
1876 int wilc_del_allstation(struct wilc_vif
*vif
, u8 mac_addr
[][ETH_ALEN
])
1882 struct wilc_del_all_sta del_sta
;
1884 memset(&del_sta
, 0x0, sizeof(del_sta
));
1885 for (i
= 0; i
< WILC_MAX_NUM_STA
; i
++) {
1886 if (!is_zero_ether_addr(mac_addr
[i
])) {
1888 ether_addr_copy(del_sta
.mac
[i
], mac_addr
[i
]);
1895 del_sta
.assoc_sta
= assoc_sta
;
1897 wid
.id
= WID_DEL_ALL_STA
;
1899 wid
.size
= (assoc_sta
* ETH_ALEN
) + 1;
1900 wid
.val
= (u8
*)&del_sta
;
1902 result
= wilc_send_config_pkt(vif
, WILC_SET_CFG
, &wid
, 1);
1904 netdev_err(vif
->ndev
, "Failed to send delete all station\n");
1909 int wilc_edit_station(struct wilc_vif
*vif
, const u8
*mac
,
1910 struct station_parameters
*params
)
1916 wid
.id
= WID_EDIT_STA
;
1918 wid
.size
= WILC_ADD_STA_LENGTH
+
1919 params
->link_sta_params
.supported_rates_len
;
1920 wid
.val
= kmalloc(wid
.size
, GFP_KERNEL
);
1925 wilc_hif_pack_sta_param(cur_byte
, mac
, params
);
1927 result
= wilc_send_config_pkt(vif
, WILC_SET_CFG
, &wid
, 1);
1929 netdev_err(vif
->ndev
, "Failed to send edit station\n");
1935 int wilc_set_power_mgmt(struct wilc_vif
*vif
, bool enabled
, u32 timeout
)
1937 struct wilc
*wilc
= vif
->wilc
;
1943 power_mode
= WILC_FW_MIN_FAST_PS
;
1945 power_mode
= WILC_FW_NO_POWERSAVE
;
1947 wid
.id
= WID_POWER_MANAGEMENT
;
1948 wid
.val
= &power_mode
;
1949 wid
.size
= sizeof(char);
1950 result
= wilc_send_config_pkt(vif
, WILC_SET_CFG
, &wid
, 1);
1952 netdev_err(vif
->ndev
, "Failed to send power management\n");
1954 wilc
->power_save_mode
= enabled
;
1959 int wilc_setup_multicast_filter(struct wilc_vif
*vif
, u32 enabled
, u32 count
,
1963 struct host_if_msg
*msg
;
1965 msg
= wilc_alloc_work(vif
, handle_set_mcast_filter
, false);
1967 return PTR_ERR(msg
);
1969 msg
->body
.mc_info
.enabled
= enabled
;
1970 msg
->body
.mc_info
.cnt
= count
;
1971 msg
->body
.mc_info
.mc_list
= mc_list
;
1973 result
= wilc_enqueue_work(msg
);
1975 netdev_err(vif
->ndev
, "%s: enqueue work failed\n", __func__
);
1981 int wilc_set_tx_power(struct wilc_vif
*vif
, u8 tx_power
)
1985 wid
.id
= WID_TX_POWER
;
1986 wid
.type
= WID_CHAR
;
1987 wid
.val
= &tx_power
;
1988 wid
.size
= sizeof(char);
1990 return wilc_send_config_pkt(vif
, WILC_SET_CFG
, &wid
, 1);
1993 int wilc_get_tx_power(struct wilc_vif
*vif
, u8
*tx_power
)
1997 wid
.id
= WID_TX_POWER
;
1998 wid
.type
= WID_CHAR
;
2000 wid
.size
= sizeof(char);
2002 return wilc_send_config_pkt(vif
, WILC_GET_CFG
, &wid
, 1);
2005 int wilc_set_default_mgmt_key_index(struct wilc_vif
*vif
, u8 index
)
2010 wid
.id
= WID_DEFAULT_MGMT_KEY_ID
;
2011 wid
.type
= WID_CHAR
;
2012 wid
.size
= sizeof(char);
2014 result
= wilc_send_config_pkt(vif
, WILC_SET_CFG
, &wid
, 1);
2016 netdev_err(vif
->ndev
,
2017 "Failed to send default mgmt key index\n");