host_interface.c 108 KB
Newer Older
1
2
3
4
#include <linux/slab.h>
#include <linux/time.h>
#include <linux/kthread.h>
#include <linux/delay.h>
5
#include <linux/completion.h>
6
7
#include "host_interface.h"
#include "coreconfigurator.h"
8
#include "wilc_wlan.h"
9
#include "wilc_wlan_if.h"
10
#include "wilc_msgqueue.h"
11
#include <linux/etherdevice.h>
12
#include "wilc_wfi_netdevice.h"
13

14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#define HOST_IF_MSG_SCAN                        0
#define HOST_IF_MSG_CONNECT                     1
#define HOST_IF_MSG_RCVD_GNRL_ASYNC_INFO        2
#define HOST_IF_MSG_KEY                         3
#define HOST_IF_MSG_RCVD_NTWRK_INFO             4
#define HOST_IF_MSG_RCVD_SCAN_COMPLETE          5
#define HOST_IF_MSG_CFG_PARAMS                  6
#define HOST_IF_MSG_SET_CHANNEL                 7
#define HOST_IF_MSG_DISCONNECT                  8
#define HOST_IF_MSG_GET_RSSI                    9
#define HOST_IF_MSG_ADD_BEACON                  11
#define HOST_IF_MSG_DEL_BEACON                  12
#define HOST_IF_MSG_ADD_STATION                 13
#define HOST_IF_MSG_DEL_STATION                 14
#define HOST_IF_MSG_EDIT_STATION                15
#define HOST_IF_MSG_SCAN_TIMER_FIRED            16
#define HOST_IF_MSG_CONNECT_TIMER_FIRED         17
#define HOST_IF_MSG_POWER_MGMT                  18
#define HOST_IF_MSG_GET_INACTIVETIME            19
#define HOST_IF_MSG_REMAIN_ON_CHAN              20
#define HOST_IF_MSG_REGISTER_FRAME              21
#define HOST_IF_MSG_LISTEN_TIMER_FIRED          22
#define HOST_IF_MSG_SET_WFIDRV_HANDLER          24
#define HOST_IF_MSG_GET_MAC_ADDRESS             26
#define HOST_IF_MSG_SET_OPERATION_MODE          27
#define HOST_IF_MSG_SET_IPADDRESS               28
#define HOST_IF_MSG_GET_IPADDRESS               29
#define HOST_IF_MSG_GET_STATISTICS              31
#define HOST_IF_MSG_SET_MULTICAST_FILTER        32
#define HOST_IF_MSG_DEL_BA_SESSION              34
#define HOST_IF_MSG_DEL_ALL_STA                 36
45
46
#define HOST_IF_MSG_SET_TX_POWER		38
#define HOST_IF_MSG_GET_TX_POWER		39
47
#define HOST_IF_MSG_EXIT                        100
48

49
50
#define HOST_IF_SCAN_TIMEOUT                    4000
#define HOST_IF_CONNECT_TIMEOUT                 9500
51

52
53
54
#define BA_SESSION_DEFAULT_BUFFER_SIZE          16
#define BA_SESSION_DEFAULT_TIMEOUT              1000
#define BLOCK_ACK_REQ_SIZE                      0x14
55
#define FALSE_FRMWR_CHANNEL			100
56

57
58
59
#define TCP_ACK_FILTER_LINK_SPEED_THRESH	54
#define DEFAULT_LINK_SPEED			72

60
struct host_if_wpa_attr {
61
	u8 *key;
62
	const u8 *mac_addr;
63
	u8 *seq;
64
	u8 seq_len;
65
	u8 index;
66
	u8 key_len;
67
	u8 mode;
68
};
69

70
struct host_if_wep_attr {
71
	u8 *key;
72
	u8 key_len;
73
	u8 index;
74
	u8 mode;
75
	enum AUTHTYPE auth_type;
76
};
77

78
union host_if_key_attr {
79
	struct host_if_wep_attr wep;
80
	struct host_if_wpa_attr wpa;
81
	struct host_if_pmkid_attr pmkid;
82
};
83

84
struct key_attr {
85
	enum KEY_TYPE type;
86
	u8 action;
87
	union host_if_key_attr attr;
88
};
89

