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