staging: wilc1000: renames u8SsidLen of connect_resp_info structure
[linux-2.6-block.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) { \
105 .band = IEEE80211_BAND_2GHZ, \
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;
b84a3ac4 160static u8 p2p_recv_random = 0x00;
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++) {
f1ab117d
LK
197 if (last_scanned_shadow[last_scanned_cnt].pu8IEs) {
198 kfree(last_scanned_shadow[i].pu8IEs);
199 last_scanned_shadow[last_scanned_cnt].pu8IEs = NULL;
c5c77ba1
JK
200 }
201
a5f9943c 202 kfree(last_scanned_shadow[i].pJoinParams);
f1ab117d 203 last_scanned_shadow[i].pJoinParams = 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;
0b8bea1c 213 u8 num_rssi = (network_info->strRssi.u8Full) ? NUM_RSSI : (network_info->strRssi.u8Index);
c5c77ba1
JK
214
215 for (i = 0; i < num_rssi; i++)
0b8bea1c 216 rssi_v += network_info->strRssi.as8RSSI[i];
c5c77ba1
JK
217
218 rssi_v /= num_rssi;
219 return rssi_v;
220}
221
48ee7bad 222static void refresh_scan(void *user_void, u8 all, bool direct_scan)
c5c77ba1 223{
2726887c 224 struct wilc_priv *priv;
c5c77ba1
JK
225 struct wiphy *wiphy;
226 struct cfg80211_bss *bss = NULL;
227 int i;
228 int rssi = 0;
229
84df0e6d 230 priv = (struct wilc_priv *)user_void;
c5c77ba1
JK
231 wiphy = priv->dev->ieee80211_ptr->wiphy;
232
771fbae4 233 for (i = 0; i < last_scanned_cnt; i++) {
6b5180a0 234 struct network_info *network_info;
8dfaafd6 235
ce3b1b5a 236 network_info = &last_scanned_shadow[i];
c5c77ba1 237
ce3b1b5a 238 if (!network_info->u8Found || all) {
c6f5e3a6 239 s32 freq;
c5c77ba1
JK
240 struct ieee80211_channel *channel;
241
ce3b1b5a 242 if (network_info) {
c6f5e3a6
LK
243 freq = ieee80211_channel_to_frequency((s32)network_info->u8channel, IEEE80211_BAND_2GHZ);
244 channel = ieee80211_get_channel(wiphy, freq);
c5c77ba1 245
ce3b1b5a 246 rssi = get_rssi_avg(network_info);
2a3ff58a 247 if (memcmp("DIRECT-", network_info->ssid, 7) ||
48ee7bad 248 direct_scan) {
fa5e2d15
LK
249 bss = cfg80211_inform_bss(wiphy,
250 channel,
251 CFG80211_BSS_FTYPE_UNKNOWN,
252 network_info->au8bssid,
253 network_info->u64Tsf,
254 network_info->cap_info,
255 network_info->u16BeaconPeriod,
256 (const u8 *)network_info->pu8IEs,
257 (size_t)network_info->u16IEsLen,
258 (s32)rssi * 100,
259 GFP_KERNEL);
c5c77ba1 260 cfg80211_put_bss(wiphy, bss);
c5c77ba1
JK
261 }
262 }
c5c77ba1
JK
263 }
264 }
c5c77ba1
JK
265}
266
12b0138b 267static void reset_shadow_found(void)
c5c77ba1 268{
c5c77ba1 269 int i;
8dfaafd6 270
771fbae4 271 for (i = 0; i < last_scanned_cnt; i++)
f1ab117d 272 last_scanned_shadow[i].u8Found = 0;
c5c77ba1
JK
273}
274
5e51d8ba 275static void update_scan_time(void)
c5c77ba1 276{
c5c77ba1 277 int i;
8dfaafd6 278
771fbae4 279 for (i = 0; i < last_scanned_cnt; i++)
f1ab117d 280 last_scanned_shadow[i].u32TimeRcvdInScan = jiffies;
c5c77ba1
JK
281}
282
93dee8ee 283static void remove_network_from_shadow(unsigned long arg)
c5c77ba1 284{
c5c77ba1
JK
285 unsigned long now = jiffies;
286 int i, j;
287
c5c77ba1 288
771fbae4 289 for (i = 0; i < last_scanned_cnt; i++) {
f1ab117d 290 if (time_after(now, last_scanned_shadow[i].u32TimeRcvdInScan + (unsigned long)(SCAN_RESULT_EXPIRE))) {
2a3ff58a
LK
291 PRINT_D(CFG80211_DBG, "Network expired ScanShadow:%s\n",
292 last_scanned_shadow[i].ssid);
c5c77ba1 293
f1ab117d
LK
294 kfree(last_scanned_shadow[i].pu8IEs);
295 last_scanned_shadow[i].pu8IEs = NULL;
c5c77ba1 296
a5f9943c 297 kfree(last_scanned_shadow[i].pJoinParams);
c5c77ba1 298
771fbae4 299 for (j = i; (j < last_scanned_cnt - 1); j++)
f1ab117d 300 last_scanned_shadow[j] = last_scanned_shadow[j + 1];
771fbae4
LK
301
302 last_scanned_cnt--;
c5c77ba1
JK
303 }
304 }
305
771fbae4
LK
306 PRINT_D(CFG80211_DBG, "Number of cached networks: %d\n",
307 last_scanned_cnt);
308 if (last_scanned_cnt != 0) {
9eb06643
GKH
309 hAgingTimer.data = arg;
310 mod_timer(&hAgingTimer, jiffies + msecs_to_jiffies(AGING_TIME));
311 } else {
c5c77ba1 312 PRINT_D(CFG80211_DBG, "No need to restart Aging timer\n");
9eb06643 313 }
c5c77ba1
JK
314}
315
93dee8ee 316static void clear_duringIP(unsigned long arg)
c5c77ba1
JK
317{
318 PRINT_D(GENERIC_DBG, "GO:IP Obtained , enable scan\n");
0e1af73d 319 wilc_optaining_ip = false;
c5c77ba1 320}
c5c77ba1 321
6b5180a0 322static int is_network_in_shadow(struct network_info *pstrNetworkInfo,
157814f0 323 void *user_void)
c5c77ba1 324{
a74cc6b8 325 int state = -1;
c5c77ba1
JK
326 int i;
327
771fbae4 328 if (last_scanned_cnt == 0) {
c5c77ba1 329 PRINT_D(CFG80211_DBG, "Starting Aging timer\n");
157814f0 330 hAgingTimer.data = (unsigned long)user_void;
9eb06643 331 mod_timer(&hAgingTimer, jiffies + msecs_to_jiffies(AGING_TIME));
c5c77ba1
JK
332 state = -1;
333 } else {
771fbae4 334 for (i = 0; i < last_scanned_cnt; i++) {
f1ab117d
LK
335 if (memcmp(last_scanned_shadow[i].au8bssid,
336 pstrNetworkInfo->au8bssid, 6) == 0) {
c5c77ba1
JK
337 state = i;
338 break;
339 }
340 }
341 }
342 return state;
343}
344
6b5180a0 345static void add_network_to_shadow(struct network_info *pstrNetworkInfo,
5c4cf0dd 346 void *user_void, void *pJoinParams)
c5c77ba1 347{
5c4cf0dd 348 int ap_found = is_network_in_shadow(pstrNetworkInfo, user_void);
fbc2fe16 349 u32 ap_index = 0;
51e825f7 350 u8 rssi_index = 0;
c5c77ba1 351
771fbae4 352 if (last_scanned_cnt >= MAX_NUM_SCANNED_NETWORKS_SHADOW) {
c5c77ba1
JK
353 PRINT_D(CFG80211_DBG, "Shadow network reached its maximum limit\n");
354 return;
355 }
356 if (ap_found == -1) {
771fbae4
LK
357 ap_index = last_scanned_cnt;
358 last_scanned_cnt++;
c5c77ba1
JK
359 } else {
360 ap_index = ap_found;
361 }
f1ab117d 362 rssi_index = last_scanned_shadow[ap_index].strRssi.u8Index;
5c23a291 363 last_scanned_shadow[ap_index].strRssi.as8RSSI[rssi_index++] = pstrNetworkInfo->rssi;
c5c77ba1
JK
364 if (rssi_index == NUM_RSSI) {
365 rssi_index = 0;
f1ab117d 366 last_scanned_shadow[ap_index].strRssi.u8Full = 1;
c5c77ba1 367 }
f1ab117d 368 last_scanned_shadow[ap_index].strRssi.u8Index = rssi_index;
5c23a291 369 last_scanned_shadow[ap_index].rssi = pstrNetworkInfo->rssi;
fa5e2d15 370 last_scanned_shadow[ap_index].cap_info = pstrNetworkInfo->cap_info;
a36e89e9 371 last_scanned_shadow[ap_index].ssid_len = pstrNetworkInfo->ssid_len;
2a3ff58a 372 memcpy(last_scanned_shadow[ap_index].ssid,
a36e89e9 373 pstrNetworkInfo->ssid, pstrNetworkInfo->ssid_len);
f1ab117d
LK
374 memcpy(last_scanned_shadow[ap_index].au8bssid,
375 pstrNetworkInfo->au8bssid, ETH_ALEN);
376 last_scanned_shadow[ap_index].u16BeaconPeriod = pstrNetworkInfo->u16BeaconPeriod;
377 last_scanned_shadow[ap_index].u8DtimPeriod = pstrNetworkInfo->u8DtimPeriod;
378 last_scanned_shadow[ap_index].u8channel = pstrNetworkInfo->u8channel;
379 last_scanned_shadow[ap_index].u16IEsLen = pstrNetworkInfo->u16IEsLen;
380 last_scanned_shadow[ap_index].u64Tsf = pstrNetworkInfo->u64Tsf;
c5c77ba1 381 if (ap_found != -1)
f1ab117d
LK
382 kfree(last_scanned_shadow[ap_index].pu8IEs);
383 last_scanned_shadow[ap_index].pu8IEs =
a89f7c55 384 kmalloc(pstrNetworkInfo->u16IEsLen, GFP_KERNEL);
f1ab117d
LK
385 memcpy(last_scanned_shadow[ap_index].pu8IEs,
386 pstrNetworkInfo->pu8IEs, pstrNetworkInfo->u16IEsLen);
387 last_scanned_shadow[ap_index].u32TimeRcvdInScan = jiffies;
388 last_scanned_shadow[ap_index].u32TimeRcvdInScanCached = jiffies;
389 last_scanned_shadow[ap_index].u8Found = 1;
c5c77ba1 390 if (ap_found != -1)
a5f9943c 391 kfree(last_scanned_shadow[ap_index].pJoinParams);
f1ab117d 392 last_scanned_shadow[ap_index].pJoinParams = pJoinParams;
c5c77ba1
JK
393}
394
1a4c8ce7 395static void CfgScanResult(enum scan_event scan_event,
6b5180a0 396 struct network_info *network_info,
30cd10c4 397 void *user_void,
bdd3460f 398 void *join_params)
c5c77ba1 399{
2726887c 400 struct wilc_priv *priv;
c5c77ba1 401 struct wiphy *wiphy;
fb4ec9ca 402 s32 s32Freq;
c5c77ba1 403 struct ieee80211_channel *channel;
c5c77ba1
JK
404 struct cfg80211_bss *bss = NULL;
405
30cd10c4 406 priv = (struct wilc_priv *)user_void;
7e4e87d3 407 if (priv->bCfgScanning) {
1a4c8ce7 408 if (scan_event == SCAN_EVENT_NETWORK_FOUND) {
c5c77ba1 409 wiphy = priv->dev->ieee80211_ptr->wiphy;
7ae43363
LK
410
411 if (!wiphy)
412 return;
413
0551a72e 414 if (wiphy->signal_type == CFG80211_SIGNAL_TYPE_UNSPEC &&
5c23a291
LK
415 (((s32)network_info->rssi * 100) < 0 ||
416 ((s32)network_info->rssi * 100) > 100))
24db713f 417 return;
c5c77ba1 418
0551a72e
LK
419 if (network_info) {
420 s32Freq = ieee80211_channel_to_frequency((s32)network_info->u8channel, IEEE80211_BAND_2GHZ);
c5c77ba1
JK
421 channel = ieee80211_get_channel(wiphy, s32Freq);
422
7ae43363
LK
423 if (!channel)
424 return;
c5c77ba1 425
fa5e2d15
LK
426 PRINT_INFO(CFG80211_DBG, "Network Info::"
427 "CHANNEL Frequency: %d,"
428 "RSSI: %d,"
429 "Capability Info: %d,"
430 "Beacon Period: %d\n",
431 channel->center_freq,
432 (s32)network_info->rssi * 100,
433 network_info->cap_info,
434 network_info->u16BeaconPeriod);
c5c77ba1 435
0551a72e 436 if (network_info->bNewNetwork) {
a89f7c55 437 if (priv->u32RcvdChCount < MAX_NUM_SCANNED_NETWORKS) {
2a3ff58a
LK
438 PRINT_D(CFG80211_DBG,
439 "Network %s found\n",
440 network_info->ssid);
c5c77ba1
JK
441 priv->u32RcvdChCount++;
442
bdd3460f 443 add_network_to_shadow(network_info, priv, join_params);
c5c77ba1 444
2a3ff58a 445 if (!(memcmp("DIRECT-", network_info->ssid, 7))) {
fa5e2d15
LK
446 bss = cfg80211_inform_bss(wiphy,
447 channel,
448 CFG80211_BSS_FTYPE_UNKNOWN,
449 network_info->au8bssid,
450 network_info->u64Tsf,
451 network_info->cap_info,
452 network_info->u16BeaconPeriod,
453 (const u8 *)network_info->pu8IEs,
454 (size_t)network_info->u16IEsLen,
455 (s32)network_info->rssi * 100,
456 GFP_KERNEL);
c5c77ba1 457 cfg80211_put_bss(wiphy, bss);
c5c77ba1 458 }
c5c77ba1
JK
459 }
460 } else {
4e4467fd 461 u32 i;
a89f7c55 462
c5c77ba1 463 for (i = 0; i < priv->u32RcvdChCount; i++) {
0551a72e 464 if (memcmp(last_scanned_shadow[i].au8bssid, network_info->au8bssid, 6) == 0) {
2a3ff58a 465 PRINT_D(CFG80211_DBG, "Update RSSI of %s\n", last_scanned_shadow[i].ssid);
c5c77ba1 466
5c23a291 467 last_scanned_shadow[i].rssi = network_info->rssi;
f1ab117d 468 last_scanned_shadow[i].u32TimeRcvdInScan = jiffies;
c5c77ba1
JK
469 break;
470 }
471 }
472 }
473 }
1a4c8ce7 474 } else if (scan_event == SCAN_EVENT_DONE) {
17aacd43
CG
475 PRINT_D(CFG80211_DBG, "Scan Done[%p]\n", priv->dev);
476 PRINT_D(CFG80211_DBG, "Refreshing Scan ...\n");
72ed4dc7 477 refresh_scan(priv, 1, false);
c5c77ba1 478
78174ada 479 if (priv->u32RcvdChCount > 0)
17aacd43 480 PRINT_D(CFG80211_DBG, "%d Network(s) found\n", priv->u32RcvdChCount);
78174ada 481 else
17aacd43 482 PRINT_D(CFG80211_DBG, "No networks found\n");
c5c77ba1 483
83383ea3 484 down(&(priv->hSemScanReq));
c5c77ba1 485
369a1d3b 486 if (priv->pstrScanReq) {
72ed4dc7 487 cfg80211_scan_done(priv->pstrScanReq, false);
c5c77ba1 488 priv->u32RcvdChCount = 0;
72ed4dc7 489 priv->bCfgScanning = false;
b1413b60 490 priv->pstrScanReq = NULL;
c5c77ba1 491 }
83383ea3 492 up(&(priv->hSemScanReq));
1a4c8ce7 493 } else if (scan_event == SCAN_EVENT_ABORTED) {
83383ea3 494 down(&(priv->hSemScanReq));
c5c77ba1 495
17aacd43 496 PRINT_D(CFG80211_DBG, "Scan Aborted\n");
369a1d3b 497 if (priv->pstrScanReq) {
5e51d8ba 498 update_scan_time();
72ed4dc7 499 refresh_scan(priv, 1, false);
c5c77ba1 500
72ed4dc7
DL
501 cfg80211_scan_done(priv->pstrScanReq, false);
502 priv->bCfgScanning = false;
b1413b60 503 priv->pstrScanReq = NULL;
c5c77ba1 504 }
83383ea3 505 up(&(priv->hSemScanReq));
c5c77ba1
JK
506 }
507 }
c5c77ba1
JK
508}
509
0e1af73d 510int wilc_connecting;
c5c77ba1 511
ed3f0379 512static void CfgConnectResult(enum conn_event enuConnDisconnEvent,
c5c77ba1 513 tstrConnectInfo *pstrConnectInfo,
63d03e47 514 u8 u8MacStatus,
c5c77ba1
JK
515 tstrDisconnectNotifInfo *pstrDisconnectNotifInfo,
516 void *pUserVoid)
517{
2726887c 518 struct wilc_priv *priv;
c5c77ba1 519 struct net_device *dev;
441dc609 520 struct host_if_drv *pstrWFIDrv;
63d03e47 521 u8 NullBssid[ETH_ALEN] = {0};
c1ec2c12 522 struct wilc *wl;
a4cac481 523 struct wilc_vif *vif;
8dfaafd6 524
0e1af73d 525 wilc_connecting = 0;
c5c77ba1 526
2726887c 527 priv = (struct wilc_priv *)pUserVoid;
c5c77ba1 528 dev = priv->dev;
a4cac481
GL
529 vif = netdev_priv(dev);
530 wl = vif->wilc;
48b28df9 531 pstrWFIDrv = (struct host_if_drv *)priv->hif_drv;
c5c77ba1
JK
532
533 if (enuConnDisconnEvent == CONN_DISCONN_EVENT_CONN_RESP) {
baba7c74 534 u16 u16ConnectStatus;
c5c77ba1
JK
535
536 u16ConnectStatus = pstrConnectInfo->u16ConnectStatus;
537
538 PRINT_D(CFG80211_DBG, " Connection response received = %d\n", u8MacStatus);
539
540 if ((u8MacStatus == MAC_DISCONNECTED) &&
541 (pstrConnectInfo->u16ConnectStatus == SUCCESSFUL_STATUSCODE)) {
c5c77ba1 542 u16ConnectStatus = WLAN_STATUS_UNSPECIFIED_FAILURE;
ba615f1e
GL
543 wilc_wlan_set_bssid(priv->dev, NullBssid,
544 STATION_MODE);
e554a305 545 eth_zero_addr(wilc_connected_ssid);
c5c77ba1 546
ab16ec0b 547 if (!pstrWFIDrv->p2p_connect)
0bd8274f 548 wlan_channel = INVALID_CHANNEL;
c5c77ba1 549
06fb9336 550 netdev_err(dev, "Unspecified failure\n");
c5c77ba1
JK
551 }
552
553 if (u16ConnectStatus == WLAN_STATUS_SUCCESS) {
72ed4dc7 554 bool bNeedScanRefresh = false;
4e4467fd 555 u32 i;
c5c77ba1
JK
556
557 PRINT_INFO(CFG80211_DBG, "Connection Successful:: BSSID: %x%x%x%x%x%x\n", pstrConnectInfo->au8bssid[0],
558 pstrConnectInfo->au8bssid[1], pstrConnectInfo->au8bssid[2], pstrConnectInfo->au8bssid[3], pstrConnectInfo->au8bssid[4], pstrConnectInfo->au8bssid[5]);
d00d2ba3 559 memcpy(priv->au8AssociatedBss, pstrConnectInfo->au8bssid, ETH_ALEN);
c5c77ba1 560
c5c77ba1 561
771fbae4 562 for (i = 0; i < last_scanned_cnt; i++) {
f1ab117d
LK
563 if (memcmp(last_scanned_shadow[i].au8bssid,
564 pstrConnectInfo->au8bssid, ETH_ALEN) == 0) {
c5c77ba1
JK
565 unsigned long now = jiffies;
566
567 if (time_after(now,
f1ab117d 568 last_scanned_shadow[i].u32TimeRcvdInScanCached + (unsigned long)(nl80211_SCAN_RESULT_EXPIRE - (1 * HZ)))) {
72ed4dc7 569 bNeedScanRefresh = true;
c5c77ba1
JK
570 }
571
572 break;
573 }
574 }
575
a89f7c55 576 if (bNeedScanRefresh)
72ed4dc7 577 refresh_scan(priv, 1, true);
c5c77ba1
JK
578 }
579
580
52db7520 581 PRINT_D(CFG80211_DBG, "Association request info elements length = %zu\n", pstrConnectInfo->ReqIEsLen);
c5c77ba1
JK
582
583 PRINT_D(CFG80211_DBG, "Association response info elements length = %d\n", pstrConnectInfo->u16RespIEsLen);
584
585 cfg80211_connect_result(dev, pstrConnectInfo->au8bssid,
586 pstrConnectInfo->pu8ReqIEs, pstrConnectInfo->ReqIEsLen,
587 pstrConnectInfo->pu8RespIEs, pstrConnectInfo->u16RespIEsLen,
a89f7c55 588 u16ConnectStatus, GFP_KERNEL);
c5c77ba1 589 } else if (enuConnDisconnEvent == CONN_DISCONN_EVENT_DISCONN_NOTIF) {
0e1af73d 590 wilc_optaining_ip = false;
583d972c 591 p2p_local_random = 0x01;
b84a3ac4 592 p2p_recv_random = 0x00;
a25d5186 593 wilc_ie = false;
bcf02653 594 eth_zero_addr(priv->au8AssociatedBss);
ba615f1e 595 wilc_wlan_set_bssid(priv->dev, NullBssid, STATION_MODE);
e554a305 596 eth_zero_addr(wilc_connected_ssid);
c5c77ba1 597
ab16ec0b 598 if (!pstrWFIDrv->p2p_connect)
0bd8274f 599 wlan_channel = INVALID_CHANNEL;
1f435d2e 600 if ((pstrWFIDrv->IFC_UP) && (dev == wl->vif[1]->ndev)) {
c5c77ba1 601 pstrDisconnectNotifInfo->u16reason = 3;
1f435d2e 602 } else if ((!pstrWFIDrv->IFC_UP) && (dev == wl->vif[1]->ndev)) {
c5c77ba1
JK
603 pstrDisconnectNotifInfo->u16reason = 1;
604 }
605 cfg80211_disconnected(dev, pstrDisconnectNotifInfo->u16reason, pstrDisconnectNotifInfo->ie,
e26bb71d
SM
606 pstrDisconnectNotifInfo->ie_len, false,
607 GFP_KERNEL);
c5c77ba1 608 }
c5c77ba1
JK
609}
610
80785a9a
CL
611static int set_channel(struct wiphy *wiphy,
612 struct cfg80211_chan_def *chandef)
c5c77ba1 613{
4e4467fd 614 u32 channelnum = 0;
2726887c 615 struct wilc_priv *priv;
dd739ea5 616 int result = 0;
cf60106b 617 struct wilc_vif *vif;
8dfaafd6 618
c5c77ba1 619 priv = wiphy_priv(wiphy);
cf60106b 620 vif = netdev_priv(priv->dev);
c5c77ba1 621
c5c77ba1
JK
622 channelnum = ieee80211_frequency_to_channel(chandef->chan->center_freq);
623 PRINT_D(CFG80211_DBG, "Setting channel %d with frequency %d\n", channelnum, chandef->chan->center_freq);
c5c77ba1 624
866a2c24 625 curr_channel = channelnum;
fbf5379b 626 result = wilc_set_mac_chnl_num(vif, channelnum);
c5c77ba1 627
dd739ea5 628 if (result != 0)
06fb9336 629 netdev_err(priv->dev, "Error in setting channel\n");
c5c77ba1 630
dd739ea5 631 return result;
c5c77ba1
JK
632}
633
0e30d06d 634static int scan(struct wiphy *wiphy, struct cfg80211_scan_request *request)
c5c77ba1 635{
2726887c 636 struct wilc_priv *priv;
4e4467fd 637 u32 i;
e6e12661 638 s32 s32Error = 0;
63d03e47 639 u8 au8ScanChanList[MAX_NUM_SCANNED_NETWORKS];
607db447 640 struct hidden_network strHiddenNetwork;
cf60106b 641 struct wilc_vif *vif;
c5c77ba1
JK
642
643 priv = wiphy_priv(wiphy);
cf60106b 644 vif = netdev_priv(priv->dev);
c5c77ba1 645
c5c77ba1
JK
646 priv->pstrScanReq = request;
647
648 priv->u32RcvdChCount = 0;
649
12b0138b 650 reset_shadow_found();
c5c77ba1 651
72ed4dc7 652 priv->bCfgScanning = true;
a89f7c55 653 if (request->n_channels <= MAX_NUM_SCANNED_NETWORKS) {
c5c77ba1 654 for (i = 0; i < request->n_channels; i++) {
63d03e47 655 au8ScanChanList[i] = (u8)ieee80211_frequency_to_channel(request->channels[i]->center_freq);
c5c77ba1
JK
656 PRINT_INFO(CFG80211_DBG, "ScanChannel List[%d] = %d,", i, au8ScanChanList[i]);
657 }
658
659 PRINT_D(CFG80211_DBG, "Requested num of scan channel %d\n", request->n_channels);
52db7520 660 PRINT_D(CFG80211_DBG, "Scan Request IE len = %zu\n", request->ie_len);
c5c77ba1
JK
661
662 PRINT_D(CFG80211_DBG, "Number of SSIDs %d\n", request->n_ssids);
663
664 if (request->n_ssids >= 1) {
245a1865 665 strHiddenNetwork.net_info = kmalloc(request->n_ssids * sizeof(struct hidden_network), GFP_KERNEL);
40e05e86 666 strHiddenNetwork.n_ssids = request->n_ssids;
c5c77ba1
JK
667
668
c5c77ba1 669 for (i = 0; i < request->n_ssids; i++) {
369a1d3b
LK
670 if (request->ssids[i].ssid &&
671 request->ssids[i].ssid_len != 0) {
245a1865
CL
672 strHiddenNetwork.net_info[i].ssid = kmalloc(request->ssids[i].ssid_len, GFP_KERNEL);
673 memcpy(strHiddenNetwork.net_info[i].ssid, request->ssids[i].ssid, request->ssids[i].ssid_len);
674 strHiddenNetwork.net_info[i].ssid_len = request->ssids[i].ssid_len;
c5c77ba1 675 } else {
17aacd43 676 PRINT_D(CFG80211_DBG, "Received one NULL SSID\n");
40e05e86 677 strHiddenNetwork.n_ssids -= 1;
c5c77ba1
JK
678 }
679 }
17aacd43 680 PRINT_D(CFG80211_DBG, "Trigger Scan Request\n");
fbf5379b
GL
681 s32Error = wilc_scan(vif, USER_SCAN, ACTIVE_SCAN,
682 au8ScanChanList,
683 request->n_channels,
684 (const u8 *)request->ie,
685 request->ie_len, CfgScanResult,
686 (void *)priv, &strHiddenNetwork);
c5c77ba1 687 } else {
17aacd43 688 PRINT_D(CFG80211_DBG, "Trigger Scan Request\n");
fbf5379b
GL
689 s32Error = wilc_scan(vif, USER_SCAN, ACTIVE_SCAN,
690 au8ScanChanList,
691 request->n_channels,
692 (const u8 *)request->ie,
693 request->ie_len, CfgScanResult,
694 (void *)priv, NULL);
c5c77ba1 695 }
c5c77ba1 696 } else {
06fb9336 697 netdev_err(priv->dev, "Requested scanned channels over\n");
c5c77ba1
JK
698 }
699
e6e12661 700 if (s32Error != 0) {
c5c77ba1
JK
701 s32Error = -EBUSY;
702 PRINT_WRN(CFG80211_DBG, "Device is busy: Error(%d)\n", s32Error);
703 }
704
705 return s32Error;
706}
707
4ffbcdb6
CL
708static int connect(struct wiphy *wiphy, struct net_device *dev,
709 struct cfg80211_connect_params *sme)
c5c77ba1 710{
e6e12661 711 s32 s32Error = 0;
4e4467fd 712 u32 i;
63d03e47 713 u8 u8security = NO_ENCRYPT;
841dfc42 714 enum AUTHTYPE tenuAuth_type = ANY;
576917ad
DL
715 char *pcgroup_encrypt_val = NULL;
716 char *pccipher_group = NULL;
717 char *pcwpa_version = NULL;
c5c77ba1 718
2726887c 719 struct wilc_priv *priv;
441dc609 720 struct host_if_drv *pstrWFIDrv;
6b5180a0 721 struct network_info *pstrNetworkInfo = NULL;
cf60106b 722 struct wilc_vif *vif;
c5c77ba1 723
0e1af73d 724 wilc_connecting = 1;
c5c77ba1 725 priv = wiphy_priv(wiphy);
cf60106b 726 vif = netdev_priv(priv->dev);
48b28df9 727 pstrWFIDrv = (struct host_if_drv *)priv->hif_drv;
c5c77ba1 728
48b28df9
LK
729 PRINT_D(CFG80211_DBG,
730 "Connecting to SSID [%s] on netdev [%p] host if [%p]\n",
731 sme->ssid, dev, priv->hif_drv);
3f882895 732 if (!(strncmp(sme->ssid, "DIRECT-", 7))) {
c5c77ba1 733 PRINT_D(CFG80211_DBG, "Connected to Direct network,OBSS disabled\n");
ab16ec0b
LK
734 pstrWFIDrv->p2p_connect = 1;
735 } else {
736 pstrWFIDrv->p2p_connect = 0;
737 }
17aacd43 738 PRINT_INFO(CFG80211_DBG, "Required SSID = %s\n , AuthType = %d\n", sme->ssid, sme->auth_type);
c5c77ba1 739
771fbae4 740 for (i = 0; i < last_scanned_cnt; i++) {
a36e89e9 741 if ((sme->ssid_len == last_scanned_shadow[i].ssid_len) &&
2a3ff58a 742 memcmp(last_scanned_shadow[i].ssid,
f1ab117d
LK
743 sme->ssid,
744 sme->ssid_len) == 0) {
c5c77ba1 745 PRINT_INFO(CFG80211_DBG, "Network with required SSID is found %s\n", sme->ssid);
369a1d3b 746 if (!sme->bssid) {
c5c77ba1
JK
747 PRINT_INFO(CFG80211_DBG, "BSSID is not passed from the user\n");
748 break;
749 } else {
f1ab117d
LK
750 if (memcmp(last_scanned_shadow[i].au8bssid,
751 sme->bssid,
752 ETH_ALEN) == 0) {
c5c77ba1
JK
753 PRINT_INFO(CFG80211_DBG, "BSSID is passed from the user and matched\n");
754 break;
755 }
756 }
757 }
758 }
759
771fbae4 760 if (i < last_scanned_cnt) {
c5c77ba1
JK
761 PRINT_D(CFG80211_DBG, "Required bss is in scan results\n");
762
f1ab117d 763 pstrNetworkInfo = &last_scanned_shadow[i];
c5c77ba1
JK
764
765 PRINT_INFO(CFG80211_DBG, "network BSSID to be associated: %x%x%x%x%x%x\n",
766 pstrNetworkInfo->au8bssid[0], pstrNetworkInfo->au8bssid[1],
767 pstrNetworkInfo->au8bssid[2], pstrNetworkInfo->au8bssid[3],
768 pstrNetworkInfo->au8bssid[4], pstrNetworkInfo->au8bssid[5]);
769 } else {
770 s32Error = -ENOENT;
771fbae4 771 if (last_scanned_cnt == 0)
c5c77ba1
JK
772 PRINT_D(CFG80211_DBG, "No Scan results yet\n");
773 else
774 PRINT_D(CFG80211_DBG, "Required bss not in scan results: Error(%d)\n", s32Error);
430e640d
GL
775 wilc_connecting = 0;
776 return s32Error;
c5c77ba1
JK
777 }
778
2cc46837
CL
779 memset(priv->WILC_WFI_wep_key, 0, sizeof(priv->WILC_WFI_wep_key));
780 memset(priv->WILC_WFI_wep_key_len, 0, sizeof(priv->WILC_WFI_wep_key_len));
c5c77ba1
JK
781
782 PRINT_INFO(CFG80211_DBG, "sme->crypto.wpa_versions=%x\n", sme->crypto.wpa_versions);
783 PRINT_INFO(CFG80211_DBG, "sme->crypto.cipher_group=%x\n", sme->crypto.cipher_group);
784
785 PRINT_INFO(CFG80211_DBG, "sme->crypto.n_ciphers_pairwise=%d\n", sme->crypto.n_ciphers_pairwise);
786
c5c77ba1 787 if (sme->crypto.cipher_group != NO_ENCRYPT) {
c5c77ba1 788 pcwpa_version = "Default";
c5c77ba1 789 if (sme->crypto.cipher_group == WLAN_CIPHER_SUITE_WEP40) {
c5c77ba1
JK
790 u8security = ENCRYPT_ENABLED | WEP;
791 pcgroup_encrypt_val = "WEP40";
792 pccipher_group = "WLAN_CIPHER_SUITE_WEP40";
793 PRINT_INFO(CFG80211_DBG, "WEP Default Key Idx = %d\n", sme->key_idx);
794
c5c77ba1 795 priv->WILC_WFI_wep_key_len[sme->key_idx] = sme->key_len;
d00d2ba3 796 memcpy(priv->WILC_WFI_wep_key[sme->key_idx], sme->key, sme->key_len);
c5c77ba1 797
c5c77ba1 798 g_key_wep_params.key_len = sme->key_len;
f3052587 799 g_key_wep_params.key = kmalloc(sme->key_len, GFP_KERNEL);
c5c77ba1
JK
800 memcpy(g_key_wep_params.key, sme->key, sme->key_len);
801 g_key_wep_params.key_idx = sme->key_idx;
72ed4dc7 802 g_wep_keys_saved = true;
c5c77ba1 803
fbf5379b
GL
804 wilc_set_wep_default_keyid(vif, sme->key_idx);
805 wilc_add_wep_key_bss_sta(vif, sme->key, sme->key_len,
806 sme->key_idx);
c5c77ba1 807 } else if (sme->crypto.cipher_group == WLAN_CIPHER_SUITE_WEP104) {
c5c77ba1
JK
808 u8security = ENCRYPT_ENABLED | WEP | WEP_EXTENDED;
809 pcgroup_encrypt_val = "WEP104";
810 pccipher_group = "WLAN_CIPHER_SUITE_WEP104";
811
c5c77ba1 812 priv->WILC_WFI_wep_key_len[sme->key_idx] = sme->key_len;
d00d2ba3 813 memcpy(priv->WILC_WFI_wep_key[sme->key_idx], sme->key, sme->key_len);
c5c77ba1 814
c5c77ba1 815 g_key_wep_params.key_len = sme->key_len;
f3052587 816 g_key_wep_params.key = kmalloc(sme->key_len, GFP_KERNEL);
c5c77ba1
JK
817 memcpy(g_key_wep_params.key, sme->key, sme->key_len);
818 g_key_wep_params.key_idx = sme->key_idx;
72ed4dc7 819 g_wep_keys_saved = true;
c5c77ba1 820
fbf5379b
GL
821 wilc_set_wep_default_keyid(vif, sme->key_idx);
822 wilc_add_wep_key_bss_sta(vif, sme->key, sme->key_len,
823 sme->key_idx);
c5c77ba1 824 } else if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_2) {
c5c77ba1 825 if (sme->crypto.cipher_group == WLAN_CIPHER_SUITE_TKIP) {
c5c77ba1
JK
826 u8security = ENCRYPT_ENABLED | WPA2 | TKIP;
827 pcgroup_encrypt_val = "WPA2_TKIP";
828 pccipher_group = "TKIP";
a89f7c55 829 } else {
c5c77ba1
JK
830 u8security = ENCRYPT_ENABLED | WPA2 | AES;
831 pcgroup_encrypt_val = "WPA2_AES";
832 pccipher_group = "AES";
833 }
834 pcwpa_version = "WPA_VERSION_2";
835 } else if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_1) {
836 if (sme->crypto.cipher_group == WLAN_CIPHER_SUITE_TKIP) {
c5c77ba1
JK
837 u8security = ENCRYPT_ENABLED | WPA | TKIP;
838 pcgroup_encrypt_val = "WPA_TKIP";
839 pccipher_group = "TKIP";
a89f7c55 840 } else {
c5c77ba1
JK
841 u8security = ENCRYPT_ENABLED | WPA | AES;
842 pcgroup_encrypt_val = "WPA_AES";
843 pccipher_group = "AES";
c5c77ba1
JK
844 }
845 pcwpa_version = "WPA_VERSION_1";
846
c5c77ba1
JK
847 } else {
848 s32Error = -ENOTSUPP;
06fb9336 849 netdev_err(dev, "Not supported cipher\n");
430e640d
GL
850 wilc_connecting = 0;
851 return s32Error;
c5c77ba1 852 }
c5c77ba1
JK
853 }
854
c5c77ba1
JK
855 if ((sme->crypto.wpa_versions & NL80211_WPA_VERSION_1)
856 || (sme->crypto.wpa_versions & NL80211_WPA_VERSION_2)) {
857 for (i = 0; i < sme->crypto.n_ciphers_pairwise; i++) {
858 if (sme->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_TKIP) {
859 u8security = u8security | TKIP;
a89f7c55 860 } else {
c5c77ba1
JK
861 u8security = u8security | AES;
862 }
863 }
864 }
865
866 PRINT_D(CFG80211_DBG, "Adding key with cipher group = %x\n", sme->crypto.cipher_group);
867
868 PRINT_D(CFG80211_DBG, "Authentication Type = %d\n", sme->auth_type);
869 switch (sme->auth_type) {
870 case NL80211_AUTHTYPE_OPEN_SYSTEM:
871 PRINT_D(CFG80211_DBG, "In OPEN SYSTEM\n");
872 tenuAuth_type = OPEN_SYSTEM;
873 break;
874
875 case NL80211_AUTHTYPE_SHARED_KEY:
876 tenuAuth_type = SHARED_KEY;
877 PRINT_D(CFG80211_DBG, "In SHARED KEY\n");
878 break;
879
880 default:
881 PRINT_D(CFG80211_DBG, "Automatic Authentation type = %d\n", sme->auth_type);
882 }
883
c5c77ba1
JK
884 if (sme->crypto.n_akm_suites) {
885 switch (sme->crypto.akm_suites[0]) {
886 case WLAN_AKM_SUITE_8021X:
887 tenuAuth_type = IEEE8021;
888 break;
889
890 default:
891 break;
892 }
893 }
894
895
896 PRINT_INFO(CFG80211_DBG, "Required Channel = %d\n", pstrNetworkInfo->u8channel);
897
898 PRINT_INFO(CFG80211_DBG, "Group encryption value = %s\n Cipher Group = %s\n WPA version = %s\n",
899 pcgroup_encrypt_val, pccipher_group, pcwpa_version);
900
866a2c24 901 curr_channel = pstrNetworkInfo->u8channel;
c5c77ba1 902
ab16ec0b 903 if (!pstrWFIDrv->p2p_connect)
0bd8274f 904 wlan_channel = pstrNetworkInfo->u8channel;
c5c77ba1 905
ba615f1e 906 wilc_wlan_set_bssid(dev, pstrNetworkInfo->au8bssid, STATION_MODE);
c5c77ba1 907
fbf5379b
GL
908 s32Error = wilc_set_join_req(vif, pstrNetworkInfo->au8bssid, sme->ssid,
909 sme->ssid_len, sme->ie, sme->ie_len,
910 CfgConnectResult, (void *)priv,
911 u8security, tenuAuth_type,
912 pstrNetworkInfo->u8channel,
913 pstrNetworkInfo->pJoinParams);
e6e12661 914 if (s32Error != 0) {
06fb9336 915 netdev_err(dev, "wilc_set_join_req(): Error\n");
c5c77ba1 916 s32Error = -ENOENT;
430e640d
GL
917 wilc_connecting = 0;
918 return s32Error;
c5c77ba1
JK
919 }
920
c5c77ba1
JK
921 return s32Error;
922}
923
b027cde9 924static int disconnect(struct wiphy *wiphy, struct net_device *dev, u16 reason_code)
c5c77ba1 925{
e6e12661 926 s32 s32Error = 0;
2726887c 927 struct wilc_priv *priv;
441dc609 928 struct host_if_drv *pstrWFIDrv;
cf60106b 929 struct wilc_vif *vif;
51e825f7 930 u8 NullBssid[ETH_ALEN] = {0};
8dfaafd6 931
0e1af73d 932 wilc_connecting = 0;
c5c77ba1 933 priv = wiphy_priv(wiphy);
cf60106b 934 vif = netdev_priv(priv->dev);
c5c77ba1 935
48b28df9 936 pstrWFIDrv = (struct host_if_drv *)priv->hif_drv;
ab16ec0b 937 if (!pstrWFIDrv->p2p_connect)
0bd8274f 938 wlan_channel = INVALID_CHANNEL;
ba615f1e 939 wilc_wlan_set_bssid(priv->dev, NullBssid, STATION_MODE);
c5c77ba1
JK
940
941 PRINT_D(CFG80211_DBG, "Disconnecting with reason code(%d)\n", reason_code);
942
583d972c 943 p2p_local_random = 0x01;
b84a3ac4 944 p2p_recv_random = 0x00;
a25d5186 945 wilc_ie = false;
1229b1ab 946 pstrWFIDrv->p2p_timeout = 0;
c5c77ba1 947
fbf5379b 948 s32Error = wilc_disconnect(vif, reason_code);
e6e12661 949 if (s32Error != 0) {
06fb9336 950 netdev_err(priv->dev, "Error in disconnecting\n");
c5c77ba1
JK
951 s32Error = -EINVAL;
952 }
953
954 return s32Error;
955}
956
953d417a
CL
957static int add_key(struct wiphy *wiphy, struct net_device *netdev, u8 key_index,
958 bool pairwise,
959 const u8 *mac_addr, struct key_params *params)
c5c77ba1
JK
960
961{
e6e12661 962 s32 s32Error = 0, KeyLen = params->key_len;
4e4467fd 963 u32 i;
2726887c 964 struct wilc_priv *priv;
057d1e97
AB
965 const u8 *pu8RxMic = NULL;
966 const u8 *pu8TxMic = NULL;
63d03e47 967 u8 u8mode = NO_ENCRYPT;
63d03e47
GKH
968 u8 u8gmode = NO_ENCRYPT;
969 u8 u8pmode = NO_ENCRYPT;
841dfc42 970 enum AUTHTYPE tenuAuth_type = ANY;
76469200 971 struct wilc *wl;
a4cac481 972 struct wilc_vif *vif;
c5c77ba1
JK
973
974 priv = wiphy_priv(wiphy);
a4cac481
GL
975 vif = netdev_priv(netdev);
976 wl = vif->wilc;
c5c77ba1
JK
977
978 PRINT_D(CFG80211_DBG, "Adding key with cipher suite = %x\n", params->cipher);
979
8a14330f 980 PRINT_D(CFG80211_DBG, "%p %p %d\n", wiphy, netdev, key_index);
c5c77ba1
JK
981
982 PRINT_D(CFG80211_DBG, "key %x %x %x\n", params->key[0],
983 params->key[1],
984 params->key[2]);
985
986
987 switch (params->cipher) {
988 case WLAN_CIPHER_SUITE_WEP40:
989 case WLAN_CIPHER_SUITE_WEP104:
c5c77ba1 990 if (priv->wdev->iftype == NL80211_IFTYPE_AP) {
c5c77ba1 991 priv->WILC_WFI_wep_key_len[key_index] = params->key_len;
d00d2ba3 992 memcpy(priv->WILC_WFI_wep_key[key_index], params->key, params->key_len);
c5c77ba1
JK
993
994 PRINT_D(CFG80211_DBG, "Adding AP WEP Default key Idx = %d\n", key_index);
995 PRINT_D(CFG80211_DBG, "Adding AP WEP Key len= %d\n", params->key_len);
996
997 for (i = 0; i < params->key_len; i++)
998 PRINT_D(CFG80211_DBG, "WEP AP key val[%d] = %x\n", i, params->key[i]);
999
1000 tenuAuth_type = OPEN_SYSTEM;
1001
1002 if (params->cipher == WLAN_CIPHER_SUITE_WEP40)
1003 u8mode = ENCRYPT_ENABLED | WEP;
1004 else
1005 u8mode = ENCRYPT_ENABLED | WEP | WEP_EXTENDED;
1006
fbf5379b
GL
1007 wilc_add_wep_key_bss_ap(vif, params->key,
1008 params->key_len, key_index,
1009 u8mode, tenuAuth_type);
c5c77ba1
JK
1010 break;
1011 }
1a646e7e 1012 if (memcmp(params->key, priv->WILC_WFI_wep_key[key_index], params->key_len)) {
c5c77ba1 1013 priv->WILC_WFI_wep_key_len[key_index] = params->key_len;
d00d2ba3 1014 memcpy(priv->WILC_WFI_wep_key[key_index], params->key, params->key_len);
c5c77ba1
JK
1015
1016 PRINT_D(CFG80211_DBG, "Adding WEP Default key Idx = %d\n", key_index);
1017 PRINT_D(CFG80211_DBG, "Adding WEP Key length = %d\n", params->key_len);
1018 if (INFO) {
1019 for (i = 0; i < params->key_len; i++)
1020 PRINT_INFO(CFG80211_DBG, "WEP key value[%d] = %d\n", i, params->key[i]);
1021 }
fbf5379b
GL
1022 wilc_add_wep_key_bss_sta(vif, params->key,
1023 params->key_len, key_index);
c5c77ba1
JK
1024 }
1025
1026 break;
1027
1028 case WLAN_CIPHER_SUITE_TKIP:
1029 case WLAN_CIPHER_SUITE_CCMP:
c5c77ba1 1030 if (priv->wdev->iftype == NL80211_IFTYPE_AP || priv->wdev->iftype == NL80211_IFTYPE_P2P_GO) {
369a1d3b 1031 if (!priv->wilc_gtk[key_index]) {
f3052587 1032 priv->wilc_gtk[key_index] = kmalloc(sizeof(struct wilc_wfi_key), GFP_KERNEL);
b1413b60
GKH
1033 priv->wilc_gtk[key_index]->key = NULL;
1034 priv->wilc_gtk[key_index]->seq = NULL;
c5c77ba1 1035 }
369a1d3b 1036 if (!priv->wilc_ptk[key_index]) {
f3052587 1037 priv->wilc_ptk[key_index] = kmalloc(sizeof(struct wilc_wfi_key), GFP_KERNEL);
b1413b60
GKH
1038 priv->wilc_ptk[key_index]->key = NULL;
1039 priv->wilc_ptk[key_index]->seq = NULL;
c5c77ba1
JK
1040 }
1041
1042
1043
1913221c 1044 if (!pairwise) {
c5c77ba1
JK
1045 if (params->cipher == WLAN_CIPHER_SUITE_TKIP)
1046 u8gmode = ENCRYPT_ENABLED | WPA | TKIP;
1047 else
1048 u8gmode = ENCRYPT_ENABLED | WPA2 | AES;
1049
1050 priv->wilc_groupkey = u8gmode;
1051
1052 if (params->key_len > 16 && params->cipher == WLAN_CIPHER_SUITE_TKIP) {
c5c77ba1
JK
1053 pu8TxMic = params->key + 24;
1054 pu8RxMic = params->key + 16;
1055 KeyLen = params->key_len - 16;
1056 }
cccfc39e 1057 kfree(priv->wilc_gtk[key_index]->key);
c5c77ba1 1058
f3052587 1059 priv->wilc_gtk[key_index]->key = kmalloc(params->key_len, GFP_KERNEL);
d00d2ba3 1060 memcpy(priv->wilc_gtk[key_index]->key, params->key, params->key_len);
cccfc39e 1061 kfree(priv->wilc_gtk[key_index]->seq);
c5c77ba1
JK
1062
1063 if ((params->seq_len) > 0) {
f3052587 1064 priv->wilc_gtk[key_index]->seq = kmalloc(params->seq_len, GFP_KERNEL);
d00d2ba3 1065 memcpy(priv->wilc_gtk[key_index]->seq, params->seq, params->seq_len);
c5c77ba1
JK
1066 }
1067
1068 priv->wilc_gtk[key_index]->cipher = params->cipher;
1069 priv->wilc_gtk[key_index]->key_len = params->key_len;
1070 priv->wilc_gtk[key_index]->seq_len = params->seq_len;
1071
1072 if (INFO) {
1073 for (i = 0; i < params->key_len; i++)
1074 PRINT_INFO(CFG80211_DBG, "Adding group key value[%d] = %x\n", i, params->key[i]);
1075 for (i = 0; i < params->seq_len; i++)
1076 PRINT_INFO(CFG80211_DBG, "Adding group seq value[%d] = %x\n", i, params->seq[i]);
1077 }
1078
1079
fbf5379b
GL
1080 wilc_add_rx_gtk(vif, params->key, KeyLen,
1081 key_index, params->seq_len,
1082 params->seq, pu8RxMic,
1083 pu8TxMic, AP_MODE, u8gmode);
c5c77ba1
JK
1084
1085 } else {
1086 PRINT_INFO(CFG80211_DBG, "STA Address: %x%x%x%x%x\n", mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4]);
1087
1088 if (params->cipher == WLAN_CIPHER_SUITE_TKIP)
1089 u8pmode = ENCRYPT_ENABLED | WPA | TKIP;
1090 else
1091 u8pmode = priv->wilc_groupkey | AES;
1092
1093
1094 if (params->key_len > 16 && params->cipher == WLAN_CIPHER_SUITE_TKIP) {
c5c77ba1
JK
1095 pu8TxMic = params->key + 24;
1096 pu8RxMic = params->key + 16;
1097 KeyLen = params->key_len - 16;
1098 }
1099
cccfc39e 1100 kfree(priv->wilc_ptk[key_index]->key);
c5c77ba1 1101
f3052587 1102 priv->wilc_ptk[key_index]->key = kmalloc(params->key_len, GFP_KERNEL);
c5c77ba1 1103
cccfc39e 1104 kfree(priv->wilc_ptk[key_index]->seq);
c5c77ba1
JK
1105
1106 if ((params->seq_len) > 0)
f3052587 1107 priv->wilc_ptk[key_index]->seq = kmalloc(params->seq_len, GFP_KERNEL);
c5c77ba1
JK
1108
1109 if (INFO) {
1110 for (i = 0; i < params->key_len; i++)
1111 PRINT_INFO(CFG80211_DBG, "Adding pairwise key value[%d] = %x\n", i, params->key[i]);
1112
1113 for (i = 0; i < params->seq_len; i++)
1114 PRINT_INFO(CFG80211_DBG, "Adding group seq value[%d] = %x\n", i, params->seq[i]);
1115 }
1116
d00d2ba3 1117 memcpy(priv->wilc_ptk[key_index]->key, params->key, params->key_len);
c5c77ba1
JK
1118
1119 if ((params->seq_len) > 0)
d00d2ba3 1120 memcpy(priv->wilc_ptk[key_index]->seq, params->seq, params->seq_len);
c5c77ba1
JK
1121
1122 priv->wilc_ptk[key_index]->cipher = params->cipher;
1123 priv->wilc_ptk[key_index]->key_len = params->key_len;
1124 priv->wilc_ptk[key_index]->seq_len = params->seq_len;
1125
fbf5379b
GL
1126 wilc_add_ptk(vif, params->key, KeyLen,
1127 mac_addr, pu8RxMic, pu8TxMic,
1128 AP_MODE, u8pmode, key_index);
c5c77ba1
JK
1129 }
1130 break;
1131 }
c5c77ba1
JK
1132
1133 {
1134 u8mode = 0;
1913221c 1135 if (!pairwise) {
c5c77ba1 1136 if (params->key_len > 16 && params->cipher == WLAN_CIPHER_SUITE_TKIP) {
c5c77ba1
JK
1137 pu8RxMic = params->key + 24;
1138 pu8TxMic = params->key + 16;
1139 KeyLen = params->key_len - 16;
1140 }
1141
1f435d2e 1142 if (!g_gtk_keys_saved && netdev == wl->vif[0]->ndev) {
c5c77ba1 1143 g_add_gtk_key_params.key_idx = key_index;
c5c77ba1 1144 g_add_gtk_key_params.pairwise = pairwise;
c5c77ba1
JK
1145 if (!mac_addr) {
1146 g_add_gtk_key_params.mac_addr = NULL;
1147 } else {
f3052587 1148 g_add_gtk_key_params.mac_addr = kmalloc(ETH_ALEN, GFP_KERNEL);
c5c77ba1
JK
1149 memcpy(g_add_gtk_key_params.mac_addr, mac_addr, ETH_ALEN);
1150 }
1151 g_key_gtk_params.key_len = params->key_len;
1152 g_key_gtk_params.seq_len = params->seq_len;
f3052587 1153 g_key_gtk_params.key = kmalloc(params->key_len, GFP_KERNEL);
c5c77ba1
JK
1154 memcpy(g_key_gtk_params.key, params->key, params->key_len);
1155 if (params->seq_len > 0) {
f3052587 1156 g_key_gtk_params.seq = kmalloc(params->seq_len, GFP_KERNEL);
c5c77ba1
JK
1157 memcpy(g_key_gtk_params.seq, params->seq, params->seq_len);
1158 }
1159 g_key_gtk_params.cipher = params->cipher;
1160
1161 PRINT_D(CFG80211_DBG, "key %x %x %x\n", g_key_gtk_params.key[0],
1162 g_key_gtk_params.key[1],
1163 g_key_gtk_params.key[2]);
72ed4dc7 1164 g_gtk_keys_saved = true;
c5c77ba1
JK
1165 }
1166
fbf5379b
GL
1167 wilc_add_rx_gtk(vif, params->key, KeyLen,
1168 key_index, params->seq_len,
1169 params->seq, pu8RxMic,
1170 pu8TxMic, STATION_MODE,
1171 u8mode);
c5c77ba1
JK
1172 } else {
1173 if (params->key_len > 16 && params->cipher == WLAN_CIPHER_SUITE_TKIP) {
c5c77ba1
JK
1174 pu8RxMic = params->key + 24;
1175 pu8TxMic = params->key + 16;
1176 KeyLen = params->key_len - 16;
1177 }
1178
1f435d2e 1179 if (!g_ptk_keys_saved && netdev == wl->vif[0]->ndev) {
c5c77ba1 1180 g_add_ptk_key_params.key_idx = key_index;
c5c77ba1 1181 g_add_ptk_key_params.pairwise = pairwise;
c5c77ba1
JK
1182 if (!mac_addr) {
1183 g_add_ptk_key_params.mac_addr = NULL;
1184 } else {
f3052587 1185 g_add_ptk_key_params.mac_addr = kmalloc(ETH_ALEN, GFP_KERNEL);
c5c77ba1
JK
1186 memcpy(g_add_ptk_key_params.mac_addr, mac_addr, ETH_ALEN);
1187 }
1188 g_key_ptk_params.key_len = params->key_len;
1189 g_key_ptk_params.seq_len = params->seq_len;
f3052587 1190 g_key_ptk_params.key = kmalloc(params->key_len, GFP_KERNEL);
c5c77ba1
JK
1191 memcpy(g_key_ptk_params.key, params->key, params->key_len);
1192 if (params->seq_len > 0) {
f3052587 1193 g_key_ptk_params.seq = kmalloc(params->seq_len, GFP_KERNEL);
c5c77ba1
JK
1194 memcpy(g_key_ptk_params.seq, params->seq, params->seq_len);
1195 }
1196 g_key_ptk_params.cipher = params->cipher;
1197
1198 PRINT_D(CFG80211_DBG, "key %x %x %x\n", g_key_ptk_params.key[0],
1199 g_key_ptk_params.key[1],
1200 g_key_ptk_params.key[2]);
72ed4dc7 1201 g_ptk_keys_saved = true;
c5c77ba1
JK
1202 }
1203
fbf5379b
GL
1204 wilc_add_ptk(vif, params->key, KeyLen,
1205 mac_addr, pu8RxMic, pu8TxMic,
1206 STATION_MODE, u8mode, key_index);
c5c77ba1
JK
1207 PRINT_D(CFG80211_DBG, "Adding pairwise key\n");
1208 if (INFO) {
1209 for (i = 0; i < params->key_len; i++)
1210 PRINT_INFO(CFG80211_DBG, "Adding pairwise key value[%d] = %d\n", i, params->key[i]);
1211 }
1212 }
1213 }
1214 break;
1215
1216 default:
06fb9336 1217 netdev_err(netdev, "Not supported cipher\n");
c5c77ba1 1218 s32Error = -ENOTSUPP;
c5c77ba1
JK
1219 }
1220
1221 return s32Error;
1222}
1223
3044ba7e
CL
1224static int del_key(struct wiphy *wiphy, struct net_device *netdev,
1225 u8 key_index,
1226 bool pairwise,
1227 const u8 *mac_addr)
c5c77ba1 1228{
2726887c 1229 struct wilc_priv *priv;
692e2ace 1230 struct wilc *wl;
a4cac481 1231 struct wilc_vif *vif;
c5c77ba1
JK
1232
1233 priv = wiphy_priv(wiphy);
a4cac481
GL
1234 vif = netdev_priv(netdev);
1235 wl = vif->wilc;
c5c77ba1 1236
1f435d2e 1237 if (netdev == wl->vif[0]->ndev) {
72ed4dc7
DL
1238 g_ptk_keys_saved = false;
1239 g_gtk_keys_saved = false;
1240 g_wep_keys_saved = false;
c5c77ba1 1241
cccfc39e
SB
1242 kfree(g_key_wep_params.key);
1243 g_key_wep_params.key = NULL;
c5c77ba1 1244
c5c77ba1 1245 if ((priv->wilc_gtk[key_index]) != NULL) {
cccfc39e
SB
1246 kfree(priv->wilc_gtk[key_index]->key);
1247 priv->wilc_gtk[key_index]->key = NULL;
1248 kfree(priv->wilc_gtk[key_index]->seq);
1249 priv->wilc_gtk[key_index]->seq = NULL;
c5c77ba1 1250
49188af2 1251 kfree(priv->wilc_gtk[key_index]);
c5c77ba1 1252 priv->wilc_gtk[key_index] = NULL;
c5c77ba1
JK
1253 }
1254
1255 if ((priv->wilc_ptk[key_index]) != NULL) {
cccfc39e
SB
1256 kfree(priv->wilc_ptk[key_index]->key);
1257 priv->wilc_ptk[key_index]->key = NULL;
1258 kfree(priv->wilc_ptk[key_index]->seq);
1259 priv->wilc_ptk[key_index]->seq = NULL;
49188af2 1260 kfree(priv->wilc_ptk[key_index]);
c5c77ba1
JK
1261 priv->wilc_ptk[key_index] = NULL;
1262 }
c5c77ba1 1263
cccfc39e
SB
1264 kfree(g_key_ptk_params.key);
1265 g_key_ptk_params.key = NULL;
1266 kfree(g_key_ptk_params.seq);
1267 g_key_ptk_params.seq = NULL;
1268
1269 kfree(g_key_gtk_params.key);
1270 g_key_gtk_params.key = NULL;
1271 kfree(g_key_gtk_params.seq);
1272 g_key_gtk_params.seq = NULL;
c5c77ba1 1273
c5c77ba1
JK
1274 }
1275
1276 if (key_index >= 0 && key_index <= 3) {
2cc46837 1277 memset(priv->WILC_WFI_wep_key[key_index], 0, priv->WILC_WFI_wep_key_len[key_index]);
c5c77ba1
JK
1278 priv->WILC_WFI_wep_key_len[key_index] = 0;
1279
1280 PRINT_D(CFG80211_DBG, "Removing WEP key with index = %d\n", key_index);
fbf5379b 1281 wilc_remove_wep_key(vif, key_index);
c5c77ba1
JK
1282 } else {
1283 PRINT_D(CFG80211_DBG, "Removing all installed keys\n");
48b28df9 1284 wilc_remove_key(priv->hif_drv, mac_addr);
c5c77ba1
JK
1285 }
1286
aaed3290 1287 return 0;
c5c77ba1
JK
1288}
1289
f4893dfc
CL
1290static int get_key(struct wiphy *wiphy, struct net_device *netdev, u8 key_index,
1291 bool pairwise,
1292 const u8 *mac_addr, void *cookie, void (*callback)(void *cookie, struct key_params *))
c5c77ba1 1293{
2726887c 1294 struct wilc_priv *priv;
c5c77ba1 1295 struct key_params key_params;
4e4467fd 1296 u32 i;
8dfaafd6 1297
c5c77ba1
JK
1298 priv = wiphy_priv(wiphy);
1299
1300
3604af50 1301 if (!pairwise) {
c5c77ba1
JK
1302 PRINT_D(CFG80211_DBG, "Getting group key idx: %x\n", key_index);
1303
1304 key_params.key = priv->wilc_gtk[key_index]->key;
1305 key_params.cipher = priv->wilc_gtk[key_index]->cipher;
1306 key_params.key_len = priv->wilc_gtk[key_index]->key_len;
1307 key_params.seq = priv->wilc_gtk[key_index]->seq;
1308 key_params.seq_len = priv->wilc_gtk[key_index]->seq_len;
1309 if (INFO) {
1310 for (i = 0; i < key_params.key_len; i++)
1311 PRINT_INFO(CFG80211_DBG, "Retrieved key value %x\n", key_params.key[i]);
1312 }
1313 } else {
1314 PRINT_D(CFG80211_DBG, "Getting pairwise key\n");
1315
1316 key_params.key = priv->wilc_ptk[key_index]->key;
1317 key_params.cipher = priv->wilc_ptk[key_index]->cipher;
1318 key_params.key_len = priv->wilc_ptk[key_index]->key_len;
1319 key_params.seq = priv->wilc_ptk[key_index]->seq;
1320 key_params.seq_len = priv->wilc_ptk[key_index]->seq_len;
1321 }
1322
1323 callback(cookie, &key_params);
1324
a89f7c55 1325 return 0;
c5c77ba1
JK
1326}
1327
0f5b8ca3
CL
1328static int set_default_key(struct wiphy *wiphy, struct net_device *netdev, u8 key_index,
1329 bool unicast, bool multicast)
c5c77ba1 1330{
2726887c 1331 struct wilc_priv *priv;
cf60106b 1332 struct wilc_vif *vif;
c5c77ba1
JK
1333
1334 priv = wiphy_priv(wiphy);
cf60106b 1335 vif = netdev_priv(priv->dev);
c5c77ba1 1336
17aacd43 1337 PRINT_D(CFG80211_DBG, "Setting default key with idx = %d\n", key_index);
c5c77ba1 1338
ec450483 1339 wilc_set_wep_default_keyid(vif, key_index);
c5c77ba1 1340
aaed3290 1341 return 0;
c5c77ba1
JK
1342}
1343
f06f562d
CL
1344static int get_station(struct wiphy *wiphy, struct net_device *dev,
1345 const u8 *mac, struct station_info *sinfo)
c5c77ba1 1346{
2726887c 1347 struct wilc_priv *priv;
a4cac481 1348 struct wilc_vif *vif;
4e4467fd
CL
1349 u32 i = 0;
1350 u32 associatedsta = 0;
1351 u32 inactive_time = 0;
c5c77ba1 1352 priv = wiphy_priv(wiphy);
a4cac481 1353 vif = netdev_priv(dev);
c5c77ba1 1354
a4cac481 1355 if (vif->iftype == AP_MODE || vif->iftype == GO_MODE) {
c5c77ba1
JK
1356 PRINT_D(HOSTAPD_DBG, "Getting station parameters\n");
1357
1358 PRINT_INFO(HOSTAPD_DBG, ": %x%x%x%x%x\n", mac[0], mac[1], mac[2], mac[3], mac[4]);
1359
1360 for (i = 0; i < NUM_STA_ASSOCIATED; i++) {
c5c77ba1
JK
1361 if (!(memcmp(mac, priv->assoc_stainfo.au8Sta_AssociatedBss[i], ETH_ALEN))) {
1362 associatedsta = i;
1363 break;
1364 }
c5c77ba1
JK
1365 }
1366
1367 if (associatedsta == -1) {
06fb9336 1368 netdev_err(dev, "sta required is not associated\n");
aaed3290 1369 return -ENOENT;
c5c77ba1
JK
1370 }
1371
c5c77ba1 1372 sinfo->filled |= BIT(NL80211_STA_INFO_INACTIVE_TIME);
c5c77ba1 1373
fbf5379b 1374 wilc_get_inactive_time(vif, mac, &inactive_time);
c5c77ba1
JK
1375 sinfo->inactive_time = 1000 * inactive_time;
1376 PRINT_D(CFG80211_DBG, "Inactive time %d\n", sinfo->inactive_time);
c5c77ba1 1377 }
c5c77ba1 1378
a4cac481 1379 if (vif->iftype == STATION_MODE) {
03e7b9c4 1380 struct rf_info strStatistics;
8dfaafd6 1381
fbf5379b 1382 wilc_get_statistics(vif, &strStatistics);
c5c77ba1 1383
c5c77ba1 1384 sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL) |
6212990a 1385 BIT(NL80211_STA_INFO_RX_PACKETS) |
c5c77ba1
JK
1386 BIT(NL80211_STA_INFO_TX_PACKETS) |
1387 BIT(NL80211_STA_INFO_TX_FAILED) |
1388 BIT(NL80211_STA_INFO_TX_BITRATE);
c5c77ba1 1389
00c8dfcf 1390 sinfo->signal = strStatistics.rssi;
9b99274a 1391 sinfo->rx_packets = strStatistics.rx_cnt;
54160376
LK
1392 sinfo->tx_packets = strStatistics.tx_cnt + strStatistics.tx_fail_cnt;
1393 sinfo->tx_failed = strStatistics.tx_fail_cnt;
5babeecb 1394 sinfo->txrate.legacy = strStatistics.link_speed * 10;
c5c77ba1 1395
5babeecb
LK
1396 if ((strStatistics.link_speed > TCP_ACK_FILTER_LINK_SPEED_THRESH) &&
1397 (strStatistics.link_speed != DEFAULT_LINK_SPEED))
0e1af73d 1398 wilc_enable_tcp_ack_filter(true);
5babeecb 1399 else if (strStatistics.link_speed != DEFAULT_LINK_SPEED)
0e1af73d 1400 wilc_enable_tcp_ack_filter(false);
c5c77ba1 1401 }
aaed3290 1402 return 0;
c5c77ba1
JK
1403}
1404
a5f7db6a
CL
1405static int change_bss(struct wiphy *wiphy, struct net_device *dev,
1406 struct bss_parameters *params)
c5c77ba1
JK
1407{
1408 PRINT_D(CFG80211_DBG, "Changing Bss parametrs\n");
1409 return 0;
1410}
1411
a76b63ef 1412static int set_wiphy_params(struct wiphy *wiphy, u32 changed)
c5c77ba1 1413{
e6e12661 1414 s32 s32Error = 0;
9529650a 1415 struct cfg_param_val pstrCfgParamVal;
2726887c 1416 struct wilc_priv *priv;
cf60106b 1417 struct wilc_vif *vif;
c5c77ba1
JK
1418
1419 priv = wiphy_priv(wiphy);
cf60106b 1420 vif = netdev_priv(priv->dev);
c5c77ba1 1421
87c05b28 1422 pstrCfgParamVal.flag = 0;
17aacd43 1423 PRINT_D(CFG80211_DBG, "Setting Wiphy params\n");
c5c77ba1
JK
1424
1425 if (changed & WIPHY_PARAM_RETRY_SHORT) {
1426 PRINT_D(CFG80211_DBG, "Setting WIPHY_PARAM_RETRY_SHORT %d\n",
1427 priv->dev->ieee80211_ptr->wiphy->retry_short);
87c05b28 1428 pstrCfgParamVal.flag |= RETRY_SHORT;
c5c77ba1
JK
1429 pstrCfgParamVal.short_retry_limit = priv->dev->ieee80211_ptr->wiphy->retry_short;
1430 }
1431 if (changed & WIPHY_PARAM_RETRY_LONG) {
c5c77ba1 1432 PRINT_D(CFG80211_DBG, "Setting WIPHY_PARAM_RETRY_LONG %d\n", priv->dev->ieee80211_ptr->wiphy->retry_long);
87c05b28 1433 pstrCfgParamVal.flag |= RETRY_LONG;
c5c77ba1 1434 pstrCfgParamVal.long_retry_limit = priv->dev->ieee80211_ptr->wiphy->retry_long;
c5c77ba1
JK
1435 }
1436 if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
1437 PRINT_D(CFG80211_DBG, "Setting WIPHY_PARAM_FRAG_THRESHOLD %d\n", priv->dev->ieee80211_ptr->wiphy->frag_threshold);
87c05b28 1438 pstrCfgParamVal.flag |= FRAG_THRESHOLD;
c5c77ba1 1439 pstrCfgParamVal.frag_threshold = priv->dev->ieee80211_ptr->wiphy->frag_threshold;
c5c77ba1
JK
1440 }
1441
1442 if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
1443 PRINT_D(CFG80211_DBG, "Setting WIPHY_PARAM_RTS_THRESHOLD %d\n", priv->dev->ieee80211_ptr->wiphy->rts_threshold);
1444
87c05b28 1445 pstrCfgParamVal.flag |= RTS_THRESHOLD;
c5c77ba1 1446 pstrCfgParamVal.rts_threshold = priv->dev->ieee80211_ptr->wiphy->rts_threshold;
c5c77ba1
JK
1447 }
1448
1449 PRINT_D(CFG80211_DBG, "Setting CFG params in the host interface\n");
fbf5379b 1450 s32Error = wilc_hif_set_cfg(vif, &pstrCfgParamVal);
c5c77ba1 1451 if (s32Error)
06fb9336 1452 netdev_err(priv->dev, "Error in setting WIPHY PARAMS\n");
c5c77ba1
JK
1453
1454 return s32Error;
1455}
e5af0561 1456
4d46657a
CL
1457static int set_pmksa(struct wiphy *wiphy, struct net_device *netdev,
1458 struct cfg80211_pmksa *pmksa)
c5c77ba1 1459{
4e4467fd 1460 u32 i;
e6e12661 1461 s32 s32Error = 0;
63d03e47 1462 u8 flag = 0;
cf60106b 1463 struct wilc_vif *vif;
2726887c 1464 struct wilc_priv *priv = wiphy_priv(wiphy);
c5c77ba1 1465
cf60106b 1466 vif = netdev_priv(priv->dev);
c5c77ba1
JK
1467 PRINT_D(CFG80211_DBG, "Setting PMKSA\n");
1468
1469
1470 for (i = 0; i < priv->pmkid_list.numpmkid; i++) {
1a646e7e 1471 if (!memcmp(pmksa->bssid, priv->pmkid_list.pmkidlist[i].bssid,
c5c77ba1 1472 ETH_ALEN)) {
c5c77ba1
JK
1473 flag = PMKID_FOUND;
1474 PRINT_D(CFG80211_DBG, "PMKID already exists\n");
1475 break;
1476 }
1477 }
1478 if (i < WILC_MAX_NUM_PMKIDS) {
1479 PRINT_D(CFG80211_DBG, "Setting PMKID in private structure\n");
d00d2ba3 1480 memcpy(priv->pmkid_list.pmkidlist[i].bssid, pmksa->bssid,
c5c77ba1 1481 ETH_ALEN);
d00d2ba3 1482 memcpy(priv->pmkid_list.pmkidlist[i].pmkid, pmksa->pmkid,
c5c77ba1
JK
1483 PMKID_LEN);
1484 if (!(flag == PMKID_FOUND))
1485 priv->pmkid_list.numpmkid++;
1486 } else {
06fb9336 1487 netdev_err(netdev, "Invalid PMKID index\n");
c5c77ba1
JK
1488 s32Error = -EINVAL;
1489 }
1490
1491 if (!s32Error) {
1492 PRINT_D(CFG80211_DBG, "Setting pmkid in the host interface\n");
fbf5379b 1493 s32Error = wilc_set_pmkid_info(vif, &priv->pmkid_list);
c5c77ba1
JK
1494 }
1495 return s32Error;
1496}
1497
1ff86d96
CL
1498static int del_pmksa(struct wiphy *wiphy, struct net_device *netdev,
1499 struct cfg80211_pmksa *pmksa)
c5c77ba1 1500{
4e4467fd 1501 u32 i;
e6e12661 1502 s32 s32Error = 0;
c5c77ba1 1503
2726887c 1504 struct wilc_priv *priv = wiphy_priv(wiphy);
c5c77ba1
JK
1505
1506 PRINT_D(CFG80211_DBG, "Deleting PMKSA keys\n");
1507
1508 for (i = 0; i < priv->pmkid_list.numpmkid; i++) {
1a646e7e 1509 if (!memcmp(pmksa->bssid, priv->pmkid_list.pmkidlist[i].bssid,
c5c77ba1 1510 ETH_ALEN)) {
c5c77ba1 1511 PRINT_D(CFG80211_DBG, "Reseting PMKID values\n");
cd1e6cb4 1512 memset(&priv->pmkid_list.pmkidlist[i], 0, sizeof(struct host_if_pmkid));
c5c77ba1
JK
1513 break;
1514 }
1515 }
1516
1517 if (i < priv->pmkid_list.numpmkid && priv->pmkid_list.numpmkid > 0) {
1518 for (; i < (priv->pmkid_list.numpmkid - 1); i++) {
d00d2ba3 1519 memcpy(priv->pmkid_list.pmkidlist[i].bssid,
c5c77ba1
JK
1520 priv->pmkid_list.pmkidlist[i + 1].bssid,
1521 ETH_ALEN);
d00d2ba3 1522 memcpy(priv->pmkid_list.pmkidlist[i].pmkid,
c5c77ba1
JK
1523 priv->pmkid_list.pmkidlist[i].pmkid,
1524 PMKID_LEN);
1525 }
1526 priv->pmkid_list.numpmkid--;
1527 } else {
1528 s32Error = -EINVAL;
1529 }
1530
1531 return s32Error;
1532}
1533
b33c39b1 1534static int flush_pmksa(struct wiphy *wiphy, struct net_device *netdev)
c5c77ba1 1535{
2726887c 1536 struct wilc_priv *priv = wiphy_priv(wiphy);
c5c77ba1
JK
1537
1538 PRINT_D(CFG80211_DBG, "Flushing PMKID key values\n");
1539
a949f909 1540 memset(&priv->pmkid_list, 0, sizeof(struct host_if_pmkid_attr));
c5c77ba1
JK
1541
1542 return 0;
1543}
c5c77ba1 1544
1608c403 1545static void WILC_WFI_CfgParseRxAction(u8 *buf, u32 len)
c5c77ba1 1546{
4e4467fd
CL
1547 u32 index = 0;
1548 u32 i = 0, j = 0;
c5c77ba1 1549
63d03e47
GKH
1550 u8 op_channel_attr_index = 0;
1551 u8 channel_list_attr_index = 0;
c5c77ba1
JK
1552
1553 while (index < len) {
1554 if (buf[index] == GO_INTENT_ATTR_ID) {
c5c77ba1 1555 buf[index + 3] = (buf[index + 3] & 0x01) | (0x00 << 1);
c5c77ba1
JK
1556 }
1557
78174ada 1558 if (buf[index] == CHANLIST_ATTR_ID)
c5c77ba1 1559 channel_list_attr_index = index;
78174ada 1560 else if (buf[index] == OPERCHAN_ATTR_ID)
c5c77ba1 1561 op_channel_attr_index = index;
a89f7c55 1562 index += buf[index + 1] + 3;
c5c77ba1 1563 }
0bd8274f 1564 if (wlan_channel != INVALID_CHANNEL) {
c5c77ba1
JK
1565 if (channel_list_attr_index) {
1566 PRINT_D(GENERIC_DBG, "Modify channel list attribute\n");
1567 for (i = channel_list_attr_index + 3; i < ((channel_list_attr_index + 3) + buf[channel_list_attr_index + 1]); i++) {
1568 if (buf[i] == 0x51) {
1569 for (j = i + 2; j < ((i + 2) + buf[i + 1]); j++) {
0bd8274f 1570 buf[j] = wlan_channel;
c5c77ba1
JK
1571 }
1572 break;
1573 }
1574 }
1575 }
a89f7c55 1576
c5c77ba1
JK
1577 if (op_channel_attr_index) {
1578 PRINT_D(GENERIC_DBG, "Modify operating channel attribute\n");
1579 buf[op_channel_attr_index + 6] = 0x51;
0bd8274f 1580 buf[op_channel_attr_index + 7] = wlan_channel;
c5c77ba1
JK
1581 }
1582 }
1583}
1584
1608c403 1585static void WILC_WFI_CfgParseTxAction(u8 *buf, u32 len, bool bOperChan, u8 iftype)
c5c77ba1 1586{
4e4467fd
CL
1587 u32 index = 0;
1588 u32 i = 0, j = 0;
c5c77ba1 1589
63d03e47
GKH
1590 u8 op_channel_attr_index = 0;
1591 u8 channel_list_attr_index = 0;
c5c77ba1
JK
1592
1593 while (index < len) {
c5c77ba1 1594 if (buf[index] == GO_INTENT_ATTR_ID) {
c5c77ba1 1595 buf[index + 3] = (buf[index + 3] & 0x01) | (0x0f << 1);
c5c77ba1
JK
1596
1597 break;
1598 }
c5c77ba1 1599
78174ada 1600 if (buf[index] == CHANLIST_ATTR_ID)
c5c77ba1 1601 channel_list_attr_index = index;
78174ada 1602 else if (buf[index] == OPERCHAN_ATTR_ID)
c5c77ba1 1603 op_channel_attr_index = index;
a89f7c55 1604 index += buf[index + 1] + 3;
c5c77ba1 1605 }
0bd8274f 1606 if (wlan_channel != INVALID_CHANNEL && bOperChan) {
c5c77ba1
JK
1607 if (channel_list_attr_index) {
1608 PRINT_D(GENERIC_DBG, "Modify channel list attribute\n");
1609 for (i = channel_list_attr_index + 3; i < ((channel_list_attr_index + 3) + buf[channel_list_attr_index + 1]); i++) {
1610 if (buf[i] == 0x51) {
1611 for (j = i + 2; j < ((i + 2) + buf[i + 1]); j++) {
0bd8274f 1612 buf[j] = wlan_channel;
c5c77ba1
JK
1613 }
1614 break;
1615 }
1616 }
1617 }
a89f7c55 1618
c5c77ba1
JK
1619 if (op_channel_attr_index) {
1620 PRINT_D(GENERIC_DBG, "Modify operating channel attribute\n");
1621 buf[op_channel_attr_index + 6] = 0x51;
0bd8274f 1622 buf[op_channel_attr_index + 7] = wlan_channel;
c5c77ba1
JK
1623 }
1624 }
1625}
1626
fbc2fe16 1627void WILC_WFI_p2p_rx (struct net_device *dev, u8 *buff, u32 size)
c5c77ba1 1628{
2726887c 1629 struct wilc_priv *priv;
4e4467fd 1630 u32 header, pkt_offset;
441dc609 1631 struct host_if_drv *pstrWFIDrv;
4e4467fd 1632 u32 i = 0;
fb4ec9ca 1633 s32 s32Freq;
8dfaafd6 1634
c5c77ba1 1635 priv = wiphy_priv(dev->ieee80211_ptr->wiphy);
48b28df9 1636 pstrWFIDrv = (struct host_if_drv *)priv->hif_drv;
c5c77ba1 1637
d00d2ba3 1638 memcpy(&header, (buff - HOST_HDR_OFFSET), HOST_HDR_OFFSET);
c5c77ba1 1639
c5c77ba1
JK
1640 pkt_offset = GET_PKT_OFFSET(header);
1641
1642 if (pkt_offset & IS_MANAGMEMENT_CALLBACK) {
1643 if (buff[FRAME_TYPE_ID] == IEEE80211_STYPE_PROBE_RESP) {
1644 PRINT_D(GENERIC_DBG, "Probe response ACK\n");
c5c77ba1 1645 cfg80211_mgmt_tx_status(priv->wdev, priv->u64tx_cookie, buff, size, true, GFP_KERNEL);
c5c77ba1
JK
1646 return;
1647 } else {
1648 if (pkt_offset & IS_MGMT_STATUS_SUCCES) {
1649 PRINT_D(GENERIC_DBG, "Success Ack - Action frame category: %x Action Subtype: %d Dialog T: %x OR %x\n", buff[ACTION_CAT_ID], buff[ACTION_SUBTYPE_ID],
1650 buff[ACTION_SUBTYPE_ID + 1], buff[P2P_PUB_ACTION_SUBTYPE + 1]);
c5c77ba1 1651 cfg80211_mgmt_tx_status(priv->wdev, priv->u64tx_cookie, buff, size, true, GFP_KERNEL);
c5c77ba1
JK
1652 } else {
1653 PRINT_D(GENERIC_DBG, "Fail Ack - Action frame category: %x Action Subtype: %d Dialog T: %x OR %x\n", buff[ACTION_CAT_ID], buff[ACTION_SUBTYPE_ID],
1654 buff[ACTION_SUBTYPE_ID + 1], buff[P2P_PUB_ACTION_SUBTYPE + 1]);
c5c77ba1 1655 cfg80211_mgmt_tx_status(priv->wdev, priv->u64tx_cookie, buff, size, false, GFP_KERNEL);
c5c77ba1
JK
1656 }
1657 return;
1658 }
1659 } else {
c5c77ba1
JK
1660 PRINT_D(GENERIC_DBG, "Rx Frame Type:%x\n", buff[FRAME_TYPE_ID]);
1661
866a2c24 1662 s32Freq = ieee80211_channel_to_frequency(curr_channel, IEEE80211_BAND_2GHZ);
c5c77ba1
JK
1663
1664 if (ieee80211_is_action(buff[FRAME_TYPE_ID])) {
1665 PRINT_D(GENERIC_DBG, "Rx Action Frame Type: %x %x\n", buff[ACTION_SUBTYPE_ID], buff[P2P_PUB_ACTION_SUBTYPE]);
1666
1229b1ab 1667 if (priv->bCfgScanning && time_after_eq(jiffies, (unsigned long)pstrWFIDrv->p2p_timeout)) {
c5c77ba1
JK
1668 PRINT_D(GENERIC_DBG, "Receiving action frames from wrong channels\n");
1669 return;
1670 }
1671 if (buff[ACTION_CAT_ID] == PUB_ACTION_ATTR_ID) {
c5c77ba1
JK
1672 switch (buff[ACTION_SUBTYPE_ID]) {
1673 case GAS_INTIAL_REQ:
1674 PRINT_D(GENERIC_DBG, "GAS INITIAL REQ %x\n", buff[ACTION_SUBTYPE_ID]);
1675 break;
1676
1677 case GAS_INTIAL_RSP:
1678 PRINT_D(GENERIC_DBG, "GAS INITIAL RSP %x\n", buff[ACTION_SUBTYPE_ID]);
1679 break;
1680
1681 case PUBLIC_ACT_VENDORSPEC:
881eb5d8 1682 if (!memcmp(p2p_oui, &buff[ACTION_SUBTYPE_ID + 1], 4)) {
c5c77ba1 1683 if ((buff[P2P_PUB_ACTION_SUBTYPE] == GO_NEG_REQ || buff[P2P_PUB_ACTION_SUBTYPE] == GO_NEG_RSP)) {
a25d5186 1684 if (!wilc_ie) {
c5c77ba1 1685 for (i = P2P_PUB_ACTION_SUBTYPE; i < size; i++) {
8668594a 1686 if (!memcmp(p2p_vendor_spec, &buff[i], 6)) {
b84a3ac4 1687 p2p_recv_random = buff[i + 6];
a25d5186 1688 wilc_ie = true;
b84a3ac4 1689 PRINT_D(GENERIC_DBG, "WILC Vendor specific IE:%02x\n", p2p_recv_random);
c5c77ba1
JK
1690 break;
1691 }
1692 }
1693 }
1694 }
b84a3ac4 1695 if (p2p_local_random > p2p_recv_random) {
c5c77ba1
JK
1696 if ((buff[P2P_PUB_ACTION_SUBTYPE] == GO_NEG_REQ || buff[P2P_PUB_ACTION_SUBTYPE] == GO_NEG_RSP
1697 || buff[P2P_PUB_ACTION_SUBTYPE] == P2P_INV_REQ || buff[P2P_PUB_ACTION_SUBTYPE] == P2P_INV_RSP)) {
1698 for (i = P2P_PUB_ACTION_SUBTYPE + 2; i < size; i++) {
881eb5d8 1699 if (buff[i] == P2PELEM_ATTR_ID && !(memcmp(p2p_oui, &buff[i + 2], 4))) {
c5c77ba1
JK
1700 WILC_WFI_CfgParseRxAction(&buff[i + 6], size - (i + 6));
1701 break;
1702 }
1703 }
1704 }
583d972c 1705 } else {
b84a3ac4 1706 PRINT_D(GENERIC_DBG, "PEER WILL BE GO LocaRand=%02x RecvRand %02x\n", p2p_local_random, p2p_recv_random);
583d972c 1707 }
c5c77ba1
JK
1708 }
1709
1710
a25d5186 1711 if ((buff[P2P_PUB_ACTION_SUBTYPE] == GO_NEG_REQ || buff[P2P_PUB_ACTION_SUBTYPE] == GO_NEG_RSP) && (wilc_ie)) {
c5c77ba1 1712 PRINT_D(GENERIC_DBG, "Sending P2P to host without extra elemnt\n");
c5c77ba1 1713 cfg80211_rx_mgmt(priv->wdev, s32Freq, 0, buff, size - 7, 0);
c5c77ba1
JK
1714 return;
1715 }
1716 break;
1717
1718 default:
1719 PRINT_D(GENERIC_DBG, "NOT HANDLED PUBLIC ACTION FRAME TYPE:%x\n", buff[ACTION_SUBTYPE_ID]);
1720 break;
1721 }
1722 }
1723 }
1724
783d07c1 1725 cfg80211_rx_mgmt(priv->wdev, s32Freq, 0, buff, size, 0);
c5c77ba1
JK
1726 }
1727}
1728
c5c77ba1
JK
1729static void WILC_WFI_mgmt_tx_complete(void *priv, int status)
1730{
1731 struct p2p_mgmt_data *pv_data = (struct p2p_mgmt_data *)priv;
1732
1733
1734 kfree(pv_data->buff);
1735 kfree(pv_data);
1736}
1737
c5c77ba1
JK
1738static void WILC_WFI_RemainOnChannelReady(void *pUserVoid)
1739{
2726887c 1740 struct wilc_priv *priv;
8dfaafd6 1741
2726887c 1742 priv = (struct wilc_priv *)pUserVoid;
c5c77ba1 1743
72ed4dc7 1744 priv->bInP2PlistenState = true;
c5c77ba1 1745
c5c77ba1
JK
1746 cfg80211_ready_on_channel(priv->wdev,
1747 priv->strRemainOnChanParams.u64ListenCookie,
1748 priv->strRemainOnChanParams.pstrListenChan,
1749 priv->strRemainOnChanParams.u32ListenDuration,
1750 GFP_KERNEL);
c5c77ba1
JK
1751}
1752
4e4467fd 1753static void WILC_WFI_RemainOnChannelExpired(void *pUserVoid, u32 u32SessionID)
c5c77ba1 1754{
2726887c 1755 struct wilc_priv *priv;
8dfaafd6 1756
2726887c 1757 priv = (struct wilc_priv *)pUserVoid;
c5c77ba1 1758
c5c77ba1 1759 if (u32SessionID == priv->strRemainOnChanParams.u32ListenSessionID) {
17aacd43 1760 PRINT_D(GENERIC_DBG, "Remain on channel expired\n");
c5c77ba1 1761
72ed4dc7 1762 priv->bInP2PlistenState = false;
c5c77ba1 1763
c5c77ba1
JK
1764 cfg80211_remain_on_channel_expired(priv->wdev,
1765 priv->strRemainOnChanParams.u64ListenCookie,
1766 priv->strRemainOnChanParams.pstrListenChan,
1767 GFP_KERNEL);
c5c77ba1
JK
1768 } else {
1769 PRINT_D(GENERIC_DBG, "Received ID 0x%x Expected ID 0x%x (No match)\n", u32SessionID
1770 , priv->strRemainOnChanParams.u32ListenSessionID);
1771 }
1772}
1773
6d19d695
CL
1774static int remain_on_channel(struct wiphy *wiphy,
1775 struct wireless_dev *wdev,
1776 struct ieee80211_channel *chan,
1777 unsigned int duration, u64 *cookie)
c5c77ba1 1778{
e6e12661 1779 s32 s32Error = 0;
2726887c 1780 struct wilc_priv *priv;
cf60106b 1781 struct wilc_vif *vif;
8dfaafd6 1782
c5c77ba1 1783 priv = wiphy_priv(wiphy);
cf60106b 1784 vif = netdev_priv(priv->dev);
c5c77ba1
JK
1785
1786 PRINT_D(GENERIC_DBG, "Remaining on channel %d\n", chan->hw_value);
1787
c5c77ba1 1788
c5c77ba1
JK
1789 if (wdev->iftype == NL80211_IFTYPE_AP) {
1790 PRINT_D(GENERIC_DBG, "Required remain-on-channel while in AP mode");
1791 return s32Error;
1792 }
c5c77ba1 1793
866a2c24 1794 curr_channel = chan->hw_value;
c5c77ba1 1795
c5c77ba1
JK
1796 priv->strRemainOnChanParams.pstrListenChan = chan;
1797 priv->strRemainOnChanParams.u64ListenCookie = *cookie;
c5c77ba1
JK
1798 priv->strRemainOnChanParams.u32ListenDuration = duration;
1799 priv->strRemainOnChanParams.u32ListenSessionID++;
1800
fbf5379b
GL
1801 s32Error = wilc_remain_on_channel(vif,
1802 priv->strRemainOnChanParams.u32ListenSessionID,
1803 duration, chan->hw_value,
1804 WILC_WFI_RemainOnChannelExpired,
1805 WILC_WFI_RemainOnChannelReady, (void *)priv);
c5c77ba1
JK
1806
1807 return s32Error;
1808}
1809
1dd5440b
CL
1810static int cancel_remain_on_channel(struct wiphy *wiphy,
1811 struct wireless_dev *wdev,
1812 u64 cookie)
c5c77ba1 1813{
e6e12661 1814 s32 s32Error = 0;
2726887c 1815 struct wilc_priv *priv;
cf60106b 1816 struct wilc_vif *vif;
8dfaafd6 1817
c5c77ba1 1818 priv = wiphy_priv(wiphy);
cf60106b 1819 vif = netdev_priv(priv->dev);
c5c77ba1
JK
1820
1821 PRINT_D(CFG80211_DBG, "Cancel remain on channel\n");
1822
fbf5379b 1823 s32Error = wilc_listen_state_expired(vif, priv->strRemainOnChanParams.u32ListenSessionID);
c5c77ba1
JK
1824 return s32Error;
1825}
a89f7c55 1826
c156032d
CL
1827static int mgmt_tx(struct wiphy *wiphy,
1828 struct wireless_dev *wdev,
1829 struct cfg80211_mgmt_tx_params *params,
1830 u64 *cookie)
c5c77ba1 1831{
c5c77ba1
JK
1832 struct ieee80211_channel *chan = params->chan;
1833 unsigned int wait = params->wait;
1834 const u8 *buf = params->buf;
1835 size_t len = params->len;
c5c77ba1
JK
1836 const struct ieee80211_mgmt *mgmt;
1837 struct p2p_mgmt_data *mgmt_tx;
2726887c 1838 struct wilc_priv *priv;
441dc609 1839 struct host_if_drv *pstrWFIDrv;
4e4467fd 1840 u32 i;
a4cac481 1841 struct wilc_vif *vif;
8668594a 1842 u32 buf_len = len + sizeof(p2p_vendor_spec) + sizeof(p2p_local_random);
c5c77ba1 1843
a4cac481 1844 vif = netdev_priv(wdev->netdev);
c5c77ba1 1845 priv = wiphy_priv(wiphy);
48b28df9 1846 pstrWFIDrv = (struct host_if_drv *)priv->hif_drv;
c5c77ba1
JK
1847
1848 *cookie = (unsigned long)buf;
1849 priv->u64tx_cookie = *cookie;
1850 mgmt = (const struct ieee80211_mgmt *) buf;
1851
1852 if (ieee80211_is_mgmt(mgmt->frame_control)) {
f3052587 1853 mgmt_tx = kmalloc(sizeof(struct p2p_mgmt_data), GFP_KERNEL);
06fb9336 1854 if (!mgmt_tx)
e6e12661 1855 return -EFAULT;
06fb9336 1856
f3052587 1857 mgmt_tx->buff = kmalloc(buf_len, GFP_KERNEL);
06fb9336 1858 if (!mgmt_tx->buff)
f638dd39 1859 kfree(mgmt_tx);
e6e12661 1860 return -EFAULT;
06fb9336 1861
d00d2ba3 1862 memcpy(mgmt_tx->buff, buf, len);
c5c77ba1
JK
1863 mgmt_tx->size = len;
1864
1865
1866 if (ieee80211_is_probe_resp(mgmt->frame_control)) {
1867 PRINT_D(GENERIC_DBG, "TX: Probe Response\n");
1868 PRINT_D(GENERIC_DBG, "Setting channel: %d\n", chan->hw_value);
fbf5379b 1869 wilc_set_mac_chnl_num(vif, chan->hw_value);
866a2c24 1870 curr_channel = chan->hw_value;
c5c77ba1 1871 } else if (ieee80211_is_action(mgmt->frame_control)) {
d85f5326 1872 PRINT_D(GENERIC_DBG, "ACTION FRAME:%x\n", (u16)mgmt->frame_control);
c5c77ba1
JK
1873
1874
c5c77ba1 1875 if (buf[ACTION_CAT_ID] == PUB_ACTION_ATTR_ID) {
c5c77ba1
JK
1876 if (buf[ACTION_SUBTYPE_ID] != PUBLIC_ACT_VENDORSPEC ||
1877 buf[P2P_PUB_ACTION_SUBTYPE] != GO_NEG_CONF) {
1878 PRINT_D(GENERIC_DBG, "Setting channel: %d\n", chan->hw_value);
fbf5379b
GL
1879 wilc_set_mac_chnl_num(vif,
1880 chan->hw_value);
866a2c24 1881 curr_channel = chan->hw_value;
c5c77ba1
JK
1882 }
1883 switch (buf[ACTION_SUBTYPE_ID]) {
1884 case GAS_INTIAL_REQ:
1885 {
1886 PRINT_D(GENERIC_DBG, "GAS INITIAL REQ %x\n", buf[ACTION_SUBTYPE_ID]);
1887 break;
1888 }
1889
1890 case GAS_INTIAL_RSP:
1891 {
1892 PRINT_D(GENERIC_DBG, "GAS INITIAL RSP %x\n", buf[ACTION_SUBTYPE_ID]);
1893 break;
1894 }
1895
1896 case PUBLIC_ACT_VENDORSPEC:
1897 {
881eb5d8 1898 if (!memcmp(p2p_oui, &buf[ACTION_SUBTYPE_ID + 1], 4)) {
c5c77ba1 1899 if ((buf[P2P_PUB_ACTION_SUBTYPE] == GO_NEG_REQ || buf[P2P_PUB_ACTION_SUBTYPE] == GO_NEG_RSP)) {
b84a3ac4 1900 if (p2p_local_random == 1 && p2p_recv_random < p2p_local_random) {
583d972c
LK
1901 get_random_bytes(&p2p_local_random, 1);
1902 p2p_local_random++;
c5c77ba1
JK
1903 }
1904 }
1905
1906 if ((buf[P2P_PUB_ACTION_SUBTYPE] == GO_NEG_REQ || buf[P2P_PUB_ACTION_SUBTYPE] == GO_NEG_RSP
1907 || buf[P2P_PUB_ACTION_SUBTYPE] == P2P_INV_REQ || buf[P2P_PUB_ACTION_SUBTYPE] == P2P_INV_RSP)) {
b84a3ac4
LK
1908 if (p2p_local_random > p2p_recv_random) {
1909 PRINT_D(GENERIC_DBG, "LOCAL WILL BE GO LocaRand=%02x RecvRand %02x\n", p2p_local_random, p2p_recv_random);
c5c77ba1 1910
c5c77ba1 1911 for (i = P2P_PUB_ACTION_SUBTYPE + 2; i < len; i++) {
881eb5d8 1912 if (buf[i] == P2PELEM_ATTR_ID && !(memcmp(p2p_oui, &buf[i + 2], 4))) {
c5c77ba1 1913 if (buf[P2P_PUB_ACTION_SUBTYPE] == P2P_INV_REQ || buf[P2P_PUB_ACTION_SUBTYPE] == P2P_INV_RSP)
a4cac481 1914 WILC_WFI_CfgParseTxAction(&mgmt_tx->buff[i + 6], len - (i + 6), true, vif->iftype);
c5c77ba1 1915 else
a4cac481 1916 WILC_WFI_CfgParseTxAction(&mgmt_tx->buff[i + 6], len - (i + 6), false, vif->iftype);
c5c77ba1
JK
1917 break;
1918 }
1919 }
1920
1921 if (buf[P2P_PUB_ACTION_SUBTYPE] != P2P_INV_REQ && buf[P2P_PUB_ACTION_SUBTYPE] != P2P_INV_RSP) {
8668594a
LK
1922 memcpy(&mgmt_tx->buff[len], p2p_vendor_spec, sizeof(p2p_vendor_spec));
1923 mgmt_tx->buff[len + sizeof(p2p_vendor_spec)] = p2p_local_random;
c5c77ba1
JK
1924 mgmt_tx->size = buf_len;
1925 }
583d972c 1926 } else {
b84a3ac4 1927 PRINT_D(GENERIC_DBG, "PEER WILL BE GO LocaRand=%02x RecvRand %02x\n", p2p_local_random, p2p_recv_random);
583d972c 1928 }
c5c77ba1
JK
1929 }
1930
1931 } else {
1932 PRINT_D(GENERIC_DBG, "Not a P2P public action frame\n");
1933 }
1934
1935 break;
1936 }
1937
1938 default:
1939 {
1940 PRINT_D(GENERIC_DBG, "NOT HANDLED PUBLIC ACTION FRAME TYPE:%x\n", buf[ACTION_SUBTYPE_ID]);
1941 break;
1942 }
1943 }
c5c77ba1
JK
1944 }
1945
1946 PRINT_D(GENERIC_DBG, "TX: ACTION FRAME Type:%x : Chan:%d\n", buf[ACTION_SUBTYPE_ID], chan->hw_value);
1229b1ab 1947 pstrWFIDrv->p2p_timeout = (jiffies + msecs_to_jiffies(wait));
c5c77ba1 1948
1229b1ab
LK
1949 PRINT_D(GENERIC_DBG, "Current Jiffies: %lu Timeout:%llu\n",
1950 jiffies, pstrWFIDrv->p2p_timeout);
c5c77ba1
JK
1951 }
1952
829c477f
GL
1953 wilc_wlan_txq_add_mgmt_pkt(wdev->netdev, mgmt_tx,
1954 mgmt_tx->buff, mgmt_tx->size,
c9d4834d 1955 WILC_WFI_mgmt_tx_complete);
c5c77ba1
JK
1956 } else {
1957 PRINT_D(GENERIC_DBG, "This function transmits only management frames\n");
1958 }
aaed3290 1959 return 0;
c5c77ba1
JK
1960}
1961
85c587a5
CL
1962static int mgmt_tx_cancel_wait(struct wiphy *wiphy,
1963 struct wireless_dev *wdev,
1964 u64 cookie)
c5c77ba1 1965{
2726887c 1966 struct wilc_priv *priv;
441dc609 1967 struct host_if_drv *pstrWFIDrv;
8dfaafd6 1968
c5c77ba1 1969 priv = wiphy_priv(wiphy);
48b28df9 1970 pstrWFIDrv = (struct host_if_drv *)priv->hif_drv;
c5c77ba1
JK
1971
1972
1973 PRINT_D(GENERIC_DBG, "Tx Cancel wait :%lu\n", jiffies);
1229b1ab 1974 pstrWFIDrv->p2p_timeout = jiffies;
c5c77ba1 1975
7e4e87d3 1976 if (!priv->bInP2PlistenState) {
c5c77ba1
JK
1977 cfg80211_remain_on_channel_expired(priv->wdev,
1978 priv->strRemainOnChanParams.u64ListenCookie,
1979 priv->strRemainOnChanParams.pstrListenChan,
1980 GFP_KERNEL);
c5c77ba1
JK
1981 }
1982
1983 return 0;
1984}
1985
8e0735c5
CL
1986void wilc_mgmt_frame_register(struct wiphy *wiphy, struct wireless_dev *wdev,
1987 u16 frame_type, bool reg)
c5c77ba1 1988{
2726887c 1989 struct wilc_priv *priv;
a4cac481 1990 struct wilc_vif *vif;
1b86935e 1991 struct wilc *wl;
c5c77ba1
JK
1992
1993 priv = wiphy_priv(wiphy);
a4cac481
GL
1994 vif = netdev_priv(priv->wdev->netdev);
1995 wl = vif->wilc;
c5c77ba1 1996
c5c77ba1
JK
1997 if (!frame_type)
1998 return;
1999
2000 PRINT_D(GENERIC_DBG, "Frame registering Frame Type: %x: Boolean: %d\n", frame_type, reg);
2001 switch (frame_type) {
2002 case PROBE_REQ:
2003 {
a4cac481
GL
2004 vif->g_struct_frame_reg[0].frame_type = frame_type;
2005 vif->g_struct_frame_reg[0].reg = reg;
c5c77ba1
JK
2006 }
2007 break;
2008
2009 case ACTION:
2010 {
a4cac481
GL
2011 vif->g_struct_frame_reg[1].frame_type = frame_type;
2012 vif->g_struct_frame_reg[1].reg = reg;
c5c77ba1
JK
2013 }
2014 break;
2015
2016 default:
2017 {
2018 break;
2019 }
c5c77ba1 2020 }
a89f7c55 2021
1b86935e 2022 if (!wl->initialized) {
c5c77ba1
JK
2023 PRINT_D(GENERIC_DBG, "Return since mac is closed\n");
2024 return;
2025 }
fbf5379b 2026 wilc_frame_register(vif, frame_type, reg);
c5c77ba1 2027}
c5c77ba1 2028
a8047e26
CL
2029static int set_cqm_rssi_config(struct wiphy *wiphy, struct net_device *dev,
2030 s32 rssi_thold, u32 rssi_hyst)
c5c77ba1
JK
2031{
2032 PRINT_D(CFG80211_DBG, "Setting CQM RSSi Function\n");
2033 return 0;
c5c77ba1 2034}
a89f7c55 2035
bdb6338f
CL
2036static int dump_station(struct wiphy *wiphy, struct net_device *dev,
2037 int idx, u8 *mac, struct station_info *sinfo)
c5c77ba1 2038{
2726887c 2039 struct wilc_priv *priv;
cf60106b 2040 struct wilc_vif *vif;
8dfaafd6 2041
c5c77ba1
JK
2042 PRINT_D(CFG80211_DBG, "Dumping station information\n");
2043
2044 if (idx != 0)
2045 return -ENOENT;
2046
2047 priv = wiphy_priv(wiphy);
cf60106b 2048 vif = netdev_priv(priv->dev);
c5c77ba1 2049
c5c77ba1 2050 sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL);
c5c77ba1 2051
fbf5379b 2052 wilc_get_rssi(vif, &sinfo->signal);
c5c77ba1 2053
c5c77ba1 2054 return 0;
c5c77ba1
JK
2055}
2056
46530679
CL
2057static int set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,
2058 bool enabled, int timeout)
c5c77ba1 2059{
2726887c 2060 struct wilc_priv *priv;
cf60106b 2061 struct wilc_vif *vif;
8dfaafd6 2062
c5c77ba1
JK
2063 PRINT_D(CFG80211_DBG, " Power save Enabled= %d , TimeOut = %d\n", enabled, timeout);
2064
369a1d3b 2065 if (!wiphy)
c5c77ba1
JK
2066 return -ENOENT;
2067
2068 priv = wiphy_priv(wiphy);
cf60106b 2069 vif = netdev_priv(priv->dev);
06fb9336 2070 if (!priv->hif_drv)
c5c77ba1 2071 return -EIO;
c5c77ba1 2072
0e1af73d 2073 if (wilc_enable_ps)
fbf5379b 2074 wilc_set_power_mgmt(vif, enabled, timeout);
c5c77ba1
JK
2075
2076
e6e12661 2077 return 0;
c5c77ba1 2078}
108b3439 2079
3615e9a3
CL
2080static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev,
2081 enum nl80211_iftype type, u32 *flags, struct vif_params *params)
c5c77ba1 2082{
2726887c 2083 struct wilc_priv *priv;
a4cac481 2084 struct wilc_vif *vif;
299382cf 2085 struct wilc *wl;
c5c77ba1 2086
a4cac481 2087 vif = netdev_priv(dev);
c5c77ba1 2088 priv = wiphy_priv(wiphy);
a4cac481 2089 wl = vif->wilc;
c5c77ba1
JK
2090
2091 PRINT_D(HOSTAPD_DBG, "In Change virtual interface function\n");
2092 PRINT_D(HOSTAPD_DBG, "Wireless interface name =%s\n", dev->name);
583d972c 2093 p2p_local_random = 0x01;
b84a3ac4 2094 p2p_recv_random = 0x00;
a25d5186 2095 wilc_ie = false;
0e1af73d
AB
2096 wilc_optaining_ip = false;
2097 del_timer(&wilc_during_ip_timer);
c5c77ba1 2098 PRINT_D(GENERIC_DBG, "Changing virtual interface, enable scan\n");
a89f7c55 2099
c5c77ba1
JK
2100 switch (type) {
2101 case NL80211_IFTYPE_STATION:
0e1af73d 2102 wilc_connecting = 0;
c5c77ba1 2103 PRINT_D(HOSTAPD_DBG, "Interface type = NL80211_IFTYPE_STATION\n");
c5c77ba1 2104
c5c77ba1
JK
2105 dev->ieee80211_ptr->iftype = type;
2106 priv->wdev->iftype = type;
a4cac481
GL
2107 vif->monitor_flag = 0;
2108 vif->iftype = STATION_MODE;
86bff01b 2109 wilc_set_operation_mode(vif, STATION_MODE);
c5c77ba1 2110
c5c77ba1 2111 memset(priv->assoc_stainfo.au8Sta_AssociatedBss, 0, MAX_NUM_STA * ETH_ALEN);
c5c77ba1 2112
86bff01b
GL
2113 wilc_enable_ps = true;
2114 wilc_set_power_mgmt(vif, 1, 0);
c5c77ba1
JK
2115 break;
2116
2117 case NL80211_IFTYPE_P2P_CLIENT:
0e1af73d 2118 wilc_connecting = 0;
c5c77ba1 2119 PRINT_D(HOSTAPD_DBG, "Interface type = NL80211_IFTYPE_P2P_CLIENT\n");
c5c77ba1 2120
c5c77ba1
JK
2121 dev->ieee80211_ptr->iftype = type;
2122 priv->wdev->iftype = type;
a4cac481 2123 vif->monitor_flag = 0;
a4cac481 2124 vif->iftype = CLIENT_MODE;
86bff01b 2125 wilc_set_operation_mode(vif, STATION_MODE);
ee632309
GL
2126
2127 wilc_enable_ps = false;
2128 wilc_set_power_mgmt(vif, 0, 0);
c5c77ba1
JK
2129 break;
2130
2131 case NL80211_IFTYPE_AP:
0e1af73d 2132 wilc_enable_ps = false;
c5c77ba1 2133 PRINT_D(HOSTAPD_DBG, "Interface type = NL80211_IFTYPE_AP %d\n", type);
c5c77ba1
JK
2134 dev->ieee80211_ptr->iftype = type;
2135 priv->wdev->iftype = type;
a4cac481 2136 vif->iftype = AP_MODE;
86bff01b
GL
2137
2138 if (wl->initialized) {
b3306865
GL
2139 wilc_set_wfi_drv_handler(vif, wilc_get_vif_idx(vif),
2140 0);
86bff01b
GL
2141 wilc_set_operation_mode(vif, AP_MODE);
2142 wilc_set_power_mgmt(vif, 0, 0);
c5c77ba1 2143 }
c5c77ba1
JK
2144 break;
2145
2146 case NL80211_IFTYPE_P2P_GO:
2147 PRINT_D(GENERIC_DBG, "start duringIP timer\n");
2148
0e1af73d 2149 wilc_optaining_ip = true;
7e872df9
LK
2150 mod_timer(&wilc_during_ip_timer,
2151 jiffies + msecs_to_jiffies(during_ip_time));
c5c77ba1 2152 PRINT_D(HOSTAPD_DBG, "Interface type = NL80211_IFTYPE_GO\n");
86bff01b
GL
2153
2154 wilc_set_operation_mode(vif, AP_MODE);
c5c77ba1
JK
2155 dev->ieee80211_ptr->iftype = type;
2156 priv->wdev->iftype = type;
a4cac481 2157 vif->iftype = GO_MODE;
ee632309
GL
2158
2159 wilc_enable_ps = false;
2160 wilc_set_power_mgmt(vif, 0, 0);
c5c77ba1
JK
2161 break;
2162
2163 default:
06fb9336 2164 netdev_err(dev, "Unknown interface type= %d\n", type);
aaed3290 2165 return -EINVAL;
c5c77ba1
JK
2166 }
2167
aaed3290 2168 return 0;
c5c77ba1
JK
2169}
2170
a13168d7
CL
2171static int start_ap(struct wiphy *wiphy, struct net_device *dev,
2172 struct cfg80211_ap_settings *settings)
c5c77ba1
JK
2173{
2174 struct cfg80211_beacon_data *beacon = &(settings->beacon);
2726887c 2175 struct wilc_priv *priv;
e6e12661 2176 s32 s32Error = 0;
684dc186 2177 struct wilc *wl;
a4cac481 2178 struct wilc_vif *vif;
c5c77ba1
JK
2179
2180 priv = wiphy_priv(wiphy);
a4cac481
GL
2181 vif = netdev_priv(dev);
2182 wl = vif ->wilc;
c5c77ba1
JK
2183 PRINT_D(HOSTAPD_DBG, "Starting ap\n");
2184
17aacd43 2185 PRINT_D(HOSTAPD_DBG, "Interval = %d\n DTIM period = %d\n Head length = %zu Tail length = %zu\n",
c5c77ba1
JK
2186 settings->beacon_interval, settings->dtim_period, beacon->head_len, beacon->tail_len);
2187
80785a9a 2188 s32Error = set_channel(wiphy, &settings->chandef);
c5c77ba1 2189
e6e12661 2190 if (s32Error != 0)
06fb9336 2191 netdev_err(dev, "Error in setting channel\n");
c5c77ba1 2192
6750140d 2193 wilc_wlan_set_bssid(dev, wl->vif[vif->idx]->src_addr, AP_MODE);
cba352a4 2194 wilc_set_power_mgmt(vif, 0, 0);
c5c77ba1 2195
fbf5379b
GL
2196 s32Error = wilc_add_beacon(vif, settings->beacon_interval,
2197 settings->dtim_period, beacon->head_len,
2198 (u8 *)beacon->head, beacon->tail_len,
2199 (u8 *)beacon->tail);
c5c77ba1
JK
2200
2201 return s32Error;
2202}
2203
2a4c84d7
CL
2204static int change_beacon(struct wiphy *wiphy, struct net_device *dev,
2205 struct cfg80211_beacon_data *beacon)
c5c77ba1 2206{
2726887c 2207 struct wilc_priv *priv;
cf60106b 2208 struct wilc_vif *vif;
e6e12661 2209 s32 s32Error = 0;
c5c77ba1
JK
2210
2211 priv = wiphy_priv(wiphy);
cf60106b 2212 vif = netdev_priv(priv->dev);
c5c77ba1
JK
2213 PRINT_D(HOSTAPD_DBG, "Setting beacon\n");
2214
2215
fbf5379b
GL
2216 s32Error = wilc_add_beacon(vif, 0, 0, beacon->head_len,
2217 (u8 *)beacon->head, beacon->tail_len,
2218 (u8 *)beacon->tail);
c5c77ba1
JK
2219
2220 return s32Error;
2221}
2222
c8cddd79 2223static int stop_ap(struct wiphy *wiphy, struct net_device *dev)
c5c77ba1 2224{
e6e12661 2225 s32 s32Error = 0;
2726887c 2226 struct wilc_priv *priv;
cf60106b 2227 struct wilc_vif *vif;
63d03e47 2228 u8 NullBssid[ETH_ALEN] = {0};
c5c77ba1 2229
7ae43363
LK
2230 if (!wiphy)
2231 return -EFAULT;
c5c77ba1
JK
2232
2233 priv = wiphy_priv(wiphy);
cf60106b 2234 vif = netdev_priv(priv->dev);
c5c77ba1
JK
2235
2236 PRINT_D(HOSTAPD_DBG, "Deleting beacon\n");
2237
ba615f1e 2238 wilc_wlan_set_bssid(dev, NullBssid, AP_MODE);
c5c77ba1 2239
fbf5379b 2240 s32Error = wilc_del_beacon(vif);
c5c77ba1 2241
7dc1d0cc 2242 if (s32Error)
06fb9336 2243 netdev_err(dev, "Host delete beacon fail\n");
c5c77ba1 2244
c5c77ba1
JK
2245 return s32Error;
2246}
2247
ed26955c
CL
2248static int add_station(struct wiphy *wiphy, struct net_device *dev,
2249 const u8 *mac, struct station_parameters *params)
c5c77ba1 2250{
e6e12661 2251 s32 s32Error = 0;
2726887c 2252 struct wilc_priv *priv;
6a89ba9c 2253 struct add_sta_param strStaParams = { {0} };
a4cac481 2254 struct wilc_vif *vif;
c5c77ba1 2255
7ae43363
LK
2256 if (!wiphy)
2257 return -EFAULT;
c5c77ba1
JK
2258
2259 priv = wiphy_priv(wiphy);
a4cac481 2260 vif = netdev_priv(dev);
c5c77ba1 2261
a4cac481 2262 if (vif->iftype == AP_MODE || vif->iftype == GO_MODE) {
2353c388 2263 memcpy(strStaParams.bssid, mac, ETH_ALEN);
d00d2ba3 2264 memcpy(priv->assoc_stainfo.au8Sta_AssociatedBss[params->aid], mac, ETH_ALEN);
4101eb8a 2265 strStaParams.aid = params->aid;
e734223c 2266 strStaParams.rates_len = params->supported_rates_len;
a622e016 2267 strStaParams.rates = params->supported_rates;
c5c77ba1
JK
2268
2269 PRINT_D(CFG80211_DBG, "Adding station parameters %d\n", params->aid);
2270
2271 PRINT_D(CFG80211_DBG, "BSSID = %x%x%x%x%x%x\n", priv->assoc_stainfo.au8Sta_AssociatedBss[params->aid][0], priv->assoc_stainfo.au8Sta_AssociatedBss[params->aid][1], priv->assoc_stainfo.au8Sta_AssociatedBss[params->aid][2], priv->assoc_stainfo.au8Sta_AssociatedBss[params->aid][3], priv->assoc_stainfo.au8Sta_AssociatedBss[params->aid][4],
2272 priv->assoc_stainfo.au8Sta_AssociatedBss[params->aid][5]);
4101eb8a 2273 PRINT_D(HOSTAPD_DBG, "ASSOC ID = %d\n", strStaParams.aid);
e734223c
LK
2274 PRINT_D(HOSTAPD_DBG, "Number of supported rates = %d\n",
2275 strStaParams.rates_len);
c5c77ba1 2276
369a1d3b 2277 if (!params->ht_capa) {
22520120 2278 strStaParams.ht_supported = false;
c5c77ba1 2279 } else {
22520120 2280 strStaParams.ht_supported = true;
0d073f69 2281 strStaParams.ht_capa_info = params->ht_capa->cap_info;
fba1f2d2 2282 strStaParams.ht_ampdu_params = params->ht_capa->ampdu_params_info;
5ebbf4f7
LK
2283 memcpy(strStaParams.ht_supp_mcs_set,
2284 &params->ht_capa->mcs,
2285 WILC_SUPP_MCS_SET_SIZE);
223741d7 2286 strStaParams.ht_ext_params = params->ht_capa->extended_ht_cap_info;
74fe73cf 2287 strStaParams.ht_tx_bf_cap = params->ht_capa->tx_BF_cap_info;
a486baff 2288 strStaParams.ht_ante_sel = params->ht_capa->antenna_selection_info;
c5c77ba1
JK
2289 }
2290
f676e17a 2291 strStaParams.flags_mask = params->sta_flags_mask;
67ab64e4 2292 strStaParams.flags_set = params->sta_flags_set;
c5c77ba1 2293
22520120
LK
2294 PRINT_D(HOSTAPD_DBG, "IS HT supported = %d\n",
2295 strStaParams.ht_supported);
0d073f69
LK
2296 PRINT_D(HOSTAPD_DBG, "Capability Info = %d\n",
2297 strStaParams.ht_capa_info);
fba1f2d2
LK
2298 PRINT_D(HOSTAPD_DBG, "AMPDU Params = %d\n",
2299 strStaParams.ht_ampdu_params);
223741d7
LK
2300 PRINT_D(HOSTAPD_DBG, "HT Extended params = %d\n",
2301 strStaParams.ht_ext_params);
74fe73cf
LK
2302 PRINT_D(HOSTAPD_DBG, "Tx Beamforming Cap = %d\n",
2303 strStaParams.ht_tx_bf_cap);
a486baff
LK
2304 PRINT_D(HOSTAPD_DBG, "Antenna selection info = %d\n",
2305 strStaParams.ht_ante_sel);
f676e17a
LK
2306 PRINT_D(HOSTAPD_DBG, "Flag Mask = %d\n",
2307 strStaParams.flags_mask);
67ab64e4
LK
2308 PRINT_D(HOSTAPD_DBG, "Flag Set = %d\n",
2309 strStaParams.flags_set);
c5c77ba1 2310
fbf5379b 2311 s32Error = wilc_add_station(vif, &strStaParams);
7dc1d0cc 2312 if (s32Error)
06fb9336 2313 netdev_err(dev, "Host add station fail\n");
c5c77ba1
JK
2314 }
2315
c5c77ba1
JK
2316 return s32Error;
2317}
2318
a0a8be95
CL
2319static int del_station(struct wiphy *wiphy, struct net_device *dev,
2320 struct station_del_parameters *params)
c5c77ba1 2321{
057d1e97 2322 const u8 *mac = params->mac;
e6e12661 2323 s32 s32Error = 0;
2726887c 2324 struct wilc_priv *priv;
a4cac481 2325 struct wilc_vif *vif;
8dfaafd6 2326
7ae43363
LK
2327 if (!wiphy)
2328 return -EFAULT;
c5c77ba1
JK
2329
2330 priv = wiphy_priv(wiphy);
a4cac481 2331 vif = netdev_priv(dev);
c5c77ba1 2332
a4cac481 2333 if (vif->iftype == AP_MODE || vif->iftype == GO_MODE) {
c5c77ba1
JK
2334 PRINT_D(HOSTAPD_DBG, "Deleting station\n");
2335
2336
369a1d3b 2337 if (!mac) {
17aacd43 2338 PRINT_D(HOSTAPD_DBG, "All associated stations\n");
fbf5379b
GL
2339 s32Error = wilc_del_allstation(vif,
2340 priv->assoc_stainfo.au8Sta_AssociatedBss);
c5c77ba1
JK
2341 } else {
2342 PRINT_D(HOSTAPD_DBG, "With mac address: %x%x%x%x%x%x\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
2343 }
2344
fbf5379b 2345 s32Error = wilc_del_station(vif, mac);
c5c77ba1 2346
7dc1d0cc 2347 if (s32Error)
06fb9336 2348 netdev_err(dev, "Host delete station fail\n");
c5c77ba1
JK
2349 }
2350 return s32Error;
2351}
2352
14b42084
CL
2353static int change_station(struct wiphy *wiphy, struct net_device *dev,
2354 const u8 *mac, struct station_parameters *params)
c5c77ba1 2355{
e6e12661 2356 s32 s32Error = 0;
2726887c 2357 struct wilc_priv *priv;
6a89ba9c 2358 struct add_sta_param strStaParams = { {0} };
a4cac481 2359 struct wilc_vif *vif;
c5c77ba1
JK
2360
2361
2362 PRINT_D(HOSTAPD_DBG, "Change station paramters\n");
2363
7ae43363
LK
2364 if (!wiphy)
2365 return -EFAULT;
c5c77ba1
JK
2366
2367 priv = wiphy_priv(wiphy);
a4cac481 2368 vif = netdev_priv(dev);
c5c77ba1 2369
a4cac481 2370 if (vif->iftype == AP_MODE || vif->iftype == GO_MODE) {
2353c388 2371 memcpy(strStaParams.bssid, mac, ETH_ALEN);
4101eb8a 2372 strStaParams.aid = params->aid;
e734223c 2373 strStaParams.rates_len = params->supported_rates_len;
a622e016 2374 strStaParams.rates = params->supported_rates;
c5c77ba1 2375
2353c388
LK
2376 PRINT_D(HOSTAPD_DBG, "BSSID = %x%x%x%x%x%x\n",
2377 strStaParams.bssid[0], strStaParams.bssid[1],
2378 strStaParams.bssid[2], strStaParams.bssid[3],
2379 strStaParams.bssid[4], strStaParams.bssid[5]);
4101eb8a 2380 PRINT_D(HOSTAPD_DBG, "ASSOC ID = %d\n", strStaParams.aid);
e734223c
LK
2381 PRINT_D(HOSTAPD_DBG, "Number of supported rates = %d\n",
2382 strStaParams.rates_len);
c5c77ba1 2383
369a1d3b 2384 if (!params->ht_capa) {
22520120 2385 strStaParams.ht_supported = false;
c5c77ba1 2386 } else {
22520120 2387 strStaParams.ht_supported = true;
0d073f69 2388 strStaParams.ht_capa_info = params->ht_capa->cap_info;
fba1f2d2 2389 strStaParams.ht_ampdu_params = params->ht_capa->ampdu_params_info;
5ebbf4f7
LK
2390 memcpy(strStaParams.ht_supp_mcs_set,
2391 &params->ht_capa->mcs,
2392 WILC_SUPP_MCS_SET_SIZE);
223741d7 2393 strStaParams.ht_ext_params = params->ht_capa->extended_ht_cap_info;
74fe73cf 2394 strStaParams.ht_tx_bf_cap = params->ht_capa->tx_BF_cap_info;
a486baff 2395 strStaParams.ht_ante_sel = params->ht_capa->antenna_selection_info;
c5c77ba1
JK
2396 }
2397
f676e17a 2398 strStaParams.flags_mask = params->sta_flags_mask;
67ab64e4 2399 strStaParams.flags_set = params->sta_flags_set;
c5c77ba1 2400
22520120
LK
2401 PRINT_D(HOSTAPD_DBG, "IS HT supported = %d\n",
2402 strStaParams.ht_supported);
0d073f69
LK
2403 PRINT_D(HOSTAPD_DBG, "Capability Info = %d\n",
2404 strStaParams.ht_capa_info);
fba1f2d2
LK
2405 PRINT_D(HOSTAPD_DBG, "AMPDU Params = %d\n",
2406 strStaParams.ht_ampdu_params);
223741d7
LK
2407 PRINT_D(HOSTAPD_DBG, "HT Extended params = %d\n",
2408 strStaParams.ht_ext_params);
74fe73cf
LK
2409 PRINT_D(HOSTAPD_DBG, "Tx Beamforming Cap = %d\n",
2410 strStaParams.ht_tx_bf_cap);
a486baff
LK
2411 PRINT_D(HOSTAPD_DBG, "Antenna selection info = %d\n",
2412 strStaParams.ht_ante_sel);
f676e17a
LK
2413 PRINT_D(HOSTAPD_DBG, "Flag Mask = %d\n",
2414 strStaParams.flags_mask);
67ab64e4
LK
2415 PRINT_D(HOSTAPD_DBG, "Flag Set = %d\n",
2416 strStaParams.flags_set);
c5c77ba1 2417
fbf5379b 2418 s32Error = wilc_edit_station(vif, &strStaParams);
7dc1d0cc 2419 if (s32Error)
06fb9336 2420 netdev_err(dev, "Host edit station fail\n");
c5c77ba1
JK
2421 }
2422 return s32Error;
2423}
2424
37316e81
CL
2425static struct wireless_dev *add_virtual_intf(struct wiphy *wiphy,
2426 const char *name,
2427 unsigned char name_assign_type,
2428 enum nl80211_iftype type,
2429 u32 *flags,
2430 struct vif_params *params)
c5c77ba1 2431{
a4cac481 2432 struct wilc_vif *vif;
2726887c 2433 struct wilc_priv *priv;
c5c77ba1 2434 struct net_device *new_ifc = NULL;
8dfaafd6 2435
c5c77ba1
JK
2436 priv = wiphy_priv(wiphy);
2437
2438
2439
2440 PRINT_D(HOSTAPD_DBG, "Adding monitor interface[%p]\n", priv->wdev->netdev);
2441
a4cac481 2442 vif = netdev_priv(priv->wdev->netdev);
c5c77ba1
JK
2443
2444
2445 if (type == NL80211_IFTYPE_MONITOR) {
2446 PRINT_D(HOSTAPD_DBG, "Monitor interface mode: Initializing mon interface virtual device driver\n");
1006b5c7
GL
2447 PRINT_D(HOSTAPD_DBG, "Adding monitor interface[%p]\n", vif->ndev);
2448 new_ifc = WILC_WFI_init_mon_interface(name, vif->ndev);
369a1d3b 2449 if (new_ifc) {
c5c77ba1 2450 PRINT_D(HOSTAPD_DBG, "Setting monitor flag in private structure\n");
a4cac481
GL
2451 vif = netdev_priv(priv->wdev->netdev);
2452 vif->monitor_flag = 1;
06fb9336 2453 }
c5c77ba1 2454 }
c5c77ba1 2455 return priv->wdev;
c5c77ba1
JK
2456}
2457
956d7211 2458static int del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev)
c5c77ba1
JK
2459{
2460 PRINT_D(HOSTAPD_DBG, "Deleting virtual interface\n");
e6e12661 2461 return 0;
c5c77ba1
JK
2462}
2463
73584a40
GL
2464static int wilc_suspend(struct wiphy *wiphy, struct cfg80211_wowlan *wow)
2465{
2466 struct wilc_priv *priv = wiphy_priv(wiphy);
2467 struct wilc_vif *vif = netdev_priv(priv->dev);
2468
2469 if (!wow && wilc_wlan_get_num_conn_ifcs(vif->wilc))
2470 vif->wilc->suspend_event = true;
2471 else
2472 vif->wilc->suspend_event = false;
2473
2474 return 0;
2475}
2476
2477static int wilc_resume(struct wiphy *wiphy)
2478{
2479 struct wilc_priv *priv = wiphy_priv(wiphy);
2480 struct wilc_vif *vif = netdev_priv(priv->dev);
2481
2482 netdev_info(vif->ndev, "cfg resume\n");
2483 return 0;
2484}
2485
2486static void wilc_set_wakeup(struct wiphy *wiphy, bool enabled)
2487{
2488 struct wilc_priv *priv = wiphy_priv(wiphy);
2489 struct wilc_vif *vif = netdev_priv(priv->dev);
2490
2491 netdev_info(vif->ndev, "cfg set wake up = %d\n", enabled);
2492}
2493
70418790
GL
2494static int set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev,
2495 enum nl80211_tx_power_setting type, int mbm)
2496{
2497 int ret;
2498 s32 tx_power = MBM_TO_DBM(mbm);
2499 struct wilc_priv *priv = wiphy_priv(wiphy);
2500 struct wilc_vif *vif = netdev_priv(priv->dev);
2501
2502 if (tx_power < 0)
2503 tx_power = 0;
2504 else if (tx_power > 18)
2505 tx_power = 18;
2506 ret = wilc_set_tx_power(vif, tx_power);
2507 if (ret)
2508 netdev_err(vif->ndev, "Failed to set tx power\n");
2509
2510 return ret;
2511}
2512
2513static int get_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev,
2514 int *dbm)
2515{
2516 int ret;
2517 struct wilc_priv *priv = wiphy_priv(wiphy);
2518 struct wilc_vif *vif = netdev_priv(priv->dev);
2519
2520 ret = wilc_get_tx_power(vif, (u8 *)dbm);
2521 if (ret)
2522 netdev_err(vif->ndev, "Failed to get tx power\n");
2523
2524 return ret;
2525}
2526
08241924 2527static struct cfg80211_ops wilc_cfg80211_ops = {
80785a9a 2528 .set_monitor_channel = set_channel,
0e30d06d 2529 .scan = scan,
4ffbcdb6 2530 .connect = connect,
b027cde9 2531 .disconnect = disconnect,
953d417a 2532 .add_key = add_key,
3044ba7e 2533 .del_key = del_key,
f4893dfc 2534 .get_key = get_key,
0f5b8ca3 2535 .set_default_key = set_default_key,
69deb4c2 2536 .add_virtual_intf = add_virtual_intf,
b4a73355 2537 .del_virtual_intf = del_virtual_intf,
3615e9a3 2538 .change_virtual_intf = change_virtual_intf,
c5c77ba1 2539
a13168d7 2540 .start_ap = start_ap,
2a4c84d7 2541 .change_beacon = change_beacon,
c8cddd79 2542 .stop_ap = stop_ap,
ed26955c 2543 .add_station = add_station,
a0a8be95 2544 .del_station = del_station,
14b42084 2545 .change_station = change_station,
f06f562d 2546 .get_station = get_station,
bdb6338f 2547 .dump_station = dump_station,
a5f7db6a 2548 .change_bss = change_bss,
a76b63ef 2549 .set_wiphy_params = set_wiphy_params,
c5c77ba1 2550
4d46657a 2551 .set_pmksa = set_pmksa,
1ff86d96 2552 .del_pmksa = del_pmksa,
b33c39b1 2553 .flush_pmksa = flush_pmksa,
6d19d695 2554 .remain_on_channel = remain_on_channel,
1dd5440b 2555 .cancel_remain_on_channel = cancel_remain_on_channel,
4a2f9b38 2556 .mgmt_tx_cancel_wait = mgmt_tx_cancel_wait,
12a26a33 2557 .mgmt_tx = mgmt_tx,
8e0735c5 2558 .mgmt_frame_register = wilc_mgmt_frame_register,
46530679 2559 .set_power_mgmt = set_power_mgmt,
a8047e26 2560 .set_cqm_rssi_config = set_cqm_rssi_config,
c5c77ba1 2561
73584a40
GL
2562 .suspend = wilc_suspend,
2563 .resume = wilc_resume,
2564 .set_wakeup = wilc_set_wakeup,
70418790
GL
2565 .set_tx_power = set_tx_power,
2566 .get_tx_power = get_tx_power,
73584a40 2567
c5c77ba1
JK
2568};
2569
c5c77ba1
JK
2570int WILC_WFI_update_stats(struct wiphy *wiphy, u32 pktlen, u8 changed)
2571{
2726887c 2572 struct wilc_priv *priv;
c5c77ba1
JK
2573
2574 priv = wiphy_priv(wiphy);
c5c77ba1 2575 switch (changed) {
c5c77ba1
JK
2576 case WILC_WFI_RX_PKT:
2577 {
c5c77ba1
JK
2578 priv->netstats.rx_packets++;
2579 priv->netstats.rx_bytes += pktlen;
2580 priv->netstats.rx_time = get_jiffies_64();
2581 }
2582 break;
2583
2584 case WILC_WFI_TX_PKT:
2585 {
2586 priv->netstats.tx_packets++;
2587 priv->netstats.tx_bytes += pktlen;
2588 priv->netstats.tx_time = get_jiffies_64();
2589
2590 }
2591 break;
2592
2593 default:
2594 break;
2595 }
c5c77ba1
JK
2596 return 0;
2597}
c5c77ba1 2598
1608c403 2599static struct wireless_dev *WILC_WFI_CfgAlloc(void)
c5c77ba1 2600{
c5c77ba1
JK
2601 struct wireless_dev *wdev;
2602
2603
2604 PRINT_D(CFG80211_DBG, "Allocating wireless device\n");
a89f7c55 2605
c5c77ba1 2606 wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL);
06fb9336 2607 if (!wdev)
c5c77ba1 2608 goto _fail_;
c5c77ba1 2609
2726887c 2610 wdev->wiphy = wiphy_new(&wilc_cfg80211_ops, sizeof(struct wilc_priv));
06fb9336 2611 if (!wdev->wiphy)
c5c77ba1 2612 goto _fail_mem_;
c5c77ba1 2613
c5c77ba1
JK
2614 WILC_WFI_band_2ghz.ht_cap.ht_supported = 1;
2615 WILC_WFI_band_2ghz.ht_cap.cap |= (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT);
2616 WILC_WFI_band_2ghz.ht_cap.mcs.rx_mask[0] = 0xff;
2617 WILC_WFI_band_2ghz.ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_8K;
2618 WILC_WFI_band_2ghz.ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_NONE;
c5c77ba1 2619
c5c77ba1
JK
2620 wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &WILC_WFI_band_2ghz;
2621
2622 return wdev;
2623
2624_fail_mem_:
2625 kfree(wdev);
2626_fail_:
2627 return NULL;
c5c77ba1 2628}
a89f7c55 2629
2e7d5377 2630struct wireless_dev *wilc_create_wiphy(struct net_device *net, struct device *dev)
c5c77ba1 2631{
2726887c 2632 struct wilc_priv *priv;
c5c77ba1 2633 struct wireless_dev *wdev;
e6e12661 2634 s32 s32Error = 0;
c5c77ba1
JK
2635
2636 PRINT_D(CFG80211_DBG, "Registering wifi device\n");
2637
2638 wdev = WILC_WFI_CfgAlloc();
369a1d3b 2639 if (!wdev) {
06fb9336 2640 netdev_err(net, "wiphy new allocate failed\n");
c5c77ba1
JK
2641 return NULL;
2642 }
2643
c5c77ba1 2644 priv = wdev_priv(wdev);
83383ea3 2645 sema_init(&(priv->SemHandleUpdateStats), 1);
c5c77ba1 2646 priv->wdev = wdev;
c5c77ba1 2647 wdev->wiphy->max_scan_ssids = MAX_NUM_PROBED_SSID;
abb4f8ad 2648#ifdef CONFIG_PM
73584a40 2649 wdev->wiphy->wowlan = &wowlan_support;
abb4f8ad 2650#endif
c5c77ba1
JK
2651 wdev->wiphy->max_num_pmkids = WILC_MAX_NUM_PMKIDS;
2652 PRINT_INFO(CFG80211_DBG, "Max number of PMKIDs = %d\n", wdev->wiphy->max_num_pmkids);
c5c77ba1
JK
2653
2654 wdev->wiphy->max_scan_ie_len = 1000;
c5c77ba1 2655 wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
c5c77ba1
JK
2656 wdev->wiphy->cipher_suites = cipher_suites;
2657 wdev->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
c5c77ba1 2658 wdev->wiphy->mgmt_stypes = wilc_wfi_cfg80211_mgmt_types;
c5c77ba1 2659
c5c77ba1 2660 wdev->wiphy->max_remain_on_channel_duration = 500;
c5c77ba1
JK
2661 wdev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_AP) | BIT(NL80211_IFTYPE_MONITOR) | BIT(NL80211_IFTYPE_P2P_GO) |
2662 BIT(NL80211_IFTYPE_P2P_CLIENT);
c5c77ba1 2663 wdev->wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
c5c77ba1
JK
2664 wdev->iftype = NL80211_IFTYPE_STATION;
2665
2666
2667
2668 PRINT_INFO(CFG80211_DBG, "Max scan ids = %d,Max scan IE len = %d,Signal Type = %d,Interface Modes = %d,Interface Type = %d\n",
2669 wdev->wiphy->max_scan_ssids, wdev->wiphy->max_scan_ie_len, wdev->wiphy->signal_type,
2670 wdev->wiphy->interface_modes, wdev->iftype);
2671
2e7d5377 2672 set_wiphy_dev(wdev->wiphy, dev);
c5c77ba1 2673
c5c77ba1 2674 s32Error = wiphy_register(wdev->wiphy);
06fb9336
LK
2675 if (s32Error)
2676 netdev_err(net, "Cannot register wiphy device\n");
2677 else
c5c77ba1 2678 PRINT_D(CFG80211_DBG, "Successful Registering\n");
c5c77ba1 2679
c5c77ba1 2680 priv->dev = net;
c5c77ba1 2681 return wdev;
c5c77ba1 2682}
a89f7c55 2683
dd4b6a83 2684int wilc_init_host_int(struct net_device *net)
c5c77ba1 2685{
1a8ccd85 2686 int s32Error = 0;
c5c77ba1 2687
2726887c 2688 struct wilc_priv *priv;
c5c77ba1 2689
c5c77ba1
JK
2690 PRINT_D(INIT_DBG, "Host[%p][%p]\n", net, net->ieee80211_ptr);
2691 priv = wdev_priv(net->ieee80211_ptr);
2692 if (op_ifcs == 0) {
93dee8ee 2693 setup_timer(&hAgingTimer, remove_network_from_shadow, 0);
0e1af73d 2694 setup_timer(&wilc_during_ip_timer, clear_duringIP, 0);
c5c77ba1
JK
2695 }
2696 op_ifcs++;
c5c77ba1 2697
72ed4dc7 2698 priv->gbAutoRateAdjusted = false;
c5c77ba1 2699
72ed4dc7 2700 priv->bInP2PlistenState = false;
c5c77ba1 2701
83383ea3 2702 sema_init(&(priv->hSemScanReq), 1);
48b28df9 2703 s32Error = wilc_init(net, &priv->hif_drv);
f1fe9c43 2704 if (s32Error)
06fb9336 2705 netdev_err(net, "Error while initializing hostinterface\n");
f1fe9c43 2706
c5c77ba1
JK
2707 return s32Error;
2708}
2709
a9a16823 2710int wilc_deinit_host_int(struct net_device *net)
c5c77ba1 2711{
1a8ccd85 2712 int s32Error = 0;
cf60106b 2713 struct wilc_vif *vif;
2726887c 2714 struct wilc_priv *priv;
8dfaafd6 2715
c5c77ba1 2716 priv = wdev_priv(net->ieee80211_ptr);
cf60106b 2717 vif = netdev_priv(priv->dev);
c5c77ba1 2718
72ed4dc7 2719 priv->gbAutoRateAdjusted = false;
c5c77ba1 2720
72ed4dc7 2721 priv->bInP2PlistenState = false;
c5c77ba1
JK
2722
2723 op_ifcs--;
2724
fbf5379b 2725 s32Error = wilc_deinit(vif);
c5c77ba1 2726
d14991af 2727 clear_shadow_scan();
368949a7 2728 if (op_ifcs == 0)
0e1af73d 2729 del_timer_sync(&wilc_during_ip_timer);
c5c77ba1 2730
f1fe9c43 2731 if (s32Error)
06fb9336 2732 netdev_err(net, "Error while deintializing host interface\n");
f1fe9c43 2733
c5c77ba1
JK
2734 return s32Error;
2735}
2736
96da20a9 2737void wilc_free_wiphy(struct net_device *net)
c5c77ba1 2738{
c5c77ba1
JK
2739 PRINT_D(CFG80211_DBG, "Unregistering wiphy\n");
2740
619837ae 2741 if (!net) {
c5c77ba1
JK
2742 PRINT_D(INIT_DBG, "net_device is NULL\n");
2743 return;
2744 }
2745
619837ae 2746 if (!net->ieee80211_ptr) {
c5c77ba1
JK
2747 PRINT_D(INIT_DBG, "ieee80211_ptr is NULL\n");
2748 return;
2749 }
2750
619837ae 2751 if (!net->ieee80211_ptr->wiphy) {
c5c77ba1
JK
2752 PRINT_D(INIT_DBG, "wiphy is NULL\n");
2753 return;
2754 }
2755
2756 wiphy_unregister(net->ieee80211_ptr->wiphy);
2757
2758 PRINT_D(INIT_DBG, "Freeing wiphy\n");
2759 wiphy_free(net->ieee80211_ptr->wiphy);
2760 kfree(net->ieee80211_ptr);
c5c77ba1 2761}