90
struct scan_attr {
91
	u8 src;
92
	u8 type;
93
	u8 *ch_freq_list;
94
	u8 ch_list_len;
95
	u8 *ies;
96
	size_t ies_len;
97
	wilc_scan_result result;
98
	void *arg;
99
	struct hidden_network hidden_network;
100
};
101

102
struct connect_attr {
103
	u8 *bssid;
104
	u8 *ssid;
105
	size_t ssid_len;
106
	u8 *ies;
107
	size_t ies_len;
108
	u8 security;
109
	wilc_connect_result result;
110
	void *arg;
111
	enum AUTHTYPE auth_type;
112
	u8 ch;
113
	void *params;
114
};
115

116
struct rcvd_async_info {
117
	u8 *buffer;
118
	u32 len;
119
};
120

121
struct channel_attr {
122
	u8 set_ch;
123
};
124

125
struct beacon_attr {
126
	u32 interval;
127
	u32 dtim_period;
128
	u32 head_len;
129
	u8 *head;
130
	u32 tail_len;
131
	u8 *tail;
132
};
133

134
struct set_multicast {
135
	bool enabled;
136
	u32 cnt;
137
};
138

139
struct del_all_sta {
140
	u8 del_all_sta[MAX_NUM_STA][ETH_ALEN];
141
	u8 assoc_sta;
142
};
143

144
struct del_sta {
145
	u8 mac_addr[ETH_ALEN];
146
};
147

148
struct power_mgmt_param {
149
	bool enabled;
150
	u32 timeout;
151
};
152

153
struct set_ip_addr {
154
	u8 *ip_addr;
155
	u8 idx;
156
};
157

158
struct sta_inactive_t {
159
	u8 mac[6];
160
};
161

162
163
164
165
struct tx_power {
	u8 tx_pwr;
};

166
union message_body {
167
	struct scan_attr scan_info;
168
	struct connect_attr con_info;
169
	struct rcvd_net_info net_info;
170
	struct rcvd_async_info async_info;
171
	struct key_attr key_info;
172
	struct cfg_param_attr cfg_info;
173
	struct channel_attr channel_info;
174
	struct beacon_attr beacon_info;
175
	struct add_sta_param add_sta_info;
176
	struct del_sta del_sta_info;
177
	struct add_sta_param edit_sta_info;
178
	struct power_mgmt_param pwr_mgmt_info;
179
	struct sta_inactive_t mac_info;
180
	struct set_ip_addr ip_info;
181
	struct drv_handler drv;
182
	struct set_multicast multicast_info;
183
	struct op_mode mode;
184
	struct get_mac_addr get_mac_info;
185
	struct ba_session_info session_info;
186
	struct remain_ch remain_on_ch;
187
	struct reg_frame reg_frame;
Tony Cho's avatar
Tony Cho committed
188
	char *data;
189
	struct del_all_sta del_all_sta_info;
190
	struct tx_power tx_power;
191
};
192

193
struct host_if_msg {
194
195
	u16 id;
	union message_body body;
196
	struct wilc_vif *vif;
197
};
198

199
struct join_bss_param {
200
	BSSTYPE_T bss_type;
201
	u8 dtim_period;
202
203
	u16 beacon_period;
	u16 cap_info;
204
	u8 bssid[6];
205
	char ssid[MAX_SSID_LEN];
206
	u8 ssid_len;
207
208
209
210
	u8 supp_rates[MAX_RATES_SUPPORTED + 1];
	u8 ht_capable;
	u8 wmm_cap;
	u8 uapsd_cap;
211
	bool rsn_found;
212
213
214
215
216
	u8 rsn_grp_policy;
	u8 mode_802_11i;
	u8 rsn_pcip_policy[3];
	u8 rsn_auth_policy[3];
	u8 rsn_cap[2];
217
	u32 tsf;
218
	u8 noa_enabled;
219
	u8 opp_enabled;
220
	u8 ct_window;
221
	u8 cnt;
222
	u8 idx;
223
	u8 duration[4];
224
	u8 interval[4];
225
	u8 start_time[4];
226
};
227

228
static struct host_if_drv *terminated_handle;
229
bool wilc_optaining_ip;
230
static u8 P2P_LISTEN_STATE;
231
static struct task_struct *hif_thread_handler;
232
static struct message_queue hif_msg_q;
233
static struct completion hif_thread_comp;
234
static struct completion hif_driver_comp;
235
static struct completion hif_wait_response;
236
static struct mutex hif_deinit_lock;
237
static struct timer_list periodic_rssi;
238

