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