]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/blame - drivers/staging/wilc1000/wilc_wfi_cfgoperations.c
Merge remote-tracking branches 'asoc/topic/sgtl5000', 'asoc/topic/simple', 'asoc...
[mirror_ubuntu-zesty-kernel.git] / drivers / staging / wilc1000 / wilc_wfi_cfgoperations.c
CommitLineData
c5c77ba1 1#include "wilc_wfi_cfgoperations.h"
491880eb 2#include "host_interface.h"
7ae43363 3#include <linux/errno.h>
c5c77ba1 4
15162fbc
AB
5#define NO_ENCRYPT 0
6#define ENCRYPT_ENABLED BIT(0)
7#define WEP BIT(1)
8#define WEP_EXTENDED BIT(2)
9#define WPA BIT(3)
10#define WPA2 BIT(4)
11#define AES BIT(5)
12#define TKIP BIT(6)
13
15162fbc
AB
14#define FRAME_TYPE_ID 0
15#define ACTION_CAT_ID 24
16#define ACTION_SUBTYPE_ID 25
17#define P2P_PUB_ACTION_SUBTYPE 30
18
15162fbc
AB
19#define ACTION_FRAME 0xd0
20#define GO_INTENT_ATTR_ID 0x04
21#define CHANLIST_ATTR_ID 0x0b
22#define OPERCHAN_ATTR_ID 0x11
23#define PUB_ACTION_ATTR_ID 0x04
24#define P2PELEM_ATTR_ID 0xdd
25
15162fbc
AB
26#define GO_NEG_REQ 0x00
27#define GO_NEG_RSP 0x01
28#define GO_NEG_CONF 0x02
29#define P2P_INV_REQ 0x03
30#define P2P_INV_RSP 0x04
31#define PUBLIC_ACT_VENDORSPEC 0x09
32#define GAS_INTIAL_REQ 0x0a
33#define GAS_INTIAL_RSP 0x0b
34
35#define INVALID_CHANNEL 0
36
37#define nl80211_SCAN_RESULT_EXPIRE (3 * HZ)
38#define SCAN_RESULT_EXPIRE (40 * HZ)
39
40static const u32 cipher_suites[] = {
41 WLAN_CIPHER_SUITE_WEP40,
42 WLAN_CIPHER_SUITE_WEP104,
43 WLAN_CIPHER_SUITE_TKIP,
44 WLAN_CIPHER_SUITE_CCMP,
45 WLAN_CIPHER_SUITE_AES_CMAC,
46};
47
48static const struct ieee80211_txrx_stypes
49 wilc_wfi_cfg80211_mgmt_types[NUM_NL80211_IFTYPES] = {
50 [NL80211_IFTYPE_STATION] = {
51 .tx = 0xffff,
52 .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
53 BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
54 },
55 [NL80211_IFTYPE_AP] = {
56 .tx = 0xffff,
57 .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
58 BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
59 BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
60 BIT(IEEE80211_STYPE_DISASSOC >> 4) |
61 BIT(IEEE80211_STYPE_AUTH >> 4) |
62 BIT(IEEE80211_STYPE_DEAUTH >> 4) |
63 BIT(IEEE80211_STYPE_ACTION >> 4)
64 },
65 [NL80211_IFTYPE_P2P_CLIENT] = {
66 .tx = 0xffff,
67 .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
68 BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
69 BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
70 BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
71 BIT(IEEE80211_STYPE_DISASSOC >> 4) |
72 BIT(IEEE80211_STYPE_AUTH >> 4) |
73 BIT(IEEE80211_STYPE_DEAUTH >> 4)
74 }
75};
76
73584a40
GL
77static const struct wiphy_wowlan_support wowlan_support = {
78 .flags = WIPHY_WOWLAN_ANY
79};
80
15162fbc
AB
81#define WILC_WFI_DWELL_PASSIVE 100
82#define WILC_WFI_DWELL_ACTIVE 40
83
84#define TCP_ACK_FILTER_LINK_SPEED_THRESH 54
85#define DEFAULT_LINK_SPEED 72
86
87
c5c77ba1
JK
88#define IS_MANAGMEMENT 0x100
89#define IS_MANAGMEMENT_CALLBACK 0x080
90#define IS_MGMT_STATUS_SUCCES 0x040
91#define GET_PKT_OFFSET(a) (((a) >> 22) & 0x1ff)
92
0e1af73d
AB
93extern int wilc_mac_open(struct net_device *ndev);
94extern int wilc_mac_close(struct net_device *ndev);
c5c77ba1 95
6b5180a0 96static struct network_info last_scanned_shadow[MAX_NUM_SCANNED_NETWORKS_SHADOW];
771fbae4 97static u32 last_scanned_cnt;
0e1af73d 98struct timer_list wilc_during_ip_timer;
1608c403 99static struct timer_list hAgingTimer;
63d03e47 100static u8 op_ifcs;
c5c77ba1 101
0e1af73d 102u8 wilc_initialized = 1;
c5c77ba1
JK
103
104#define CHAN2G(_channel, _freq, _flags) { \
57fbcce3 105 .band = NL80211_BAND_2GHZ, \
c5c77ba1
JK
106 .center_freq = (_freq), \
107 .hw_value = (_channel), \
108 .flags = (_flags), \
109 .max_antenna_gain = 0, \
110 .max_power = 30, \
111}
112
2736f476 113static struct ieee80211_channel ieee80211_2ghz_channels[] = {
c5c77ba1
JK
114 CHAN2G(1, 2412, 0),
115 CHAN2G(2, 2417, 0),
116 CHAN2G(3, 2422, 0),
117 CHAN2G(4, 2427, 0),
118 CHAN2G(5, 2432, 0),
119 CHAN2G(6, 2437, 0),
120 CHAN2G(7, 2442, 0),
121 CHAN2G(8, 2447, 0),
122 CHAN2G(9, 2452, 0),
123 CHAN2G(10, 2457, 0),
124 CHAN2G(11, 2462, 0),
125 CHAN2G(12, 2467, 0),
126 CHAN2G(13, 2472, 0),
127 CHAN2G(14, 2484, 0),
128};
129
130#define RATETAB_ENT(_rate, _hw_value, _flags) { \
131 .bitrate = (_rate), \
132 .hw_value = (_hw_value), \
133 .flags = (_flags), \
134}
135
8d48b5ba 136static struct ieee80211_rate ieee80211_bitrates[] = {
c5c77ba1
JK
137 RATETAB_ENT(10, 0, 0),
138 RATETAB_ENT(20, 1, 0),
139 RATETAB_ENT(55, 2, 0),
140 RATETAB_ENT(110, 3, 0),
141 RATETAB_ENT(60, 9, 0),
142 RATETAB_ENT(90, 6, 0),
143 RATETAB_ENT(120, 7, 0),
144 RATETAB_ENT(180, 8, 0),
145 RATETAB_ENT(240, 9, 0),
146 RATETAB_ENT(360, 10, 0),
147 RATETAB_ENT(480, 11, 0),
148 RATETAB_ENT(540, 12, 0),
149};
150
c5c77ba1
JK
151struct p2p_mgmt_data {
152 int size;
153 u8 *buff;
154};
155
0bd8274f 156static u8 wlan_channel = INVALID_CHANNEL;
1608c403 157static u8 curr_channel;
881eb5d8 158static u8 p2p_oui[] = {0x50, 0x6f, 0x9A, 0x09};
583d972c 159static u8 p2p_local_random = 0x01;
d38f5ba4 160static u8 p2p_recv_random;
8668594a 161static u8 p2p_vendor_spec[] = {0xdd, 0x05, 0x00, 0x08, 0x40, 0x03};
a25d5186 162static bool wilc_ie;
c5c77ba1
JK
163
164static struct ieee80211_supported_band WILC_WFI_band_2ghz = {
2736f476
LK
165 .channels = ieee80211_2ghz_channels,
166 .n_channels = ARRAY_SIZE(ieee80211_2ghz_channels),
8d48b5ba
LK
167 .bitrates = ieee80211_bitrates,
168 .n_bitrates = ARRAY_SIZE(ieee80211_bitrates),
c5c77ba1
JK
169};
170
171
c5c77ba1
JK
172struct add_key_params {
173 u8 key_idx;
c5c77ba1 174 bool pairwise;
c5c77ba1
JK
175 u8 *mac_addr;
176};
1608c403
AB
177static struct add_key_params g_add_gtk_key_params;
178static struct wilc_wfi_key g_key_gtk_params;
179static struct add_key_params g_add_ptk_key_params;
180static struct wilc_wfi_key g_key_ptk_params;
181static struct wilc_wfi_wep_key g_key_wep_params;
182static bool g_ptk_keys_saved;
183static bool g_gtk_keys_saved;
184static bool g_wep_keys_saved;
c5c77ba1
JK
185
186#define AGING_TIME (9 * 1000)
7e872df9 187#define during_ip_time 15000
c5c77ba1 188
d14991af 189static void clear_shadow_scan(void)
c5c77ba1 190{
c5c77ba1 191 int i;
8dfaafd6 192
c5c77ba1 193 if (op_ifcs == 0) {
4183e979 194 del_timer_sync(&hAgingTimer);
c5c77ba1 195
771fbae4 196 for (i = 0; i < last_scanned_cnt; i++) {
390b6db0
LK
197 if (last_scanned_shadow[last_scanned_cnt].ies) {
198 kfree(last_scanned_shadow[i].ies);
199 last_scanned_shadow[last_scanned_cnt].ies = NULL;
c5c77ba1
JK
200 }
201
cb64de7c
LK
202 kfree(last_scanned_shadow[i].join_params);
203 last_scanned_shadow[i].join_params = NULL;
c5c77ba1 204 }
771fbae4 205 last_scanned_cnt = 0;
c5c77ba1 206 }
c5c77ba1
JK
207}
208
6b5180a0 209static u32 get_rssi_avg(struct network_info *network_info)
c5c77ba1 210{
51e825f7 211 u8 i;
c5c77ba1 212 int rssi_v = 0;
f2050a18
LK
213 u8 num_rssi = (network_info->str_rssi.u8Full) ?
214 NUM_RSSI : (network_info->str_rssi.u8Index);
c5c77ba1
JK
215
216 for (i = 0; i < num_rssi; i++)
f2050a18 217 rssi_v += network_info->str_rssi.as8RSSI[i];
c5c77ba1
JK
218
219 rssi_v /= num_rssi;
220 return rssi_v;
221}
222
48ee7bad 223static void refresh_scan(void *user_void, u8 all, bool direct_scan)
c5c77ba1 224{
2726887c 225 struct wilc_priv *priv;
c5c77ba1
JK
226 struct wiphy *wiphy;
227 struct cfg80211_bss *bss = NULL;
228 int i;
229 int rssi = 0;
230
4375cad9 231 priv = user_void;
c5c77ba1
JK
232 wiphy = priv->dev->ieee80211_ptr->wiphy;
233
771fbae4 234 for (i = 0; i < last_scanned_cnt; i++) {
6b5180a0 235 struct network_info *network_info;
8dfaafd6 236
ce3b1b5a 237 network_info = &last_scanned_shadow[i];
c5c77ba1 238
a35d6e2d 239 if (!network_info->found || all) {
c6f5e3a6 240 s32 freq;
c5c77ba1
JK
241 struct ieee80211_channel *channel;
242
ce3b1b5a 243 if (network_info) {
57fbcce3 244 freq = ieee80211_channel_to_frequency((s32)network_info->ch, NL80211_BAND_2GHZ);
c6f5e3a6 245 channel = ieee80211_get_channel(wiphy, freq);
c5c77ba1 246
ce3b1b5a 247 rssi = get_rssi_avg(network_info);
2a3ff58a 248 if (memcmp("DIRECT-", network_info->ssid, 7) ||
48ee7bad 249 direct_scan) {
fa5e2d15
LK
250 bss = cfg80211_inform_bss(wiphy,
251 channel,
252 CFG80211_BSS_FTYPE_UNKNOWN,
38d3bb78 253 network_info->bssid,
17d2f2b3 254 network_info->tsf_hi,
fa5e2d15 255 network_info->cap_info,
4b313e91 256 network_info->beacon_period,
390b6db0
LK
257 (const u8 *)network_info->ies,
258 (size_t)network_info->ies_len,
fa5e2d15
LK
259 (s32)rssi * 100,
260 GFP_KERNEL);
c5c77ba1 261 cfg80211_put_bss(wiphy, bss);
c5c77ba1
JK
262 }
263 }
c5c77ba1
JK
264 }
265 }
c5c77ba1
JK
266}
267
12b0138b 268static void reset_shadow_found(void)
c5c77ba1 269{
c5c77ba1 270 int i;
8dfaafd6 271
771fbae4 272 for (i = 0; i < last_scanned_cnt; i++)
a35d6e2d 273 last_scanned_shadow[i].found = 0;
c5c77ba1
JK
274}
275
5e51d8ba 276static void update_scan_time(void)
c5c77ba1 277{
c5c77ba1 278 int i;
8dfaafd6 279
771fbae4 280 for (i = 0; i < last_scanned_cnt; i++)
264d70f4 281 last_scanned_shadow[i].time_scan = jiffies;
c5c77ba1
JK
282}
283
93dee8ee 284static void remove_network_from_shadow(unsigned long arg)
c5c77ba1 285{
c5c77ba1
JK
286 unsigned long now = jiffies;
287 int i, j;
288
c5c77ba1 289
771fbae4 290 for (i = 0; i < last_scanned_cnt; i++) {
264d70f4
LK
291 if (time_after(now, last_scanned_shadow[i].time_scan +
292 (unsigned long)(SCAN_RESULT_EXPIRE))) {
390b6db0
LK
293 kfree(last_scanned_shadow[i].ies);
294 last_scanned_shadow[i].ies = NULL;
c5c77ba1 295
cb64de7c 296 kfree(last_scanned_shadow[i].join_params);
c5c77ba1 297
771fbae4 298 for (j = i; (j < last_scanned_cnt - 1); j++)
f1ab117d 299 last_scanned_shadow[j] = last_scanned_shadow[j + 1];
771fbae4
LK
300
301 last_scanned_cnt--;
c5c77ba1
JK
302 }
303 }
304
771fbae4 305 if (last_scanned_cnt != 0) {
9eb06643
GKH
306 hAgingTimer.data = arg;
307 mod_timer(&hAgingTimer, jiffies + msecs_to_jiffies(AGING_TIME));
9eb06643 308 }
c5c77ba1
JK
309}
310
93dee8ee 311static void clear_duringIP(unsigned long arg)
c5c77ba1 312{
0e1af73d 313 wilc_optaining_ip = false;
c5c77ba1 314}
c5c77ba1 315
6b5180a0 316static int is_network_in_shadow(struct network_info *pstrNetworkInfo,
157814f0 317 void *user_void)
c5c77ba1 318{
a74cc6b8 319 int state = -1;
c5c77ba1
JK
320 int i;
321
771fbae4 322 if (last_scanned_cnt == 0) {
157814f0 323 hAgingTimer.data = (unsigned long)user_void;
9eb06643 324 mod_timer(&hAgingTimer, jiffies + msecs_to_jiffies(AGING_TIME));
c5c77ba1
JK
325 state = -1;
326 } else {
771fbae4 327 for (i = 0; i < last_scanned_cnt; i++) {
38d3bb78
LK
328 if (memcmp(last_scanned_shadow[i].bssid,
329 pstrNetworkInfo->bssid, 6) == 0) {
c5c77ba1
JK
330 state = i;
331 break;
332 }
333 }
334 }
335 return state;
336}
337
6b5180a0 338static void add_network_to_shadow(struct network_info *pstrNetworkInfo,
5c4cf0dd 339 void *user_void, void *pJoinParams)
c5c77ba1 340{
5c4cf0dd 341 int ap_found = is_network_in_shadow(pstrNetworkInfo, user_void);
fbc2fe16 342 u32 ap_index = 0;
51e825f7 343 u8 rssi_index = 0;
c5c77ba1 344
64d3546a 345 if (last_scanned_cnt >= MAX_NUM_SCANNED_NETWORKS_SHADOW)
c5c77ba1 346 return;
64d3546a 347
c5c77ba1 348 if (ap_found == -1) {
771fbae4
LK
349 ap_index = last_scanned_cnt;
350 last_scanned_cnt++;
c5c77ba1
JK
351 } else {
352 ap_index = ap_found;
353 }
f2050a18
LK
354 rssi_index = last_scanned_shadow[ap_index].str_rssi.u8Index;
355 last_scanned_shadow[ap_index].str_rssi.as8RSSI[rssi_index++] = pstrNetworkInfo->rssi;
c5c77ba1
JK
356 if (rssi_index == NUM_RSSI) {
357 rssi_index = 0;
f2050a18 358 last_scanned_shadow[ap_index].str_rssi.u8Full = 1;
c5c77ba1 359 }
f2050a18 360 last_scanned_shadow[ap_index].str_rssi.u8Index = rssi_index;
5c23a291 361 last_scanned_shadow[ap_index].rssi = pstrNetworkInfo->rssi;
fa5e2d15 362 last_scanned_shadow[ap_index].cap_info = pstrNetworkInfo->cap_info;
a36e89e9 363 last_scanned_shadow[ap_index].ssid_len = pstrNetworkInfo->ssid_len;
2a3ff58a 364 memcpy(last_scanned_shadow[ap_index].ssid,
a36e89e9 365 pstrNetworkInfo->ssid, pstrNetworkInfo->ssid_len);
38d3bb78
LK
366 memcpy(last_scanned_shadow[ap_index].bssid,
367 pstrNetworkInfo->bssid, ETH_ALEN);
4b313e91 368 last_scanned_shadow[ap_index].beacon_period = pstrNetworkInfo->beacon_period;
df340fdf 369 last_scanned_shadow[ap_index].dtim_period = pstrNetworkInfo->dtim_period;
405a8c78 370 last_scanned_shadow[ap_index].ch = pstrNetworkInfo->ch;
390b6db0 371 last_scanned_shadow[ap_index].ies_len = pstrNetworkInfo->ies_len;
17d2f2b3 372 last_scanned_shadow[ap_index].tsf_hi = pstrNetworkInfo->tsf_hi;
c5c77ba1 373 if (ap_found != -1)
390b6db0
LK
374 kfree(last_scanned_shadow[ap_index].ies);
375 last_scanned_shadow[ap_index].ies = kmalloc(pstrNetworkInfo->ies_len,
376 GFP_KERNEL);
377 memcpy(last_scanned_shadow[ap_index].ies,
378 pstrNetworkInfo->ies, pstrNetworkInfo->ies_len);
264d70f4
LK
379 last_scanned_shadow[ap_index].time_scan = jiffies;
380 last_scanned_shadow[ap_index].time_scan_cached = jiffies;
a35d6e2d 381 last_scanned_shadow[ap_index].found = 1;
c5c77ba1 382 if (ap_found != -1)
cb64de7c
LK
383 kfree(last_scanned_shadow[ap_index].join_params);
384 last_scanned_shadow[ap_index].join_params = pJoinParams;
c5c77ba1
JK
385}
386
1a4c8ce7 387static void CfgScanResult(enum scan_event scan_event,
6b5180a0 388 struct network_info *network_info,
30cd10c4 389 void *user_void,
bdd3460f 390 void *join_params)
c5c77ba1 391{
2726887c 392 struct wilc_priv *priv;
c5c77ba1 393 struct wiphy *wiphy;
fb4ec9ca 394 s32 s32Freq;
c5c77ba1 395 struct ieee80211_channel *channel;
c5c77ba1
JK
396 struct cfg80211_bss *bss = NULL;
397
4375cad9 398 priv = user_void;
7e4e87d3 399 if (priv->bCfgScanning) {
1a4c8ce7 400 if (scan_event == SCAN_EVENT_NETWORK_FOUND) {
c5c77ba1 401 wiphy = priv->dev->ieee80211_ptr->wiphy;
7ae43363
LK
402
403 if (!wiphy)
404 return;
405
0551a72e 406 if (wiphy->signal_type == CFG80211_SIGNAL_TYPE_UNSPEC &&
5c23a291
LK
407 (((s32)network_info->rssi * 100) < 0 ||
408 ((s32)network_info->rssi * 100) > 100))
24db713f 409 return;
c5c77ba1 410
0551a72e 411 if (network_info) {
57fbcce3 412 s32Freq = ieee80211_channel_to_frequency((s32)network_info->ch, NL80211_BAND_2GHZ);
c5c77ba1
JK
413 channel = ieee80211_get_channel(wiphy, s32Freq);
414
7ae43363
LK
415 if (!channel)
416 return;
c5c77ba1 417
d4020763 418 if (network_info->new_network) {
a89f7c55 419 if (priv->u32RcvdChCount < MAX_NUM_SCANNED_NETWORKS) {
c5c77ba1
JK
420 priv->u32RcvdChCount++;
421
bdd3460f 422 add_network_to_shadow(network_info, priv, join_params);
c5c77ba1 423
2a3ff58a 424 if (!(memcmp("DIRECT-", network_info->ssid, 7))) {
fa5e2d15
LK
425 bss = cfg80211_inform_bss(wiphy,
426 channel,
427 CFG80211_BSS_FTYPE_UNKNOWN,
38d3bb78 428 network_info->bssid,
17d2f2b3 429 network_info->tsf_hi,
fa5e2d15 430 network_info->cap_info,
4b313e91 431 network_info->beacon_period,
390b6db0
LK
432 (const u8 *)network_info->ies,
433 (size_t)network_info->ies_len,
fa5e2d15
LK
434 (s32)network_info->rssi * 100,
435 GFP_KERNEL);
c5c77ba1 436 cfg80211_put_bss(wiphy, bss);
c5c77ba1 437 }
c5c77ba1
JK
438 }
439 } else {
4e4467fd 440 u32 i;
a89f7c55 441
c5c77ba1 442 for (i = 0; i < priv->u32RcvdChCount; i++) {
38d3bb78 443 if (memcmp(last_scanned_shadow[i].bssid, network_info->bssid, 6) == 0) {
5c23a291 444 last_scanned_shadow[i].rssi = network_info->rssi;
264d70f4 445 last_scanned_shadow[i].time_scan = jiffies;
c5c77ba1
JK
446 break;
447 }
448 }
449 }
450 }
1a4c8ce7 451 } else if (scan_event == SCAN_EVENT_DONE) {
72ed4dc7 452 refresh_scan(priv, 1, false);
c5c77ba1 453
08662097 454 mutex_lock(&priv->scan_req_lock);
c5c77ba1 455
369a1d3b 456 if (priv->pstrScanReq) {
1d76250b
AS
457 struct cfg80211_scan_info info = {
458 .aborted = false,
459 };
460
461 cfg80211_scan_done(priv->pstrScanReq, &info);
c5c77ba1 462 priv->u32RcvdChCount = 0;
72ed4dc7 463 priv->bCfgScanning = false;
b1413b60 464 priv->pstrScanReq = NULL;
c5c77ba1 465 }
08662097 466 mutex_unlock(&priv->scan_req_lock);
1a4c8ce7 467 } else if (scan_event == SCAN_EVENT_ABORTED) {
08662097 468 mutex_lock(&priv->scan_req_lock);
c5c77ba1 469
369a1d3b 470 if (priv->pstrScanReq) {
1d76250b
AS
471 struct cfg80211_scan_info info = {
472 .aborted = false,
473 };
474
5e51d8ba 475 update_scan_time();
72ed4dc7 476 refresh_scan(priv, 1, false);
c5c77ba1 477
1d76250b 478 cfg80211_scan_done(priv->pstrScanReq, &info);
72ed4dc7 479 priv->bCfgScanning = false;
b1413b60 480 priv->pstrScanReq = NULL;
c5c77ba1 481 }
08662097 482 mutex_unlock(&priv->scan_req_lock);
c5c77ba1
JK
483 }
484 }
c5c77ba1
JK
485}
486
0e1af73d 487int wilc_connecting;
c5c77ba1 488
ed3f0379 489static void CfgConnectResult(enum conn_event enuConnDisconnEvent,
3b0437e1 490 struct connect_info *pstrConnectInfo,
63d03e47 491 u8 u8MacStatus,
bb76df5a 492 struct disconnect_info *pstrDisconnectNotifInfo,
c5c77ba1
JK
493 void *pUserVoid)
494{
2726887c 495 struct wilc_priv *priv;
c5c77ba1 496 struct net_device *dev;
441dc609 497 struct host_if_drv *pstrWFIDrv;
63d03e47 498 u8 NullBssid[ETH_ALEN] = {0};
c1ec2c12 499 struct wilc *wl;
a4cac481 500 struct wilc_vif *vif;
8dfaafd6 501
0e1af73d 502 wilc_connecting = 0;
c5c77ba1 503
4375cad9 504 priv = pUserVoid;
c5c77ba1 505 dev = priv->dev;
a4cac481
GL
506 vif = netdev_priv(dev);
507 wl = vif->wilc;
48b28df9 508 pstrWFIDrv = (struct host_if_drv *)priv->hif_drv;
c5c77ba1
JK
509
510 if (enuConnDisconnEvent == CONN_DISCONN_EVENT_CONN_RESP) {
baba7c74 511 u16 u16ConnectStatus;
c5c77ba1 512
134b4cf2 513 u16ConnectStatus = pstrConnectInfo->status;
c5c77ba1 514
c5c77ba1 515 if ((u8MacStatus == MAC_DISCONNECTED) &&
134b4cf2 516 (pstrConnectInfo->status == SUCCESSFUL_STATUSCODE)) {
c5c77ba1 517 u16ConnectStatus = WLAN_STATUS_UNSPECIFIED_FAILURE;
ba615f1e
GL
518 wilc_wlan_set_bssid(priv->dev, NullBssid,
519 STATION_MODE);
e554a305 520 eth_zero_addr(wilc_connected_ssid);
c5c77ba1 521
ab16ec0b 522 if (!pstrWFIDrv->p2p_connect)
0bd8274f 523 wlan_channel = INVALID_CHANNEL;
c5c77ba1 524
06fb9336 525 netdev_err(dev, "Unspecified failure\n");
c5c77ba1
JK
526 }
527
528 if (u16ConnectStatus == WLAN_STATUS_SUCCESS) {
72ed4dc7 529 bool bNeedScanRefresh = false;
4e4467fd 530 u32 i;
c5c77ba1 531
d4a24e08 532 memcpy(priv->au8AssociatedBss, pstrConnectInfo->bssid, ETH_ALEN);
c5c77ba1 533
c5c77ba1 534
771fbae4 535 for (i = 0; i < last_scanned_cnt; i++) {
38d3bb78 536 if (memcmp(last_scanned_shadow[i].bssid,
d4a24e08 537 pstrConnectInfo->bssid,
38d3bb78 538 ETH_ALEN) == 0) {
c5c77ba1
JK
539 unsigned long now = jiffies;
540
541 if (time_after(now,
264d70f4
LK
542 last_scanned_shadow[i].time_scan_cached +
543 (unsigned long)(nl80211_SCAN_RESULT_EXPIRE - (1 * HZ))))
72ed4dc7 544 bNeedScanRefresh = true;
c5c77ba1
JK
545
546 break;
547 }
548 }
549
a89f7c55 550 if (bNeedScanRefresh)
72ed4dc7 551 refresh_scan(priv, 1, true);
c5c77ba1
JK
552 }
553
d4a24e08 554 cfg80211_connect_result(dev, pstrConnectInfo->bssid,
4607f9cc 555 pstrConnectInfo->req_ies, pstrConnectInfo->req_ies_len,
3e7477c2 556 pstrConnectInfo->resp_ies, pstrConnectInfo->resp_ies_len,
a89f7c55 557 u16ConnectStatus, GFP_KERNEL);
c5c77ba1 558 } else if (enuConnDisconnEvent == CONN_DISCONN_EVENT_DISCONN_NOTIF) {
0e1af73d 559 wilc_optaining_ip = false;
583d972c 560 p2p_local_random = 0x01;
b84a3ac4 561 p2p_recv_random = 0x00;
a25d5186 562 wilc_ie = false;
bcf02653 563 eth_zero_addr(priv->au8AssociatedBss);
ba615f1e 564 wilc_wlan_set_bssid(priv->dev, NullBssid, STATION_MODE);
e554a305 565 eth_zero_addr(wilc_connected_ssid);
c5c77ba1 566
ab16ec0b 567 if (!pstrWFIDrv->p2p_connect)
0bd8274f 568 wlan_channel = INVALID_CHANNEL;
d5e27e8b 569 if ((pstrWFIDrv->IFC_UP) && (dev == wl->vif[1]->ndev))
90f209da 570 pstrDisconnectNotifInfo->reason = 3;
d5e27e8b 571 else if ((!pstrWFIDrv->IFC_UP) && (dev == wl->vif[1]->ndev))
90f209da 572 pstrDisconnectNotifInfo->reason = 1;
d5e27e8b 573
90f209da 574 cfg80211_disconnected(dev, pstrDisconnectNotifInfo->reason, pstrDisconnectNotifInfo->ie,
e26bb71d
SM
575 pstrDisconnectNotifInfo->ie_len, false,
576 GFP_KERNEL);
c5c77ba1 577 }
c5c77ba1
JK
578}
579
80785a9a
CL
580static int set_channel(struct wiphy *wiphy,
581 struct cfg80211_chan_def *chandef)
c5c77ba1 582{
4e4467fd 583 u32 channelnum = 0;
2726887c 584 struct wilc_priv *priv;
dd739ea5 585 int result = 0;
cf60106b 586 struct wilc_vif *vif;
8dfaafd6 587
c5c77ba1 588 priv = wiphy_priv(wiphy);
cf60106b 589 vif = netdev_priv(priv->dev);
c5c77ba1 590
c5c77ba1 591 channelnum = ieee80211_frequency_to_channel(chandef->chan->center_freq);
c5c77ba1 592
866a2c24 593 curr_channel = channelnum;
fbf5379b 594 result = wilc_set_mac_chnl_num(vif, channelnum);
c5c77ba1 595
dd739ea5 596 if (result != 0)
06fb9336 597 netdev_err(priv->dev, "Error in setting channel\n");
c5c77ba1 598
dd739ea5 599 return result;
c5c77ba1
JK
600}
601
0e30d06d 602static int scan(struct wiphy *wiphy, struct cfg80211_scan_request *request)
c5c77ba1 603{
2726887c 604 struct wilc_priv *priv;
4e4467fd 605 u32 i;
e6e12661 606 s32 s32Error = 0;
63d03e47 607 u8 au8ScanChanList[MAX_NUM_SCANNED_NETWORKS];
607db447 608 struct hidden_network strHiddenNetwork;
cf60106b 609 struct wilc_vif *vif;
c5c77ba1
JK
610
611 priv = wiphy_priv(wiphy);
cf60106b 612 vif = netdev_priv(priv->dev);
c5c77ba1 613
c5c77ba1
JK
614 priv->pstrScanReq = request;
615
616 priv->u32RcvdChCount = 0;
617
12b0138b 618 reset_shadow_found();
c5c77ba1 619
72ed4dc7 620 priv->bCfgScanning = true;
a89f7c55 621 if (request->n_channels <= MAX_NUM_SCANNED_NETWORKS) {
64d3546a 622 for (i = 0; i < request->n_channels; i++)
63d03e47 623 au8ScanChanList[i] = (u8)ieee80211_frequency_to_channel(request->channels[i]->center_freq);
c5c77ba1
JK
624
625 if (request->n_ssids >= 1) {
8459af6a
JR
626 strHiddenNetwork.net_info =
627 kmalloc_array(request->n_ssids,
628 sizeof(struct hidden_network),
629 GFP_KERNEL);
396fa30e
LK
630 if (!strHiddenNetwork.net_info)
631 return -ENOMEM;
40e05e86 632 strHiddenNetwork.n_ssids = request->n_ssids;
c5c77ba1
JK
633
634
c5c77ba1 635 for (i = 0; i < request->n_ssids; i++) {
4562d224 636 if (request->ssids[i].ssid_len != 0) {
245a1865
CL
637 strHiddenNetwork.net_info[i].ssid = kmalloc(request->ssids[i].ssid_len, GFP_KERNEL);
638 memcpy(strHiddenNetwork.net_info[i].ssid, request->ssids[i].ssid, request->ssids[i].ssid_len);
639 strHiddenNetwork.net_info[i].ssid_len = request->ssids[i].ssid_len;
c5c77ba1 640 } else {
40e05e86 641 strHiddenNetwork.n_ssids -= 1;
c5c77ba1
JK
642 }
643 }
fbf5379b
GL
644 s32Error = wilc_scan(vif, USER_SCAN, ACTIVE_SCAN,
645 au8ScanChanList,
646 request->n_channels,
647 (const u8 *)request->ie,
648 request->ie_len, CfgScanResult,
649 (void *)priv, &strHiddenNetwork);
c5c77ba1 650 } else {
fbf5379b
GL
651 s32Error = wilc_scan(vif, USER_SCAN, ACTIVE_SCAN,
652 au8ScanChanList,
653 request->n_channels,
654 (const u8 *)request->ie,
655 request->ie_len, CfgScanResult,
656 (void *)priv, NULL);
c5c77ba1 657 }
c5c77ba1 658 } else {
06fb9336 659 netdev_err(priv->dev, "Requested scanned channels over\n");
c5c77ba1
JK
660 }
661
64d3546a 662 if (s32Error != 0)
c5c77ba1 663 s32Error = -EBUSY;
c5c77ba1
JK
664
665 return s32Error;
666}
667
4ffbcdb6
CL
668static int connect(struct wiphy *wiphy, struct net_device *dev,
669 struct cfg80211_connect_params *sme)
c5c77ba1 670{
e6e12661 671 s32 s32Error = 0;
4e4467fd 672 u32 i;
63d03e47 673 u8 u8security = NO_ENCRYPT;
841dfc42 674 enum AUTHTYPE tenuAuth_type = ANY;
c5c77ba1 675
2726887c 676 struct wilc_priv *priv;
441dc609 677 struct host_if_drv *pstrWFIDrv;
6b5180a0 678 struct network_info *pstrNetworkInfo = NULL;
cf60106b 679 struct wilc_vif *vif;
c5c77ba1 680
0e1af73d 681 wilc_connecting = 1;
c5c77ba1 682 priv = wiphy_priv(wiphy);
cf60106b 683 vif = netdev_priv(priv->dev);
48b28df9 684 pstrWFIDrv = (struct host_if_drv *)priv->hif_drv;
c5c77ba1 685
64d3546a 686 if (!(strncmp(sme->ssid, "DIRECT-", 7)))
ab16ec0b 687 pstrWFIDrv->p2p_connect = 1;
64d3546a 688 else
ab16ec0b 689 pstrWFIDrv->p2p_connect = 0;
c5c77ba1 690
771fbae4 691 for (i = 0; i < last_scanned_cnt; i++) {
a36e89e9 692 if ((sme->ssid_len == last_scanned_shadow[i].ssid_len) &&
2a3ff58a 693 memcmp(last_scanned_shadow[i].ssid,
f1ab117d
LK
694 sme->ssid,
695 sme->ssid_len) == 0) {
64d3546a 696 if (!sme->bssid)
c5c77ba1 697 break;
64d3546a 698 else
38d3bb78 699 if (memcmp(last_scanned_shadow[i].bssid,
f1ab117d 700 sme->bssid,
64d3546a 701 ETH_ALEN) == 0)
c5c77ba1 702 break;
c5c77ba1
JK
703 }
704 }
705
771fbae4 706 if (i < last_scanned_cnt) {
f1ab117d 707 pstrNetworkInfo = &last_scanned_shadow[i];
c5c77ba1
JK
708 } else {
709 s32Error = -ENOENT;
430e640d
GL
710 wilc_connecting = 0;
711 return s32Error;
c5c77ba1
JK
712 }
713
2cc46837
CL
714 memset(priv->WILC_WFI_wep_key, 0, sizeof(priv->WILC_WFI_wep_key));
715 memset(priv->WILC_WFI_wep_key_len, 0, sizeof(priv->WILC_WFI_wep_key_len));
c5c77ba1 716
c5c77ba1 717 if (sme->crypto.cipher_group != NO_ENCRYPT) {
c5c77ba1 718 if (sme->crypto.cipher_group == WLAN_CIPHER_SUITE_WEP40) {
c5c77ba1 719 u8security = ENCRYPT_ENABLED | WEP;
c5c77ba1 720
c5c77ba1 721 priv->WILC_WFI_wep_key_len[sme->key_idx] = sme->key_len;
d00d2ba3 722 memcpy(priv->WILC_WFI_wep_key[sme->key_idx], sme->key, sme->key_len);
c5c77ba1 723
c5c77ba1 724 g_key_wep_params.key_len = sme->key_len;
f3052587 725 g_key_wep_params.key = kmalloc(sme->key_len, GFP_KERNEL);
c5c77ba1
JK
726 memcpy(g_key_wep_params.key, sme->key, sme->key_len);
727 g_key_wep_params.key_idx = sme->key_idx;
72ed4dc7 728 g_wep_keys_saved = true;
c5c77ba1 729
fbf5379b
GL
730 wilc_set_wep_default_keyid(vif, sme->key_idx);
731 wilc_add_wep_key_bss_sta(vif, sme->key, sme->key_len,
732 sme->key_idx);
c5c77ba1 733 } else if (sme->crypto.cipher_group == WLAN_CIPHER_SUITE_WEP104) {
c5c77ba1 734 u8security = ENCRYPT_ENABLED | WEP | WEP_EXTENDED;
c5c77ba1 735
c5c77ba1 736 priv->WILC_WFI_wep_key_len[sme->key_idx] = sme->key_len;
d00d2ba3 737 memcpy(priv->WILC_WFI_wep_key[sme->key_idx], sme->key, sme->key_len);
c5c77ba1 738
c5c77ba1 739 g_key_wep_params.key_len = sme->key_len;
f3052587 740 g_key_wep_params.key = kmalloc(sme->key_len, GFP_KERNEL);
c5c77ba1
JK
741 memcpy(g_key_wep_params.key, sme->key, sme->key_len);
742 g_key_wep_params.key_idx = sme->key_idx;
72ed4dc7 743 g_wep_keys_saved = true;
c5c77ba1 744
fbf5379b
GL
745 wilc_set_wep_default_keyid(vif, sme->key_idx);
746 wilc_add_wep_key_bss_sta(vif, sme->key, sme->key_len,
747 sme->key_idx);
c5c77ba1 748 } else if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_2) {
d5e27e8b 749 if (sme->crypto.cipher_group == WLAN_CIPHER_SUITE_TKIP)
c5c77ba1 750 u8security = ENCRYPT_ENABLED | WPA2 | TKIP;
d5e27e8b 751 else
c5c77ba1 752 u8security = ENCRYPT_ENABLED | WPA2 | AES;
c5c77ba1 753 } else if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_1) {
d5e27e8b 754 if (sme->crypto.cipher_group == WLAN_CIPHER_SUITE_TKIP)
c5c77ba1 755 u8security = ENCRYPT_ENABLED | WPA | TKIP;
d5e27e8b 756 else
c5c77ba1 757 u8security = ENCRYPT_ENABLED | WPA | AES;
c5c77ba1
JK
758 } else {
759 s32Error = -ENOTSUPP;
06fb9336 760 netdev_err(dev, "Not supported cipher\n");
430e640d
GL
761 wilc_connecting = 0;
762 return s32Error;
c5c77ba1 763 }
c5c77ba1
JK
764 }
765
c5c77ba1
JK
766 if ((sme->crypto.wpa_versions & NL80211_WPA_VERSION_1)
767 || (sme->crypto.wpa_versions & NL80211_WPA_VERSION_2)) {
768 for (i = 0; i < sme->crypto.n_ciphers_pairwise; i++) {
d5e27e8b 769 if (sme->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_TKIP)
c5c77ba1 770 u8security = u8security | TKIP;
d5e27e8b 771 else
c5c77ba1 772 u8security = u8security | AES;
c5c77ba1
JK
773 }
774 }
775
c5c77ba1
JK
776 switch (sme->auth_type) {
777 case NL80211_AUTHTYPE_OPEN_SYSTEM:
c5c77ba1
JK
778 tenuAuth_type = OPEN_SYSTEM;
779 break;
780
781 case NL80211_AUTHTYPE_SHARED_KEY:
782 tenuAuth_type = SHARED_KEY;
c5c77ba1
JK
783 break;
784
785 default:
40bbaac7 786 break;
c5c77ba1
JK
787 }
788
c5c77ba1
JK
789 if (sme->crypto.n_akm_suites) {
790 switch (sme->crypto.akm_suites[0]) {
791 case WLAN_AKM_SUITE_8021X:
792 tenuAuth_type = IEEE8021;
793 break;
794
795 default:
796 break;
797 }
798 }
799
405a8c78 800 curr_channel = pstrNetworkInfo->ch;
c5c77ba1 801
ab16ec0b 802 if (!pstrWFIDrv->p2p_connect)
405a8c78 803 wlan_channel = pstrNetworkInfo->ch;
c5c77ba1 804
38d3bb78 805 wilc_wlan_set_bssid(dev, pstrNetworkInfo->bssid, STATION_MODE);
c5c77ba1 806
38d3bb78 807 s32Error = wilc_set_join_req(vif, pstrNetworkInfo->bssid, sme->ssid,
fbf5379b
GL
808 sme->ssid_len, sme->ie, sme->ie_len,
809 CfgConnectResult, (void *)priv,
810 u8security, tenuAuth_type,
405a8c78 811 pstrNetworkInfo->ch,
cb64de7c 812 pstrNetworkInfo->join_params);
e6e12661 813 if (s32Error != 0) {
06fb9336 814 netdev_err(dev, "wilc_set_join_req(): Error\n");
c5c77ba1 815 s32Error = -ENOENT;
430e640d
GL
816 wilc_connecting = 0;
817 return s32Error;
c5c77ba1
JK
818 }
819
c5c77ba1
JK
820 return s32Error;
821}
822
b027cde9 823static int disconnect(struct wiphy *wiphy, struct net_device *dev, u16 reason_code)
c5c77ba1 824{
e6e12661 825 s32 s32Error = 0;
2726887c 826 struct wilc_priv *priv;
441dc609 827 struct host_if_drv *pstrWFIDrv;
cf60106b 828 struct wilc_vif *vif;
8006109b 829 struct wilc *wilc;
51e825f7 830 u8 NullBssid[ETH_ALEN] = {0};
8dfaafd6 831
0e1af73d 832 wilc_connecting = 0;
c5c77ba1 833 priv = wiphy_priv(wiphy);
cf60106b 834 vif = netdev_priv(priv->dev);
8006109b
LK
835 wilc = vif->wilc;
836
837 if (!wilc)
838 return -EIO;
839
840 if (wilc->close) {
841 /* already disconnected done */
842 cfg80211_disconnected(dev, 0, NULL, 0, true, GFP_KERNEL);
843 return 0;
844 }
c5c77ba1 845
48b28df9 846 pstrWFIDrv = (struct host_if_drv *)priv->hif_drv;
ab16ec0b 847 if (!pstrWFIDrv->p2p_connect)
0bd8274f 848 wlan_channel = INVALID_CHANNEL;
ba615f1e 849 wilc_wlan_set_bssid(priv->dev, NullBssid, STATION_MODE);
c5c77ba1 850
583d972c 851 p2p_local_random = 0x01;
b84a3ac4 852 p2p_recv_random = 0x00;
a25d5186 853 wilc_ie = false;
1229b1ab 854 pstrWFIDrv->p2p_timeout = 0;
c5c77ba1 855
fbf5379b 856 s32Error = wilc_disconnect(vif, reason_code);
e6e12661 857 if (s32Error != 0) {
06fb9336 858 netdev_err(priv->dev, "Error in disconnecting\n");
c5c77ba1
JK
859 s32Error = -EINVAL;
860 }
861
862 return s32Error;
863}
864
953d417a
CL
865static int add_key(struct wiphy *wiphy, struct net_device *netdev, u8 key_index,
866 bool pairwise,
867 const u8 *mac_addr, struct key_params *params)
c5c77ba1
JK
868
869{
e6e12661 870 s32 s32Error = 0, KeyLen = params->key_len;
2726887c 871 struct wilc_priv *priv;
057d1e97
AB
872 const u8 *pu8RxMic = NULL;
873 const u8 *pu8TxMic = NULL;
63d03e47 874 u8 u8mode = NO_ENCRYPT;
63d03e47
GKH
875 u8 u8gmode = NO_ENCRYPT;
876 u8 u8pmode = NO_ENCRYPT;
841dfc42 877 enum AUTHTYPE tenuAuth_type = ANY;
76469200 878 struct wilc *wl;
a4cac481 879 struct wilc_vif *vif;
c5c77ba1
JK
880
881 priv = wiphy_priv(wiphy);
a4cac481
GL
882 vif = netdev_priv(netdev);
883 wl = vif->wilc;
c5c77ba1 884
c5c77ba1
JK
885 switch (params->cipher) {
886 case WLAN_CIPHER_SUITE_WEP40:
887 case WLAN_CIPHER_SUITE_WEP104:
c5c77ba1 888 if (priv->wdev->iftype == NL80211_IFTYPE_AP) {
c5c77ba1 889 priv->WILC_WFI_wep_key_len[key_index] = params->key_len;
d00d2ba3 890 memcpy(priv->WILC_WFI_wep_key[key_index], params->key, params->key_len);
c5c77ba1 891
c5c77ba1
JK
892 tenuAuth_type = OPEN_SYSTEM;
893
894 if (params->cipher == WLAN_CIPHER_SUITE_WEP40)
895 u8mode = ENCRYPT_ENABLED | WEP;
896 else
897 u8mode = ENCRYPT_ENABLED | WEP | WEP_EXTENDED;
898
fbf5379b
GL
899 wilc_add_wep_key_bss_ap(vif, params->key,
900 params->key_len, key_index,
901 u8mode, tenuAuth_type);
c5c77ba1
JK
902 break;
903 }
1a646e7e 904 if (memcmp(params->key, priv->WILC_WFI_wep_key[key_index], params->key_len)) {
c5c77ba1 905 priv->WILC_WFI_wep_key_len[key_index] = params->key_len;
d00d2ba3 906 memcpy(priv->WILC_WFI_wep_key[key_index], params->key, params->key_len);
c5c77ba1 907
fbf5379b
GL
908 wilc_add_wep_key_bss_sta(vif, params->key,
909 params->key_len, key_index);
c5c77ba1
JK
910 }
911
912 break;
913
914 case WLAN_CIPHER_SUITE_TKIP:
915 case WLAN_CIPHER_SUITE_CCMP:
c5c77ba1 916 if (priv->wdev->iftype == NL80211_IFTYPE_AP || priv->wdev->iftype == NL80211_IFTYPE_P2P_GO) {
369a1d3b 917 if (!priv->wilc_gtk[key_index]) {
f3052587 918 priv->wilc_gtk[key_index] = kmalloc(sizeof(struct wilc_wfi_key), GFP_KERNEL);
b1413b60
GKH
919 priv->wilc_gtk[key_index]->key = NULL;
920 priv->wilc_gtk[key_index]->seq = NULL;
c5c77ba1 921 }
369a1d3b 922 if (!priv->wilc_ptk[key_index]) {
f3052587 923 priv->wilc_ptk[key_index] = kmalloc(sizeof(struct wilc_wfi_key), GFP_KERNEL);
b1413b60
GKH
924 priv->wilc_ptk[key_index]->key = NULL;
925 priv->wilc_ptk[key_index]->seq = NULL;
c5c77ba1
JK
926 }
927
928
929
1913221c 930 if (!pairwise) {
c5c77ba1
JK
931 if (params->cipher == WLAN_CIPHER_SUITE_TKIP)
932 u8gmode = ENCRYPT_ENABLED | WPA | TKIP;
933 else
934 u8gmode = ENCRYPT_ENABLED | WPA2 | AES;
935
936 priv->wilc_groupkey = u8gmode;
937
938 if (params->key_len > 16 && params->cipher == WLAN_CIPHER_SUITE_TKIP) {
c5c77ba1
JK
939 pu8TxMic = params->key + 24;
940 pu8RxMic = params->key + 16;
941 KeyLen = params->key_len - 16;
942 }
cccfc39e 943 kfree(priv->wilc_gtk[key_index]->key);
c5c77ba1 944
f3052587 945 priv->wilc_gtk[key_index]->key = kmalloc(params->key_len, GFP_KERNEL);
d00d2ba3 946 memcpy(priv->wilc_gtk[key_index]->key, params->key, params->key_len);
cccfc39e 947 kfree(priv->wilc_gtk[key_index]->seq);
c5c77ba1
JK
948
949 if ((params->seq_len) > 0) {
f3052587 950 priv->wilc_gtk[key_index]->seq = kmalloc(params->seq_len, GFP_KERNEL);
d00d2ba3 951 memcpy(priv->wilc_gtk[key_index]->seq, params->seq, params->seq_len);
c5c77ba1
JK
952 }
953
954 priv->wilc_gtk[key_index]->cipher = params->cipher;
955 priv->wilc_gtk[key_index]->key_len = params->key_len;
956 priv->wilc_gtk[key_index]->seq_len = params->seq_len;
957
fbf5379b
GL
958 wilc_add_rx_gtk(vif, params->key, KeyLen,
959 key_index, params->seq_len,
960 params->seq, pu8RxMic,
961 pu8TxMic, AP_MODE, u8gmode);
c5c77ba1
JK
962
963 } else {
c5c77ba1
JK
964 if (params->cipher == WLAN_CIPHER_SUITE_TKIP)
965 u8pmode = ENCRYPT_ENABLED | WPA | TKIP;
966 else
967 u8pmode = priv->wilc_groupkey | AES;
968
969
970 if (params->key_len > 16 && params->cipher == WLAN_CIPHER_SUITE_TKIP) {
c5c77ba1
JK
971 pu8TxMic = params->key + 24;
972 pu8RxMic = params->key + 16;
973 KeyLen = params->key_len - 16;
974 }
975
cccfc39e 976 kfree(priv->wilc_ptk[key_index]->key);
c5c77ba1 977
f3052587 978 priv->wilc_ptk[key_index]->key = kmalloc(params->key_len, GFP_KERNEL);
c5c77ba1 979
cccfc39e 980 kfree(priv->wilc_ptk[key_index]->seq);
c5c77ba1
JK
981
982 if ((params->seq_len) > 0)
f3052587 983 priv->wilc_ptk[key_index]->seq = kmalloc(params->seq_len, GFP_KERNEL);
c5c77ba1 984
d00d2ba3 985 memcpy(priv->wilc_ptk[key_index]->key, params->key, params->key_len);
c5c77ba1
JK
986
987 if ((params->seq_len) > 0)
d00d2ba3 988 memcpy(priv->wilc_ptk[key_index]->seq, params->seq, params->seq_len);
c5c77ba1
JK
989
990 priv->wilc_ptk[key_index]->cipher = params->cipher;
991 priv->wilc_ptk[key_index]->key_len = params->key_len;
992 priv->wilc_ptk[key_index]->seq_len = params->seq_len;
993
fbf5379b
GL
994 wilc_add_ptk(vif, params->key, KeyLen,
995 mac_addr, pu8RxMic, pu8TxMic,
996 AP_MODE, u8pmode, key_index);
c5c77ba1
JK
997 }
998 break;
999 }
c5c77ba1
JK
1000
1001 {
1002 u8mode = 0;
1913221c 1003 if (!pairwise) {
c5c77ba1 1004 if (params->key_len > 16 && params->cipher == WLAN_CIPHER_SUITE_TKIP) {
c5c77ba1
JK
1005 pu8RxMic = params->key + 24;
1006 pu8TxMic = params->key + 16;
1007 KeyLen = params->key_len - 16;
1008 }
1009
1f435d2e 1010 if (!g_gtk_keys_saved && netdev == wl->vif[0]->ndev) {
c5c77ba1 1011 g_add_gtk_key_params.key_idx = key_index;
c5c77ba1 1012 g_add_gtk_key_params.pairwise = pairwise;
c5c77ba1
JK
1013 if (!mac_addr) {
1014 g_add_gtk_key_params.mac_addr = NULL;
1015 } else {
f3052587 1016 g_add_gtk_key_params.mac_addr = kmalloc(ETH_ALEN, GFP_KERNEL);
c5c77ba1
JK
1017 memcpy(g_add_gtk_key_params.mac_addr, mac_addr, ETH_ALEN);
1018 }
1019 g_key_gtk_params.key_len = params->key_len;
1020 g_key_gtk_params.seq_len = params->seq_len;
f3052587 1021 g_key_gtk_params.key = kmalloc(params->key_len, GFP_KERNEL);
c5c77ba1
JK
1022 memcpy(g_key_gtk_params.key, params->key, params->key_len);
1023 if (params->seq_len > 0) {
f3052587 1024 g_key_gtk_params.seq = kmalloc(params->seq_len, GFP_KERNEL);
c5c77ba1
JK
1025 memcpy(g_key_gtk_params.seq, params->seq, params->seq_len);
1026 }
1027 g_key_gtk_params.cipher = params->cipher;
72ed4dc7 1028 g_gtk_keys_saved = true;
c5c77ba1
JK
1029 }
1030
fbf5379b
GL
1031 wilc_add_rx_gtk(vif, params->key, KeyLen,
1032 key_index, params->seq_len,
1033 params->seq, pu8RxMic,
1034 pu8TxMic, STATION_MODE,
1035 u8mode);
c5c77ba1
JK
1036 } else {
1037 if (params->key_len > 16 && params->cipher == WLAN_CIPHER_SUITE_TKIP) {
c5c77ba1
JK
1038 pu8RxMic = params->key + 24;
1039 pu8TxMic = params->key + 16;
1040 KeyLen = params->key_len - 16;
1041 }
1042
1f435d2e 1043 if (!g_ptk_keys_saved && netdev == wl->vif[0]->ndev) {
c5c77ba1 1044 g_add_ptk_key_params.key_idx = key_index;
c5c77ba1 1045 g_add_ptk_key_params.pairwise = pairwise;
c5c77ba1
JK
1046 if (!mac_addr) {
1047 g_add_ptk_key_params.mac_addr = NULL;
1048 } else {
f3052587 1049 g_add_ptk_key_params.mac_addr = kmalloc(ETH_ALEN, GFP_KERNEL);
c5c77ba1
JK
1050 memcpy(g_add_ptk_key_params.mac_addr, mac_addr, ETH_ALEN);
1051 }
1052 g_key_ptk_params.key_len = params->key_len;
1053 g_key_ptk_params.seq_len = params->seq_len;
f3052587 1054 g_key_ptk_params.key = kmalloc(params->key_len, GFP_KERNEL);
c5c77ba1
JK
1055 memcpy(g_key_ptk_params.key, params->key, params->key_len);
1056 if (params->seq_len > 0) {
f3052587 1057 g_key_ptk_params.seq = kmalloc(params->seq_len, GFP_KERNEL);
c5c77ba1
JK
1058 memcpy(g_key_ptk_params.seq, params->seq, params->seq_len);
1059 }
1060 g_key_ptk_params.cipher = params->cipher;
72ed4dc7 1061 g_ptk_keys_saved = true;
c5c77ba1
JK
1062 }
1063
fbf5379b
GL
1064 wilc_add_ptk(vif, params->key, KeyLen,
1065 mac_addr, pu8RxMic, pu8TxMic,
1066 STATION_MODE, u8mode, key_index);
c5c77ba1
JK
1067 }
1068 }
1069 break;
1070
1071 default:
06fb9336 1072 netdev_err(netdev, "Not supported cipher\n");
c5c77ba1 1073 s32Error = -ENOTSUPP;
c5c77ba1
JK
1074 }
1075
1076 return s32Error;
1077}
1078
3044ba7e
CL
1079static int del_key(struct wiphy *wiphy, struct net_device *netdev,
1080 u8 key_index,
1081 bool pairwise,
1082 const u8 *mac_addr)
c5c77ba1 1083{
2726887c 1084 struct wilc_priv *priv;
692e2ace 1085 struct wilc *wl;
a4cac481 1086 struct wilc_vif *vif;
c5c77ba1
JK
1087
1088 priv = wiphy_priv(wiphy);
a4cac481
GL
1089 vif = netdev_priv(netdev);
1090 wl = vif->wilc;
c5c77ba1 1091
1f435d2e 1092 if (netdev == wl->vif[0]->ndev) {
72ed4dc7
DL
1093 g_ptk_keys_saved = false;
1094 g_gtk_keys_saved = false;
1095 g_wep_keys_saved = false;
c5c77ba1 1096
cccfc39e
SB
1097 kfree(g_key_wep_params.key);
1098 g_key_wep_params.key = NULL;
c5c77ba1 1099
c5c77ba1 1100 if ((priv->wilc_gtk[key_index]) != NULL) {
cccfc39e
SB
1101 kfree(priv->wilc_gtk[key_index]->key);
1102 priv->wilc_gtk[key_index]->key = NULL;
1103 kfree(priv->wilc_gtk[key_index]->seq);
1104 priv->wilc_gtk[key_index]->seq = NULL;
c5c77ba1 1105
49188af2 1106 kfree(priv->wilc_gtk[key_index]);
c5c77ba1 1107 priv->wilc_gtk[key_index] = NULL;
c5c77ba1
JK
1108 }
1109
1110 if ((priv->wilc_ptk[key_index]) != NULL) {
cccfc39e
SB
1111 kfree(priv->wilc_ptk[key_index]->key);
1112 priv->wilc_ptk[key_index]->key = NULL;
1113 kfree(priv->wilc_ptk[key_index]->seq);
1114 priv->wilc_ptk[key_index]->seq = NULL;
49188af2 1115 kfree(priv->wilc_ptk[key_index]);
c5c77ba1
JK
1116 priv->wilc_ptk[key_index] = NULL;
1117 }
c5c77ba1 1118
cccfc39e
SB
1119 kfree(g_key_ptk_params.key);
1120 g_key_ptk_params.key = NULL;
1121 kfree(g_key_ptk_params.seq);
1122 g_key_ptk_params.seq = NULL;
1123
1124 kfree(g_key_gtk_params.key);
1125 g_key_gtk_params.key = NULL;
1126 kfree(g_key_gtk_params.seq);
1127 g_key_gtk_params.seq = NULL;
c5c77ba1 1128
c5c77ba1
JK
1129 }
1130
1131 if (key_index >= 0 && key_index <= 3) {
b0f1836f
LK
1132 if (priv->WILC_WFI_wep_key_len[key_index]) {
1133 memset(priv->WILC_WFI_wep_key[key_index], 0,
1134 priv->WILC_WFI_wep_key_len[key_index]);
1135 priv->WILC_WFI_wep_key_len[key_index] = 0;
1136 wilc_remove_wep_key(vif, key_index);
1137 }
c5c77ba1 1138 } else {
48b28df9 1139 wilc_remove_key(priv->hif_drv, mac_addr);
c5c77ba1
JK
1140 }
1141
aaed3290 1142 return 0;
c5c77ba1
JK
1143}
1144
f4893dfc
CL
1145static int get_key(struct wiphy *wiphy, struct net_device *netdev, u8 key_index,
1146 bool pairwise,
1147 const u8 *mac_addr, void *cookie, void (*callback)(void *cookie, struct key_params *))
c5c77ba1 1148{
2726887c 1149 struct wilc_priv *priv;
c5c77ba1 1150 struct key_params key_params;
8dfaafd6 1151
c5c77ba1
JK
1152 priv = wiphy_priv(wiphy);
1153
1154
3604af50 1155 if (!pairwise) {
c5c77ba1
JK
1156 key_params.key = priv->wilc_gtk[key_index]->key;
1157 key_params.cipher = priv->wilc_gtk[key_index]->cipher;
1158 key_params.key_len = priv->wilc_gtk[key_index]->key_len;
1159 key_params.seq = priv->wilc_gtk[key_index]->seq;
1160 key_params.seq_len = priv->wilc_gtk[key_index]->seq_len;
c5c77ba1 1161 } else {
c5c77ba1
JK
1162 key_params.key = priv->wilc_ptk[key_index]->key;
1163 key_params.cipher = priv->wilc_ptk[key_index]->cipher;
1164 key_params.key_len = priv->wilc_ptk[key_index]->key_len;
1165 key_params.seq = priv->wilc_ptk[key_index]->seq;
1166 key_params.seq_len = priv->wilc_ptk[key_index]->seq_len;
1167 }
1168
1169 callback(cookie, &key_params);
1170
a89f7c55 1171 return 0;
c5c77ba1
JK
1172}
1173
0f5b8ca3
CL
1174static int set_default_key(struct wiphy *wiphy, struct net_device *netdev, u8 key_index,
1175 bool unicast, bool multicast)
c5c77ba1 1176{
2726887c 1177 struct wilc_priv *priv;
cf60106b 1178 struct wilc_vif *vif;
c5c77ba1
JK
1179
1180 priv = wiphy_priv(wiphy);
cf60106b 1181 vif = netdev_priv(priv->dev);
c5c77ba1 1182
ec450483 1183 wilc_set_wep_default_keyid(vif, key_index);
c5c77ba1 1184
aaed3290 1185 return 0;
c5c77ba1
JK
1186}
1187
f06f562d
CL
1188static int get_station(struct wiphy *wiphy, struct net_device *dev,
1189 const u8 *mac, struct station_info *sinfo)
c5c77ba1 1190{
2726887c 1191 struct wilc_priv *priv;
a4cac481 1192 struct wilc_vif *vif;
4e4467fd 1193 u32 i = 0;
6c08fda0 1194 u32 associatedsta = ~0;
4e4467fd 1195 u32 inactive_time = 0;
c5c77ba1 1196 priv = wiphy_priv(wiphy);
a4cac481 1197 vif = netdev_priv(dev);
c5c77ba1 1198
a4cac481 1199 if (vif->iftype == AP_MODE || vif->iftype == GO_MODE) {
c5c77ba1 1200 for (i = 0; i < NUM_STA_ASSOCIATED; i++) {
c5c77ba1
JK
1201 if (!(memcmp(mac, priv->assoc_stainfo.au8Sta_AssociatedBss[i], ETH_ALEN))) {
1202 associatedsta = i;
1203 break;
1204 }
c5c77ba1
JK
1205 }
1206
6c08fda0 1207 if (associatedsta == ~0) {
06fb9336 1208 netdev_err(dev, "sta required is not associated\n");
aaed3290 1209 return -ENOENT;
c5c77ba1
JK
1210 }
1211
c5c77ba1 1212 sinfo->filled |= BIT(NL80211_STA_INFO_INACTIVE_TIME);
c5c77ba1 1213
fbf5379b 1214 wilc_get_inactive_time(vif, mac, &inactive_time);
c5c77ba1 1215 sinfo->inactive_time = 1000 * inactive_time;
c5c77ba1 1216 }
c5c77ba1 1217
a4cac481 1218 if (vif->iftype == STATION_MODE) {
03e7b9c4 1219 struct rf_info strStatistics;
8dfaafd6 1220
fbf5379b 1221 wilc_get_statistics(vif, &strStatistics);
c5c77ba1 1222
c5c77ba1 1223 sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL) |
6212990a 1224 BIT(NL80211_STA_INFO_RX_PACKETS) |
c5c77ba1
JK
1225 BIT(NL80211_STA_INFO_TX_PACKETS) |
1226 BIT(NL80211_STA_INFO_TX_FAILED) |
1227 BIT(NL80211_STA_INFO_TX_BITRATE);
c5c77ba1 1228
00c8dfcf 1229 sinfo->signal = strStatistics.rssi;
9b99274a 1230 sinfo->rx_packets = strStatistics.rx_cnt;
54160376
LK
1231 sinfo->tx_packets = strStatistics.tx_cnt + strStatistics.tx_fail_cnt;
1232 sinfo->tx_failed = strStatistics.tx_fail_cnt;
5babeecb 1233 sinfo->txrate.legacy = strStatistics.link_speed * 10;
c5c77ba1 1234
5babeecb
LK
1235 if ((strStatistics.link_speed > TCP_ACK_FILTER_LINK_SPEED_THRESH) &&
1236 (strStatistics.link_speed != DEFAULT_LINK_SPEED))
0e1af73d 1237 wilc_enable_tcp_ack_filter(true);
5babeecb 1238 else if (strStatistics.link_speed != DEFAULT_LINK_SPEED)
0e1af73d 1239 wilc_enable_tcp_ack_filter(false);
c5c77ba1 1240 }
aaed3290 1241 return 0;
c5c77ba1
JK
1242}
1243
a5f7db6a
CL
1244static int change_bss(struct wiphy *wiphy, struct net_device *dev,
1245 struct bss_parameters *params)
c5c77ba1 1246{
c5c77ba1
JK
1247 return 0;
1248}
1249
a76b63ef 1250static int set_wiphy_params(struct wiphy *wiphy, u32 changed)
c5c77ba1 1251{
e6e12661 1252 s32 s32Error = 0;
a5f0fb5c 1253 struct cfg_param_attr pstrCfgParamVal;
2726887c 1254 struct wilc_priv *priv;
cf60106b 1255 struct wilc_vif *vif;
c5c77ba1
JK
1256
1257 priv = wiphy_priv(wiphy);
cf60106b 1258 vif = netdev_priv(priv->dev);
c5c77ba1 1259
87c05b28 1260 pstrCfgParamVal.flag = 0;
c5c77ba1
JK
1261
1262 if (changed & WIPHY_PARAM_RETRY_SHORT) {
87c05b28 1263 pstrCfgParamVal.flag |= RETRY_SHORT;
c5c77ba1
JK
1264 pstrCfgParamVal.short_retry_limit = priv->dev->ieee80211_ptr->wiphy->retry_short;
1265 }
1266 if (changed & WIPHY_PARAM_RETRY_LONG) {
87c05b28 1267 pstrCfgParamVal.flag |= RETRY_LONG;
c5c77ba1 1268 pstrCfgParamVal.long_retry_limit = priv->dev->ieee80211_ptr->wiphy->retry_long;
c5c77ba1
JK
1269 }
1270 if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
87c05b28 1271 pstrCfgParamVal.flag |= FRAG_THRESHOLD;
c5c77ba1 1272 pstrCfgParamVal.frag_threshold = priv->dev->ieee80211_ptr->wiphy->frag_threshold;
c5c77ba1
JK
1273 }
1274
1275 if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
87c05b28 1276 pstrCfgParamVal.flag |= RTS_THRESHOLD;
c5c77ba1 1277 pstrCfgParamVal.rts_threshold = priv->dev->ieee80211_ptr->wiphy->rts_threshold;
c5c77ba1
JK
1278 }
1279
fbf5379b 1280 s32Error = wilc_hif_set_cfg(vif, &pstrCfgParamVal);
c5c77ba1 1281 if (s32Error)
06fb9336 1282 netdev_err(priv->dev, "Error in setting WIPHY PARAMS\n");
c5c77ba1
JK
1283
1284 return s32Error;
1285}
e5af0561 1286
4d46657a
CL
1287static int set_pmksa(struct wiphy *wiphy, struct net_device *netdev,
1288 struct cfg80211_pmksa *pmksa)
c5c77ba1 1289{
4e4467fd 1290 u32 i;
e6e12661 1291 s32 s32Error = 0;
63d03e47 1292 u8 flag = 0;
cf60106b 1293 struct wilc_vif *vif;
2726887c 1294 struct wilc_priv *priv = wiphy_priv(wiphy);
c5c77ba1 1295
cf60106b 1296 vif = netdev_priv(priv->dev);
c5c77ba1
JK
1297
1298
1299 for (i = 0; i < priv->pmkid_list.numpmkid; i++) {
1a646e7e 1300 if (!memcmp(pmksa->bssid, priv->pmkid_list.pmkidlist[i].bssid,
c5c77ba1 1301 ETH_ALEN)) {
c5c77ba1 1302 flag = PMKID_FOUND;
c5c77ba1
JK
1303 break;
1304 }
1305 }
1306 if (i < WILC_MAX_NUM_PMKIDS) {
d00d2ba3 1307 memcpy(priv->pmkid_list.pmkidlist[i].bssid, pmksa->bssid,
c5c77ba1 1308 ETH_ALEN);
d00d2ba3 1309 memcpy(priv->pmkid_list.pmkidlist[i].pmkid, pmksa->pmkid,
c5c77ba1
JK
1310 PMKID_LEN);
1311 if (!(flag == PMKID_FOUND))
1312 priv->pmkid_list.numpmkid++;
1313 } else {
06fb9336 1314 netdev_err(netdev, "Invalid PMKID index\n");
c5c77ba1
JK
1315 s32Error = -EINVAL;
1316 }
1317
64d3546a 1318 if (!s32Error)
fbf5379b 1319 s32Error = wilc_set_pmkid_info(vif, &priv->pmkid_list);
64d3546a 1320
c5c77ba1
JK
1321 return s32Error;
1322}
1323
1ff86d96
CL
1324static int del_pmksa(struct wiphy *wiphy, struct net_device *netdev,
1325 struct cfg80211_pmksa *pmksa)
c5c77ba1 1326{
4e4467fd 1327 u32 i;
e6e12661 1328 s32 s32Error = 0;
c5c77ba1 1329
2726887c 1330 struct wilc_priv *priv = wiphy_priv(wiphy);
c5c77ba1 1331
c5c77ba1 1332 for (i = 0; i < priv->pmkid_list.numpmkid; i++) {
1a646e7e 1333 if (!memcmp(pmksa->bssid, priv->pmkid_list.pmkidlist[i].bssid,
c5c77ba1 1334 ETH_ALEN)) {
cd1e6cb4 1335 memset(&priv->pmkid_list.pmkidlist[i], 0, sizeof(struct host_if_pmkid));
c5c77ba1
JK
1336 break;
1337 }
1338 }
1339
1340 if (i < priv->pmkid_list.numpmkid && priv->pmkid_list.numpmkid > 0) {
1341 for (; i < (priv->pmkid_list.numpmkid - 1); i++) {
d00d2ba3 1342 memcpy(priv->pmkid_list.pmkidlist[i].bssid,
c5c77ba1
JK
1343 priv->pmkid_list.pmkidlist[i + 1].bssid,
1344 ETH_ALEN);
d00d2ba3 1345 memcpy(priv->pmkid_list.pmkidlist[i].pmkid,
c5c77ba1
JK
1346 priv->pmkid_list.pmkidlist[i].pmkid,
1347 PMKID_LEN);
1348 }
1349 priv->pmkid_list.numpmkid--;
1350 } else {
1351 s32Error = -EINVAL;
1352 }
1353
1354 return s32Error;
1355}
1356
b33c39b1 1357static int flush_pmksa(struct wiphy *wiphy, struct net_device *netdev)
c5c77ba1 1358{
2726887c 1359 struct wilc_priv *priv = wiphy_priv(wiphy);
c5c77ba1 1360
a949f909 1361 memset(&priv->pmkid_list, 0, sizeof(struct host_if_pmkid_attr));
c5c77ba1
JK
1362
1363 return 0;
1364}
c5c77ba1 1365
1608c403 1366static void WILC_WFI_CfgParseRxAction(u8 *buf, u32 len)
c5c77ba1 1367{
4e4467fd
CL
1368 u32 index = 0;
1369 u32 i = 0, j = 0;
c5c77ba1 1370
63d03e47
GKH
1371 u8 op_channel_attr_index = 0;
1372 u8 channel_list_attr_index = 0;
c5c77ba1
JK
1373
1374 while (index < len) {
d5e27e8b 1375 if (buf[index] == GO_INTENT_ATTR_ID)
c5c77ba1 1376 buf[index + 3] = (buf[index + 3] & 0x01) | (0x00 << 1);
c5c77ba1 1377
78174ada 1378 if (buf[index] == CHANLIST_ATTR_ID)
c5c77ba1 1379 channel_list_attr_index = index;
78174ada 1380 else if (buf[index] == OPERCHAN_ATTR_ID)
c5c77ba1 1381 op_channel_attr_index = index;
a89f7c55 1382 index += buf[index + 1] + 3;
c5c77ba1 1383 }
0bd8274f 1384 if (wlan_channel != INVALID_CHANNEL) {
c5c77ba1 1385 if (channel_list_attr_index) {
c5c77ba1
JK
1386 for (i = channel_list_attr_index + 3; i < ((channel_list_attr_index + 3) + buf[channel_list_attr_index + 1]); i++) {
1387 if (buf[i] == 0x51) {
d5e27e8b 1388 for (j = i + 2; j < ((i + 2) + buf[i + 1]); j++)
0bd8274f 1389 buf[j] = wlan_channel;
c5c77ba1
JK
1390 break;
1391 }
1392 }
1393 }
a89f7c55 1394
c5c77ba1 1395 if (op_channel_attr_index) {
c5c77ba1 1396 buf[op_channel_attr_index + 6] = 0x51;
0bd8274f 1397 buf[op_channel_attr_index + 7] = wlan_channel;
c5c77ba1
JK
1398 }
1399 }
1400}
1401
1608c403 1402static void WILC_WFI_CfgParseTxAction(u8 *buf, u32 len, bool bOperChan, u8 iftype)
c5c77ba1 1403{
4e4467fd
CL
1404 u32 index = 0;
1405 u32 i = 0, j = 0;
c5c77ba1 1406
63d03e47
GKH
1407 u8 op_channel_attr_index = 0;
1408 u8 channel_list_attr_index = 0;
c5c77ba1
JK
1409
1410 while (index < len) {
c5c77ba1 1411 if (buf[index] == GO_INTENT_ATTR_ID) {
c5c77ba1 1412 buf[index + 3] = (buf[index + 3] & 0x01) | (0x0f << 1);
c5c77ba1
JK
1413
1414 break;
1415 }
c5c77ba1 1416
78174ada 1417 if (buf[index] == CHANLIST_ATTR_ID)
c5c77ba1 1418 channel_list_attr_index = index;
78174ada 1419 else if (buf[index] == OPERCHAN_ATTR_ID)
c5c77ba1 1420 op_channel_attr_index = index;
a89f7c55 1421 index += buf[index + 1] + 3;
c5c77ba1 1422 }
0bd8274f 1423 if (wlan_channel != INVALID_CHANNEL && bOperChan) {
c5c77ba1 1424 if (channel_list_attr_index) {
c5c77ba1
JK
1425 for (i = channel_list_attr_index + 3; i < ((channel_list_attr_index + 3) + buf[channel_list_attr_index + 1]); i++) {
1426 if (buf[i] == 0x51) {
d5e27e8b 1427 for (j = i + 2; j < ((i + 2) + buf[i + 1]); j++)
0bd8274f 1428 buf[j] = wlan_channel;
c5c77ba1
JK
1429 break;
1430 }
1431 }
1432 }
a89f7c55 1433
c5c77ba1 1434 if (op_channel_attr_index) {
c5c77ba1 1435 buf[op_channel_attr_index + 6] = 0x51;
0bd8274f 1436 buf[op_channel_attr_index + 7] = wlan_channel;
c5c77ba1
JK
1437 }
1438 }
1439}
1440
63f80351 1441void WILC_WFI_p2p_rx(struct net_device *dev, u8 *buff, u32 size)
c5c77ba1 1442{
2726887c 1443 struct wilc_priv *priv;
4e4467fd 1444 u32 header, pkt_offset;
441dc609 1445 struct host_if_drv *pstrWFIDrv;
4e4467fd 1446 u32 i = 0;
fb4ec9ca 1447 s32 s32Freq;
8dfaafd6 1448
c5c77ba1 1449 priv = wiphy_priv(dev->ieee80211_ptr->wiphy);
48b28df9 1450 pstrWFIDrv = (struct host_if_drv *)priv->hif_drv;
c5c77ba1 1451
d00d2ba3 1452 memcpy(&header, (buff - HOST_HDR_OFFSET), HOST_HDR_OFFSET);
c5c77ba1 1453
c5c77ba1
JK
1454 pkt_offset = GET_PKT_OFFSET(header);
1455
1456 if (pkt_offset & IS_MANAGMEMENT_CALLBACK) {
1457 if (buff[FRAME_TYPE_ID] == IEEE80211_STYPE_PROBE_RESP) {
c5c77ba1 1458 cfg80211_mgmt_tx_status(priv->wdev, priv->u64tx_cookie, buff, size, true, GFP_KERNEL);
c5c77ba1
JK
1459 return;
1460 } else {
e3f16965 1461 if (pkt_offset & IS_MGMT_STATUS_SUCCES)
c5c77ba1 1462 cfg80211_mgmt_tx_status(priv->wdev, priv->u64tx_cookie, buff, size, true, GFP_KERNEL);
e3f16965 1463 else
c5c77ba1 1464 cfg80211_mgmt_tx_status(priv->wdev, priv->u64tx_cookie, buff, size, false, GFP_KERNEL);
c5c77ba1
JK
1465 return;
1466 }
1467 } else {
57fbcce3 1468 s32Freq = ieee80211_channel_to_frequency(curr_channel, NL80211_BAND_2GHZ);
c5c77ba1
JK
1469
1470 if (ieee80211_is_action(buff[FRAME_TYPE_ID])) {
1229b1ab 1471 if (priv->bCfgScanning && time_after_eq(jiffies, (unsigned long)pstrWFIDrv->p2p_timeout)) {
e3f16965 1472 netdev_dbg(dev, "Receiving action wrong ch\n");
c5c77ba1
JK
1473 return;
1474 }
1475 if (buff[ACTION_CAT_ID] == PUB_ACTION_ATTR_ID) {
c5c77ba1
JK
1476 switch (buff[ACTION_SUBTYPE_ID]) {
1477 case GAS_INTIAL_REQ:
c5c77ba1
JK
1478 break;
1479
1480 case GAS_INTIAL_RSP:
c5c77ba1
JK
1481 break;
1482
1483 case PUBLIC_ACT_VENDORSPEC:
881eb5d8 1484 if (!memcmp(p2p_oui, &buff[ACTION_SUBTYPE_ID + 1], 4)) {
c5c77ba1 1485 if ((buff[P2P_PUB_ACTION_SUBTYPE] == GO_NEG_REQ || buff[P2P_PUB_ACTION_SUBTYPE] == GO_NEG_RSP)) {
a25d5186 1486 if (!wilc_ie) {
c5c77ba1 1487 for (i = P2P_PUB_ACTION_SUBTYPE; i < size; i++) {
8668594a 1488 if (!memcmp(p2p_vendor_spec, &buff[i], 6)) {
b84a3ac4 1489 p2p_recv_random = buff[i + 6];
a25d5186 1490 wilc_ie = true;
c5c77ba1
JK
1491 break;
1492 }
1493 }
1494 }
1495 }
b84a3ac4 1496 if (p2p_local_random > p2p_recv_random) {
c5c77ba1
JK
1497 if ((buff[P2P_PUB_ACTION_SUBTYPE] == GO_NEG_REQ || buff[P2P_PUB_ACTION_SUBTYPE] == GO_NEG_RSP
1498 || buff[P2P_PUB_ACTION_SUBTYPE] == P2P_INV_REQ || buff[P2P_PUB_ACTION_SUBTYPE] == P2P_INV_RSP)) {
1499 for (i = P2P_PUB_ACTION_SUBTYPE + 2; i < size; i++) {
881eb5d8 1500 if (buff[i] == P2PELEM_ATTR_ID && !(memcmp(p2p_oui, &buff[i + 2], 4))) {
c5c77ba1
JK
1501 WILC_WFI_CfgParseRxAction(&buff[i + 6], size - (i + 6));
1502 break;
1503 }
1504 }
1505 }
583d972c 1506 } else {
e3f16965 1507 netdev_dbg(dev, "PEER WILL BE GO LocaRand=%02x RecvRand %02x\n", p2p_local_random, p2p_recv_random);
583d972c 1508 }
c5c77ba1
JK
1509 }
1510
1511
a25d5186 1512 if ((buff[P2P_PUB_ACTION_SUBTYPE] == GO_NEG_REQ || buff[P2P_PUB_ACTION_SUBTYPE] == GO_NEG_RSP) && (wilc_ie)) {
c5c77ba1 1513 cfg80211_rx_mgmt(priv->wdev, s32Freq, 0, buff, size - 7, 0);
c5c77ba1
JK
1514 return;
1515 }
1516 break;
1517
1518 default:
e3f16965 1519 netdev_dbg(dev, "NOT HANDLED PUBLIC ACTION FRAME TYPE:%x\n", buff[ACTION_SUBTYPE_ID]);
c5c77ba1
JK
1520 break;
1521 }
1522 }
1523 }
1524
783d07c1 1525 cfg80211_rx_mgmt(priv->wdev, s32Freq, 0, buff, size, 0);
c5c77ba1
JK
1526 }
1527}
1528
c5c77ba1
JK
1529static void WILC_WFI_mgmt_tx_complete(void *priv, int status)
1530{
4375cad9 1531 struct p2p_mgmt_data *pv_data = priv;
c5c77ba1
JK
1532
1533
1534 kfree(pv_data->buff);
1535 kfree(pv_data);
1536}
1537
c5c77ba1
JK
1538static void WILC_WFI_RemainOnChannelReady(void *pUserVoid)
1539{
2726887c 1540 struct wilc_priv *priv;
8dfaafd6 1541
4375cad9 1542 priv = pUserVoid;
c5c77ba1 1543
72ed4dc7 1544 priv->bInP2PlistenState = true;
c5c77ba1 1545
c5c77ba1
JK
1546 cfg80211_ready_on_channel(priv->wdev,
1547 priv->strRemainOnChanParams.u64ListenCookie,
1548 priv->strRemainOnChanParams.pstrListenChan,
1549 priv->strRemainOnChanParams.u32ListenDuration,
1550 GFP_KERNEL);
c5c77ba1
JK
1551}
1552
4e4467fd 1553static void WILC_WFI_RemainOnChannelExpired(void *pUserVoid, u32 u32SessionID)
c5c77ba1 1554{
2726887c 1555 struct wilc_priv *priv;
8dfaafd6 1556
4375cad9 1557 priv = pUserVoid;
c5c77ba1 1558
c5c77ba1 1559 if (u32SessionID == priv->strRemainOnChanParams.u32ListenSessionID) {
72ed4dc7 1560 priv->bInP2PlistenState = false;
c5c77ba1 1561
c5c77ba1
JK
1562 cfg80211_remain_on_channel_expired(priv->wdev,
1563 priv->strRemainOnChanParams.u64ListenCookie,
1564 priv->strRemainOnChanParams.pstrListenChan,
1565 GFP_KERNEL);
c5c77ba1
JK
1566 }
1567}
1568
6d19d695
CL
1569static int remain_on_channel(struct wiphy *wiphy,
1570 struct wireless_dev *wdev,
1571 struct ieee80211_channel *chan,
1572 unsigned int duration, u64 *cookie)
c5c77ba1 1573{
e6e12661 1574 s32 s32Error = 0;
2726887c 1575 struct wilc_priv *priv;
cf60106b 1576 struct wilc_vif *vif;
8dfaafd6 1577
c5c77ba1 1578 priv = wiphy_priv(wiphy);
cf60106b 1579 vif = netdev_priv(priv->dev);
c5c77ba1 1580
c5c77ba1 1581 if (wdev->iftype == NL80211_IFTYPE_AP) {
e3f16965 1582 netdev_dbg(vif->ndev, "Required while in AP mode\n");
c5c77ba1
JK
1583 return s32Error;
1584 }
c5c77ba1 1585
866a2c24 1586 curr_channel = chan->hw_value;
c5c77ba1 1587
c5c77ba1
JK
1588 priv->strRemainOnChanParams.pstrListenChan = chan;
1589 priv->strRemainOnChanParams.u64ListenCookie = *cookie;
c5c77ba1
JK
1590 priv->strRemainOnChanParams.u32ListenDuration = duration;
1591 priv->strRemainOnChanParams.u32ListenSessionID++;
1592
fbf5379b
GL
1593 s32Error = wilc_remain_on_channel(vif,
1594 priv->strRemainOnChanParams.u32ListenSessionID,
1595 duration, chan->hw_value,
1596 WILC_WFI_RemainOnChannelExpired,
1597 WILC_WFI_RemainOnChannelReady, (void *)priv);
c5c77ba1
JK
1598
1599 return s32Error;
1600}
1601
1dd5440b
CL
1602static int cancel_remain_on_channel(struct wiphy *wiphy,
1603 struct wireless_dev *wdev,
1604 u64 cookie)
c5c77ba1 1605{
e6e12661 1606 s32 s32Error = 0;
2726887c 1607 struct wilc_priv *priv;
cf60106b 1608 struct wilc_vif *vif;
8dfaafd6 1609
c5c77ba1 1610 priv = wiphy_priv(wiphy);
cf60106b 1611 vif = netdev_priv(priv->dev);
c5c77ba1 1612
fbf5379b 1613 s32Error = wilc_listen_state_expired(vif, priv->strRemainOnChanParams.u32ListenSessionID);
c5c77ba1
JK
1614 return s32Error;
1615}
a89f7c55 1616
c156032d
CL
1617static int mgmt_tx(struct wiphy *wiphy,
1618 struct wireless_dev *wdev,
1619 struct cfg80211_mgmt_tx_params *params,
1620 u64 *cookie)
c5c77ba1 1621{
c5c77ba1
JK
1622 struct ieee80211_channel *chan = params->chan;
1623 unsigned int wait = params->wait;
1624 const u8 *buf = params->buf;
1625 size_t len = params->len;
c5c77ba1
JK
1626 const struct ieee80211_mgmt *mgmt;
1627 struct p2p_mgmt_data *mgmt_tx;
2726887c 1628 struct wilc_priv *priv;
441dc609 1629 struct host_if_drv *pstrWFIDrv;
4e4467fd 1630 u32 i;
a4cac481 1631 struct wilc_vif *vif;
8668594a 1632 u32 buf_len = len + sizeof(p2p_vendor_spec) + sizeof(p2p_local_random);
c5c77ba1 1633
a4cac481 1634 vif = netdev_priv(wdev->netdev);
c5c77ba1 1635 priv = wiphy_priv(wiphy);
48b28df9 1636 pstrWFIDrv = (struct host_if_drv *)priv->hif_drv;
c5c77ba1
JK
1637
1638 *cookie = (unsigned long)buf;
1639 priv->u64tx_cookie = *cookie;
1640 mgmt = (const struct ieee80211_mgmt *) buf;
1641
1642 if (ieee80211_is_mgmt(mgmt->frame_control)) {
f3052587 1643 mgmt_tx = kmalloc(sizeof(struct p2p_mgmt_data), GFP_KERNEL);
06fb9336 1644 if (!mgmt_tx)
e6e12661 1645 return -EFAULT;
06fb9336 1646
f3052587 1647 mgmt_tx->buff = kmalloc(buf_len, GFP_KERNEL);
d99ee289 1648 if (!mgmt_tx->buff) {
f638dd39 1649 kfree(mgmt_tx);
d99ee289
DC
1650 return -ENOMEM;
1651 }
06fb9336 1652
d00d2ba3 1653 memcpy(mgmt_tx->buff, buf, len);
c5c77ba1
JK
1654 mgmt_tx->size = len;
1655
1656
1657 if (ieee80211_is_probe_resp(mgmt->frame_control)) {
fbf5379b 1658 wilc_set_mac_chnl_num(vif, chan->hw_value);
866a2c24 1659 curr_channel = chan->hw_value;
c5c77ba1 1660 } else if (ieee80211_is_action(mgmt->frame_control)) {
c5c77ba1 1661 if (buf[ACTION_CAT_ID] == PUB_ACTION_ATTR_ID) {
c5c77ba1
JK
1662 if (buf[ACTION_SUBTYPE_ID] != PUBLIC_ACT_VENDORSPEC ||
1663 buf[P2P_PUB_ACTION_SUBTYPE] != GO_NEG_CONF) {
fbf5379b
GL
1664 wilc_set_mac_chnl_num(vif,
1665 chan->hw_value);
866a2c24 1666 curr_channel = chan->hw_value;
c5c77ba1
JK
1667 }
1668 switch (buf[ACTION_SUBTYPE_ID]) {
1669 case GAS_INTIAL_REQ:
c5c77ba1 1670 break;
c5c77ba1
JK
1671
1672 case GAS_INTIAL_RSP:
c5c77ba1 1673 break;
c5c77ba1
JK
1674
1675 case PUBLIC_ACT_VENDORSPEC:
1676 {
881eb5d8 1677 if (!memcmp(p2p_oui, &buf[ACTION_SUBTYPE_ID + 1], 4)) {
c5c77ba1 1678 if ((buf[P2P_PUB_ACTION_SUBTYPE] == GO_NEG_REQ || buf[P2P_PUB_ACTION_SUBTYPE] == GO_NEG_RSP)) {
b84a3ac4 1679 if (p2p_local_random == 1 && p2p_recv_random < p2p_local_random) {
583d972c
LK
1680 get_random_bytes(&p2p_local_random, 1);
1681 p2p_local_random++;
c5c77ba1
JK
1682 }
1683 }
1684
1685 if ((buf[P2P_PUB_ACTION_SUBTYPE] == GO_NEG_REQ || buf[P2P_PUB_ACTION_SUBTYPE] == GO_NEG_RSP
1686 || buf[P2P_PUB_ACTION_SUBTYPE] == P2P_INV_REQ || buf[P2P_PUB_ACTION_SUBTYPE] == P2P_INV_RSP)) {
b84a3ac4 1687 if (p2p_local_random > p2p_recv_random) {
c5c77ba1 1688 for (i = P2P_PUB_ACTION_SUBTYPE + 2; i < len; i++) {
881eb5d8 1689 if (buf[i] == P2PELEM_ATTR_ID && !(memcmp(p2p_oui, &buf[i + 2], 4))) {
c5c77ba1 1690 if (buf[P2P_PUB_ACTION_SUBTYPE] == P2P_INV_REQ || buf[P2P_PUB_ACTION_SUBTYPE] == P2P_INV_RSP)
a4cac481 1691 WILC_WFI_CfgParseTxAction(&mgmt_tx->buff[i + 6], len - (i + 6), true, vif->iftype);
c5c77ba1 1692 else
a4cac481 1693 WILC_WFI_CfgParseTxAction(&mgmt_tx->buff[i + 6], len - (i + 6), false, vif->iftype);
c5c77ba1
JK
1694 break;
1695 }
1696 }
1697
1698 if (buf[P2P_PUB_ACTION_SUBTYPE] != P2P_INV_REQ && buf[P2P_PUB_ACTION_SUBTYPE] != P2P_INV_RSP) {
8668594a
LK
1699 memcpy(&mgmt_tx->buff[len], p2p_vendor_spec, sizeof(p2p_vendor_spec));
1700 mgmt_tx->buff[len + sizeof(p2p_vendor_spec)] = p2p_local_random;
c5c77ba1
JK
1701 mgmt_tx->size = buf_len;
1702 }
583d972c 1703 }
c5c77ba1
JK
1704 }
1705
1706 } else {
e3f16965 1707 netdev_dbg(vif->ndev, "Not a P2P public action frame\n");
c5c77ba1
JK
1708 }
1709
1710 break;
1711 }
1712
1713 default:
1714 {
e3f16965 1715 netdev_dbg(vif->ndev, "NOT HANDLED PUBLIC ACTION FRAME TYPE:%x\n", buf[ACTION_SUBTYPE_ID]);
c5c77ba1
JK
1716 break;
1717 }
1718 }
c5c77ba1
JK
1719 }
1720
1229b1ab 1721 pstrWFIDrv->p2p_timeout = (jiffies + msecs_to_jiffies(wait));
c5c77ba1
JK
1722 }
1723
829c477f
GL
1724 wilc_wlan_txq_add_mgmt_pkt(wdev->netdev, mgmt_tx,
1725 mgmt_tx->buff, mgmt_tx->size,
c9d4834d 1726 WILC_WFI_mgmt_tx_complete);
c5c77ba1 1727 }
aaed3290 1728 return 0;
c5c77ba1
JK
1729}
1730
85c587a5
CL
1731static int mgmt_tx_cancel_wait(struct wiphy *wiphy,
1732 struct wireless_dev *wdev,
1733 u64 cookie)
c5c77ba1 1734{
2726887c 1735 struct wilc_priv *priv;
441dc609 1736 struct host_if_drv *pstrWFIDrv;
8dfaafd6 1737
c5c77ba1 1738 priv = wiphy_priv(wiphy);
48b28df9 1739 pstrWFIDrv = (struct host_if_drv *)priv->hif_drv;
1229b1ab 1740 pstrWFIDrv->p2p_timeout = jiffies;
c5c77ba1 1741
7e4e87d3 1742 if (!priv->bInP2PlistenState) {
c5c77ba1
JK
1743 cfg80211_remain_on_channel_expired(priv->wdev,
1744 priv->strRemainOnChanParams.u64ListenCookie,
1745 priv->strRemainOnChanParams.pstrListenChan,
1746 GFP_KERNEL);
c5c77ba1
JK
1747 }
1748
1749 return 0;
1750}
1751
8e0735c5
CL
1752void wilc_mgmt_frame_register(struct wiphy *wiphy, struct wireless_dev *wdev,
1753 u16 frame_type, bool reg)
c5c77ba1 1754{
2726887c 1755 struct wilc_priv *priv;
a4cac481 1756 struct wilc_vif *vif;
1b86935e 1757 struct wilc *wl;
c5c77ba1
JK
1758
1759 priv = wiphy_priv(wiphy);
a4cac481
GL
1760 vif = netdev_priv(priv->wdev->netdev);
1761 wl = vif->wilc;
c5c77ba1 1762
c5c77ba1
JK
1763 if (!frame_type)
1764 return;
1765
c5c77ba1
JK
1766 switch (frame_type) {
1767 case PROBE_REQ:
1768 {
340a84ff 1769 vif->frame_reg[0].type = frame_type;
89febb21 1770 vif->frame_reg[0].reg = reg;
c5c77ba1
JK
1771 }
1772 break;
1773
1774 case ACTION:
1775 {
340a84ff 1776 vif->frame_reg[1].type = frame_type;
89febb21 1777 vif->frame_reg[1].reg = reg;
c5c77ba1
JK
1778 }
1779 break;
1780
1781 default:
1782 {
1783 break;
1784 }
c5c77ba1 1785 }
a89f7c55 1786
e3f16965 1787 if (!wl->initialized)
c5c77ba1 1788 return;
fbf5379b 1789 wilc_frame_register(vif, frame_type, reg);
c5c77ba1 1790}
c5c77ba1 1791
a8047e26
CL
1792static int set_cqm_rssi_config(struct wiphy *wiphy, struct net_device *dev,
1793 s32 rssi_thold, u32 rssi_hyst)
c5c77ba1 1794{
c5c77ba1 1795 return 0;
c5c77ba1 1796}
a89f7c55 1797
bdb6338f
CL
1798static int dump_station(struct wiphy *wiphy, struct net_device *dev,
1799 int idx, u8 *mac, struct station_info *sinfo)
c5c77ba1 1800{
2726887c 1801 struct wilc_priv *priv;
cf60106b 1802 struct wilc_vif *vif;
8dfaafd6 1803
c5c77ba1
JK
1804 if (idx != 0)
1805 return -ENOENT;
1806
1807 priv = wiphy_priv(wiphy);
cf60106b 1808 vif = netdev_priv(priv->dev);
c5c77ba1 1809
c5c77ba1 1810 sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL);
c5c77ba1 1811
fbf5379b 1812 wilc_get_rssi(vif, &sinfo->signal);
c5c77ba1 1813
d1382968 1814 memcpy(mac, priv->au8AssociatedBss, ETH_ALEN);
c5c77ba1 1815 return 0;
c5c77ba1
JK
1816}
1817
46530679
CL
1818static int set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,
1819 bool enabled, int timeout)
c5c77ba1 1820{
2726887c 1821 struct wilc_priv *priv;
cf60106b 1822 struct wilc_vif *vif;
8dfaafd6 1823
369a1d3b 1824 if (!wiphy)
c5c77ba1
JK
1825 return -ENOENT;
1826
1827 priv = wiphy_priv(wiphy);
cf60106b 1828 vif = netdev_priv(priv->dev);
06fb9336 1829 if (!priv->hif_drv)
c5c77ba1 1830 return -EIO;
c5c77ba1 1831
0e1af73d 1832 if (wilc_enable_ps)
fbf5379b 1833 wilc_set_power_mgmt(vif, enabled, timeout);
c5c77ba1
JK
1834
1835
e6e12661 1836 return 0;
c5c77ba1 1837}
108b3439 1838
3615e9a3
CL
1839static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev,
1840 enum nl80211_iftype type, u32 *flags, struct vif_params *params)
c5c77ba1 1841{
2726887c 1842 struct wilc_priv *priv;
a4cac481 1843 struct wilc_vif *vif;
299382cf 1844 struct wilc *wl;
c5c77ba1 1845
a4cac481 1846 vif = netdev_priv(dev);
c5c77ba1 1847 priv = wiphy_priv(wiphy);
a4cac481 1848 wl = vif->wilc;
583d972c 1849 p2p_local_random = 0x01;
b84a3ac4 1850 p2p_recv_random = 0x00;
a25d5186 1851 wilc_ie = false;
0e1af73d
AB
1852 wilc_optaining_ip = false;
1853 del_timer(&wilc_during_ip_timer);
a89f7c55 1854
c5c77ba1
JK
1855 switch (type) {
1856 case NL80211_IFTYPE_STATION:
0e1af73d 1857 wilc_connecting = 0;
c5c77ba1
JK
1858 dev->ieee80211_ptr->iftype = type;
1859 priv->wdev->iftype = type;
a4cac481
GL
1860 vif->monitor_flag = 0;
1861 vif->iftype = STATION_MODE;
86bff01b 1862 wilc_set_operation_mode(vif, STATION_MODE);
c5c77ba1 1863
c5c77ba1 1864 memset(priv->assoc_stainfo.au8Sta_AssociatedBss, 0, MAX_NUM_STA * ETH_ALEN);
c5c77ba1 1865
86bff01b
GL
1866 wilc_enable_ps = true;
1867 wilc_set_power_mgmt(vif, 1, 0);
c5c77ba1
JK
1868 break;
1869
1870 case NL80211_IFTYPE_P2P_CLIENT:
0e1af73d 1871 wilc_connecting = 0;
c5c77ba1
JK
1872 dev->ieee80211_ptr->iftype = type;
1873 priv->wdev->iftype = type;
a4cac481 1874 vif->monitor_flag = 0;
a4cac481 1875 vif->iftype = CLIENT_MODE;
86bff01b 1876 wilc_set_operation_mode(vif, STATION_MODE);
ee632309
GL
1877
1878 wilc_enable_ps = false;
1879 wilc_set_power_mgmt(vif, 0, 0);
c5c77ba1
JK
1880 break;
1881
1882 case NL80211_IFTYPE_AP:
0e1af73d 1883 wilc_enable_ps = false;
c5c77ba1
JK
1884 dev->ieee80211_ptr->iftype = type;
1885 priv->wdev->iftype = type;
a4cac481 1886 vif->iftype = AP_MODE;
86bff01b
GL
1887
1888 if (wl->initialized) {
b3306865
GL
1889 wilc_set_wfi_drv_handler(vif, wilc_get_vif_idx(vif),
1890 0);
86bff01b
GL
1891 wilc_set_operation_mode(vif, AP_MODE);
1892 wilc_set_power_mgmt(vif, 0, 0);
c5c77ba1 1893 }
c5c77ba1
JK
1894 break;
1895
1896 case NL80211_IFTYPE_P2P_GO:
0e1af73d 1897 wilc_optaining_ip = true;
7e872df9
LK
1898 mod_timer(&wilc_during_ip_timer,
1899 jiffies + msecs_to_jiffies(during_ip_time));
86bff01b 1900 wilc_set_operation_mode(vif, AP_MODE);
c5c77ba1
JK
1901 dev->ieee80211_ptr->iftype = type;
1902 priv->wdev->iftype = type;
a4cac481 1903 vif->iftype = GO_MODE;
ee632309
GL
1904
1905 wilc_enable_ps = false;
1906 wilc_set_power_mgmt(vif, 0, 0);
c5c77ba1
JK
1907 break;
1908
1909 default:
06fb9336 1910 netdev_err(dev, "Unknown interface type= %d\n", type);
aaed3290 1911 return -EINVAL;
c5c77ba1
JK
1912 }
1913
aaed3290 1914 return 0;
c5c77ba1
JK
1915}
1916
a13168d7
CL
1917static int start_ap(struct wiphy *wiphy, struct net_device *dev,
1918 struct cfg80211_ap_settings *settings)
c5c77ba1
JK
1919{
1920 struct cfg80211_beacon_data *beacon = &(settings->beacon);
2726887c 1921 struct wilc_priv *priv;
e6e12661 1922 s32 s32Error = 0;
684dc186 1923 struct wilc *wl;
a4cac481 1924 struct wilc_vif *vif;
c5c77ba1
JK
1925
1926 priv = wiphy_priv(wiphy);
a4cac481 1927 vif = netdev_priv(dev);
79f7dfa5 1928 wl = vif->wilc;
c5c77ba1 1929
80785a9a 1930 s32Error = set_channel(wiphy, &settings->chandef);
c5c77ba1 1931
e6e12661 1932 if (s32Error != 0)
06fb9336 1933 netdev_err(dev, "Error in setting channel\n");
c5c77ba1 1934
6750140d 1935 wilc_wlan_set_bssid(dev, wl->vif[vif->idx]->src_addr, AP_MODE);
cba352a4 1936 wilc_set_power_mgmt(vif, 0, 0);
c5c77ba1 1937
fbf5379b
GL
1938 s32Error = wilc_add_beacon(vif, settings->beacon_interval,
1939 settings->dtim_period, beacon->head_len,
1940 (u8 *)beacon->head, beacon->tail_len,
1941 (u8 *)beacon->tail);
c5c77ba1
JK
1942
1943 return s32Error;
1944}
1945
2a4c84d7
CL
1946static int change_beacon(struct wiphy *wiphy, struct net_device *dev,
1947 struct cfg80211_beacon_data *beacon)
c5c77ba1 1948{
2726887c 1949 struct wilc_priv *priv;
cf60106b 1950 struct wilc_vif *vif;
e6e12661 1951 s32 s32Error = 0;
c5c77ba1
JK
1952
1953 priv = wiphy_priv(wiphy);
cf60106b 1954 vif = netdev_priv(priv->dev);
c5c77ba1 1955
fbf5379b
GL
1956 s32Error = wilc_add_beacon(vif, 0, 0, beacon->head_len,
1957 (u8 *)beacon->head, beacon->tail_len,
1958 (u8 *)beacon->tail);
c5c77ba1
JK
1959
1960 return s32Error;
1961}
1962
c8cddd79 1963static int stop_ap(struct wiphy *wiphy, struct net_device *dev)
c5c77ba1 1964{
e6e12661 1965 s32 s32Error = 0;
2726887c 1966 struct wilc_priv *priv;
cf60106b 1967 struct wilc_vif *vif;
63d03e47 1968 u8 NullBssid[ETH_ALEN] = {0};
c5c77ba1 1969
7ae43363
LK
1970 if (!wiphy)
1971 return -EFAULT;
c5c77ba1
JK
1972
1973 priv = wiphy_priv(wiphy);
cf60106b 1974 vif = netdev_priv(priv->dev);
c5c77ba1 1975
ba615f1e 1976 wilc_wlan_set_bssid(dev, NullBssid, AP_MODE);
c5c77ba1 1977
fbf5379b 1978 s32Error = wilc_del_beacon(vif);
c5c77ba1 1979
7dc1d0cc 1980 if (s32Error)
06fb9336 1981 netdev_err(dev, "Host delete beacon fail\n");
c5c77ba1 1982
c5c77ba1
JK
1983 return s32Error;
1984}
1985
ed26955c
CL
1986static int add_station(struct wiphy *wiphy, struct net_device *dev,
1987 const u8 *mac, struct station_parameters *params)
c5c77ba1 1988{
e6e12661 1989 s32 s32Error = 0;
2726887c 1990 struct wilc_priv *priv;
6a89ba9c 1991 struct add_sta_param strStaParams = { {0} };
a4cac481 1992 struct wilc_vif *vif;
c5c77ba1 1993
7ae43363
LK
1994 if (!wiphy)
1995 return -EFAULT;
c5c77ba1
JK
1996
1997 priv = wiphy_priv(wiphy);
a4cac481 1998 vif = netdev_priv(dev);
c5c77ba1 1999
a4cac481 2000 if (vif->iftype == AP_MODE || vif->iftype == GO_MODE) {
2353c388 2001 memcpy(strStaParams.bssid, mac, ETH_ALEN);
d00d2ba3 2002 memcpy(priv->assoc_stainfo.au8Sta_AssociatedBss[params->aid], mac, ETH_ALEN);
4101eb8a 2003 strStaParams.aid = params->aid;
e734223c 2004 strStaParams.rates_len = params->supported_rates_len;
a622e016 2005 strStaParams.rates = params->supported_rates;
c5c77ba1 2006
369a1d3b 2007 if (!params->ht_capa) {
22520120 2008 strStaParams.ht_supported = false;
c5c77ba1 2009 } else {
22520120 2010 strStaParams.ht_supported = true;
0d073f69 2011 strStaParams.ht_capa_info = params->ht_capa->cap_info;
fba1f2d2 2012 strStaParams.ht_ampdu_params = params->ht_capa->ampdu_params_info;
5ebbf4f7
LK
2013 memcpy(strStaParams.ht_supp_mcs_set,
2014 &params->ht_capa->mcs,
2015 WILC_SUPP_MCS_SET_SIZE);
223741d7 2016 strStaParams.ht_ext_params = params->ht_capa->extended_ht_cap_info;
74fe73cf 2017 strStaParams.ht_tx_bf_cap = params->ht_capa->tx_BF_cap_info;
a486baff 2018 strStaParams.ht_ante_sel = params->ht_capa->antenna_selection_info;
c5c77ba1
JK
2019 }
2020
f676e17a 2021 strStaParams.flags_mask = params->sta_flags_mask;
67ab64e4 2022 strStaParams.flags_set = params->sta_flags_set;
c5c77ba1 2023
fbf5379b 2024 s32Error = wilc_add_station(vif, &strStaParams);
7dc1d0cc 2025 if (s32Error)
06fb9336 2026 netdev_err(dev, "Host add station fail\n");
c5c77ba1
JK
2027 }
2028
c5c77ba1
JK
2029 return s32Error;
2030}
2031
a0a8be95
CL
2032static int del_station(struct wiphy *wiphy, struct net_device *dev,
2033 struct station_del_parameters *params)
c5c77ba1 2034{
057d1e97 2035 const u8 *mac = params->mac;
e6e12661 2036 s32 s32Error = 0;
2726887c 2037 struct wilc_priv *priv;
a4cac481 2038 struct wilc_vif *vif;
8dfaafd6 2039
7ae43363
LK
2040 if (!wiphy)
2041 return -EFAULT;
c5c77ba1
JK
2042
2043 priv = wiphy_priv(wiphy);
a4cac481 2044 vif = netdev_priv(dev);
c5c77ba1 2045
a4cac481 2046 if (vif->iftype == AP_MODE || vif->iftype == GO_MODE) {
a1b56a4c 2047 if (!mac)
fbf5379b
GL
2048 s32Error = wilc_del_allstation(vif,
2049 priv->assoc_stainfo.au8Sta_AssociatedBss);
c5c77ba1 2050
fbf5379b 2051 s32Error = wilc_del_station(vif, mac);
c5c77ba1 2052
7dc1d0cc 2053 if (s32Error)
06fb9336 2054 netdev_err(dev, "Host delete station fail\n");
c5c77ba1
JK
2055 }
2056 return s32Error;
2057}
2058
14b42084
CL
2059static int change_station(struct wiphy *wiphy, struct net_device *dev,
2060 const u8 *mac, struct station_parameters *params)
c5c77ba1 2061{
e6e12661 2062 s32 s32Error = 0;
2726887c 2063 struct wilc_priv *priv;
6a89ba9c 2064 struct add_sta_param strStaParams = { {0} };
a4cac481 2065 struct wilc_vif *vif;
c5c77ba1 2066
7ae43363
LK
2067 if (!wiphy)
2068 return -EFAULT;
c5c77ba1
JK
2069
2070 priv = wiphy_priv(wiphy);
a4cac481 2071 vif = netdev_priv(dev);
c5c77ba1 2072
a4cac481 2073 if (vif->iftype == AP_MODE || vif->iftype == GO_MODE) {
2353c388 2074 memcpy(strStaParams.bssid, mac, ETH_ALEN);
4101eb8a 2075 strStaParams.aid = params->aid;
e734223c 2076 strStaParams.rates_len = params->supported_rates_len;
a622e016 2077 strStaParams.rates = params->supported_rates;
c5c77ba1 2078
369a1d3b 2079 if (!params->ht_capa) {
22520120 2080 strStaParams.ht_supported = false;
c5c77ba1 2081 } else {
22520120 2082 strStaParams.ht_supported = true;
0d073f69 2083 strStaParams.ht_capa_info = params->ht_capa->cap_info;
fba1f2d2 2084 strStaParams.ht_ampdu_params = params->ht_capa->ampdu_params_info;
5ebbf4f7
LK
2085 memcpy(strStaParams.ht_supp_mcs_set,
2086 &params->ht_capa->mcs,
2087 WILC_SUPP_MCS_SET_SIZE);
223741d7 2088 strStaParams.ht_ext_params = params->ht_capa->extended_ht_cap_info;
74fe73cf 2089 strStaParams.ht_tx_bf_cap = params->ht_capa->tx_BF_cap_info;
a486baff 2090 strStaParams.ht_ante_sel = params->ht_capa->antenna_selection_info;
c5c77ba1
JK
2091 }
2092
f676e17a 2093 strStaParams.flags_mask = params->sta_flags_mask;
67ab64e4 2094 strStaParams.flags_set = params->sta_flags_set;
c5c77ba1 2095
fbf5379b 2096 s32Error = wilc_edit_station(vif, &strStaParams);
7dc1d0cc 2097 if (s32Error)
06fb9336 2098 netdev_err(dev, "Host edit station fail\n");
c5c77ba1
JK
2099 }
2100 return s32Error;
2101}
2102
37316e81
CL
2103static struct wireless_dev *add_virtual_intf(struct wiphy *wiphy,
2104 const char *name,
2105 unsigned char name_assign_type,
2106 enum nl80211_iftype type,
2107 u32 *flags,
2108 struct vif_params *params)
c5c77ba1 2109{
a4cac481 2110 struct wilc_vif *vif;
2726887c 2111 struct wilc_priv *priv;
c5c77ba1 2112 struct net_device *new_ifc = NULL;
8dfaafd6 2113
c5c77ba1 2114 priv = wiphy_priv(wiphy);
a4cac481 2115 vif = netdev_priv(priv->wdev->netdev);
c5c77ba1
JK
2116
2117
2118 if (type == NL80211_IFTYPE_MONITOR) {
1006b5c7 2119 new_ifc = WILC_WFI_init_mon_interface(name, vif->ndev);
369a1d3b 2120 if (new_ifc) {
a4cac481
GL
2121 vif = netdev_priv(priv->wdev->netdev);
2122 vif->monitor_flag = 1;
06fb9336 2123 }
c5c77ba1 2124 }
c5c77ba1 2125 return priv->wdev;
c5c77ba1
JK
2126}
2127
956d7211 2128static int del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev)
c5c77ba1 2129{
e6e12661 2130 return 0;
c5c77ba1
JK
2131}
2132
73584a40
GL
2133static int wilc_suspend(struct wiphy *wiphy, struct cfg80211_wowlan *wow)
2134{
2135 struct wilc_priv *priv = wiphy_priv(wiphy);
2136 struct wilc_vif *vif = netdev_priv(priv->dev);
2137
2138 if (!wow && wilc_wlan_get_num_conn_ifcs(vif->wilc))
2139 vif->wilc->suspend_event = true;
2140 else
2141 vif->wilc->suspend_event = false;
2142
2143 return 0;
2144}
2145
2146static int wilc_resume(struct wiphy *wiphy)
2147{
2148 struct wilc_priv *priv = wiphy_priv(wiphy);
2149 struct wilc_vif *vif = netdev_priv(priv->dev);
2150
2151 netdev_info(vif->ndev, "cfg resume\n");
2152 return 0;
2153}
2154
2155static void wilc_set_wakeup(struct wiphy *wiphy, bool enabled)
2156{
2157 struct wilc_priv *priv = wiphy_priv(wiphy);
2158 struct wilc_vif *vif = netdev_priv(priv->dev);
2159
2160 netdev_info(vif->ndev, "cfg set wake up = %d\n", enabled);
2161}
2162
70418790
GL
2163static int set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev,
2164 enum nl80211_tx_power_setting type, int mbm)
2165{
2166 int ret;
2167 s32 tx_power = MBM_TO_DBM(mbm);
2168 struct wilc_priv *priv = wiphy_priv(wiphy);
2169 struct wilc_vif *vif = netdev_priv(priv->dev);
2170
2171 if (tx_power < 0)
2172 tx_power = 0;
2173 else if (tx_power > 18)
2174 tx_power = 18;
2175 ret = wilc_set_tx_power(vif, tx_power);
2176 if (ret)
2177 netdev_err(vif->ndev, "Failed to set tx power\n");
2178
2179 return ret;
2180}
2181
2182static int get_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev,
2183 int *dbm)
2184{
2185 int ret;
2186 struct wilc_priv *priv = wiphy_priv(wiphy);
2187 struct wilc_vif *vif = netdev_priv(priv->dev);
8827bd88
LK
2188 struct wilc *wl;
2189
2190 wl = vif->wilc;
2191
2192 /* If firmware is not started, return. */
2193 if (!wl->initialized)
2194 return -EIO;
70418790
GL
2195
2196 ret = wilc_get_tx_power(vif, (u8 *)dbm);
2197 if (ret)
2198 netdev_err(vif->ndev, "Failed to get tx power\n");
2199
2200 return ret;
2201}
2202
08241924 2203static struct cfg80211_ops wilc_cfg80211_ops = {
80785a9a 2204 .set_monitor_channel = set_channel,
0e30d06d 2205 .scan = scan,
4ffbcdb6 2206 .connect = connect,
b027cde9 2207 .disconnect = disconnect,
953d417a 2208 .add_key = add_key,
3044ba7e 2209 .del_key = del_key,
f4893dfc 2210 .get_key = get_key,
0f5b8ca3 2211 .set_default_key = set_default_key,
69deb4c2 2212 .add_virtual_intf = add_virtual_intf,
b4a73355 2213 .del_virtual_intf = del_virtual_intf,
3615e9a3 2214 .change_virtual_intf = change_virtual_intf,
c5c77ba1 2215
a13168d7 2216 .start_ap = start_ap,
2a4c84d7 2217 .change_beacon = change_beacon,
c8cddd79 2218 .stop_ap = stop_ap,
ed26955c 2219 .add_station = add_station,
a0a8be95 2220 .del_station = del_station,
14b42084 2221 .change_station = change_station,
f06f562d 2222 .get_station = get_station,
bdb6338f 2223 .dump_station = dump_station,
a5f7db6a 2224 .change_bss = change_bss,
a76b63ef 2225 .set_wiphy_params = set_wiphy_params,
c5c77ba1 2226
4d46657a 2227 .set_pmksa = set_pmksa,
1ff86d96 2228 .del_pmksa = del_pmksa,
b33c39b1 2229 .flush_pmksa = flush_pmksa,
6d19d695 2230 .remain_on_channel = remain_on_channel,
1dd5440b 2231 .cancel_remain_on_channel = cancel_remain_on_channel,
4a2f9b38 2232 .mgmt_tx_cancel_wait = mgmt_tx_cancel_wait,
12a26a33 2233 .mgmt_tx = mgmt_tx,
8e0735c5 2234 .mgmt_frame_register = wilc_mgmt_frame_register,
46530679 2235 .set_power_mgmt = set_power_mgmt,
a8047e26 2236 .set_cqm_rssi_config = set_cqm_rssi_config,
c5c77ba1 2237
73584a40
GL
2238 .suspend = wilc_suspend,
2239 .resume = wilc_resume,
2240 .set_wakeup = wilc_set_wakeup,
70418790
GL
2241 .set_tx_power = set_tx_power,
2242 .get_tx_power = get_tx_power,
73584a40 2243
c5c77ba1
JK
2244};
2245
1608c403 2246static struct wireless_dev *WILC_WFI_CfgAlloc(void)
c5c77ba1 2247{
c5c77ba1
JK
2248 struct wireless_dev *wdev;
2249
c5c77ba1 2250 wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL);
06fb9336 2251 if (!wdev)
c5c77ba1 2252 goto _fail_;
c5c77ba1 2253
2726887c 2254 wdev->wiphy = wiphy_new(&wilc_cfg80211_ops, sizeof(struct wilc_priv));
06fb9336 2255 if (!wdev->wiphy)
c5c77ba1 2256 goto _fail_mem_;
c5c77ba1 2257
c5c77ba1
JK
2258 WILC_WFI_band_2ghz.ht_cap.ht_supported = 1;
2259 WILC_WFI_band_2ghz.ht_cap.cap |= (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT);
2260 WILC_WFI_band_2ghz.ht_cap.mcs.rx_mask[0] = 0xff;
2261 WILC_WFI_band_2ghz.ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_8K;
2262 WILC_WFI_band_2ghz.ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_NONE;
c5c77ba1 2263
57fbcce3 2264 wdev->wiphy->bands[NL80211_BAND_2GHZ] = &WILC_WFI_band_2ghz;
c5c77ba1
JK
2265
2266 return wdev;
2267
2268_fail_mem_:
2269 kfree(wdev);
2270_fail_:
2271 return NULL;
c5c77ba1 2272}
a89f7c55 2273
2e7d5377 2274struct wireless_dev *wilc_create_wiphy(struct net_device *net, struct device *dev)
c5c77ba1 2275{
2726887c 2276 struct wilc_priv *priv;
c5c77ba1 2277 struct wireless_dev *wdev;
e6e12661 2278 s32 s32Error = 0;
c5c77ba1 2279
c5c77ba1 2280 wdev = WILC_WFI_CfgAlloc();
369a1d3b 2281 if (!wdev) {
06fb9336 2282 netdev_err(net, "wiphy new allocate failed\n");
c5c77ba1
JK
2283 return NULL;
2284 }
2285
c5c77ba1 2286 priv = wdev_priv(wdev);
c5c77ba1 2287 priv->wdev = wdev;
c5c77ba1 2288 wdev->wiphy->max_scan_ssids = MAX_NUM_PROBED_SSID;
abb4f8ad 2289#ifdef CONFIG_PM
73584a40 2290 wdev->wiphy->wowlan = &wowlan_support;
abb4f8ad 2291#endif
c5c77ba1 2292 wdev->wiphy->max_num_pmkids = WILC_MAX_NUM_PMKIDS;
c5c77ba1 2293 wdev->wiphy->max_scan_ie_len = 1000;
c5c77ba1 2294 wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
c5c77ba1
JK
2295 wdev->wiphy->cipher_suites = cipher_suites;
2296 wdev->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
c5c77ba1 2297 wdev->wiphy->mgmt_stypes = wilc_wfi_cfg80211_mgmt_types;
c5c77ba1 2298
c5c77ba1 2299 wdev->wiphy->max_remain_on_channel_duration = 500;
c5c77ba1
JK
2300 wdev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_AP) | BIT(NL80211_IFTYPE_MONITOR) | BIT(NL80211_IFTYPE_P2P_GO) |
2301 BIT(NL80211_IFTYPE_P2P_CLIENT);
c5c77ba1 2302 wdev->wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
c5c77ba1
JK
2303 wdev->iftype = NL80211_IFTYPE_STATION;
2304
2e7d5377 2305 set_wiphy_dev(wdev->wiphy, dev);
c5c77ba1 2306
c5c77ba1 2307 s32Error = wiphy_register(wdev->wiphy);
06fb9336
LK
2308 if (s32Error)
2309 netdev_err(net, "Cannot register wiphy device\n");
c5c77ba1 2310
c5c77ba1 2311 priv->dev = net;
c5c77ba1 2312 return wdev;
c5c77ba1 2313}
a89f7c55 2314
dd4b6a83 2315int wilc_init_host_int(struct net_device *net)
c5c77ba1 2316{
1a8ccd85 2317 int s32Error = 0;
c5c77ba1 2318
2726887c 2319 struct wilc_priv *priv;
c5c77ba1 2320
c5c77ba1
JK
2321 priv = wdev_priv(net->ieee80211_ptr);
2322 if (op_ifcs == 0) {
93dee8ee 2323 setup_timer(&hAgingTimer, remove_network_from_shadow, 0);
0e1af73d 2324 setup_timer(&wilc_during_ip_timer, clear_duringIP, 0);
c5c77ba1
JK
2325 }
2326 op_ifcs++;
c5c77ba1 2327
72ed4dc7 2328 priv->gbAutoRateAdjusted = false;
c5c77ba1 2329
72ed4dc7 2330 priv->bInP2PlistenState = false;
c5c77ba1 2331
08662097 2332 mutex_init(&priv->scan_req_lock);
48b28df9 2333 s32Error = wilc_init(net, &priv->hif_drv);
f1fe9c43 2334 if (s32Error)
06fb9336 2335 netdev_err(net, "Error while initializing hostinterface\n");
f1fe9c43 2336
c5c77ba1
JK
2337 return s32Error;
2338}
2339
a9a16823 2340int wilc_deinit_host_int(struct net_device *net)
c5c77ba1 2341{
1a8ccd85 2342 int s32Error = 0;
cf60106b 2343 struct wilc_vif *vif;
2726887c 2344 struct wilc_priv *priv;
8dfaafd6 2345
c5c77ba1 2346 priv = wdev_priv(net->ieee80211_ptr);
cf60106b 2347 vif = netdev_priv(priv->dev);
c5c77ba1 2348
72ed4dc7 2349 priv->gbAutoRateAdjusted = false;
c5c77ba1 2350
72ed4dc7 2351 priv->bInP2PlistenState = false;
c5c77ba1
JK
2352
2353 op_ifcs--;
2354
fbf5379b 2355 s32Error = wilc_deinit(vif);
c5c77ba1 2356
d14991af 2357 clear_shadow_scan();
368949a7 2358 if (op_ifcs == 0)
0e1af73d 2359 del_timer_sync(&wilc_during_ip_timer);
c5c77ba1 2360
f1fe9c43 2361 if (s32Error)
06fb9336 2362 netdev_err(net, "Error while deintializing host interface\n");
f1fe9c43 2363
c5c77ba1
JK
2364 return s32Error;
2365}
2366
96da20a9 2367void wilc_free_wiphy(struct net_device *net)
c5c77ba1 2368{
d9766d52 2369 if (!net)
c5c77ba1 2370 return;
c5c77ba1 2371
d9766d52 2372 if (!net->ieee80211_ptr)
c5c77ba1 2373 return;
c5c77ba1 2374
d9766d52 2375 if (!net->ieee80211_ptr->wiphy)
c5c77ba1 2376 return;
c5c77ba1
JK
2377
2378 wiphy_unregister(net->ieee80211_ptr->wiphy);
2379
c5c77ba1
JK
2380 wiphy_free(net->ieee80211_ptr->wiphy);
2381 kfree(net->ieee80211_ptr);
c5c77ba1 2382}