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
, ¶ms
->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
;
864 struct wilc_priv
*priv
= wdev_priv(vif
->ndev
->ieee80211_ptr
);
866 if (priv
->p2p_listen_state
) {
867 remain_on_chan_flag
= false;
868 wid
.id
= WID_REMAIN_ON_CHAN
;
872 wid
.val
= kmalloc(wid
.size
, GFP_KERNEL
);
876 wid
.val
[0] = remain_on_chan_flag
;
877 wid
.val
[1] = WILC_FALSE_FRMWR_CHANNEL
;
879 result
= wilc_send_config_pkt(vif
, WILC_SET_CFG
, &wid
, 1);
882 netdev_err(vif
->ndev
, "Failed to set remain channel\n");
886 if (hif_drv
->remain_on_ch
.expired
) {
887 hif_drv
->remain_on_ch
.expired(hif_drv
->remain_on_ch
.arg
,
891 netdev_dbg(vif
->ndev
, "Not in listen state\n");
897 static void wilc_handle_listen_state_expired(struct work_struct
*work
)
899 struct host_if_msg
*msg
= container_of(work
, struct host_if_msg
, work
);
901 wilc_handle_roc_expired(msg
->vif
, msg
->body
.remain_on_ch
.cookie
);
905 static void listen_timer_cb(struct timer_list
*t
)
907 struct host_if_drv
*hif_drv
= from_timer(hif_drv
, t
,
909 struct wilc_vif
*vif
= hif_drv
->remain_on_ch_timer_vif
;
911 struct host_if_msg
*msg
;
913 del_timer(&vif
->hif_drv
->remain_on_ch_timer
);
915 msg
= wilc_alloc_work(vif
, wilc_handle_listen_state_expired
, false);
919 msg
->body
.remain_on_ch
.cookie
= vif
->hif_drv
->remain_on_ch
.cookie
;
921 result
= wilc_enqueue_work(msg
);
923 netdev_err(vif
->ndev
, "%s: enqueue work failed\n", __func__
);
928 static void handle_set_mcast_filter(struct work_struct
*work
)
930 struct host_if_msg
*msg
= container_of(work
, struct host_if_msg
, work
);
931 struct wilc_vif
*vif
= msg
->vif
;
932 struct wilc_set_multicast
*set_mc
= &msg
->body
.mc_info
;
937 wid
.id
= WID_SETUP_MULTICAST_FILTER
;
939 wid
.size
= sizeof(struct wilc_set_multicast
) + (set_mc
->cnt
* ETH_ALEN
);
940 wid
.val
= kmalloc(wid
.size
, GFP_KERNEL
);
945 put_unaligned_le32(set_mc
->enabled
, cur_byte
);
948 put_unaligned_le32(set_mc
->cnt
, cur_byte
);
951 if (set_mc
->cnt
> 0 && set_mc
->mc_list
)
952 memcpy(cur_byte
, set_mc
->mc_list
, set_mc
->cnt
* ETH_ALEN
);
954 result
= wilc_send_config_pkt(vif
, WILC_SET_CFG
, &wid
, 1);
956 netdev_err(vif
->ndev
, "Failed to send setup multicast\n");
959 kfree(set_mc
->mc_list
);
964 static void handle_scan_timer(struct work_struct
*work
)
966 struct host_if_msg
*msg
= container_of(work
, struct host_if_msg
, work
);
968 handle_scan_done(msg
->vif
, SCAN_EVENT_ABORTED
);
972 static void handle_scan_complete(struct work_struct
*work
)
974 struct host_if_msg
*msg
= container_of(work
, struct host_if_msg
, work
);
976 del_timer(&msg
->vif
->hif_drv
->scan_timer
);
978 handle_scan_done(msg
->vif
, SCAN_EVENT_DONE
);
983 static void timer_scan_cb(struct timer_list
*t
)
985 struct host_if_drv
*hif_drv
= from_timer(hif_drv
, t
, scan_timer
);
986 struct wilc_vif
*vif
= hif_drv
->scan_timer_vif
;
987 struct host_if_msg
*msg
;
990 msg
= wilc_alloc_work(vif
, handle_scan_timer
, false);
994 result
= wilc_enqueue_work(msg
);
999 static void timer_connect_cb(struct timer_list
*t
)
1001 struct host_if_drv
*hif_drv
= from_timer(hif_drv
, t
,
1003 struct wilc_vif
*vif
= hif_drv
->connect_timer_vif
;
1004 struct host_if_msg
*msg
;
1007 msg
= wilc_alloc_work(vif
, handle_connect_timeout
, false);
1011 result
= wilc_enqueue_work(msg
);
1016 int wilc_remove_wep_key(struct wilc_vif
*vif
, u8 index
)
1021 wid
.id
= WID_REMOVE_WEP_KEY
;
1023 wid
.size
= sizeof(char);
1026 result
= wilc_send_config_pkt(vif
, WILC_SET_CFG
, &wid
, 1);
1028 netdev_err(vif
->ndev
,
1029 "Failed to send remove wep key config packet\n");
1033 int wilc_set_wep_default_keyid(struct wilc_vif
*vif
, u8 index
)
1038 wid
.id
= WID_KEY_ID
;
1039 wid
.type
= WID_CHAR
;
1040 wid
.size
= sizeof(char);
1042 result
= wilc_send_config_pkt(vif
, WILC_SET_CFG
, &wid
, 1);
1044 netdev_err(vif
->ndev
,
1045 "Failed to send wep default key config packet\n");
1050 int wilc_add_wep_key_bss_sta(struct wilc_vif
*vif
, const u8
*key
, u8 len
,
1055 struct wilc_wep_key
*wep_key
;
1057 wid
.id
= WID_ADD_WEP_KEY
;
1059 wid
.size
= sizeof(*wep_key
) + len
;
1060 wep_key
= kzalloc(wid
.size
, GFP_KERNEL
);
1064 wid
.val
= (u8
*)wep_key
;
1066 wep_key
->index
= index
;
1067 wep_key
->key_len
= len
;
1068 memcpy(wep_key
->key
, key
, len
);
1070 result
= wilc_send_config_pkt(vif
, WILC_SET_CFG
, &wid
, 1);
1072 netdev_err(vif
->ndev
,
1073 "Failed to add wep key config packet\n");
1079 int wilc_add_wep_key_bss_ap(struct wilc_vif
*vif
, const u8
*key
, u8 len
,
1080 u8 index
, u8 mode
, enum authtype auth_type
)
1082 struct wid wid_list
[3];
1084 struct wilc_wep_key
*wep_key
;
1086 wid_list
[0].id
= WID_11I_MODE
;
1087 wid_list
[0].type
= WID_CHAR
;
1088 wid_list
[0].size
= sizeof(char);
1089 wid_list
[0].val
= &mode
;
1091 wid_list
[1].id
= WID_AUTH_TYPE
;
1092 wid_list
[1].type
= WID_CHAR
;
1093 wid_list
[1].size
= sizeof(char);
1094 wid_list
[1].val
= (s8
*)&auth_type
;
1096 wid_list
[2].id
= WID_WEP_KEY_VALUE
;
1097 wid_list
[2].type
= WID_STR
;
1098 wid_list
[2].size
= sizeof(*wep_key
) + len
;
1099 wep_key
= kzalloc(wid_list
[2].size
, GFP_KERNEL
);
1103 wid_list
[2].val
= (u8
*)wep_key
;
1105 wep_key
->index
= index
;
1106 wep_key
->key_len
= len
;
1107 memcpy(wep_key
->key
, key
, len
);
1108 result
= wilc_send_config_pkt(vif
, WILC_SET_CFG
, wid_list
,
1109 ARRAY_SIZE(wid_list
));
1111 netdev_err(vif
->ndev
,
1112 "Failed to add wep ap key config packet\n");
1118 int wilc_add_ptk(struct wilc_vif
*vif
, const u8
*ptk
, u8 ptk_key_len
,
1119 const u8
*mac_addr
, const u8
*rx_mic
, const u8
*tx_mic
,
1120 u8 mode
, u8 cipher_mode
, u8 index
)
1123 u8 t_key_len
= ptk_key_len
+ WILC_RX_MIC_KEY_LEN
+ WILC_TX_MIC_KEY_LEN
;
1125 if (mode
== WILC_AP_MODE
) {
1126 struct wid wid_list
[2];
1127 struct wilc_ap_wpa_ptk
*key_buf
;
1129 wid_list
[0].id
= WID_11I_MODE
;
1130 wid_list
[0].type
= WID_CHAR
;
1131 wid_list
[0].size
= sizeof(char);
1132 wid_list
[0].val
= (s8
*)&cipher_mode
;
1134 key_buf
= kzalloc(sizeof(*key_buf
) + t_key_len
, GFP_KERNEL
);
1138 ether_addr_copy(key_buf
->mac_addr
, mac_addr
);
1139 key_buf
->index
= index
;
1140 key_buf
->key_len
= t_key_len
;
1141 memcpy(&key_buf
->key
[0], ptk
, ptk_key_len
);
1144 memcpy(&key_buf
->key
[ptk_key_len
], rx_mic
,
1145 WILC_RX_MIC_KEY_LEN
);
1148 memcpy(&key_buf
->key
[ptk_key_len
+ WILC_RX_MIC_KEY_LEN
],
1149 tx_mic
, WILC_TX_MIC_KEY_LEN
);
1151 wid_list
[1].id
= WID_ADD_PTK
;
1152 wid_list
[1].type
= WID_STR
;
1153 wid_list
[1].size
= sizeof(*key_buf
) + t_key_len
;
1154 wid_list
[1].val
= (u8
*)key_buf
;
1155 result
= wilc_send_config_pkt(vif
, WILC_SET_CFG
, wid_list
,
1156 ARRAY_SIZE(wid_list
));
1158 } else if (mode
== WILC_STATION_MODE
) {
1160 struct wilc_sta_wpa_ptk
*key_buf
;
1162 key_buf
= kzalloc(sizeof(*key_buf
) + t_key_len
, GFP_KERNEL
);
1166 ether_addr_copy(key_buf
->mac_addr
, mac_addr
);
1167 key_buf
->key_len
= t_key_len
;
1168 memcpy(&key_buf
->key
[0], ptk
, ptk_key_len
);
1171 memcpy(&key_buf
->key
[ptk_key_len
], rx_mic
,
1172 WILC_RX_MIC_KEY_LEN
);
1175 memcpy(&key_buf
->key
[ptk_key_len
+ WILC_RX_MIC_KEY_LEN
],
1176 tx_mic
, WILC_TX_MIC_KEY_LEN
);
1178 wid
.id
= WID_ADD_PTK
;
1180 wid
.size
= sizeof(*key_buf
) + t_key_len
;
1181 wid
.val
= (s8
*)key_buf
;
1182 result
= wilc_send_config_pkt(vif
, WILC_SET_CFG
, &wid
, 1);
1189 int wilc_add_rx_gtk(struct wilc_vif
*vif
, const u8
*rx_gtk
, u8 gtk_key_len
,
1190 u8 index
, u32 key_rsc_len
, const u8
*key_rsc
,
1191 const u8
*rx_mic
, const u8
*tx_mic
, u8 mode
,
1195 struct wilc_gtk_key
*gtk_key
;
1196 int t_key_len
= gtk_key_len
+ WILC_RX_MIC_KEY_LEN
+ WILC_TX_MIC_KEY_LEN
;
1198 gtk_key
= kzalloc(sizeof(*gtk_key
) + t_key_len
, GFP_KERNEL
);
1202 /* fill bssid value only in station mode */
1203 if (mode
== WILC_STATION_MODE
&&
1204 vif
->hif_drv
->hif_state
== HOST_IF_CONNECTED
)
1205 memcpy(gtk_key
->mac_addr
, vif
->hif_drv
->assoc_bssid
, ETH_ALEN
);
1208 memcpy(gtk_key
->rsc
, key_rsc
, 8);
1209 gtk_key
->index
= index
;
1210 gtk_key
->key_len
= t_key_len
;
1211 memcpy(>k_key
->key
[0], rx_gtk
, gtk_key_len
);
1214 memcpy(>k_key
->key
[gtk_key_len
], rx_mic
, WILC_RX_MIC_KEY_LEN
);
1217 memcpy(>k_key
->key
[gtk_key_len
+ WILC_RX_MIC_KEY_LEN
],
1218 tx_mic
, WILC_TX_MIC_KEY_LEN
);
1220 if (mode
== WILC_AP_MODE
) {
1221 struct wid wid_list
[2];
1223 wid_list
[0].id
= WID_11I_MODE
;
1224 wid_list
[0].type
= WID_CHAR
;
1225 wid_list
[0].size
= sizeof(char);
1226 wid_list
[0].val
= (s8
*)&cipher_mode
;
1228 wid_list
[1].id
= WID_ADD_RX_GTK
;
1229 wid_list
[1].type
= WID_STR
;
1230 wid_list
[1].size
= sizeof(*gtk_key
) + t_key_len
;
1231 wid_list
[1].val
= (u8
*)gtk_key
;
1233 result
= wilc_send_config_pkt(vif
, WILC_SET_CFG
, wid_list
,
1234 ARRAY_SIZE(wid_list
));
1235 } else if (mode
== WILC_STATION_MODE
) {
1238 wid
.id
= WID_ADD_RX_GTK
;
1240 wid
.size
= sizeof(*gtk_key
) + t_key_len
;
1241 wid
.val
= (u8
*)gtk_key
;
1242 result
= wilc_send_config_pkt(vif
, WILC_SET_CFG
, &wid
, 1);
1249 int wilc_set_pmkid_info(struct wilc_vif
*vif
, struct wilc_pmkid_attr
*pmkid
)
1253 wid
.id
= WID_PMKID_INFO
;
1255 wid
.size
= (pmkid
->numpmkid
* sizeof(struct wilc_pmkid
)) + 1;
1256 wid
.val
= (u8
*)pmkid
;
1258 return wilc_send_config_pkt(vif
, WILC_SET_CFG
, &wid
, 1);
1261 int wilc_get_mac_address(struct wilc_vif
*vif
, u8
*mac_addr
)
1266 wid
.id
= WID_MAC_ADDR
;
1268 wid
.size
= ETH_ALEN
;
1271 result
= wilc_send_config_pkt(vif
, WILC_GET_CFG
, &wid
, 1);
1273 netdev_err(vif
->ndev
, "Failed to get mac address\n");
1278 int wilc_set_join_req(struct wilc_vif
*vif
, u8
*bssid
, const u8
*ies
,
1282 struct host_if_drv
*hif_drv
= vif
->hif_drv
;
1283 struct wilc_conn_info
*conn_info
= &hif_drv
->conn_info
;
1286 ether_addr_copy(conn_info
->bssid
, bssid
);
1289 conn_info
->req_ies_len
= ies_len
;
1290 conn_info
->req_ies
= kmemdup(ies
, ies_len
, GFP_KERNEL
);
1291 if (!conn_info
->req_ies
)
1295 result
= wilc_send_connect_wid(vif
);
1299 hif_drv
->connect_timer_vif
= vif
;
1300 mod_timer(&hif_drv
->connect_timer
,
1301 jiffies
+ msecs_to_jiffies(WILC_HIF_CONNECT_TIMEOUT_MS
));
1306 kfree(conn_info
->req_ies
);
1311 int wilc_set_mac_chnl_num(struct wilc_vif
*vif
, u8 channel
)
1316 wid
.id
= WID_CURRENT_CHANNEL
;
1317 wid
.type
= WID_CHAR
;
1318 wid
.size
= sizeof(char);
1321 result
= wilc_send_config_pkt(vif
, WILC_SET_CFG
, &wid
, 1);
1323 netdev_err(vif
->ndev
, "Failed to set channel\n");
1328 int wilc_set_operation_mode(struct wilc_vif
*vif
, int index
, u8 mode
,
1333 struct wilc_drv_handler drv
;
1335 wid
.id
= WID_SET_OPERATION_MODE
;
1337 wid
.size
= sizeof(drv
);
1338 wid
.val
= (u8
*)&drv
;
1340 drv
.handler
= cpu_to_le32(index
);
1341 drv
.mode
= (ifc_id
| (mode
<< 1));
1343 result
= wilc_send_config_pkt(vif
, WILC_SET_CFG
, &wid
, 1);
1345 netdev_err(vif
->ndev
, "Failed to set driver handler\n");
1350 s32
wilc_get_inactive_time(struct wilc_vif
*vif
, const u8
*mac
, u32
*out_val
)
1355 wid
.id
= WID_SET_STA_MAC_INACTIVE_TIME
;
1357 wid
.size
= ETH_ALEN
;
1358 wid
.val
= kzalloc(wid
.size
, GFP_KERNEL
);
1362 ether_addr_copy(wid
.val
, mac
);
1363 result
= wilc_send_config_pkt(vif
, WILC_SET_CFG
, &wid
, 1);
1366 netdev_err(vif
->ndev
, "Failed to set inactive mac\n");
1370 wid
.id
= WID_GET_INACTIVE_TIME
;
1372 wid
.val
= (s8
*)out_val
;
1373 wid
.size
= sizeof(u32
);
1374 result
= wilc_send_config_pkt(vif
, WILC_GET_CFG
, &wid
, 1);
1376 netdev_err(vif
->ndev
, "Failed to get inactive time\n");
1381 int wilc_get_rssi(struct wilc_vif
*vif
, s8
*rssi_level
)
1387 netdev_err(vif
->ndev
, "%s: RSSI level is NULL\n", __func__
);
1392 wid
.type
= WID_CHAR
;
1393 wid
.size
= sizeof(char);
1394 wid
.val
= rssi_level
;
1395 result
= wilc_send_config_pkt(vif
, WILC_GET_CFG
, &wid
, 1);
1397 netdev_err(vif
->ndev
, "Failed to get RSSI value\n");
1402 static int wilc_get_stats_async(struct wilc_vif
*vif
, struct rf_info
*stats
)
1405 struct host_if_msg
*msg
;
1407 msg
= wilc_alloc_work(vif
, handle_get_statistics
, false);
1409 return PTR_ERR(msg
);
1411 msg
->body
.data
= (char *)stats
;
1413 result
= wilc_enqueue_work(msg
);
1415 netdev_err(vif
->ndev
, "%s: enqueue work failed\n", __func__
);
1423 int wilc_hif_set_cfg(struct wilc_vif
*vif
, struct cfg_param_attr
*param
)
1425 struct wid wid_list
[4];
1428 if (param
->flag
& WILC_CFG_PARAM_RETRY_SHORT
) {
1429 wid_list
[i
].id
= WID_SHORT_RETRY_LIMIT
;
1430 wid_list
[i
].val
= (s8
*)¶m
->short_retry_limit
;
1431 wid_list
[i
].type
= WID_SHORT
;
1432 wid_list
[i
].size
= sizeof(u16
);
1435 if (param
->flag
& WILC_CFG_PARAM_RETRY_LONG
) {
1436 wid_list
[i
].id
= WID_LONG_RETRY_LIMIT
;
1437 wid_list
[i
].val
= (s8
*)¶m
->long_retry_limit
;
1438 wid_list
[i
].type
= WID_SHORT
;
1439 wid_list
[i
].size
= sizeof(u16
);
1442 if (param
->flag
& WILC_CFG_PARAM_FRAG_THRESHOLD
) {
1443 wid_list
[i
].id
= WID_FRAG_THRESHOLD
;
1444 wid_list
[i
].val
= (s8
*)¶m
->frag_threshold
;
1445 wid_list
[i
].type
= WID_SHORT
;
1446 wid_list
[i
].size
= sizeof(u16
);
1449 if (param
->flag
& WILC_CFG_PARAM_RTS_THRESHOLD
) {
1450 wid_list
[i
].id
= WID_RTS_THRESHOLD
;
1451 wid_list
[i
].val
= (s8
*)¶m
->rts_threshold
;
1452 wid_list
[i
].type
= WID_SHORT
;
1453 wid_list
[i
].size
= sizeof(u16
);
1457 return wilc_send_config_pkt(vif
, WILC_SET_CFG
, wid_list
, i
);
1460 static void get_periodic_rssi(struct timer_list
*t
)
1462 struct wilc_vif
*vif
= from_timer(vif
, t
, periodic_rssi
);
1464 if (!vif
->hif_drv
) {
1465 netdev_err(vif
->ndev
, "%s: hif driver is NULL", __func__
);
1469 if (vif
->hif_drv
->hif_state
== HOST_IF_CONNECTED
)
1470 wilc_get_stats_async(vif
, &vif
->periodic_stat
);
1472 mod_timer(&vif
->periodic_rssi
, jiffies
+ msecs_to_jiffies(5000));
1475 int wilc_init(struct net_device
*dev
, struct host_if_drv
**hif_drv_handler
)
1477 struct host_if_drv
*hif_drv
;
1478 struct wilc_vif
*vif
= netdev_priv(dev
);
1479 struct wilc
*wilc
= vif
->wilc
;
1481 hif_drv
= kzalloc(sizeof(*hif_drv
), GFP_KERNEL
);
1485 *hif_drv_handler
= hif_drv
;
1487 vif
->hif_drv
= hif_drv
;
1489 if (wilc
->clients_count
== 0)
1490 mutex_init(&wilc
->deinit_lock
);
1492 timer_setup(&vif
->periodic_rssi
, get_periodic_rssi
, 0);
1493 mod_timer(&vif
->periodic_rssi
, jiffies
+ msecs_to_jiffies(5000));
1495 timer_setup(&hif_drv
->scan_timer
, timer_scan_cb
, 0);
1496 timer_setup(&hif_drv
->connect_timer
, timer_connect_cb
, 0);
1497 timer_setup(&hif_drv
->remain_on_ch_timer
, listen_timer_cb
, 0);
1499 hif_drv
->hif_state
= HOST_IF_IDLE
;
1501 hif_drv
->p2p_timeout
= 0;
1503 wilc
->clients_count
++;
1508 int wilc_deinit(struct wilc_vif
*vif
)
1511 struct host_if_drv
*hif_drv
= vif
->hif_drv
;
1514 netdev_err(vif
->ndev
, "%s: hif driver is NULL", __func__
);
1518 mutex_lock(&vif
->wilc
->deinit_lock
);
1520 del_timer_sync(&hif_drv
->scan_timer
);
1521 del_timer_sync(&hif_drv
->connect_timer
);
1522 del_timer_sync(&vif
->periodic_rssi
);
1523 del_timer_sync(&hif_drv
->remain_on_ch_timer
);
1525 if (hif_drv
->usr_scan_req
.scan_result
) {
1526 hif_drv
->usr_scan_req
.scan_result(SCAN_EVENT_ABORTED
, NULL
,
1527 hif_drv
->usr_scan_req
.arg
);
1528 hif_drv
->usr_scan_req
.scan_result
= NULL
;
1531 hif_drv
->hif_state
= HOST_IF_IDLE
;
1534 vif
->hif_drv
= NULL
;
1535 vif
->wilc
->clients_count
--;
1536 mutex_unlock(&vif
->wilc
->deinit_lock
);
1540 void wilc_network_info_received(struct wilc
*wilc
, u8
*buffer
, u32 length
)
1543 struct host_if_msg
*msg
;
1545 struct host_if_drv
*hif_drv
;
1546 struct wilc_vif
*vif
;
1548 id
= get_unaligned_le32(&buffer
[length
- 4]);
1549 vif
= wilc_get_vif_from_idx(wilc
, id
);
1552 hif_drv
= vif
->hif_drv
;
1555 netdev_err(vif
->ndev
, "driver not init[%p]\n", hif_drv
);
1559 msg
= wilc_alloc_work(vif
, handle_rcvd_ntwrk_info
, false);
1563 msg
->body
.net_info
.frame_len
= get_unaligned_le16(&buffer
[6]) - 1;
1564 msg
->body
.net_info
.rssi
= buffer
[8];
1565 msg
->body
.net_info
.mgmt
= kmemdup(&buffer
[9],
1566 msg
->body
.net_info
.frame_len
,
1568 if (!msg
->body
.net_info
.mgmt
) {
1573 result
= wilc_enqueue_work(msg
);
1575 netdev_err(vif
->ndev
, "%s: enqueue work failed\n", __func__
);
1576 kfree(msg
->body
.net_info
.mgmt
);
1581 void wilc_gnrl_async_info_received(struct wilc
*wilc
, u8
*buffer
, u32 length
)
1584 struct host_if_msg
*msg
;
1586 struct host_if_drv
*hif_drv
;
1587 struct wilc_vif
*vif
;
1589 mutex_lock(&wilc
->deinit_lock
);
1591 id
= get_unaligned_le32(&buffer
[length
- 4]);
1592 vif
= wilc_get_vif_from_idx(wilc
, id
);
1594 mutex_unlock(&wilc
->deinit_lock
);
1598 hif_drv
= vif
->hif_drv
;
1601 mutex_unlock(&wilc
->deinit_lock
);
1605 if (!hif_drv
->conn_info
.conn_result
) {
1606 netdev_err(vif
->ndev
, "%s: conn_result is NULL\n", __func__
);
1607 mutex_unlock(&wilc
->deinit_lock
);
1611 msg
= wilc_alloc_work(vif
, handle_rcvd_gnrl_async_info
, false);
1613 mutex_unlock(&wilc
->deinit_lock
);
1617 msg
->body
.mac_info
.status
= buffer
[7];
1618 result
= wilc_enqueue_work(msg
);
1620 netdev_err(vif
->ndev
, "%s: enqueue work failed\n", __func__
);
1624 mutex_unlock(&wilc
->deinit_lock
);
1627 void wilc_scan_complete_received(struct wilc
*wilc
, u8
*buffer
, u32 length
)
1631 struct host_if_drv
*hif_drv
;
1632 struct wilc_vif
*vif
;
1634 id
= get_unaligned_le32(&buffer
[length
- 4]);
1635 vif
= wilc_get_vif_from_idx(wilc
, id
);
1638 hif_drv
= vif
->hif_drv
;
1643 if (hif_drv
->usr_scan_req
.scan_result
) {
1644 struct host_if_msg
*msg
;
1646 msg
= wilc_alloc_work(vif
, handle_scan_complete
, false);
1650 result
= wilc_enqueue_work(msg
);
1652 netdev_err(vif
->ndev
, "%s: enqueue work failed\n",
1659 int wilc_remain_on_channel(struct wilc_vif
*vif
, u64 cookie
,
1660 u32 duration
, u16 chan
,
1661 void (*expired
)(void *, u64
),
1664 struct wilc_remain_ch roc
;
1668 roc
.expired
= expired
;
1670 roc
.duration
= duration
;
1671 roc
.cookie
= cookie
;
1672 result
= handle_remain_on_chan(vif
, &roc
);
1674 netdev_err(vif
->ndev
, "%s: failed to set remain on channel\n",
1680 int wilc_listen_state_expired(struct wilc_vif
*vif
, u64 cookie
)
1682 if (!vif
->hif_drv
) {
1683 netdev_err(vif
->ndev
, "%s: hif driver is NULL", __func__
);
1687 del_timer(&vif
->hif_drv
->remain_on_ch_timer
);
1689 return wilc_handle_roc_expired(vif
, cookie
);
1692 void wilc_frame_register(struct wilc_vif
*vif
, u16 frame_type
, bool reg
)
1696 struct wilc_reg_frame reg_frame
;
1698 wid
.id
= WID_REGISTER_FRAME
;
1700 wid
.size
= sizeof(reg_frame
);
1701 wid
.val
= (u8
*)®_frame
;
1703 memset(®_frame
, 0x0, sizeof(reg_frame
));
1708 switch (frame_type
) {
1709 case IEEE80211_STYPE_ACTION
:
1710 reg_frame
.reg_id
= WILC_FW_ACTION_FRM_IDX
;
1713 case IEEE80211_STYPE_PROBE_REQ
:
1714 reg_frame
.reg_id
= WILC_FW_PROBE_REQ_IDX
;
1720 reg_frame
.frame_type
= cpu_to_le16(frame_type
);
1721 result
= wilc_send_config_pkt(vif
, WILC_SET_CFG
, &wid
, 1);
1723 netdev_err(vif
->ndev
, "Failed to frame register\n");
1726 int wilc_add_beacon(struct wilc_vif
*vif
, u32 interval
, u32 dtim_period
,
1727 struct cfg80211_beacon_data
*params
)
1733 wid
.id
= WID_ADD_BEACON
;
1735 wid
.size
= params
->head_len
+ params
->tail_len
+ 16;
1736 wid
.val
= kzalloc(wid
.size
, GFP_KERNEL
);
1741 put_unaligned_le32(interval
, cur_byte
);
1743 put_unaligned_le32(dtim_period
, cur_byte
);
1745 put_unaligned_le32(params
->head_len
, cur_byte
);
1748 if (params
->head_len
> 0)
1749 memcpy(cur_byte
, params
->head
, params
->head_len
);
1750 cur_byte
+= params
->head_len
;
1752 put_unaligned_le32(params
->tail_len
, cur_byte
);
1755 if (params
->tail_len
> 0)
1756 memcpy(cur_byte
, params
->tail
, params
->tail_len
);
1758 result
= wilc_send_config_pkt(vif
, WILC_SET_CFG
, &wid
, 1);
1760 netdev_err(vif
->ndev
, "Failed to send add beacon\n");
1767 int wilc_del_beacon(struct wilc_vif
*vif
)
1773 wid
.id
= WID_DEL_BEACON
;
1774 wid
.type
= WID_CHAR
;
1775 wid
.size
= sizeof(char);
1776 wid
.val
= &del_beacon
;
1778 result
= wilc_send_config_pkt(vif
, WILC_SET_CFG
, &wid
, 1);
1780 netdev_err(vif
->ndev
, "Failed to send delete beacon\n");
1785 int wilc_add_station(struct wilc_vif
*vif
, const u8
*mac
,
1786 struct station_parameters
*params
)
1792 wid
.id
= WID_ADD_STA
;
1794 wid
.size
= WILC_ADD_STA_LENGTH
+ params
->supported_rates_len
;
1795 wid
.val
= kmalloc(wid
.size
, GFP_KERNEL
);
1800 wilc_hif_pack_sta_param(cur_byte
, mac
, params
);
1802 result
= wilc_send_config_pkt(vif
, WILC_SET_CFG
, &wid
, 1);
1804 netdev_err(vif
->ndev
, "Failed to send add station\n");
1811 int wilc_del_station(struct wilc_vif
*vif
, const u8
*mac_addr
)
1816 wid
.id
= WID_REMOVE_STA
;
1818 wid
.size
= ETH_ALEN
;
1819 wid
.val
= kzalloc(wid
.size
, GFP_KERNEL
);
1824 eth_broadcast_addr(wid
.val
);
1826 ether_addr_copy(wid
.val
, mac_addr
);
1828 result
= wilc_send_config_pkt(vif
, WILC_SET_CFG
, &wid
, 1);
1830 netdev_err(vif
->ndev
, "Failed to del station\n");
1837 int wilc_del_allstation(struct wilc_vif
*vif
, u8 mac_addr
[][ETH_ALEN
])
1843 struct wilc_del_all_sta del_sta
;
1845 memset(&del_sta
, 0x0, sizeof(del_sta
));
1846 for (i
= 0; i
< WILC_MAX_NUM_STA
; i
++) {
1847 if (!is_zero_ether_addr(mac_addr
[i
])) {
1849 ether_addr_copy(del_sta
.mac
[i
], mac_addr
[i
]);
1856 del_sta
.assoc_sta
= assoc_sta
;
1858 wid
.id
= WID_DEL_ALL_STA
;
1860 wid
.size
= (assoc_sta
* ETH_ALEN
) + 1;
1861 wid
.val
= (u8
*)&del_sta
;
1863 result
= wilc_send_config_pkt(vif
, WILC_SET_CFG
, &wid
, 1);
1865 netdev_err(vif
->ndev
, "Failed to send delete all station\n");
1870 int wilc_edit_station(struct wilc_vif
*vif
, const u8
*mac
,
1871 struct station_parameters
*params
)
1877 wid
.id
= WID_EDIT_STA
;
1879 wid
.size
= WILC_ADD_STA_LENGTH
+ params
->supported_rates_len
;
1880 wid
.val
= kmalloc(wid
.size
, GFP_KERNEL
);
1885 wilc_hif_pack_sta_param(cur_byte
, mac
, params
);
1887 result
= wilc_send_config_pkt(vif
, WILC_SET_CFG
, &wid
, 1);
1889 netdev_err(vif
->ndev
, "Failed to send edit station\n");
1895 int wilc_set_power_mgmt(struct wilc_vif
*vif
, bool enabled
, u32 timeout
)
1902 power_mode
= WILC_FW_MIN_FAST_PS
;
1904 power_mode
= WILC_FW_NO_POWERSAVE
;
1906 wid
.id
= WID_POWER_MANAGEMENT
;
1907 wid
.val
= &power_mode
;
1908 wid
.size
= sizeof(char);
1909 result
= wilc_send_config_pkt(vif
, WILC_SET_CFG
, &wid
, 1);
1911 netdev_err(vif
->ndev
, "Failed to send power management\n");
1916 int wilc_setup_multicast_filter(struct wilc_vif
*vif
, u32 enabled
, u32 count
,
1920 struct host_if_msg
*msg
;
1922 msg
= wilc_alloc_work(vif
, handle_set_mcast_filter
, false);
1924 return PTR_ERR(msg
);
1926 msg
->body
.mc_info
.enabled
= enabled
;
1927 msg
->body
.mc_info
.cnt
= count
;
1928 msg
->body
.mc_info
.mc_list
= mc_list
;
1930 result
= wilc_enqueue_work(msg
);
1932 netdev_err(vif
->ndev
, "%s: enqueue work failed\n", __func__
);
1938 int wilc_set_tx_power(struct wilc_vif
*vif
, u8 tx_power
)
1942 wid
.id
= WID_TX_POWER
;
1943 wid
.type
= WID_CHAR
;
1944 wid
.val
= &tx_power
;
1945 wid
.size
= sizeof(char);
1947 return wilc_send_config_pkt(vif
, WILC_SET_CFG
, &wid
, 1);
1950 int wilc_get_tx_power(struct wilc_vif
*vif
, u8
*tx_power
)
1954 wid
.id
= WID_TX_POWER
;
1955 wid
.type
= WID_CHAR
;
1957 wid
.size
= sizeof(char);
1959 return wilc_send_config_pkt(vif
, WILC_GET_CFG
, &wid
, 1);