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