239
u8 wilc_multicast_mac_addr_list[WILC_MULTICAST_TABLE_SIZE][ETH_ALEN];
240

241
static u8 rcv_assoc_resp[MAX_ASSOC_RESP_FRAME_SIZE];
242

243
static bool scan_while_connected;
244

245
static s8 rssi;
246
static u8 set_ip[2][4];
247
static u8 get_ip[2][4];
248
static u32 inactive_time;
249
static u8 del_beacon;
250
static u32 clients_count;
251

252
static u8 *join_req;
253
static u8 *info_element;
254
static u8 mode_11i;
255
256
static u8 auth_type;
static u32 join_req_size;
257
static u32 info_element_size;
258
static struct wilc_vif *join_req_vif;
259
260
#define REAL_JOIN_REQ 0
#define FLUSHED_JOIN_REQ 1
261
#define FLUSHED_BYTE_POS 79
262

263
static void *host_int_ParseJoinBssParam(struct network_info *ptstrNetworkInfo);
264
static int host_int_get_ipaddress(struct wilc_vif *vif, u8 *ip_addr, u8 idx);
265
static s32 Handle_ScanDone(struct wilc_vif *vif, enum scan_event enuEvent);
266

267
268
269
270
/* The u8IfIdx starts from 0 to NUM_CONCURRENT_IFC -1, but 0 index used as
 * special purpose in wilc device, so we add 1 to the index to starts from 1.
 * As a result, the returned index will be 1 to NUM_CONCURRENT_IFC.
 */
271
int wilc_get_vif_idx(struct wilc_vif *vif)
272
{
273
	return vif->idx + 1;
274
275
276
277
278
279
280
281
282
283
284
285
}

/* We need to minus 1 from idx which is from wilc device to get real index
 * of wilc->vif[], because we add 1 when pass to wilc device in the function
 * wilc_get_vif_idx.
 * As a result, the index should be between 0 and NUM_CONCURRENT_IFC -1.
 */
static struct wilc_vif *wilc_get_vif_from_idx(struct wilc *wilc, int idx)
{
	int index = idx - 1;

	if (index < 0 || index >= NUM_CONCURRENT_IFC)
286
		return NULL;
287
288

	return wilc->vif[index];
289
290
}

291
292
static void handle_set_channel(struct wilc_vif *vif,
			       struct channel_attr *hif_set_ch)
293
{
294
	int ret = 0;
295
	struct wid wid;
296

297
298
	wid.id = (u16)WID_CURRENT_CHANNEL;
	wid.type = WID_CHAR;
299
	wid.val = (char *)&hif_set_ch->set_ch;
300
	wid.size = sizeof(char);
301

302
303
	ret = wilc_send_config_pkt(vif, SET_CFG, &wid, 1,
				   wilc_get_vif_idx(vif));
304

305
	if (ret)
306
		netdev_err(vif->ndev, "Failed to set channel\n");
307
}
308

309
310
static void handle_set_wfi_drv_handler(struct wilc_vif *vif,
				       struct drv_handler *hif_drv_handler)
311
{
312
	int ret = 0;
313
	struct wid wid;
314

315
	wid.id = (u16)WID_SET_DRV_HANDLER;
316
317
318
	wid.type = WID_STR;
	wid.val = (s8 *)hif_drv_handler;
	wid.size = sizeof(*hif_drv_handler);
319

320
321
	ret = wilc_send_config_pkt(vif, SET_CFG, &wid, 1,
				   hif_drv_handler->handler);
322

323
	if (!hif_drv_handler->handler)
324
		complete(&hif_driver_comp);
325

326
	if (ret)
327
		netdev_err(vif->ndev, "Failed to set driver handler\n");
328
329
}

330
331
static void handle_set_operation_mode(struct wilc_vif *vif,
				      struct op_mode *hif_op_mode)
332
{
333
	int ret = 0;
334
	struct wid wid;
335

336
337
	wid.id = (u16)WID_SET_OPERATION_MODE;
	wid.type = WID_INT;
338
	wid.val = (s8 *)&hif_op_mode->mode;
339
	wid.size = sizeof(u32);
340

341
342
	ret = wilc_send_config_pkt(vif, SET_CFG, &wid, 1,
				   wilc_get_vif_idx(vif));
343

344
	if ((hif_op_mode->mode) == IDLE_MODE)
345
		complete(&hif_driver_comp);
346

347
	if (ret)
348
		netdev_err(vif->ndev, "Failed to set driver handler\n");
349
350
}

