]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/blame - drivers/staging/wilc1000/host_interface.c
staging: wilc1000: handle_cfg_param: rename wid_cnt
[mirror_ubuntu-hirsute-kernel.git] / drivers / staging / wilc1000 / host_interface.c
CommitLineData
e215a871
CL
1#include <linux/slab.h>
2#include <linux/time.h>
3#include <linux/kthread.h>
4#include <linux/delay.h>
c5c77ba1 5#include "host_interface.h"
c5c77ba1 6#include "coreconfigurator.h"
491880eb 7#include "wilc_wlan.h"
5366012d 8#include "wilc_wlan_if.h"
f23eb98b 9#include "wilc_msgqueue.h"
281dd5ac 10#include <linux/etherdevice.h>
d5382219 11#include "wilc_wfi_netdevice.h"
c5c77ba1 12
9eac3a15
CL
13#define HOST_IF_MSG_SCAN 0
14#define HOST_IF_MSG_CONNECT 1
15#define HOST_IF_MSG_RCVD_GNRL_ASYNC_INFO 2
16#define HOST_IF_MSG_KEY 3
17#define HOST_IF_MSG_RCVD_NTWRK_INFO 4
18#define HOST_IF_MSG_RCVD_SCAN_COMPLETE 5
19#define HOST_IF_MSG_CFG_PARAMS 6
20#define HOST_IF_MSG_SET_CHANNEL 7
21#define HOST_IF_MSG_DISCONNECT 8
22#define HOST_IF_MSG_GET_RSSI 9
23#define HOST_IF_MSG_GET_CHNL 10
24#define HOST_IF_MSG_ADD_BEACON 11
25#define HOST_IF_MSG_DEL_BEACON 12
26#define HOST_IF_MSG_ADD_STATION 13
27#define HOST_IF_MSG_DEL_STATION 14
28#define HOST_IF_MSG_EDIT_STATION 15
29#define HOST_IF_MSG_SCAN_TIMER_FIRED 16
30#define HOST_IF_MSG_CONNECT_TIMER_FIRED 17
31#define HOST_IF_MSG_POWER_MGMT 18
32#define HOST_IF_MSG_GET_INACTIVETIME 19
33#define HOST_IF_MSG_REMAIN_ON_CHAN 20
34#define HOST_IF_MSG_REGISTER_FRAME 21
35#define HOST_IF_MSG_LISTEN_TIMER_FIRED 22
36#define HOST_IF_MSG_GET_LINKSPEED 23
37#define HOST_IF_MSG_SET_WFIDRV_HANDLER 24
38#define HOST_IF_MSG_SET_MAC_ADDRESS 25
39#define HOST_IF_MSG_GET_MAC_ADDRESS 26
40#define HOST_IF_MSG_SET_OPERATION_MODE 27
41#define HOST_IF_MSG_SET_IPADDRESS 28
42#define HOST_IF_MSG_GET_IPADDRESS 29
43#define HOST_IF_MSG_FLUSH_CONNECT 30
44#define HOST_IF_MSG_GET_STATISTICS 31
45#define HOST_IF_MSG_SET_MULTICAST_FILTER 32
9eac3a15
CL
46#define HOST_IF_MSG_DEL_BA_SESSION 34
47#define HOST_IF_MSG_Q_IDLE 35
48#define HOST_IF_MSG_DEL_ALL_STA 36
70418790
GL
49#define HOST_IF_MSG_DEL_ALL_RX_BA_SESSIONS 37
50#define HOST_IF_MSG_SET_TX_POWER 38
51#define HOST_IF_MSG_GET_TX_POWER 39
9eac3a15 52#define HOST_IF_MSG_EXIT 100
d85f5326 53
e54d5b75
CL
54#define HOST_IF_SCAN_TIMEOUT 4000
55#define HOST_IF_CONNECT_TIMEOUT 9500
c5c77ba1 56
e54d5b75
CL
57#define BA_SESSION_DEFAULT_BUFFER_SIZE 16
58#define BA_SESSION_DEFAULT_TIMEOUT 1000
59#define BLOCK_ACK_REQ_SIZE 0x14
9f3295a2 60#define FALSE_FRMWR_CHANNEL 100
c5c77ba1 61
4fd62291
GL
62#define TCP_ACK_FILTER_LINK_SPEED_THRESH 54
63#define DEFAULT_LINK_SPEED 72
64
4372d3d3 65struct host_if_wpa_attr {
124968fc 66 u8 *key;
248080aa 67 const u8 *mac_addr;
0e74c009 68 u8 *seq;
dacc594d 69 u8 seq_len;
e2dfbac5 70 u8 index;
6acf2919 71 u8 key_len;
7b2ebb28 72 u8 mode;
4372d3d3 73};
c5c77ba1 74
c276c44a 75struct host_if_wep_attr {
e5538d34 76 u8 *key;
d520e355 77 u8 key_len;
259b3aa6 78 u8 index;
b5eaff12 79 u8 mode;
7fa252e7 80 enum AUTHTYPE auth_type;
c276c44a 81};
c5c77ba1 82
40cc2c90 83union host_if_key_attr {
2ed7a2fb 84 struct host_if_wep_attr wep;
e3501a4d 85 struct host_if_wpa_attr wpa;
610e3868 86 struct host_if_pmkid_attr pmkid;
40cc2c90 87};
c5c77ba1 88
c98387a5 89struct key_attr {
8e9f427a 90 enum KEY_TYPE type;
0d17e382 91 u8 action;
73b2e381 92 union host_if_key_attr attr;
c98387a5 93};
c5c77ba1 94
c476feb8 95struct scan_attr {
42568898 96 u8 src;
1e276c88 97 u8 type;
82eeb0ad 98 u8 *ch_freq_list;
f97bd9ca 99 u8 ch_list_len;
d6f19aa5 100 u8 *ies;
7b1f76cd 101 size_t ies_len;
c17c6da6 102 wilc_scan_result result;
5f2b50c8 103 void *arg;
629b9ca0 104 struct hidden_network hidden_network;
c476feb8 105};
c5c77ba1 106
120ae593 107struct connect_attr {
9254db07 108 u8 *bssid;
f7bbd9cf 109 u8 *ssid;
8b3c9fa6 110 size_t ssid_len;
2ea158c4 111 u8 *ies;
b59d5c5b 112 size_t ies_len;
a64fd677 113 u8 security;
6abcc11d 114 wilc_connect_result result;
8f38db89 115 void *arg;
61b4fd02 116 enum AUTHTYPE auth_type;
0d1527e6 117 u8 ch;
f2bed2ca 118 void *params;
120ae593 119};
c5c77ba1 120
f23a9eab 121struct rcvd_async_info {
33722ac7 122 u8 *buffer;
f94f4889 123 u32 len;
f23a9eab 124};
c5c77ba1 125
94bdfe42 126struct channel_attr {
730ee059 127 u8 set_ch;
326b323d 128};
c5c77ba1 129
7f33fecd 130struct beacon_attr {
12262dda 131 u32 interval;
e76ab770 132 u32 dtim_period;
51c66185 133 u32 head_len;
8ce528b9 134 u8 *head;
030c57e2 135 u32 tail_len;
7dbcb6d3 136 u8 *tail;
902362b1 137};
c5c77ba1 138
641210ac 139struct set_multicast {
bae636eb 140 bool enabled;
adab2f71 141 u32 cnt;
641210ac 142};
c5c77ba1 143
b4e644e4 144struct del_all_sta {
e51b9216 145 u8 del_all_sta[MAX_NUM_STA][ETH_ALEN];
8ba1803f 146 u8 assoc_sta;
b4e644e4 147};
c5c77ba1 148
fb93a1e1 149struct del_sta {
e4839d39 150 u8 mac_addr[ETH_ALEN];
fb93a1e1 151};
c5c77ba1 152
5a008f1c 153struct power_mgmt_param {
33c70c1b 154 bool enabled;
937918ff 155 u32 timeout;
5a008f1c 156};
c5c77ba1 157
15191eaf 158struct set_ip_addr {
78675be5 159 u8 *ip_addr;
63d03e47 160 u8 idx;
15191eaf 161};
c5c77ba1 162
3d1eac04 163struct sta_inactive_t {
63d03e47 164 u8 mac[6];
3d1eac04 165};
ae4dfa57 166
70418790
GL
167struct tx_power {
168 u8 tx_pwr;
169};
170
dfc7663b 171union message_body {
4528bdb5 172 struct scan_attr scan_info;
3f501971 173 struct connect_attr con_info;
02d19460 174 struct rcvd_net_info net_info;
66add622 175 struct rcvd_async_info async_info;
18990bfe 176 struct key_attr key_info;
a2340c36 177 struct cfg_param_attr cfg_info;
ffd6dbc8 178 struct channel_attr channel_info;
a98491e5 179 struct beacon_attr beacon_info;
ca8f47f8 180 struct add_sta_param add_sta_info;
889c25be 181 struct del_sta del_sta_info;
4a930962 182 struct add_sta_param edit_sta_info;
49e1f81b 183 struct power_mgmt_param pwr_mgmt_info;
66bac7f2 184 struct sta_inactive_t mac_info;
fb2d65ed 185 struct set_ip_addr ip_info;
5e4377e6 186 struct drv_handler drv;
a079cf4d 187 struct set_multicast multicast_info;
00c4630e 188 struct op_mode mode;
15326e28 189 struct set_mac_addr set_mac_info;
a5848695 190 struct get_mac_addr get_mac_info;
c833b474 191 struct ba_session_info session_info;
070d365c 192 struct remain_ch remain_on_ch;
5c4008db 193 struct reg_frame reg_frame;
e60831e9 194 char *data;
b0c1e80e 195 struct del_all_sta del_all_sta_info;
70418790 196 struct tx_power tx_power;
dfc7663b 197};
c5c77ba1 198
3a8c41b5 199struct host_if_msg {
ae4dfa57
LK
200 u16 id;
201 union message_body body;
cf60106b 202 struct wilc_vif *vif;
3a8c41b5 203};
c5c77ba1 204
e0a12217 205struct join_bss_param {
c5c77ba1 206 BSSTYPE_T bss_type;
63d03e47 207 u8 dtim_period;
d85f5326
CL
208 u16 beacon_period;
209 u16 cap_info;
f1764293 210 u8 bssid[6];
576917ad 211 char ssid[MAX_SSID_LEN];
619d27b8 212 u8 ssid_len;
63d03e47
GKH
213 u8 supp_rates[MAX_RATES_SUPPORTED + 1];
214 u8 ht_capable;
215 u8 wmm_cap;
216 u8 uapsd_cap;
72ed4dc7 217 bool rsn_found;
63d03e47
GKH
218 u8 rsn_grp_policy;
219 u8 mode_802_11i;
220 u8 rsn_pcip_policy[3];
221 u8 rsn_auth_policy[3];
222 u8 rsn_cap[2];
4e4467fd 223 u32 tsf;
7a8d51d7 224 u8 noa_enabled;
d72b33ca 225 u8 opp_enabled;
99b66945 226 u8 ct_window;
c21047ed 227 u8 cnt;
cc179008 228 u8 idx;
109e6cab 229 u8 duration[4];
1d8b76b3 230 u8 interval[4];
4be55e22 231 u8 start_time[4];
e0a12217 232};
c5c77ba1 233
d27afda3 234static struct host_if_drv *terminated_handle;
0e1af73d 235bool wilc_optaining_ip;
1608c403 236static u8 P2P_LISTEN_STATE;
c2115d8e 237static struct task_struct *hif_thread_handler;
5ba89554 238static struct message_queue hif_msg_q;
834e0cb0 239static struct semaphore hif_sema_thread;
413f930e 240static struct semaphore hif_sema_driver;
2d25af87 241static struct semaphore hif_sema_wait_response;
17225002 242static struct semaphore hif_sema_deinit;
24aadb8b 243static struct timer_list periodic_rssi;
c5c77ba1 244
0e1af73d 245u8 wilc_multicast_mac_addr_list[WILC_MULTICAST_TABLE_SIZE][ETH_ALEN];
c5c77ba1 246
a633c0b5 247static u8 rcv_assoc_resp[MAX_ASSOC_RESP_FRAME_SIZE];
c5c77ba1 248
f64321c6 249static bool scan_while_connected;
c5c77ba1 250
144b7b23 251static s8 rssi;
75327a02 252static s8 link_speed;
95ebb0ff 253static u8 ch_no;
078b1e98 254static u8 set_ip[2][4];
1e75d01c 255static u8 get_ip[2][4];
ad26906f 256static u32 inactive_time;
a74c7bf8 257static u8 del_beacon;
7178aed8 258static u32 clients_count;
c5c77ba1 259
ef599194 260static u8 *join_req;
1608c403 261static u8 *info_element;
23047d5b 262static u8 mode_11i;
1608c403
AB
263static u8 auth_type;
264static u32 join_req_size;
5e0e7c2e 265static u32 info_element_size;
7036c624 266static struct wilc_vif *join_req_vif;
c5c77ba1
JK
267#define REAL_JOIN_REQ 0
268#define FLUSHED_JOIN_REQ 1
ae4dfa57 269#define FLUSHED_BYTE_POS 79
c5c77ba1 270
6b5180a0 271static void *host_int_ParseJoinBssParam(struct network_info *ptstrNetworkInfo);
4ad878be 272static int host_int_get_ipaddress(struct wilc_vif *vif, u8 *ip_addr, u8 idx);
c5c77ba1 273
eb9939b7
GL
274/* The u8IfIdx starts from 0 to NUM_CONCURRENT_IFC -1, but 0 index used as
275 * special purpose in wilc device, so we add 1 to the index to starts from 1.
276 * As a result, the returned index will be 1 to NUM_CONCURRENT_IFC.
277 */
31f0f697 278int wilc_get_vif_idx(struct wilc_vif *vif)
d42ab083 279{
6750140d 280 return vif->idx + 1;
eb9939b7
GL
281}
282
283/* We need to minus 1 from idx which is from wilc device to get real index
284 * of wilc->vif[], because we add 1 when pass to wilc device in the function
285 * wilc_get_vif_idx.
286 * As a result, the index should be between 0 and NUM_CONCURRENT_IFC -1.
287 */
288static struct wilc_vif *wilc_get_vif_from_idx(struct wilc *wilc, int idx)
289{
290 int index = idx - 1;
291
292 if (index < 0 || index >= NUM_CONCURRENT_IFC)
d42ab083 293 return NULL;
eb9939b7
GL
294
295 return wilc->vif[index];
d42ab083
JK
296}
297
c43f5f9d
CL
298static void handle_set_channel(struct wilc_vif *vif,
299 struct channel_attr *hif_set_ch)
c5c77ba1 300{
5349f6da 301 int ret = 0;
45102f83 302 struct wid wid;
c5c77ba1 303
45102f83
LK
304 wid.id = (u16)WID_CURRENT_CHANNEL;
305 wid.type = WID_CHAR;
9cf7878c 306 wid.val = (char *)&hif_set_ch->set_ch;
45102f83 307 wid.size = sizeof(char);
c5c77ba1 308
5349f6da
CL
309 ret = wilc_send_config_pkt(vif, SET_CFG, &wid, 1,
310 wilc_get_vif_idx(vif));
31390eec 311
5349f6da 312 if (ret)
ecdd5c74 313 netdev_err(vif->ndev, "Failed to set channel\n");
c5c77ba1 314}
ae4dfa57 315
71130e81 316static s32 handle_set_wfi_drv_handler(struct wilc_vif *vif,
23f2badd 317 struct drv_handler *hif_drv_handler)
c5c77ba1 318{
31390eec 319 s32 result = 0;
45102f83 320 struct wid wid;
c5c77ba1 321
45102f83 322 wid.id = (u16)WID_SET_DRV_HANDLER;
b3306865
GL
323 wid.type = WID_STR;
324 wid.val = (s8 *)hif_drv_handler;
325 wid.size = sizeof(*hif_drv_handler);
c5c77ba1 326
79df6a49 327 result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1,
ec62e6d1 328 hif_drv_handler->handler);
c5c77ba1 329
31f0f697 330 if (!hif_drv_handler->handler)
27ff2168 331 up(&hif_sema_driver);
c5c77ba1 332
31390eec 333 if (result) {
b92f9304 334 netdev_err(vif->ndev, "Failed to set driver handler\n");
24db713f 335 return -EINVAL;
c5c77ba1
JK
336 }
337
31390eec 338 return result;
c5c77ba1
JK
339}
340
71130e81 341static s32 handle_set_operation_mode(struct wilc_vif *vif,
97b5c591 342 struct op_mode *hif_op_mode)
c5c77ba1 343{
31390eec 344 s32 result = 0;
45102f83 345 struct wid wid;
c5c77ba1 346
45102f83
LK
347 wid.id = (u16)WID_SET_OPERATION_MODE;
348 wid.type = WID_INT;
acff1d71 349 wid.val = (s8 *)&hif_op_mode->mode;
45102f83 350 wid.size = sizeof(u32);
c5c77ba1 351
79df6a49 352 result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1,
4cf93d70 353 wilc_get_vif_idx(vif));
c5c77ba1 354
acff1d71 355 if ((hif_op_mode->mode) == IDLE_MODE)
27ff2168 356 up(&hif_sema_driver);
c5c77ba1 357
31390eec 358 if (result) {
b92f9304 359 netdev_err(vif->ndev, "Failed to set driver handler\n");
24db713f 360 return -EINVAL;
c5c77ba1
JK
361 }
362
31390eec 363 return result;
c5c77ba1
JK
364}
365
71130e81 366static s32 handle_set_ip_address(struct wilc_vif *vif, u8 *ip_addr, u8 idx)
c5c77ba1 367{
31390eec 368 s32 result = 0;
45102f83 369 struct wid wid;
ebc57d19 370 char firmware_ip_addr[4] = {0};
c5c77ba1 371
a6527c3b
LK
372 if (ip_addr[0] < 192)
373 ip_addr[0] = 0;
c5c77ba1 374
a6527c3b 375 memcpy(set_ip[idx], ip_addr, IP_ALEN);
c5c77ba1 376
45102f83
LK
377 wid.id = (u16)WID_IP_ADDRESS;
378 wid.type = WID_STR;
a6527c3b 379 wid.val = (u8 *)ip_addr;
45102f83 380 wid.size = IP_ALEN;
c5c77ba1 381
79df6a49 382 result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1,
4cf93d70 383 wilc_get_vif_idx(vif));
c5c77ba1 384
f8813d3a 385 host_int_get_ipaddress(vif, firmware_ip_addr, idx);
c5c77ba1 386
31390eec 387 if (result) {
b92f9304 388 netdev_err(vif->ndev, "Failed to set IP address\n");
24db713f 389 return -EINVAL;
c5c77ba1
JK
390 }
391
31390eec 392 return result;
c5c77ba1
JK
393}
394
71130e81 395static s32 handle_get_ip_address(struct wilc_vif *vif, u8 idx)
c5c77ba1 396{
31390eec 397 s32 result = 0;
45102f83 398 struct wid wid;
c5c77ba1 399
45102f83
LK
400 wid.id = (u16)WID_IP_ADDRESS;
401 wid.type = WID_STR;
402 wid.val = kmalloc(IP_ALEN, GFP_KERNEL);
403 wid.size = IP_ALEN;
c5c77ba1 404
79df6a49 405 result = wilc_send_config_pkt(vif, GET_CFG, &wid, 1,
4cf93d70 406 wilc_get_vif_idx(vif));
c5c77ba1 407
45102f83 408 memcpy(get_ip[idx], wid.val, IP_ALEN);
c5c77ba1 409
45102f83 410 kfree(wid.val);
c5c77ba1 411
1e75d01c 412 if (memcmp(get_ip[idx], set_ip[idx], IP_ALEN) != 0)
fbf5379b 413 wilc_setup_ipaddress(vif, set_ip[idx], idx);
c5c77ba1 414
31390eec 415 if (result != 0) {
b92f9304 416 netdev_err(vif->ndev, "Failed to get IP address\n");
24db713f 417 return -EINVAL;
c5c77ba1
JK
418 }
419
31390eec 420 return result;
c5c77ba1
JK
421}
422
157edcca
CL
423static void handle_set_mac_address(struct wilc_vif *vif,
424 struct set_mac_addr *set_mac_addr)
c5c77ba1 425{
47b89ad6 426 int ret = 0;
45102f83 427 struct wid wid;
3027eafd 428 u8 *mac_buf;
c09389ac 429
3027eafd 430 mac_buf = kmemdup(set_mac_addr->mac_addr, ETH_ALEN, GFP_KERNEL);
b713ce0e 431 if (!mac_buf)
157edcca 432 return;
b713ce0e 433
45102f83
LK
434 wid.id = (u16)WID_MAC_ADDR;
435 wid.type = WID_STR;
436 wid.val = mac_buf;
437 wid.size = ETH_ALEN;
ae4dfa57 438
47b89ad6
CL
439 ret = wilc_send_config_pkt(vif, SET_CFG, &wid, 1,
440 wilc_get_vif_idx(vif));
441 if (ret)
9eab9a8f 442 netdev_err(vif->ndev, "Failed to set mac address\n");
c5c77ba1 443
49188af2 444 kfree(mac_buf);
c5c77ba1
JK
445}
446
71130e81 447static s32 handle_get_mac_address(struct wilc_vif *vif,
b3bf8fd9 448 struct get_mac_addr *get_mac_addr)
c5c77ba1 449{
31390eec 450 s32 result = 0;
45102f83 451 struct wid wid;
c5c77ba1 452
45102f83
LK
453 wid.id = (u16)WID_MAC_ADDR;
454 wid.type = WID_STR;
7f0ee9a6 455 wid.val = get_mac_addr->mac_addr;
45102f83 456 wid.size = ETH_ALEN;
c5c77ba1 457
79df6a49 458 result = wilc_send_config_pkt(vif, GET_CFG, &wid, 1,
4cf93d70 459 wilc_get_vif_idx(vif));
31390eec
LK
460
461 if (result) {
b92f9304 462 netdev_err(vif->ndev, "Failed to get mac address\n");
31390eec 463 result = -EFAULT;
c5c77ba1 464 }
2d25af87 465 up(&hif_sema_wait_response);
c5c77ba1 466
31390eec 467 return result;
c5c77ba1
JK
468}
469
71130e81 470static s32 handle_cfg_param(struct wilc_vif *vif,
dc276664 471 struct cfg_param_attr *cfg_param_attr)
c5c77ba1 472{
31390eec 473 s32 result = 0;
13ca52ad 474 struct wid wid_list[32];
71130e81 475 struct host_if_drv *hif_drv = vif->hif_drv;
44a4db1d 476 int i = 0;
c5c77ba1 477
33110ad7 478 down(&hif_drv->sem_cfg_values);
c5c77ba1 479
a5f0fb5c
CL
480 if (cfg_param_attr->flag & BSS_TYPE) {
481 if (cfg_param_attr->bss_type < 6) {
44a4db1d
CL
482 wid_list[i].id = WID_BSS_TYPE;
483 wid_list[i].val = (s8 *)&cfg_param_attr->bss_type;
484 wid_list[i].type = WID_CHAR;
485 wid_list[i].size = sizeof(char);
a5f0fb5c 486 hif_drv->cfg_values.bss_type = (u8)cfg_param_attr->bss_type;
c5c77ba1 487 } else {
b92f9304 488 netdev_err(vif->ndev, "check value 6 over\n");
31390eec 489 result = -EINVAL;
24db713f 490 goto ERRORHANDLER;
c5c77ba1 491 }
44a4db1d 492 i++;
c5c77ba1 493 }
a5f0fb5c
CL
494 if (cfg_param_attr->flag & AUTH_TYPE) {
495 if (cfg_param_attr->auth_type == 1 ||
496 cfg_param_attr->auth_type == 2 ||
497 cfg_param_attr->auth_type == 5) {
44a4db1d
CL
498 wid_list[i].id = WID_AUTH_TYPE;
499 wid_list[i].val = (s8 *)&cfg_param_attr->auth_type;
500 wid_list[i].type = WID_CHAR;
501 wid_list[i].size = sizeof(char);
a5f0fb5c 502 hif_drv->cfg_values.auth_type = (u8)cfg_param_attr->auth_type;
c5c77ba1 503 } else {
b92f9304 504 netdev_err(vif->ndev, "Impossible value \n");
31390eec 505 result = -EINVAL;
24db713f 506 goto ERRORHANDLER;
c5c77ba1 507 }
44a4db1d 508 i++;
c5c77ba1 509 }
a5f0fb5c
CL
510 if (cfg_param_attr->flag & AUTHEN_TIMEOUT) {
511 if (cfg_param_attr->auth_timeout > 0 &&
512 cfg_param_attr->auth_timeout < 65536) {
44a4db1d
CL
513 wid_list[i].id = WID_AUTH_TIMEOUT;
514 wid_list[i].val = (s8 *)&cfg_param_attr->auth_timeout;
515 wid_list[i].type = WID_SHORT;
516 wid_list[i].size = sizeof(u16);
a5f0fb5c 517 hif_drv->cfg_values.auth_timeout = cfg_param_attr->auth_timeout;
c5c77ba1 518 } else {
b92f9304 519 netdev_err(vif->ndev, "Range(1 ~ 65535) over\n");
31390eec 520 result = -EINVAL;
24db713f 521 goto ERRORHANDLER;
c5c77ba1 522 }
44a4db1d 523 i++;
c5c77ba1 524 }
a5f0fb5c
CL
525 if (cfg_param_attr->flag & POWER_MANAGEMENT) {
526 if (cfg_param_attr->power_mgmt_mode < 5) {
44a4db1d
CL
527 wid_list[i].id = WID_POWER_MANAGEMENT;
528 wid_list[i].val = (s8 *)&cfg_param_attr->power_mgmt_mode;
529 wid_list[i].type = WID_CHAR;
530 wid_list[i].size = sizeof(char);
a5f0fb5c 531 hif_drv->cfg_values.power_mgmt_mode = (u8)cfg_param_attr->power_mgmt_mode;
c5c77ba1 532 } else {
b92f9304 533 netdev_err(vif->ndev, "Invalid power mode\n");
31390eec 534 result = -EINVAL;
24db713f 535 goto ERRORHANDLER;
c5c77ba1 536 }
44a4db1d 537 i++;
c5c77ba1 538 }
a5f0fb5c
CL
539 if (cfg_param_attr->flag & RETRY_SHORT) {
540 if (cfg_param_attr->short_retry_limit > 0 &&
541 cfg_param_attr->short_retry_limit < 256) {
44a4db1d
CL
542 wid_list[i].id = WID_SHORT_RETRY_LIMIT;
543 wid_list[i].val = (s8 *)&cfg_param_attr->short_retry_limit;
544 wid_list[i].type = WID_SHORT;
545 wid_list[i].size = sizeof(u16);
a5f0fb5c 546 hif_drv->cfg_values.short_retry_limit = cfg_param_attr->short_retry_limit;
c5c77ba1 547 } else {
b92f9304 548 netdev_err(vif->ndev, "Range(1~256) over\n");
31390eec 549 result = -EINVAL;
24db713f 550 goto ERRORHANDLER;
c5c77ba1 551 }
44a4db1d 552 i++;
c5c77ba1 553 }
a5f0fb5c
CL
554 if (cfg_param_attr->flag & RETRY_LONG) {
555 if (cfg_param_attr->long_retry_limit > 0 &&
556 cfg_param_attr->long_retry_limit < 256) {
44a4db1d
CL
557 wid_list[i].id = WID_LONG_RETRY_LIMIT;
558 wid_list[i].val = (s8 *)&cfg_param_attr->long_retry_limit;
559 wid_list[i].type = WID_SHORT;
560 wid_list[i].size = sizeof(u16);
a5f0fb5c 561 hif_drv->cfg_values.long_retry_limit = cfg_param_attr->long_retry_limit;
c5c77ba1 562 } else {
b92f9304 563 netdev_err(vif->ndev, "Range(1~256) over\n");
31390eec 564 result = -EINVAL;
24db713f 565 goto ERRORHANDLER;
c5c77ba1 566 }
44a4db1d 567 i++;
c5c77ba1 568 }
a5f0fb5c
CL
569 if (cfg_param_attr->flag & FRAG_THRESHOLD) {
570 if (cfg_param_attr->frag_threshold > 255 &&
571 cfg_param_attr->frag_threshold < 7937) {
44a4db1d
CL
572 wid_list[i].id = WID_FRAG_THRESHOLD;
573 wid_list[i].val = (s8 *)&cfg_param_attr->frag_threshold;
574 wid_list[i].type = WID_SHORT;
575 wid_list[i].size = sizeof(u16);
a5f0fb5c 576 hif_drv->cfg_values.frag_threshold = cfg_param_attr->frag_threshold;
c5c77ba1 577 } else {
b92f9304 578 netdev_err(vif->ndev, "Threshold Range fail\n");
31390eec 579 result = -EINVAL;
24db713f 580 goto ERRORHANDLER;
c5c77ba1 581 }
44a4db1d 582 i++;
c5c77ba1 583 }
a5f0fb5c
CL
584 if (cfg_param_attr->flag & RTS_THRESHOLD) {
585 if (cfg_param_attr->rts_threshold > 255 &&
586 cfg_param_attr->rts_threshold < 65536) {
44a4db1d
CL
587 wid_list[i].id = WID_RTS_THRESHOLD;
588 wid_list[i].val = (s8 *)&cfg_param_attr->rts_threshold;
589 wid_list[i].type = WID_SHORT;
590 wid_list[i].size = sizeof(u16);
a5f0fb5c 591 hif_drv->cfg_values.rts_threshold = cfg_param_attr->rts_threshold;
c5c77ba1 592 } else {
b92f9304 593 netdev_err(vif->ndev, "Threshold Range fail\n");
31390eec 594 result = -EINVAL;
24db713f 595 goto ERRORHANDLER;
c5c77ba1 596 }
44a4db1d 597 i++;
c5c77ba1 598 }
a5f0fb5c
CL
599 if (cfg_param_attr->flag & PREAMBLE) {
600 if (cfg_param_attr->preamble_type < 3) {
44a4db1d
CL
601 wid_list[i].id = WID_PREAMBLE;
602 wid_list[i].val = (s8 *)&cfg_param_attr->preamble_type;
603 wid_list[i].type = WID_CHAR;
604 wid_list[i].size = sizeof(char);
a5f0fb5c 605 hif_drv->cfg_values.preamble_type = cfg_param_attr->preamble_type;
c5c77ba1 606 } else {
b92f9304 607 netdev_err(vif->ndev, "Preamle Range(0~2) over\n");
31390eec 608 result = -EINVAL;
24db713f 609 goto ERRORHANDLER;
c5c77ba1 610 }
44a4db1d 611 i++;
c5c77ba1 612 }
a5f0fb5c
CL
613 if (cfg_param_attr->flag & SHORT_SLOT_ALLOWED) {
614 if (cfg_param_attr->short_slot_allowed < 2) {
44a4db1d
CL
615 wid_list[i].id = WID_SHORT_SLOT_ALLOWED;
616 wid_list[i].val = (s8 *)&cfg_param_attr->short_slot_allowed;
617 wid_list[i].type = WID_CHAR;
618 wid_list[i].size = sizeof(char);
a5f0fb5c 619 hif_drv->cfg_values.short_slot_allowed = (u8)cfg_param_attr->short_slot_allowed;
c5c77ba1 620 } else {
b92f9304 621 netdev_err(vif->ndev, "Short slot(2) over\n");
31390eec 622 result = -EINVAL;
24db713f 623 goto ERRORHANDLER;
c5c77ba1 624 }
44a4db1d 625 i++;
c5c77ba1 626 }
a5f0fb5c
CL
627 if (cfg_param_attr->flag & TXOP_PROT_DISABLE) {
628 if (cfg_param_attr->txop_prot_disabled < 2) {
44a4db1d
CL
629 wid_list[i].id = WID_11N_TXOP_PROT_DISABLE;
630 wid_list[i].val = (s8 *)&cfg_param_attr->txop_prot_disabled;
631 wid_list[i].type = WID_CHAR;
632 wid_list[i].size = sizeof(char);
a5f0fb5c 633 hif_drv->cfg_values.txop_prot_disabled = (u8)cfg_param_attr->txop_prot_disabled;
c5c77ba1 634 } else {
b92f9304 635 netdev_err(vif->ndev, "TXOP prot disable\n");
31390eec 636 result = -EINVAL;
24db713f 637 goto ERRORHANDLER;
c5c77ba1 638 }
44a4db1d 639 i++;
c5c77ba1 640 }
a5f0fb5c
CL
641 if (cfg_param_attr->flag & BEACON_INTERVAL) {
642 if (cfg_param_attr->beacon_interval > 0 &&
643 cfg_param_attr->beacon_interval < 65536) {
44a4db1d
CL
644 wid_list[i].id = WID_BEACON_INTERVAL;
645 wid_list[i].val = (s8 *)&cfg_param_attr->beacon_interval;
646 wid_list[i].type = WID_SHORT;
647 wid_list[i].size = sizeof(u16);
a5f0fb5c 648 hif_drv->cfg_values.beacon_interval = cfg_param_attr->beacon_interval;
c5c77ba1 649 } else {
b92f9304 650 netdev_err(vif->ndev, "Beacon interval(1~65535)fail\n");
31390eec 651 result = -EINVAL;
24db713f 652 goto ERRORHANDLER;
c5c77ba1 653 }
44a4db1d 654 i++;
c5c77ba1 655 }
a5f0fb5c
CL
656 if (cfg_param_attr->flag & DTIM_PERIOD) {
657 if (cfg_param_attr->dtim_period > 0 &&
658 cfg_param_attr->dtim_period < 256) {
44a4db1d
CL
659 wid_list[i].id = WID_DTIM_PERIOD;
660 wid_list[i].val = (s8 *)&cfg_param_attr->dtim_period;
661 wid_list[i].type = WID_CHAR;
662 wid_list[i].size = sizeof(char);
a5f0fb5c 663 hif_drv->cfg_values.dtim_period = cfg_param_attr->dtim_period;
c5c77ba1 664 } else {
b92f9304 665 netdev_err(vif->ndev, "DTIM range(1~255) fail\n");
31390eec 666 result = -EINVAL;
24db713f 667 goto ERRORHANDLER;
c5c77ba1 668 }
44a4db1d 669 i++;
c5c77ba1 670 }
a5f0fb5c
CL
671 if (cfg_param_attr->flag & SITE_SURVEY) {
672 if (cfg_param_attr->site_survey_enabled < 3) {
44a4db1d
CL
673 wid_list[i].id = WID_SITE_SURVEY;
674 wid_list[i].val = (s8 *)&cfg_param_attr->site_survey_enabled;
675 wid_list[i].type = WID_CHAR;
676 wid_list[i].size = sizeof(char);
a5f0fb5c 677 hif_drv->cfg_values.site_survey_enabled = (u8)cfg_param_attr->site_survey_enabled;
c5c77ba1 678 } else {
b92f9304 679 netdev_err(vif->ndev, "Site survey disable\n");
31390eec 680 result = -EINVAL;
24db713f 681 goto ERRORHANDLER;
c5c77ba1 682 }
44a4db1d 683 i++;
c5c77ba1 684 }
a5f0fb5c
CL
685 if (cfg_param_attr->flag & SITE_SURVEY_SCAN_TIME) {
686 if (cfg_param_attr->site_survey_scan_time > 0 &&
687 cfg_param_attr->site_survey_scan_time < 65536) {
44a4db1d
CL
688 wid_list[i].id = WID_SITE_SURVEY_SCAN_TIME;
689 wid_list[i].val = (s8 *)&cfg_param_attr->site_survey_scan_time;
690 wid_list[i].type = WID_SHORT;
691 wid_list[i].size = sizeof(u16);
a5f0fb5c 692 hif_drv->cfg_values.site_survey_scan_time = cfg_param_attr->site_survey_scan_time;
c5c77ba1 693 } else {
b92f9304 694 netdev_err(vif->ndev, "Site scan time(1~65535) over\n");
31390eec 695 result = -EINVAL;
24db713f 696 goto ERRORHANDLER;
c5c77ba1 697 }
44a4db1d 698 i++;
c5c77ba1 699 }
a5f0fb5c
CL
700 if (cfg_param_attr->flag & ACTIVE_SCANTIME) {
701 if (cfg_param_attr->active_scan_time > 0 &&
702 cfg_param_attr->active_scan_time < 65536) {
44a4db1d
CL
703 wid_list[i].id = WID_ACTIVE_SCAN_TIME;
704 wid_list[i].val = (s8 *)&cfg_param_attr->active_scan_time;
705 wid_list[i].type = WID_SHORT;
706 wid_list[i].size = sizeof(u16);
a5f0fb5c 707 hif_drv->cfg_values.active_scan_time = cfg_param_attr->active_scan_time;
c5c77ba1 708 } else {
b92f9304 709 netdev_err(vif->ndev, "Active time(1~65535) over\n");
31390eec 710 result = -EINVAL;
24db713f 711 goto ERRORHANDLER;
c5c77ba1 712 }
44a4db1d 713 i++;
c5c77ba1 714 }
a5f0fb5c
CL
715 if (cfg_param_attr->flag & PASSIVE_SCANTIME) {
716 if (cfg_param_attr->passive_scan_time > 0 &&
717 cfg_param_attr->passive_scan_time < 65536) {
44a4db1d
CL
718 wid_list[i].id = WID_PASSIVE_SCAN_TIME;
719 wid_list[i].val = (s8 *)&cfg_param_attr->passive_scan_time;
720 wid_list[i].type = WID_SHORT;
721 wid_list[i].size = sizeof(u16);
a5f0fb5c 722 hif_drv->cfg_values.passive_scan_time = cfg_param_attr->passive_scan_time;
c5c77ba1 723 } else {
b92f9304 724 netdev_err(vif->ndev, "Passive time(1~65535) over\n");
31390eec 725 result = -EINVAL;
24db713f 726 goto ERRORHANDLER;
c5c77ba1 727 }
44a4db1d 728 i++;
c5c77ba1 729 }
a5f0fb5c
CL
730 if (cfg_param_attr->flag & CURRENT_TX_RATE) {
731 enum CURRENT_TXRATE curr_tx_rate = cfg_param_attr->curr_tx_rate;
c09389ac 732
c5c77ba1
JK
733 if (curr_tx_rate == AUTORATE || curr_tx_rate == MBPS_1
734 || curr_tx_rate == MBPS_2 || curr_tx_rate == MBPS_5_5
735 || curr_tx_rate == MBPS_11 || curr_tx_rate == MBPS_6
736 || curr_tx_rate == MBPS_9 || curr_tx_rate == MBPS_12
737 || curr_tx_rate == MBPS_18 || curr_tx_rate == MBPS_24
738 || curr_tx_rate == MBPS_36 || curr_tx_rate == MBPS_48 || curr_tx_rate == MBPS_54) {
44a4db1d
CL
739 wid_list[i].id = WID_CURRENT_TX_RATE;
740 wid_list[i].val = (s8 *)&curr_tx_rate;
741 wid_list[i].type = WID_SHORT;
742 wid_list[i].size = sizeof(u16);
ace303f0 743 hif_drv->cfg_values.curr_tx_rate = (u8)curr_tx_rate;
c5c77ba1 744 } else {
b92f9304 745 netdev_err(vif->ndev, "out of TX rate\n");
31390eec 746 result = -EINVAL;
24db713f 747 goto ERRORHANDLER;
c5c77ba1 748 }
44a4db1d 749 i++;
c5c77ba1 750 }
31390eec 751
79df6a49 752 result = wilc_send_config_pkt(vif, SET_CFG, wid_list,
44a4db1d 753 i, wilc_get_vif_idx(vif));
c5c77ba1 754
31390eec 755 if (result)
b92f9304 756 netdev_err(vif->ndev, "Error in setting CFG params\n");
c5c77ba1 757
24db713f 758ERRORHANDLER:
33110ad7 759 up(&hif_drv->sem_cfg_values);
31390eec 760 return result;
c5c77ba1
JK
761}
762
3b840e49 763static void Handle_wait_msg_q_empty(void)
c5c77ba1 764{
0e1af73d 765 wilc_initialized = 0;
2d25af87 766 up(&hif_sema_wait_response);
c5c77ba1
JK
767}
768
71130e81 769static s32 Handle_ScanDone(struct wilc_vif *vif,
1608c403
AB
770 enum scan_event enuEvent);
771
71130e81 772static s32 Handle_Scan(struct wilc_vif *vif,
c476feb8 773 struct scan_attr *pstrHostIFscanAttr)
c5c77ba1 774{
31390eec 775 s32 result = 0;
e9e0c260 776 struct wid strWIDList[5];
4e4467fd
CL
777 u32 u32WidsCount = 0;
778 u32 i;
63d03e47
GKH
779 u8 *pu8Buffer;
780 u8 valuesize = 0;
781 u8 *pu8HdnNtwrksWidVal = NULL;
71130e81 782 struct host_if_drv *hif_drv = vif->hif_drv;
c5c77ba1 783
bc801855 784 hif_drv->usr_scan_req.scan_result = pstrHostIFscanAttr->result;
66eaea30 785 hif_drv->usr_scan_req.arg = pstrHostIFscanAttr->arg;
c5c77ba1 786
b60005a8
LK
787 if ((hif_drv->hif_state >= HOST_IF_SCANNING) &&
788 (hif_drv->hif_state < HOST_IF_CONNECTED)) {
b92f9304 789 netdev_err(vif->ndev, "Already scan\n");
31390eec 790 result = -EBUSY;
24db713f 791 goto ERRORHANDLER;
c5c77ba1
JK
792 }
793
0e1af73d 794 if (wilc_optaining_ip || wilc_connecting) {
b92f9304 795 netdev_err(vif->ndev, "Don't do obss scan\n");
31390eec 796 result = -EBUSY;
24db713f 797 goto ERRORHANDLER;
c5c77ba1 798 }
c5c77ba1 799
f79756ee 800 hif_drv->usr_scan_req.rcvd_ch_cnt = 0;
c5c77ba1 801
daaf16ba 802 strWIDList[u32WidsCount].id = (u16)WID_SSID_PROBE_REQ;
416d8321 803 strWIDList[u32WidsCount].type = WID_STR;
c5c77ba1 804
40e05e86 805 for (i = 0; i < pstrHostIFscanAttr->hidden_network.n_ssids; i++)
245a1865 806 valuesize += ((pstrHostIFscanAttr->hidden_network.net_info[i].ssid_len) + 1);
f3052587 807 pu8HdnNtwrksWidVal = kmalloc(valuesize + 1, GFP_KERNEL);
900bb4a6 808 strWIDList[u32WidsCount].val = pu8HdnNtwrksWidVal;
91109e11 809 if (strWIDList[u32WidsCount].val) {
900bb4a6 810 pu8Buffer = strWIDList[u32WidsCount].val;
c5c77ba1 811
40e05e86 812 *pu8Buffer++ = pstrHostIFscanAttr->hidden_network.n_ssids;
c5c77ba1 813
40e05e86 814 for (i = 0; i < pstrHostIFscanAttr->hidden_network.n_ssids; i++) {
245a1865
CL
815 *pu8Buffer++ = pstrHostIFscanAttr->hidden_network.net_info[i].ssid_len;
816 memcpy(pu8Buffer, pstrHostIFscanAttr->hidden_network.net_info[i].ssid, pstrHostIFscanAttr->hidden_network.net_info[i].ssid_len);
817 pu8Buffer += pstrHostIFscanAttr->hidden_network.net_info[i].ssid_len;
c5c77ba1
JK
818 }
819
2fd3e443 820 strWIDList[u32WidsCount].size = (s32)(valuesize + 1);
c5c77ba1
JK
821 u32WidsCount++;
822 }
823
c5c77ba1 824 {
daaf16ba 825 strWIDList[u32WidsCount].id = WID_INFO_ELEMENT_PROBE;
416d8321 826 strWIDList[u32WidsCount].type = WID_BIN_DATA;
d6f19aa5 827 strWIDList[u32WidsCount].val = pstrHostIFscanAttr->ies;
7b1f76cd 828 strWIDList[u32WidsCount].size = pstrHostIFscanAttr->ies_len;
c5c77ba1
JK
829 u32WidsCount++;
830 }
831
daaf16ba 832 strWIDList[u32WidsCount].id = WID_SCAN_TYPE;
416d8321 833 strWIDList[u32WidsCount].type = WID_CHAR;
2fd3e443 834 strWIDList[u32WidsCount].size = sizeof(char);
bafaa696 835 strWIDList[u32WidsCount].val = (s8 *)&pstrHostIFscanAttr->type;
c5c77ba1
JK
836 u32WidsCount++;
837
daaf16ba 838 strWIDList[u32WidsCount].id = WID_SCAN_CHANNEL_LIST;
416d8321 839 strWIDList[u32WidsCount].type = WID_BIN_DATA;
c5c77ba1 840
91109e11
LK
841 if (pstrHostIFscanAttr->ch_freq_list &&
842 pstrHostIFscanAttr->ch_list_len > 0) {
c5c77ba1
JK
843 int i;
844
f97bd9ca 845 for (i = 0; i < pstrHostIFscanAttr->ch_list_len; i++) {
82eeb0ad
LK
846 if (pstrHostIFscanAttr->ch_freq_list[i] > 0)
847 pstrHostIFscanAttr->ch_freq_list[i] = pstrHostIFscanAttr->ch_freq_list[i] - 1;
c5c77ba1
JK
848 }
849 }
850
82eeb0ad 851 strWIDList[u32WidsCount].val = pstrHostIFscanAttr->ch_freq_list;
f97bd9ca 852 strWIDList[u32WidsCount].size = pstrHostIFscanAttr->ch_list_len;
c5c77ba1
JK
853 u32WidsCount++;
854
daaf16ba 855 strWIDList[u32WidsCount].id = WID_START_SCAN_REQ;
416d8321 856 strWIDList[u32WidsCount].type = WID_CHAR;
2fd3e443 857 strWIDList[u32WidsCount].size = sizeof(char);
bafaa696 858 strWIDList[u32WidsCount].val = (s8 *)&pstrHostIFscanAttr->src;
c5c77ba1
JK
859 u32WidsCount++;
860
b60005a8 861 if (hif_drv->hif_state == HOST_IF_CONNECTED)
ca8540e4 862 scan_while_connected = true;
b60005a8 863 else if (hif_drv->hif_state == HOST_IF_IDLE)
ca8540e4 864 scan_while_connected = false;
c5c77ba1 865
79df6a49 866 result = wilc_send_config_pkt(vif, SET_CFG, strWIDList,
ec62e6d1 867 u32WidsCount,
eb9939b7 868 wilc_get_vif_idx(vif));
c5c77ba1 869
31390eec 870 if (result)
b92f9304 871 netdev_err(vif->ndev, "Failed to send scan parameters\n");
c5c77ba1 872
24db713f 873ERRORHANDLER:
31390eec 874 if (result) {
13b313e4 875 del_timer(&hif_drv->scan_timer);
71130e81 876 Handle_ScanDone(vif, SCAN_EVENT_ABORTED);
c5c77ba1
JK
877 }
878
95f840fb
SB
879 kfree(pstrHostIFscanAttr->ch_freq_list);
880 pstrHostIFscanAttr->ch_freq_list = NULL;
c5c77ba1 881
95f840fb
SB
882 kfree(pstrHostIFscanAttr->ies);
883 pstrHostIFscanAttr->ies = NULL;
245a1865
CL
884 kfree(pstrHostIFscanAttr->hidden_network.net_info);
885 pstrHostIFscanAttr->hidden_network.net_info = NULL;
c5c77ba1 886
95f840fb 887 kfree(pu8HdnNtwrksWidVal);
c5c77ba1 888
31390eec 889 return result;
c5c77ba1
JK
890}
891
71130e81 892static s32 Handle_ScanDone(struct wilc_vif *vif,
a4ab1ade 893 enum scan_event enuEvent)
c5c77ba1 894{
31390eec 895 s32 result = 0;
63d03e47 896 u8 u8abort_running_scan;
45102f83 897 struct wid wid;
71130e81 898 struct host_if_drv *hif_drv = vif->hif_drv;
c5c77ba1 899
c5c77ba1 900 if (enuEvent == SCAN_EVENT_ABORTED) {
c5c77ba1 901 u8abort_running_scan = 1;
45102f83
LK
902 wid.id = (u16)WID_ABORT_RUNNING_SCAN;
903 wid.type = WID_CHAR;
904 wid.val = (s8 *)&u8abort_running_scan;
905 wid.size = sizeof(char);
c5c77ba1 906
79df6a49 907 result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1,
4cf93d70 908 wilc_get_vif_idx(vif));
31390eec
LK
909
910 if (result) {
b92f9304 911 netdev_err(vif->ndev, "Failed to set abort running\n");
31390eec 912 result = -EFAULT;
c5c77ba1
JK
913 }
914 }
915
a4ab1ade 916 if (!hif_drv) {
b92f9304 917 netdev_err(vif->ndev, "Driver handler is NULL\n");
31390eec 918 return result;
c5c77ba1
JK
919 }
920
bc801855
LK
921 if (hif_drv->usr_scan_req.scan_result) {
922 hif_drv->usr_scan_req.scan_result(enuEvent, NULL,
66eaea30 923 hif_drv->usr_scan_req.arg, NULL);
bc801855 924 hif_drv->usr_scan_req.scan_result = NULL;
c5c77ba1
JK
925 }
926
31390eec 927 return result;
c5c77ba1
JK
928}
929
e554a305 930u8 wilc_connected_ssid[6] = {0};
71130e81 931static s32 Handle_Connect(struct wilc_vif *vif,
120ae593 932 struct connect_attr *pstrHostIFconnectAttr)
c5c77ba1 933{
31390eec 934 s32 result = 0;
e9e0c260 935 struct wid strWIDList[8];
4e4467fd 936 u32 u32WidsCount = 0, dummyval = 0;
63d03e47 937 u8 *pu8CurrByte = NULL;
e0a12217 938 struct join_bss_param *ptstrJoinBssParam;
71130e81 939 struct host_if_drv *hif_drv = vif->hif_drv;
c5c77ba1 940
e554a305 941 if (memcmp(pstrHostIFconnectAttr->bssid, wilc_connected_ssid, ETH_ALEN) == 0) {
31390eec 942 result = 0;
b92f9304 943 netdev_err(vif->ndev, "Discard connect request\n");
31390eec 944 return result;
c5c77ba1
JK
945 }
946
59b97b36 947 ptstrJoinBssParam = pstrHostIFconnectAttr->params;
91109e11 948 if (!ptstrJoinBssParam) {
b92f9304 949 netdev_err(vif->ndev, "Required BSSID not found\n");
31390eec 950 result = -ENOENT;
24db713f 951 goto ERRORHANDLER;
c5c77ba1 952 }
c5c77ba1 953
91109e11 954 if (pstrHostIFconnectAttr->bssid) {
788f6fc0
CL
955 hif_drv->usr_conn_req.bssid = kmalloc(6, GFP_KERNEL);
956 memcpy(hif_drv->usr_conn_req.bssid, pstrHostIFconnectAttr->bssid, 6);
c5c77ba1
JK
957 }
958
74ab5e45 959 hif_drv->usr_conn_req.ssid_len = pstrHostIFconnectAttr->ssid_len;
91109e11 960 if (pstrHostIFconnectAttr->ssid) {
72216411
CL
961 hif_drv->usr_conn_req.ssid = kmalloc(pstrHostIFconnectAttr->ssid_len + 1, GFP_KERNEL);
962 memcpy(hif_drv->usr_conn_req.ssid,
8c8360b3
LK
963 pstrHostIFconnectAttr->ssid,
964 pstrHostIFconnectAttr->ssid_len);
72216411 965 hif_drv->usr_conn_req.ssid[pstrHostIFconnectAttr->ssid_len] = '\0';
c5c77ba1
JK
966 }
967
331ed080 968 hif_drv->usr_conn_req.ies_len = pstrHostIFconnectAttr->ies_len;
91109e11 969 if (pstrHostIFconnectAttr->ies) {
a3b2f4b9
LK
970 hif_drv->usr_conn_req.ies = kmalloc(pstrHostIFconnectAttr->ies_len, GFP_KERNEL);
971 memcpy(hif_drv->usr_conn_req.ies,
8c8360b3
LK
972 pstrHostIFconnectAttr->ies,
973 pstrHostIFconnectAttr->ies_len);
c5c77ba1
JK
974 }
975
a0942c57 976 hif_drv->usr_conn_req.security = pstrHostIFconnectAttr->security;
7d069728 977 hif_drv->usr_conn_req.auth_type = pstrHostIFconnectAttr->auth_type;
33bfb198 978 hif_drv->usr_conn_req.conn_result = pstrHostIFconnectAttr->result;
73abaa49 979 hif_drv->usr_conn_req.arg = pstrHostIFconnectAttr->arg;
c5c77ba1 980
daaf16ba 981 strWIDList[u32WidsCount].id = WID_SUCCESS_FRAME_COUNT;
416d8321 982 strWIDList[u32WidsCount].type = WID_INT;
2fd3e443 983 strWIDList[u32WidsCount].size = sizeof(u32);
900bb4a6 984 strWIDList[u32WidsCount].val = (s8 *)(&(dummyval));
c5c77ba1
JK
985 u32WidsCount++;
986
daaf16ba 987 strWIDList[u32WidsCount].id = WID_RECEIVED_FRAGMENT_COUNT;
416d8321 988 strWIDList[u32WidsCount].type = WID_INT;
2fd3e443 989 strWIDList[u32WidsCount].size = sizeof(u32);
900bb4a6 990 strWIDList[u32WidsCount].val = (s8 *)(&(dummyval));
c5c77ba1
JK
991 u32WidsCount++;
992
daaf16ba 993 strWIDList[u32WidsCount].id = WID_FAILED_COUNT;
416d8321 994 strWIDList[u32WidsCount].type = WID_INT;
2fd3e443 995 strWIDList[u32WidsCount].size = sizeof(u32);
900bb4a6 996 strWIDList[u32WidsCount].val = (s8 *)(&(dummyval));
c5c77ba1
JK
997 u32WidsCount++;
998
c5c77ba1 999 {
daaf16ba 1000 strWIDList[u32WidsCount].id = WID_INFO_ELEMENT_ASSOCIATE;
416d8321 1001 strWIDList[u32WidsCount].type = WID_BIN_DATA;
a3b2f4b9 1002 strWIDList[u32WidsCount].val = hif_drv->usr_conn_req.ies;
331ed080 1003 strWIDList[u32WidsCount].size = hif_drv->usr_conn_req.ies_len;
c5c77ba1
JK
1004 u32WidsCount++;
1005
f7bbd9cf 1006 if (memcmp("DIRECT-", pstrHostIFconnectAttr->ssid, 7)) {
331ed080 1007 info_element_size = hif_drv->usr_conn_req.ies_len;
dfef7b84 1008 info_element = kmalloc(info_element_size, GFP_KERNEL);
a3b2f4b9 1009 memcpy(info_element, hif_drv->usr_conn_req.ies,
dfef7b84 1010 info_element_size);
c5c77ba1
JK
1011 }
1012 }
daaf16ba 1013 strWIDList[u32WidsCount].id = (u16)WID_11I_MODE;
416d8321 1014 strWIDList[u32WidsCount].type = WID_CHAR;
2fd3e443 1015 strWIDList[u32WidsCount].size = sizeof(char);
a0942c57 1016 strWIDList[u32WidsCount].val = (s8 *)&hif_drv->usr_conn_req.security;
c5c77ba1
JK
1017 u32WidsCount++;
1018
f7bbd9cf 1019 if (memcmp("DIRECT-", pstrHostIFconnectAttr->ssid, 7))
a0942c57 1020 mode_11i = hif_drv->usr_conn_req.security;
c5c77ba1 1021
daaf16ba 1022 strWIDList[u32WidsCount].id = (u16)WID_AUTH_TYPE;
416d8321 1023 strWIDList[u32WidsCount].type = WID_CHAR;
2fd3e443 1024 strWIDList[u32WidsCount].size = sizeof(char);
7d069728 1025 strWIDList[u32WidsCount].val = (s8 *)&hif_drv->usr_conn_req.auth_type;
c5c77ba1
JK
1026 u32WidsCount++;
1027
f7bbd9cf 1028 if (memcmp("DIRECT-", pstrHostIFconnectAttr->ssid, 7))
7d069728 1029 auth_type = (u8)hif_drv->usr_conn_req.auth_type;
c5c77ba1 1030
daaf16ba 1031 strWIDList[u32WidsCount].id = (u16)WID_JOIN_REQ_EXTENDED;
416d8321 1032 strWIDList[u32WidsCount].type = WID_STR;
ae4dfa57 1033 strWIDList[u32WidsCount].size = 112;
900bb4a6 1034 strWIDList[u32WidsCount].val = kmalloc(strWIDList[u32WidsCount].size, GFP_KERNEL);
c5c77ba1 1035
f7bbd9cf 1036 if (memcmp("DIRECT-", pstrHostIFconnectAttr->ssid, 7)) {
0626baaa
LK
1037 join_req_size = strWIDList[u32WidsCount].size;
1038 join_req = kmalloc(join_req_size, GFP_KERNEL);
c5c77ba1 1039 }
91109e11 1040 if (!strWIDList[u32WidsCount].val) {
31390eec 1041 result = -EFAULT;
24db713f
LK
1042 goto ERRORHANDLER;
1043 }
c5c77ba1 1044
900bb4a6 1045 pu8CurrByte = strWIDList[u32WidsCount].val;
c5c77ba1 1046
91109e11 1047 if (pstrHostIFconnectAttr->ssid) {
8b3c9fa6
LK
1048 memcpy(pu8CurrByte, pstrHostIFconnectAttr->ssid, pstrHostIFconnectAttr->ssid_len);
1049 pu8CurrByte[pstrHostIFconnectAttr->ssid_len] = '\0';
c5c77ba1
JK
1050 }
1051 pu8CurrByte += MAX_SSID_LEN;
c5c77ba1 1052 *(pu8CurrByte++) = INFRASTRUCTURE;
ae4dfa57 1053
0d1527e6
LK
1054 if ((pstrHostIFconnectAttr->ch >= 1) && (pstrHostIFconnectAttr->ch <= 14)) {
1055 *(pu8CurrByte++) = pstrHostIFconnectAttr->ch;
c5c77ba1 1056 } else {
b92f9304 1057 netdev_err(vif->ndev, "Channel out of range\n");
c5c77ba1
JK
1058 *(pu8CurrByte++) = 0xFF;
1059 }
c5c77ba1
JK
1060 *(pu8CurrByte++) = (ptstrJoinBssParam->cap_info) & 0xFF;
1061 *(pu8CurrByte++) = ((ptstrJoinBssParam->cap_info) >> 8) & 0xFF;
c5c77ba1 1062
91109e11 1063 if (pstrHostIFconnectAttr->bssid)
9254db07 1064 memcpy(pu8CurrByte, pstrHostIFconnectAttr->bssid, 6);
c5c77ba1
JK
1065 pu8CurrByte += 6;
1066
c0f52fba
TC
1067 if (pstrHostIFconnectAttr->bssid)
1068 memcpy(pu8CurrByte, pstrHostIFconnectAttr->bssid, 6);
1069 pu8CurrByte += 6;
1070
c5c77ba1
JK
1071 *(pu8CurrByte++) = (ptstrJoinBssParam->beacon_period) & 0xFF;
1072 *(pu8CurrByte++) = ((ptstrJoinBssParam->beacon_period) >> 8) & 0xFF;
c5c77ba1 1073 *(pu8CurrByte++) = ptstrJoinBssParam->dtim_period;
ae4dfa57 1074
d00d2ba3 1075 memcpy(pu8CurrByte, ptstrJoinBssParam->supp_rates, MAX_RATES_SUPPORTED + 1);
c5c77ba1
JK
1076 pu8CurrByte += (MAX_RATES_SUPPORTED + 1);
1077
c5c77ba1 1078 *(pu8CurrByte++) = ptstrJoinBssParam->wmm_cap;
c5c77ba1
JK
1079 *(pu8CurrByte++) = ptstrJoinBssParam->uapsd_cap;
1080
c5c77ba1 1081 *(pu8CurrByte++) = ptstrJoinBssParam->ht_capable;
ff06982c 1082 hif_drv->usr_conn_req.ht_capable = ptstrJoinBssParam->ht_capable;
c5c77ba1 1083
c5c77ba1 1084 *(pu8CurrByte++) = ptstrJoinBssParam->rsn_found;
c5c77ba1 1085 *(pu8CurrByte++) = ptstrJoinBssParam->rsn_grp_policy;
c5c77ba1 1086 *(pu8CurrByte++) = ptstrJoinBssParam->mode_802_11i;
ae4dfa57 1087
d00d2ba3 1088 memcpy(pu8CurrByte, ptstrJoinBssParam->rsn_pcip_policy, sizeof(ptstrJoinBssParam->rsn_pcip_policy));
c5c77ba1
JK
1089 pu8CurrByte += sizeof(ptstrJoinBssParam->rsn_pcip_policy);
1090
d00d2ba3 1091 memcpy(pu8CurrByte, ptstrJoinBssParam->rsn_auth_policy, sizeof(ptstrJoinBssParam->rsn_auth_policy));
c5c77ba1
JK
1092 pu8CurrByte += sizeof(ptstrJoinBssParam->rsn_auth_policy);
1093
d00d2ba3 1094 memcpy(pu8CurrByte, ptstrJoinBssParam->rsn_cap, sizeof(ptstrJoinBssParam->rsn_cap));
c5c77ba1
JK
1095 pu8CurrByte += sizeof(ptstrJoinBssParam->rsn_cap);
1096
c5c77ba1 1097 *(pu8CurrByte++) = REAL_JOIN_REQ;
7a8d51d7 1098 *(pu8CurrByte++) = ptstrJoinBssParam->noa_enabled;
c5c77ba1 1099
7a8d51d7 1100 if (ptstrJoinBssParam->noa_enabled) {
c5c77ba1
JK
1101 *(pu8CurrByte++) = (ptstrJoinBssParam->tsf) & 0xFF;
1102 *(pu8CurrByte++) = ((ptstrJoinBssParam->tsf) >> 8) & 0xFF;
1103 *(pu8CurrByte++) = ((ptstrJoinBssParam->tsf) >> 16) & 0xFF;
1104 *(pu8CurrByte++) = ((ptstrJoinBssParam->tsf) >> 24) & 0xFF;
1105
d72b33ca 1106 *(pu8CurrByte++) = ptstrJoinBssParam->opp_enabled;
cc179008 1107 *(pu8CurrByte++) = ptstrJoinBssParam->idx;
c5c77ba1 1108
d72b33ca 1109 if (ptstrJoinBssParam->opp_enabled)
99b66945 1110 *(pu8CurrByte++) = ptstrJoinBssParam->ct_window;
c5c77ba1 1111
c21047ed 1112 *(pu8CurrByte++) = ptstrJoinBssParam->cnt;
c5c77ba1 1113
109e6cab
LK
1114 memcpy(pu8CurrByte, ptstrJoinBssParam->duration, sizeof(ptstrJoinBssParam->duration));
1115 pu8CurrByte += sizeof(ptstrJoinBssParam->duration);
c5c77ba1 1116
1d8b76b3
LK
1117 memcpy(pu8CurrByte, ptstrJoinBssParam->interval, sizeof(ptstrJoinBssParam->interval));
1118 pu8CurrByte += sizeof(ptstrJoinBssParam->interval);
c5c77ba1 1119
4be55e22
LK
1120 memcpy(pu8CurrByte, ptstrJoinBssParam->start_time, sizeof(ptstrJoinBssParam->start_time));
1121 pu8CurrByte += sizeof(ptstrJoinBssParam->start_time);
c4f97526 1122 }
c5c77ba1 1123
900bb4a6 1124 pu8CurrByte = strWIDList[u32WidsCount].val;
c5c77ba1 1125 u32WidsCount++;
c5c77ba1 1126
f7bbd9cf 1127 if (memcmp("DIRECT-", pstrHostIFconnectAttr->ssid, 7)) {
0626baaa 1128 memcpy(join_req, pu8CurrByte, join_req_size);
7036c624 1129 join_req_vif = vif;
c5c77ba1
JK
1130 }
1131
e3f16965 1132 if (pstrHostIFconnectAttr->bssid)
e554a305
LK
1133 memcpy(wilc_connected_ssid,
1134 pstrHostIFconnectAttr->bssid, ETH_ALEN);
c5c77ba1 1135
79df6a49 1136 result = wilc_send_config_pkt(vif, SET_CFG, strWIDList,
ec62e6d1 1137 u32WidsCount,
eb9939b7 1138 wilc_get_vif_idx(vif));
31390eec 1139 if (result) {
b92f9304 1140 netdev_err(vif->ndev, "failed to send config packet\n");
31390eec 1141 result = -EFAULT;
24db713f 1142 goto ERRORHANDLER;
c5c77ba1 1143 } else {
b60005a8 1144 hif_drv->hif_state = HOST_IF_WAITING_CONN_RESP;
c5c77ba1 1145 }
c5c77ba1 1146
24db713f 1147ERRORHANDLER:
31390eec 1148 if (result) {
c5c77ba1
JK
1149 tstrConnectInfo strConnectInfo;
1150
81a59506 1151 del_timer(&hif_drv->connect_timer);
c5c77ba1 1152
2cc46837 1153 memset(&strConnectInfo, 0, sizeof(tstrConnectInfo));
c5c77ba1 1154
91109e11
LK
1155 if (pstrHostIFconnectAttr->result) {
1156 if (pstrHostIFconnectAttr->bssid)
9254db07 1157 memcpy(strConnectInfo.au8bssid, pstrHostIFconnectAttr->bssid, 6);
c5c77ba1 1158
91109e11 1159 if (pstrHostIFconnectAttr->ies) {
b59d5c5b
LK
1160 strConnectInfo.ReqIEsLen = pstrHostIFconnectAttr->ies_len;
1161 strConnectInfo.pu8ReqIEs = kmalloc(pstrHostIFconnectAttr->ies_len, GFP_KERNEL);
d00d2ba3 1162 memcpy(strConnectInfo.pu8ReqIEs,
8c8360b3
LK
1163 pstrHostIFconnectAttr->ies,
1164 pstrHostIFconnectAttr->ies_len);
c5c77ba1
JK
1165 }
1166
6abcc11d 1167 pstrHostIFconnectAttr->result(CONN_DISCONN_EVENT_CONN_RESP,
c5c77ba1
JK
1168 &strConnectInfo,
1169 MAC_DISCONNECTED,
1170 NULL,
8f38db89 1171 pstrHostIFconnectAttr->arg);
b60005a8 1172 hif_drv->hif_state = HOST_IF_IDLE;
95f840fb
SB
1173 kfree(strConnectInfo.pu8ReqIEs);
1174 strConnectInfo.pu8ReqIEs = NULL;
c5c77ba1
JK
1175
1176 } else {
b92f9304 1177 netdev_err(vif->ndev, "Connect callback is NULL\n");
c5c77ba1
JK
1178 }
1179 }
1180
95f840fb
SB
1181 kfree(pstrHostIFconnectAttr->bssid);
1182 pstrHostIFconnectAttr->bssid = NULL;
c5c77ba1 1183
95f840fb
SB
1184 kfree(pstrHostIFconnectAttr->ssid);
1185 pstrHostIFconnectAttr->ssid = NULL;
c5c77ba1 1186
95f840fb
SB
1187 kfree(pstrHostIFconnectAttr->ies);
1188 pstrHostIFconnectAttr->ies = NULL;
c5c77ba1 1189
95f840fb 1190 kfree(pu8CurrByte);
31390eec 1191 return result;
c5c77ba1
JK
1192}
1193
71130e81 1194static s32 Handle_FlushConnect(struct wilc_vif *vif)
c5c77ba1 1195{
31390eec 1196 s32 result = 0;
e9e0c260 1197 struct wid strWIDList[5];
4e4467fd 1198 u32 u32WidsCount = 0;
63d03e47 1199 u8 *pu8CurrByte = NULL;
c5c77ba1 1200
daaf16ba 1201 strWIDList[u32WidsCount].id = WID_INFO_ELEMENT_ASSOCIATE;
416d8321 1202 strWIDList[u32WidsCount].type = WID_BIN_DATA;
48ce2465 1203 strWIDList[u32WidsCount].val = info_element;
dfef7b84 1204 strWIDList[u32WidsCount].size = info_element_size;
c5c77ba1
JK
1205 u32WidsCount++;
1206
daaf16ba 1207 strWIDList[u32WidsCount].id = (u16)WID_11I_MODE;
416d8321 1208 strWIDList[u32WidsCount].type = WID_CHAR;
2fd3e443 1209 strWIDList[u32WidsCount].size = sizeof(char);
1bd9d44c 1210 strWIDList[u32WidsCount].val = (s8 *)(&(mode_11i));
c5c77ba1
JK
1211 u32WidsCount++;
1212
daaf16ba 1213 strWIDList[u32WidsCount].id = (u16)WID_AUTH_TYPE;
416d8321 1214 strWIDList[u32WidsCount].type = WID_CHAR;
2fd3e443 1215 strWIDList[u32WidsCount].size = sizeof(char);
fba4989e 1216 strWIDList[u32WidsCount].val = (s8 *)(&auth_type);
c5c77ba1
JK
1217 u32WidsCount++;
1218
daaf16ba 1219 strWIDList[u32WidsCount].id = (u16)WID_JOIN_REQ_EXTENDED;
416d8321 1220 strWIDList[u32WidsCount].type = WID_STR;
0626baaa 1221 strWIDList[u32WidsCount].size = join_req_size;
044a6410 1222 strWIDList[u32WidsCount].val = (s8 *)join_req;
900bb4a6 1223 pu8CurrByte = strWIDList[u32WidsCount].val;
c5c77ba1
JK
1224
1225 pu8CurrByte += FLUSHED_BYTE_POS;
1226 *(pu8CurrByte) = FLUSHED_JOIN_REQ;
1227
1228 u32WidsCount++;
1229
79df6a49 1230 result = wilc_send_config_pkt(vif, SET_CFG, strWIDList,
ec62e6d1 1231 u32WidsCount,
7036c624 1232 wilc_get_vif_idx(join_req_vif));
31390eec 1233 if (result) {
b92f9304 1234 netdev_err(vif->ndev, "failed to send config packet\n");
31390eec 1235 result = -EINVAL;
c5c77ba1
JK
1236 }
1237
31390eec 1238 return result;
c5c77ba1
JK
1239}
1240
71130e81 1241static s32 Handle_ConnectTimeout(struct wilc_vif *vif)
c5c77ba1 1242{
31390eec 1243 s32 result = 0;
c5c77ba1 1244 tstrConnectInfo strConnectInfo;
45102f83 1245 struct wid wid;
d85f5326 1246 u16 u16DummyReasonCode = 0;
71130e81 1247 struct host_if_drv *hif_drv = vif->hif_drv;
c5c77ba1 1248
a4ab1ade 1249 if (!hif_drv) {
b92f9304 1250 netdev_err(vif->ndev, "Driver handler is NULL\n");
31390eec 1251 return result;
c5c77ba1
JK
1252 }
1253
b60005a8 1254 hif_drv->hif_state = HOST_IF_IDLE;
c5c77ba1 1255
ca8540e4 1256 scan_while_connected = false;
c5c77ba1 1257
2cc46837 1258 memset(&strConnectInfo, 0, sizeof(tstrConnectInfo));
c5c77ba1 1259
33bfb198 1260 if (hif_drv->usr_conn_req.conn_result) {
788f6fc0 1261 if (hif_drv->usr_conn_req.bssid) {
d00d2ba3 1262 memcpy(strConnectInfo.au8bssid,
788f6fc0 1263 hif_drv->usr_conn_req.bssid, 6);
c5c77ba1
JK
1264 }
1265
a3b2f4b9 1266 if (hif_drv->usr_conn_req.ies) {
331ed080
LK
1267 strConnectInfo.ReqIEsLen = hif_drv->usr_conn_req.ies_len;
1268 strConnectInfo.pu8ReqIEs = kmalloc(hif_drv->usr_conn_req.ies_len, GFP_KERNEL);
d00d2ba3 1269 memcpy(strConnectInfo.pu8ReqIEs,
a3b2f4b9 1270 hif_drv->usr_conn_req.ies,
331ed080 1271 hif_drv->usr_conn_req.ies_len);
c5c77ba1
JK
1272 }
1273
33bfb198
LK
1274 hif_drv->usr_conn_req.conn_result(CONN_DISCONN_EVENT_CONN_RESP,
1275 &strConnectInfo,
1276 MAC_DISCONNECTED,
1277 NULL,
73abaa49 1278 hif_drv->usr_conn_req.arg);
c5c77ba1 1279
95f840fb
SB
1280 kfree(strConnectInfo.pu8ReqIEs);
1281 strConnectInfo.pu8ReqIEs = NULL;
c5c77ba1 1282 } else {
b92f9304 1283 netdev_err(vif->ndev, "Connect callback is NULL\n");
c5c77ba1
JK
1284 }
1285
45102f83
LK
1286 wid.id = (u16)WID_DISCONNECT;
1287 wid.type = WID_CHAR;
1288 wid.val = (s8 *)&u16DummyReasonCode;
1289 wid.size = sizeof(char);
c5c77ba1 1290
79df6a49 1291 result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1,
4cf93d70 1292 wilc_get_vif_idx(vif));
31390eec 1293 if (result)
b92f9304 1294 netdev_err(vif->ndev, "Failed to send dissconect\n");
c5c77ba1 1295
74ab5e45 1296 hif_drv->usr_conn_req.ssid_len = 0;
72216411
CL
1297 kfree(hif_drv->usr_conn_req.ssid);
1298 hif_drv->usr_conn_req.ssid = NULL;
788f6fc0
CL
1299 kfree(hif_drv->usr_conn_req.bssid);
1300 hif_drv->usr_conn_req.bssid = NULL;
331ed080 1301 hif_drv->usr_conn_req.ies_len = 0;
a3b2f4b9 1302 kfree(hif_drv->usr_conn_req.ies);
cc28e4bf 1303 hif_drv->usr_conn_req.ies = NULL;
c5c77ba1 1304
e554a305 1305 eth_zero_addr(wilc_connected_ssid);
ae4dfa57 1306
7036c624 1307 if (join_req && join_req_vif == vif) {
044a6410
LK
1308 kfree(join_req);
1309 join_req = NULL;
c5c77ba1 1310 }
48ce2465 1311
7036c624 1312 if (info_element && join_req_vif == vif) {
48ce2465
LK
1313 kfree(info_element);
1314 info_element = NULL;
c5c77ba1
JK
1315 }
1316
31390eec 1317 return result;
c5c77ba1
JK
1318}
1319
71130e81 1320static s32 Handle_RcvdNtwrkInfo(struct wilc_vif *vif,
3bbd59f5 1321 struct rcvd_net_info *pstrRcvdNetworkInfo)
c5c77ba1 1322{
4e4467fd 1323 u32 i;
72ed4dc7 1324 bool bNewNtwrkFound;
31390eec 1325 s32 result = 0;
6b5180a0 1326 struct network_info *pstrNetworkInfo = NULL;
c5c77ba1 1327 void *pJoinParams = NULL;
71130e81 1328 struct host_if_drv *hif_drv = vif->hif_drv;
c5c77ba1 1329
72ed4dc7 1330 bNewNtwrkFound = true;
c5c77ba1 1331
bc801855 1332 if (hif_drv->usr_scan_req.scan_result) {
0e1af73d 1333 wilc_parse_network_info(pstrRcvdNetworkInfo->buffer, &pstrNetworkInfo);
91109e11 1334 if ((!pstrNetworkInfo) ||
bc801855 1335 (!hif_drv->usr_scan_req.scan_result)) {
b92f9304 1336 netdev_err(vif->ndev, "driver is null\n");
31390eec 1337 result = -EINVAL;
24db713f 1338 goto done;
c5c77ba1
JK
1339 }
1340
f79756ee 1341 for (i = 0; i < hif_drv->usr_scan_req.rcvd_ch_cnt; i++) {
69dc533e 1342 if ((hif_drv->usr_scan_req.net_info[i].bssid) &&
38d3bb78 1343 (pstrNetworkInfo->bssid)) {
69dc533e 1344 if (memcmp(hif_drv->usr_scan_req.net_info[i].bssid,
38d3bb78 1345 pstrNetworkInfo->bssid, 6) == 0) {
5cfbbf14 1346 if (pstrNetworkInfo->rssi <= hif_drv->usr_scan_req.net_info[i].rssi) {
c5c77ba1
JK
1347 goto done;
1348 } else {
5cfbbf14 1349 hif_drv->usr_scan_req.net_info[i].rssi = pstrNetworkInfo->rssi;
72ed4dc7 1350 bNewNtwrkFound = false;
c5c77ba1
JK
1351 break;
1352 }
1353 }
1354 }
1355 }
1356
047e6646 1357 if (bNewNtwrkFound) {
f79756ee 1358 if (hif_drv->usr_scan_req.rcvd_ch_cnt < MAX_NUM_SCANNED_NETWORKS) {
5cfbbf14 1359 hif_drv->usr_scan_req.net_info[hif_drv->usr_scan_req.rcvd_ch_cnt].rssi = pstrNetworkInfo->rssi;
c5c77ba1 1360
69dc533e 1361 if (hif_drv->usr_scan_req.net_info[hif_drv->usr_scan_req.rcvd_ch_cnt].bssid &&
38d3bb78 1362 pstrNetworkInfo->bssid) {
69dc533e 1363 memcpy(hif_drv->usr_scan_req.net_info[hif_drv->usr_scan_req.rcvd_ch_cnt].bssid,
38d3bb78 1364 pstrNetworkInfo->bssid, 6);
c5c77ba1 1365
f79756ee 1366 hif_drv->usr_scan_req.rcvd_ch_cnt++;
c5c77ba1 1367
d4020763 1368 pstrNetworkInfo->new_network = true;
c5c77ba1 1369 pJoinParams = host_int_ParseJoinBssParam(pstrNetworkInfo);
c5c77ba1 1370
bc801855 1371 hif_drv->usr_scan_req.scan_result(SCAN_EVENT_NETWORK_FOUND, pstrNetworkInfo,
66eaea30 1372 hif_drv->usr_scan_req.arg,
bc801855 1373 pJoinParams);
c5c77ba1 1374 }
c5c77ba1
JK
1375 }
1376 } else {
d4020763 1377 pstrNetworkInfo->new_network = false;
bc801855 1378 hif_drv->usr_scan_req.scan_result(SCAN_EVENT_NETWORK_FOUND, pstrNetworkInfo,
66eaea30 1379 hif_drv->usr_scan_req.arg, NULL);
c5c77ba1
JK
1380 }
1381 }
1382
c5c77ba1 1383done:
95f840fb
SB
1384 kfree(pstrRcvdNetworkInfo->buffer);
1385 pstrRcvdNetworkInfo->buffer = NULL;
c5c77ba1 1386
91109e11 1387 if (pstrNetworkInfo) {
390b6db0 1388 kfree(pstrNetworkInfo->ies);
d9fb23d7 1389 kfree(pstrNetworkInfo);
c5c77ba1
JK
1390 }
1391
31390eec 1392 return result;
c5c77ba1
JK
1393}
1394
71130e81 1395static s32 host_int_get_assoc_res_info(struct wilc_vif *vif,
1608c403
AB
1396 u8 *pu8AssocRespInfo,
1397 u32 u32MaxAssocRespInfoLen,
1398 u32 *pu32RcvdAssocRespInfoLen);
1399
cf60106b 1400static s32 Handle_RcvdGnrlAsyncInfo(struct wilc_vif *vif,
f23a9eab 1401 struct rcvd_async_info *pstrRcvdGnrlAsyncInfo)
c5c77ba1 1402{
31390eec 1403 s32 result = 0;
63d03e47
GKH
1404 u8 u8MsgType = 0;
1405 u8 u8MsgID = 0;
d85f5326
CL
1406 u16 u16MsgLen = 0;
1407 u16 u16WidID = (u16)WID_NIL;
63d03e47
GKH
1408 u8 u8WidLen = 0;
1409 u8 u8MacStatus;
1410 u8 u8MacStatusReasonCode;
1411 u8 u8MacStatusAdditionalInfo;
c5c77ba1
JK
1412 tstrConnectInfo strConnectInfo;
1413 tstrDisconnectNotifInfo strDisconnectNotifInfo;
e6e12661 1414 s32 s32Err = 0;
71130e81 1415 struct host_if_drv *hif_drv = vif->hif_drv;
78c87591 1416
a4ab1ade 1417 if (!hif_drv) {
b92f9304 1418 netdev_err(vif->ndev, "Driver handler is NULL\n");
234837de
LK
1419 return -ENODEV;
1420 }
c5c77ba1 1421
b60005a8
LK
1422 if ((hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP) ||
1423 (hif_drv->hif_state == HOST_IF_CONNECTED) ||
bc801855 1424 hif_drv->usr_scan_req.scan_result) {
91109e11 1425 if (!pstrRcvdGnrlAsyncInfo->buffer ||
33bfb198 1426 !hif_drv->usr_conn_req.conn_result) {
b92f9304 1427 netdev_err(vif->ndev, "driver is null\n");
24db713f 1428 return -EINVAL;
c5c77ba1
JK
1429 }
1430
33722ac7 1431 u8MsgType = pstrRcvdGnrlAsyncInfo->buffer[0];
c5c77ba1 1432
c5c77ba1 1433 if ('I' != u8MsgType) {
b92f9304 1434 netdev_err(vif->ndev, "Received Message incorrect.\n");
24db713f 1435 return -EFAULT;
c5c77ba1
JK
1436 }
1437
33722ac7
LK
1438 u8MsgID = pstrRcvdGnrlAsyncInfo->buffer[1];
1439 u16MsgLen = MAKE_WORD16(pstrRcvdGnrlAsyncInfo->buffer[2], pstrRcvdGnrlAsyncInfo->buffer[3]);
1440 u16WidID = MAKE_WORD16(pstrRcvdGnrlAsyncInfo->buffer[4], pstrRcvdGnrlAsyncInfo->buffer[5]);
1441 u8WidLen = pstrRcvdGnrlAsyncInfo->buffer[6];
1442 u8MacStatus = pstrRcvdGnrlAsyncInfo->buffer[7];
1443 u8MacStatusReasonCode = pstrRcvdGnrlAsyncInfo->buffer[8];
1444 u8MacStatusAdditionalInfo = pstrRcvdGnrlAsyncInfo->buffer[9];
b60005a8 1445 if (hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP) {
71130e81 1446 u32 u32RcvdAssocRespInfoLen = 0;
40d96e1d 1447 struct connect_resp_info *pstrConnectRespInfo = NULL;
c5c77ba1 1448
2cc46837 1449 memset(&strConnectInfo, 0, sizeof(tstrConnectInfo));
c5c77ba1
JK
1450
1451 if (u8MacStatus == MAC_CONNECTED) {
a633c0b5 1452 memset(rcv_assoc_resp, 0, MAX_ASSOC_RESP_FRAME_SIZE);
c5c77ba1 1453
71130e81 1454 host_int_get_assoc_res_info(vif,
a633c0b5 1455 rcv_assoc_resp,
c5c77ba1
JK
1456 MAX_ASSOC_RESP_FRAME_SIZE,
1457 &u32RcvdAssocRespInfoLen);
1458
c5c77ba1 1459 if (u32RcvdAssocRespInfoLen != 0) {
0e1af73d 1460 s32Err = wilc_parse_assoc_resp_info(rcv_assoc_resp, u32RcvdAssocRespInfoLen,
c5c77ba1
JK
1461 &pstrConnectRespInfo);
1462 if (s32Err) {
b92f9304 1463 netdev_err(vif->ndev, "wilc_parse_assoc_resp_info() returned error %d\n", s32Err);
c5c77ba1 1464 } else {
ba7b6ff5 1465 strConnectInfo.u16ConnectStatus = pstrConnectRespInfo->status;
c5c77ba1
JK
1466
1467 if (strConnectInfo.u16ConnectStatus == SUCCESSFUL_STATUSCODE) {
ba7b6ff5
LK
1468 if (pstrConnectRespInfo->ies) {
1469 strConnectInfo.u16RespIEsLen = pstrConnectRespInfo->ies_len;
1470 strConnectInfo.pu8RespIEs = kmalloc(pstrConnectRespInfo->ies_len, GFP_KERNEL);
1471 memcpy(strConnectInfo.pu8RespIEs, pstrConnectRespInfo->ies,
1472 pstrConnectRespInfo->ies_len);
c5c77ba1
JK
1473 }
1474 }
1475
91109e11 1476 if (pstrConnectRespInfo) {
ba7b6ff5 1477 kfree(pstrConnectRespInfo->ies);
5f79c2ae 1478 kfree(pstrConnectRespInfo);
c5c77ba1
JK
1479 }
1480 }
1481 }
1482 }
1483
c5c77ba1
JK
1484 if ((u8MacStatus == MAC_CONNECTED) &&
1485 (strConnectInfo.u16ConnectStatus != SUCCESSFUL_STATUSCODE)) {
b92f9304 1486 netdev_err(vif->ndev, "Received MAC status is MAC_CONNECTED while the received status code in Asoc Resp is not SUCCESSFUL_STATUSCODE\n");
e554a305 1487 eth_zero_addr(wilc_connected_ssid);
c5c77ba1 1488 } else if (u8MacStatus == MAC_DISCONNECTED) {
b92f9304 1489 netdev_err(vif->ndev, "Received MAC status is MAC_DISCONNECTED\n");
e554a305 1490 eth_zero_addr(wilc_connected_ssid);
c5c77ba1
JK
1491 }
1492
788f6fc0
CL
1493 if (hif_drv->usr_conn_req.bssid) {
1494 memcpy(strConnectInfo.au8bssid, hif_drv->usr_conn_req.bssid, 6);
c5c77ba1
JK
1495
1496 if ((u8MacStatus == MAC_CONNECTED) &&
1497 (strConnectInfo.u16ConnectStatus == SUCCESSFUL_STATUSCODE)) {
2a4eded9 1498 memcpy(hif_drv->assoc_bssid,
788f6fc0 1499 hif_drv->usr_conn_req.bssid, ETH_ALEN);
c5c77ba1
JK
1500 }
1501 }
1502
a3b2f4b9 1503 if (hif_drv->usr_conn_req.ies) {
331ed080
LK
1504 strConnectInfo.ReqIEsLen = hif_drv->usr_conn_req.ies_len;
1505 strConnectInfo.pu8ReqIEs = kmalloc(hif_drv->usr_conn_req.ies_len, GFP_KERNEL);
d00d2ba3 1506 memcpy(strConnectInfo.pu8ReqIEs,
a3b2f4b9 1507 hif_drv->usr_conn_req.ies,
331ed080 1508 hif_drv->usr_conn_req.ies_len);
c5c77ba1
JK
1509 }
1510
81a59506 1511 del_timer(&hif_drv->connect_timer);
33bfb198
LK
1512 hif_drv->usr_conn_req.conn_result(CONN_DISCONN_EVENT_CONN_RESP,
1513 &strConnectInfo,
1514 u8MacStatus,
1515 NULL,
73abaa49 1516 hif_drv->usr_conn_req.arg);
c5c77ba1 1517
c5c77ba1
JK
1518 if ((u8MacStatus == MAC_CONNECTED) &&
1519 (strConnectInfo.u16ConnectStatus == SUCCESSFUL_STATUSCODE)) {
fbf5379b 1520 wilc_set_power_mgmt(vif, 0, 0);
c5c77ba1 1521
b60005a8 1522 hif_drv->hif_state = HOST_IF_CONNECTED;
c5c77ba1 1523
0e1af73d
AB
1524 wilc_optaining_ip = true;
1525 mod_timer(&wilc_during_ip_timer,
9eb06643 1526 jiffies + msecs_to_jiffies(10000));
c5c77ba1 1527 } else {
b60005a8 1528 hif_drv->hif_state = HOST_IF_IDLE;
ca8540e4 1529 scan_while_connected = false;
c5c77ba1
JK
1530 }
1531
95f840fb
SB
1532 kfree(strConnectInfo.pu8RespIEs);
1533 strConnectInfo.pu8RespIEs = NULL;
c5c77ba1 1534
95f840fb
SB
1535 kfree(strConnectInfo.pu8ReqIEs);
1536 strConnectInfo.pu8ReqIEs = NULL;
74ab5e45 1537 hif_drv->usr_conn_req.ssid_len = 0;
72216411
CL
1538 kfree(hif_drv->usr_conn_req.ssid);
1539 hif_drv->usr_conn_req.ssid = NULL;
788f6fc0
CL
1540 kfree(hif_drv->usr_conn_req.bssid);
1541 hif_drv->usr_conn_req.bssid = NULL;
331ed080 1542 hif_drv->usr_conn_req.ies_len = 0;
a3b2f4b9 1543 kfree(hif_drv->usr_conn_req.ies);
cc28e4bf 1544 hif_drv->usr_conn_req.ies = NULL;
c5c77ba1 1545 } else if ((u8MacStatus == MAC_DISCONNECTED) &&
b60005a8 1546 (hif_drv->hif_state == HOST_IF_CONNECTED)) {
2cc46837 1547 memset(&strDisconnectNotifInfo, 0, sizeof(tstrDisconnectNotifInfo));
c5c77ba1 1548
bc801855 1549 if (hif_drv->usr_scan_req.scan_result) {
13b313e4 1550 del_timer(&hif_drv->scan_timer);
71130e81 1551 Handle_ScanDone(vif, SCAN_EVENT_ABORTED);
c5c77ba1
JK
1552 }
1553
1554 strDisconnectNotifInfo.u16reason = 0;
1555 strDisconnectNotifInfo.ie = NULL;
1556 strDisconnectNotifInfo.ie_len = 0;
1557
33bfb198 1558 if (hif_drv->usr_conn_req.conn_result) {
0e1af73d 1559 wilc_optaining_ip = false;
fbf5379b 1560 wilc_set_power_mgmt(vif, 0, 0);
c5c77ba1 1561
33bfb198
LK
1562 hif_drv->usr_conn_req.conn_result(CONN_DISCONN_EVENT_DISCONN_NOTIF,
1563 NULL,
1564 0,
1565 &strDisconnectNotifInfo,
73abaa49 1566 hif_drv->usr_conn_req.arg);
c5c77ba1 1567 } else {
b92f9304 1568 netdev_err(vif->ndev, "Connect result NULL\n");
c5c77ba1
JK
1569 }
1570
2a4eded9 1571 eth_zero_addr(hif_drv->assoc_bssid);
c5c77ba1 1572
74ab5e45 1573 hif_drv->usr_conn_req.ssid_len = 0;
72216411
CL
1574 kfree(hif_drv->usr_conn_req.ssid);
1575 hif_drv->usr_conn_req.ssid = NULL;
788f6fc0
CL
1576 kfree(hif_drv->usr_conn_req.bssid);
1577 hif_drv->usr_conn_req.bssid = NULL;
331ed080 1578 hif_drv->usr_conn_req.ies_len = 0;
a3b2f4b9 1579 kfree(hif_drv->usr_conn_req.ies);
cc28e4bf 1580 hif_drv->usr_conn_req.ies = NULL;
c5c77ba1 1581
7036c624 1582 if (join_req && join_req_vif == vif) {
044a6410
LK
1583 kfree(join_req);
1584 join_req = NULL;
c5c77ba1 1585 }
48ce2465 1586
7036c624 1587 if (info_element && join_req_vif == vif) {
48ce2465
LK
1588 kfree(info_element);
1589 info_element = NULL;
c5c77ba1
JK
1590 }
1591
b60005a8 1592 hif_drv->hif_state = HOST_IF_IDLE;
ca8540e4 1593 scan_while_connected = false;
c5c77ba1
JK
1594
1595 } else if ((u8MacStatus == MAC_DISCONNECTED) &&
bc801855 1596 (hif_drv->usr_scan_req.scan_result)) {
13b313e4 1597 del_timer(&hif_drv->scan_timer);
bc801855 1598 if (hif_drv->usr_scan_req.scan_result)
71130e81 1599 Handle_ScanDone(vif, SCAN_EVENT_ABORTED);
c5c77ba1 1600 }
c5c77ba1
JK
1601 }
1602
95f840fb
SB
1603 kfree(pstrRcvdGnrlAsyncInfo->buffer);
1604 pstrRcvdGnrlAsyncInfo->buffer = NULL;
c5c77ba1 1605
31390eec 1606 return result;
c5c77ba1
JK
1607}
1608
71130e81 1609static int Handle_Key(struct wilc_vif *vif,
c98387a5 1610 struct key_attr *pstrHostIFkeyAttr)
c5c77ba1 1611{
31390eec 1612 s32 result = 0;
45102f83 1613 struct wid wid;
e9e0c260 1614 struct wid strWIDList[5];
63d03e47
GKH
1615 u8 i;
1616 u8 *pu8keybuf;
ca356ada
CL
1617 s8 s8idxarray[1];
1618 s8 ret = 0;
71130e81 1619 struct host_if_drv *hif_drv = vif->hif_drv;
c5c77ba1 1620
8e9f427a 1621 switch (pstrHostIFkeyAttr->type) {
c5c77ba1
JK
1622 case WEP:
1623
0d17e382 1624 if (pstrHostIFkeyAttr->action & ADDKEY_AP) {
daaf16ba 1625 strWIDList[0].id = (u16)WID_11I_MODE;
416d8321 1626 strWIDList[0].type = WID_CHAR;
2fd3e443 1627 strWIDList[0].size = sizeof(char);
bafaa696 1628 strWIDList[0].val = (s8 *)&pstrHostIFkeyAttr->attr.wep.mode;
c5c77ba1 1629
daaf16ba 1630 strWIDList[1].id = WID_AUTH_TYPE;
416d8321 1631 strWIDList[1].type = WID_CHAR;
2fd3e443 1632 strWIDList[1].size = sizeof(char);
bafaa696 1633 strWIDList[1].val = (s8 *)&pstrHostIFkeyAttr->attr.wep.auth_type;
c5c77ba1 1634
ec450483 1635 pu8keybuf = kmalloc(pstrHostIFkeyAttr->attr.wep.key_len + 2,
543f5b13 1636 GFP_KERNEL);
77f3a71f 1637 if (!pu8keybuf)
9081987d 1638 return -ENOMEM;
c5c77ba1 1639
ec450483
GL
1640 pu8keybuf[0] = pstrHostIFkeyAttr->attr.wep.index;
1641 pu8keybuf[1] = pstrHostIFkeyAttr->attr.wep.key_len;
1642
1643 memcpy(&pu8keybuf[2], pstrHostIFkeyAttr->attr.wep.key,
1644 pstrHostIFkeyAttr->attr.wep.key_len);
1645
73b2e381 1646 kfree(pstrHostIFkeyAttr->attr.wep.key);
c5c77ba1 1647
ec450483
GL
1648 strWIDList[2].id = (u16)WID_WEP_KEY_VALUE;
1649 strWIDList[2].type = WID_STR;
1650 strWIDList[2].size = pstrHostIFkeyAttr->attr.wep.key_len + 2;
1651 strWIDList[2].val = (s8 *)pu8keybuf;
c5c77ba1 1652
79df6a49 1653 result = wilc_send_config_pkt(vif, SET_CFG,
ec450483 1654 strWIDList, 3,
4cf93d70 1655 wilc_get_vif_idx(vif));
49188af2 1656 kfree(pu8keybuf);
9edaa5f3 1657 } else if (pstrHostIFkeyAttr->action & ADDKEY) {
73b2e381 1658 pu8keybuf = kmalloc(pstrHostIFkeyAttr->attr.wep.key_len + 2, GFP_KERNEL);
77f3a71f 1659 if (!pu8keybuf)
9081987d 1660 return -ENOMEM;
73b2e381
LK
1661 pu8keybuf[0] = pstrHostIFkeyAttr->attr.wep.index;
1662 memcpy(pu8keybuf + 1, &pstrHostIFkeyAttr->attr.wep.key_len, 1);
1663 memcpy(pu8keybuf + 2, pstrHostIFkeyAttr->attr.wep.key,
8c8360b3 1664 pstrHostIFkeyAttr->attr.wep.key_len);
73b2e381 1665 kfree(pstrHostIFkeyAttr->attr.wep.key);
c5c77ba1 1666
45102f83
LK
1667 wid.id = (u16)WID_ADD_WEP_KEY;
1668 wid.type = WID_STR;
1669 wid.val = (s8 *)pu8keybuf;
1670 wid.size = pstrHostIFkeyAttr->attr.wep.key_len + 2;
c5c77ba1 1671
79df6a49 1672 result = wilc_send_config_pkt(vif, SET_CFG,
4cf93d70
CL
1673 &wid, 1,
1674 wilc_get_vif_idx(vif));
49188af2 1675 kfree(pu8keybuf);
0d17e382 1676 } else if (pstrHostIFkeyAttr->action & REMOVEKEY) {
45102f83
LK
1677 wid.id = (u16)WID_REMOVE_WEP_KEY;
1678 wid.type = WID_STR;
c5c77ba1 1679
73b2e381 1680 s8idxarray[0] = (s8)pstrHostIFkeyAttr->attr.wep.index;
45102f83
LK
1681 wid.val = s8idxarray;
1682 wid.size = 1;
c5c77ba1 1683
79df6a49 1684 result = wilc_send_config_pkt(vif, SET_CFG,
4cf93d70
CL
1685 &wid, 1,
1686 wilc_get_vif_idx(vif));
ec450483 1687 } else if (pstrHostIFkeyAttr->action & DEFAULTKEY) {
45102f83
LK
1688 wid.id = (u16)WID_KEY_ID;
1689 wid.type = WID_CHAR;
1690 wid.val = (s8 *)&pstrHostIFkeyAttr->attr.wep.index;
1691 wid.size = sizeof(char);
c5c77ba1 1692
79df6a49 1693 result = wilc_send_config_pkt(vif, SET_CFG,
4cf93d70
CL
1694 &wid, 1,
1695 wilc_get_vif_idx(vif));
c5c77ba1 1696 }
9ea47133 1697 up(&hif_drv->sem_test_key_block);
c5c77ba1
JK
1698 break;
1699
5cd8f7ae 1700 case WPA_RX_GTK:
0d17e382 1701 if (pstrHostIFkeyAttr->action & ADDKEY_AP) {
b156f1ed 1702 pu8keybuf = kzalloc(RX_MIC_KEY_MSG_LEN, GFP_KERNEL);
91109e11 1703 if (!pu8keybuf) {
9081987d 1704 ret = -ENOMEM;
c5c77ba1
JK
1705 goto _WPARxGtk_end_case_;
1706 }
1707
91109e11 1708 if (pstrHostIFkeyAttr->attr.wpa.seq)
0e74c009 1709 memcpy(pu8keybuf + 6, pstrHostIFkeyAttr->attr.wpa.seq, 8);
c5c77ba1 1710
e2dfbac5 1711 memcpy(pu8keybuf + 14, &pstrHostIFkeyAttr->attr.wpa.index, 1);
6acf2919 1712 memcpy(pu8keybuf + 15, &pstrHostIFkeyAttr->attr.wpa.key_len, 1);
124968fc 1713 memcpy(pu8keybuf + 16, pstrHostIFkeyAttr->attr.wpa.key,
8c8360b3 1714 pstrHostIFkeyAttr->attr.wpa.key_len);
c5c77ba1 1715
daaf16ba 1716 strWIDList[0].id = (u16)WID_11I_MODE;
416d8321 1717 strWIDList[0].type = WID_CHAR;
2fd3e443 1718 strWIDList[0].size = sizeof(char);
bafaa696 1719 strWIDList[0].val = (s8 *)&pstrHostIFkeyAttr->attr.wpa.mode;
c5c77ba1 1720
daaf16ba 1721 strWIDList[1].id = (u16)WID_ADD_RX_GTK;
416d8321 1722 strWIDList[1].type = WID_STR;
900bb4a6 1723 strWIDList[1].val = (s8 *)pu8keybuf;
2fd3e443 1724 strWIDList[1].size = RX_MIC_KEY_MSG_LEN;
c5c77ba1 1725
79df6a49 1726 result = wilc_send_config_pkt(vif, SET_CFG,
4cf93d70
CL
1727 strWIDList, 2,
1728 wilc_get_vif_idx(vif));
c5c77ba1 1729
49188af2 1730 kfree(pu8keybuf);
9ea47133 1731 up(&hif_drv->sem_test_key_block);
9edaa5f3 1732 } else if (pstrHostIFkeyAttr->action & ADDKEY) {
b156f1ed 1733 pu8keybuf = kzalloc(RX_MIC_KEY_MSG_LEN, GFP_KERNEL);
c5c77ba1 1734 if (pu8keybuf == NULL) {
9081987d 1735 ret = -ENOMEM;
c5c77ba1
JK
1736 goto _WPARxGtk_end_case_;
1737 }
1738
b60005a8 1739 if (hif_drv->hif_state == HOST_IF_CONNECTED)
2a4eded9 1740 memcpy(pu8keybuf, hif_drv->assoc_bssid, ETH_ALEN);
78174ada 1741 else
b92f9304 1742 netdev_err(vif->ndev, "Couldn't handle\n");
c5c77ba1 1743
0e74c009 1744 memcpy(pu8keybuf + 6, pstrHostIFkeyAttr->attr.wpa.seq, 8);
e2dfbac5 1745 memcpy(pu8keybuf + 14, &pstrHostIFkeyAttr->attr.wpa.index, 1);
6acf2919 1746 memcpy(pu8keybuf + 15, &pstrHostIFkeyAttr->attr.wpa.key_len, 1);
124968fc 1747 memcpy(pu8keybuf + 16, pstrHostIFkeyAttr->attr.wpa.key,
8c8360b3 1748 pstrHostIFkeyAttr->attr.wpa.key_len);
c5c77ba1 1749
45102f83
LK
1750 wid.id = (u16)WID_ADD_RX_GTK;
1751 wid.type = WID_STR;
1752 wid.val = (s8 *)pu8keybuf;
1753 wid.size = RX_MIC_KEY_MSG_LEN;
c5c77ba1 1754
79df6a49 1755 result = wilc_send_config_pkt(vif, SET_CFG,
4cf93d70
CL
1756 &wid, 1,
1757 wilc_get_vif_idx(vif));
c5c77ba1 1758
49188af2 1759 kfree(pu8keybuf);
9ea47133 1760 up(&hif_drv->sem_test_key_block);
c5c77ba1
JK
1761 }
1762_WPARxGtk_end_case_:
124968fc 1763 kfree(pstrHostIFkeyAttr->attr.wpa.key);
0e74c009 1764 kfree(pstrHostIFkeyAttr->attr.wpa.seq);
9081987d 1765 if (ret)
c5c77ba1
JK
1766 return ret;
1767
1768 break;
1769
2141fe39 1770 case WPA_PTK:
0d17e382 1771 if (pstrHostIFkeyAttr->action & ADDKEY_AP) {
f3052587 1772 pu8keybuf = kmalloc(PTK_KEY_MSG_LEN + 1, GFP_KERNEL);
91109e11 1773 if (!pu8keybuf) {
9081987d 1774 ret = -ENOMEM;
c5c77ba1 1775 goto _WPAPtk_end_case_;
c5c77ba1
JK
1776 }
1777
248080aa 1778 memcpy(pu8keybuf, pstrHostIFkeyAttr->attr.wpa.mac_addr, 6);
e2dfbac5 1779 memcpy(pu8keybuf + 6, &pstrHostIFkeyAttr->attr.wpa.index, 1);
6acf2919 1780 memcpy(pu8keybuf + 7, &pstrHostIFkeyAttr->attr.wpa.key_len, 1);
124968fc 1781 memcpy(pu8keybuf + 8, pstrHostIFkeyAttr->attr.wpa.key,
8c8360b3 1782 pstrHostIFkeyAttr->attr.wpa.key_len);
c5c77ba1 1783
daaf16ba 1784 strWIDList[0].id = (u16)WID_11I_MODE;
416d8321 1785 strWIDList[0].type = WID_CHAR;
2fd3e443 1786 strWIDList[0].size = sizeof(char);
bafaa696 1787 strWIDList[0].val = (s8 *)&pstrHostIFkeyAttr->attr.wpa.mode;
c5c77ba1 1788
daaf16ba 1789 strWIDList[1].id = (u16)WID_ADD_PTK;
416d8321 1790 strWIDList[1].type = WID_STR;
900bb4a6 1791 strWIDList[1].val = (s8 *)pu8keybuf;
2fd3e443 1792 strWIDList[1].size = PTK_KEY_MSG_LEN + 1;
c5c77ba1 1793
79df6a49 1794 result = wilc_send_config_pkt(vif, SET_CFG,
4cf93d70
CL
1795 strWIDList, 2,
1796 wilc_get_vif_idx(vif));
49188af2 1797 kfree(pu8keybuf);
9ea47133 1798 up(&hif_drv->sem_test_key_block);
9edaa5f3 1799 } else if (pstrHostIFkeyAttr->action & ADDKEY) {
f3052587 1800 pu8keybuf = kmalloc(PTK_KEY_MSG_LEN, GFP_KERNEL);
91109e11 1801 if (!pu8keybuf) {
b92f9304 1802 netdev_err(vif->ndev, "No buffer send PTK\n");
9081987d 1803 ret = -ENOMEM;
c5c77ba1 1804 goto _WPAPtk_end_case_;
c5c77ba1
JK
1805 }
1806
248080aa 1807 memcpy(pu8keybuf, pstrHostIFkeyAttr->attr.wpa.mac_addr, 6);
6acf2919 1808 memcpy(pu8keybuf + 6, &pstrHostIFkeyAttr->attr.wpa.key_len, 1);
124968fc 1809 memcpy(pu8keybuf + 7, pstrHostIFkeyAttr->attr.wpa.key,
8c8360b3 1810 pstrHostIFkeyAttr->attr.wpa.key_len);
c5c77ba1 1811
45102f83
LK
1812 wid.id = (u16)WID_ADD_PTK;
1813 wid.type = WID_STR;
1814 wid.val = (s8 *)pu8keybuf;
1815 wid.size = PTK_KEY_MSG_LEN;
c5c77ba1 1816
79df6a49 1817 result = wilc_send_config_pkt(vif, SET_CFG,
4cf93d70
CL
1818 &wid, 1,
1819 wilc_get_vif_idx(vif));
49188af2 1820 kfree(pu8keybuf);
9ea47133 1821 up(&hif_drv->sem_test_key_block);
c5c77ba1
JK
1822 }
1823
1824_WPAPtk_end_case_:
124968fc 1825 kfree(pstrHostIFkeyAttr->attr.wpa.key);
9081987d 1826 if (ret)
c5c77ba1
JK
1827 return ret;
1828
1829 break;
1830
c5c77ba1 1831 case PMKSA:
73b2e381 1832 pu8keybuf = kmalloc((pstrHostIFkeyAttr->attr.pmkid.numpmkid * PMKSA_KEY_LEN) + 1, GFP_KERNEL);
91109e11 1833 if (!pu8keybuf) {
b92f9304 1834 netdev_err(vif->ndev, "No buffer to send PMKSA Key\n");
9081987d 1835 return -ENOMEM;
c5c77ba1
JK
1836 }
1837
73b2e381 1838 pu8keybuf[0] = pstrHostIFkeyAttr->attr.pmkid.numpmkid;
c5c77ba1 1839
73b2e381
LK
1840 for (i = 0; i < pstrHostIFkeyAttr->attr.pmkid.numpmkid; i++) {
1841 memcpy(pu8keybuf + ((PMKSA_KEY_LEN * i) + 1), pstrHostIFkeyAttr->attr.pmkid.pmkidlist[i].bssid, ETH_ALEN);
1842 memcpy(pu8keybuf + ((PMKSA_KEY_LEN * i) + ETH_ALEN + 1), pstrHostIFkeyAttr->attr.pmkid.pmkidlist[i].pmkid, PMKID_LEN);
c5c77ba1
JK
1843 }
1844
45102f83
LK
1845 wid.id = (u16)WID_PMKID_INFO;
1846 wid.type = WID_STR;
1847 wid.val = (s8 *)pu8keybuf;
1848 wid.size = (pstrHostIFkeyAttr->attr.pmkid.numpmkid * PMKSA_KEY_LEN) + 1;
c5c77ba1 1849
79df6a49 1850 result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1,
4cf93d70 1851 wilc_get_vif_idx(vif));
c5c77ba1 1852
49188af2 1853 kfree(pu8keybuf);
c5c77ba1
JK
1854 break;
1855 }
1856
31390eec 1857 if (result)
b92f9304 1858 netdev_err(vif->ndev, "Failed to send key config packet\n");
c5c77ba1 1859
31390eec 1860 return result;
c5c77ba1
JK
1861}
1862
71130e81 1863static void Handle_Disconnect(struct wilc_vif *vif)
c5c77ba1 1864{
45102f83 1865 struct wid wid;
71130e81 1866 struct host_if_drv *hif_drv = vif->hif_drv;
c5c77ba1 1867
31390eec 1868 s32 result = 0;
d85f5326 1869 u16 u16DummyReasonCode = 0;
c5c77ba1 1870
45102f83
LK
1871 wid.id = (u16)WID_DISCONNECT;
1872 wid.type = WID_CHAR;
1873 wid.val = (s8 *)&u16DummyReasonCode;
1874 wid.size = sizeof(char);
c5c77ba1 1875
0e1af73d 1876 wilc_optaining_ip = false;
fbf5379b 1877 wilc_set_power_mgmt(vif, 0, 0);
c5c77ba1 1878
e554a305 1879 eth_zero_addr(wilc_connected_ssid);
c5c77ba1 1880
79df6a49 1881 result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1,
4cf93d70 1882 wilc_get_vif_idx(vif));
c5c77ba1 1883
31390eec 1884 if (result) {
b92f9304 1885 netdev_err(vif->ndev, "Failed to send dissconect\n");
c5c77ba1
JK
1886 } else {
1887 tstrDisconnectNotifInfo strDisconnectNotifInfo;
1888
2cc46837 1889 memset(&strDisconnectNotifInfo, 0, sizeof(tstrDisconnectNotifInfo));
c5c77ba1
JK
1890
1891 strDisconnectNotifInfo.u16reason = 0;
1892 strDisconnectNotifInfo.ie = NULL;
1893 strDisconnectNotifInfo.ie_len = 0;
1894
bc801855 1895 if (hif_drv->usr_scan_req.scan_result) {
13b313e4 1896 del_timer(&hif_drv->scan_timer);
33bfb198
LK
1897 hif_drv->usr_scan_req.scan_result(SCAN_EVENT_ABORTED,
1898 NULL,
1899 hif_drv->usr_scan_req.arg,
1900 NULL);
bc801855 1901 hif_drv->usr_scan_req.scan_result = NULL;
c5c77ba1
JK
1902 }
1903
33bfb198 1904 if (hif_drv->usr_conn_req.conn_result) {
c4f97526 1905 if (hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP)
81a59506 1906 del_timer(&hif_drv->connect_timer);
c5c77ba1 1907
33bfb198
LK
1908 hif_drv->usr_conn_req.conn_result(CONN_DISCONN_EVENT_DISCONN_NOTIF,
1909 NULL,
1910 0,
1911 &strDisconnectNotifInfo,
73abaa49 1912 hif_drv->usr_conn_req.arg);
c5c77ba1 1913 } else {
b92f9304 1914 netdev_err(vif->ndev, "conn_result = NULL\n");
c5c77ba1
JK
1915 }
1916
ca8540e4 1917 scan_while_connected = false;
c5c77ba1 1918
b60005a8 1919 hif_drv->hif_state = HOST_IF_IDLE;
c5c77ba1 1920
2a4eded9 1921 eth_zero_addr(hif_drv->assoc_bssid);
c5c77ba1 1922
74ab5e45 1923 hif_drv->usr_conn_req.ssid_len = 0;
72216411
CL
1924 kfree(hif_drv->usr_conn_req.ssid);
1925 hif_drv->usr_conn_req.ssid = NULL;
788f6fc0
CL
1926 kfree(hif_drv->usr_conn_req.bssid);
1927 hif_drv->usr_conn_req.bssid = NULL;
331ed080 1928 hif_drv->usr_conn_req.ies_len = 0;
a3b2f4b9 1929 kfree(hif_drv->usr_conn_req.ies);
cc28e4bf 1930 hif_drv->usr_conn_req.ies = NULL;
c5c77ba1 1931
7036c624 1932 if (join_req && join_req_vif == vif) {
044a6410
LK
1933 kfree(join_req);
1934 join_req = NULL;
c5c77ba1 1935 }
48ce2465 1936
7036c624 1937 if (info_element && join_req_vif == vif) {
48ce2465
LK
1938 kfree(info_element);
1939 info_element = NULL;
c5c77ba1 1940 }
c5c77ba1
JK
1941 }
1942
e55e4967 1943 up(&hif_drv->sem_test_disconn_block);
c5c77ba1
JK
1944}
1945
fbf5379b 1946void wilc_resolve_disconnect_aberration(struct wilc_vif *vif)
c5c77ba1 1947{
fbf5379b 1948 if (!vif->hif_drv)
c5c77ba1 1949 return;
fbf5379b 1950 if ((vif->hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP) ||
c4f97526 1951 (vif->hif_drv->hif_state == HOST_IF_CONNECTING))
fbf5379b 1952 wilc_disconnect(vif, 1);
c5c77ba1 1953}
c5c77ba1 1954
71130e81 1955static s32 Handle_GetChnl(struct wilc_vif *vif)
c5c77ba1 1956{
31390eec 1957 s32 result = 0;
45102f83 1958 struct wid wid;
78c87591 1959
45102f83
LK
1960 wid.id = (u16)WID_CURRENT_CHANNEL;
1961 wid.type = WID_CHAR;
1962 wid.val = (s8 *)&ch_no;
1963 wid.size = sizeof(char);
c5c77ba1 1964
79df6a49 1965 result = wilc_send_config_pkt(vif, GET_CFG, &wid, 1,
4cf93d70 1966 wilc_get_vif_idx(vif));
ae4dfa57 1967
31390eec 1968 if (result) {
b92f9304 1969 netdev_err(vif->ndev, "Failed to get channel number\n");
31390eec 1970 result = -EFAULT;
c5c77ba1
JK
1971 }
1972
31390eec 1973 return result;
c5c77ba1
JK
1974}
1975
71130e81 1976static void Handle_GetRssi(struct wilc_vif *vif)
c5c77ba1 1977{
31390eec 1978 s32 result = 0;
45102f83 1979 struct wid wid;
c5c77ba1 1980
45102f83
LK
1981 wid.id = (u16)WID_RSSI;
1982 wid.type = WID_CHAR;
1983 wid.val = &rssi;
1984 wid.size = sizeof(char);
c5c77ba1 1985
79df6a49 1986 result = wilc_send_config_pkt(vif, GET_CFG, &wid, 1,
4cf93d70 1987 wilc_get_vif_idx(vif));
31390eec 1988 if (result) {
b92f9304 1989 netdev_err(vif->ndev, "Failed to get RSSI value\n");
31390eec 1990 result = -EFAULT;
c5c77ba1
JK
1991 }
1992
71130e81 1993 up(&vif->hif_drv->sem_get_rssi);
c5c77ba1
JK
1994}
1995
71130e81 1996static void Handle_GetLinkspeed(struct wilc_vif *vif)
c5c77ba1 1997{
31390eec 1998 s32 result = 0;
45102f83 1999 struct wid wid;
c5c77ba1 2000
75327a02 2001 link_speed = 0;
c5c77ba1 2002
45102f83
LK
2003 wid.id = (u16)WID_LINKSPEED;
2004 wid.type = WID_CHAR;
2005 wid.val = &link_speed;
2006 wid.size = sizeof(char);
ae4dfa57 2007
79df6a49 2008 result = wilc_send_config_pkt(vif, GET_CFG, &wid, 1,
4cf93d70 2009 wilc_get_vif_idx(vif));
31390eec 2010 if (result) {
b92f9304 2011 netdev_err(vif->ndev, "Failed to get LINKSPEED value\n");
31390eec 2012 result = -EFAULT;
c5c77ba1
JK
2013 }
2014
c5c77ba1
JK
2015}
2016
71130e81
GL
2017static s32 Handle_GetStatistics(struct wilc_vif *vif,
2018 struct rf_info *pstrStatistics)
c5c77ba1 2019{
e9e0c260 2020 struct wid strWIDList[5];
31390eec 2021 u32 u32WidsCount = 0, result = 0;
c5c77ba1 2022
daaf16ba 2023 strWIDList[u32WidsCount].id = WID_LINKSPEED;
416d8321 2024 strWIDList[u32WidsCount].type = WID_CHAR;
2fd3e443 2025 strWIDList[u32WidsCount].size = sizeof(char);
5babeecb 2026 strWIDList[u32WidsCount].val = (s8 *)&pstrStatistics->link_speed;
c5c77ba1
JK
2027 u32WidsCount++;
2028
daaf16ba 2029 strWIDList[u32WidsCount].id = WID_RSSI;
416d8321 2030 strWIDList[u32WidsCount].type = WID_CHAR;
2fd3e443 2031 strWIDList[u32WidsCount].size = sizeof(char);
00c8dfcf 2032 strWIDList[u32WidsCount].val = (s8 *)&pstrStatistics->rssi;
c5c77ba1
JK
2033 u32WidsCount++;
2034
daaf16ba 2035 strWIDList[u32WidsCount].id = WID_SUCCESS_FRAME_COUNT;
416d8321 2036 strWIDList[u32WidsCount].type = WID_INT;
2fd3e443 2037 strWIDList[u32WidsCount].size = sizeof(u32);
7e84ff4e 2038 strWIDList[u32WidsCount].val = (s8 *)&pstrStatistics->tx_cnt;
c5c77ba1
JK
2039 u32WidsCount++;
2040
daaf16ba 2041 strWIDList[u32WidsCount].id = WID_RECEIVED_FRAGMENT_COUNT;
416d8321 2042 strWIDList[u32WidsCount].type = WID_INT;
2fd3e443 2043 strWIDList[u32WidsCount].size = sizeof(u32);
9b99274a 2044 strWIDList[u32WidsCount].val = (s8 *)&pstrStatistics->rx_cnt;
c5c77ba1
JK
2045 u32WidsCount++;
2046
daaf16ba 2047 strWIDList[u32WidsCount].id = WID_FAILED_COUNT;
416d8321 2048 strWIDList[u32WidsCount].type = WID_INT;
2fd3e443 2049 strWIDList[u32WidsCount].size = sizeof(u32);
54160376 2050 strWIDList[u32WidsCount].val = (s8 *)&pstrStatistics->tx_fail_cnt;
c5c77ba1
JK
2051 u32WidsCount++;
2052
79df6a49 2053 result = wilc_send_config_pkt(vif, GET_CFG, strWIDList,
4cf93d70
CL
2054 u32WidsCount,
2055 wilc_get_vif_idx(vif));
c5c77ba1 2056
31390eec 2057 if (result)
b92f9304 2058 netdev_err(vif->ndev, "Failed to send scan parameters\n");
24db713f 2059
4fd62291
GL
2060 if (pstrStatistics->link_speed > TCP_ACK_FILTER_LINK_SPEED_THRESH &&
2061 pstrStatistics->link_speed != DEFAULT_LINK_SPEED)
2062 wilc_enable_tcp_ack_filter(true);
2063 else if (pstrStatistics->link_speed != DEFAULT_LINK_SPEED)
2064 wilc_enable_tcp_ack_filter(false);
2065
2066 if (pstrStatistics != &vif->wilc->dummy_statistics)
2067 up(&hif_sema_wait_response);
c5c77ba1 2068 return 0;
c5c77ba1
JK
2069}
2070
71130e81 2071static s32 Handle_Get_InActiveTime(struct wilc_vif *vif,
3d1eac04 2072 struct sta_inactive_t *strHostIfStaInactiveT)
c5c77ba1 2073{
31390eec 2074 s32 result = 0;
63d03e47 2075 u8 *stamac;
45102f83 2076 struct wid wid;
71130e81 2077 struct host_if_drv *hif_drv = vif->hif_drv;
c5c77ba1 2078
45102f83
LK
2079 wid.id = (u16)WID_SET_STA_MAC_INACTIVE_TIME;
2080 wid.type = WID_STR;
2081 wid.size = ETH_ALEN;
2082 wid.val = kmalloc(wid.size, GFP_KERNEL);
c5c77ba1 2083
45102f83 2084 stamac = wid.val;
d00d2ba3 2085 memcpy(stamac, strHostIfStaInactiveT->mac, ETH_ALEN);
c5c77ba1 2086
79df6a49 2087 result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1,
4cf93d70 2088 wilc_get_vif_idx(vif));
ae4dfa57 2089
31390eec 2090 if (result) {
b92f9304 2091 netdev_err(vif->ndev, "Failed to SET incative time\n");
24db713f 2092 return -EFAULT;
c5c77ba1
JK
2093 }
2094
45102f83
LK
2095 wid.id = (u16)WID_GET_INACTIVE_TIME;
2096 wid.type = WID_INT;
2097 wid.val = (s8 *)&inactive_time;
2098 wid.size = sizeof(u32);
c5c77ba1 2099
79df6a49 2100 result = wilc_send_config_pkt(vif, GET_CFG, &wid, 1,
4cf93d70 2101 wilc_get_vif_idx(vif));
ae4dfa57 2102
31390eec 2103 if (result) {
b92f9304 2104 netdev_err(vif->ndev, "Failed to get incative time\n");
24db713f 2105 return -EFAULT;
c5c77ba1
JK
2106 }
2107
569a3c67 2108 up(&hif_drv->sem_inactive_time);
c5c77ba1 2109
31390eec 2110 return result;
c5c77ba1
JK
2111}
2112
71130e81 2113static void Handle_AddBeacon(struct wilc_vif *vif,
7f33fecd 2114 struct beacon_attr *pstrSetBeaconParam)
c5c77ba1 2115{
31390eec 2116 s32 result = 0;
45102f83 2117 struct wid wid;
63d03e47 2118 u8 *pu8CurrByte;
78c87591 2119
45102f83
LK
2120 wid.id = (u16)WID_ADD_BEACON;
2121 wid.type = WID_BIN;
2122 wid.size = pstrSetBeaconParam->head_len + pstrSetBeaconParam->tail_len + 16;
2123 wid.val = kmalloc(wid.size, GFP_KERNEL);
2124 if (!wid.val)
24db713f 2125 goto ERRORHANDLER;
c5c77ba1 2126
45102f83 2127 pu8CurrByte = wid.val;
12262dda
LK
2128 *pu8CurrByte++ = (pstrSetBeaconParam->interval & 0xFF);
2129 *pu8CurrByte++ = ((pstrSetBeaconParam->interval >> 8) & 0xFF);
2130 *pu8CurrByte++ = ((pstrSetBeaconParam->interval >> 16) & 0xFF);
2131 *pu8CurrByte++ = ((pstrSetBeaconParam->interval >> 24) & 0xFF);
c5c77ba1 2132
e76ab770
LK
2133 *pu8CurrByte++ = (pstrSetBeaconParam->dtim_period & 0xFF);
2134 *pu8CurrByte++ = ((pstrSetBeaconParam->dtim_period >> 8) & 0xFF);
2135 *pu8CurrByte++ = ((pstrSetBeaconParam->dtim_period >> 16) & 0xFF);
2136 *pu8CurrByte++ = ((pstrSetBeaconParam->dtim_period >> 24) & 0xFF);
c5c77ba1 2137
51c66185
LK
2138 *pu8CurrByte++ = (pstrSetBeaconParam->head_len & 0xFF);
2139 *pu8CurrByte++ = ((pstrSetBeaconParam->head_len >> 8) & 0xFF);
2140 *pu8CurrByte++ = ((pstrSetBeaconParam->head_len >> 16) & 0xFF);
2141 *pu8CurrByte++ = ((pstrSetBeaconParam->head_len >> 24) & 0xFF);
c5c77ba1 2142
8ce528b9 2143 memcpy(pu8CurrByte, pstrSetBeaconParam->head, pstrSetBeaconParam->head_len);
51c66185 2144 pu8CurrByte += pstrSetBeaconParam->head_len;
c5c77ba1 2145
030c57e2
LK
2146 *pu8CurrByte++ = (pstrSetBeaconParam->tail_len & 0xFF);
2147 *pu8CurrByte++ = ((pstrSetBeaconParam->tail_len >> 8) & 0xFF);
2148 *pu8CurrByte++ = ((pstrSetBeaconParam->tail_len >> 16) & 0xFF);
2149 *pu8CurrByte++ = ((pstrSetBeaconParam->tail_len >> 24) & 0xFF);
c5c77ba1 2150
7cf8e59e 2151 if (pstrSetBeaconParam->tail)
7dbcb6d3 2152 memcpy(pu8CurrByte, pstrSetBeaconParam->tail, pstrSetBeaconParam->tail_len);
030c57e2 2153 pu8CurrByte += pstrSetBeaconParam->tail_len;
c5c77ba1 2154
79df6a49
GL
2155 result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1,
2156 wilc_get_vif_idx(vif));
31390eec 2157 if (result)
b92f9304 2158 netdev_err(vif->ndev, "Failed to send add beacon\n");
c5c77ba1 2159
24db713f 2160ERRORHANDLER:
45102f83 2161 kfree(wid.val);
8ce528b9 2162 kfree(pstrSetBeaconParam->head);
7dbcb6d3 2163 kfree(pstrSetBeaconParam->tail);
c5c77ba1
JK
2164}
2165
71130e81 2166static void Handle_DelBeacon(struct wilc_vif *vif)
c5c77ba1 2167{
31390eec 2168 s32 result = 0;
45102f83 2169 struct wid wid;
63d03e47 2170 u8 *pu8CurrByte;
78c87591 2171
45102f83
LK
2172 wid.id = (u16)WID_DEL_BEACON;
2173 wid.type = WID_CHAR;
2174 wid.size = sizeof(char);
2175 wid.val = &del_beacon;
c5c77ba1 2176
45102f83 2177 if (!wid.val)
24db713f 2178 return;
c5c77ba1 2179
45102f83 2180 pu8CurrByte = wid.val;
c5c77ba1 2181
79df6a49 2182 result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1,
4cf93d70 2183 wilc_get_vif_idx(vif));
31390eec 2184 if (result)
b92f9304 2185 netdev_err(vif->ndev, "Failed to send delete beacon\n");
c5c77ba1
JK
2186}
2187
6a89ba9c
TC
2188static u32 WILC_HostIf_PackStaParam(u8 *pu8Buffer,
2189 struct add_sta_param *pstrStationParam)
c5c77ba1 2190{
63d03e47 2191 u8 *pu8CurrByte;
c5c77ba1
JK
2192
2193 pu8CurrByte = pu8Buffer;
2194
2353c388 2195 memcpy(pu8CurrByte, pstrStationParam->bssid, ETH_ALEN);
c5c77ba1
JK
2196 pu8CurrByte += ETH_ALEN;
2197
4101eb8a
LK
2198 *pu8CurrByte++ = pstrStationParam->aid & 0xFF;
2199 *pu8CurrByte++ = (pstrStationParam->aid >> 8) & 0xFF;
c5c77ba1 2200
e734223c
LK
2201 *pu8CurrByte++ = pstrStationParam->rates_len;
2202 if (pstrStationParam->rates_len > 0)
a622e016 2203 memcpy(pu8CurrByte, pstrStationParam->rates,
e734223c
LK
2204 pstrStationParam->rates_len);
2205 pu8CurrByte += pstrStationParam->rates_len;
c5c77ba1 2206
22520120 2207 *pu8CurrByte++ = pstrStationParam->ht_supported;
0d073f69
LK
2208 *pu8CurrByte++ = pstrStationParam->ht_capa_info & 0xFF;
2209 *pu8CurrByte++ = (pstrStationParam->ht_capa_info >> 8) & 0xFF;
c5c77ba1 2210
fba1f2d2 2211 *pu8CurrByte++ = pstrStationParam->ht_ampdu_params;
5ebbf4f7
LK
2212 memcpy(pu8CurrByte, pstrStationParam->ht_supp_mcs_set,
2213 WILC_SUPP_MCS_SET_SIZE);
c5c77ba1
JK
2214 pu8CurrByte += WILC_SUPP_MCS_SET_SIZE;
2215
223741d7
LK
2216 *pu8CurrByte++ = pstrStationParam->ht_ext_params & 0xFF;
2217 *pu8CurrByte++ = (pstrStationParam->ht_ext_params >> 8) & 0xFF;
c5c77ba1 2218
74fe73cf
LK
2219 *pu8CurrByte++ = pstrStationParam->ht_tx_bf_cap & 0xFF;
2220 *pu8CurrByte++ = (pstrStationParam->ht_tx_bf_cap >> 8) & 0xFF;
2221 *pu8CurrByte++ = (pstrStationParam->ht_tx_bf_cap >> 16) & 0xFF;
2222 *pu8CurrByte++ = (pstrStationParam->ht_tx_bf_cap >> 24) & 0xFF;
c5c77ba1 2223
a486baff 2224 *pu8CurrByte++ = pstrStationParam->ht_ante_sel;
c5c77ba1 2225
f676e17a
LK
2226 *pu8CurrByte++ = pstrStationParam->flags_mask & 0xFF;
2227 *pu8CurrByte++ = (pstrStationParam->flags_mask >> 8) & 0xFF;
c5c77ba1 2228
67ab64e4
LK
2229 *pu8CurrByte++ = pstrStationParam->flags_set & 0xFF;
2230 *pu8CurrByte++ = (pstrStationParam->flags_set >> 8) & 0xFF;
c5c77ba1
JK
2231
2232 return pu8CurrByte - pu8Buffer;
2233}
2234
71130e81 2235static void Handle_AddStation(struct wilc_vif *vif,
6a89ba9c 2236 struct add_sta_param *pstrStationParam)
c5c77ba1 2237{
31390eec 2238 s32 result = 0;
45102f83 2239 struct wid wid;
63d03e47 2240 u8 *pu8CurrByte;
78c87591 2241
45102f83
LK
2242 wid.id = (u16)WID_ADD_STA;
2243 wid.type = WID_BIN;
e734223c 2244 wid.size = WILC_ADD_STA_LENGTH + pstrStationParam->rates_len;
c5c77ba1 2245
45102f83
LK
2246 wid.val = kmalloc(wid.size, GFP_KERNEL);
2247 if (!wid.val)
24db713f 2248 goto ERRORHANDLER;
c5c77ba1 2249
45102f83 2250 pu8CurrByte = wid.val;
c5c77ba1
JK
2251 pu8CurrByte += WILC_HostIf_PackStaParam(pu8CurrByte, pstrStationParam);
2252
79df6a49 2253 result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1,
4cf93d70 2254 wilc_get_vif_idx(vif));
31390eec 2255 if (result != 0)
b92f9304 2256 netdev_err(vif->ndev, "Failed to send add station\n");
c5c77ba1 2257
24db713f 2258ERRORHANDLER:
a622e016 2259 kfree(pstrStationParam->rates);
45102f83 2260 kfree(wid.val);
c5c77ba1
JK
2261}
2262
71130e81 2263static void Handle_DelAllSta(struct wilc_vif *vif,
b4e644e4 2264 struct del_all_sta *pstrDelAllStaParam)
c5c77ba1 2265{
31390eec 2266 s32 result = 0;
45102f83 2267 struct wid wid;
63d03e47 2268 u8 *pu8CurrByte;
63d03e47 2269 u8 i;
3703480b 2270 u8 au8Zero_Buff[6] = {0};
78c87591 2271
45102f83
LK
2272 wid.id = (u16)WID_DEL_ALL_STA;
2273 wid.type = WID_STR;
2274 wid.size = (pstrDelAllStaParam->assoc_sta * ETH_ALEN) + 1;
c5c77ba1 2275
45102f83
LK
2276 wid.val = kmalloc((pstrDelAllStaParam->assoc_sta * ETH_ALEN) + 1, GFP_KERNEL);
2277 if (!wid.val)
24db713f 2278 goto ERRORHANDLER;
c5c77ba1 2279
45102f83 2280 pu8CurrByte = wid.val;
c5c77ba1 2281
8ba1803f 2282 *(pu8CurrByte++) = pstrDelAllStaParam->assoc_sta;
c5c77ba1
JK
2283
2284 for (i = 0; i < MAX_NUM_STA; i++) {
e51b9216
LK
2285 if (memcmp(pstrDelAllStaParam->del_all_sta[i], au8Zero_Buff, ETH_ALEN))
2286 memcpy(pu8CurrByte, pstrDelAllStaParam->del_all_sta[i], ETH_ALEN);
c5c77ba1
JK
2287 else
2288 continue;
2289
2290 pu8CurrByte += ETH_ALEN;
2291 }
2292
79df6a49 2293 result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1,
4cf93d70 2294 wilc_get_vif_idx(vif));
31390eec 2295 if (result)
b92f9304 2296 netdev_err(vif->ndev, "Failed to send add station\n");
c5c77ba1 2297
24db713f 2298ERRORHANDLER:
45102f83 2299 kfree(wid.val);
c5c77ba1 2300
2d25af87 2301 up(&hif_sema_wait_response);
c5c77ba1
JK
2302}
2303
71130e81 2304static void Handle_DelStation(struct wilc_vif *vif,
fb93a1e1 2305 struct del_sta *pstrDelStaParam)
c5c77ba1 2306{
31390eec 2307 s32 result = 0;
45102f83 2308 struct wid wid;
63d03e47 2309 u8 *pu8CurrByte;
c5c77ba1 2310
45102f83
LK
2311 wid.id = (u16)WID_REMOVE_STA;
2312 wid.type = WID_BIN;
2313 wid.size = ETH_ALEN;
c5c77ba1 2314
45102f83
LK
2315 wid.val = kmalloc(wid.size, GFP_KERNEL);
2316 if (!wid.val)
24db713f 2317 goto ERRORHANDLER;
c5c77ba1 2318
45102f83 2319 pu8CurrByte = wid.val;
c5c77ba1 2320
e4839d39 2321 memcpy(pu8CurrByte, pstrDelStaParam->mac_addr, ETH_ALEN);
c5c77ba1 2322
79df6a49 2323 result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1,
4cf93d70 2324 wilc_get_vif_idx(vif));
31390eec 2325 if (result)
b92f9304 2326 netdev_err(vif->ndev, "Failed to send add station\n");
c5c77ba1 2327
24db713f 2328ERRORHANDLER:
45102f83 2329 kfree(wid.val);
c5c77ba1
JK
2330}
2331
71130e81 2332static void Handle_EditStation(struct wilc_vif *vif,
6a89ba9c 2333 struct add_sta_param *pstrStationParam)
c5c77ba1 2334{
31390eec 2335 s32 result = 0;
45102f83 2336 struct wid wid;
63d03e47 2337 u8 *pu8CurrByte;
c5c77ba1 2338
45102f83
LK
2339 wid.id = (u16)WID_EDIT_STA;
2340 wid.type = WID_BIN;
e734223c 2341 wid.size = WILC_ADD_STA_LENGTH + pstrStationParam->rates_len;
c5c77ba1 2342
45102f83
LK
2343 wid.val = kmalloc(wid.size, GFP_KERNEL);
2344 if (!wid.val)
24db713f 2345 goto ERRORHANDLER;
c5c77ba1 2346
45102f83 2347 pu8CurrByte = wid.val;
c5c77ba1
JK
2348 pu8CurrByte += WILC_HostIf_PackStaParam(pu8CurrByte, pstrStationParam);
2349
79df6a49 2350 result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1,
4cf93d70 2351 wilc_get_vif_idx(vif));
31390eec 2352 if (result)
b92f9304 2353 netdev_err(vif->ndev, "Failed to send edit station\n");
c5c77ba1 2354
24db713f 2355ERRORHANDLER:
a622e016 2356 kfree(pstrStationParam->rates);
45102f83 2357 kfree(wid.val);
c5c77ba1 2358}
c5c77ba1 2359
71130e81 2360static int Handle_RemainOnChan(struct wilc_vif *vif,
2f9c03f5 2361 struct remain_ch *pstrHostIfRemainOnChan)
c5c77ba1 2362{
31390eec 2363 s32 result = 0;
63d03e47 2364 u8 u8remain_on_chan_flag;
45102f83 2365 struct wid wid;
71130e81 2366 struct host_if_drv *hif_drv = vif->hif_drv;
c5c77ba1 2367
5beef2ca 2368 if (!hif_drv->remain_on_ch_pending) {
c5cc4b12 2369 hif_drv->remain_on_ch.arg = pstrHostIfRemainOnChan->arg;
bfb62abc 2370 hif_drv->remain_on_ch.expired = pstrHostIfRemainOnChan->expired;
5e5f7916 2371 hif_drv->remain_on_ch.ready = pstrHostIfRemainOnChan->ready;
839ab709 2372 hif_drv->remain_on_ch.ch = pstrHostIfRemainOnChan->ch;
9d764e38 2373 hif_drv->remain_on_ch.id = pstrHostIfRemainOnChan->id;
c5c77ba1 2374 } else {
839ab709 2375 pstrHostIfRemainOnChan->ch = hif_drv->remain_on_ch.ch;
c5c77ba1
JK
2376 }
2377
bc801855 2378 if (hif_drv->usr_scan_req.scan_result) {
5beef2ca 2379 hif_drv->remain_on_ch_pending = 1;
31390eec 2380 result = -EBUSY;
24db713f 2381 goto ERRORHANDLER;
c5c77ba1 2382 }
b60005a8 2383 if (hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP) {
31390eec 2384 result = -EBUSY;
24db713f 2385 goto ERRORHANDLER;
c5c77ba1
JK
2386 }
2387
0e1af73d 2388 if (wilc_optaining_ip || wilc_connecting) {
31390eec 2389 result = -EBUSY;
24db713f 2390 goto ERRORHANDLER;
c5c77ba1 2391 }
c5c77ba1 2392
72ed4dc7 2393 u8remain_on_chan_flag = true;
45102f83
LK
2394 wid.id = (u16)WID_REMAIN_ON_CHAN;
2395 wid.type = WID_STR;
2396 wid.size = 2;
2397 wid.val = kmalloc(wid.size, GFP_KERNEL);
2398 if (!wid.val) {
31390eec 2399 result = -ENOMEM;
24db713f
LK
2400 goto ERRORHANDLER;
2401 }
c5c77ba1 2402
45102f83 2403 wid.val[0] = u8remain_on_chan_flag;
839ab709 2404 wid.val[1] = (s8)pstrHostIfRemainOnChan->ch;
c5c77ba1 2405
79df6a49 2406 result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1,
4cf93d70 2407 wilc_get_vif_idx(vif));
31390eec 2408 if (result != 0)
b92f9304 2409 netdev_err(vif->ndev, "Failed to set remain on channel\n");
c5c77ba1 2410
24db713f 2411ERRORHANDLER:
c5c77ba1
JK
2412 {
2413 P2P_LISTEN_STATE = 1;
71130e81 2414 hif_drv->remain_on_ch_timer.data = (unsigned long)vif;
cc2d7e9e 2415 mod_timer(&hif_drv->remain_on_ch_timer,
9eb06643 2416 jiffies +
fb6e0680 2417 msecs_to_jiffies(pstrHostIfRemainOnChan->duration));
c5c77ba1 2418
5e5f7916 2419 if (hif_drv->remain_on_ch.ready)
c5cc4b12 2420 hif_drv->remain_on_ch.ready(hif_drv->remain_on_ch.arg);
c5c77ba1 2421
5beef2ca
LK
2422 if (hif_drv->remain_on_ch_pending)
2423 hif_drv->remain_on_ch_pending = 0;
c5c77ba1 2424 }
31390eec
LK
2425
2426 return result;
c5c77ba1
JK
2427}
2428
71130e81 2429static int Handle_RegisterFrame(struct wilc_vif *vif,
bc37c5df 2430 struct reg_frame *pstrHostIfRegisterFrame)
c5c77ba1 2431{
31390eec 2432 s32 result = 0;
45102f83 2433 struct wid wid;
63d03e47 2434 u8 *pu8CurrByte;
c5c77ba1 2435
45102f83
LK
2436 wid.id = (u16)WID_REGISTER_FRAME;
2437 wid.type = WID_STR;
2438 wid.val = kmalloc(sizeof(u16) + 2, GFP_KERNEL);
2439 if (!wid.val)
24db713f 2440 return -ENOMEM;
c5c77ba1 2441
45102f83 2442 pu8CurrByte = wid.val;
c5c77ba1 2443
6abf8681 2444 *pu8CurrByte++ = pstrHostIfRegisterFrame->reg;
bcb410bb 2445 *pu8CurrByte++ = pstrHostIfRegisterFrame->reg_id;
d5f654ca 2446 memcpy(pu8CurrByte, &pstrHostIfRegisterFrame->frame_type, sizeof(u16));
c5c77ba1 2447
45102f83 2448 wid.size = sizeof(u16) + 2;
c5c77ba1 2449
79df6a49 2450 result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1,
4cf93d70 2451 wilc_get_vif_idx(vif));
31390eec 2452 if (result) {
b92f9304 2453 netdev_err(vif->ndev, "Failed to frame register\n");
31390eec 2454 result = -EINVAL;
c5c77ba1
JK
2455 }
2456
31390eec 2457 return result;
c5c77ba1
JK
2458}
2459
71130e81 2460static u32 Handle_ListenStateExpired(struct wilc_vif *vif,
2f9c03f5 2461 struct remain_ch *pstrHostIfRemainOnChan)
c5c77ba1 2462{
63d03e47 2463 u8 u8remain_on_chan_flag;
45102f83 2464 struct wid wid;
31390eec 2465 s32 result = 0;
71130e81 2466 struct host_if_drv *hif_drv = vif->hif_drv;
c5c77ba1 2467
c5c77ba1 2468 if (P2P_LISTEN_STATE) {
72ed4dc7 2469 u8remain_on_chan_flag = false;
45102f83
LK
2470 wid.id = (u16)WID_REMAIN_ON_CHAN;
2471 wid.type = WID_STR;
2472 wid.size = 2;
2473 wid.val = kmalloc(wid.size, GFP_KERNEL);
c5c77ba1 2474
653bb463 2475 if (!wid.val) {
b92f9304 2476 netdev_err(vif->ndev, "Failed to allocate memory\n");
653bb463
LK
2477 return -ENOMEM;
2478 }
c5c77ba1 2479
45102f83
LK
2480 wid.val[0] = u8remain_on_chan_flag;
2481 wid.val[1] = FALSE_FRMWR_CHANNEL;
c5c77ba1 2482
79df6a49 2483 result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1,
4cf93d70 2484 wilc_get_vif_idx(vif));
31390eec 2485 if (result != 0) {
b92f9304 2486 netdev_err(vif->ndev, "Failed to set remain channel\n");
c5c77ba1
JK
2487 goto _done_;
2488 }
2489
bfb62abc 2490 if (hif_drv->remain_on_ch.expired) {
c5cc4b12 2491 hif_drv->remain_on_ch.expired(hif_drv->remain_on_ch.arg,
9d764e38 2492 pstrHostIfRemainOnChan->id);
c5c77ba1
JK
2493 }
2494 P2P_LISTEN_STATE = 0;
2495 } else {
e3f16965 2496 netdev_dbg(vif->ndev, "Not in listen state\n");
31390eec 2497 result = -EFAULT;
c5c77ba1
JK
2498 }
2499
2500_done_:
31390eec 2501 return result;
c5c77ba1
JK
2502}
2503
93dee8ee 2504static void ListenTimerCB(unsigned long arg)
c5c77ba1 2505{
31390eec 2506 s32 result = 0;
143eb95a 2507 struct host_if_msg msg;
71130e81 2508 struct wilc_vif *vif = (struct wilc_vif *)arg;
ae4dfa57 2509
71130e81 2510 del_timer(&vif->hif_drv->remain_on_ch_timer);
c5c77ba1 2511
143eb95a 2512 memset(&msg, 0, sizeof(struct host_if_msg));
a9f812a6 2513 msg.id = HOST_IF_MSG_LISTEN_TIMER_FIRED;
71130e81
GL
2514 msg.vif = vif;
2515 msg.body.remain_on_ch.id = vif->hif_drv->remain_on_ch.id;
c5c77ba1 2516
31390eec
LK
2517 result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
2518 if (result)
b92f9304 2519 netdev_err(vif->ndev, "wilc_mq_send fail\n");
c5c77ba1 2520}
c5c77ba1 2521
71130e81 2522static void Handle_PowerManagement(struct wilc_vif *vif,
5a008f1c 2523 struct power_mgmt_param *strPowerMgmtParam)
c5c77ba1 2524{
31390eec 2525 s32 result = 0;
45102f83 2526 struct wid wid;
ca356ada 2527 s8 s8PowerMode;
78c87591 2528
45102f83 2529 wid.id = (u16)WID_POWER_MANAGEMENT;
c5c77ba1 2530
047e6646 2531 if (strPowerMgmtParam->enabled)
c5c77ba1 2532 s8PowerMode = MIN_FAST_PS;
78174ada 2533 else
c5c77ba1 2534 s8PowerMode = NO_POWERSAVE;
c4f97526 2535
45102f83
LK
2536 wid.val = &s8PowerMode;
2537 wid.size = sizeof(char);
c5c77ba1 2538
79df6a49 2539 result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1,
4cf93d70 2540 wilc_get_vif_idx(vif));
31390eec 2541 if (result)
b92f9304 2542 netdev_err(vif->ndev, "Failed to send power management\n");
c5c77ba1
JK
2543}
2544
71130e81 2545static void Handle_SetMulticastFilter(struct wilc_vif *vif,
641210ac 2546 struct set_multicast *strHostIfSetMulti)
c5c77ba1 2547{
31390eec 2548 s32 result = 0;
45102f83 2549 struct wid wid;
63d03e47 2550 u8 *pu8CurrByte;
c5c77ba1 2551
45102f83
LK
2552 wid.id = (u16)WID_SETUP_MULTICAST_FILTER;
2553 wid.type = WID_BIN;
2554 wid.size = sizeof(struct set_multicast) + ((strHostIfSetMulti->cnt) * ETH_ALEN);
2555 wid.val = kmalloc(wid.size, GFP_KERNEL);
2556 if (!wid.val)
24db713f 2557 goto ERRORHANDLER;
c5c77ba1 2558
45102f83 2559 pu8CurrByte = wid.val;
bae636eb 2560 *pu8CurrByte++ = (strHostIfSetMulti->enabled & 0xFF);
c8751ad7
LK
2561 *pu8CurrByte++ = 0;
2562 *pu8CurrByte++ = 0;
2563 *pu8CurrByte++ = 0;
c5c77ba1 2564
adab2f71
LK
2565 *pu8CurrByte++ = (strHostIfSetMulti->cnt & 0xFF);
2566 *pu8CurrByte++ = ((strHostIfSetMulti->cnt >> 8) & 0xFF);
2567 *pu8CurrByte++ = ((strHostIfSetMulti->cnt >> 16) & 0xFF);
2568 *pu8CurrByte++ = ((strHostIfSetMulti->cnt >> 24) & 0xFF);
c5c77ba1 2569
adab2f71 2570 if ((strHostIfSetMulti->cnt) > 0)
0e1af73d 2571 memcpy(pu8CurrByte, wilc_multicast_mac_addr_list,
fb70e9f5 2572 ((strHostIfSetMulti->cnt) * ETH_ALEN));
c5c77ba1 2573
79df6a49 2574 result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1,
4cf93d70 2575 wilc_get_vif_idx(vif));
31390eec 2576 if (result)
b92f9304 2577 netdev_err(vif->ndev, "Failed to send setup multicast\n");
c5c77ba1 2578
24db713f 2579ERRORHANDLER:
45102f83 2580 kfree(wid.val);
c5c77ba1
JK
2581}
2582
71130e81 2583static s32 Handle_DelAllRxBASessions(struct wilc_vif *vif,
54265472 2584 struct ba_session_info *strHostIfBASessionInfo)
c5c77ba1 2585{
31390eec 2586 s32 result = 0;
45102f83 2587 struct wid wid;
c5c77ba1 2588 char *ptr = NULL;
c5c77ba1 2589
45102f83
LK
2590 wid.id = (u16)WID_DEL_ALL_RX_BA;
2591 wid.type = WID_STR;
2592 wid.val = kmalloc(BLOCK_ACK_REQ_SIZE, GFP_KERNEL);
2593 wid.size = BLOCK_ACK_REQ_SIZE;
2594 ptr = wid.val;
c5c77ba1
JK
2595 *ptr++ = 0x14;
2596 *ptr++ = 0x3;
2597 *ptr++ = 0x2;
3fc4999e 2598 memcpy(ptr, strHostIfBASessionInfo->bssid, ETH_ALEN);
c5c77ba1 2599 ptr += ETH_ALEN;
16c9b391 2600 *ptr++ = strHostIfBASessionInfo->tid;
c5c77ba1 2601 *ptr++ = 0;
ae4dfa57 2602 *ptr++ = 32;
c5c77ba1 2603
79df6a49 2604 result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1,
4cf93d70 2605 wilc_get_vif_idx(vif));
c5c77ba1 2606
45102f83 2607 kfree(wid.val);
c5c77ba1 2608
2d25af87 2609 up(&hif_sema_wait_response);
c5c77ba1 2610
31390eec 2611 return result;
c5c77ba1
JK
2612}
2613
70418790
GL
2614static void handle_set_tx_pwr(struct wilc_vif *vif, u8 tx_pwr)
2615{
2616 int ret;
2617 struct wid wid;
2618
2619 wid.id = (u16)WID_TX_POWER;
2620 wid.type = WID_CHAR;
2621 wid.val = &tx_pwr;
2622 wid.size = sizeof(char);
2623
79df6a49
GL
2624 ret = wilc_send_config_pkt(vif, SET_CFG, &wid, 1,
2625 wilc_get_vif_idx(vif));
70418790
GL
2626 if (ret)
2627 netdev_err(vif->ndev, "Failed to set TX PWR\n");
2628}
2629
2630static void handle_get_tx_pwr(struct wilc_vif *vif, u8 *tx_pwr)
2631{
2632 s32 ret = 0;
2633 struct wid wid;
2634
2635 wid.id = (u16)WID_TX_POWER;
2636 wid.type = WID_CHAR;
2637 wid.val = (s8 *)tx_pwr;
2638 wid.size = sizeof(char);
2639
79df6a49
GL
2640 ret = wilc_send_config_pkt(vif, GET_CFG, &wid, 1,
2641 wilc_get_vif_idx(vif));
70418790
GL
2642 if (ret)
2643 netdev_err(vif->ndev, "Failed to get TX PWR\n");
2644
2645 up(&hif_sema_wait_response);
2646}
2647
1999bd52 2648static int hostIFthread(void *pvArg)
c5c77ba1 2649{
4e4467fd 2650 u32 u32Ret;
143eb95a 2651 struct host_if_msg msg;
59b97b36 2652 struct wilc *wilc = pvArg;
cf60106b 2653 struct wilc_vif *vif;
c5c77ba1 2654
143eb95a 2655 memset(&msg, 0, sizeof(struct host_if_msg));
c5c77ba1
JK
2656
2657 while (1) {
cb067dcf 2658 wilc_mq_recv(&hif_msg_q, &msg, sizeof(struct host_if_msg), &u32Ret);
cf60106b 2659 vif = msg.vif;
e3f16965 2660 if (msg.id == HOST_IF_MSG_EXIT)
c5c77ba1 2661 break;
c5c77ba1 2662
0e1af73d 2663 if ((!wilc_initialized)) {
80e29c7a 2664 usleep_range(200 * 1000, 200 * 1000);
cb067dcf 2665 wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
c5c77ba1
JK
2666 continue;
2667 }
2668
91109e11 2669 if (msg.id == HOST_IF_MSG_CONNECT &&
b13584a8 2670 vif->hif_drv->usr_scan_req.scan_result) {
cb067dcf 2671 wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
80e29c7a 2672 usleep_range(2 * 1000, 2 * 1000);
c5c77ba1
JK
2673 continue;
2674 }
2675
a9f812a6 2676 switch (msg.id) {
c5c77ba1
JK
2677 case HOST_IF_MSG_Q_IDLE:
2678 Handle_wait_msg_q_empty();
2679 break;
2680
2681 case HOST_IF_MSG_SCAN:
71130e81 2682 Handle_Scan(msg.vif, &msg.body.scan_info);
c5c77ba1
JK
2683 break;
2684
2685 case HOST_IF_MSG_CONNECT:
71130e81 2686 Handle_Connect(msg.vif, &msg.body.con_info);
c5c77ba1
JK
2687 break;
2688
c5c77ba1 2689 case HOST_IF_MSG_FLUSH_CONNECT:
71130e81 2690 Handle_FlushConnect(msg.vif);
c5c77ba1
JK
2691 break;
2692
2693 case HOST_IF_MSG_RCVD_NTWRK_INFO:
71130e81 2694 Handle_RcvdNtwrkInfo(msg.vif, &msg.body.net_info);
c5c77ba1
JK
2695 break;
2696
2697 case HOST_IF_MSG_RCVD_GNRL_ASYNC_INFO:
71130e81 2698 Handle_RcvdGnrlAsyncInfo(vif,
cf60106b 2699 &msg.body.async_info);
c5c77ba1
JK
2700 break;
2701
2702 case HOST_IF_MSG_KEY:
71130e81 2703 Handle_Key(msg.vif, &msg.body.key_info);
c5c77ba1
JK
2704 break;
2705
2706 case HOST_IF_MSG_CFG_PARAMS:
71130e81 2707 handle_cfg_param(msg.vif, &msg.body.cfg_info);
c5c77ba1
JK
2708 break;
2709
2710 case HOST_IF_MSG_SET_CHANNEL:
71130e81 2711 handle_set_channel(msg.vif, &msg.body.channel_info);
c5c77ba1
JK
2712 break;
2713
2714 case HOST_IF_MSG_DISCONNECT:
71130e81 2715 Handle_Disconnect(msg.vif);
c5c77ba1
JK
2716 break;
2717
2718 case HOST_IF_MSG_RCVD_SCAN_COMPLETE:
b13584a8 2719 del_timer(&vif->hif_drv->scan_timer);
c5c77ba1 2720
825b966f 2721 if (!wilc_wlan_get_num_conn_ifcs(wilc))
00215dde 2722 wilc_chip_sleep_manually(wilc);
c5c77ba1 2723
71130e81 2724 Handle_ScanDone(msg.vif, SCAN_EVENT_DONE);
c5c77ba1 2725
b13584a8 2726 if (vif->hif_drv->remain_on_ch_pending)
71130e81
GL
2727 Handle_RemainOnChan(msg.vif,
2728 &msg.body.remain_on_ch);
c5c77ba1
JK
2729
2730 break;
2731
2732 case HOST_IF_MSG_GET_RSSI:
71130e81 2733 Handle_GetRssi(msg.vif);
c5c77ba1
JK
2734 break;
2735
2736 case HOST_IF_MSG_GET_LINKSPEED:
71130e81 2737 Handle_GetLinkspeed(msg.vif);
c5c77ba1
JK
2738 break;
2739
2740 case HOST_IF_MSG_GET_STATISTICS:
71130e81
GL
2741 Handle_GetStatistics(msg.vif,
2742 (struct rf_info *)msg.body.data);
c5c77ba1
JK
2743 break;
2744
2745 case HOST_IF_MSG_GET_CHNL:
71130e81 2746 Handle_GetChnl(msg.vif);
c5c77ba1
JK
2747 break;
2748
c5c77ba1 2749 case HOST_IF_MSG_ADD_BEACON:
71130e81 2750 Handle_AddBeacon(msg.vif, &msg.body.beacon_info);
c5c77ba1
JK
2751 break;
2752
2753 case HOST_IF_MSG_DEL_BEACON:
71130e81 2754 Handle_DelBeacon(msg.vif);
c5c77ba1
JK
2755 break;
2756
2757 case HOST_IF_MSG_ADD_STATION:
71130e81 2758 Handle_AddStation(msg.vif, &msg.body.add_sta_info);
c5c77ba1
JK
2759 break;
2760
2761 case HOST_IF_MSG_DEL_STATION:
71130e81 2762 Handle_DelStation(msg.vif, &msg.body.del_sta_info);
c5c77ba1
JK
2763 break;
2764
2765 case HOST_IF_MSG_EDIT_STATION:
71130e81 2766 Handle_EditStation(msg.vif, &msg.body.edit_sta_info);
c5c77ba1
JK
2767 break;
2768
2769 case HOST_IF_MSG_GET_INACTIVETIME:
71130e81 2770 Handle_Get_InActiveTime(msg.vif, &msg.body.mac_info);
c5c77ba1
JK
2771 break;
2772
c5c77ba1 2773 case HOST_IF_MSG_SCAN_TIMER_FIRED:
c5c77ba1 2774
71130e81 2775 Handle_ScanDone(msg.vif, SCAN_EVENT_ABORTED);
c5c77ba1
JK
2776 break;
2777
2778 case HOST_IF_MSG_CONNECT_TIMER_FIRED:
71130e81 2779 Handle_ConnectTimeout(msg.vif);
c5c77ba1
JK
2780 break;
2781
2782 case HOST_IF_MSG_POWER_MGMT:
71130e81
GL
2783 Handle_PowerManagement(msg.vif,
2784 &msg.body.pwr_mgmt_info);
c5c77ba1
JK
2785 break;
2786
2787 case HOST_IF_MSG_SET_WFIDRV_HANDLER:
71130e81 2788 handle_set_wfi_drv_handler(msg.vif, &msg.body.drv);
c5c77ba1
JK
2789 break;
2790
2791 case HOST_IF_MSG_SET_OPERATION_MODE:
71130e81 2792 handle_set_operation_mode(msg.vif, &msg.body.mode);
c5c77ba1
JK
2793 break;
2794
2795 case HOST_IF_MSG_SET_IPADDRESS:
71130e81 2796 handle_set_ip_address(vif,
a6e6d48b
LK
2797 msg.body.ip_info.ip_addr,
2798 msg.body.ip_info.idx);
c5c77ba1
JK
2799 break;
2800
2801 case HOST_IF_MSG_GET_IPADDRESS:
71130e81 2802 handle_get_ip_address(vif, msg.body.ip_info.idx);
c5c77ba1
JK
2803 break;
2804
c5c77ba1 2805 case HOST_IF_MSG_SET_MAC_ADDRESS:
71130e81 2806 handle_set_mac_address(msg.vif,
a8267421 2807 &msg.body.set_mac_info);
c5c77ba1
JK
2808 break;
2809
c5c77ba1 2810 case HOST_IF_MSG_GET_MAC_ADDRESS:
71130e81 2811 handle_get_mac_address(msg.vif,
b3bf8fd9 2812 &msg.body.get_mac_info);
c5c77ba1
JK
2813 break;
2814
c5c77ba1 2815 case HOST_IF_MSG_REMAIN_ON_CHAN:
71130e81 2816 Handle_RemainOnChan(msg.vif, &msg.body.remain_on_ch);
c5c77ba1
JK
2817 break;
2818
2819 case HOST_IF_MSG_REGISTER_FRAME:
71130e81 2820 Handle_RegisterFrame(msg.vif, &msg.body.reg_frame);
c5c77ba1
JK
2821 break;
2822
2823 case HOST_IF_MSG_LISTEN_TIMER_FIRED:
71130e81 2824 Handle_ListenStateExpired(msg.vif, &msg.body.remain_on_ch);
c5c77ba1
JK
2825 break;
2826
c5c77ba1 2827 case HOST_IF_MSG_SET_MULTICAST_FILTER:
71130e81 2828 Handle_SetMulticastFilter(msg.vif, &msg.body.multicast_info);
c5c77ba1
JK
2829 break;
2830
c5c77ba1 2831 case HOST_IF_MSG_DEL_ALL_RX_BA_SESSIONS:
71130e81 2832 Handle_DelAllRxBASessions(msg.vif, &msg.body.session_info);
c5c77ba1
JK
2833 break;
2834
2835 case HOST_IF_MSG_DEL_ALL_STA:
71130e81 2836 Handle_DelAllSta(msg.vif, &msg.body.del_all_sta_info);
c5c77ba1
JK
2837 break;
2838
70418790
GL
2839 case HOST_IF_MSG_SET_TX_POWER:
2840 handle_set_tx_pwr(msg.vif, msg.body.tx_power.tx_pwr);
2841 break;
2842
2843 case HOST_IF_MSG_GET_TX_POWER:
2844 handle_get_tx_pwr(msg.vif, &msg.body.tx_power.tx_pwr);
2845 break;
c5c77ba1 2846 default:
b92f9304 2847 netdev_err(vif->ndev, "[Host Interface] undefined\n");
c5c77ba1
JK
2848 break;
2849 }
2850 }
2851
834e0cb0 2852 up(&hif_sema_thread);
1999bd52 2853 return 0;
c5c77ba1
JK
2854}
2855
93dee8ee 2856static void TimerCB_Scan(unsigned long arg)
c5c77ba1 2857{
71130e81 2858 struct wilc_vif *vif = (struct wilc_vif *)arg;
143eb95a 2859 struct host_if_msg msg;
c5c77ba1 2860
143eb95a 2861 memset(&msg, 0, sizeof(struct host_if_msg));
71130e81 2862 msg.vif = vif;
a9f812a6 2863 msg.id = HOST_IF_MSG_SCAN_TIMER_FIRED;
c5c77ba1 2864
cb067dcf 2865 wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
c5c77ba1
JK
2866}
2867
93dee8ee 2868static void TimerCB_Connect(unsigned long arg)
c5c77ba1 2869{
71130e81 2870 struct wilc_vif *vif = (struct wilc_vif *)arg;
143eb95a 2871 struct host_if_msg msg;
c5c77ba1 2872
143eb95a 2873 memset(&msg, 0, sizeof(struct host_if_msg));
71130e81 2874 msg.vif = vif;
a9f812a6 2875 msg.id = HOST_IF_MSG_CONNECT_TIMER_FIRED;
c5c77ba1 2876
cb067dcf 2877 wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
c5c77ba1
JK
2878}
2879
0e1af73d 2880s32 wilc_remove_key(struct host_if_drv *hif_drv, const u8 *pu8StaAddress)
c5c77ba1 2881{
45102f83 2882 struct wid wid;
c5c77ba1 2883
45102f83
LK
2884 wid.id = (u16)WID_REMOVE_KEY;
2885 wid.type = WID_STR;
2886 wid.val = (s8 *)pu8StaAddress;
2887 wid.size = 6;
c5c77ba1 2888
b68d820b 2889 return 0;
c5c77ba1
JK
2890}
2891
fbf5379b 2892int wilc_remove_wep_key(struct wilc_vif *vif, u8 index)
c5c77ba1 2893{
9e5e8b44 2894 int result = 0;
143eb95a 2895 struct host_if_msg msg;
fbf5379b 2896 struct host_if_drv *hif_drv = vif->hif_drv;
c5c77ba1 2897
a4ab1ade 2898 if (!hif_drv) {
9e5e8b44 2899 result = -EFAULT;
b92f9304 2900 netdev_err(vif->ndev, "Failed to send setup multicast\n");
9e5e8b44 2901 return result;
24db713f 2902 }
c5c77ba1 2903
143eb95a 2904 memset(&msg, 0, sizeof(struct host_if_msg));
c5c77ba1 2905
a9f812a6 2906 msg.id = HOST_IF_MSG_KEY;
8e9f427a 2907 msg.body.key_info.type = WEP;
0d17e382 2908 msg.body.key_info.action = REMOVEKEY;
cf60106b 2909 msg.vif = vif;
73b2e381 2910 msg.body.key_info.attr.wep.index = index;
c5c77ba1 2911
cb067dcf 2912 result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
9e5e8b44 2913 if (result)
b92f9304 2914 netdev_err(vif->ndev, "Request to remove WEP key\n");
9ea47133 2915 down(&hif_drv->sem_test_key_block);
c5c77ba1 2916
9e5e8b44 2917 return result;
c5c77ba1
JK
2918}
2919
fbf5379b 2920int wilc_set_wep_default_keyid(struct wilc_vif *vif, u8 index)
c5c77ba1 2921{
5b41c7c9 2922 int result = 0;
143eb95a 2923 struct host_if_msg msg;
fbf5379b 2924 struct host_if_drv *hif_drv = vif->hif_drv;
c5c77ba1 2925
a4ab1ade 2926 if (!hif_drv) {
31390eec 2927 result = -EFAULT;
b92f9304 2928 netdev_err(vif->ndev, "driver is null\n");
31390eec 2929 return result;
24db713f 2930 }
c5c77ba1 2931
143eb95a 2932 memset(&msg, 0, sizeof(struct host_if_msg));
c5c77ba1 2933
a9f812a6 2934 msg.id = HOST_IF_MSG_KEY;
8e9f427a 2935 msg.body.key_info.type = WEP;
0d17e382 2936 msg.body.key_info.action = DEFAULTKEY;
cf60106b 2937 msg.vif = vif;
e91d0349 2938 msg.body.key_info.attr.wep.index = index;
c5c77ba1 2939
31390eec
LK
2940 result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
2941 if (result)
b92f9304 2942 netdev_err(vif->ndev, "Default key index\n");
9ea47133 2943 down(&hif_drv->sem_test_key_block);
c5c77ba1 2944
31390eec 2945 return result;
c5c77ba1
JK
2946}
2947
fbf5379b
GL
2948int wilc_add_wep_key_bss_sta(struct wilc_vif *vif, const u8 *key, u8 len,
2949 u8 index)
c5c77ba1 2950{
66b8cb89 2951 int result = 0;
143eb95a 2952 struct host_if_msg msg;
fbf5379b 2953 struct host_if_drv *hif_drv = vif->hif_drv;
c5c77ba1 2954
a4ab1ade 2955 if (!hif_drv) {
b92f9304 2956 netdev_err(vif->ndev, "driver is null\n");
77178807 2957 return -EFAULT;
24db713f 2958 }
c5c77ba1 2959
143eb95a 2960 memset(&msg, 0, sizeof(struct host_if_msg));
c5c77ba1 2961
a9f812a6 2962 msg.id = HOST_IF_MSG_KEY;
8e9f427a 2963 msg.body.key_info.type = WEP;
0d17e382 2964 msg.body.key_info.action = ADDKEY;
cf60106b 2965 msg.vif = vif;
1cc0c328
CL
2966 msg.body.key_info.attr.wep.key = kmemdup(key, len, GFP_KERNEL);
2967 if (!msg.body.key_info.attr.wep.key)
2968 return -ENOMEM;
2969
dbc53194 2970 msg.body.key_info.attr.wep.key_len = len;
0b2cc3e5 2971 msg.body.key_info.attr.wep.index = index;
c5c77ba1 2972
31390eec
LK
2973 result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
2974 if (result)
b92f9304 2975 netdev_err(vif->ndev, "STA - WEP Key\n");
9ea47133 2976 down(&hif_drv->sem_test_key_block);
c5c77ba1 2977
31390eec 2978 return result;
c5c77ba1
JK
2979}
2980
fbf5379b
GL
2981int wilc_add_wep_key_bss_ap(struct wilc_vif *vif, const u8 *key, u8 len,
2982 u8 index, u8 mode, enum AUTHTYPE auth_type)
c5c77ba1 2983{
641c20a6 2984 int result = 0;
143eb95a 2985 struct host_if_msg msg;
fbf5379b 2986 struct host_if_drv *hif_drv = vif->hif_drv;
c5c77ba1 2987
a4ab1ade 2988 if (!hif_drv) {
b92f9304 2989 netdev_err(vif->ndev, "driver is null\n");
77178807 2990 return -EFAULT;
24db713f 2991 }
c5c77ba1 2992
143eb95a 2993 memset(&msg, 0, sizeof(struct host_if_msg));
c5c77ba1 2994
a9f812a6 2995 msg.id = HOST_IF_MSG_KEY;
8e9f427a 2996 msg.body.key_info.type = WEP;
0d17e382 2997 msg.body.key_info.action = ADDKEY_AP;
cf60106b 2998 msg.vif = vif;
58eabd68
CL
2999 msg.body.key_info.attr.wep.key = kmemdup(key, len, GFP_KERNEL);
3000 if (!msg.body.key_info.attr.wep.key)
3001 return -ENOMEM;
3002
a5389b07 3003 msg.body.key_info.attr.wep.key_len = len;
a76dc953 3004 msg.body.key_info.attr.wep.index = index;
730a28da 3005 msg.body.key_info.attr.wep.mode = mode;
ff3bce2f 3006 msg.body.key_info.attr.wep.auth_type = auth_type;
ae4dfa57 3007
31390eec 3008 result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
c5c77ba1 3009
31390eec 3010 if (result)
b92f9304 3011 netdev_err(vif->ndev, "AP - WEP Key\n");
9ea47133 3012 down(&hif_drv->sem_test_key_block);
c5c77ba1 3013
31390eec 3014 return result;
c5c77ba1 3015}
108b3439 3016
fbf5379b
GL
3017int wilc_add_ptk(struct wilc_vif *vif, const u8 *ptk, u8 ptk_key_len,
3018 const u8 *mac_addr, const u8 *rx_mic, const u8 *tx_mic,
3019 u8 mode, u8 cipher_mode, u8 index)
c5c77ba1 3020{
706ab42e 3021 int result = 0;
143eb95a 3022 struct host_if_msg msg;
fbf5379b 3023 struct host_if_drv *hif_drv = vif->hif_drv;
53bbbb57 3024 u8 key_len = ptk_key_len;
78c87591 3025
a4ab1ade 3026 if (!hif_drv) {
b92f9304 3027 netdev_err(vif->ndev, "driver is null\n");
77178807 3028 return -EFAULT;
24db713f 3029 }
91109e11 3030
38f66290 3031 if (rx_mic)
53bbbb57 3032 key_len += RX_MIC_KEY_LEN;
91109e11 3033
d7c0242b 3034 if (tx_mic)
53bbbb57 3035 key_len += TX_MIC_KEY_LEN;
c5c77ba1 3036
143eb95a 3037 memset(&msg, 0, sizeof(struct host_if_msg));
c5c77ba1 3038
a9f812a6 3039 msg.id = HOST_IF_MSG_KEY;
2141fe39 3040 msg.body.key_info.type = WPA_PTK;
c5c77ba1 3041 if (mode == AP_MODE) {
0d17e382 3042 msg.body.key_info.action = ADDKEY_AP;
3e5c4ab6 3043 msg.body.key_info.attr.wpa.index = index;
c5c77ba1 3044 }
c5c77ba1 3045 if (mode == STATION_MODE)
0d17e382 3046 msg.body.key_info.action = ADDKEY;
c5c77ba1 3047
8ab8c592
CL
3048 msg.body.key_info.attr.wpa.key = kmemdup(ptk, ptk_key_len, GFP_KERNEL);
3049 if (!msg.body.key_info.attr.wpa.key)
3050 return -ENOMEM;
c5c77ba1 3051
9ac0c05c 3052 if (rx_mic)
38f66290 3053 memcpy(msg.body.key_info.attr.wpa.key + 16, rx_mic, RX_MIC_KEY_LEN);
9ac0c05c
CP
3054
3055 if (tx_mic)
d7c0242b 3056 memcpy(msg.body.key_info.attr.wpa.key + 24, tx_mic, TX_MIC_KEY_LEN);
c5c77ba1 3057
53bbbb57 3058 msg.body.key_info.attr.wpa.key_len = key_len;
248080aa 3059 msg.body.key_info.attr.wpa.mac_addr = mac_addr;
f0c82579 3060 msg.body.key_info.attr.wpa.mode = cipher_mode;
cf60106b 3061 msg.vif = vif;
c5c77ba1 3062
31390eec 3063 result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
c5c77ba1 3064
31390eec 3065 if (result)
b92f9304 3066 netdev_err(vif->ndev, "PTK Key\n");
c5c77ba1 3067
9ea47133 3068 down(&hif_drv->sem_test_key_block);
c5c77ba1 3069
31390eec 3070 return result;
c5c77ba1
JK
3071}
3072
fbf5379b
GL
3073int wilc_add_rx_gtk(struct wilc_vif *vif, const u8 *rx_gtk, u8 gtk_key_len,
3074 u8 index, u32 key_rsc_len, const u8 *key_rsc,
3075 const u8 *rx_mic, const u8 *tx_mic, u8 mode,
3076 u8 cipher_mode)
c5c77ba1 3077{
1503457f 3078 int result = 0;
143eb95a 3079 struct host_if_msg msg;
fbf5379b 3080 struct host_if_drv *hif_drv = vif->hif_drv;
d002fcc0 3081 u8 key_len = gtk_key_len;
c5c77ba1 3082
a4ab1ade 3083 if (!hif_drv) {
b92f9304 3084 netdev_err(vif->ndev, "driver is null\n");
77178807 3085 return -EFAULT;
24db713f 3086 }
143eb95a 3087 memset(&msg, 0, sizeof(struct host_if_msg));
c5c77ba1 3088
6d36c273 3089 if (rx_mic)
d002fcc0 3090 key_len += RX_MIC_KEY_LEN;
91109e11 3091
2f79758d 3092 if (tx_mic)
d002fcc0 3093 key_len += TX_MIC_KEY_LEN;
91109e11 3094
982859cc 3095 if (key_rsc) {
9bfda382
CL
3096 msg.body.key_info.attr.wpa.seq = kmemdup(key_rsc,
3097 key_rsc_len,
3098 GFP_KERNEL);
3099 if (!msg.body.key_info.attr.wpa.seq)
3100 return -ENOMEM;
c5c77ba1
JK
3101 }
3102
a9f812a6 3103 msg.id = HOST_IF_MSG_KEY;
5cd8f7ae 3104 msg.body.key_info.type = WPA_RX_GTK;
cf60106b 3105 msg.vif = vif;
c5c77ba1 3106
c5c77ba1 3107 if (mode == AP_MODE) {
0d17e382 3108 msg.body.key_info.action = ADDKEY_AP;
57bfcbc4 3109 msg.body.key_info.attr.wpa.mode = cipher_mode;
c5c77ba1 3110 }
c5c77ba1 3111 if (mode == STATION_MODE)
0d17e382 3112 msg.body.key_info.action = ADDKEY;
c5c77ba1 3113
9bfda382
CL
3114 msg.body.key_info.attr.wpa.key = kmemdup(rx_gtk,
3115 key_len,
3116 GFP_KERNEL);
3117 if (!msg.body.key_info.attr.wpa.key)
3118 return -ENOMEM;
c5c77ba1 3119
6d36c273
CL
3120 if (rx_mic)
3121 memcpy(msg.body.key_info.attr.wpa.key + 16, rx_mic,
d1666e2a 3122 RX_MIC_KEY_LEN);
91109e11 3123
2f79758d
CL
3124 if (tx_mic)
3125 memcpy(msg.body.key_info.attr.wpa.key + 24, tx_mic,
d1666e2a 3126 TX_MIC_KEY_LEN);
c5c77ba1 3127
9a5e5736 3128 msg.body.key_info.attr.wpa.index = index;
d002fcc0 3129 msg.body.key_info.attr.wpa.key_len = key_len;
18bef999 3130 msg.body.key_info.attr.wpa.seq_len = key_rsc_len;
c5c77ba1 3131
31390eec
LK
3132 result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
3133 if (result)
b92f9304 3134 netdev_err(vif->ndev, "RX GTK\n");
ae4dfa57 3135
9ea47133 3136 down(&hif_drv->sem_test_key_block);
c5c77ba1 3137
31390eec 3138 return result;
c5c77ba1 3139}
c5c77ba1 3140
1ab58705 3141int wilc_set_pmkid_info(struct wilc_vif *vif,
16c0cba7 3142 struct host_if_pmkid_attr *pmkid)
c5c77ba1 3143{
1ab58705 3144 int result = 0;
143eb95a 3145 struct host_if_msg msg;
fbf5379b 3146 struct host_if_drv *hif_drv = vif->hif_drv;
89dec139 3147 int i;
c5c77ba1 3148
a4ab1ade 3149 if (!hif_drv) {
b92f9304 3150 netdev_err(vif->ndev, "driver is null\n");
77178807 3151 return -EFAULT;
24db713f 3152 }
c5c77ba1 3153
143eb95a 3154 memset(&msg, 0, sizeof(struct host_if_msg));
c5c77ba1 3155
a9f812a6 3156 msg.id = HOST_IF_MSG_KEY;
8e9f427a 3157 msg.body.key_info.type = PMKSA;
0d17e382 3158 msg.body.key_info.action = ADDKEY;
cf60106b 3159 msg.vif = vif;
c5c77ba1 3160
16c0cba7 3161 for (i = 0; i < pmkid->numpmkid; i++) {
8c8360b3 3162 memcpy(msg.body.key_info.attr.pmkid.pmkidlist[i].bssid,
16c0cba7 3163 &pmkid->pmkidlist[i].bssid, ETH_ALEN);
8c8360b3 3164 memcpy(msg.body.key_info.attr.pmkid.pmkidlist[i].pmkid,
16c0cba7 3165 &pmkid->pmkidlist[i].pmkid, PMKID_LEN);
c5c77ba1
JK
3166 }
3167
31390eec
LK
3168 result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
3169 if (result)
b92f9304 3170 netdev_err(vif->ndev, "PMKID Info\n");
c5c77ba1 3171
31390eec 3172 return result;
c5c77ba1
JK
3173}
3174
1eabfe3f 3175int wilc_get_mac_address(struct wilc_vif *vif, u8 *mac_addr)
c5c77ba1 3176{
dcb15a08 3177 int result = 0;
143eb95a 3178 struct host_if_msg msg;
c5c77ba1 3179
143eb95a 3180 memset(&msg, 0, sizeof(struct host_if_msg));
c5c77ba1 3181
a9f812a6 3182 msg.id = HOST_IF_MSG_GET_MAC_ADDRESS;
1eabfe3f 3183 msg.body.get_mac_info.mac_addr = mac_addr;
cf60106b 3184 msg.vif = vif;
ae4dfa57 3185
31390eec
LK
3186 result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
3187 if (result) {
b92f9304 3188 netdev_err(vif->ndev, "Failed to send get mac address\n");
e6e12661 3189 return -EFAULT;
c5c77ba1
JK
3190 }
3191
2d25af87 3192 down(&hif_sema_wait_response);
31390eec 3193 return result;
c5c77ba1
JK
3194}
3195
f2cb5f3f 3196int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ssid,
8c38d960 3197 size_t ssid_len, const u8 *ies, size_t ies_len,
2ef29833 3198 wilc_connect_result connect_result, void *user_arg,
12a3b8bc 3199 u8 security, enum AUTHTYPE auth_type,
f382b376 3200 u8 channel, void *join_params)
c5c77ba1 3201{
0a285b27 3202 int result = 0;
143eb95a 3203 struct host_if_msg msg;
fbf5379b 3204 struct host_if_drv *hif_drv = vif->hif_drv;
c5c77ba1 3205
81c23a7e 3206 if (!hif_drv || !connect_result) {
b92f9304 3207 netdev_err(vif->ndev, "Driver is null\n");
77178807 3208 return -EFAULT;
24db713f 3209 }
c5c77ba1 3210
f382b376 3211 if (!join_params) {
b92f9304 3212 netdev_err(vif->ndev, "Unable to Join - JoinParams is NULL\n");
24db713f 3213 return -EFAULT;
c5c77ba1 3214 }
24db713f 3215
143eb95a 3216 memset(&msg, 0, sizeof(struct host_if_msg));
c5c77ba1 3217
a9f812a6 3218 msg.id = HOST_IF_MSG_CONNECT;
c5c77ba1 3219
e0c54a88 3220 msg.body.con_info.security = security;
12a3b8bc 3221 msg.body.con_info.auth_type = auth_type;
0ea1ece0 3222 msg.body.con_info.ch = channel;
81c23a7e 3223 msg.body.con_info.result = connect_result;
2ef29833 3224 msg.body.con_info.arg = user_arg;
f382b376 3225 msg.body.con_info.params = join_params;
cf60106b 3226 msg.vif = vif;
c5c77ba1 3227
16a537ca 3228 if (bssid) {
11623136
CL
3229 msg.body.con_info.bssid = kmemdup(bssid, 6, GFP_KERNEL);
3230 if (!msg.body.con_info.bssid)
3231 return -ENOMEM;
c5c77ba1
JK
3232 }
3233
f2cb5f3f 3234 if (ssid) {
dee39b1b 3235 msg.body.con_info.ssid_len = ssid_len;
11623136
CL
3236 msg.body.con_info.ssid = kmemdup(ssid, ssid_len, GFP_KERNEL);
3237 if (!msg.body.con_info.ssid)
3238 return -ENOMEM;
c5c77ba1
JK
3239 }
3240
88c9421a 3241 if (ies) {
8c38d960 3242 msg.body.con_info.ies_len = ies_len;
11623136
CL
3243 msg.body.con_info.ies = kmemdup(ies, ies_len, GFP_KERNEL);
3244 if (!msg.body.con_info.ies)
3245 return -ENOMEM;
c5c77ba1 3246 }
b60005a8
LK
3247 if (hif_drv->hif_state < HOST_IF_CONNECTING)
3248 hif_drv->hif_state = HOST_IF_CONNECTING;
c5c77ba1 3249
31390eec
LK
3250 result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
3251 if (result) {
b92f9304 3252 netdev_err(vif->ndev, "send message: Set join request\n");
24db713f 3253 return -EFAULT;
c5c77ba1
JK
3254 }
3255
71130e81 3256 hif_drv->connect_timer.data = (unsigned long)vif;
81a59506 3257 mod_timer(&hif_drv->connect_timer,
9eb06643 3258 jiffies + msecs_to_jiffies(HOST_IF_CONNECT_TIMEOUT));
c5c77ba1 3259
31390eec 3260 return result;
c5c77ba1
JK
3261}
3262
9f723fde 3263int wilc_disconnect(struct wilc_vif *vif, u16 reason_code)
c5c77ba1 3264{
5350251a 3265 int result = 0;
143eb95a 3266 struct host_if_msg msg;
fbf5379b 3267 struct host_if_drv *hif_drv = vif->hif_drv;
c5c77ba1 3268
a4ab1ade 3269 if (!hif_drv) {
b92f9304 3270 netdev_err(vif->ndev, "Driver is null\n");
24db713f 3271 return -EFAULT;
c5c77ba1
JK
3272 }
3273
143eb95a 3274 memset(&msg, 0, sizeof(struct host_if_msg));
c5c77ba1 3275
a9f812a6 3276 msg.id = HOST_IF_MSG_DISCONNECT;
cf60106b 3277 msg.vif = vif;
c5c77ba1 3278
31390eec
LK
3279 result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
3280 if (result)
b92f9304 3281 netdev_err(vif->ndev, "Failed to send message: disconnect\n");
ae4dfa57 3282
e55e4967 3283 down(&hif_drv->sem_test_disconn_block);
c5c77ba1 3284
31390eec 3285 return result;
c5c77ba1
JK
3286}
3287
71130e81 3288static s32 host_int_get_assoc_res_info(struct wilc_vif *vif,
1608c403
AB
3289 u8 *pu8AssocRespInfo,
3290 u32 u32MaxAssocRespInfoLen,
3291 u32 *pu32RcvdAssocRespInfoLen)
c5c77ba1 3292{
31390eec 3293 s32 result = 0;
45102f83 3294 struct wid wid;
71130e81 3295 struct host_if_drv *hif_drv = vif->hif_drv;
c5c77ba1 3296
a4ab1ade 3297 if (!hif_drv) {
b92f9304 3298 netdev_err(vif->ndev, "Driver is null\n");
24db713f 3299 return -EFAULT;
c5c77ba1
JK
3300 }
3301
45102f83
LK
3302 wid.id = (u16)WID_ASSOC_RES_INFO;
3303 wid.type = WID_STR;
3304 wid.val = pu8AssocRespInfo;
3305 wid.size = u32MaxAssocRespInfoLen;
c5c77ba1 3306
79df6a49 3307 result = wilc_send_config_pkt(vif, GET_CFG, &wid, 1,
4cf93d70 3308 wilc_get_vif_idx(vif));
31390eec 3309 if (result) {
c5c77ba1 3310 *pu32RcvdAssocRespInfoLen = 0;
b92f9304 3311 netdev_err(vif->ndev, "Failed to send association response\n");
24db713f 3312 return -EINVAL;
c5c77ba1 3313 }
c22177db 3314
24c6c29d 3315 *pu32RcvdAssocRespInfoLen = wid.size;
31390eec 3316 return result;
c5c77ba1
JK
3317}
3318
fbf5379b 3319int wilc_set_mac_chnl_num(struct wilc_vif *vif, u8 channel)
c5c77ba1 3320{
792fb25b 3321 int result;
143eb95a 3322 struct host_if_msg msg;
fbf5379b 3323 struct host_if_drv *hif_drv = vif->hif_drv;
c5c77ba1 3324
a4ab1ade 3325 if (!hif_drv) {
b92f9304 3326 netdev_err(vif->ndev, "driver is null\n");
24db713f
LK
3327 return -EFAULT;
3328 }
c5c77ba1 3329
143eb95a 3330 memset(&msg, 0, sizeof(struct host_if_msg));
a9f812a6 3331 msg.id = HOST_IF_MSG_SET_CHANNEL;
730ee059 3332 msg.body.channel_info.set_ch = channel;
cf60106b 3333 msg.vif = vif;
c5c77ba1 3334
cb067dcf 3335 result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
1ef58e42 3336 if (result) {
b92f9304 3337 netdev_err(vif->ndev, "wilc mq send fail\n");
792fb25b 3338 return -EINVAL;
c5c77ba1
JK
3339 }
3340
792fb25b 3341 return 0;
c5c77ba1
JK
3342}
3343
b3306865 3344int wilc_set_wfi_drv_handler(struct wilc_vif *vif, int index, u8 mac_idx)
c5c77ba1 3345{
a094101c 3346 int result = 0;
143eb95a 3347 struct host_if_msg msg;
c09389ac 3348
143eb95a 3349 memset(&msg, 0, sizeof(struct host_if_msg));
a9f812a6 3350 msg.id = HOST_IF_MSG_SET_WFIDRV_HANDLER;
31f0f697 3351 msg.body.drv.handler = index;
b3306865 3352 msg.body.drv.mac_idx = mac_idx;
cf60106b 3353 msg.vif = vif;
c5c77ba1 3354
cb067dcf 3355 result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
a094101c 3356 if (result) {
b92f9304 3357 netdev_err(vif->ndev, "wilc mq send fail\n");
a094101c 3358 result = -EINVAL;
c5c77ba1
JK
3359 }
3360
a094101c 3361 return result;
c5c77ba1
JK
3362}
3363
fbf5379b 3364int wilc_set_operation_mode(struct wilc_vif *vif, u32 mode)
c5c77ba1 3365{
a0c1ee0c 3366 int result = 0;
143eb95a 3367 struct host_if_msg msg;
c09389ac 3368
143eb95a 3369 memset(&msg, 0, sizeof(struct host_if_msg));
a9f812a6 3370 msg.id = HOST_IF_MSG_SET_OPERATION_MODE;
c96debf1 3371 msg.body.mode.mode = mode;
cf60106b 3372 msg.vif = vif;
c5c77ba1 3373
cb067dcf 3374 result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
a0c1ee0c 3375 if (result) {
b92f9304 3376 netdev_err(vif->ndev, "wilc mq send fail\n");
a0c1ee0c 3377 result = -EINVAL;
c5c77ba1
JK
3378 }
3379
a0c1ee0c 3380 return result;
c5c77ba1
JK
3381}
3382
fbf5379b
GL
3383s32 wilc_get_inactive_time(struct wilc_vif *vif, const u8 *mac,
3384 u32 *pu32InactiveTime)
c5c77ba1 3385{
31390eec 3386 s32 result = 0;
143eb95a 3387 struct host_if_msg msg;
fbf5379b 3388 struct host_if_drv *hif_drv = vif->hif_drv;
c5c77ba1 3389
a4ab1ade 3390 if (!hif_drv) {
b92f9304 3391 netdev_err(vif->ndev, "driver is null\n");
24db713f 3392 return -EFAULT;
c5c77ba1
JK
3393 }
3394
143eb95a 3395 memset(&msg, 0, sizeof(struct host_if_msg));
8c8360b3 3396 memcpy(msg.body.mac_info.mac, mac, ETH_ALEN);
c5c77ba1 3397
a9f812a6 3398 msg.id = HOST_IF_MSG_GET_INACTIVETIME;
cf60106b 3399 msg.vif = vif;
c5c77ba1 3400
31390eec
LK
3401 result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
3402 if (result)
b92f9304 3403 netdev_err(vif->ndev, "Failed to send get host ch param\n");
c5c77ba1 3404
569a3c67 3405 down(&hif_drv->sem_inactive_time);
c5c77ba1 3406
ad26906f 3407 *pu32InactiveTime = inactive_time;
c5c77ba1 3408
31390eec 3409 return result;
c5c77ba1 3410}
108b3439 3411
652bb5e8 3412int wilc_get_rssi(struct wilc_vif *vif, s8 *rssi_level)
c5c77ba1 3413{
e16aed64 3414 int result = 0;
143eb95a 3415 struct host_if_msg msg;
fbf5379b 3416 struct host_if_drv *hif_drv = vif->hif_drv;
c5c77ba1 3417
c09389ac 3418 memset(&msg, 0, sizeof(struct host_if_msg));
a9f812a6 3419 msg.id = HOST_IF_MSG_GET_RSSI;
cf60106b 3420 msg.vif = vif;
c5c77ba1 3421
31390eec
LK
3422 result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
3423 if (result) {
b92f9304 3424 netdev_err(vif->ndev, "Failed to send get host ch param\n");
e6e12661 3425 return -EFAULT;
c5c77ba1
JK
3426 }
3427
7e111f9e 3428 down(&hif_drv->sem_get_rssi);
c5c77ba1 3429
652bb5e8 3430 if (!rssi_level) {
b92f9304 3431 netdev_err(vif->ndev, "RSS pointer value is null\n");
e6e12661 3432 return -EFAULT;
c5c77ba1
JK
3433 }
3434
652bb5e8 3435 *rssi_level = rssi;
c5c77ba1 3436
31390eec 3437 return result;
c5c77ba1
JK
3438}
3439
f70b25ff 3440int wilc_get_statistics(struct wilc_vif *vif, struct rf_info *stats)
c5c77ba1 3441{
cd163d32 3442 int result = 0;
143eb95a 3443 struct host_if_msg msg;
c5c77ba1 3444
c09389ac 3445 memset(&msg, 0, sizeof(struct host_if_msg));
a9f812a6 3446 msg.id = HOST_IF_MSG_GET_STATISTICS;
f70b25ff 3447 msg.body.data = (char *)stats;
cf60106b 3448 msg.vif = vif;
ae4dfa57 3449
31390eec
LK
3450 result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
3451 if (result) {
b92f9304 3452 netdev_err(vif->ndev, "Failed to send get host channel\n");
e6e12661 3453 return -EFAULT;
c5c77ba1
JK
3454 }
3455
4fd62291
GL
3456 if (stats != &vif->wilc->dummy_statistics)
3457 down(&hif_sema_wait_response);
31390eec 3458 return result;
c5c77ba1
JK
3459}
3460
c0734df9 3461int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type,
ce2d023f 3462 u8 *ch_freq_list, u8 ch_list_len, const u8 *ies,
2c97f2d4 3463 size_t ies_len, wilc_scan_result scan_result, void *user_arg,
d317818b 3464 struct hidden_network *hidden_network)
c5c77ba1 3465{
03a5d8c0 3466 int result = 0;
143eb95a 3467 struct host_if_msg msg;
b41dfdb1 3468 struct scan_attr *scan_info = &msg.body.scan_info;
fbf5379b 3469 struct host_if_drv *hif_drv = vif->hif_drv;
c5c77ba1 3470
c8fb0bf9 3471 if (!hif_drv || !scan_result) {
b92f9304 3472 netdev_err(vif->ndev, "hif_drv or scan_result = NULL\n");
24db713f
LK
3473 return -EFAULT;
3474 }
c5c77ba1 3475
143eb95a 3476 memset(&msg, 0, sizeof(struct host_if_msg));
c5c77ba1 3477
a9f812a6 3478 msg.id = HOST_IF_MSG_SCAN;
c5c77ba1 3479
d317818b 3480 if (hidden_network) {
b41dfdb1
CL
3481 scan_info->hidden_network.net_info = hidden_network->net_info;
3482 scan_info->hidden_network.n_ssids = hidden_network->n_ssids;
c4f97526 3483 }
c5c77ba1 3484
cf60106b 3485 msg.vif = vif;
b41dfdb1
CL
3486 scan_info->src = scan_source;
3487 scan_info->type = scan_type;
3488 scan_info->result = scan_result;
3489 scan_info->arg = user_arg;
3490
3491 scan_info->ch_list_len = ch_list_len;
3492 scan_info->ch_freq_list = kmemdup(ch_freq_list,
3493 ch_list_len,
3494 GFP_KERNEL);
3495 if (!scan_info->ch_freq_list)
1a271d99 3496 return -ENOMEM;
c5c77ba1 3497
b41dfdb1
CL
3498 scan_info->ies_len = ies_len;
3499 scan_info->ies = kmemdup(ies, ies_len, GFP_KERNEL);
3500 if (!scan_info->ies)
1a271d99 3501 return -ENOMEM;
c5c77ba1 3502
31390eec
LK
3503 result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
3504 if (result) {
b92f9304 3505 netdev_err(vif->ndev, "Error in sending message queue\n");
24db713f 3506 return -EINVAL;
c5c77ba1
JK
3507 }
3508
71130e81 3509 hif_drv->scan_timer.data = (unsigned long)vif;
13b313e4 3510 mod_timer(&hif_drv->scan_timer,
9eb06643 3511 jiffies + msecs_to_jiffies(HOST_IF_SCAN_TIMEOUT));
c5c77ba1 3512
31390eec 3513 return result;
c5c77ba1 3514}
ae4dfa57 3515
4168da71 3516int wilc_hif_set_cfg(struct wilc_vif *vif,
a5f0fb5c 3517 struct cfg_param_attr *cfg_param)
c5c77ba1 3518{
4168da71 3519 int result = 0;
143eb95a 3520 struct host_if_msg msg;
fbf5379b 3521 struct host_if_drv *hif_drv = vif->hif_drv;
c5c77ba1 3522
a4ab1ade 3523 if (!hif_drv) {
b92f9304 3524 netdev_err(vif->ndev, "hif_drv NULL\n");
24db713f
LK
3525 return -EFAULT;
3526 }
ae4dfa57 3527
143eb95a 3528 memset(&msg, 0, sizeof(struct host_if_msg));
a9f812a6 3529 msg.id = HOST_IF_MSG_CFG_PARAMS;
a5f0fb5c 3530 msg.body.cfg_info = *cfg_param;
cf60106b 3531 msg.vif = vif;
c5c77ba1 3532
31390eec 3533 result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
c5c77ba1 3534
31390eec 3535 return result;
c5c77ba1
JK
3536}
3537
93dee8ee 3538static void GetPeriodicRSSI(unsigned long arg)
c5c77ba1 3539{
71130e81 3540 struct wilc_vif *vif = (struct wilc_vif *)arg;
78c87591 3541
71130e81 3542 if (!vif->hif_drv) {
b92f9304 3543 netdev_err(vif->ndev, "Driver handler is NULL\n");
c5c77ba1
JK
3544 return;
3545 }
3546
4fd62291
GL
3547 if (vif->hif_drv->hif_state == HOST_IF_CONNECTED)
3548 wilc_get_statistics(vif, &vif->wilc->dummy_statistics);
c5c77ba1 3549
71130e81 3550 periodic_rssi.data = (unsigned long)vif;
262f55e1 3551 mod_timer(&periodic_rssi, jiffies + msecs_to_jiffies(5000));
c5c77ba1
JK
3552}
3553
1e995c10 3554int wilc_init(struct net_device *dev, struct host_if_drv **hif_drv_handler)
c5c77ba1 3555{
1e995c10 3556 int result = 0;
a4ab1ade 3557 struct host_if_drv *hif_drv;
a4cac481 3558 struct wilc_vif *vif;
d5382219 3559 struct wilc *wilc;
03efae32 3560 int i;
d5382219 3561
a4cac481
GL
3562 vif = netdev_priv(dev);
3563 wilc = vif->wilc;
c5c77ba1 3564
ca8540e4 3565 scan_while_connected = false;
c5c77ba1 3566
2d25af87 3567 sema_init(&hif_sema_wait_response, 0);
c5c77ba1 3568
a4ab1ade
TC
3569 hif_drv = kzalloc(sizeof(struct host_if_drv), GFP_KERNEL);
3570 if (!hif_drv) {
5b09bd32 3571 result = -ENOMEM;
17db84eb 3572 goto _fail_;
c5c77ba1 3573 }
a4ab1ade 3574 *hif_drv_handler = hif_drv;
03efae32
GL
3575 for (i = 0; i < wilc->vif_num; i++)
3576 if (dev == wilc->vif[i]->ndev) {
3577 wilc->vif[i]->hif_drv = hif_drv;
3578 break;
3579 }
c5c77ba1 3580
0e1af73d 3581 wilc_optaining_ip = false;
c5c77ba1 3582
c5c77ba1 3583 if (clients_count == 0) {
834e0cb0 3584 sema_init(&hif_sema_thread, 0);
27ff2168 3585 sema_init(&hif_sema_driver, 0);
440e8993 3586 sema_init(&hif_sema_deinit, 1);
83383ea3
AB
3587 }
3588
9ea47133 3589 sema_init(&hif_drv->sem_test_key_block, 0);
e55e4967 3590 sema_init(&hif_drv->sem_test_disconn_block, 0);
7e111f9e 3591 sema_init(&hif_drv->sem_get_rssi, 0);
569a3c67 3592 sema_init(&hif_drv->sem_inactive_time, 0);
c5c77ba1 3593
c5c77ba1 3594 if (clients_count == 0) {
cb067dcf 3595 result = wilc_mq_create(&hif_msg_q);
c5c77ba1 3596
5b09bd32 3597 if (result < 0) {
b92f9304 3598 netdev_err(vif->ndev, "Failed to creat MQ\n");
c5c77ba1
JK
3599 goto _fail_;
3600 }
c2115d8e 3601
d5382219
GL
3602 hif_thread_handler = kthread_run(hostIFthread, wilc,
3603 "WILC_kthread");
c2115d8e
LK
3604
3605 if (IS_ERR(hif_thread_handler)) {
b92f9304 3606 netdev_err(vif->ndev, "Failed to creat Thread\n");
5b09bd32 3607 result = -EFAULT;
c5c77ba1
JK
3608 goto _fail_mq_;
3609 }
262f55e1 3610 setup_timer(&periodic_rssi, GetPeriodicRSSI,
71130e81 3611 (unsigned long)vif);
262f55e1 3612 mod_timer(&periodic_rssi, jiffies + msecs_to_jiffies(5000));
c5c77ba1
JK
3613 }
3614
13b313e4 3615 setup_timer(&hif_drv->scan_timer, TimerCB_Scan, 0);
81a59506 3616 setup_timer(&hif_drv->connect_timer, TimerCB_Connect, 0);
cc2d7e9e 3617 setup_timer(&hif_drv->remain_on_ch_timer, ListenTimerCB, 0);
c5c77ba1 3618
33110ad7
LK
3619 sema_init(&hif_drv->sem_cfg_values, 1);
3620 down(&hif_drv->sem_cfg_values);
c5c77ba1 3621
b60005a8 3622 hif_drv->hif_state = HOST_IF_IDLE;
ace303f0
LK
3623 hif_drv->cfg_values.site_survey_enabled = SITE_SURVEY_OFF;
3624 hif_drv->cfg_values.scan_source = DEFAULT_SCAN;
3625 hif_drv->cfg_values.active_scan_time = ACTIVE_SCAN_TIME;
3626 hif_drv->cfg_values.passive_scan_time = PASSIVE_SCAN_TIME;
3627 hif_drv->cfg_values.curr_tx_rate = AUTORATE;
c5c77ba1 3628
1229b1ab 3629 hif_drv->p2p_timeout = 0;
c5c77ba1 3630
33110ad7 3631 up(&hif_drv->sem_cfg_values);
c5c77ba1 3632
ae4dfa57 3633 clients_count++;
c5c77ba1 3634
5b09bd32 3635 return result;
c5c77ba1 3636
c5c77ba1 3637_fail_mq_:
cb067dcf 3638 wilc_mq_destroy(&hif_msg_q);
c5c77ba1 3639_fail_:
5b09bd32 3640 return result;
c5c77ba1 3641}
c5c77ba1 3642
127a27c3 3643int wilc_deinit(struct wilc_vif *vif)
c5c77ba1 3644{
127a27c3 3645 int result = 0;
143eb95a 3646 struct host_if_msg msg;
fbf5379b 3647 struct host_if_drv *hif_drv = vif->hif_drv;
c5c77ba1 3648
a4ab1ade 3649 if (!hif_drv) {
b92f9304 3650 netdev_err(vif->ndev, "hif_drv = NULL\n");
8eb62f3f 3651 return -EFAULT;
c5c77ba1
JK
3652 }
3653
440e8993 3654 down(&hif_sema_deinit);
c5c77ba1 3655
a4ab1ade 3656 terminated_handle = hif_drv;
c5c77ba1 3657
c4f97526
CP
3658 del_timer_sync(&hif_drv->scan_timer);
3659 del_timer_sync(&hif_drv->connect_timer);
3660 del_timer_sync(&periodic_rssi);
cc2d7e9e 3661 del_timer_sync(&hif_drv->remain_on_ch_timer);
c5c77ba1 3662
b3306865 3663 wilc_set_wfi_drv_handler(vif, 0, 0);
27ff2168 3664 down(&hif_sema_driver);
c5c77ba1 3665
bc801855
LK
3666 if (hif_drv->usr_scan_req.scan_result) {
3667 hif_drv->usr_scan_req.scan_result(SCAN_EVENT_ABORTED, NULL,
66eaea30 3668 hif_drv->usr_scan_req.arg, NULL);
bc801855 3669 hif_drv->usr_scan_req.scan_result = NULL;
c5c77ba1 3670 }
c5c77ba1 3671
b60005a8 3672 hif_drv->hif_state = HOST_IF_IDLE;
c5c77ba1 3673
ca8540e4 3674 scan_while_connected = false;
c5c77ba1 3675
143eb95a 3676 memset(&msg, 0, sizeof(struct host_if_msg));
c5c77ba1
JK
3677
3678 if (clients_count == 1) {
c4f97526 3679 del_timer_sync(&periodic_rssi);
a9f812a6 3680 msg.id = HOST_IF_MSG_EXIT;
cf60106b 3681 msg.vif = vif;
c5c77ba1 3682
31390eec
LK
3683 result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
3684 if (result != 0)
b92f9304 3685 netdev_err(vif->ndev, "deinit : Error(%d)\n", result);
c5c77ba1 3686
834e0cb0 3687 down(&hif_sema_thread);
c5c77ba1 3688
cb067dcf 3689 wilc_mq_destroy(&hif_msg_q);
c5c77ba1
JK
3690 }
3691
a4ab1ade 3692 kfree(hif_drv);
c5c77ba1 3693
ae4dfa57 3694 clients_count--;
b1413b60 3695 terminated_handle = NULL;
440e8993 3696 up(&hif_sema_deinit);
31390eec 3697 return result;
c5c77ba1
JK
3698}
3699
cd04d221
GL
3700void wilc_network_info_received(struct wilc *wilc, u8 *pu8Buffer,
3701 u32 u32Length)
c5c77ba1 3702{
31390eec 3703 s32 result = 0;
143eb95a 3704 struct host_if_msg msg;
d42ab083 3705 int id;
a4ab1ade 3706 struct host_if_drv *hif_drv = NULL;
eb9939b7 3707 struct wilc_vif *vif;
c5c77ba1 3708
d42ab083 3709 id = ((pu8Buffer[u32Length - 4]) | (pu8Buffer[u32Length - 3] << 8) | (pu8Buffer[u32Length - 2] << 16) | (pu8Buffer[u32Length - 1] << 24));
eb9939b7
GL
3710 vif = wilc_get_vif_from_idx(wilc, id);
3711 if (!vif)
3712 return;
3713 hif_drv = vif->hif_drv;
c5c77ba1 3714
a4ab1ade 3715 if (!hif_drv || hif_drv == terminated_handle) {
b92f9304 3716 netdev_err(vif->ndev, "driver not init[%p]\n", hif_drv);
c5c77ba1
JK
3717 return;
3718 }
3719
143eb95a 3720 memset(&msg, 0, sizeof(struct host_if_msg));
c5c77ba1 3721
a9f812a6 3722 msg.id = HOST_IF_MSG_RCVD_NTWRK_INFO;
eb9939b7 3723 msg.vif = vif;
c5c77ba1 3724
3bffac68 3725 msg.body.net_info.len = u32Length;
b021b80b
LK
3726 msg.body.net_info.buffer = kmalloc(u32Length, GFP_KERNEL);
3727 memcpy(msg.body.net_info.buffer, pu8Buffer, u32Length);
c5c77ba1 3728
31390eec
LK
3729 result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
3730 if (result)
b92f9304 3731 netdev_err(vif->ndev, "message parameters (%d)\n", result);
c5c77ba1
JK
3732}
3733
cd04d221
GL
3734void wilc_gnrl_async_info_received(struct wilc *wilc, u8 *pu8Buffer,
3735 u32 u32Length)
c5c77ba1 3736{
31390eec 3737 s32 result = 0;
143eb95a 3738 struct host_if_msg msg;
d42ab083 3739 int id;
a4ab1ade 3740 struct host_if_drv *hif_drv = NULL;
eb9939b7 3741 struct wilc_vif *vif;
c5c77ba1 3742
440e8993 3743 down(&hif_sema_deinit);
c5c77ba1 3744
d42ab083 3745 id = ((pu8Buffer[u32Length - 4]) | (pu8Buffer[u32Length - 3] << 8) | (pu8Buffer[u32Length - 2] << 16) | (pu8Buffer[u32Length - 1] << 24));
eb9939b7
GL
3746 vif = wilc_get_vif_from_idx(wilc, id);
3747 if (!vif) {
3748 up(&hif_sema_deinit);
3749 return;
3750 }
3751
3752 hif_drv = vif->hif_drv;
c5c77ba1 3753
a4ab1ade 3754 if (!hif_drv || hif_drv == terminated_handle) {
440e8993 3755 up(&hif_sema_deinit);
c5c77ba1
JK
3756 return;
3757 }
3758
33bfb198 3759 if (!hif_drv->usr_conn_req.conn_result) {
b92f9304 3760 netdev_err(vif->ndev, "there is no current Connect Request\n");
440e8993 3761 up(&hif_sema_deinit);
c5c77ba1
JK
3762 return;
3763 }
3764
143eb95a 3765 memset(&msg, 0, sizeof(struct host_if_msg));
c5c77ba1 3766
a9f812a6 3767 msg.id = HOST_IF_MSG_RCVD_GNRL_ASYNC_INFO;
eb9939b7 3768 msg.vif = vif;
c5c77ba1 3769
f94f4889 3770 msg.body.async_info.len = u32Length;
33722ac7
LK
3771 msg.body.async_info.buffer = kmalloc(u32Length, GFP_KERNEL);
3772 memcpy(msg.body.async_info.buffer, pu8Buffer, u32Length);
c5c77ba1 3773
31390eec
LK
3774 result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
3775 if (result)
b92f9304 3776 netdev_err(vif->ndev, "synchronous info (%d)\n", result);
c5c77ba1 3777
440e8993 3778 up(&hif_sema_deinit);
c5c77ba1
JK
3779}
3780
cd04d221
GL
3781void wilc_scan_complete_received(struct wilc *wilc, u8 *pu8Buffer,
3782 u32 u32Length)
c5c77ba1 3783{
31390eec 3784 s32 result = 0;
143eb95a 3785 struct host_if_msg msg;
d42ab083 3786 int id;
a4ab1ade 3787 struct host_if_drv *hif_drv = NULL;
eb9939b7 3788 struct wilc_vif *vif;
78c87591 3789
d42ab083 3790 id = ((pu8Buffer[u32Length - 4]) | (pu8Buffer[u32Length - 3] << 8) | (pu8Buffer[u32Length - 2] << 16) | (pu8Buffer[u32Length - 1] << 24));
eb9939b7
GL
3791 vif = wilc_get_vif_from_idx(wilc, id);
3792 if (!vif)
3793 return;
3794 hif_drv = vif->hif_drv;
c5c77ba1 3795
a4ab1ade 3796 if (!hif_drv || hif_drv == terminated_handle)
c5c77ba1 3797 return;
c5c77ba1 3798
bc801855 3799 if (hif_drv->usr_scan_req.scan_result) {
143eb95a 3800 memset(&msg, 0, sizeof(struct host_if_msg));
c5c77ba1 3801
a9f812a6 3802 msg.id = HOST_IF_MSG_RCVD_SCAN_COMPLETE;
eb9939b7 3803 msg.vif = vif;
c5c77ba1 3804
31390eec
LK
3805 result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
3806 if (result)
b92f9304 3807 netdev_err(vif->ndev, "complete param (%d)\n", result);
c5c77ba1 3808 }
c5c77ba1
JK
3809}
3810
6f7584be 3811int wilc_remain_on_channel(struct wilc_vif *vif, u32 session_id,
d44cd45e 3812 u32 duration, u16 chan,
95bfdd58 3813 wilc_remain_on_chan_expired expired,
1aae9398 3814 wilc_remain_on_chan_ready ready,
482c4330 3815 void *user_arg)
c5c77ba1 3816{
6d6bc400 3817 int result = 0;
143eb95a 3818 struct host_if_msg msg;
fbf5379b 3819 struct host_if_drv *hif_drv = vif->hif_drv;
c5c77ba1 3820
a4ab1ade 3821 if (!hif_drv) {
b92f9304 3822 netdev_err(vif->ndev, "driver is null\n");
24db713f
LK
3823 return -EFAULT;
3824 }
c5c77ba1 3825
143eb95a 3826 memset(&msg, 0, sizeof(struct host_if_msg));
c5c77ba1 3827
a9f812a6 3828 msg.id = HOST_IF_MSG_REMAIN_ON_CHAN;
839ab709 3829 msg.body.remain_on_ch.ch = chan;
95bfdd58 3830 msg.body.remain_on_ch.expired = expired;
1aae9398 3831 msg.body.remain_on_ch.ready = ready;
482c4330 3832 msg.body.remain_on_ch.arg = user_arg;
d44cd45e 3833 msg.body.remain_on_ch.duration = duration;
6f7584be 3834 msg.body.remain_on_ch.id = session_id;
cf60106b 3835 msg.vif = vif;
143eb95a 3836
31390eec
LK
3837 result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
3838 if (result)
b92f9304 3839 netdev_err(vif->ndev, "wilc mq send fail\n");
c5c77ba1 3840
31390eec 3841 return result;
c5c77ba1
JK
3842}
3843
6b0f7cdd 3844int wilc_listen_state_expired(struct wilc_vif *vif, u32 session_id)
c5c77ba1 3845{
5ca581ef 3846 int result = 0;
143eb95a 3847 struct host_if_msg msg;
fbf5379b 3848 struct host_if_drv *hif_drv = vif->hif_drv;
c5c77ba1 3849
a4ab1ade 3850 if (!hif_drv) {
b92f9304 3851 netdev_err(vif->ndev, "driver is null\n");
24db713f
LK
3852 return -EFAULT;
3853 }
c5c77ba1 3854
cc2d7e9e 3855 del_timer(&hif_drv->remain_on_ch_timer);
c5c77ba1 3856
143eb95a 3857 memset(&msg, 0, sizeof(struct host_if_msg));
a9f812a6 3858 msg.id = HOST_IF_MSG_LISTEN_TIMER_FIRED;
cf60106b 3859 msg.vif = vif;
6b0f7cdd 3860 msg.body.remain_on_ch.id = session_id;
c5c77ba1 3861
31390eec
LK
3862 result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
3863 if (result)
b92f9304 3864 netdev_err(vif->ndev, "wilc mq send fail\n");
c5c77ba1 3865
31390eec 3866 return result;
c5c77ba1
JK
3867}
3868
8859fc28 3869int wilc_frame_register(struct wilc_vif *vif, u16 frame_type, bool reg)
c5c77ba1 3870{
de61db9e 3871 int result = 0;
143eb95a 3872 struct host_if_msg msg;
fbf5379b 3873 struct host_if_drv *hif_drv = vif->hif_drv;
c5c77ba1 3874
a4ab1ade 3875 if (!hif_drv) {
b92f9304 3876 netdev_err(vif->ndev, "driver is null\n");
24db713f
LK
3877 return -EFAULT;
3878 }
c5c77ba1 3879
143eb95a 3880 memset(&msg, 0, sizeof(struct host_if_msg));
c5c77ba1 3881
a9f812a6 3882 msg.id = HOST_IF_MSG_REGISTER_FRAME;
2a8432ff 3883 switch (frame_type) {
c5c77ba1 3884 case ACTION:
bcb410bb 3885 msg.body.reg_frame.reg_id = ACTION_FRM_IDX;
c5c77ba1
JK
3886 break;
3887
3888 case PROBE_REQ:
bcb410bb 3889 msg.body.reg_frame.reg_id = PROBE_REQ_IDX;
c5c77ba1
JK
3890 break;
3891
3892 default:
c5c77ba1
JK
3893 break;
3894 }
2a8432ff 3895 msg.body.reg_frame.frame_type = frame_type;
8859fc28 3896 msg.body.reg_frame.reg = reg;
cf60106b 3897 msg.vif = vif;
c5c77ba1 3898
31390eec
LK
3899 result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
3900 if (result)
b92f9304 3901 netdev_err(vif->ndev, "wilc mq send fail\n");
c5c77ba1 3902
31390eec 3903 return result;
c5c77ba1 3904}
c5c77ba1 3905
916935f5 3906int wilc_add_beacon(struct wilc_vif *vif, u32 interval, u32 dtim_period,
733d1031 3907 u32 head_len, u8 *head, u32 tail_len, u8 *tail)
c5c77ba1 3908{
4d84dbed 3909 int result = 0;
143eb95a 3910 struct host_if_msg msg;
75bf22c1 3911 struct beacon_attr *beacon_info = &msg.body.beacon_info;
fbf5379b 3912 struct host_if_drv *hif_drv = vif->hif_drv;
c5c77ba1 3913
a4ab1ade 3914 if (!hif_drv) {
b92f9304 3915 netdev_err(vif->ndev, "driver is null\n");
24db713f
LK
3916 return -EFAULT;
3917 }
c5c77ba1 3918
143eb95a 3919 memset(&msg, 0, sizeof(struct host_if_msg));
c5c77ba1 3920
a9f812a6 3921 msg.id = HOST_IF_MSG_ADD_BEACON;
cf60106b 3922 msg.vif = vif;
75bf22c1
CL
3923 beacon_info->interval = interval;
3924 beacon_info->dtim_period = dtim_period;
3925 beacon_info->head_len = head_len;
3926 beacon_info->head = kmemdup(head, head_len, GFP_KERNEL);
3927 if (!beacon_info->head) {
31390eec 3928 result = -ENOMEM;
24db713f
LK
3929 goto ERRORHANDLER;
3930 }
75bf22c1 3931 beacon_info->tail_len = tail_len;
c5c77ba1 3932
2df3585b 3933 if (tail_len > 0) {
75bf22c1
CL
3934 beacon_info->tail = kmemdup(tail, tail_len, GFP_KERNEL);
3935 if (!beacon_info->tail) {
31390eec 3936 result = -ENOMEM;
24db713f
LK
3937 goto ERRORHANDLER;
3938 }
c5c77ba1 3939 } else {
75bf22c1 3940 beacon_info->tail = NULL;
c5c77ba1
JK
3941 }
3942
31390eec
LK
3943 result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
3944 if (result)
b92f9304 3945 netdev_err(vif->ndev, "wilc mq send fail\n");
c5c77ba1 3946
24db713f 3947ERRORHANDLER:
31390eec 3948 if (result) {
75bf22c1 3949 kfree(beacon_info->head);
c5c77ba1 3950
75bf22c1 3951 kfree(beacon_info->tail);
c5c77ba1
JK
3952 }
3953
31390eec 3954 return result;
c5c77ba1
JK
3955}
3956
fbf5379b 3957int wilc_del_beacon(struct wilc_vif *vif)
c5c77ba1 3958{
0a5298cb 3959 int result = 0;
143eb95a 3960 struct host_if_msg msg;
fbf5379b 3961 struct host_if_drv *hif_drv = vif->hif_drv;
c5c77ba1 3962
a4ab1ade 3963 if (!hif_drv) {
b92f9304 3964 netdev_err(vif->ndev, "driver is null\n");
24db713f
LK
3965 return -EFAULT;
3966 }
c5c77ba1 3967
a9f812a6 3968 msg.id = HOST_IF_MSG_DEL_BEACON;
cf60106b 3969 msg.vif = vif;
c5c77ba1 3970
31390eec
LK
3971 result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
3972 if (result)
b92f9304 3973 netdev_err(vif->ndev, "wilc_mq_send fail\n");
c5c77ba1 3974
31390eec 3975 return result;
c5c77ba1
JK
3976}
3977
fbf5379b 3978int wilc_add_station(struct wilc_vif *vif, struct add_sta_param *sta_param)
c5c77ba1 3979{
18cfbd33 3980 int result = 0;
143eb95a 3981 struct host_if_msg msg;
773e02e6 3982 struct add_sta_param *add_sta_info = &msg.body.add_sta_info;
fbf5379b 3983 struct host_if_drv *hif_drv = vif->hif_drv;
c5c77ba1 3984
a4ab1ade 3985 if (!hif_drv) {
b92f9304 3986 netdev_err(vif->ndev, "driver is null\n");
24db713f
LK
3987 return -EFAULT;
3988 }
c5c77ba1 3989
143eb95a 3990 memset(&msg, 0, sizeof(struct host_if_msg));
c5c77ba1 3991
a9f812a6 3992 msg.id = HOST_IF_MSG_ADD_STATION;
cf60106b 3993 msg.vif = vif;
c5c77ba1 3994
773e02e6
CL
3995 memcpy(add_sta_info, sta_param, sizeof(struct add_sta_param));
3996 if (add_sta_info->rates_len > 0) {
9062305b
CL
3997 add_sta_info->rates = kmemdup(sta_param->rates,
3998 add_sta_info->rates_len,
3999 GFP_KERNEL);
4000 if (!add_sta_info->rates)
7ae43363 4001 return -ENOMEM;
c5c77ba1
JK
4002 }
4003
31390eec
LK
4004 result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
4005 if (result)
b92f9304 4006 netdev_err(vif->ndev, "wilc_mq_send fail\n");
31390eec 4007 return result;
c5c77ba1
JK
4008}
4009
fbf5379b 4010int wilc_del_station(struct wilc_vif *vif, const u8 *mac_addr)
c5c77ba1 4011{
79a0c0a8 4012 int result = 0;
143eb95a 4013 struct host_if_msg msg;
c87fbede 4014 struct del_sta *del_sta_info = &msg.body.del_sta_info;
fbf5379b 4015 struct host_if_drv *hif_drv = vif->hif_drv;
c5c77ba1 4016
a4ab1ade 4017 if (!hif_drv) {
b92f9304 4018 netdev_err(vif->ndev, "driver is null\n");
24db713f
LK
4019 return -EFAULT;
4020 }
c5c77ba1 4021
143eb95a 4022 memset(&msg, 0, sizeof(struct host_if_msg));
c5c77ba1 4023
a9f812a6 4024 msg.id = HOST_IF_MSG_DEL_STATION;
cf60106b 4025 msg.vif = vif;
c5c77ba1 4026
c9c4eb41 4027 if (!mac_addr)
c87fbede 4028 eth_broadcast_addr(del_sta_info->mac_addr);
c5c77ba1 4029 else
c87fbede 4030 memcpy(del_sta_info->mac_addr, mac_addr, ETH_ALEN);
c5c77ba1 4031
31390eec
LK
4032 result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
4033 if (result)
b92f9304 4034 netdev_err(vif->ndev, "wilc_mq_send fail\n");
31390eec 4035 return result;
c5c77ba1 4036}
ae4dfa57 4037
2092374d 4038int wilc_del_allstation(struct wilc_vif *vif, u8 mac_addr[][ETH_ALEN])
c5c77ba1 4039{
253eb92e 4040 int result = 0;
143eb95a 4041 struct host_if_msg msg;
55d44a62 4042 struct del_all_sta *del_all_sta_info = &msg.body.del_all_sta_info;
fbf5379b 4043 struct host_if_drv *hif_drv = vif->hif_drv;
06e682b0 4044 u8 zero_addr[ETH_ALEN] = {0};
cc971eec 4045 int i;
9d6cec9f 4046 u8 assoc_sta = 0;
c5c77ba1 4047
a4ab1ade 4048 if (!hif_drv) {
b92f9304 4049 netdev_err(vif->ndev, "driver is null\n");
24db713f
LK
4050 return -EFAULT;
4051 }
c5c77ba1 4052
143eb95a 4053 memset(&msg, 0, sizeof(struct host_if_msg));
c5c77ba1 4054
a9f812a6 4055 msg.id = HOST_IF_MSG_DEL_ALL_STA;
cf60106b 4056 msg.vif = vif;
c5c77ba1 4057
c5c77ba1 4058 for (i = 0; i < MAX_NUM_STA; i++) {
06e682b0 4059 if (memcmp(mac_addr[i], zero_addr, ETH_ALEN)) {
55d44a62 4060 memcpy(del_all_sta_info->del_all_sta[i], mac_addr[i], ETH_ALEN);
9d6cec9f 4061 assoc_sta++;
c5c77ba1
JK
4062 }
4063 }
9ac0c05c 4064 if (!assoc_sta)
31390eec 4065 return result;
c5c77ba1 4066
9d6cec9f 4067 del_all_sta_info->assoc_sta = assoc_sta;
31390eec 4068 result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
c5c77ba1 4069
31390eec 4070 if (result)
b92f9304 4071 netdev_err(vif->ndev, "wilc_mq_send fail\n");
c5c77ba1 4072
2d25af87 4073 down(&hif_sema_wait_response);
c5c77ba1 4074
31390eec 4075 return result;
c5c77ba1
JK
4076}
4077
4208e663 4078int wilc_edit_station(struct wilc_vif *vif,
4c7abe19 4079 struct add_sta_param *sta_param)
c5c77ba1 4080{
4208e663 4081 int result = 0;
143eb95a 4082 struct host_if_msg msg;
785c0712 4083 struct add_sta_param *add_sta_info = &msg.body.add_sta_info;
fbf5379b 4084 struct host_if_drv *hif_drv = vif->hif_drv;
c5c77ba1 4085
a4ab1ade 4086 if (!hif_drv) {
b92f9304 4087 netdev_err(vif->ndev, "driver is null\n");
24db713f
LK
4088 return -EFAULT;
4089 }
c5c77ba1 4090
143eb95a 4091 memset(&msg, 0, sizeof(struct host_if_msg));
c5c77ba1 4092
a9f812a6 4093 msg.id = HOST_IF_MSG_EDIT_STATION;
cf60106b 4094 msg.vif = vif;
c5c77ba1 4095
785c0712
CL
4096 memcpy(add_sta_info, sta_param, sizeof(struct add_sta_param));
4097 if (add_sta_info->rates_len > 0) {
e38d850f
CL
4098 add_sta_info->rates = kmemdup(sta_param->rates,
4099 add_sta_info->rates_len,
4100 GFP_KERNEL);
4101 if (!add_sta_info->rates)
7ae43363 4102 return -ENOMEM;
c5c77ba1
JK
4103 }
4104
31390eec
LK
4105 result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
4106 if (result)
b92f9304 4107 netdev_err(vif->ndev, "wilc_mq_send fail\n");
24db713f 4108
31390eec 4109 return result;
c5c77ba1 4110}
108b3439 4111
ecd27500 4112int wilc_set_power_mgmt(struct wilc_vif *vif, bool enabled, u32 timeout)
c5c77ba1 4113{
5d48f12c 4114 int result = 0;
143eb95a 4115 struct host_if_msg msg;
568640e4 4116 struct power_mgmt_param *pwr_mgmt_info = &msg.body.pwr_mgmt_info;
fbf5379b 4117 struct host_if_drv *hif_drv = vif->hif_drv;
c5c77ba1 4118
a4ab1ade 4119 if (!hif_drv) {
b92f9304 4120 netdev_err(vif->ndev, "driver is null\n");
24db713f
LK
4121 return -EFAULT;
4122 }
c5c77ba1 4123
ff9d65ab
GL
4124 if (wilc_wlan_get_num_conn_ifcs(vif->wilc) == 2 && enabled)
4125 return 0;
4126
143eb95a 4127 memset(&msg, 0, sizeof(struct host_if_msg));
c5c77ba1 4128
a9f812a6 4129 msg.id = HOST_IF_MSG_POWER_MGMT;
cf60106b 4130 msg.vif = vif;
c5c77ba1 4131
568640e4
CL
4132 pwr_mgmt_info->enabled = enabled;
4133 pwr_mgmt_info->timeout = timeout;
c5c77ba1 4134
31390eec
LK
4135 result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
4136 if (result)
b92f9304 4137 netdev_err(vif->ndev, "wilc_mq_send fail\n");
31390eec 4138 return result;
c5c77ba1
JK
4139}
4140
b80c0943 4141int wilc_setup_multicast_filter(struct wilc_vif *vif, bool enabled,
2dff2d42 4142 u32 count)
c5c77ba1 4143{
14d9526f 4144 int result = 0;
143eb95a 4145 struct host_if_msg msg;
40ecd38a 4146 struct set_multicast *multicast_filter_param = &msg.body.multicast_info;
fbf5379b 4147 struct host_if_drv *hif_drv = vif->hif_drv;
c5c77ba1 4148
a4ab1ade 4149 if (!hif_drv) {
b92f9304 4150 netdev_err(vif->ndev, "driver is null\n");
24db713f
LK
4151 return -EFAULT;
4152 }
c5c77ba1 4153
143eb95a 4154 memset(&msg, 0, sizeof(struct host_if_msg));
c5c77ba1 4155
a9f812a6 4156 msg.id = HOST_IF_MSG_SET_MULTICAST_FILTER;
cf60106b 4157 msg.vif = vif;
c5c77ba1 4158
40ecd38a
CL
4159 multicast_filter_param->enabled = enabled;
4160 multicast_filter_param->cnt = count;
c5c77ba1 4161
31390eec
LK
4162 result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
4163 if (result)
b92f9304 4164 netdev_err(vif->ndev, "wilc_mq_send fail\n");
31390eec 4165 return result;
c5c77ba1
JK
4166}
4167
6b5180a0 4168static void *host_int_ParseJoinBssParam(struct network_info *ptstrNetworkInfo)
c5c77ba1 4169{
e0a12217 4170 struct join_bss_param *pNewJoinBssParam = NULL;
63d03e47 4171 u8 *pu8IEs;
d85f5326
CL
4172 u16 u16IEsLen;
4173 u16 index = 0;
63d03e47
GKH
4174 u8 suppRatesNo = 0;
4175 u8 extSuppRatesNo;
d85f5326 4176 u16 jumpOffset;
63d03e47
GKH
4177 u8 pcipherCount;
4178 u8 authCount;
4179 u8 pcipherTotalCount = 0;
4180 u8 authTotalCount = 0;
4181 u8 i, j;
c5c77ba1 4182
390b6db0
LK
4183 pu8IEs = ptstrNetworkInfo->ies;
4184 u16IEsLen = ptstrNetworkInfo->ies_len;
c5c77ba1 4185
b156f1ed 4186 pNewJoinBssParam = kzalloc(sizeof(struct join_bss_param), GFP_KERNEL);
91109e11 4187 if (pNewJoinBssParam) {
df340fdf 4188 pNewJoinBssParam->dtim_period = ptstrNetworkInfo->dtim_period;
4b313e91 4189 pNewJoinBssParam->beacon_period = ptstrNetworkInfo->beacon_period;
fa5e2d15 4190 pNewJoinBssParam->cap_info = ptstrNetworkInfo->cap_info;
f1764293 4191 memcpy(pNewJoinBssParam->bssid, ptstrNetworkInfo->bssid, 6);
2a3ff58a 4192 memcpy((u8 *)pNewJoinBssParam->ssid, ptstrNetworkInfo->ssid,
a36e89e9
LK
4193 ptstrNetworkInfo->ssid_len + 1);
4194 pNewJoinBssParam->ssid_len = ptstrNetworkInfo->ssid_len;
2cc46837
CL
4195 memset(pNewJoinBssParam->rsn_pcip_policy, 0xFF, 3);
4196 memset(pNewJoinBssParam->rsn_auth_policy, 0xFF, 3);
c5c77ba1 4197
c5c77ba1 4198 while (index < u16IEsLen) {
c5c77ba1 4199 if (pu8IEs[index] == SUPP_RATES_IE) {
c5c77ba1
JK
4200 suppRatesNo = pu8IEs[index + 1];
4201 pNewJoinBssParam->supp_rates[0] = suppRatesNo;
ae4dfa57 4202 index += 2;
c5c77ba1 4203
d1666e2a 4204 for (i = 0; i < suppRatesNo; i++)
c5c77ba1 4205 pNewJoinBssParam->supp_rates[i + 1] = pu8IEs[index + i];
d1666e2a 4206
c5c77ba1
JK
4207 index += suppRatesNo;
4208 continue;
ae4dfa57 4209 } else if (pu8IEs[index] == EXT_SUPP_RATES_IE) {
c5c77ba1
JK
4210 extSuppRatesNo = pu8IEs[index + 1];
4211 if (extSuppRatesNo > (MAX_RATES_SUPPORTED - suppRatesNo))
4212 pNewJoinBssParam->supp_rates[0] = MAX_RATES_SUPPORTED;
4213 else
4214 pNewJoinBssParam->supp_rates[0] += extSuppRatesNo;
4215 index += 2;
d1666e2a 4216 for (i = 0; i < (pNewJoinBssParam->supp_rates[0] - suppRatesNo); i++)
c5c77ba1 4217 pNewJoinBssParam->supp_rates[suppRatesNo + i + 1] = pu8IEs[index + i];
d1666e2a 4218
c5c77ba1
JK
4219 index += extSuppRatesNo;
4220 continue;
ae4dfa57 4221 } else if (pu8IEs[index] == HT_CAPABILITY_IE) {
0be1eb74 4222 pNewJoinBssParam->ht_capable = true;
ae4dfa57 4223 index += pu8IEs[index + 1] + 2;
c5c77ba1 4224 continue;
ae4dfa57 4225 } else if ((pu8IEs[index] == WMM_IE) &&
c5c77ba1 4226 (pu8IEs[index + 2] == 0x00) && (pu8IEs[index + 3] == 0x50) &&
ae4dfa57
LK
4227 (pu8IEs[index + 4] == 0xF2) &&
4228 (pu8IEs[index + 5] == 0x02) &&
4229 ((pu8IEs[index + 6] == 0x00) || (pu8IEs[index + 6] == 0x01)) &&
c5c77ba1 4230 (pu8IEs[index + 7] == 0x01)) {
0be1eb74 4231 pNewJoinBssParam->wmm_cap = true;
c5c77ba1 4232
ffda203c 4233 if (pu8IEs[index + 8] & BIT(7))
0be1eb74 4234 pNewJoinBssParam->uapsd_cap = true;
c5c77ba1
JK
4235 index += pu8IEs[index + 1] + 2;
4236 continue;
ae4dfa57 4237 } else if ((pu8IEs[index] == P2P_IE) &&
c5c77ba1 4238 (pu8IEs[index + 2] == 0x50) && (pu8IEs[index + 3] == 0x6f) &&
ae4dfa57
LK
4239 (pu8IEs[index + 4] == 0x9a) &&
4240 (pu8IEs[index + 5] == 0x09) && (pu8IEs[index + 6] == 0x0c)) {
d85f5326 4241 u16 u16P2P_count;
78c87591 4242
afb70653 4243 pNewJoinBssParam->tsf = ptstrNetworkInfo->tsf_lo;
7a8d51d7 4244 pNewJoinBssParam->noa_enabled = 1;
cc179008 4245 pNewJoinBssParam->idx = pu8IEs[index + 9];
c5c77ba1 4246
ffda203c 4247 if (pu8IEs[index + 10] & BIT(7)) {
d72b33ca 4248 pNewJoinBssParam->opp_enabled = 1;
99b66945 4249 pNewJoinBssParam->ct_window = pu8IEs[index + 10];
d72b33ca
LK
4250 } else {
4251 pNewJoinBssParam->opp_enabled = 0;
4252 }
ae4dfa57 4253
c21047ed 4254 pNewJoinBssParam->cnt = pu8IEs[index + 11];
c5c77ba1
JK
4255 u16P2P_count = index + 12;
4256
109e6cab 4257 memcpy(pNewJoinBssParam->duration, pu8IEs + u16P2P_count, 4);
c5c77ba1
JK
4258 u16P2P_count += 4;
4259
1d8b76b3 4260 memcpy(pNewJoinBssParam->interval, pu8IEs + u16P2P_count, 4);
c5c77ba1
JK
4261 u16P2P_count += 4;
4262
4be55e22 4263 memcpy(pNewJoinBssParam->start_time, pu8IEs + u16P2P_count, 4);
c5c77ba1
JK
4264
4265 index += pu8IEs[index + 1] + 2;
4266 continue;
4267
ae4dfa57 4268 } else if ((pu8IEs[index] == RSN_IE) ||
c5c77ba1
JK
4269 ((pu8IEs[index] == WPA_IE) && (pu8IEs[index + 2] == 0x00) &&
4270 (pu8IEs[index + 3] == 0x50) && (pu8IEs[index + 4] == 0xF2) &&
4271 (pu8IEs[index + 5] == 0x01))) {
d85f5326 4272 u16 rsnIndex = index;
ae4dfa57 4273
c5c77ba1
JK
4274 if (pu8IEs[rsnIndex] == RSN_IE) {
4275 pNewJoinBssParam->mode_802_11i = 2;
ae4dfa57 4276 } else {
c5c77ba1
JK
4277 if (pNewJoinBssParam->mode_802_11i == 0)
4278 pNewJoinBssParam->mode_802_11i = 1;
c5c77ba1
JK
4279 rsnIndex += 4;
4280 }
ae4dfa57
LK
4281
4282 rsnIndex += 7;
c5c77ba1
JK
4283 pNewJoinBssParam->rsn_grp_policy = pu8IEs[rsnIndex];
4284 rsnIndex++;
ae4dfa57 4285 jumpOffset = pu8IEs[rsnIndex] * 4;
c5c77ba1 4286 pcipherCount = (pu8IEs[rsnIndex] > 3) ? 3 : pu8IEs[rsnIndex];
ae4dfa57 4287 rsnIndex += 2;
c5c77ba1 4288
d1666e2a 4289 for (i = pcipherTotalCount, j = 0; i < pcipherCount + pcipherTotalCount && i < 3; i++, j++)
c5c77ba1 4290 pNewJoinBssParam->rsn_pcip_policy[i] = pu8IEs[rsnIndex + ((j + 1) * 4) - 1];
d1666e2a 4291
c5c77ba1
JK
4292 pcipherTotalCount += pcipherCount;
4293 rsnIndex += jumpOffset;
4294
4295 jumpOffset = pu8IEs[rsnIndex] * 4;
4296
c5c77ba1 4297 authCount = (pu8IEs[rsnIndex] > 3) ? 3 : pu8IEs[rsnIndex];
ae4dfa57 4298 rsnIndex += 2;
c5c77ba1 4299
d1666e2a 4300 for (i = authTotalCount, j = 0; i < authTotalCount + authCount; i++, j++)
c5c77ba1 4301 pNewJoinBssParam->rsn_auth_policy[i] = pu8IEs[rsnIndex + ((j + 1) * 4) - 1];
d1666e2a 4302
c5c77ba1
JK
4303 authTotalCount += authCount;
4304 rsnIndex += jumpOffset;
ae4dfa57 4305
c5c77ba1
JK
4306 if (pu8IEs[index] == RSN_IE) {
4307 pNewJoinBssParam->rsn_cap[0] = pu8IEs[rsnIndex];
4308 pNewJoinBssParam->rsn_cap[1] = pu8IEs[rsnIndex + 1];
4309 rsnIndex += 2;
4310 }
f717c0eb 4311 pNewJoinBssParam->rsn_found = true;
ae4dfa57 4312 index += pu8IEs[index + 1] + 2;
c5c77ba1
JK
4313 continue;
4314 } else
ae4dfa57 4315 index += pu8IEs[index + 1] + 2;
c5c77ba1 4316 }
c5c77ba1
JK
4317 }
4318
4319 return (void *)pNewJoinBssParam;
c5c77ba1
JK
4320}
4321
6964f086 4322int wilc_setup_ipaddress(struct wilc_vif *vif, u8 *ip_addr, u8 idx)
c5c77ba1 4323{
3d2a0bf7 4324 int result = 0;
143eb95a 4325 struct host_if_msg msg;
fbf5379b 4326 struct host_if_drv *hif_drv = vif->hif_drv;
c5c77ba1 4327
a4ab1ade 4328 if (!hif_drv) {
b92f9304 4329 netdev_err(vif->ndev, "driver is null\n");
24db713f
LK
4330 return -EFAULT;
4331 }
c5c77ba1 4332
143eb95a 4333 memset(&msg, 0, sizeof(struct host_if_msg));
c5c77ba1 4334
a9f812a6 4335 msg.id = HOST_IF_MSG_SET_IPADDRESS;
c5c77ba1 4336
6964f086 4337 msg.body.ip_info.ip_addr = ip_addr;
cf60106b 4338 msg.vif = vif;
fb2d65ed 4339 msg.body.ip_info.idx = idx;
c5c77ba1 4340
31390eec
LK
4341 result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
4342 if (result)
b92f9304 4343 netdev_err(vif->ndev, "wilc_mq_send fail\n");
c5c77ba1 4344
31390eec 4345 return result;
c5c77ba1
JK
4346}
4347
3b4276d9 4348static int host_int_get_ipaddress(struct wilc_vif *vif, u8 *ip_addr, u8 idx)
c5c77ba1 4349{
cb8f4e0e 4350 int result = 0;
143eb95a 4351 struct host_if_msg msg;
f8813d3a 4352 struct host_if_drv *hif_drv = vif->hif_drv;
c5c77ba1 4353
a4ab1ade 4354 if (!hif_drv) {
b92f9304 4355 netdev_err(vif->ndev, "driver is null\n");
24db713f
LK
4356 return -EFAULT;
4357 }
c5c77ba1 4358
143eb95a 4359 memset(&msg, 0, sizeof(struct host_if_msg));
c5c77ba1 4360
a9f812a6 4361 msg.id = HOST_IF_MSG_GET_IPADDRESS;
c5c77ba1 4362
3b4276d9 4363 msg.body.ip_info.ip_addr = ip_addr;
cf60106b 4364 msg.vif = vif;
fb2d65ed 4365 msg.body.ip_info.idx = idx;
c5c77ba1 4366
31390eec
LK
4367 result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
4368 if (result)
b92f9304 4369 netdev_err(vif->ndev, "wilc_mq_send fail\n");
c5c77ba1 4370
31390eec 4371 return result;
c5c77ba1 4372}
70418790
GL
4373
4374int wilc_set_tx_power(struct wilc_vif *vif, u8 tx_power)
4375{
4376 int ret = 0;
4377 struct host_if_msg msg;
4378
4379 memset(&msg, 0, sizeof(struct host_if_msg));
4380
4381 msg.id = HOST_IF_MSG_SET_TX_POWER;
4382 msg.body.tx_power.tx_pwr = tx_power;
4383 msg.vif = vif;
4384
4385 ret = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
4386 if (ret)
4387 netdev_err(vif->ndev, "wilc_mq_send fail\n");
4388
4389 return ret;
4390}
4391
4392int wilc_get_tx_power(struct wilc_vif *vif, u8 *tx_power)
4393{
4394 int ret = 0;
4395 struct host_if_msg msg;
4396
4397 memset(&msg, 0, sizeof(struct host_if_msg));
4398
4399 msg.id = HOST_IF_MSG_GET_TX_POWER;
4400 msg.vif = vif;
4401
4402 ret = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
4403 if (ret)
4404 netdev_err(vif->ndev, "Failed to get TX PWR\n");
4405
4406 down(&hif_sema_wait_response);
4407 *tx_power = msg.body.tx_power.tx_pwr;
4408
4409 return ret;
4410}