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