351
static void handle_set_ip_address(struct wilc_vif *vif, u8 *ip_addr, u8 idx)
352
{
353
	int ret = 0;
354
	struct wid wid;
355
	char firmware_ip_addr[4] = {0};
356

357
358
	if (ip_addr[0] < 192)
		ip_addr[0] = 0;
359

360
	memcpy(set_ip[idx], ip_addr, IP_ALEN);
361

362
363
	wid.id = (u16)WID_IP_ADDRESS;
	wid.type = WID_STR;
364
	wid.val = (u8 *)ip_addr;
365
	wid.size = IP_ALEN;
366

367
368
	ret = wilc_send_config_pkt(vif, SET_CFG, &wid, 1,
				   wilc_get_vif_idx(vif));
369

370
	host_int_get_ipaddress(vif, firmware_ip_addr, idx);
371

372
	if (ret)
373
		netdev_err(vif->ndev, "Failed to set IP address\n");
374
375
}

376
static void handle_get_ip_address(struct wilc_vif *vif, u8 idx)
377
{
378
	int ret = 0;
379
	struct wid wid;
380

381
382
383
384
	wid.id = (u16)WID_IP_ADDRESS;
	wid.type = WID_STR;
	wid.val = kmalloc(IP_ALEN, GFP_KERNEL);
	wid.size = IP_ALEN;
385

386
387
	ret = wilc_send_config_pkt(vif, GET_CFG, &wid, 1,
				   wilc_get_vif_idx(vif));
388

389
	memcpy(get_ip[idx], wid.val, IP_ALEN);
390

391
	kfree(wid.val);
392

393
	if (memcmp(get_ip[idx], set_ip[idx], IP_ALEN) != 0)
394
		wilc_setup_ipaddress(vif, set_ip[idx], idx);
395

396
	if (ret)
397
		netdev_err(vif->ndev, "Failed to get IP address\n");
398
399
}

400
401
static void handle_get_mac_address(struct wilc_vif *vif,
				   struct get_mac_addr *get_mac_addr)
402
{
403
	int ret = 0;
404
	struct wid wid;
405

406
407
	wid.id = (u16)WID_MAC_ADDR;
	wid.type = WID_STR;
408
	wid.val = get_mac_addr->mac_addr;
409
	wid.size = ETH_ALEN;
410

411
412
	ret = wilc_send_config_pkt(vif, GET_CFG, &wid, 1,
				   wilc_get_vif_idx(vif));
413

414
	if (ret)
415
		netdev_err(vif->ndev, "Failed to get mac address\n");
416
	complete(&hif_wait_response);
417
418
}

419
420
static void handle_cfg_param(struct wilc_vif *vif,
			     struct cfg_param_attr *cfg_param_attr)
