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 struct wilc_rcvd_mac_info
{
18 struct wilc_set_multicast
{
24 struct wilc_del_all_sta
{
26 u8 mac
[WILC_MAX_NUM_STA
][ETH_ALEN
];
29 union wilc_message_body
{
30 struct wilc_rcvd_net_info net_info
;
31 struct wilc_rcvd_mac_info mac_info
;
32 struct wilc_set_multicast mc_info
;
33 struct wilc_remain_ch remain_on_ch
;
38 union wilc_message_body body
;
40 struct work_struct work
;
41 void (*fn
)(struct work_struct
*ws
);
42 struct completion work_comp
;
46 /* 'msg' should be free by the caller for syc */
47 static struct host_if_msg
*
48 wilc_alloc_work(struct wilc_vif
*vif
, void (*work_fun
)(struct work_struct
*),
51 struct host_if_msg
*msg
;
54 return ERR_PTR(-EINVAL
);
56 msg
= kzalloc(sizeof(*msg
), GFP_ATOMIC
);
58 return ERR_PTR(-ENOMEM
);
61 msg
->is_sync
= is_sync
;
63 init_completion(&msg
->work_comp
);
68 static int wilc_enqueue_work(struct host_if_msg
*msg
)
70 INIT_WORK(&msg
->work
, msg
->fn
);
72 if (!msg
->vif
|| !msg
->vif
->wilc
|| !msg
->vif
->wilc
->hif_workqueue
)
75 if (!queue_work(msg
->vif
->wilc
->hif_workqueue
, &msg
->work
))
81 /* The idx starts from 0 to (NUM_CONCURRENT_IFC - 1), but 0 index used as
82 * special purpose in wilc device, so we add 1 to the index to starts from 1.
83 * As a result, the returned index will be 1 to NUM_CONCURRENT_IFC.
85 int wilc_get_vif_idx(struct wilc_vif
*vif
)
90 /* We need to minus 1 from idx which is from wilc device to get real index
91 * of wilc->vif[], because we add 1 when pass to wilc device in the function
93 * As a result, the index should be between 0 and (NUM_CONCURRENT_IFC - 1).
95 static struct wilc_vif
*wilc_get_vif_from_idx(struct wilc
*wilc
, int idx
)
100 if (index
< 0 || index
>= WILC_NUM_CONCURRENT_IFC
)
103 list_for_each_entry_rcu(vif
, &wilc
->vif_list
, list
) {
104 if (vif
->idx
== index
)
111 static int handle_scan_done(struct wilc_vif
*vif
, enum scan_event evt
)
114 u8 abort_running_scan
;
116 struct host_if_drv
*hif_drv
= vif
->hif_drv
;
117 struct wilc_user_scan_req
*scan_req
;
119 if (evt
== SCAN_EVENT_ABORTED
) {
120 abort_running_scan
= 1;
121 wid
.id
= WID_ABORT_RUNNING_SCAN
;
123 wid
.val
= (s8
*)&abort_running_scan
;
124 wid
.size
= sizeof(char);
126 result
= wilc_send_config_pkt(vif
, WILC_SET_CFG
, &wid
, 1);
128 netdev_err(vif
->ndev
, "Failed to set abort running\n");
134 netdev_err(vif
->ndev
, "%s: hif driver is NULL\n", __func__
);
138 scan_req
= &hif_drv
->usr_scan_req
;
139 if (scan_req
->scan_result
) {
140 scan_req
->scan_result(evt
, NULL
, scan_req
->arg
);
141 scan_req
->scan_result
= NULL
;
147 int wilc_scan(struct wilc_vif
*vif
, u8 scan_source
, u8 scan_type
,
148 u8
*ch_freq_list
, u8 ch_list_len
,
149 void (*scan_result_fn
)(enum scan_event
,
150 struct wilc_rcvd_net_info
*, void *),
151 void *user_arg
, struct cfg80211_scan_request
*request
)
154 struct wid wid_list
[5];
159 u8
*search_ssid_vals
= NULL
;
160 struct host_if_drv
*hif_drv
= vif
->hif_drv
;
162 if (hif_drv
->hif_state
>= HOST_IF_SCANNING
&&
163 hif_drv
->hif_state
< HOST_IF_CONNECTED
) {
164 netdev_err(vif
->ndev
, "Already scan\n");
169 if (vif
->connecting
) {
170 netdev_err(vif
->ndev
, "Don't do obss scan\n");
175 hif_drv
->usr_scan_req
.ch_cnt
= 0;
177 if (request
->n_ssids
) {
178 for (i
= 0; i
< request
->n_ssids
; i
++)
179 valuesize
+= ((request
->ssids
[i
].ssid_len
) + 1);
180 search_ssid_vals
= kmalloc(valuesize
+ 1, GFP_KERNEL
);
181 if (search_ssid_vals
) {
182 wid_list
[index
].id
= WID_SSID_PROBE_REQ
;
183 wid_list
[index
].type
= WID_STR
;
184 wid_list
[index
].val
= search_ssid_vals
;
185 buffer
= wid_list
[index
].val
;
187 *buffer
++ = request
->n_ssids
;
189 for (i
= 0; i
< request
->n_ssids
; i
++) {
190 *buffer
++ = request
->ssids
[i
].ssid_len
;
191 memcpy(buffer
, request
->ssids
[i
].ssid
,
192 request
->ssids
[i
].ssid_len
);
193 buffer
+= request
->ssids
[i
].ssid_len
;
195 wid_list
[index
].size
= (s32
)(valuesize
+ 1);
200 wid_list
[index
].id
= WID_INFO_ELEMENT_PROBE
;
201 wid_list
[index
].type
= WID_BIN_DATA
;
202 wid_list
[index
].val
= (s8
*)request
->ie
;
203 wid_list
[index
].size
= request
->ie_len
;
206 wid_list
[index
].id
= WID_SCAN_TYPE
;
207 wid_list
[index
].type
= WID_CHAR
;
208 wid_list
[index
].size
= sizeof(char);
209 wid_list
[index
].val
= (s8
*)&scan_type
;
212 if (scan_type
== WILC_FW_PASSIVE_SCAN
&& request
->duration
) {
213 wid_list
[index
].id
= WID_PASSIVE_SCAN_TIME
;
214 wid_list
[index
].type
= WID_SHORT
;
215 wid_list
[index
].size
= sizeof(u16
);
216 wid_list
[index
].val
= (s8
*)&request
->duration
;
219 scan_timeout
= (request
->duration
* ch_list_len
) + 500;
221 scan_timeout
= WILC_HIF_SCAN_TIMEOUT_MS
;
224 wid_list
[index
].id
= WID_SCAN_CHANNEL_LIST
;
225 wid_list
[index
].type
= WID_BIN_DATA
;
227 if (ch_freq_list
&& ch_list_len
> 0) {
228 for (i
= 0; i
< ch_list_len
; i
++) {
229 if (ch_freq_list
[i
] > 0)
230 ch_freq_list
[i
] -= 1;
234 wid_list
[index
].val
= ch_freq_list
;
235 wid_list
[index
].size
= ch_list_len
;
238 wid_list
[index
].id
= WID_START_SCAN_REQ
;
239 wid_list
[index
].type
= WID_CHAR
;
240 wid_list
[index
].size
= sizeof(char);
241 wid_list
[index
].val
= (s8
*)&scan_source
;
244 hif_drv
->usr_scan_req
.scan_result
= scan_result_fn
;
245 hif_drv
->usr_scan_req
.arg
= user_arg
;
247 result
= wilc_send_config_pkt(vif
, WILC_SET_CFG
, wid_list
, index
);
249 netdev_err(vif
->ndev
, "Failed to send scan parameters\n");
253 hif_drv
->scan_timer_vif
= vif
;
254 mod_timer(&hif_drv
->scan_timer
,
255 jiffies
+ msecs_to_jiffies(scan_timeout
));
259 kfree(search_ssid_vals
);
264 static int wilc_send_connect_wid(struct wilc_vif
*vif
)
267 struct wid wid_list
[4];
269 struct host_if_drv
*hif_drv
= vif
->hif_drv
;
270 struct wilc_conn_info
*conn_attr
= &hif_drv
->conn_info
;
271 struct wilc_join_bss_param
*bss_param
= conn_attr
->param
;
273 wid_list
[wid_cnt
].id
= WID_INFO_ELEMENT_ASSOCIATE
;
274 wid_list
[wid_cnt
].type
= WID_BIN_DATA
;
275 wid_list
[wid_cnt
].val
= conn_attr
->req_ies
;
276 wid_list
[wid_cnt
].size
= conn_attr
->req_ies_len
;
279 wid_list
[wid_cnt
].id
= WID_11I_MODE
;
280 wid_list
[wid_cnt
].type
= WID_CHAR
;
281 wid_list
[wid_cnt
].size
= sizeof(char);
282 wid_list
[wid_cnt
].val
= (s8
*)&conn_attr
->security
;
285 wid_list
[wid_cnt
].id
= WID_AUTH_TYPE
;
286 wid_list
[wid_cnt
].type
= WID_CHAR
;
287 wid_list
[wid_cnt
].size
= sizeof(char);
288 wid_list
[wid_cnt
].val
= (s8
*)&conn_attr
->auth_type
;
291 wid_list
[wid_cnt
].id
= WID_JOIN_REQ_EXTENDED
;
292 wid_list
[wid_cnt
].type
= WID_STR
;
293 wid_list
[wid_cnt
].size
= sizeof(*bss_param
);
294 wid_list
[wid_cnt
].val
= (u8
*)bss_param
;
297 result
= wilc_send_config_pkt(vif
, WILC_SET_CFG
, wid_list
, wid_cnt
);
299 netdev_err(vif
->ndev
, "failed to send config packet\n");
302 hif_drv
->hif_state
= HOST_IF_WAITING_CONN_RESP
;
309 kfree(conn_attr
->req_ies
);
310 conn_attr
->req_ies
= NULL
;
315 static void handle_connect_timeout(struct work_struct
*work
)
317 struct host_if_msg
*msg
= container_of(work
, struct host_if_msg
, work
);
318 struct wilc_vif
*vif
= msg
->vif
;
321 u16 dummy_reason_code
= 0;
322 struct host_if_drv
*hif_drv
= vif
->hif_drv
;
325 netdev_err(vif
->ndev
, "%s: hif driver is NULL\n", __func__
);
329 hif_drv
->hif_state
= HOST_IF_IDLE
;
331 if (hif_drv
->conn_info
.conn_result
) {
332 hif_drv
->conn_info
.conn_result(CONN_DISCONN_EVENT_CONN_RESP
,
333 WILC_MAC_STATUS_DISCONNECTED
,
334 hif_drv
->conn_info
.arg
);
337 netdev_err(vif
->ndev
, "%s: conn_result is NULL\n", __func__
);
340 wid
.id
= WID_DISCONNECT
;
342 wid
.val
= (s8
*)&dummy_reason_code
;
343 wid
.size
= sizeof(char);
345 result
= wilc_send_config_pkt(vif
, WILC_SET_CFG
, &wid
, 1);
347 netdev_err(vif
->ndev
, "Failed to send disconnect\n");
349 hif_drv
->conn_info
.req_ies_len
= 0;
350 kfree(hif_drv
->conn_info
.req_ies
);
351 hif_drv
->conn_info
.req_ies
= NULL
;
357 void *wilc_parse_join_bss_param(struct cfg80211_bss
*bss
,
358 struct cfg80211_crypto_settings
*crypto
)
360 struct wilc_join_bss_param
*param
;
361 struct ieee80211_p2p_noa_attr noa_attr
;
363 const u8
*tim_elm
, *ssid_elm
, *rates_ie
, *supp_rates_ie
;
364 const u8
*ht_ie
, *wpa_ie
, *wmm_ie
, *rsn_ie
;
366 const struct cfg80211_bss_ies
*ies
= rcu_dereference(bss
->ies
);
368 param
= kzalloc(sizeof(*param
), GFP_KERNEL
);
372 param
->beacon_period
= cpu_to_le16(bss
->beacon_interval
);
373 param
->cap_info
= cpu_to_le16(bss
->capability
);
374 param
->bss_type
= WILC_FW_BSS_TYPE_INFRA
;
375 param
->ch
= ieee80211_frequency_to_channel(bss
->channel
->center_freq
);
376 ether_addr_copy(param
->bssid
, bss
->bssid
);
378 ssid_elm
= cfg80211_find_ie(WLAN_EID_SSID
, ies
->data
, ies
->len
);
380 if (ssid_elm
[1] <= IEEE80211_MAX_SSID_LEN
)
381 memcpy(param
->ssid
, ssid_elm
+ 2, ssid_elm
[1]);
384 tim_elm
= cfg80211_find_ie(WLAN_EID_TIM
, ies
->data
, ies
->len
);
385 if (tim_elm
&& tim_elm
[1] >= 2)
386 param
->dtim_period
= tim_elm
[3];
388 memset(param
->p_suites
, 0xFF, 3);
389 memset(param
->akm_suites
, 0xFF, 3);
391 rates_ie
= cfg80211_find_ie(WLAN_EID_SUPP_RATES
, ies
->data
, ies
->len
);
393 rates_len
= rates_ie
[1];
394 if (rates_len
> WILC_MAX_RATES_SUPPORTED
)
395 rates_len
= WILC_MAX_RATES_SUPPORTED
;
396 param
->supp_rates
[0] = rates_len
;
397 memcpy(¶m
->supp_rates
[1], rates_ie
+ 2, rates_len
);
400 if (rates_len
< WILC_MAX_RATES_SUPPORTED
) {
401 supp_rates_ie
= cfg80211_find_ie(WLAN_EID_EXT_SUPP_RATES
,
402 ies
->data
, ies
->len
);
404 u8 ext_rates
= supp_rates_ie
[1];
406 if (ext_rates
> (WILC_MAX_RATES_SUPPORTED
- rates_len
))
407 param
->supp_rates
[0] = WILC_MAX_RATES_SUPPORTED
;
409 param
->supp_rates
[0] += ext_rates
;
411 memcpy(¶m
->supp_rates
[rates_len
+ 1],
413 (param
->supp_rates
[0] - rates_len
));
417 ht_ie
= cfg80211_find_ie(WLAN_EID_HT_CAPABILITY
, ies
->data
, ies
->len
);
419 param
->ht_capable
= true;
421 ret
= cfg80211_get_p2p_attr(ies
->data
, ies
->len
,
422 IEEE80211_P2P_ATTR_ABSENCE_NOTICE
,
423 (u8
*)&noa_attr
, sizeof(noa_attr
));
425 param
->tsf_lo
= cpu_to_le32(ies
->tsf
);
426 param
->noa_enabled
= 1;
427 param
->idx
= noa_attr
.index
;
428 if (noa_attr
.oppps_ctwindow
& IEEE80211_P2P_OPPPS_ENABLE_BIT
) {
429 param
->opp_enabled
= 1;
430 param
->opp_en
.ct_window
= noa_attr
.oppps_ctwindow
;
431 param
->opp_en
.cnt
= noa_attr
.desc
[0].count
;
432 param
->opp_en
.duration
= noa_attr
.desc
[0].duration
;
433 param
->opp_en
.interval
= noa_attr
.desc
[0].interval
;
434 param
->opp_en
.start_time
= noa_attr
.desc
[0].start_time
;
436 param
->opp_enabled
= 0;
437 param
->opp_dis
.cnt
= noa_attr
.desc
[0].count
;
438 param
->opp_dis
.duration
= noa_attr
.desc
[0].duration
;
439 param
->opp_dis
.interval
= noa_attr
.desc
[0].interval
;
440 param
->opp_dis
.start_time
= noa_attr
.desc
[0].start_time
;
443 wmm_ie
= cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT
,
444 WLAN_OUI_TYPE_MICROSOFT_WMM
,
445 ies
->data
, ies
->len
);
447 struct ieee80211_wmm_param_ie
*ie
;
449 ie
= (struct ieee80211_wmm_param_ie
*)wmm_ie
;
450 if ((ie
->oui_subtype
== 0 || ie
->oui_subtype
== 1) &&
452 param
->wmm_cap
= true;
453 if (ie
->qos_info
& BIT(7))
454 param
->uapsd_cap
= true;
458 wpa_ie
= cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT
,
459 WLAN_OUI_TYPE_MICROSOFT_WPA
,
460 ies
->data
, ies
->len
);
462 param
->mode_802_11i
= 1;
463 param
->rsn_found
= true;
466 rsn_ie
= cfg80211_find_ie(WLAN_EID_RSN
, ies
->data
, ies
->len
);
470 param
->mode_802_11i
= 2;
471 param
->rsn_found
= true;
472 /* extract RSN capabilities */
473 offset
+= (rsn_ie
[offset
] * 4) + 2;
474 offset
+= (rsn_ie
[offset
] * 4) + 2;
475 memcpy(param
->rsn_cap
, &rsn_ie
[offset
], 2);
478 if (param
->rsn_found
) {
481 param
->rsn_grp_policy
= crypto
->cipher_group
& 0xFF;
482 for (i
= 0; i
< crypto
->n_ciphers_pairwise
&& i
< 3; i
++)
483 param
->p_suites
[i
] = crypto
->ciphers_pairwise
[i
] & 0xFF;
485 for (i
= 0; i
< crypto
->n_akm_suites
&& i
< 3; i
++)
486 param
->akm_suites
[i
] = crypto
->akm_suites
[i
] & 0xFF;
489 return (void *)param
;
492 static void handle_rcvd_ntwrk_info(struct work_struct
*work
)
494 struct host_if_msg
*msg
= container_of(work
, struct host_if_msg
, work
);
495 struct wilc_rcvd_net_info
*rcvd_info
= &msg
->body
.net_info
;
496 struct wilc_user_scan_req
*scan_req
= &msg
->vif
->hif_drv
->usr_scan_req
;
502 if (ieee80211_is_probe_resp(rcvd_info
->mgmt
->frame_control
))
503 offset
= offsetof(struct ieee80211_mgmt
, u
.probe_resp
.variable
);
504 else if (ieee80211_is_beacon(rcvd_info
->mgmt
->frame_control
))
505 offset
= offsetof(struct ieee80211_mgmt
, u
.beacon
.variable
);
509 ies
= rcvd_info
->mgmt
->u
.beacon
.variable
;
510 ies_len
= rcvd_info
->frame_len
- offset
;
514 ch_elm
= cfg80211_find_ie(WLAN_EID_DS_PARAMS
, ies
, ies_len
);
515 if (ch_elm
&& ch_elm
[1] > 0)
516 rcvd_info
->ch
= ch_elm
[2];
518 if (scan_req
->scan_result
)
519 scan_req
->scan_result(SCAN_EVENT_NETWORK_FOUND
, rcvd_info
,
523 kfree(rcvd_info
->mgmt
);
527 static void host_int_get_assoc_res_info(struct wilc_vif
*vif
,
529 u32 max_assoc_resp_info_len
,
530 u32
*rcvd_assoc_resp_info_len
)
535 wid
.id
= WID_ASSOC_RES_INFO
;
537 wid
.val
= assoc_resp_info
;
538 wid
.size
= max_assoc_resp_info_len
;
540 result
= wilc_send_config_pkt(vif
, WILC_GET_CFG
, &wid
, 1);
542 *rcvd_assoc_resp_info_len
= 0;
543 netdev_err(vif
->ndev
, "Failed to send association response\n");
547 *rcvd_assoc_resp_info_len
= wid
.size
;
550 static s32
wilc_parse_assoc_resp_info(u8
*buffer
, u32 buffer_len
,
551 struct wilc_conn_info
*ret_conn_info
)
555 struct wilc_assoc_resp
*res
= (struct wilc_assoc_resp
*)buffer
;
557 ret_conn_info
->status
= le16_to_cpu(res
->status_code
);
558 if (ret_conn_info
->status
== WLAN_STATUS_SUCCESS
) {
559 ies
= &buffer
[sizeof(*res
)];
560 ies_len
= buffer_len
- sizeof(*res
);
562 ret_conn_info
->resp_ies
= kmemdup(ies
, ies_len
, GFP_KERNEL
);
563 if (!ret_conn_info
->resp_ies
)
566 ret_conn_info
->resp_ies_len
= ies_len
;
572 static inline void host_int_parse_assoc_resp_info(struct wilc_vif
*vif
,
575 struct host_if_drv
*hif_drv
= vif
->hif_drv
;
576 struct wilc_conn_info
*conn_info
= &hif_drv
->conn_info
;
578 if (mac_status
== WILC_MAC_STATUS_CONNECTED
) {
579 u32 assoc_resp_info_len
;
581 memset(hif_drv
->assoc_resp
, 0, WILC_MAX_ASSOC_RESP_FRAME_SIZE
);
583 host_int_get_assoc_res_info(vif
, hif_drv
->assoc_resp
,
584 WILC_MAX_ASSOC_RESP_FRAME_SIZE
,
585 &assoc_resp_info_len
);
587 if (assoc_resp_info_len
!= 0) {
590 err
= wilc_parse_assoc_resp_info(hif_drv
->assoc_resp
,
594 netdev_err(vif
->ndev
,
595 "wilc_parse_assoc_resp_info() returned error %d\n",
600 del_timer(&hif_drv
->connect_timer
);
601 conn_info
->conn_result(CONN_DISCONN_EVENT_CONN_RESP
, mac_status
,
602 hif_drv
->conn_info
.arg
);
604 if (mac_status
== WILC_MAC_STATUS_CONNECTED
&&
605 conn_info
->status
== WLAN_STATUS_SUCCESS
) {
606 ether_addr_copy(hif_drv
->assoc_bssid
, conn_info
->bssid
);
607 hif_drv
->hif_state
= HOST_IF_CONNECTED
;
609 hif_drv
->hif_state
= HOST_IF_IDLE
;
612 kfree(conn_info
->resp_ies
);
613 conn_info
->resp_ies
= NULL
;
614 conn_info
->resp_ies_len
= 0;
616 kfree(conn_info
->req_ies
);
617 conn_info
->req_ies
= NULL
;
618 conn_info
->req_ies_len
= 0;
621 static inline void host_int_handle_disconnect(struct wilc_vif
*vif
)
623 struct host_if_drv
*hif_drv
= vif
->hif_drv
;
625 if (hif_drv
->usr_scan_req
.scan_result
) {
626 del_timer(&hif_drv
->scan_timer
);
627 handle_scan_done(vif
, SCAN_EVENT_ABORTED
);
630 if (hif_drv
->conn_info
.conn_result
)
631 hif_drv
->conn_info
.conn_result(CONN_DISCONN_EVENT_DISCONN_NOTIF
,
632 0, hif_drv
->conn_info
.arg
);
634 netdev_err(vif
->ndev
, "%s: conn_result is NULL\n", __func__
);
636 eth_zero_addr(hif_drv
->assoc_bssid
);
638 hif_drv
->conn_info
.req_ies_len
= 0;
639 kfree(hif_drv
->conn_info
.req_ies
);
640 hif_drv
->conn_info
.req_ies
= NULL
;
641 hif_drv
->hif_state
= HOST_IF_IDLE
;
644 static void handle_rcvd_gnrl_async_info(struct work_struct
*work
)
646 struct host_if_msg
*msg
= container_of(work
, struct host_if_msg
, work
);
647 struct wilc_vif
*vif
= msg
->vif
;
648 struct wilc_rcvd_mac_info
*mac_info
= &msg
->body
.mac_info
;
649 struct host_if_drv
*hif_drv
= vif
->hif_drv
;
652 netdev_err(vif
->ndev
, "%s: hif driver is NULL\n", __func__
);
656 if (!hif_drv
->conn_info
.conn_result
) {
657 netdev_err(vif
->ndev
, "%s: conn_result is NULL\n", __func__
);
661 if (hif_drv
->hif_state
== HOST_IF_WAITING_CONN_RESP
) {
662 host_int_parse_assoc_resp_info(vif
, mac_info
->status
);
663 } else if (mac_info
->status
== WILC_MAC_STATUS_DISCONNECTED
) {
664 if (hif_drv
->hif_state
== HOST_IF_CONNECTED
) {
665 host_int_handle_disconnect(vif
);
666 } else if (hif_drv
->usr_scan_req
.scan_result
) {
667 del_timer(&hif_drv
->scan_timer
);
668 handle_scan_done(vif
, SCAN_EVENT_ABORTED
);
676 int wilc_disconnect(struct wilc_vif
*vif
)
679 struct host_if_drv
*hif_drv
= vif
->hif_drv
;
680 struct wilc_user_scan_req
*scan_req
;
681 struct wilc_conn_info
*conn_info
;
683 u16 dummy_reason_code
= 0;
685 wid
.id
= WID_DISCONNECT
;
687 wid
.val
= (s8
*)&dummy_reason_code
;
688 wid
.size
= sizeof(char);
690 result
= wilc_send_config_pkt(vif
, WILC_SET_CFG
, &wid
, 1);
692 netdev_err(vif
->ndev
, "Failed to send disconnect\n");
696 scan_req
= &hif_drv
->usr_scan_req
;
697 conn_info
= &hif_drv
->conn_info
;
699 if (scan_req
->scan_result
) {
700 del_timer(&hif_drv
->scan_timer
);
701 scan_req
->scan_result(SCAN_EVENT_ABORTED
, NULL
, scan_req
->arg
);
702 scan_req
->scan_result
= NULL
;
705 if (conn_info
->conn_result
) {
706 if (hif_drv
->hif_state
== HOST_IF_WAITING_CONN_RESP
)
707 del_timer(&hif_drv
->connect_timer
);
709 conn_info
->conn_result(CONN_DISCONN_EVENT_DISCONN_NOTIF
, 0,
712 netdev_err(vif
->ndev
, "%s: conn_result is NULL\n", __func__
);
715 hif_drv
->hif_state
= HOST_IF_IDLE
;
717 eth_zero_addr(hif_drv
->assoc_bssid
);
719 conn_info
->req_ies_len
= 0;
720 kfree(conn_info
->req_ies
);
721 conn_info
->req_ies
= NULL
;
726 int wilc_get_statistics(struct wilc_vif
*vif
, struct rf_info
*stats
)
728 struct wid wid_list
[5];
729 u32 wid_cnt
= 0, result
;
731 wid_list
[wid_cnt
].id
= WID_LINKSPEED
;
732 wid_list
[wid_cnt
].type
= WID_CHAR
;
733 wid_list
[wid_cnt
].size
= sizeof(char);
734 wid_list
[wid_cnt
].val
= (s8
*)&stats
->link_speed
;
737 wid_list
[wid_cnt
].id
= WID_RSSI
;
738 wid_list
[wid_cnt
].type
= WID_CHAR
;
739 wid_list
[wid_cnt
].size
= sizeof(char);
740 wid_list
[wid_cnt
].val
= (s8
*)&stats
->rssi
;
743 wid_list
[wid_cnt
].id
= WID_SUCCESS_FRAME_COUNT
;
744 wid_list
[wid_cnt
].type
= WID_INT
;
745 wid_list
[wid_cnt
].size
= sizeof(u32
);
746 wid_list
[wid_cnt
].val
= (s8
*)&stats
->tx_cnt
;
749 wid_list
[wid_cnt
].id
= WID_RECEIVED_FRAGMENT_COUNT
;
750 wid_list
[wid_cnt
].type
= WID_INT
;
751 wid_list
[wid_cnt
].size
= sizeof(u32
);
752 wid_list
[wid_cnt
].val
= (s8
*)&stats
->rx_cnt
;
755 wid_list
[wid_cnt
].id
= WID_FAILED_COUNT
;
756 wid_list
[wid_cnt
].type
= WID_INT
;
757 wid_list
[wid_cnt
].size
= sizeof(u32
);
758 wid_list
[wid_cnt
].val
= (s8
*)&stats
->tx_fail_cnt
;
761 result
= wilc_send_config_pkt(vif
, WILC_GET_CFG
, wid_list
, wid_cnt
);
763 netdev_err(vif
->ndev
, "Failed to send scan parameters\n");
767 if (stats
->link_speed
> TCP_ACK_FILTER_LINK_SPEED_THRESH
&&
768 stats
->link_speed
!= DEFAULT_LINK_SPEED
)
769 wilc_enable_tcp_ack_filter(vif
, true);
770 else if (stats
->link_speed
!= DEFAULT_LINK_SPEED
)
771 wilc_enable_tcp_ack_filter(vif
, false);
776 static void handle_get_statistics(struct work_struct
*work
)
778 struct host_if_msg
*msg
= container_of(work
, struct host_if_msg
, work
);
779 struct wilc_vif
*vif
= msg
->vif
;
780 struct rf_info
*stats
= (struct rf_info
*)msg
->body
.data
;
782 wilc_get_statistics(vif
, stats
);
787 static void wilc_hif_pack_sta_param(u8
*cur_byte
, const u8
*mac
,
788 struct station_parameters
*params
)
790 ether_addr_copy(cur_byte
, mac
);
791 cur_byte
+= ETH_ALEN
;
793 put_unaligned_le16(params
->aid
, cur_byte
);
796 *cur_byte
++ = params
->supported_rates_len
;
797 if (params
->supported_rates_len
> 0)
798 memcpy(cur_byte
, params
->supported_rates
,
799 params
->supported_rates_len
);
800 cur_byte
+= params
->supported_rates_len
;
802 if (params
->ht_capa
) {
804 memcpy(cur_byte
, params
->ht_capa
,
805 sizeof(struct ieee80211_ht_cap
));
809 cur_byte
+= sizeof(struct ieee80211_ht_cap
);
811 put_unaligned_le16(params
->sta_flags_mask
, cur_byte
);
813 put_unaligned_le16(params
->sta_flags_set
, cur_byte
);
816 static int handle_remain_on_chan(struct wilc_vif
*vif
,
817 struct wilc_remain_ch
*hif_remain_ch
)
820 u8 remain_on_chan_flag
;
822 struct host_if_drv
*hif_drv
= vif
->hif_drv
;
824 if (hif_drv
->usr_scan_req
.scan_result
)
827 if (hif_drv
->hif_state
== HOST_IF_WAITING_CONN_RESP
)
833 remain_on_chan_flag
= true;
834 wid
.id
= WID_REMAIN_ON_CHAN
;
837 wid
.val
= kmalloc(wid
.size
, GFP_KERNEL
);
841 wid
.val
[0] = remain_on_chan_flag
;
842 wid
.val
[1] = (s8
)hif_remain_ch
->ch
;
844 result
= wilc_send_config_pkt(vif
, WILC_SET_CFG
, &wid
, 1);
849 hif_drv
->remain_on_ch
.arg
= hif_remain_ch
->arg
;
850 hif_drv
->remain_on_ch
.expired
= hif_remain_ch
->expired
;
851 hif_drv
->remain_on_ch
.ch
= hif_remain_ch
->ch
;
852 hif_drv
->remain_on_ch
.cookie
= hif_remain_ch
->cookie
;
853 hif_drv
->remain_on_ch_timer_vif
= vif
;
858 static int wilc_handle_roc_expired(struct wilc_vif
*vif
, u64 cookie
)
860 u8 remain_on_chan_flag
;
863 struct host_if_drv
*hif_drv
= vif
->hif_drv
;
865 if (vif
->priv
.p2p_listen_state
) {
866 remain_on_chan_flag
= false;
867 wid
.id
= WID_REMAIN_ON_CHAN
;
871 wid
.val
= kmalloc(wid
.size
, GFP_KERNEL
);
875 wid
.val
[0] = remain_on_chan_flag
;
876 wid
.val
[1] = WILC_FALSE_FRMWR_CHANNEL
;
878 result
= wilc_send_config_pkt(vif
, WILC_SET_CFG
, &wid
, 1);
881 netdev_err(vif
->ndev
, "Failed to set remain channel\n");
885 if (hif_drv
->remain_on_ch
.expired
) {
886 hif_drv
->remain_on_ch
.expired(hif_drv
->remain_on_ch
.arg
,
890 netdev_dbg(vif
->ndev
, "Not in listen state\n");
896 static void wilc_handle_listen_state_expired(struct work_struct
*work
)
898 struct host_if_msg
*msg
= container_of(work
, struct host_if_msg
, work
);
900 wilc_handle_roc_expired(msg
->vif
, msg
->body
.remain_on_ch
.cookie
);
904 static void listen_timer_cb(struct timer_list
*t
)
906 struct host_if_drv
*hif_drv
= from_timer(hif_drv
, t
,
908 struct wilc_vif
*vif
= hif_drv
->remain_on_ch_timer_vif
;
910 struct host_if_msg
*msg
;
912 del_timer(&vif
->hif_drv
->remain_on_ch_timer
);
914 msg
= wilc_alloc_work(vif
, wilc_handle_listen_state_expired
, false);
918 msg
->body
.remain_on_ch
.cookie
= vif
->hif_drv
->remain_on_ch
.cookie
;
920 result
= wilc_enqueue_work(msg
);
922 netdev_err(vif
->ndev
, "%s: enqueue work failed\n", __func__
);
927 static void handle_set_mcast_filter(struct work_struct
*work
)
929 struct host_if_msg
*msg
= container_of(work
, struct host_if_msg
, work
);
930 struct wilc_vif
*vif
= msg
->vif
;
931 struct wilc_set_multicast
*set_mc
= &msg
->body
.mc_info
;
936 wid
.id
= WID_SETUP_MULTICAST_FILTER
;
938 wid
.size
= sizeof(struct wilc_set_multicast
) + (set_mc
->cnt
* ETH_ALEN
);
939 wid
.val
= kmalloc(wid
.size
, GFP_KERNEL
);
944 put_unaligned_le32(set_mc
->enabled
, cur_byte
);
947 put_unaligned_le32(set_mc
->cnt
, cur_byte
);
950 if (set_mc
->cnt
> 0 && set_mc
->mc_list
)
951 memcpy(cur_byte
, set_mc
->mc_list
, set_mc
->cnt
* ETH_ALEN
);
953 result
= wilc_send_config_pkt(vif
, WILC_SET_CFG
, &wid
, 1);
955 netdev_err(vif
->ndev
, "Failed to send setup multicast\n");
958 kfree(set_mc
->mc_list
);
963 static void handle_scan_timer(struct work_struct
*work
)
965 struct host_if_msg
*msg
= container_of(work
, struct host_if_msg
, work
);
967 handle_scan_done(msg
->vif
, SCAN_EVENT_ABORTED
);
971 static void handle_scan_complete(struct work_struct
*work
)
973 struct host_if_msg
*msg
= container_of(work
, struct host_if_msg
, work
);
975 del_timer(&msg
->vif
->hif_drv
->scan_timer
);
977 handle_scan_done(msg
->vif
, SCAN_EVENT_DONE
);
982 static void timer_scan_cb(struct timer_list
*t
)
984 struct host_if_drv
*hif_drv
= from_timer(hif_drv
, t
, scan_timer
);
985 struct wilc_vif
*vif
= hif_drv
->scan_timer_vif
;
986 struct host_if_msg
*msg
;
989 msg
= wilc_alloc_work(vif
, handle_scan_timer
, false);
993 result
= wilc_enqueue_work(msg
);
998 static void timer_connect_cb(struct timer_list
*t
)
1000 struct host_if_drv
*hif_drv
= from_timer(hif_drv
, t
,
1002 struct wilc_vif
*vif
= hif_drv
->connect_timer_vif
;
1003 struct host_if_msg
*msg
;
1006 msg
= wilc_alloc_work(vif
, handle_connect_timeout
, false);
1010 result
= wilc_enqueue_work(msg
);
1015 int wilc_remove_wep_key(struct wilc_vif
*vif
, u8 index
)
1020 wid
.id
= WID_REMOVE_WEP_KEY
;
1022 wid
.size
= sizeof(char);
1025 result
= wilc_send_config_pkt(vif
, WILC_SET_CFG
, &wid
, 1);
1027 netdev_err(vif
->ndev
,
1028 "Failed to send remove wep key config packet\n");
1032 int wilc_set_wep_default_keyid(struct wilc_vif
*vif
, u8 index
)
1037 wid
.id
= WID_KEY_ID
;
1038 wid
.type
= WID_CHAR
;
1039 wid
.size
= sizeof(char);
1041 result
= wilc_send_config_pkt(vif
, WILC_SET_CFG
, &wid
, 1);
1043 netdev_err(vif
->ndev
,
1044 "Failed to send wep default key config packet\n");
1049 int wilc_add_wep_key_bss_sta(struct wilc_vif
*vif
, const u8
*key
, u8 len
,
1054 struct wilc_wep_key
*wep_key
;
1056 wid
.id
= WID_ADD_WEP_KEY
;
1058 wid
.size
= sizeof(*wep_key
) + len
;
1059 wep_key
= kzalloc(wid
.size
, GFP_KERNEL
);
1063 wid
.val
= (u8
*)wep_key
;
1065 wep_key
->index
= index
;
1066 wep_key
->key_len
= len
;
1067 memcpy(wep_key
->key
, key
, len
);
1069 result
= wilc_send_config_pkt(vif
, WILC_SET_CFG
, &wid
, 1);
1071 netdev_err(vif
->ndev
,
1072 "Failed to add wep key config packet\n");
1078 int wilc_add_wep_key_bss_ap(struct wilc_vif
*vif
, const u8
*key
, u8 len
,
1079 u8 index
, u8 mode
, enum authtype auth_type
)
1081 struct wid wid_list
[3];
1083 struct wilc_wep_key
*wep_key
;
1085 wid_list
[0].id
= WID_11I_MODE
;
1086 wid_list
[0].type
= WID_CHAR
;
1087 wid_list
[0].size
= sizeof(char);
1088 wid_list
[0].val
= &mode
;
1090 wid_list
[1].id
= WID_AUTH_TYPE
;
1091 wid_list
[1].type
= WID_CHAR
;
1092 wid_list
[1].size
= sizeof(char);
1093 wid_list
[1].val
= (s8
*)&auth_type
;
1095 wid_list
[2].id
= WID_WEP_KEY_VALUE
;
1096 wid_list
[2].type
= WID_STR
;
1097 wid_list
[2].size
= sizeof(*wep_key
) + len
;
1098 wep_key
= kzalloc(wid_list
[2].size
, GFP_KERNEL
);
1102 wid_list
[2].val
= (u8
*)wep_key
;
1104 wep_key
->index
= index
;
1105 wep_key
->key_len
= len
;
1106 memcpy(wep_key
->key
, key
, len
);
1107 result
= wilc_send_config_pkt(vif
, WILC_SET_CFG
, wid_list
,
1108 ARRAY_SIZE(wid_list
));
1110 netdev_err(vif
->ndev
,
1111 "Failed to add wep ap key config packet\n");
1117 int wilc_add_ptk(struct wilc_vif
*vif
, const u8
*ptk
, u8 ptk_key_len
,
1118 const u8
*mac_addr
, const u8
*rx_mic
, const u8
*tx_mic
,
1119 u8 mode
, u8 cipher_mode
, u8 index
)
1122 u8 t_key_len
= ptk_key_len
+ WILC_RX_MIC_KEY_LEN
+ WILC_TX_MIC_KEY_LEN
;
1124 if (mode
== WILC_AP_MODE
) {
1125 struct wid wid_list
[2];
1126 struct wilc_ap_wpa_ptk
*key_buf
;
1128 wid_list
[0].id
= WID_11I_MODE
;
1129 wid_list
[0].type
= WID_CHAR
;
1130 wid_list
[0].size
= sizeof(char);
1131 wid_list
[0].val
= (s8
*)&cipher_mode
;
1133 key_buf
= kzalloc(sizeof(*key_buf
) + t_key_len
, GFP_KERNEL
);
1137 ether_addr_copy(key_buf
->mac_addr
, mac_addr
);
1138 key_buf
->index
= index
;
1139 key_buf
->key_len
= t_key_len
;
1140 memcpy(&key_buf
->key
[0], ptk
, ptk_key_len
);
1143 memcpy(&key_buf
->key
[ptk_key_len
], rx_mic
,
1144 WILC_RX_MIC_KEY_LEN
);
1147 memcpy(&key_buf
->key
[ptk_key_len
+ WILC_RX_MIC_KEY_LEN
],
1148 tx_mic
, WILC_TX_MIC_KEY_LEN
);
1150 wid_list
[1].id
= WID_ADD_PTK
;
1151 wid_list
[1].type
= WID_STR
;
1152 wid_list
[1].size
= sizeof(*key_buf
) + t_key_len
;
1153 wid_list
[1].val
= (u8
*)key_buf
;
1154 result
= wilc_send_config_pkt(vif
, WILC_SET_CFG
, wid_list
,
1155 ARRAY_SIZE(wid_list
));
1157 } else if (mode
== WILC_STATION_MODE
) {
1159 struct wilc_sta_wpa_ptk
*key_buf
;
1161 key_buf
= kzalloc(sizeof(*key_buf
) + t_key_len
, GFP_KERNEL
);
1165 ether_addr_copy(key_buf
->mac_addr
, mac_addr
);
1166 key_buf
->key_len
= t_key_len
;
1167 memcpy(&key_buf
->key
[0], ptk
, ptk_key_len
);
1170 memcpy(&key_buf
->key
[ptk_key_len
], rx_mic
,
1171 WILC_RX_MIC_KEY_LEN
);
1174 memcpy(&key_buf
->key
[ptk_key_len
+ WILC_RX_MIC_KEY_LEN
],
1175 tx_mic
, WILC_TX_MIC_KEY_LEN
);
1177 wid
.id
= WID_ADD_PTK
;
1179 wid
.size
= sizeof(*key_buf
) + t_key_len
;
1180 wid
.val
= (s8
*)key_buf
;
1181 result
= wilc_send_config_pkt(vif
, WILC_SET_CFG
, &wid
, 1);
1188 int wilc_add_rx_gtk(struct wilc_vif
*vif
, const u8
*rx_gtk
, u8 gtk_key_len
,
1189 u8 index
, u32 key_rsc_len
, const u8
*key_rsc
,
1190 const u8
*rx_mic
, const u8
*tx_mic
, u8 mode
,
1194 struct wilc_gtk_key
*gtk_key
;
1195 int t_key_len
= gtk_key_len
+ WILC_RX_MIC_KEY_LEN
+ WILC_TX_MIC_KEY_LEN
;
1197 gtk_key
= kzalloc(sizeof(*gtk_key
) + t_key_len
, GFP_KERNEL
);
1201 /* fill bssid value only in station mode */
1202 if (mode
== WILC_STATION_MODE
&&
1203 vif
->hif_drv
->hif_state
== HOST_IF_CONNECTED
)
1204 memcpy(gtk_key
->mac_addr
, vif
->hif_drv
->assoc_bssid
, ETH_ALEN
);
1207 memcpy(gtk_key
->rsc
, key_rsc
, 8);
1208 gtk_key
->index
= index
;
1209 gtk_key
->key_len
= t_key_len
;
1210 memcpy(>k_key
->key
[0], rx_gtk
, gtk_key_len
);
1213 memcpy(>k_key
->key
[gtk_key_len
], rx_mic
, WILC_RX_MIC_KEY_LEN
);
1216 memcpy(>k_key
->key
[gtk_key_len
+ WILC_RX_MIC_KEY_LEN
],
1217 tx_mic
, WILC_TX_MIC_KEY_LEN
);
1219 if (mode
== WILC_AP_MODE
) {
1220 struct wid wid_list
[2];
1222 wid_list
[0].id
= WID_11I_MODE
;
1223 wid_list
[0].type
= WID_CHAR
;
1224 wid_list
[0].size
= sizeof(char);
1225 wid_list
[0].val
= (s8
*)&cipher_mode
;
1227 wid_list
[1].id
= WID_ADD_RX_GTK
;
1228 wid_list
[1].type
= WID_STR
;
1229 wid_list
[1].size
= sizeof(*gtk_key
) + t_key_len
;
1230 wid_list
[1].val
= (u8
*)gtk_key
;
1232 result
= wilc_send_config_pkt(vif
, WILC_SET_CFG
, wid_list
,
1233 ARRAY_SIZE(wid_list
));
1234 } else if (mode
== WILC_STATION_MODE
) {
1237 wid
.id
= WID_ADD_RX_GTK
;
1239 wid
.size
= sizeof(*gtk_key
) + t_key_len
;
1240 wid
.val
= (u8
*)gtk_key
;
1241 result
= wilc_send_config_pkt(vif
, WILC_SET_CFG
, &wid
, 1);
1248 int wilc_set_pmkid_info(struct wilc_vif
*vif
, struct wilc_pmkid_attr
*pmkid
)
1252 wid
.id
= WID_PMKID_INFO
;
1254 wid
.size
= (pmkid
->numpmkid
* sizeof(struct wilc_pmkid
)) + 1;
1255 wid
.val
= (u8
*)pmkid
;
1257 return wilc_send_config_pkt(vif
, WILC_SET_CFG
, &wid
, 1);
1260 int wilc_get_mac_address(struct wilc_vif
*vif
, u8
*mac_addr
)
1265 wid
.id
= WID_MAC_ADDR
;
1267 wid
.size
= ETH_ALEN
;
1270 result
= wilc_send_config_pkt(vif
, WILC_GET_CFG
, &wid
, 1);
1272 netdev_err(vif
->ndev
, "Failed to get mac address\n");
1277 int wilc_set_join_req(struct wilc_vif
*vif
, u8
*bssid
, const u8
*ies
,
1281 struct host_if_drv
*hif_drv
= vif
->hif_drv
;
1282 struct wilc_conn_info
*conn_info
= &hif_drv
->conn_info
;
1285 ether_addr_copy(conn_info
->bssid
, bssid
);
1288 conn_info
->req_ies_len
= ies_len
;
1289 conn_info
->req_ies
= kmemdup(ies
, ies_len
, GFP_KERNEL
);
1290 if (!conn_info
->req_ies
)
1294 result
= wilc_send_connect_wid(vif
);
1298 hif_drv
->connect_timer_vif
= vif
;
1299 mod_timer(&hif_drv
->connect_timer
,
1300 jiffies
+ msecs_to_jiffies(WILC_HIF_CONNECT_TIMEOUT_MS
));
1305 kfree(conn_info
->req_ies
);
1310 int wilc_set_mac_chnl_num(struct wilc_vif
*vif
, u8 channel
)
1315 wid
.id
= WID_CURRENT_CHANNEL
;
1316 wid
.type
= WID_CHAR
;
1317 wid
.size
= sizeof(char);
1320 result
= wilc_send_config_pkt(vif
, WILC_SET_CFG
, &wid
, 1);
1322 netdev_err(vif
->ndev
, "Failed to set channel\n");
1327 int wilc_set_operation_mode(struct wilc_vif
*vif
, int index
, u8 mode
,
1332 struct wilc_drv_handler drv
;
1334 wid
.id
= WID_SET_OPERATION_MODE
;
1336 wid
.size
= sizeof(drv
);
1337 wid
.val
= (u8
*)&drv
;
1339 drv
.handler
= cpu_to_le32(index
);
1340 drv
.mode
= (ifc_id
| (mode
<< 1));
1342 result
= wilc_send_config_pkt(vif
, WILC_SET_CFG
, &wid
, 1);
1344 netdev_err(vif
->ndev
, "Failed to set driver handler\n");
1349 s32
wilc_get_inactive_time(struct wilc_vif
*vif
, const u8
*mac
, u32
*out_val
)
1354 wid
.id
= WID_SET_STA_MAC_INACTIVE_TIME
;
1356 wid
.size
= ETH_ALEN
;
1357 wid
.val
= kzalloc(wid
.size
, GFP_KERNEL
);
1361 ether_addr_copy(wid
.val
, mac
);
1362 result
= wilc_send_config_pkt(vif
, WILC_SET_CFG
, &wid
, 1);
1365 netdev_err(vif
->ndev
, "Failed to set inactive mac\n");
1369 wid
.id
= WID_GET_INACTIVE_TIME
;
1371 wid
.val
= (s8
*)out_val
;
1372 wid
.size
= sizeof(u32
);
1373 result
= wilc_send_config_pkt(vif
, WILC_GET_CFG
, &wid
, 1);
1375 netdev_err(vif
->ndev
, "Failed to get inactive time\n");
1380 int wilc_get_rssi(struct wilc_vif
*vif
, s8
*rssi_level
)
1386 netdev_err(vif
->ndev
, "%s: RSSI level is NULL\n", __func__
);
1391 wid
.type
= WID_CHAR
;
1392 wid
.size
= sizeof(char);
1393 wid
.val
= rssi_level
;
1394 result
= wilc_send_config_pkt(vif
, WILC_GET_CFG
, &wid
, 1);
1396 netdev_err(vif
->ndev
, "Failed to get RSSI value\n");
1401 static int wilc_get_stats_async(struct wilc_vif
*vif
, struct rf_info
*stats
)
1404 struct host_if_msg
*msg
;
1406 msg
= wilc_alloc_work(vif
, handle_get_statistics
, false);
1408 return PTR_ERR(msg
);
1410 msg
->body
.data
= (char *)stats
;
1412 result
= wilc_enqueue_work(msg
);
1414 netdev_err(vif
->ndev
, "%s: enqueue work failed\n", __func__
);
1422 int wilc_hif_set_cfg(struct wilc_vif
*vif
, struct cfg_param_attr
*param
)
1424 struct wid wid_list
[4];
1427 if (param
->flag
& WILC_CFG_PARAM_RETRY_SHORT
) {
1428 wid_list
[i
].id
= WID_SHORT_RETRY_LIMIT
;
1429 wid_list
[i
].val
= (s8
*)¶m
->short_retry_limit
;
1430 wid_list
[i
].type
= WID_SHORT
;
1431 wid_list
[i
].size
= sizeof(u16
);
1434 if (param
->flag
& WILC_CFG_PARAM_RETRY_LONG
) {
1435 wid_list
[i
].id
= WID_LONG_RETRY_LIMIT
;
1436 wid_list
[i
].val
= (s8
*)¶m
->long_retry_limit
;
1437 wid_list
[i
].type
= WID_SHORT
;
1438 wid_list
[i
].size
= sizeof(u16
);
1441 if (param
->flag
& WILC_CFG_PARAM_FRAG_THRESHOLD
) {
1442 wid_list
[i
].id
= WID_FRAG_THRESHOLD
;
1443 wid_list
[i
].val
= (s8
*)¶m
->frag_threshold
;
1444 wid_list
[i
].type
= WID_SHORT
;
1445 wid_list
[i
].size
= sizeof(u16
);
1448 if (param
->flag
& WILC_CFG_PARAM_RTS_THRESHOLD
) {
1449 wid_list
[i
].id
= WID_RTS_THRESHOLD
;
1450 wid_list
[i
].val
= (s8
*)¶m
->rts_threshold
;
1451 wid_list
[i
].type
= WID_SHORT
;
1452 wid_list
[i
].size
= sizeof(u16
);
1456 return wilc_send_config_pkt(vif
, WILC_SET_CFG
, wid_list
, i
);
1459 static void get_periodic_rssi(struct timer_list
*t
)
1461 struct wilc_vif
*vif
= from_timer(vif
, t
, periodic_rssi
);
1463 if (!vif
->hif_drv
) {
1464 netdev_err(vif
->ndev
, "%s: hif driver is NULL", __func__
);
1468 if (vif
->hif_drv
->hif_state
== HOST_IF_CONNECTED
)
1469 wilc_get_stats_async(vif
, &vif
->periodic_stat
);
1471 mod_timer(&vif
->periodic_rssi
, jiffies
+ msecs_to_jiffies(5000));
1474 int wilc_init(struct net_device
*dev
, struct host_if_drv
**hif_drv_handler
)
1476 struct host_if_drv
*hif_drv
;
1477 struct wilc_vif
*vif
= netdev_priv(dev
);
1478 struct wilc
*wilc
= vif
->wilc
;
1480 hif_drv
= kzalloc(sizeof(*hif_drv
), GFP_KERNEL
);
1484 *hif_drv_handler
= hif_drv
;
1486 vif
->hif_drv
= hif_drv
;
1488 if (wilc
->clients_count
== 0)
1489 mutex_init(&wilc
->deinit_lock
);
1491 timer_setup(&vif
->periodic_rssi
, get_periodic_rssi
, 0);
1492 mod_timer(&vif
->periodic_rssi
, jiffies
+ msecs_to_jiffies(5000));
1494 timer_setup(&hif_drv
->scan_timer
, timer_scan_cb
, 0);
1495 timer_setup(&hif_drv
->connect_timer
, timer_connect_cb
, 0);
1496 timer_setup(&hif_drv
->remain_on_ch_timer
, listen_timer_cb
, 0);
1498 hif_drv
->hif_state
= HOST_IF_IDLE
;
1500 hif_drv
->p2p_timeout
= 0;
1502 wilc
->clients_count
++;
1507 int wilc_deinit(struct wilc_vif
*vif
)
1510 struct host_if_drv
*hif_drv
= vif
->hif_drv
;
1513 netdev_err(vif
->ndev
, "%s: hif driver is NULL", __func__
);
1517 mutex_lock(&vif
->wilc
->deinit_lock
);
1519 del_timer_sync(&hif_drv
->scan_timer
);
1520 del_timer_sync(&hif_drv
->connect_timer
);
1521 del_timer_sync(&vif
->periodic_rssi
);
1522 del_timer_sync(&hif_drv
->remain_on_ch_timer
);
1524 if (hif_drv
->usr_scan_req
.scan_result
) {
1525 hif_drv
->usr_scan_req
.scan_result(SCAN_EVENT_ABORTED
, NULL
,
1526 hif_drv
->usr_scan_req
.arg
);
1527 hif_drv
->usr_scan_req
.scan_result
= NULL
;
1530 hif_drv
->hif_state
= HOST_IF_IDLE
;
1533 vif
->hif_drv
= NULL
;
1534 vif
->wilc
->clients_count
--;
1535 mutex_unlock(&vif
->wilc
->deinit_lock
);
1539 void wilc_network_info_received(struct wilc
*wilc
, u8
*buffer
, u32 length
)
1542 struct host_if_msg
*msg
;
1544 struct host_if_drv
*hif_drv
;
1545 struct wilc_vif
*vif
;
1547 id
= get_unaligned_le32(&buffer
[length
- 4]);
1548 vif
= wilc_get_vif_from_idx(wilc
, id
);
1551 hif_drv
= vif
->hif_drv
;
1554 netdev_err(vif
->ndev
, "driver not init[%p]\n", hif_drv
);
1558 msg
= wilc_alloc_work(vif
, handle_rcvd_ntwrk_info
, false);
1562 msg
->body
.net_info
.frame_len
= get_unaligned_le16(&buffer
[6]) - 1;
1563 msg
->body
.net_info
.rssi
= buffer
[8];
1564 msg
->body
.net_info
.mgmt
= kmemdup(&buffer
[9],
1565 msg
->body
.net_info
.frame_len
,
1567 if (!msg
->body
.net_info
.mgmt
) {
1572 result
= wilc_enqueue_work(msg
);
1574 netdev_err(vif
->ndev
, "%s: enqueue work failed\n", __func__
);
1575 kfree(msg
->body
.net_info
.mgmt
);
1580 void wilc_gnrl_async_info_received(struct wilc
*wilc
, u8
*buffer
, u32 length
)
1583 struct host_if_msg
*msg
;
1585 struct host_if_drv
*hif_drv
;
1586 struct wilc_vif
*vif
;
1588 mutex_lock(&wilc
->deinit_lock
);
1590 id
= get_unaligned_le32(&buffer
[length
- 4]);
1591 vif
= wilc_get_vif_from_idx(wilc
, id
);
1593 mutex_unlock(&wilc
->deinit_lock
);
1597 hif_drv
= vif
->hif_drv
;
1600 mutex_unlock(&wilc
->deinit_lock
);
1604 if (!hif_drv
->conn_info
.conn_result
) {
1605 netdev_err(vif
->ndev
, "%s: conn_result is NULL\n", __func__
);
1606 mutex_unlock(&wilc
->deinit_lock
);
1610 msg
= wilc_alloc_work(vif
, handle_rcvd_gnrl_async_info
, false);
1612 mutex_unlock(&wilc
->deinit_lock
);
1616 msg
->body
.mac_info
.status
= buffer
[7];
1617 result
= wilc_enqueue_work(msg
);
1619 netdev_err(vif
->ndev
, "%s: enqueue work failed\n", __func__
);
1623 mutex_unlock(&wilc
->deinit_lock
);
1626 void wilc_scan_complete_received(struct wilc
*wilc
, u8
*buffer
, u32 length
)
1630 struct host_if_drv
*hif_drv
;
1631 struct wilc_vif
*vif
;
1633 id
= get_unaligned_le32(&buffer
[length
- 4]);
1634 vif
= wilc_get_vif_from_idx(wilc
, id
);
1637 hif_drv
= vif
->hif_drv
;
1642 if (hif_drv
->usr_scan_req
.scan_result
) {
1643 struct host_if_msg
*msg
;
1645 msg
= wilc_alloc_work(vif
, handle_scan_complete
, false);
1649 result
= wilc_enqueue_work(msg
);
1651 netdev_err(vif
->ndev
, "%s: enqueue work failed\n",
1658 int wilc_remain_on_channel(struct wilc_vif
*vif
, u64 cookie
,
1659 u32 duration
, u16 chan
,
1660 void (*expired
)(void *, u64
),
1663 struct wilc_remain_ch roc
;
1667 roc
.expired
= expired
;
1669 roc
.duration
= duration
;
1670 roc
.cookie
= cookie
;
1671 result
= handle_remain_on_chan(vif
, &roc
);
1673 netdev_err(vif
->ndev
, "%s: failed to set remain on channel\n",
1679 int wilc_listen_state_expired(struct wilc_vif
*vif
, u64 cookie
)
1681 if (!vif
->hif_drv
) {
1682 netdev_err(vif
->ndev
, "%s: hif driver is NULL", __func__
);
1686 del_timer(&vif
->hif_drv
->remain_on_ch_timer
);
1688 return wilc_handle_roc_expired(vif
, cookie
);
1691 void wilc_frame_register(struct wilc_vif
*vif
, u16 frame_type
, bool reg
)
1695 struct wilc_reg_frame reg_frame
;
1697 wid
.id
= WID_REGISTER_FRAME
;
1699 wid
.size
= sizeof(reg_frame
);
1700 wid
.val
= (u8
*)®_frame
;
1702 memset(®_frame
, 0x0, sizeof(reg_frame
));
1707 switch (frame_type
) {
1708 case IEEE80211_STYPE_ACTION
:
1709 reg_frame
.reg_id
= WILC_FW_ACTION_FRM_IDX
;
1712 case IEEE80211_STYPE_PROBE_REQ
:
1713 reg_frame
.reg_id
= WILC_FW_PROBE_REQ_IDX
;
1719 reg_frame
.frame_type
= cpu_to_le16(frame_type
);
1720 result
= wilc_send_config_pkt(vif
, WILC_SET_CFG
, &wid
, 1);
1722 netdev_err(vif
->ndev
, "Failed to frame register\n");
1725 int wilc_add_beacon(struct wilc_vif
*vif
, u32 interval
, u32 dtim_period
,
1726 struct cfg80211_beacon_data
*params
)
1732 wid
.id
= WID_ADD_BEACON
;
1734 wid
.size
= params
->head_len
+ params
->tail_len
+ 16;
1735 wid
.val
= kzalloc(wid
.size
, GFP_KERNEL
);
1740 put_unaligned_le32(interval
, cur_byte
);
1742 put_unaligned_le32(dtim_period
, cur_byte
);
1744 put_unaligned_le32(params
->head_len
, cur_byte
);
1747 if (params
->head_len
> 0)
1748 memcpy(cur_byte
, params
->head
, params
->head_len
);
1749 cur_byte
+= params
->head_len
;
1751 put_unaligned_le32(params
->tail_len
, cur_byte
);
1754 if (params
->tail_len
> 0)
1755 memcpy(cur_byte
, params
->tail
, params
->tail_len
);
1757 result
= wilc_send_config_pkt(vif
, WILC_SET_CFG
, &wid
, 1);
1759 netdev_err(vif
->ndev
, "Failed to send add beacon\n");
1766 int wilc_del_beacon(struct wilc_vif
*vif
)
1772 wid
.id
= WID_DEL_BEACON
;
1773 wid
.type
= WID_CHAR
;
1774 wid
.size
= sizeof(char);
1775 wid
.val
= &del_beacon
;
1777 result
= wilc_send_config_pkt(vif
, WILC_SET_CFG
, &wid
, 1);
1779 netdev_err(vif
->ndev
, "Failed to send delete beacon\n");
1784 int wilc_add_station(struct wilc_vif
*vif
, const u8
*mac
,
1785 struct station_parameters
*params
)
1791 wid
.id
= WID_ADD_STA
;
1793 wid
.size
= WILC_ADD_STA_LENGTH
+ params
->supported_rates_len
;
1794 wid
.val
= kmalloc(wid
.size
, GFP_KERNEL
);
1799 wilc_hif_pack_sta_param(cur_byte
, mac
, params
);
1801 result
= wilc_send_config_pkt(vif
, WILC_SET_CFG
, &wid
, 1);
1803 netdev_err(vif
->ndev
, "Failed to send add station\n");
1810 int wilc_del_station(struct wilc_vif
*vif
, const u8
*mac_addr
)
1815 wid
.id
= WID_REMOVE_STA
;
1817 wid
.size
= ETH_ALEN
;
1818 wid
.val
= kzalloc(wid
.size
, GFP_KERNEL
);
1823 eth_broadcast_addr(wid
.val
);
1825 ether_addr_copy(wid
.val
, mac_addr
);
1827 result
= wilc_send_config_pkt(vif
, WILC_SET_CFG
, &wid
, 1);
1829 netdev_err(vif
->ndev
, "Failed to del station\n");
1836 int wilc_del_allstation(struct wilc_vif
*vif
, u8 mac_addr
[][ETH_ALEN
])
1842 struct wilc_del_all_sta del_sta
;
1844 memset(&del_sta
, 0x0, sizeof(del_sta
));
1845 for (i
= 0; i
< WILC_MAX_NUM_STA
; i
++) {
1846 if (!is_zero_ether_addr(mac_addr
[i
])) {
1848 ether_addr_copy(del_sta
.mac
[i
], mac_addr
[i
]);
1855 del_sta
.assoc_sta
= assoc_sta
;
1857 wid
.id
= WID_DEL_ALL_STA
;
1859 wid
.size
= (assoc_sta
* ETH_ALEN
) + 1;
1860 wid
.val
= (u8
*)&del_sta
;
1862 result
= wilc_send_config_pkt(vif
, WILC_SET_CFG
, &wid
, 1);
1864 netdev_err(vif
->ndev
, "Failed to send delete all station\n");
1869 int wilc_edit_station(struct wilc_vif
*vif
, const u8
*mac
,
1870 struct station_parameters
*params
)
1876 wid
.id
= WID_EDIT_STA
;
1878 wid
.size
= WILC_ADD_STA_LENGTH
+ params
->supported_rates_len
;
1879 wid
.val
= kmalloc(wid
.size
, GFP_KERNEL
);
1884 wilc_hif_pack_sta_param(cur_byte
, mac
, params
);
1886 result
= wilc_send_config_pkt(vif
, WILC_SET_CFG
, &wid
, 1);
1888 netdev_err(vif
->ndev
, "Failed to send edit station\n");
1894 int wilc_set_power_mgmt(struct wilc_vif
*vif
, bool enabled
, u32 timeout
)
1901 power_mode
= WILC_FW_MIN_FAST_PS
;
1903 power_mode
= WILC_FW_NO_POWERSAVE
;
1905 wid
.id
= WID_POWER_MANAGEMENT
;
1906 wid
.val
= &power_mode
;
1907 wid
.size
= sizeof(char);
1908 result
= wilc_send_config_pkt(vif
, WILC_SET_CFG
, &wid
, 1);
1910 netdev_err(vif
->ndev
, "Failed to send power management\n");
1915 int wilc_setup_multicast_filter(struct wilc_vif
*vif
, u32 enabled
, u32 count
,
1919 struct host_if_msg
*msg
;
1921 msg
= wilc_alloc_work(vif
, handle_set_mcast_filter
, false);
1923 return PTR_ERR(msg
);
1925 msg
->body
.mc_info
.enabled
= enabled
;
1926 msg
->body
.mc_info
.cnt
= count
;
1927 msg
->body
.mc_info
.mc_list
= mc_list
;
1929 result
= wilc_enqueue_work(msg
);
1931 netdev_err(vif
->ndev
, "%s: enqueue work failed\n", __func__
);
1937 int wilc_set_tx_power(struct wilc_vif
*vif
, u8 tx_power
)
1941 wid
.id
= WID_TX_POWER
;
1942 wid
.type
= WID_CHAR
;
1943 wid
.val
= &tx_power
;
1944 wid
.size
= sizeof(char);
1946 return wilc_send_config_pkt(vif
, WILC_SET_CFG
, &wid
, 1);
1949 int wilc_get_tx_power(struct wilc_vif
*vif
, u8
*tx_power
)
1953 wid
.id
= WID_TX_POWER
;
1954 wid
.type
= WID_CHAR
;
1956 wid
.size
= sizeof(char);
1958 return wilc_send_config_pkt(vif
, WILC_GET_CFG
, &wid
, 1);