GNU Linux-libre 4.14.266-gnu1
[releases.git] / drivers / staging / wilc1000 / wilc_wfi_cfgoperations.c
1 // SPDX-License-Identifier: GPL-2.0
2 #include "wilc_wfi_cfgoperations.h"
3 #include "host_interface.h"
4 #include <linux/errno.h>
5
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
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
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
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
33 #define GAS_INITIAL_REQ                 0x0a
34 #define GAS_INITIAL_RSP                 0x0b
35
36 #define INVALID_CHANNEL                 0
37
38 #define nl80211_SCAN_RESULT_EXPIRE      (3 * HZ)
39 #define SCAN_RESULT_EXPIRE              (40 * HZ)
40
41 static 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
49 static 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
78 static const struct wiphy_wowlan_support wowlan_support = {
79         .flags = WIPHY_WOWLAN_ANY
80 };
81
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
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
93 static struct network_info last_scanned_shadow[MAX_NUM_SCANNED_NETWORKS_SHADOW];
94 static u32 last_scanned_cnt;
95 struct timer_list wilc_during_ip_timer;
96 static struct timer_list hAgingTimer;
97 static u8 op_ifcs;
98
99 #define CHAN2G(_channel, _freq, _flags) {        \
100                 .band             = NL80211_BAND_2GHZ, \
101                 .center_freq      = (_freq),             \
102                 .hw_value         = (_channel),          \
103                 .flags            = (_flags),            \
104                 .max_antenna_gain = 0,                   \
105                 .max_power        = 30,                  \
106 }
107
108 static struct ieee80211_channel ieee80211_2ghz_channels[] = {
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
131 static struct ieee80211_rate ieee80211_bitrates[] = {
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
146 struct p2p_mgmt_data {
147         int size;
148         u8 *buff;
149 };
150
151 static u8 wlan_channel = INVALID_CHANNEL;
152 static u8 curr_channel;
153 static u8 p2p_oui[] = {0x50, 0x6f, 0x9A, 0x09};
154 static u8 p2p_local_random = 0x01;
155 static u8 p2p_recv_random;
156 static u8 p2p_vendor_spec[] = {0xdd, 0x05, 0x00, 0x08, 0x40, 0x03};
157 static bool wilc_ie;
158
159 static struct ieee80211_supported_band WILC_WFI_band_2ghz = {
160         .channels = ieee80211_2ghz_channels,
161         .n_channels = ARRAY_SIZE(ieee80211_2ghz_channels),
162         .bitrates = ieee80211_bitrates,
163         .n_bitrates = ARRAY_SIZE(ieee80211_bitrates),
164 };
165
166 struct add_key_params {
167         u8 key_idx;
168         bool pairwise;
169         u8 *mac_addr;
170 };
171
172 static struct add_key_params g_add_gtk_key_params;
173 static struct wilc_wfi_key g_key_gtk_params;
174 static struct add_key_params g_add_ptk_key_params;
175 static struct wilc_wfi_key g_key_ptk_params;
176 static struct wilc_wfi_wep_key g_key_wep_params;
177 static bool g_ptk_keys_saved;
178 static bool g_gtk_keys_saved;
179 static bool g_wep_keys_saved;
180
181 #define AGING_TIME      (9 * 1000)
182 #define during_ip_time  15000
183
184 static void clear_shadow_scan(void)
185 {
186         int i;
187
188         if (op_ifcs == 0) {
189                 del_timer_sync(&hAgingTimer);
190
191                 for (i = 0; i < last_scanned_cnt; i++) {
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;
195                         }
196
197                         kfree(last_scanned_shadow[i].join_params);
198                         last_scanned_shadow[i].join_params = NULL;
199                 }
200                 last_scanned_cnt = 0;
201         }
202 }
203
204 static u32 get_rssi_avg(struct network_info *network_info)
205 {
206         u8 i;
207         int rssi_v = 0;
208         u8 num_rssi = (network_info->rssi_history.full) ?
209                        NUM_RSSI : (network_info->rssi_history.index);
210
211         for (i = 0; i < num_rssi; i++)
212                 rssi_v += network_info->rssi_history.samples[i];
213
214         rssi_v /= num_rssi;
215         return rssi_v;
216 }
217
218 static void refresh_scan(struct wilc_priv *priv, bool direct_scan)
219 {
220         struct wiphy *wiphy = priv->dev->ieee80211_ptr->wiphy;
221         int i;
222
223         for (i = 0; i < last_scanned_cnt; i++) {
224                 struct network_info *network_info;
225                 s32 freq;
226                 struct ieee80211_channel *channel;
227                 int rssi;
228                 struct cfg80211_bss *bss;
229
230                 network_info = &last_scanned_shadow[i];
231
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);
251         }
252 }
253
254 static void reset_shadow_found(void)
255 {
256         int i;
257
258         for (i = 0; i < last_scanned_cnt; i++)
259                 last_scanned_shadow[i].found = 0;
260 }
261
262 static void update_scan_time(void)
263 {
264         int i;
265
266         for (i = 0; i < last_scanned_cnt; i++)
267                 last_scanned_shadow[i].time_scan = jiffies;
268 }
269
270 static void remove_network_from_shadow(unsigned long arg)
271 {
272         unsigned long now = jiffies;
273         int i, j;
274
275         for (i = 0; i < last_scanned_cnt; i++) {
276                 if (time_after(now, last_scanned_shadow[i].time_scan +
277                                (unsigned long)(SCAN_RESULT_EXPIRE))) {
278                         kfree(last_scanned_shadow[i].ies);
279                         last_scanned_shadow[i].ies = NULL;
280
281                         kfree(last_scanned_shadow[i].join_params);
282
283                         for (j = i; (j < last_scanned_cnt - 1); j++)
284                                 last_scanned_shadow[j] = last_scanned_shadow[j + 1];
285
286                         last_scanned_cnt--;
287                 }
288         }
289
290         if (last_scanned_cnt != 0) {
291                 hAgingTimer.data = arg;
292                 mod_timer(&hAgingTimer, jiffies + msecs_to_jiffies(AGING_TIME));
293         }
294 }
295
296 static void clear_duringIP(unsigned long arg)
297 {
298         wilc_optaining_ip = false;
299 }
300
301 static int is_network_in_shadow(struct network_info *pstrNetworkInfo,
302                                 void *user_void)
303 {
304         int state = -1;
305         int i;
306
307         if (last_scanned_cnt == 0) {
308                 hAgingTimer.data = (unsigned long)user_void;
309                 mod_timer(&hAgingTimer, jiffies + msecs_to_jiffies(AGING_TIME));
310                 state = -1;
311         } else {
312                 for (i = 0; i < last_scanned_cnt; i++) {
313                         if (memcmp(last_scanned_shadow[i].bssid,
314                                    pstrNetworkInfo->bssid, 6) == 0) {
315                                 state = i;
316                                 break;
317                         }
318                 }
319         }
320         return state;
321 }
322
323 static void add_network_to_shadow(struct network_info *pstrNetworkInfo,
324                                   void *user_void, void *pJoinParams)
325 {
326         int ap_found = is_network_in_shadow(pstrNetworkInfo, user_void);
327         u32 ap_index = 0;
328         u8 rssi_index = 0;
329
330         if (last_scanned_cnt >= MAX_NUM_SCANNED_NETWORKS_SHADOW)
331                 return;
332
333         if (ap_found == -1) {
334                 ap_index = last_scanned_cnt;
335                 last_scanned_cnt++;
336         } else {
337                 ap_index = ap_found;
338         }
339         rssi_index = last_scanned_shadow[ap_index].rssi_history.index;
340         last_scanned_shadow[ap_index].rssi_history.samples[rssi_index++] = pstrNetworkInfo->rssi;
341         if (rssi_index == NUM_RSSI) {
342                 rssi_index = 0;
343                 last_scanned_shadow[ap_index].rssi_history.full = true;
344         }
345         last_scanned_shadow[ap_index].rssi_history.index = rssi_index;
346         last_scanned_shadow[ap_index].rssi = pstrNetworkInfo->rssi;
347         last_scanned_shadow[ap_index].cap_info = pstrNetworkInfo->cap_info;
348         last_scanned_shadow[ap_index].ssid_len = pstrNetworkInfo->ssid_len;
349         memcpy(last_scanned_shadow[ap_index].ssid,
350                pstrNetworkInfo->ssid, pstrNetworkInfo->ssid_len);
351         memcpy(last_scanned_shadow[ap_index].bssid,
352                pstrNetworkInfo->bssid, ETH_ALEN);
353         last_scanned_shadow[ap_index].beacon_period = pstrNetworkInfo->beacon_period;
354         last_scanned_shadow[ap_index].dtim_period = pstrNetworkInfo->dtim_period;
355         last_scanned_shadow[ap_index].ch = pstrNetworkInfo->ch;
356         last_scanned_shadow[ap_index].ies_len = pstrNetworkInfo->ies_len;
357         last_scanned_shadow[ap_index].tsf_hi = pstrNetworkInfo->tsf_hi;
358         if (ap_found != -1)
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);
364         last_scanned_shadow[ap_index].time_scan = jiffies;
365         last_scanned_shadow[ap_index].time_scan_cached = jiffies;
366         last_scanned_shadow[ap_index].found = 1;
367         if (ap_found != -1)
368                 kfree(last_scanned_shadow[ap_index].join_params);
369         last_scanned_shadow[ap_index].join_params = pJoinParams;
370 }
371
372 static void CfgScanResult(enum scan_event scan_event,
373                           struct network_info *network_info,
374                           void *user_void,
375                           void *join_params)
376 {
377         struct wilc_priv *priv;
378         struct wiphy *wiphy;
379         s32 s32Freq;
380         struct ieee80211_channel *channel;
381         struct cfg80211_bss *bss = NULL;
382
383         priv = user_void;
384         if (priv->bCfgScanning) {
385                 if (scan_event == SCAN_EVENT_NETWORK_FOUND) {
386                         wiphy = priv->dev->ieee80211_ptr->wiphy;
387
388                         if (!wiphy)
389                                 return;
390
391                         if (wiphy->signal_type == CFG80211_SIGNAL_TYPE_UNSPEC &&
392                             (((s32)network_info->rssi * 100) < 0 ||
393                             ((s32)network_info->rssi * 100) > 100))
394                                 return;
395
396                         if (network_info) {
397                                 s32Freq = ieee80211_channel_to_frequency((s32)network_info->ch, NL80211_BAND_2GHZ);
398                                 channel = ieee80211_get_channel(wiphy, s32Freq);
399
400                                 if (!channel)
401                                         return;
402
403                                 if (network_info->new_network) {
404                                         if (priv->u32RcvdChCount < MAX_NUM_SCANNED_NETWORKS) {
405                                                 priv->u32RcvdChCount++;
406
407                                                 add_network_to_shadow(network_info, priv, join_params);
408
409                                                 if (!(memcmp("DIRECT-", network_info->ssid, 7))) {
410                                                         bss = cfg80211_inform_bss(wiphy,
411                                                                                   channel,
412                                                                                   CFG80211_BSS_FTYPE_UNKNOWN,
413                                                                                   network_info->bssid,
414                                                                                   network_info->tsf_hi,
415                                                                                   network_info->cap_info,
416                                                                                   network_info->beacon_period,
417                                                                                   (const u8 *)network_info->ies,
418                                                                                   (size_t)network_info->ies_len,
419                                                                                   (s32)network_info->rssi * 100,
420                                                                                   GFP_KERNEL);
421                                                         cfg80211_put_bss(wiphy, bss);
422                                                 }
423                                         }
424                                 } else {
425                                         u32 i;
426
427                                         for (i = 0; i < priv->u32RcvdChCount; i++) {
428                                                 if (memcmp(last_scanned_shadow[i].bssid, network_info->bssid, 6) == 0) {
429                                                         last_scanned_shadow[i].rssi = network_info->rssi;
430                                                         last_scanned_shadow[i].time_scan = jiffies;
431                                                         break;
432                                                 }
433                                         }
434                                 }
435                         }
436                 } else if (scan_event == SCAN_EVENT_DONE) {
437                         refresh_scan(priv, false);
438
439                         mutex_lock(&priv->scan_req_lock);
440
441                         if (priv->pstrScanReq) {
442                                 struct cfg80211_scan_info info = {
443                                         .aborted = false,
444                                 };
445
446                                 cfg80211_scan_done(priv->pstrScanReq, &info);
447                                 priv->u32RcvdChCount = 0;
448                                 priv->bCfgScanning = false;
449                                 priv->pstrScanReq = NULL;
450                         }
451                         mutex_unlock(&priv->scan_req_lock);
452                 } else if (scan_event == SCAN_EVENT_ABORTED) {
453                         mutex_lock(&priv->scan_req_lock);
454
455                         if (priv->pstrScanReq) {
456                                 struct cfg80211_scan_info info = {
457                                         .aborted = false,
458                                 };
459
460                                 update_scan_time();
461                                 refresh_scan(priv, false);
462
463                                 cfg80211_scan_done(priv->pstrScanReq, &info);
464                                 priv->bCfgScanning = false;
465                                 priv->pstrScanReq = NULL;
466                         }
467                         mutex_unlock(&priv->scan_req_lock);
468                 }
469         }
470 }
471
472 int wilc_connecting;
473
474 static void CfgConnectResult(enum conn_event enuConnDisconnEvent,
475                              struct connect_info *pstrConnectInfo,
476                              u8 u8MacStatus,
477                              struct disconnect_info *pstrDisconnectNotifInfo,
478                              void *pUserVoid)
479 {
480         struct wilc_priv *priv;
481         struct net_device *dev;
482         struct host_if_drv *pstrWFIDrv;
483         u8 NullBssid[ETH_ALEN] = {0};
484         struct wilc *wl;
485         struct wilc_vif *vif;
486
487         wilc_connecting = 0;
488
489         priv = pUserVoid;
490         dev = priv->dev;
491         vif = netdev_priv(dev);
492         wl = vif->wilc;
493         pstrWFIDrv = (struct host_if_drv *)priv->hif_drv;
494
495         if (enuConnDisconnEvent == CONN_DISCONN_EVENT_CONN_RESP) {
496                 u16 u16ConnectStatus;
497
498                 u16ConnectStatus = pstrConnectInfo->status;
499
500                 if ((u8MacStatus == MAC_DISCONNECTED) &&
501                     (pstrConnectInfo->status == SUCCESSFUL_STATUSCODE)) {
502                         u16ConnectStatus = WLAN_STATUS_UNSPECIFIED_FAILURE;
503                         wilc_wlan_set_bssid(priv->dev, NullBssid,
504                                             STATION_MODE);
505                         eth_zero_addr(wilc_connected_ssid);
506
507                         if (!pstrWFIDrv->p2p_connect)
508                                 wlan_channel = INVALID_CHANNEL;
509
510                         netdev_err(dev, "Unspecified failure\n");
511                 }
512
513                 if (u16ConnectStatus == WLAN_STATUS_SUCCESS) {
514                         bool bNeedScanRefresh = false;
515                         u32 i;
516
517                         memcpy(priv->au8AssociatedBss, pstrConnectInfo->bssid, ETH_ALEN);
518
519                         for (i = 0; i < last_scanned_cnt; i++) {
520                                 if (memcmp(last_scanned_shadow[i].bssid,
521                                            pstrConnectInfo->bssid,
522                                            ETH_ALEN) == 0) {
523                                         unsigned long now = jiffies;
524
525                                         if (time_after(now,
526                                                        last_scanned_shadow[i].time_scan_cached +
527                                                        (unsigned long)(nl80211_SCAN_RESULT_EXPIRE - (1 * HZ))))
528                                                 bNeedScanRefresh = true;
529
530                                         break;
531                                 }
532                         }
533
534                         if (bNeedScanRefresh)
535                                 refresh_scan(priv, true);
536                 }
537
538                 cfg80211_connect_result(dev, pstrConnectInfo->bssid,
539                                         pstrConnectInfo->req_ies, pstrConnectInfo->req_ies_len,
540                                         pstrConnectInfo->resp_ies, pstrConnectInfo->resp_ies_len,
541                                         u16ConnectStatus, GFP_KERNEL);
542         } else if (enuConnDisconnEvent == CONN_DISCONN_EVENT_DISCONN_NOTIF)    {
543                 wilc_optaining_ip = false;
544                 p2p_local_random = 0x01;
545                 p2p_recv_random = 0x00;
546                 wilc_ie = false;
547                 eth_zero_addr(priv->au8AssociatedBss);
548                 wilc_wlan_set_bssid(priv->dev, NullBssid, STATION_MODE);
549                 eth_zero_addr(wilc_connected_ssid);
550
551                 if (!pstrWFIDrv->p2p_connect)
552                         wlan_channel = INVALID_CHANNEL;
553                 if ((pstrWFIDrv->IFC_UP) && (dev == wl->vif[1]->ndev))
554                         pstrDisconnectNotifInfo->reason = 3;
555                 else if ((!pstrWFIDrv->IFC_UP) && (dev == wl->vif[1]->ndev))
556                         pstrDisconnectNotifInfo->reason = 1;
557
558                 cfg80211_disconnected(dev, pstrDisconnectNotifInfo->reason, pstrDisconnectNotifInfo->ie,
559                                       pstrDisconnectNotifInfo->ie_len, false,
560                                       GFP_KERNEL);
561         }
562 }
563
564 static int set_channel(struct wiphy *wiphy,
565                        struct cfg80211_chan_def *chandef)
566 {
567         u32 channelnum = 0;
568         struct wilc_priv *priv;
569         int result = 0;
570         struct wilc_vif *vif;
571
572         priv = wiphy_priv(wiphy);
573         vif = netdev_priv(priv->dev);
574
575         channelnum = ieee80211_frequency_to_channel(chandef->chan->center_freq);
576
577         curr_channel = channelnum;
578         result = wilc_set_mac_chnl_num(vif, channelnum);
579
580         if (result != 0)
581                 netdev_err(priv->dev, "Error in setting channel\n");
582
583         return result;
584 }
585
586 static int scan(struct wiphy *wiphy, struct cfg80211_scan_request *request)
587 {
588         struct wilc_priv *priv;
589         u32 i;
590         s32 s32Error = 0;
591         u8 au8ScanChanList[MAX_NUM_SCANNED_NETWORKS];
592         struct hidden_network strHiddenNetwork;
593         struct wilc_vif *vif;
594
595         priv = wiphy_priv(wiphy);
596         vif = netdev_priv(priv->dev);
597
598         priv->pstrScanReq = request;
599
600         priv->u32RcvdChCount = 0;
601
602         reset_shadow_found();
603
604         priv->bCfgScanning = true;
605         if (request->n_channels <= MAX_NUM_SCANNED_NETWORKS) {
606                 for (i = 0; i < request->n_channels; i++)
607                         au8ScanChanList[i] = (u8)ieee80211_frequency_to_channel(request->channels[i]->center_freq);
608
609                 if (request->n_ssids >= 1) {
610                         strHiddenNetwork.net_info =
611                                 kmalloc_array(request->n_ssids,
612                                               sizeof(struct hidden_network),
613                                               GFP_KERNEL);
614                         if (!strHiddenNetwork.net_info)
615                                 return -ENOMEM;
616                         strHiddenNetwork.n_ssids = request->n_ssids;
617
618                         for (i = 0; i < request->n_ssids; i++) {
619                                 if (request->ssids[i].ssid_len != 0) {
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;
623                                 } else {
624                                         strHiddenNetwork.n_ssids -= 1;
625                                 }
626                         }
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);
633                 } else {
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);
640                 }
641         } else {
642                 netdev_err(priv->dev, "Requested scanned channels over\n");
643         }
644
645         if (s32Error != 0)
646                 s32Error = -EBUSY;
647
648         return s32Error;
649 }
650
651 static int connect(struct wiphy *wiphy, struct net_device *dev,
652                    struct cfg80211_connect_params *sme)
653 {
654         s32 s32Error = 0;
655         u32 i;
656         u32 sel_bssi_idx = UINT_MAX;
657         u8 u8security = NO_ENCRYPT;
658         enum AUTHTYPE tenuAuth_type = ANY;
659
660         struct wilc_priv *priv;
661         struct host_if_drv *pstrWFIDrv;
662         struct network_info *pstrNetworkInfo = NULL;
663         struct wilc_vif *vif;
664
665         wilc_connecting = 1;
666         priv = wiphy_priv(wiphy);
667         vif = netdev_priv(priv->dev);
668         pstrWFIDrv = (struct host_if_drv *)priv->hif_drv;
669
670         if (!(strncmp(sme->ssid, "DIRECT-", 7)))
671                 pstrWFIDrv->p2p_connect = 1;
672         else
673                 pstrWFIDrv->p2p_connect = 0;
674
675         for (i = 0; i < last_scanned_cnt; i++) {
676                 if ((sme->ssid_len == last_scanned_shadow[i].ssid_len) &&
677                     memcmp(last_scanned_shadow[i].ssid,
678                            sme->ssid,
679                            sme->ssid_len) == 0) {
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 {
686                                 if (memcmp(last_scanned_shadow[i].bssid,
687                                            sme->bssid,
688                                            ETH_ALEN) == 0) {
689                                         sel_bssi_idx = i;
690                                         break;
691                                 }
692                         }
693                 }
694         }
695
696         if (sel_bssi_idx < last_scanned_cnt) {
697                 pstrNetworkInfo = &last_scanned_shadow[sel_bssi_idx];
698         } else {
699                 s32Error = -ENOENT;
700                 wilc_connecting = 0;
701                 return s32Error;
702         }
703
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));
706
707         if (sme->crypto.cipher_group != NO_ENCRYPT) {
708                 if (sme->crypto.cipher_group == WLAN_CIPHER_SUITE_WEP40) {
709                         u8security = ENCRYPT_ENABLED | WEP;
710
711                         priv->WILC_WFI_wep_key_len[sme->key_idx] = sme->key_len;
712                         memcpy(priv->WILC_WFI_wep_key[sme->key_idx], sme->key, sme->key_len);
713
714                         g_key_wep_params.key_len = sme->key_len;
715                         g_key_wep_params.key = kmalloc(sme->key_len, GFP_KERNEL);
716                         memcpy(g_key_wep_params.key, sme->key, sme->key_len);
717                         g_key_wep_params.key_idx = sme->key_idx;
718                         g_wep_keys_saved = true;
719
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);
723                 } else if (sme->crypto.cipher_group == WLAN_CIPHER_SUITE_WEP104)   {
724                         u8security = ENCRYPT_ENABLED | WEP | WEP_EXTENDED;
725
726                         priv->WILC_WFI_wep_key_len[sme->key_idx] = sme->key_len;
727                         memcpy(priv->WILC_WFI_wep_key[sme->key_idx], sme->key, sme->key_len);
728
729                         g_key_wep_params.key_len = sme->key_len;
730                         g_key_wep_params.key = kmalloc(sme->key_len, GFP_KERNEL);
731                         memcpy(g_key_wep_params.key, sme->key, sme->key_len);
732                         g_key_wep_params.key_idx = sme->key_idx;
733                         g_wep_keys_saved = true;
734
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);
738                 } else if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_2)   {
739                         if (sme->crypto.cipher_group == WLAN_CIPHER_SUITE_TKIP)
740                                 u8security = ENCRYPT_ENABLED | WPA2 | TKIP;
741                         else
742                                 u8security = ENCRYPT_ENABLED | WPA2 | AES;
743                 } else if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_1)   {
744                         if (sme->crypto.cipher_group == WLAN_CIPHER_SUITE_TKIP)
745                                 u8security = ENCRYPT_ENABLED | WPA | TKIP;
746                         else
747                                 u8security = ENCRYPT_ENABLED | WPA | AES;
748                 } else {
749                         s32Error = -ENOTSUPP;
750                         netdev_err(dev, "Not supported cipher\n");
751                         wilc_connecting = 0;
752                         return s32Error;
753                 }
754         }
755
756         if ((sme->crypto.wpa_versions & NL80211_WPA_VERSION_1) ||
757             (sme->crypto.wpa_versions & NL80211_WPA_VERSION_2)) {
758                 for (i = 0; i < sme->crypto.n_ciphers_pairwise; i++) {
759                         if (sme->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_TKIP)
760                                 u8security = u8security | TKIP;
761                         else
762                                 u8security = u8security | AES;
763                 }
764         }
765
766         switch (sme->auth_type) {
767         case NL80211_AUTHTYPE_OPEN_SYSTEM:
768                 tenuAuth_type = OPEN_SYSTEM;
769                 break;
770
771         case NL80211_AUTHTYPE_SHARED_KEY:
772                 tenuAuth_type = SHARED_KEY;
773                 break;
774
775         default:
776                 break;
777         }
778
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
790         curr_channel = pstrNetworkInfo->ch;
791
792         if (!pstrWFIDrv->p2p_connect)
793                 wlan_channel = pstrNetworkInfo->ch;
794
795         wilc_wlan_set_bssid(dev, pstrNetworkInfo->bssid, STATION_MODE);
796
797         s32Error = wilc_set_join_req(vif, pstrNetworkInfo->bssid, sme->ssid,
798                                      sme->ssid_len, sme->ie, sme->ie_len,
799                                      CfgConnectResult, (void *)priv,
800                                      u8security, tenuAuth_type,
801                                      pstrNetworkInfo->ch,
802                                      pstrNetworkInfo->join_params);
803         if (s32Error != 0) {
804                 netdev_err(dev, "wilc_set_join_req(): Error\n");
805                 s32Error = -ENOENT;
806                 wilc_connecting = 0;
807                 return s32Error;
808         }
809
810         return s32Error;
811 }
812
813 static int disconnect(struct wiphy *wiphy, struct net_device *dev, u16 reason_code)
814 {
815         s32 s32Error = 0;
816         struct wilc_priv *priv;
817         struct host_if_drv *pstrWFIDrv;
818         struct wilc_vif *vif;
819         struct wilc *wilc;
820         u8 NullBssid[ETH_ALEN] = {0};
821
822         wilc_connecting = 0;
823         priv = wiphy_priv(wiphy);
824         vif = netdev_priv(priv->dev);
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         }
835
836         pstrWFIDrv = (struct host_if_drv *)priv->hif_drv;
837         if (!pstrWFIDrv->p2p_connect)
838                 wlan_channel = INVALID_CHANNEL;
839         wilc_wlan_set_bssid(priv->dev, NullBssid, STATION_MODE);
840
841         p2p_local_random = 0x01;
842         p2p_recv_random = 0x00;
843         wilc_ie = false;
844         pstrWFIDrv->p2p_timeout = 0;
845
846         s32Error = wilc_disconnect(vif, reason_code);
847         if (s32Error != 0) {
848                 netdev_err(priv->dev, "Error in disconnecting\n");
849                 s32Error = -EINVAL;
850         }
851
852         return s32Error;
853 }
854
855 static 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)
858
859 {
860         s32 s32Error = 0, KeyLen = params->key_len;
861         struct wilc_priv *priv;
862         const u8 *pu8RxMic = NULL;
863         const u8 *pu8TxMic = NULL;
864         u8 u8mode = NO_ENCRYPT;
865         u8 u8gmode = NO_ENCRYPT;
866         u8 u8pmode = NO_ENCRYPT;
867         enum AUTHTYPE tenuAuth_type = ANY;
868         struct wilc *wl;
869         struct wilc_vif *vif;
870
871         priv = wiphy_priv(wiphy);
872         vif = netdev_priv(netdev);
873         wl = vif->wilc;
874
875         switch (params->cipher) {
876         case WLAN_CIPHER_SUITE_WEP40:
877         case WLAN_CIPHER_SUITE_WEP104:
878                 if (priv->wdev->iftype == NL80211_IFTYPE_AP) {
879                         priv->WILC_WFI_wep_key_len[key_index] = params->key_len;
880                         memcpy(priv->WILC_WFI_wep_key[key_index], params->key, params->key_len);
881
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
889                         wilc_add_wep_key_bss_ap(vif, params->key,
890                                                 params->key_len, key_index,
891                                                 u8mode, tenuAuth_type);
892                         break;
893                 }
894                 if (memcmp(params->key, priv->WILC_WFI_wep_key[key_index], params->key_len)) {
895                         priv->WILC_WFI_wep_key_len[key_index] = params->key_len;
896                         memcpy(priv->WILC_WFI_wep_key[key_index], params->key, params->key_len);
897
898                         wilc_add_wep_key_bss_sta(vif, params->key,
899                                                  params->key_len, key_index);
900                 }
901
902                 break;
903
904         case WLAN_CIPHER_SUITE_TKIP:
905         case WLAN_CIPHER_SUITE_CCMP:
906                 if (priv->wdev->iftype == NL80211_IFTYPE_AP || priv->wdev->iftype == NL80211_IFTYPE_P2P_GO) {
907                         if (!priv->wilc_gtk[key_index]) {
908                                 priv->wilc_gtk[key_index] = kmalloc(sizeof(struct wilc_wfi_key), GFP_KERNEL);
909                                 priv->wilc_gtk[key_index]->key = NULL;
910                                 priv->wilc_gtk[key_index]->seq = NULL;
911                         }
912                         if (!priv->wilc_ptk[key_index]) {
913                                 priv->wilc_ptk[key_index] = kmalloc(sizeof(struct wilc_wfi_key), GFP_KERNEL);
914                                 priv->wilc_ptk[key_index]->key = NULL;
915                                 priv->wilc_ptk[key_index]->seq = NULL;
916                         }
917
918                         if (!pairwise) {
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) {
927                                         pu8TxMic = params->key + 24;
928                                         pu8RxMic = params->key + 16;
929                                         KeyLen = params->key_len - 16;
930                                 }
931                                 kfree(priv->wilc_gtk[key_index]->key);
932
933                                 priv->wilc_gtk[key_index]->key = kmalloc(params->key_len, GFP_KERNEL);
934                                 memcpy(priv->wilc_gtk[key_index]->key, params->key, params->key_len);
935                                 kfree(priv->wilc_gtk[key_index]->seq);
936
937                                 if ((params->seq_len) > 0) {
938                                         priv->wilc_gtk[key_index]->seq = kmalloc(params->seq_len, GFP_KERNEL);
939                                         memcpy(priv->wilc_gtk[key_index]->seq, params->seq, params->seq_len);
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
946                                 wilc_add_rx_gtk(vif, params->key, KeyLen,
947                                                 key_index, params->seq_len,
948                                                 params->seq, pu8RxMic,
949                                                 pu8TxMic, AP_MODE, u8gmode);
950
951                         } else {
952                                 if (params->cipher == WLAN_CIPHER_SUITE_TKIP)
953                                         u8pmode = ENCRYPT_ENABLED | WPA | TKIP;
954                                 else
955                                         u8pmode = priv->wilc_groupkey | AES;
956
957                                 if (params->key_len > 16 && params->cipher == WLAN_CIPHER_SUITE_TKIP) {
958                                         pu8TxMic = params->key + 24;
959                                         pu8RxMic = params->key + 16;
960                                         KeyLen = params->key_len - 16;
961                                 }
962
963                                 kfree(priv->wilc_ptk[key_index]->key);
964
965                                 priv->wilc_ptk[key_index]->key = kmalloc(params->key_len, GFP_KERNEL);
966
967                                 kfree(priv->wilc_ptk[key_index]->seq);
968
969                                 if ((params->seq_len) > 0)
970                                         priv->wilc_ptk[key_index]->seq = kmalloc(params->seq_len, GFP_KERNEL);
971
972                                 memcpy(priv->wilc_ptk[key_index]->key, params->key, params->key_len);
973
974                                 if ((params->seq_len) > 0)
975                                         memcpy(priv->wilc_ptk[key_index]->seq, params->seq, params->seq_len);
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
981                                 wilc_add_ptk(vif, params->key, KeyLen,
982                                              mac_addr, pu8RxMic, pu8TxMic,
983                                              AP_MODE, u8pmode, key_index);
984                         }
985                         break;
986                 }
987
988                 {
989                         u8mode = 0;
990                         if (!pairwise) {
991                                 if (params->key_len > 16 && params->cipher == WLAN_CIPHER_SUITE_TKIP) {
992                                         pu8RxMic = params->key + 24;
993                                         pu8TxMic = params->key + 16;
994                                         KeyLen = params->key_len - 16;
995                                 }
996
997                                 if (!g_gtk_keys_saved && netdev == wl->vif[0]->ndev) {
998                                         g_add_gtk_key_params.key_idx = key_index;
999                                         g_add_gtk_key_params.pairwise = pairwise;
1000                                         if (!mac_addr) {
1001                                                 g_add_gtk_key_params.mac_addr = NULL;
1002                                         } else {
1003                                                 g_add_gtk_key_params.mac_addr = kmalloc(ETH_ALEN, GFP_KERNEL);
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;
1008                                         g_key_gtk_params.key =  kmalloc(params->key_len, GFP_KERNEL);
1009                                         memcpy(g_key_gtk_params.key, params->key, params->key_len);
1010                                         if (params->seq_len > 0) {
1011                                                 g_key_gtk_params.seq =  kmalloc(params->seq_len, GFP_KERNEL);
1012                                                 memcpy(g_key_gtk_params.seq, params->seq, params->seq_len);
1013                                         }
1014                                         g_key_gtk_params.cipher = params->cipher;
1015                                         g_gtk_keys_saved = true;
1016                                 }
1017
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);
1023                         } else {
1024                                 if (params->key_len > 16 && params->cipher == WLAN_CIPHER_SUITE_TKIP) {
1025                                         pu8RxMic = params->key + 24;
1026                                         pu8TxMic = params->key + 16;
1027                                         KeyLen = params->key_len - 16;
1028                                 }
1029
1030                                 if (!g_ptk_keys_saved && netdev == wl->vif[0]->ndev) {
1031                                         g_add_ptk_key_params.key_idx = key_index;
1032                                         g_add_ptk_key_params.pairwise = pairwise;
1033                                         if (!mac_addr) {
1034                                                 g_add_ptk_key_params.mac_addr = NULL;
1035                                         } else {
1036                                                 g_add_ptk_key_params.mac_addr = kmalloc(ETH_ALEN, GFP_KERNEL);
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;
1041                                         g_key_ptk_params.key =  kmalloc(params->key_len, GFP_KERNEL);
1042                                         memcpy(g_key_ptk_params.key, params->key, params->key_len);
1043                                         if (params->seq_len > 0) {
1044                                                 g_key_ptk_params.seq =  kmalloc(params->seq_len, GFP_KERNEL);
1045                                                 memcpy(g_key_ptk_params.seq, params->seq, params->seq_len);
1046                                         }
1047                                         g_key_ptk_params.cipher = params->cipher;
1048                                         g_ptk_keys_saved = true;
1049                                 }
1050
1051                                 wilc_add_ptk(vif, params->key, KeyLen,
1052                                              mac_addr, pu8RxMic, pu8TxMic,
1053                                              STATION_MODE, u8mode, key_index);
1054                         }
1055                 }
1056                 break;
1057
1058         default:
1059                 netdev_err(netdev, "Not supported cipher\n");
1060                 s32Error = -ENOTSUPP;
1061         }
1062
1063         return s32Error;
1064 }
1065
1066 static int del_key(struct wiphy *wiphy, struct net_device *netdev,
1067                    u8 key_index,
1068                    bool pairwise,
1069                    const u8 *mac_addr)
1070 {
1071         struct wilc_priv *priv;
1072         struct wilc *wl;
1073         struct wilc_vif *vif;
1074
1075         priv = wiphy_priv(wiphy);
1076         vif = netdev_priv(netdev);
1077         wl = vif->wilc;
1078
1079         if (netdev == wl->vif[0]->ndev) {
1080                 g_ptk_keys_saved = false;
1081                 g_gtk_keys_saved = false;
1082                 g_wep_keys_saved = false;
1083
1084                 kfree(g_key_wep_params.key);
1085                 g_key_wep_params.key = NULL;
1086
1087                 if ((priv->wilc_gtk[key_index]) != NULL) {
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;
1092
1093                         kfree(priv->wilc_gtk[key_index]);
1094                         priv->wilc_gtk[key_index] = NULL;
1095                 }
1096
1097                 if ((priv->wilc_ptk[key_index]) != NULL) {
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;
1102                         kfree(priv->wilc_ptk[key_index]);
1103                         priv->wilc_ptk[key_index] = NULL;
1104                 }
1105
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;
1115
1116         }
1117
1118         if (key_index >= 0 && key_index <= 3) {
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                 }
1125         } else {
1126                 wilc_remove_key(priv->hif_drv, mac_addr);
1127         }
1128
1129         return 0;
1130 }
1131
1132 static 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 *))
1135 {
1136         struct wilc_priv *priv;
1137         struct  key_params key_params;
1138
1139         priv = wiphy_priv(wiphy);
1140
1141         if (!pairwise) {
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;
1147         } else {
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
1157         return 0;
1158 }
1159
1160 static int set_default_key(struct wiphy *wiphy, struct net_device *netdev, u8 key_index,
1161                            bool unicast, bool multicast)
1162 {
1163         struct wilc_priv *priv;
1164         struct wilc_vif *vif;
1165
1166         priv = wiphy_priv(wiphy);
1167         vif = netdev_priv(priv->dev);
1168
1169         wilc_set_wep_default_keyid(vif, key_index);
1170
1171         return 0;
1172 }
1173
1174 static int get_station(struct wiphy *wiphy, struct net_device *dev,
1175                        const u8 *mac, struct station_info *sinfo)
1176 {
1177         struct wilc_priv *priv;
1178         struct wilc_vif *vif;
1179         u32 i = 0;
1180         u32 associatedsta = ~0;
1181         u32 inactive_time = 0;
1182
1183         priv = wiphy_priv(wiphy);
1184         vif = netdev_priv(dev);
1185
1186         if (vif->iftype == AP_MODE || vif->iftype == GO_MODE) {
1187                 for (i = 0; i < NUM_STA_ASSOCIATED; i++) {
1188                         if (!(memcmp(mac, priv->assoc_stainfo.au8Sta_AssociatedBss[i], ETH_ALEN))) {
1189                                 associatedsta = i;
1190                                 break;
1191                         }
1192                 }
1193
1194                 if (associatedsta == ~0) {
1195                         netdev_err(dev, "sta required is not associated\n");
1196                         return -ENOENT;
1197                 }
1198
1199                 sinfo->filled |= BIT(NL80211_STA_INFO_INACTIVE_TIME);
1200
1201                 wilc_get_inactive_time(vif, mac, &inactive_time);
1202                 sinfo->inactive_time = 1000 * inactive_time;
1203         }
1204
1205         if (vif->iftype == STATION_MODE) {
1206                 struct rf_info strStatistics;
1207
1208                 wilc_get_statistics(vif, &strStatistics);
1209
1210                 sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL) |
1211                                                 BIT(NL80211_STA_INFO_RX_PACKETS) |
1212                                                 BIT(NL80211_STA_INFO_TX_PACKETS) |
1213                                                 BIT(NL80211_STA_INFO_TX_FAILED) |
1214                                                 BIT(NL80211_STA_INFO_TX_BITRATE);
1215
1216                 sinfo->signal = strStatistics.rssi;
1217                 sinfo->rx_packets = strStatistics.rx_cnt;
1218                 sinfo->tx_packets = strStatistics.tx_cnt + strStatistics.tx_fail_cnt;
1219                 sinfo->tx_failed = strStatistics.tx_fail_cnt;
1220                 sinfo->txrate.legacy = strStatistics.link_speed * 10;
1221
1222                 if ((strStatistics.link_speed > TCP_ACK_FILTER_LINK_SPEED_THRESH) &&
1223                     (strStatistics.link_speed != DEFAULT_LINK_SPEED))
1224                         wilc_enable_tcp_ack_filter(true);
1225                 else if (strStatistics.link_speed != DEFAULT_LINK_SPEED)
1226                         wilc_enable_tcp_ack_filter(false);
1227         }
1228         return 0;
1229 }
1230
1231 static int change_bss(struct wiphy *wiphy, struct net_device *dev,
1232                       struct bss_parameters *params)
1233 {
1234         return 0;
1235 }
1236
1237 static int set_wiphy_params(struct wiphy *wiphy, u32 changed)
1238 {
1239         s32 s32Error = 0;
1240         struct cfg_param_attr pstrCfgParamVal;
1241         struct wilc_priv *priv;
1242         struct wilc_vif *vif;
1243
1244         priv = wiphy_priv(wiphy);
1245         vif = netdev_priv(priv->dev);
1246
1247         pstrCfgParamVal.flag = 0;
1248
1249         if (changed & WIPHY_PARAM_RETRY_SHORT) {
1250                 pstrCfgParamVal.flag  |= RETRY_SHORT;
1251                 pstrCfgParamVal.short_retry_limit = priv->dev->ieee80211_ptr->wiphy->retry_short;
1252         }
1253         if (changed & WIPHY_PARAM_RETRY_LONG) {
1254                 pstrCfgParamVal.flag |= RETRY_LONG;
1255                 pstrCfgParamVal.long_retry_limit = priv->dev->ieee80211_ptr->wiphy->retry_long;
1256         }
1257         if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
1258                 pstrCfgParamVal.flag |= FRAG_THRESHOLD;
1259                 pstrCfgParamVal.frag_threshold = priv->dev->ieee80211_ptr->wiphy->frag_threshold;
1260         }
1261
1262         if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
1263                 pstrCfgParamVal.flag |= RTS_THRESHOLD;
1264                 pstrCfgParamVal.rts_threshold = priv->dev->ieee80211_ptr->wiphy->rts_threshold;
1265         }
1266
1267         s32Error = wilc_hif_set_cfg(vif, &pstrCfgParamVal);
1268         if (s32Error)
1269                 netdev_err(priv->dev, "Error in setting WIPHY PARAMS\n");
1270
1271         return s32Error;
1272 }
1273
1274 static int set_pmksa(struct wiphy *wiphy, struct net_device *netdev,
1275                      struct cfg80211_pmksa *pmksa)
1276 {
1277         u32 i;
1278         s32 s32Error = 0;
1279         u8 flag = 0;
1280         struct wilc_vif *vif;
1281         struct wilc_priv *priv = wiphy_priv(wiphy);
1282
1283         vif = netdev_priv(priv->dev);
1284
1285         for (i = 0; i < priv->pmkid_list.numpmkid; i++) {
1286                 if (!memcmp(pmksa->bssid, priv->pmkid_list.pmkidlist[i].bssid,
1287                             ETH_ALEN)) {
1288                         flag = PMKID_FOUND;
1289                         break;
1290                 }
1291         }
1292         if (i < WILC_MAX_NUM_PMKIDS) {
1293                 memcpy(priv->pmkid_list.pmkidlist[i].bssid, pmksa->bssid,
1294                        ETH_ALEN);
1295                 memcpy(priv->pmkid_list.pmkidlist[i].pmkid, pmksa->pmkid,
1296                        PMKID_LEN);
1297                 if (!(flag == PMKID_FOUND))
1298                         priv->pmkid_list.numpmkid++;
1299         } else {
1300                 netdev_err(netdev, "Invalid PMKID index\n");
1301                 s32Error = -EINVAL;
1302         }
1303
1304         if (!s32Error)
1305                 s32Error = wilc_set_pmkid_info(vif, &priv->pmkid_list);
1306
1307         return s32Error;
1308 }
1309
1310 static int del_pmksa(struct wiphy *wiphy, struct net_device *netdev,
1311                      struct cfg80211_pmksa *pmksa)
1312 {
1313         u32 i;
1314         s32 s32Error = 0;
1315
1316         struct wilc_priv *priv = wiphy_priv(wiphy);
1317
1318         for (i = 0; i < priv->pmkid_list.numpmkid; i++) {
1319                 if (!memcmp(pmksa->bssid, priv->pmkid_list.pmkidlist[i].bssid,
1320                             ETH_ALEN)) {
1321                         memset(&priv->pmkid_list.pmkidlist[i], 0, sizeof(struct host_if_pmkid));
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++) {
1328                         memcpy(priv->pmkid_list.pmkidlist[i].bssid,
1329                                priv->pmkid_list.pmkidlist[i + 1].bssid,
1330                                ETH_ALEN);
1331                         memcpy(priv->pmkid_list.pmkidlist[i].pmkid,
1332                                priv->pmkid_list.pmkidlist[i + 1].pmkid,
1333                                PMKID_LEN);
1334                 }
1335                 priv->pmkid_list.numpmkid--;
1336         } else {
1337                 s32Error = -EINVAL;
1338         }
1339
1340         return s32Error;
1341 }
1342
1343 static int flush_pmksa(struct wiphy *wiphy, struct net_device *netdev)
1344 {
1345         struct wilc_priv *priv = wiphy_priv(wiphy);
1346
1347         memset(&priv->pmkid_list, 0, sizeof(struct host_if_pmkid_attr));
1348
1349         return 0;
1350 }
1351
1352 static void WILC_WFI_CfgParseRxAction(u8 *buf, u32 len)
1353 {
1354         u32 index = 0;
1355         u32 i = 0, j = 0;
1356
1357         u8 op_channel_attr_index = 0;
1358         u8 channel_list_attr_index = 0;
1359
1360         while (index < len) {
1361                 if (buf[index] == GO_INTENT_ATTR_ID)
1362                         buf[index + 3] = (buf[index + 3]  & 0x01) | (0x00 << 1);
1363
1364                 if (buf[index] ==  CHANLIST_ATTR_ID)
1365                         channel_list_attr_index = index;
1366                 else if (buf[index] ==  OPERCHAN_ATTR_ID)
1367                         op_channel_attr_index = index;
1368                 index += buf[index + 1] + 3;
1369         }
1370         if (wlan_channel != INVALID_CHANNEL) {
1371                 if (channel_list_attr_index) {
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) {
1374                                         for (j = i + 2; j < ((i + 2) + buf[i + 1]); j++)
1375                                                 buf[j] = wlan_channel;
1376                                         break;
1377                                 }
1378                         }
1379                 }
1380
1381                 if (op_channel_attr_index) {
1382                         buf[op_channel_attr_index + 6] = 0x51;
1383                         buf[op_channel_attr_index + 7] = wlan_channel;
1384                 }
1385         }
1386 }
1387
1388 static void WILC_WFI_CfgParseTxAction(u8 *buf, u32 len, bool bOperChan, u8 iftype)
1389 {
1390         u32 index = 0;
1391         u32 i = 0, j = 0;
1392
1393         u8 op_channel_attr_index = 0;
1394         u8 channel_list_attr_index = 0;
1395
1396         while (index < len) {
1397                 if (buf[index] == GO_INTENT_ATTR_ID) {
1398                         buf[index + 3] = (buf[index + 3]  & 0x01) | (0x0f << 1);
1399
1400                         break;
1401                 }
1402
1403                 if (buf[index] ==  CHANLIST_ATTR_ID)
1404                         channel_list_attr_index = index;
1405                 else if (buf[index] ==  OPERCHAN_ATTR_ID)
1406                         op_channel_attr_index = index;
1407                 index += buf[index + 1] + 3;
1408         }
1409         if (wlan_channel != INVALID_CHANNEL && bOperChan) {
1410                 if (channel_list_attr_index) {
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) {
1413                                         for (j = i + 2; j < ((i + 2) + buf[i + 1]); j++)
1414                                                 buf[j] = wlan_channel;
1415                                         break;
1416                                 }
1417                         }
1418                 }
1419
1420                 if (op_channel_attr_index) {
1421                         buf[op_channel_attr_index + 6] = 0x51;
1422                         buf[op_channel_attr_index + 7] = wlan_channel;
1423                 }
1424         }
1425 }
1426
1427 void WILC_WFI_p2p_rx(struct net_device *dev, u8 *buff, u32 size)
1428 {
1429         struct wilc_priv *priv;
1430         u32 header, pkt_offset;
1431         struct host_if_drv *pstrWFIDrv;
1432         u32 i = 0;
1433         s32 s32Freq;
1434
1435         priv = wiphy_priv(dev->ieee80211_ptr->wiphy);
1436         pstrWFIDrv = (struct host_if_drv *)priv->hif_drv;
1437
1438         memcpy(&header, (buff - HOST_HDR_OFFSET), HOST_HDR_OFFSET);
1439
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) {
1444                         cfg80211_mgmt_tx_status(priv->wdev, priv->u64tx_cookie, buff, size, true, GFP_KERNEL);
1445                         return;
1446                 } else {
1447                         if (pkt_offset & IS_MGMT_STATUS_SUCCES)
1448                                 cfg80211_mgmt_tx_status(priv->wdev, priv->u64tx_cookie, buff, size, true, GFP_KERNEL);
1449                         else
1450                                 cfg80211_mgmt_tx_status(priv->wdev, priv->u64tx_cookie, buff, size, false, GFP_KERNEL);
1451                         return;
1452                 }
1453         } else {
1454                 s32Freq = ieee80211_channel_to_frequency(curr_channel, NL80211_BAND_2GHZ);
1455
1456                 if (ieee80211_is_action(buff[FRAME_TYPE_ID])) {
1457                         if (priv->bCfgScanning && time_after_eq(jiffies, (unsigned long)pstrWFIDrv->p2p_timeout)) {
1458                                 netdev_dbg(dev, "Receiving action wrong ch\n");
1459                                 return;
1460                         }
1461                         if (buff[ACTION_CAT_ID] == PUB_ACTION_ATTR_ID) {
1462                                 switch (buff[ACTION_SUBTYPE_ID]) {
1463                                 case GAS_INITIAL_REQ:
1464                                         break;
1465
1466                                 case GAS_INITIAL_RSP:
1467                                         break;
1468
1469                                 case PUBLIC_ACT_VENDORSPEC:
1470                                         if (!memcmp(p2p_oui, &buff[ACTION_SUBTYPE_ID + 1], 4)) {
1471                                                 if ((buff[P2P_PUB_ACTION_SUBTYPE] == GO_NEG_REQ || buff[P2P_PUB_ACTION_SUBTYPE] == GO_NEG_RSP)) {
1472                                                         if (!wilc_ie) {
1473                                                                 for (i = P2P_PUB_ACTION_SUBTYPE; i < size; i++) {
1474                                                                         if (!memcmp(p2p_vendor_spec, &buff[i], 6)) {
1475                                                                                 p2p_recv_random = buff[i + 6];
1476                                                                                 wilc_ie = true;
1477                                                                                 break;
1478                                                                         }
1479                                                                 }
1480                                                         }
1481                                                 }
1482                                                 if (p2p_local_random > p2p_recv_random) {
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)) {
1485                                                                 for (i = P2P_PUB_ACTION_SUBTYPE + 2; i < size; i++) {
1486                                                                         if (buff[i] == P2PELEM_ATTR_ID && !(memcmp(p2p_oui, &buff[i + 2], 4))) {
1487                                                                                 WILC_WFI_CfgParseRxAction(&buff[i + 6], size - (i + 6));
1488                                                                                 break;
1489                                                                         }
1490                                                                 }
1491                                                         }
1492                                                 } else {
1493                                                         netdev_dbg(dev, "PEER WILL BE GO LocaRand=%02x RecvRand %02x\n", p2p_local_random, p2p_recv_random);
1494                                                 }
1495                                         }
1496
1497                                         if ((buff[P2P_PUB_ACTION_SUBTYPE] == GO_NEG_REQ || buff[P2P_PUB_ACTION_SUBTYPE] == GO_NEG_RSP) && (wilc_ie))    {
1498                                                 cfg80211_rx_mgmt(priv->wdev, s32Freq, 0, buff, size - 7, 0);
1499                                                 return;
1500                                         }
1501                                         break;
1502
1503                                 default:
1504                                         netdev_dbg(dev, "NOT HANDLED PUBLIC ACTION FRAME TYPE:%x\n", buff[ACTION_SUBTYPE_ID]);
1505                                         break;
1506                                 }
1507                         }
1508                 }
1509
1510                 cfg80211_rx_mgmt(priv->wdev, s32Freq, 0, buff, size, 0);
1511         }
1512 }
1513
1514 static void WILC_WFI_mgmt_tx_complete(void *priv, int status)
1515 {
1516         struct p2p_mgmt_data *pv_data = priv;
1517
1518         kfree(pv_data->buff);
1519         kfree(pv_data);
1520 }
1521
1522 static void WILC_WFI_RemainOnChannelReady(void *pUserVoid)
1523 {
1524         struct wilc_priv *priv;
1525
1526         priv = pUserVoid;
1527
1528         priv->bInP2PlistenState = true;
1529
1530         cfg80211_ready_on_channel(priv->wdev,
1531                                   priv->strRemainOnChanParams.u64ListenCookie,
1532                                   priv->strRemainOnChanParams.pstrListenChan,
1533                                   priv->strRemainOnChanParams.u32ListenDuration,
1534                                   GFP_KERNEL);
1535 }
1536
1537 static void WILC_WFI_RemainOnChannelExpired(void *pUserVoid, u32 u32SessionID)
1538 {
1539         struct wilc_priv *priv;
1540
1541         priv = pUserVoid;
1542
1543         if (u32SessionID == priv->strRemainOnChanParams.u32ListenSessionID) {
1544                 priv->bInP2PlistenState = false;
1545
1546                 cfg80211_remain_on_channel_expired(priv->wdev,
1547                                                    priv->strRemainOnChanParams.u64ListenCookie,
1548                                                    priv->strRemainOnChanParams.pstrListenChan,
1549                                                    GFP_KERNEL);
1550         }
1551 }
1552
1553 static int remain_on_channel(struct wiphy *wiphy,
1554                              struct wireless_dev *wdev,
1555                              struct ieee80211_channel *chan,
1556                              unsigned int duration, u64 *cookie)
1557 {
1558         s32 s32Error = 0;
1559         struct wilc_priv *priv;
1560         struct wilc_vif *vif;
1561
1562         priv = wiphy_priv(wiphy);
1563         vif = netdev_priv(priv->dev);
1564
1565         if (wdev->iftype == NL80211_IFTYPE_AP) {
1566                 netdev_dbg(vif->ndev, "Required while in AP mode\n");
1567                 return s32Error;
1568         }
1569
1570         curr_channel = chan->hw_value;
1571
1572         priv->strRemainOnChanParams.pstrListenChan = chan;
1573         priv->strRemainOnChanParams.u64ListenCookie = *cookie;
1574         priv->strRemainOnChanParams.u32ListenDuration = duration;
1575         priv->strRemainOnChanParams.u32ListenSessionID++;
1576
1577         return wilc_remain_on_channel(vif,
1578                                 priv->strRemainOnChanParams.u32ListenSessionID,
1579                                 duration, chan->hw_value,
1580                                 WILC_WFI_RemainOnChannelExpired,
1581                                 WILC_WFI_RemainOnChannelReady, (void *)priv);
1582 }
1583
1584 static int cancel_remain_on_channel(struct wiphy *wiphy,
1585                                     struct wireless_dev *wdev,
1586                                     u64 cookie)
1587 {
1588         struct wilc_priv *priv;
1589         struct wilc_vif *vif;
1590
1591         priv = wiphy_priv(wiphy);
1592         vif = netdev_priv(priv->dev);
1593
1594         return wilc_listen_state_expired(vif,
1595                         priv->strRemainOnChanParams.u32ListenSessionID);
1596 }
1597
1598 static int mgmt_tx(struct wiphy *wiphy,
1599                    struct wireless_dev *wdev,
1600                    struct cfg80211_mgmt_tx_params *params,
1601                    u64 *cookie)
1602 {
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;
1607         const struct ieee80211_mgmt *mgmt;
1608         struct p2p_mgmt_data *mgmt_tx;
1609         struct wilc_priv *priv;
1610         struct host_if_drv *pstrWFIDrv;
1611         u32 i;
1612         struct wilc_vif *vif;
1613         u32 buf_len = len + sizeof(p2p_vendor_spec) + sizeof(p2p_local_random);
1614
1615         vif = netdev_priv(wdev->netdev);
1616         priv = wiphy_priv(wiphy);
1617         pstrWFIDrv = (struct host_if_drv *)priv->hif_drv;
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)) {
1624                 mgmt_tx = kmalloc(sizeof(struct p2p_mgmt_data), GFP_KERNEL);
1625                 if (!mgmt_tx)
1626                         return -EFAULT;
1627
1628                 mgmt_tx->buff = kmalloc(buf_len, GFP_KERNEL);
1629                 if (!mgmt_tx->buff) {
1630                         kfree(mgmt_tx);
1631                         return -ENOMEM;
1632                 }
1633
1634                 memcpy(mgmt_tx->buff, buf, len);
1635                 mgmt_tx->size = len;
1636
1637                 if (ieee80211_is_probe_resp(mgmt->frame_control)) {
1638                         wilc_set_mac_chnl_num(vif, chan->hw_value);
1639                         curr_channel = chan->hw_value;
1640                 } else if (ieee80211_is_action(mgmt->frame_control))   {
1641                         if (buf[ACTION_CAT_ID] == PUB_ACTION_ATTR_ID) {
1642                                 if (buf[ACTION_SUBTYPE_ID] != PUBLIC_ACT_VENDORSPEC ||
1643                                     buf[P2P_PUB_ACTION_SUBTYPE] != GO_NEG_CONF) {
1644                                         wilc_set_mac_chnl_num(vif,
1645                                                               chan->hw_value);
1646                                         curr_channel = chan->hw_value;
1647                                 }
1648                                 switch (buf[ACTION_SUBTYPE_ID]) {
1649                                 case GAS_INITIAL_REQ:
1650                                         break;
1651
1652                                 case GAS_INITIAL_RSP:
1653                                         break;
1654
1655                                 case PUBLIC_ACT_VENDORSPEC:
1656                                 {
1657                                         if (!memcmp(p2p_oui, &buf[ACTION_SUBTYPE_ID + 1], 4)) {
1658                                                 if ((buf[P2P_PUB_ACTION_SUBTYPE] == GO_NEG_REQ || buf[P2P_PUB_ACTION_SUBTYPE] == GO_NEG_RSP)) {
1659                                                         if (p2p_local_random == 1 && p2p_recv_random < p2p_local_random) {
1660                                                                 get_random_bytes(&p2p_local_random, 1);
1661                                                                 p2p_local_random++;
1662                                                         }
1663                                                 }
1664
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)) {
1667                                                         if (p2p_local_random > p2p_recv_random) {
1668                                                                 for (i = P2P_PUB_ACTION_SUBTYPE + 2; i < len; i++) {
1669                                                                         if (buf[i] == P2PELEM_ATTR_ID && !(memcmp(p2p_oui, &buf[i + 2], 4))) {
1670                                                                                 if (buf[P2P_PUB_ACTION_SUBTYPE] == P2P_INV_REQ || buf[P2P_PUB_ACTION_SUBTYPE] == P2P_INV_RSP)
1671                                                                                         WILC_WFI_CfgParseTxAction(&mgmt_tx->buff[i + 6], len - (i + 6), true, vif->iftype);
1672                                                                                 else
1673                                                                                         WILC_WFI_CfgParseTxAction(&mgmt_tx->buff[i + 6], len - (i + 6), false, vif->iftype);
1674                                                                                 break;
1675                                                                         }
1676                                                                 }
1677
1678                                                                 if (buf[P2P_PUB_ACTION_SUBTYPE] != P2P_INV_REQ && buf[P2P_PUB_ACTION_SUBTYPE] != P2P_INV_RSP) {
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;
1681                                                                         mgmt_tx->size = buf_len;
1682                                                                 }
1683                                                         }
1684                                                 }
1685
1686                                         } else {
1687                                                 netdev_dbg(vif->ndev, "Not a P2P public action frame\n");
1688                                         }
1689
1690                                         break;
1691                                 }
1692
1693                                 default:
1694                                 {
1695                                         netdev_dbg(vif->ndev, "NOT HANDLED PUBLIC ACTION FRAME TYPE:%x\n", buf[ACTION_SUBTYPE_ID]);
1696                                         break;
1697                                 }
1698                                 }
1699                         }
1700
1701                         pstrWFIDrv->p2p_timeout = (jiffies + msecs_to_jiffies(wait));
1702                 }
1703
1704                 wilc_wlan_txq_add_mgmt_pkt(wdev->netdev, mgmt_tx,
1705                                            mgmt_tx->buff, mgmt_tx->size,
1706                                            WILC_WFI_mgmt_tx_complete);
1707         }
1708         return 0;
1709 }
1710
1711 static int mgmt_tx_cancel_wait(struct wiphy *wiphy,
1712                                struct wireless_dev *wdev,
1713                                u64 cookie)
1714 {
1715         struct wilc_priv *priv;
1716         struct host_if_drv *pstrWFIDrv;
1717
1718         priv = wiphy_priv(wiphy);
1719         pstrWFIDrv = (struct host_if_drv *)priv->hif_drv;
1720         pstrWFIDrv->p2p_timeout = jiffies;
1721
1722         if (!priv->bInP2PlistenState) {
1723                 cfg80211_remain_on_channel_expired(priv->wdev,
1724                                                    priv->strRemainOnChanParams.u64ListenCookie,
1725                                                    priv->strRemainOnChanParams.pstrListenChan,
1726                                                    GFP_KERNEL);
1727         }
1728
1729         return 0;
1730 }
1731
1732 void wilc_mgmt_frame_register(struct wiphy *wiphy, struct wireless_dev *wdev,
1733                               u16 frame_type, bool reg)
1734 {
1735         struct wilc_priv *priv;
1736         struct wilc_vif *vif;
1737         struct wilc *wl;
1738
1739         priv = wiphy_priv(wiphy);
1740         vif = netdev_priv(priv->wdev->netdev);
1741         wl = vif->wilc;
1742
1743         if (!frame_type)
1744                 return;
1745
1746         switch (frame_type) {
1747         case PROBE_REQ:
1748         {
1749                 vif->frame_reg[0].type = frame_type;
1750                 vif->frame_reg[0].reg = reg;
1751         }
1752         break;
1753
1754         case ACTION:
1755         {
1756                 vif->frame_reg[1].type = frame_type;
1757                 vif->frame_reg[1].reg = reg;
1758         }
1759         break;
1760
1761         default:
1762         {
1763                 break;
1764         }
1765         }
1766
1767         if (!wl->initialized)
1768                 return;
1769         wilc_frame_register(vif, frame_type, reg);
1770 }
1771
1772 static int set_cqm_rssi_config(struct wiphy *wiphy, struct net_device *dev,
1773                                s32 rssi_thold, u32 rssi_hyst)
1774 {
1775         return 0;
1776 }
1777
1778 static int dump_station(struct wiphy *wiphy, struct net_device *dev,
1779                         int idx, u8 *mac, struct station_info *sinfo)
1780 {
1781         struct wilc_priv *priv;
1782         struct wilc_vif *vif;
1783
1784         if (idx != 0)
1785                 return -ENOENT;
1786
1787         priv = wiphy_priv(wiphy);
1788         vif = netdev_priv(priv->dev);
1789
1790         sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL);
1791
1792         wilc_get_rssi(vif, &sinfo->signal);
1793
1794         memcpy(mac, priv->au8AssociatedBss, ETH_ALEN);
1795         return 0;
1796 }
1797
1798 static int set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,
1799                           bool enabled, int timeout)
1800 {
1801         struct wilc_priv *priv;
1802         struct wilc_vif *vif;
1803
1804         if (!wiphy)
1805                 return -ENOENT;
1806
1807         priv = wiphy_priv(wiphy);
1808         vif = netdev_priv(priv->dev);
1809         if (!priv->hif_drv)
1810                 return -EIO;
1811
1812         if (wilc_enable_ps)
1813                 wilc_set_power_mgmt(vif, enabled, timeout);
1814
1815         return 0;
1816 }
1817
1818 static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev,
1819                                enum nl80211_iftype type, struct vif_params *params)
1820 {
1821         struct wilc_priv *priv;
1822         struct wilc_vif *vif;
1823         struct wilc *wl;
1824
1825         vif = netdev_priv(dev);
1826         priv = wiphy_priv(wiphy);
1827         wl = vif->wilc;
1828         p2p_local_random = 0x01;
1829         p2p_recv_random = 0x00;
1830         wilc_ie = false;
1831         wilc_optaining_ip = false;
1832         del_timer(&wilc_during_ip_timer);
1833
1834         switch (type) {
1835         case NL80211_IFTYPE_STATION:
1836                 wilc_connecting = 0;
1837                 dev->ieee80211_ptr->iftype = type;
1838                 priv->wdev->iftype = type;
1839                 vif->monitor_flag = 0;
1840                 vif->iftype = STATION_MODE;
1841                 wilc_set_operation_mode(vif, STATION_MODE);
1842
1843                 memset(priv->assoc_stainfo.au8Sta_AssociatedBss, 0, MAX_NUM_STA * ETH_ALEN);
1844
1845                 wilc_enable_ps = true;
1846                 wilc_set_power_mgmt(vif, 1, 0);
1847                 break;
1848
1849         case NL80211_IFTYPE_P2P_CLIENT:
1850                 wilc_connecting = 0;
1851                 dev->ieee80211_ptr->iftype = type;
1852                 priv->wdev->iftype = type;
1853                 vif->monitor_flag = 0;
1854                 vif->iftype = CLIENT_MODE;
1855                 wilc_set_operation_mode(vif, STATION_MODE);
1856
1857                 wilc_enable_ps = false;
1858                 wilc_set_power_mgmt(vif, 0, 0);
1859                 break;
1860
1861         case NL80211_IFTYPE_AP:
1862                 wilc_enable_ps = false;
1863                 dev->ieee80211_ptr->iftype = type;
1864                 priv->wdev->iftype = type;
1865                 vif->iftype = AP_MODE;
1866
1867                 if (wl->initialized) {
1868                         wilc_set_wfi_drv_handler(vif, wilc_get_vif_idx(vif),
1869                                                  0, vif->ifc_id);
1870                         wilc_set_operation_mode(vif, AP_MODE);
1871                         wilc_set_power_mgmt(vif, 0, 0);
1872                 }
1873                 break;
1874
1875         case NL80211_IFTYPE_P2P_GO:
1876                 wilc_optaining_ip = true;
1877                 mod_timer(&wilc_during_ip_timer,
1878                           jiffies + msecs_to_jiffies(during_ip_time));
1879                 wilc_set_operation_mode(vif, AP_MODE);
1880                 dev->ieee80211_ptr->iftype = type;
1881                 priv->wdev->iftype = type;
1882                 vif->iftype = GO_MODE;
1883
1884                 wilc_enable_ps = false;
1885                 wilc_set_power_mgmt(vif, 0, 0);
1886                 break;
1887
1888         default:
1889                 netdev_err(dev, "Unknown interface type= %d\n", type);
1890                 return -EINVAL;
1891         }
1892
1893         return 0;
1894 }
1895
1896 static int start_ap(struct wiphy *wiphy, struct net_device *dev,
1897                     struct cfg80211_ap_settings *settings)
1898 {
1899         struct cfg80211_beacon_data *beacon = &(settings->beacon);
1900         struct wilc_priv *priv;
1901         s32 s32Error = 0;
1902         struct wilc *wl;
1903         struct wilc_vif *vif;
1904
1905         priv = wiphy_priv(wiphy);
1906         vif = netdev_priv(dev);
1907         wl = vif->wilc;
1908
1909         s32Error = set_channel(wiphy, &settings->chandef);
1910
1911         if (s32Error != 0)
1912                 netdev_err(dev, "Error in setting channel\n");
1913
1914         wilc_wlan_set_bssid(dev, wl->vif[vif->idx]->src_addr, AP_MODE);
1915         wilc_set_power_mgmt(vif, 0, 0);
1916
1917         return wilc_add_beacon(vif, settings->beacon_interval,
1918                                    settings->dtim_period, beacon->head_len,
1919                                    (u8 *)beacon->head, beacon->tail_len,
1920                                    (u8 *)beacon->tail);
1921 }
1922
1923 static int change_beacon(struct wiphy *wiphy, struct net_device *dev,
1924                          struct cfg80211_beacon_data *beacon)
1925 {
1926         struct wilc_priv *priv;
1927         struct wilc_vif *vif;
1928
1929         priv = wiphy_priv(wiphy);
1930         vif = netdev_priv(priv->dev);
1931
1932         return wilc_add_beacon(vif, 0, 0, beacon->head_len,
1933                                    (u8 *)beacon->head, beacon->tail_len,
1934                                    (u8 *)beacon->tail);
1935 }
1936
1937 static int stop_ap(struct wiphy *wiphy, struct net_device *dev)
1938 {
1939         s32 s32Error = 0;
1940         struct wilc_priv *priv;
1941         struct wilc_vif *vif;
1942         u8 NullBssid[ETH_ALEN] = {0};
1943
1944         if (!wiphy)
1945                 return -EFAULT;
1946
1947         priv = wiphy_priv(wiphy);
1948         vif = netdev_priv(priv->dev);
1949
1950         wilc_wlan_set_bssid(dev, NullBssid, AP_MODE);
1951
1952         s32Error = wilc_del_beacon(vif);
1953
1954         if (s32Error)
1955                 netdev_err(dev, "Host delete beacon fail\n");
1956
1957         return s32Error;
1958 }
1959
1960 static int add_station(struct wiphy *wiphy, struct net_device *dev,
1961                        const u8 *mac, struct station_parameters *params)
1962 {
1963         s32 s32Error = 0;
1964         struct wilc_priv *priv;
1965         struct add_sta_param strStaParams = { {0} };
1966         struct wilc_vif *vif;
1967
1968         if (!wiphy)
1969                 return -EFAULT;
1970
1971         priv = wiphy_priv(wiphy);
1972         vif = netdev_priv(dev);
1973
1974         if (vif->iftype == AP_MODE || vif->iftype == GO_MODE) {
1975                 memcpy(strStaParams.bssid, mac, ETH_ALEN);
1976                 memcpy(priv->assoc_stainfo.au8Sta_AssociatedBss[params->aid], mac, ETH_ALEN);
1977                 strStaParams.aid = params->aid;
1978                 strStaParams.rates_len = params->supported_rates_len;
1979                 strStaParams.rates = params->supported_rates;
1980
1981                 if (!params->ht_capa) {
1982                         strStaParams.ht_supported = false;
1983                 } else {
1984                         strStaParams.ht_supported = true;
1985                         strStaParams.ht_capa = *params->ht_capa;
1986                 }
1987
1988                 strStaParams.flags_mask = params->sta_flags_mask;
1989                 strStaParams.flags_set = params->sta_flags_set;
1990
1991                 s32Error = wilc_add_station(vif, &strStaParams);
1992                 if (s32Error)
1993                         netdev_err(dev, "Host add station fail\n");
1994         }
1995
1996         return s32Error;
1997 }
1998
1999 static int del_station(struct wiphy *wiphy, struct net_device *dev,
2000                        struct station_del_parameters *params)
2001 {
2002         const u8 *mac = params->mac;
2003         s32 s32Error = 0;
2004         struct wilc_priv *priv;
2005         struct wilc_vif *vif;
2006
2007         if (!wiphy)
2008                 return -EFAULT;
2009
2010         priv = wiphy_priv(wiphy);
2011         vif = netdev_priv(dev);
2012
2013         if (vif->iftype == AP_MODE || vif->iftype == GO_MODE) {
2014                 if (!mac)
2015                         s32Error = wilc_del_allstation(vif,
2016                                      priv->assoc_stainfo.au8Sta_AssociatedBss);
2017
2018                 s32Error = wilc_del_station(vif, mac);
2019
2020                 if (s32Error)
2021                         netdev_err(dev, "Host delete station fail\n");
2022         }
2023         return s32Error;
2024 }
2025
2026 static int change_station(struct wiphy *wiphy, struct net_device *dev,
2027                           const u8 *mac, struct station_parameters *params)
2028 {
2029         s32 s32Error = 0;
2030         struct wilc_priv *priv;
2031         struct add_sta_param strStaParams = { {0} };
2032         struct wilc_vif *vif;
2033
2034         if (!wiphy)
2035                 return -EFAULT;
2036
2037         priv = wiphy_priv(wiphy);
2038         vif = netdev_priv(dev);
2039
2040         if (vif->iftype == AP_MODE || vif->iftype == GO_MODE) {
2041                 memcpy(strStaParams.bssid, mac, ETH_ALEN);
2042                 strStaParams.aid = params->aid;
2043                 strStaParams.rates_len = params->supported_rates_len;
2044                 strStaParams.rates = params->supported_rates;
2045
2046                 if (!params->ht_capa) {
2047                         strStaParams.ht_supported = false;
2048                 } else {
2049                         strStaParams.ht_supported = true;
2050                         strStaParams.ht_capa = *params->ht_capa;
2051                 }
2052
2053                 strStaParams.flags_mask = params->sta_flags_mask;
2054                 strStaParams.flags_set = params->sta_flags_set;
2055
2056                 s32Error = wilc_edit_station(vif, &strStaParams);
2057                 if (s32Error)
2058                         netdev_err(dev, "Host edit station fail\n");
2059         }
2060         return s32Error;
2061 }
2062
2063 static struct wireless_dev *add_virtual_intf(struct wiphy *wiphy,
2064                                              const char *name,
2065                                              unsigned char name_assign_type,
2066                                              enum nl80211_iftype type,
2067                                              struct vif_params *params)
2068 {
2069         struct wilc_vif *vif;
2070         struct wilc_priv *priv;
2071         struct net_device *new_ifc = NULL;
2072
2073         priv = wiphy_priv(wiphy);
2074         vif = netdev_priv(priv->wdev->netdev);
2075
2076         if (type == NL80211_IFTYPE_MONITOR) {
2077                 new_ifc = WILC_WFI_init_mon_interface(name, vif->ndev);
2078                 if (new_ifc) {
2079                         vif = netdev_priv(priv->wdev->netdev);
2080                         vif->monitor_flag = 1;
2081                 }
2082         }
2083         return priv->wdev;
2084 }
2085
2086 static int del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev)
2087 {
2088         return 0;
2089 }
2090
2091 static 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
2104 static 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
2113 static 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
2121 static 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
2140 static 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);
2146         struct wilc *wl;
2147
2148         wl = vif->wilc;
2149
2150         /* If firmware is not started, return. */
2151         if (!wl->initialized)
2152                 return -EIO;
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
2161 static const struct cfg80211_ops wilc_cfg80211_ops = {
2162         .set_monitor_channel = set_channel,
2163         .scan = scan,
2164         .connect = connect,
2165         .disconnect = disconnect,
2166         .add_key = add_key,
2167         .del_key = del_key,
2168         .get_key = get_key,
2169         .set_default_key = set_default_key,
2170         .add_virtual_intf = add_virtual_intf,
2171         .del_virtual_intf = del_virtual_intf,
2172         .change_virtual_intf = change_virtual_intf,
2173
2174         .start_ap = start_ap,
2175         .change_beacon = change_beacon,
2176         .stop_ap = stop_ap,
2177         .add_station = add_station,
2178         .del_station = del_station,
2179         .change_station = change_station,
2180         .get_station = get_station,
2181         .dump_station = dump_station,
2182         .change_bss = change_bss,
2183         .set_wiphy_params = set_wiphy_params,
2184
2185         .set_pmksa = set_pmksa,
2186         .del_pmksa = del_pmksa,
2187         .flush_pmksa = flush_pmksa,
2188         .remain_on_channel = remain_on_channel,
2189         .cancel_remain_on_channel = cancel_remain_on_channel,
2190         .mgmt_tx_cancel_wait = mgmt_tx_cancel_wait,
2191         .mgmt_tx = mgmt_tx,
2192         .mgmt_frame_register = wilc_mgmt_frame_register,
2193         .set_power_mgmt = set_power_mgmt,
2194         .set_cqm_rssi_config = set_cqm_rssi_config,
2195
2196         .suspend = wilc_suspend,
2197         .resume = wilc_resume,
2198         .set_wakeup = wilc_set_wakeup,
2199         .set_tx_power = set_tx_power,
2200         .get_tx_power = get_tx_power,
2201
2202 };
2203
2204 static struct wireless_dev *WILC_WFI_CfgAlloc(void)
2205 {
2206         struct wireless_dev *wdev;
2207
2208         wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL);
2209         if (!wdev)
2210                 goto _fail_;
2211
2212         wdev->wiphy = wiphy_new(&wilc_cfg80211_ops, sizeof(struct wilc_priv));
2213         if (!wdev->wiphy)
2214                 goto _fail_mem_;
2215
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;
2221
2222         wdev->wiphy->bands[NL80211_BAND_2GHZ] = &WILC_WFI_band_2ghz;
2223
2224         return wdev;
2225
2226 _fail_mem_:
2227         kfree(wdev);
2228 _fail_:
2229         return NULL;
2230 }
2231
2232 struct wireless_dev *wilc_create_wiphy(struct net_device *net, struct device *dev)
2233 {
2234         struct wilc_priv *priv;
2235         struct wireless_dev *wdev;
2236         s32 s32Error = 0;
2237
2238         wdev = WILC_WFI_CfgAlloc();
2239         if (!wdev) {
2240                 netdev_err(net, "wiphy new allocate failed\n");
2241                 return NULL;
2242         }
2243
2244         priv = wdev_priv(wdev);
2245         priv->wdev = wdev;
2246         wdev->wiphy->max_scan_ssids = MAX_NUM_PROBED_SSID;
2247 #ifdef CONFIG_PM
2248         wdev->wiphy->wowlan = &wowlan_support;
2249 #endif
2250         wdev->wiphy->max_num_pmkids = WILC_MAX_NUM_PMKIDS;
2251         wdev->wiphy->max_scan_ie_len = 1000;
2252         wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
2253         wdev->wiphy->cipher_suites = cipher_suites;
2254         wdev->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
2255         wdev->wiphy->mgmt_stypes = wilc_wfi_cfg80211_mgmt_types;
2256
2257         wdev->wiphy->max_remain_on_channel_duration = 500;
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);
2263         wdev->wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
2264         wdev->iftype = NL80211_IFTYPE_STATION;
2265
2266         set_wiphy_dev(wdev->wiphy, dev);
2267
2268         s32Error = wiphy_register(wdev->wiphy);
2269         if (s32Error)
2270                 netdev_err(net, "Cannot register wiphy device\n");
2271
2272         priv->dev = net;
2273         return wdev;
2274 }
2275
2276 int wilc_init_host_int(struct net_device *net)
2277 {
2278         int s32Error = 0;
2279
2280         struct wilc_priv *priv;
2281
2282         priv = wdev_priv(net->ieee80211_ptr);
2283         if (op_ifcs == 0) {
2284                 setup_timer(&hAgingTimer, remove_network_from_shadow, 0);
2285                 setup_timer(&wilc_during_ip_timer, clear_duringIP, 0);
2286         }
2287         op_ifcs++;
2288
2289         priv->gbAutoRateAdjusted = false;
2290
2291         priv->bInP2PlistenState = false;
2292
2293         mutex_init(&priv->scan_req_lock);
2294         s32Error = wilc_init(net, &priv->hif_drv);
2295         if (s32Error)
2296                 netdev_err(net, "Error while initializing hostinterface\n");
2297
2298         return s32Error;
2299 }
2300
2301 int wilc_deinit_host_int(struct net_device *net)
2302 {
2303         int s32Error = 0;
2304         struct wilc_vif *vif;
2305         struct wilc_priv *priv;
2306
2307         priv = wdev_priv(net->ieee80211_ptr);
2308         vif = netdev_priv(priv->dev);
2309
2310         priv->gbAutoRateAdjusted = false;
2311
2312         priv->bInP2PlistenState = false;
2313
2314         op_ifcs--;
2315
2316         s32Error = wilc_deinit(vif);
2317
2318         clear_shadow_scan();
2319         if (op_ifcs == 0)
2320                 del_timer_sync(&wilc_during_ip_timer);
2321
2322         if (s32Error)
2323                 netdev_err(net, "Error while deinitializing host interface\n");
2324
2325         return s32Error;
2326 }
2327
2328 void wilc_free_wiphy(struct net_device *net)
2329 {
2330         if (!net)
2331                 return;
2332
2333         if (!net->ieee80211_ptr)
2334                 return;
2335
2336         if (!net->ieee80211_ptr->wiphy)
2337                 return;
2338
2339         wiphy_unregister(net->ieee80211_ptr->wiphy);
2340
2341         wiphy_free(net->ieee80211_ptr->wiphy);
2342         kfree(net->ieee80211_ptr);
2343 }