421
{
422
	int ret = 0;
423
	struct wid wid_list[32];
424
	struct host_if_drv *hif_drv = vif->hif_drv;
425
	int i = 0;
426

427
	mutex_lock(&hif_drv->cfg_values_lock);
428

429
	if (cfg_param_attr->flag & BSS_TYPE) {
430
431
432
		u8 bss_type = cfg_param_attr->bss_type;

		if (bss_type < 6) {
433
			wid_list[i].id = WID_BSS_TYPE;
434
			wid_list[i].val = (s8 *)&bss_type;
435
436
			wid_list[i].type = WID_CHAR;
			wid_list[i].size = sizeof(char);
437
			hif_drv->cfg_values.bss_type = bss_type;
438
		} else {
439
			netdev_err(vif->ndev, "check value 6 over\n");
440
			goto unlock;
441
		}
442
		i++;
443
	}
444
445
446
447
	if (cfg_param_attr->flag & AUTH_TYPE) {
		if (cfg_param_attr->auth_type == 1 ||
		    cfg_param_attr->auth_type == 2 ||
		    cfg_param_attr->auth_type == 5) {
448
449
450
451
			wid_list[i].id = WID_AUTH_TYPE;
			wid_list[i].val = (s8 *)&cfg_param_attr->auth_type;
			wid_list[i].type = WID_CHAR;
			wid_list[i].size = sizeof(char);
452
			hif_drv->cfg_values.auth_type = (u8)cfg_param_attr->auth_type;
453
		} else {
454
			netdev_err(vif->ndev, "Impossible value\n");
455
			goto unlock;
456
		}
457
		i++;
458
	}
459
460
461
	if (cfg_param_attr->flag & AUTHEN_TIMEOUT) {
		if (cfg_param_attr->auth_timeout > 0 &&
		    cfg_param_attr->auth_timeout < 65536) {
462
463
464
465
			wid_list[i].id = WID_AUTH_TIMEOUT;
			wid_list[i].val = (s8 *)&cfg_param_attr->auth_timeout;
			wid_list[i].type = WID_SHORT;
			wid_list[i].size = sizeof(u16);
466
			hif_drv->cfg_values.auth_timeout = cfg_param_attr->auth_timeout;
467
		} else {
468
			netdev_err(vif->ndev, "Range(1 ~ 65535) over\n");
469
			goto unlock;
470
		}
471
		i++;
472
	}
473
474
	if (cfg_param_attr->flag & POWER_MANAGEMENT) {
		if (cfg_param_attr->power_mgmt_mode < 5) {
475
476
477
478
			wid_list[i].id = WID_POWER_MANAGEMENT;
			wid_list[i].val = (s8 *)&cfg_param_attr->power_mgmt_mode;
			wid_list[i].type = WID_CHAR;
			wid_list[i].size = sizeof(char);
479
			hif_drv->cfg_values.power_mgmt_mode = (u8)cfg_param_attr->power_mgmt_mode;
480
		} else {
481
			netdev_err(vif->ndev, "Invalid power mode\n");
482
			goto unlock;
483
		}
484
		i++;
485
	}
486
487
488
	if (cfg_param_attr->flag & RETRY_SHORT) {
		if (cfg_param_attr->short_retry_limit > 0 &&
		    cfg_param_attr->short_retry_limit < 256) {
489
490
491
492
			wid_list[i].id = WID_SHORT_RETRY_LIMIT;
			wid_list[i].val = (s8 *)&cfg_param_attr->short_retry_limit;
			wid_list[i].type = WID_SHORT;
			wid_list[i].size = sizeof(u16);
493
			hif_drv->cfg_values.short_retry_limit = cfg_param_attr->short_retry_limit;
494
		} else {
495
			netdev_err(vif->ndev, "Range(1~256) over\n");
496
			goto unlock;
497
		}
498
		i++;
499
	}
500
501
502
	if (cfg_param_attr->flag & RETRY_LONG) {
		if (cfg_param_attr->long_retry_limit > 0 &&
		    cfg_param_attr->long_retry_limit < 256) {
503
504
505
506
			wid_list[i].id = WID_LONG_RETRY_LIMIT;
			wid_list[i].val = (s8 *)&cfg_param_attr->long_retry_limit;
			wid_list[i].type = WID_SHORT;
			wid_list[i].size = sizeof(u16);
507
			hif_drv->cfg_values.long_retry_limit = cfg_param_attr->long_retry_limit;
508
		} else {
509
			netdev_err(vif->ndev, "Range(1~256) over\n");
510
			goto unlock;
511
		}
512
		i++;
513
	}
514
515
516
	if (cfg_param_attr->flag & FRAG_THRESHOLD) {
		if (cfg_param_attr->frag_threshold > 255 &&
		    cfg_param_attr->frag_threshold < 7937) {
517
518
519
520
			wid_list[i].id = WID_FRAG_THRESHOLD;
			wid_list[i].val = (s8 *)&cfg_param_attr->frag_threshold;
			wid_list[i].type = WID_SHORT;
			wid_list[i].size = sizeof(u16);
521
			hif_drv->cfg_values.frag_threshold = cfg_param_attr->frag_threshold;
522
		} else {
523
			netdev_err(vif->ndev, "Threshold Range fail\n");
524
			goto unlock;
525
		}
526
		i++;
527
	}
528
529
530
	if (cfg_param_attr->flag & RTS_THRESHOLD) {
		if (cfg_param_attr->rts_threshold > 255 &&
		    cfg_param_attr->rts_threshold < 65536) {
531
532
533
534
			wid_list[i].id = WID_RTS_THRESHOLD;
			wid_list[i].val = (s8 *)&cfg_param_attr->rts_threshold;
			wid_list[i].type = WID_SHORT;
			wid_list[i].size = sizeof(u16);
535
			hif_drv->cfg_values.rts_threshold = cfg_param_attr->rts_threshold;
536
		} else {
537
			netdev_err(vif->ndev, "Threshold Range fail\n");
538
			goto unlock;
539
		}
540
		i++;
541
	}
542
543
	if (cfg_param_attr->flag & PREAMBLE) {
		if (cfg_param_attr->preamble_type < 3) {
544
545
546
547
			wid_list[i].id = WID_PREAMBLE;
			wid_list[i].val = (s8 *)&cfg_param_attr->preamble_type;
			wid_list[i].type = WID_CHAR;
			wid_list[i].size = sizeof(char);
548
			hif_drv->cfg_values.preamble_type = cfg_param_attr->preamble_type;
549
		} else {
550
			netdev_err(vif->ndev, "Preamle Range(0~2) over\n");
551
			goto unlock;
552
		}
553
		i++;
554
	}
555
556
	if (cfg_param_attr->flag & SHORT_SLOT_ALLOWED) {
		if (cfg_param_attr->short_slot_allowed < 2) {
557
558
559
560
			wid_list[i].id = WID_SHORT_SLOT_ALLOWED;
			wid_list[i].val = (s8 *)&cfg_param_attr->short_slot_allowed;
			wid_list[i].type = WID_CHAR;
			wid_list[i].size = sizeof(char);
561
			hif_drv->cfg_values.short_slot_allowed = (u8)cfg_param_attr->short_slot_allowed;
562
		} else {
563
			netdev_err(vif->ndev, "Short slot(2) over\n");
564
			goto unlock;
565
		}
566
		i++;
567
	}
568
569
	if (cfg_param_attr->flag & TXOP_PROT_DISABLE) {
		if (cfg_param_attr->txop_prot_disabled < 2) {
570
571
572
573
			wid_list[i].id = WID_11N_TXOP_PROT_DISABLE;
			wid_list[i].val = (s8 *)&cfg_param_attr->txop_prot_disabled;
			wid_list[i].type = WID_CHAR;
			wid_list[i].size = sizeof(char);
574
			hif_drv->cfg_values.txop_prot_disabled = (u8)cfg_param_attr->txop_prot_disabled;
575
		} else {
576
			netdev_err(vif->ndev, "TXOP prot disable\n");
577
			goto unlock;
578
		}
579
		i++;
580
	}
581
582
583
	if (cfg_param_attr->flag & BEACON_INTERVAL) {
		if (cfg_param_attr->beacon_interval > 0 &&
		    cfg_param_attr->beacon_interval < 65536) {
584
585
586
587
			wid_list[i].id = WID_BEACON_INTERVAL;
			wid_list[i].val = (s8 *)&cfg_param_attr->beacon_interval;
			wid_list[i].type = WID_SHORT;
			wid_list[i].size = sizeof(u16);
588
			hif_drv->cfg_values.beacon_interval = cfg_param_attr->beacon_interval;
589
		} else {
590
			netdev_err(vif->ndev, "Beacon interval(1~65535)fail\n");
591
			goto unlock;
592
		}
593
		i++;
594
	}
595
596
597
	if (cfg_param_attr->flag & DTIM_PERIOD) {
		if (cfg_param_attr->dtim_period > 0 &&
		    cfg_param_attr->dtim_period < 256) {
598
599
600
601
			wid_list[i].id = WID_DTIM_PERIOD;
			wid_list[i].val = (s8 *)&cfg_param_attr->dtim_period;
			wid_list[i].type = WID_CHAR;
			wid_list[i].size = sizeof(char);
602
			hif_drv->cfg_values.dtim_period = cfg_param_attr->dtim_period;
603
		} else {
604
			netdev_err(vif->ndev, "DTIM range(1~255) fail\n");
605
			goto unlock;
606
		}
607
		i++;
608
	}
609
610
	if (cfg_param_attr->flag & SITE_SURVEY) {
		if (cfg_param_attr->site_survey_enabled < 3) {
611
612
613
614
			wid_list[i].id = WID_SITE_SURVEY;
			wid_list[i].val = (s8 *)&cfg_param_attr->site_survey_enabled;
			wid_list[i].type = WID_CHAR;
			wid_list[i].size = sizeof(char);
615
			hif_drv->cfg_values.site_survey_enabled = (u8)cfg_param_attr->site_survey_enabled;
616
		} else {
617
			netdev_err(vif->ndev, "Site survey disable\n");
618
			goto unlock;
619
		}
620
		i++;
621
	}
622
623
624
	if (cfg_param_attr->flag & SITE_SURVEY_SCAN_TIME) {
		if (cfg_param_attr->site_survey_scan_time > 0 &&
		    cfg_param_attr->site_survey_scan_time < 65536) {
625
626
627
628
			wid_list[i].id = WID_SITE_SURVEY_SCAN_TIME;
			wid_list[i].val = (s8 *)&cfg_param_attr->site_survey_scan_time;
			wid_list[i].type = WID_SHORT;
			wid_list[i].size = sizeof(u16);
629
			hif_drv->cfg_values.site_survey_scan_time = cfg_param_attr->site_survey_scan_time;
630
		} else {
631
			netdev_err(vif->ndev, "Site scan time(1~65535) over\n");
632
			goto unlock;
633
		}
634
		i++;
635
	}
636
637
638
	if (cfg_param_attr->flag & ACTIVE_SCANTIME) {
		if (cfg_param_attr->active_scan_time > 0 &&
		    cfg_param_attr->active_scan_time < 65536) {
639
640
641
642
			wid_list[i].id = WID_ACTIVE_SCAN_TIME;
			wid_list[i].val = (s8 *)&cfg_param_attr->active_scan_time;
			wid_list[i].type = WID_SHORT;
			wid_list[i].size = sizeof(u16);
643
			hif_drv->cfg_values.active_scan_time = cfg_param_attr->active_scan_time;
644
		} else {
645
			netdev_err(vif->ndev, "Active time(1~65535) over\n");
646
			goto unlock;
647
		}
648
		i++;
649
	}
650
651
652
	if (cfg_param_attr->flag & PASSIVE_SCANTIME) {
		if (cfg_param_attr->passive_scan_time > 0 &&
		    cfg_param_attr->passive_scan_time < 65536) {
653
654
655
656
			wid_list[i].id = WID_PASSIVE_SCAN_TIME;
			wid_list[i].val = (s8 *)&cfg_param_attr->passive_scan_time;
			wid_list[i].type = WID_SHORT;
			wid_list[i].size = sizeof(u16);
657
			hif_drv->cfg_values.passive_scan_time = cfg_param_attr->passive_scan_time;
658
		} else {
659
			netdev_err(vif->ndev, "Passive time(1~65535) over\n");
660
			goto unlock;
661
		}
662
		i++;
663
	}
664
665
	if (cfg_param_attr->flag & CURRENT_TX_RATE) {
		enum CURRENT_TXRATE curr_tx_rate = cfg_param_attr->curr_tx_rate;
666

667
668
669
670
671
		if (curr_tx_rate == AUTORATE || curr_tx_rate == MBPS_1 ||
		    curr_tx_rate == MBPS_2 || curr_tx_rate == MBPS_5_5 ||
		    curr_tx_rate == MBPS_11 || curr_tx_rate == MBPS_6 ||
		    curr_tx_rate == MBPS_9 || curr_tx_rate == MBPS_12 ||
		    curr_tx_rate == MBPS_18 || curr_tx_rate == MBPS_24 ||
672
673
		    curr_tx_rate == MBPS_36 || curr_tx_rate == MBPS_48 ||
		    curr_tx_rate == MBPS_54) {
674
675
676
677
			wid_list[i].id = WID_CURRENT_TX_RATE;
			wid_list[i].val = (s8 *)&curr_tx_rate;
			wid_list[i].type = WID_SHORT;
			wid_list[i].size = sizeof(u16);
678
			hif_drv->cfg_values.curr_tx_rate = (u8)curr_tx_rate;
679
		} else {
680
			netdev_err(vif->ndev, "out of TX rate\n");
681
			goto unlock;
682
		}
683
		i++;
684
	}
685

686
687
	ret = wilc_send_config_pkt(vif, SET_CFG, wid_list,
				   i, wilc_get_vif_idx(vif));
688

689
	if (ret)
690
		netdev_err(vif->ndev, "Error in setting CFG params\n");
691

692
unlock:
693
	mutex_unlock(&hif_drv->cfg_values_lock);
694
695
}

696
static s32 handle_scan(