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