linux/drivers/staging/wilc1000/host_interface.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_netdevice.h"
   8
   9#define WILC_HIF_SCAN_TIMEOUT_MS                4000
  10#define WILC_HIF_CONNECT_TIMEOUT_MS             9500
  11
  12#define WILC_FALSE_FRMWR_CHANNEL                100
  13#define WILC_MAX_RATES_SUPPORTED                12
  14
  15struct wilc_rcvd_mac_info {
  16        u8 status;
  17};
  18
  19struct wilc_set_multicast {
  20        u32 enabled;
  21        u32 cnt;
  22        u8 *mc_list;
  23};
  24
  25struct wilc_del_all_sta {
  26        u8 assoc_sta;
  27        u8 mac[WILC_MAX_NUM_STA][ETH_ALEN];
  28};
  29
  30struct wilc_op_mode {
  31        __le32 mode;
  32};
  33
  34struct wilc_reg_frame {
  35        bool reg;
  36        u8 reg_id;
  37        __le16 frame_type;
  38} __packed;
  39
  40struct wilc_drv_handler {
  41        __le32 handler;
  42        u8 mode;
  43} __packed;
  44
  45struct wilc_wep_key {
  46        u8 index;
  47        u8 key_len;
  48        u8 key[0];
  49} __packed;
  50
  51struct wilc_sta_wpa_ptk {
  52        u8 mac_addr[ETH_ALEN];
  53        u8 key_len;
  54        u8 key[0];
  55} __packed;
  56
  57struct wilc_ap_wpa_ptk {
  58        u8 mac_addr[ETH_ALEN];
  59        u8 index;
  60        u8 key_len;
  61        u8 key[0];
  62} __packed;
  63
  64struct wilc_gtk_key {
  65        u8 mac_addr[ETH_ALEN];
  66        u8 rsc[8];
  67        u8 index;
  68        u8 key_len;
  69        u8 key[0];
  70} __packed;
  71
  72union wilc_message_body {
  73        struct wilc_rcvd_net_info net_info;
  74        struct wilc_rcvd_mac_info mac_info;
  75        struct wilc_set_multicast mc_info;
  76        struct wilc_remain_ch remain_on_ch;
  77        char *data;
  78};
  79
  80struct host_if_msg {
  81        union wilc_message_body body;
  82        struct wilc_vif *vif;
  83        struct work_struct work;
  84        void (*fn)(struct work_struct *ws);
  85        struct completion work_comp;
  86        bool is_sync;
  87};
  88
  89struct wilc_noa_opp_enable {
  90        u8 ct_window;
  91        u8 cnt;
  92        __le32 duration;
  93        __le32 interval;
  94        __le32 start_time;
  95} __packed;
  96
  97struct wilc_noa_opp_disable {
  98        u8 cnt;
  99        __le32 duration;
 100        __le32 interval;
 101        __le32 start_time;
 102} __packed;
 103
 104struct wilc_join_bss_param {
 105        char ssid[IEEE80211_MAX_SSID_LEN];
 106        u8 ssid_terminator;
 107        u8 bss_type;
 108        u8 ch;
 109        __le16 cap_info;
 110        u8 sa[ETH_ALEN];
 111        u8 bssid[ETH_ALEN];
 112        __le16 beacon_period;
 113        u8 dtim_period;
 114        u8 supp_rates[WILC_MAX_RATES_SUPPORTED + 1];
 115        u8 wmm_cap;
 116        u8 uapsd_cap;
 117        u8 ht_capable;
 118        u8 rsn_found;
 119        u8 rsn_grp_policy;
 120        u8 mode_802_11i;
 121        u8 p_suites[3];
 122        u8 akm_suites[3];
 123        u8 rsn_cap[2];
 124        u8 noa_enabled;
 125        __le32 tsf_lo;
 126        u8 idx;
 127        u8 opp_enabled;
 128        union {
 129                struct wilc_noa_opp_disable opp_dis;
 130                struct wilc_noa_opp_enable opp_en;
 131        };
 132} __packed;
 133
 134/* 'msg' should be free by the caller for syc */
 135static struct host_if_msg*
 136wilc_alloc_work(struct wilc_vif *vif, void (*work_fun)(struct work_struct *),
 137                bool is_sync)
 138{
 139        struct host_if_msg *msg;
 140
 141        if (!work_fun)
 142                return ERR_PTR(-EINVAL);
 143
 144        msg = kzalloc(sizeof(*msg), GFP_ATOMIC);
 145        if (!msg)
 146                return ERR_PTR(-ENOMEM);
 147        msg->fn = work_fun;
 148        msg->vif = vif;
 149        msg->is_sync = is_sync;
 150        if (is_sync)
 151                init_completion(&msg->work_comp);
 152
 153        return msg;
 154}
 155
 156static int wilc_enqueue_work(struct host_if_msg *msg)
 157{
 158        INIT_WORK(&msg->work, msg->fn);
 159
 160        if (!msg->vif || !msg->vif->wilc || !msg->vif->wilc->hif_workqueue)
 161                return -EINVAL;
 162
 163        if (!queue_work(msg->vif->wilc->hif_workqueue, &msg->work))
 164                return -EINVAL;
 165
 166        return 0;
 167}
 168
 169/* The idx starts from 0 to (NUM_CONCURRENT_IFC - 1), but 0 index used as
 170 * special purpose in wilc device, so we add 1 to the index to starts from 1.
 171 * As a result, the returned index will be 1 to NUM_CONCURRENT_IFC.
 172 */
 173int wilc_get_vif_idx(struct wilc_vif *vif)
 174{
 175        return vif->idx + 1;
 176}
 177
 178/* We need to minus 1 from idx which is from wilc device to get real index
 179 * of wilc->vif[], because we add 1 when pass to wilc device in the function
 180 * wilc_get_vif_idx.
 181 * As a result, the index should be between 0 and (NUM_CONCURRENT_IFC - 1).
 182 */
 183static struct wilc_vif *wilc_get_vif_from_idx(struct wilc *wilc, int idx)
 184{
 185        int index = idx - 1;
 186
 187        if (index < 0 || index >= WILC_NUM_CONCURRENT_IFC)
 188                return NULL;
 189
 190        return wilc->vif[index];
 191}
 192
 193static int handle_scan_done(struct wilc_vif *vif, enum scan_event evt)
 194{
 195        int result = 0;
 196        u8 abort_running_scan;
 197        struct wid wid;
 198        struct host_if_drv *hif_drv = vif->hif_drv;
 199        struct wilc_user_scan_req *scan_req;
 200
 201        if (evt == SCAN_EVENT_ABORTED) {
 202                abort_running_scan = 1;
 203                wid.id = WID_ABORT_RUNNING_SCAN;
 204                wid.type = WID_CHAR;
 205                wid.val = (s8 *)&abort_running_scan;
 206                wid.size = sizeof(char);
 207
 208                result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
 209                                              wilc_get_vif_idx(vif));
 210
 211                if (result) {
 212                        netdev_err(vif->ndev, "Failed to set abort running\n");
 213                        result = -EFAULT;
 214                }
 215        }
 216
 217        if (!hif_drv) {
 218                netdev_err(vif->ndev, "%s: hif driver is NULL\n", __func__);
 219                return result;
 220        }
 221
 222        scan_req = &hif_drv->usr_scan_req;
 223        if (scan_req->scan_result) {
 224                scan_req->scan_result(evt, NULL, scan_req->arg);
 225                scan_req->scan_result = NULL;
 226        }
 227
 228        return result;
 229}
 230
 231int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type,
 232              u8 *ch_freq_list, u8 ch_list_len,
 233              void (*scan_result_fn)(enum scan_event,
 234                                     struct wilc_rcvd_net_info *, void *),
 235              void *user_arg, struct cfg80211_scan_request *request)
 236{
 237        int result = 0;
 238        struct wid wid_list[5];
 239        u32 index = 0;
 240        u32 i;
 241        u8 *buffer;
 242        u8 valuesize = 0;
 243        u8 *search_ssid_vals = NULL;
 244        struct host_if_drv *hif_drv = vif->hif_drv;
 245
 246        if (hif_drv->hif_state >= HOST_IF_SCANNING &&
 247            hif_drv->hif_state < HOST_IF_CONNECTED) {
 248                netdev_err(vif->ndev, "Already scan\n");
 249                result = -EBUSY;
 250                goto error;
 251        }
 252
 253        if (vif->obtaining_ip || vif->connecting) {
 254                netdev_err(vif->ndev, "Don't do obss scan\n");
 255                result = -EBUSY;
 256                goto error;
 257        }
 258
 259        hif_drv->usr_scan_req.ch_cnt = 0;
 260
 261        if (request->n_ssids) {
 262                for (i = 0; i < request->n_ssids; i++)
 263                        valuesize += ((request->ssids[i].ssid_len) + 1);
 264                search_ssid_vals = kmalloc(valuesize + 1, GFP_KERNEL);
 265                if (search_ssid_vals) {
 266                        wid_list[index].id = WID_SSID_PROBE_REQ;
 267                        wid_list[index].type = WID_STR;
 268                        wid_list[index].val = search_ssid_vals;
 269                        buffer = wid_list[index].val;
 270
 271                        *buffer++ = request->n_ssids;
 272
 273                        for (i = 0; i < request->n_ssids; i++) {
 274                                *buffer++ = request->ssids[i].ssid_len;
 275                                memcpy(buffer, request->ssids[i].ssid,
 276                                       request->ssids[i].ssid_len);
 277                                buffer += request->ssids[i].ssid_len;
 278                        }
 279                        wid_list[index].size = (s32)(valuesize + 1);
 280                        index++;
 281                }
 282        }
 283
 284        wid_list[index].id = WID_INFO_ELEMENT_PROBE;
 285        wid_list[index].type = WID_BIN_DATA;
 286        wid_list[index].val = (s8 *)request->ie;
 287        wid_list[index].size = request->ie_len;
 288        index++;
 289
 290        wid_list[index].id = WID_SCAN_TYPE;
 291        wid_list[index].type = WID_CHAR;
 292        wid_list[index].size = sizeof(char);
 293        wid_list[index].val = (s8 *)&scan_type;
 294        index++;
 295
 296        wid_list[index].id = WID_SCAN_CHANNEL_LIST;
 297        wid_list[index].type = WID_BIN_DATA;
 298
 299        if (ch_freq_list && ch_list_len > 0) {
 300                for (i = 0; i < ch_list_len; i++) {
 301                        if (ch_freq_list[i] > 0)
 302                                ch_freq_list[i] -= 1;
 303                }
 304        }
 305
 306        wid_list[index].val = ch_freq_list;
 307        wid_list[index].size = ch_list_len;
 308        index++;
 309
 310        wid_list[index].id = WID_START_SCAN_REQ;
 311        wid_list[index].type = WID_CHAR;
 312        wid_list[index].size = sizeof(char);
 313        wid_list[index].val = (s8 *)&scan_source;
 314        index++;
 315
 316        hif_drv->usr_scan_req.scan_result = scan_result_fn;
 317        hif_drv->usr_scan_req.arg = user_arg;
 318
 319        result = wilc_send_config_pkt(vif, WILC_SET_CFG, wid_list,
 320                                      index,
 321                                      wilc_get_vif_idx(vif));
 322        if (result) {
 323                netdev_err(vif->ndev, "Failed to send scan parameters\n");
 324                goto error;
 325        }
 326
 327        hif_drv->scan_timer_vif = vif;
 328        mod_timer(&hif_drv->scan_timer,
 329                  jiffies + msecs_to_jiffies(WILC_HIF_SCAN_TIMEOUT_MS));
 330
 331error:
 332
 333        kfree(search_ssid_vals);
 334
 335        return result;
 336}
 337
 338static int wilc_send_connect_wid(struct wilc_vif *vif)
 339{
 340        int result = 0;
 341        struct wid wid_list[4];
 342        u32 wid_cnt = 0;
 343        struct host_if_drv *hif_drv = vif->hif_drv;
 344        struct wilc_conn_info *conn_attr = &hif_drv->conn_info;
 345        struct wilc_join_bss_param *bss_param = conn_attr->param;
 346
 347        wid_list[wid_cnt].id = WID_INFO_ELEMENT_ASSOCIATE;
 348        wid_list[wid_cnt].type = WID_BIN_DATA;
 349        wid_list[wid_cnt].val = conn_attr->req_ies;
 350        wid_list[wid_cnt].size = conn_attr->req_ies_len;
 351        wid_cnt++;
 352
 353        wid_list[wid_cnt].id = WID_11I_MODE;
 354        wid_list[wid_cnt].type = WID_CHAR;
 355        wid_list[wid_cnt].size = sizeof(char);
 356        wid_list[wid_cnt].val = (s8 *)&conn_attr->security;
 357        wid_cnt++;
 358
 359        wid_list[wid_cnt].id = WID_AUTH_TYPE;
 360        wid_list[wid_cnt].type = WID_CHAR;
 361        wid_list[wid_cnt].size = sizeof(char);
 362        wid_list[wid_cnt].val = (s8 *)&conn_attr->auth_type;
 363        wid_cnt++;
 364
 365        wid_list[wid_cnt].id = WID_JOIN_REQ_EXTENDED;
 366        wid_list[wid_cnt].type = WID_STR;
 367        wid_list[wid_cnt].size = sizeof(*bss_param);
 368        wid_list[wid_cnt].val = (u8 *)bss_param;
 369        wid_cnt++;
 370
 371        result = wilc_send_config_pkt(vif, WILC_SET_CFG, wid_list,
 372                                      wid_cnt,
 373                                      wilc_get_vif_idx(vif));
 374        if (result) {
 375                netdev_err(vif->ndev, "failed to send config packet\n");
 376                goto error;
 377        } else {
 378                hif_drv->hif_state = HOST_IF_WAITING_CONN_RESP;
 379        }
 380
 381        return 0;
 382
 383error:
 384
 385        kfree(conn_attr->req_ies);
 386        conn_attr->req_ies = NULL;
 387
 388        return result;
 389}
 390
 391static void handle_connect_timeout(struct work_struct *work)
 392{
 393        struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
 394        struct wilc_vif *vif = msg->vif;
 395        int result;
 396        struct wid wid;
 397        u16 dummy_reason_code = 0;
 398        struct host_if_drv *hif_drv = vif->hif_drv;
 399
 400        if (!hif_drv) {
 401                netdev_err(vif->ndev, "%s: hif driver is NULL\n", __func__);
 402                goto out;
 403        }
 404
 405        hif_drv->hif_state = HOST_IF_IDLE;
 406
 407        if (hif_drv->conn_info.conn_result) {
 408                hif_drv->conn_info.conn_result(CONN_DISCONN_EVENT_CONN_RESP,
 409                                               WILC_MAC_STATUS_DISCONNECTED,
 410                                               hif_drv->conn_info.arg);
 411
 412        } else {
 413                netdev_err(vif->ndev, "%s: conn_result is NULL\n", __func__);
 414        }
 415
 416        wid.id = WID_DISCONNECT;
 417        wid.type = WID_CHAR;
 418        wid.val = (s8 *)&dummy_reason_code;
 419        wid.size = sizeof(char);
 420
 421        result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
 422                                      wilc_get_vif_idx(vif));
 423        if (result)
 424                netdev_err(vif->ndev, "Failed to send disconnect\n");
 425
 426        hif_drv->conn_info.req_ies_len = 0;
 427        kfree(hif_drv->conn_info.req_ies);
 428        hif_drv->conn_info.req_ies = NULL;
 429
 430out:
 431        kfree(msg);
 432}
 433
 434void *wilc_parse_join_bss_param(struct cfg80211_bss *bss,
 435                                struct cfg80211_crypto_settings *crypto)
 436{
 437        struct wilc_join_bss_param *param;
 438        struct ieee80211_p2p_noa_attr noa_attr;
 439        u8 rates_len = 0;
 440        const u8 *tim_elm, *ssid_elm, *rates_ie, *supp_rates_ie;
 441        const u8 *ht_ie, *wpa_ie, *wmm_ie, *rsn_ie;
 442        int ret;
 443        const struct cfg80211_bss_ies *ies = rcu_dereference(bss->ies);
 444
 445        param = kzalloc(sizeof(*param), GFP_KERNEL);
 446        if (!param)
 447                return NULL;
 448
 449        param->beacon_period = cpu_to_le16(bss->beacon_interval);
 450        param->cap_info = cpu_to_le16(bss->capability);
 451        param->bss_type = WILC_FW_BSS_TYPE_INFRA;
 452        param->ch = ieee80211_frequency_to_channel(bss->channel->center_freq);
 453        ether_addr_copy(param->bssid, bss->bssid);
 454
 455        ssid_elm = cfg80211_find_ie(WLAN_EID_SSID, ies->data, ies->len);
 456        if (ssid_elm) {
 457                if (ssid_elm[1] <= IEEE80211_MAX_SSID_LEN)
 458                        memcpy(param->ssid, ssid_elm + 2, ssid_elm[1]);
 459        }
 460
 461        tim_elm = cfg80211_find_ie(WLAN_EID_TIM, ies->data, ies->len);
 462        if (tim_elm && tim_elm[1] >= 2)
 463                param->dtim_period = tim_elm[3];
 464
 465        memset(param->p_suites, 0xFF, 3);
 466        memset(param->akm_suites, 0xFF, 3);
 467
 468        rates_ie = cfg80211_find_ie(WLAN_EID_SUPP_RATES, ies->data, ies->len);
 469        if (rates_ie) {
 470                rates_len = rates_ie[1];
 471                param->supp_rates[0] = rates_len;
 472                memcpy(&param->supp_rates[1], rates_ie + 2, rates_len);
 473        }
 474
 475        supp_rates_ie = cfg80211_find_ie(WLAN_EID_EXT_SUPP_RATES, ies->data,
 476                                         ies->len);
 477        if (supp_rates_ie) {
 478                if (supp_rates_ie[1] > (WILC_MAX_RATES_SUPPORTED - rates_len))
 479                        param->supp_rates[0] = WILC_MAX_RATES_SUPPORTED;
 480                else
 481                        param->supp_rates[0] += supp_rates_ie[1];
 482
 483                memcpy(&param->supp_rates[rates_len + 1], supp_rates_ie + 2,
 484                       (param->supp_rates[0] - rates_len));
 485        }
 486
 487        ht_ie = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, ies->data, ies->len);
 488        if (ht_ie)
 489                param->ht_capable = true;
 490
 491        ret = cfg80211_get_p2p_attr(ies->data, ies->len,
 492                                    IEEE80211_P2P_ATTR_ABSENCE_NOTICE,
 493                                    (u8 *)&noa_attr, sizeof(noa_attr));
 494        if (ret > 0) {
 495                param->tsf_lo = cpu_to_le32(ies->tsf);
 496                param->noa_enabled = 1;
 497                param->idx = noa_attr.index;
 498                if (noa_attr.oppps_ctwindow & IEEE80211_P2P_OPPPS_ENABLE_BIT) {
 499                        param->opp_enabled = 1;
 500                        param->opp_en.ct_window = noa_attr.oppps_ctwindow;
 501                        param->opp_en.cnt = noa_attr.desc[0].count;
 502                        param->opp_en.duration = noa_attr.desc[0].duration;
 503                        param->opp_en.interval = noa_attr.desc[0].interval;
 504                        param->opp_en.start_time = noa_attr.desc[0].start_time;
 505                } else {
 506                        param->opp_enabled = 0;
 507                        param->opp_dis.cnt = noa_attr.desc[0].count;
 508                        param->opp_dis.duration = noa_attr.desc[0].duration;
 509                        param->opp_dis.interval = noa_attr.desc[0].interval;
 510                        param->opp_dis.start_time = noa_attr.desc[0].start_time;
 511                }
 512        }
 513        wmm_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
 514                                         WLAN_OUI_TYPE_MICROSOFT_WMM,
 515                                         ies->data, ies->len);
 516        if (wmm_ie) {
 517                struct ieee80211_wmm_param_ie *ie;
 518
 519                ie = (struct ieee80211_wmm_param_ie *)wmm_ie;
 520                if ((ie->oui_subtype == 0 || ie->oui_subtype == 1) &&
 521                    ie->version == 1) {
 522                        param->wmm_cap = true;
 523                        if (ie->qos_info & BIT(7))
 524                                param->uapsd_cap = true;
 525                }
 526        }
 527
 528        wpa_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
 529                                         WLAN_OUI_TYPE_MICROSOFT_WPA,
 530                                         ies->data, ies->len);
 531        if (wpa_ie) {
 532                param->mode_802_11i = 1;
 533                param->rsn_found = true;
 534        }
 535
 536        rsn_ie = cfg80211_find_ie(WLAN_EID_RSN, ies->data, ies->len);
 537        if (rsn_ie) {
 538                int offset = 8;
 539
 540                param->mode_802_11i = 2;
 541                param->rsn_found = true;
 542                //extract RSN capabilities
 543                offset += (rsn_ie[offset] * 4) + 2;
 544                offset += (rsn_ie[offset] * 4) + 2;
 545                memcpy(param->rsn_cap, &rsn_ie[offset], 2);
 546        }
 547
 548        if (param->rsn_found) {
 549                int i;
 550
 551                param->rsn_grp_policy = crypto->cipher_group & 0xFF;
 552                for (i = 0; i < crypto->n_ciphers_pairwise && i < 3; i++)
 553                        param->p_suites[i] = crypto->ciphers_pairwise[i] & 0xFF;
 554
 555                for (i = 0; i < crypto->n_akm_suites && i < 3; i++)
 556                        param->akm_suites[i] = crypto->akm_suites[i] & 0xFF;
 557        }
 558
 559        return (void *)param;
 560}
 561
 562static void handle_rcvd_ntwrk_info(struct work_struct *work)
 563{
 564        struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
 565        struct wilc_rcvd_net_info *rcvd_info = &msg->body.net_info;
 566        struct wilc_user_scan_req *scan_req = &msg->vif->hif_drv->usr_scan_req;
 567        const u8 *ch_elm;
 568        u8 *ies;
 569        int ies_len;
 570        size_t offset;
 571
 572        if (ieee80211_is_probe_resp(rcvd_info->mgmt->frame_control))
 573                offset = offsetof(struct ieee80211_mgmt, u.probe_resp.variable);
 574        else if (ieee80211_is_beacon(rcvd_info->mgmt->frame_control))
 575                offset = offsetof(struct ieee80211_mgmt, u.beacon.variable);
 576        else
 577                goto done;
 578
 579        ies = rcvd_info->mgmt->u.beacon.variable;
 580        ies_len = rcvd_info->frame_len - offset;
 581        if (ies_len <= 0)
 582                goto done;
 583
 584        ch_elm = cfg80211_find_ie(WLAN_EID_DS_PARAMS, ies, ies_len);
 585        if (ch_elm && ch_elm[1] > 0)
 586                rcvd_info->ch = ch_elm[2];
 587
 588        if (scan_req->scan_result)
 589                scan_req->scan_result(SCAN_EVENT_NETWORK_FOUND, rcvd_info,
 590                                      scan_req->arg);
 591
 592done:
 593        kfree(rcvd_info->mgmt);
 594        kfree(msg);
 595}
 596
 597static void host_int_get_assoc_res_info(struct wilc_vif *vif,
 598                                        u8 *assoc_resp_info,
 599                                        u32 max_assoc_resp_info_len,
 600                                        u32 *rcvd_assoc_resp_info_len)
 601{
 602        int result;
 603        struct wid wid;
 604
 605        wid.id = WID_ASSOC_RES_INFO;
 606        wid.type = WID_STR;
 607        wid.val = assoc_resp_info;
 608        wid.size = max_assoc_resp_info_len;
 609
 610        result = wilc_send_config_pkt(vif, WILC_GET_CFG, &wid, 1,
 611                                      wilc_get_vif_idx(vif));
 612        if (result) {
 613                *rcvd_assoc_resp_info_len = 0;
 614                netdev_err(vif->ndev, "Failed to send association response\n");
 615                return;
 616        }
 617
 618        *rcvd_assoc_resp_info_len = wid.size;
 619}
 620
 621static s32 wilc_parse_assoc_resp_info(u8 *buffer, u32 buffer_len,
 622                                      struct wilc_conn_info *ret_conn_info)
 623{
 624        u8 *ies;
 625        u16 ies_len;
 626        struct assoc_resp *res = (struct assoc_resp *)buffer;
 627
 628        ret_conn_info->status = le16_to_cpu(res->status_code);
 629        if (ret_conn_info->status == WLAN_STATUS_SUCCESS) {
 630                ies = &buffer[sizeof(*res)];
 631                ies_len = buffer_len - sizeof(*res);
 632
 633                ret_conn_info->resp_ies = kmemdup(ies, ies_len, GFP_KERNEL);
 634                if (!ret_conn_info->resp_ies)
 635                        return -ENOMEM;
 636
 637                ret_conn_info->resp_ies_len = ies_len;
 638        }
 639
 640        return 0;
 641}
 642
 643static inline void host_int_parse_assoc_resp_info(struct wilc_vif *vif,
 644                                                  u8 mac_status)
 645{
 646        struct host_if_drv *hif_drv = vif->hif_drv;
 647        struct wilc_conn_info *conn_info = &hif_drv->conn_info;
 648
 649        if (mac_status == WILC_MAC_STATUS_CONNECTED) {
 650                u32 assoc_resp_info_len;
 651
 652                memset(hif_drv->assoc_resp, 0, WILC_MAX_ASSOC_RESP_FRAME_SIZE);
 653
 654                host_int_get_assoc_res_info(vif, hif_drv->assoc_resp,
 655                                            WILC_MAX_ASSOC_RESP_FRAME_SIZE,
 656                                            &assoc_resp_info_len);
 657
 658                if (assoc_resp_info_len != 0) {
 659                        s32 err = 0;
 660
 661                        err = wilc_parse_assoc_resp_info(hif_drv->assoc_resp,
 662                                                         assoc_resp_info_len,
 663                                                         conn_info);
 664                        if (err)
 665                                netdev_err(vif->ndev,
 666                                           "wilc_parse_assoc_resp_info() returned error %d\n",
 667                                           err);
 668                }
 669        }
 670
 671        del_timer(&hif_drv->connect_timer);
 672        conn_info->conn_result(CONN_DISCONN_EVENT_CONN_RESP, mac_status,
 673                               hif_drv->conn_info.arg);
 674
 675        if (mac_status == WILC_MAC_STATUS_CONNECTED &&
 676            conn_info->status == WLAN_STATUS_SUCCESS) {
 677                ether_addr_copy(hif_drv->assoc_bssid, conn_info->bssid);
 678                wilc_set_power_mgmt(vif, 0, 0);
 679
 680                hif_drv->hif_state = HOST_IF_CONNECTED;
 681
 682                vif->obtaining_ip = true;
 683                mod_timer(&vif->during_ip_timer,
 684                          jiffies + msecs_to_jiffies(10000));
 685        } else {
 686                hif_drv->hif_state = HOST_IF_IDLE;
 687        }
 688
 689        kfree(conn_info->resp_ies);
 690        conn_info->resp_ies = NULL;
 691        conn_info->resp_ies_len = 0;
 692
 693        kfree(conn_info->req_ies);
 694        conn_info->req_ies = NULL;
 695        conn_info->req_ies_len = 0;
 696}
 697
 698static inline void host_int_handle_disconnect(struct wilc_vif *vif)
 699{
 700        struct host_if_drv *hif_drv = vif->hif_drv;
 701
 702        if (hif_drv->usr_scan_req.scan_result) {
 703                del_timer(&hif_drv->scan_timer);
 704                handle_scan_done(vif, SCAN_EVENT_ABORTED);
 705        }
 706
 707        if (hif_drv->conn_info.conn_result) {
 708                vif->obtaining_ip = false;
 709                wilc_set_power_mgmt(vif, 0, 0);
 710
 711                hif_drv->conn_info.conn_result(CONN_DISCONN_EVENT_DISCONN_NOTIF,
 712                                               0, hif_drv->conn_info.arg);
 713        } else {
 714                netdev_err(vif->ndev, "%s: conn_result is NULL\n", __func__);
 715        }
 716
 717        eth_zero_addr(hif_drv->assoc_bssid);
 718
 719        hif_drv->conn_info.req_ies_len = 0;
 720        kfree(hif_drv->conn_info.req_ies);
 721        hif_drv->conn_info.req_ies = NULL;
 722        hif_drv->hif_state = HOST_IF_IDLE;
 723}
 724
 725static void handle_rcvd_gnrl_async_info(struct work_struct *work)
 726{
 727        struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
 728        struct wilc_vif *vif = msg->vif;
 729        struct wilc_rcvd_mac_info *mac_info = &msg->body.mac_info;
 730        struct host_if_drv *hif_drv = vif->hif_drv;
 731
 732        if (!hif_drv) {
 733                netdev_err(vif->ndev, "%s: hif driver is NULL\n", __func__);
 734                goto free_msg;
 735        }
 736
 737        if (!hif_drv->conn_info.conn_result) {
 738                netdev_err(vif->ndev, "%s: conn_result is NULL\n", __func__);
 739                goto free_msg;
 740        }
 741
 742        if (hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP) {
 743                host_int_parse_assoc_resp_info(vif, mac_info->status);
 744        } else if (mac_info->status == WILC_MAC_STATUS_DISCONNECTED) {
 745                if (hif_drv->hif_state == HOST_IF_CONNECTED) {
 746                        host_int_handle_disconnect(vif);
 747                } else if (hif_drv->usr_scan_req.scan_result) {
 748                        del_timer(&hif_drv->scan_timer);
 749                        handle_scan_done(vif, SCAN_EVENT_ABORTED);
 750                }
 751        }
 752
 753free_msg:
 754        kfree(msg);
 755}
 756
 757int wilc_disconnect(struct wilc_vif *vif)
 758{
 759        struct wid wid;
 760        struct host_if_drv *hif_drv = vif->hif_drv;
 761        struct wilc_user_scan_req *scan_req;
 762        struct wilc_conn_info *conn_info;
 763        int result;
 764        u16 dummy_reason_code = 0;
 765
 766        wid.id = WID_DISCONNECT;
 767        wid.type = WID_CHAR;
 768        wid.val = (s8 *)&dummy_reason_code;
 769        wid.size = sizeof(char);
 770
 771        vif->obtaining_ip = false;
 772        wilc_set_power_mgmt(vif, 0, 0);
 773
 774        result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
 775                                      wilc_get_vif_idx(vif));
 776        if (result) {
 777                netdev_err(vif->ndev, "Failed to send disconnect\n");
 778                return result;
 779        }
 780
 781        scan_req = &hif_drv->usr_scan_req;
 782        conn_info = &hif_drv->conn_info;
 783
 784        if (scan_req->scan_result) {
 785                del_timer(&hif_drv->scan_timer);
 786                scan_req->scan_result(SCAN_EVENT_ABORTED, NULL, scan_req->arg);
 787                scan_req->scan_result = NULL;
 788        }
 789
 790        if (conn_info->conn_result) {
 791                if (hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP)
 792                        del_timer(&hif_drv->connect_timer);
 793
 794                conn_info->conn_result(CONN_DISCONN_EVENT_DISCONN_NOTIF, 0,
 795                                       conn_info->arg);
 796        } else {
 797                netdev_err(vif->ndev, "%s: conn_result is NULL\n", __func__);
 798        }
 799
 800        hif_drv->hif_state = HOST_IF_IDLE;
 801
 802        eth_zero_addr(hif_drv->assoc_bssid);
 803
 804        conn_info->req_ies_len = 0;
 805        kfree(conn_info->req_ies);
 806        conn_info->req_ies = NULL;
 807
 808        return 0;
 809}
 810
 811void wilc_resolve_disconnect_aberration(struct wilc_vif *vif)
 812{
 813        if (!vif->hif_drv)
 814                return;
 815        if (vif->hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP ||
 816            vif->hif_drv->hif_state == HOST_IF_CONNECTING)
 817                wilc_disconnect(vif);
 818}
 819
 820int wilc_get_statistics(struct wilc_vif *vif, struct rf_info *stats)
 821{
 822        struct wid wid_list[5];
 823        u32 wid_cnt = 0, result;
 824
 825        wid_list[wid_cnt].id = WID_LINKSPEED;
 826        wid_list[wid_cnt].type = WID_CHAR;
 827        wid_list[wid_cnt].size = sizeof(char);
 828        wid_list[wid_cnt].val = (s8 *)&stats->link_speed;
 829        wid_cnt++;
 830
 831        wid_list[wid_cnt].id = WID_RSSI;
 832        wid_list[wid_cnt].type = WID_CHAR;
 833        wid_list[wid_cnt].size = sizeof(char);
 834        wid_list[wid_cnt].val = (s8 *)&stats->rssi;
 835        wid_cnt++;
 836
 837        wid_list[wid_cnt].id = WID_SUCCESS_FRAME_COUNT;
 838        wid_list[wid_cnt].type = WID_INT;
 839        wid_list[wid_cnt].size = sizeof(u32);
 840        wid_list[wid_cnt].val = (s8 *)&stats->tx_cnt;
 841        wid_cnt++;
 842
 843        wid_list[wid_cnt].id = WID_RECEIVED_FRAGMENT_COUNT;
 844        wid_list[wid_cnt].type = WID_INT;
 845        wid_list[wid_cnt].size = sizeof(u32);
 846        wid_list[wid_cnt].val = (s8 *)&stats->rx_cnt;
 847        wid_cnt++;
 848
 849        wid_list[wid_cnt].id = WID_FAILED_COUNT;
 850        wid_list[wid_cnt].type = WID_INT;
 851        wid_list[wid_cnt].size = sizeof(u32);
 852        wid_list[wid_cnt].val = (s8 *)&stats->tx_fail_cnt;
 853        wid_cnt++;
 854
 855        result = wilc_send_config_pkt(vif, WILC_GET_CFG, wid_list,
 856                                      wid_cnt,
 857                                      wilc_get_vif_idx(vif));
 858
 859        if (result) {
 860                netdev_err(vif->ndev, "Failed to send scan parameters\n");
 861                return result;
 862        }
 863
 864        if (stats->link_speed > TCP_ACK_FILTER_LINK_SPEED_THRESH &&
 865            stats->link_speed != DEFAULT_LINK_SPEED)
 866                wilc_enable_tcp_ack_filter(vif, true);
 867        else if (stats->link_speed != DEFAULT_LINK_SPEED)
 868                wilc_enable_tcp_ack_filter(vif, false);
 869
 870        return result;
 871}
 872
 873static void handle_get_statistics(struct work_struct *work)
 874{
 875        struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
 876        struct wilc_vif *vif = msg->vif;
 877        struct rf_info *stats = (struct rf_info *)msg->body.data;
 878
 879        wilc_get_statistics(vif, stats);
 880
 881        kfree(msg);
 882}
 883
 884static void wilc_hif_pack_sta_param(u8 *cur_byte, const u8 *mac,
 885                                    struct station_parameters *params)
 886{
 887        ether_addr_copy(cur_byte, mac);
 888        cur_byte += ETH_ALEN;
 889
 890        put_unaligned_le16(params->aid, cur_byte);
 891        cur_byte += 2;
 892
 893        *cur_byte++ = params->supported_rates_len;
 894        if (params->supported_rates_len > 0)
 895                memcpy(cur_byte, params->supported_rates,
 896                       params->supported_rates_len);
 897        cur_byte += params->supported_rates_len;
 898
 899        if (params->ht_capa) {
 900                *cur_byte++ = true;
 901                memcpy(cur_byte, &params->ht_capa,
 902                       sizeof(struct ieee80211_ht_cap));
 903        } else {
 904                *cur_byte++ = false;
 905        }
 906        cur_byte += sizeof(struct ieee80211_ht_cap);
 907
 908        put_unaligned_le16(params->sta_flags_mask, cur_byte);
 909        cur_byte += 2;
 910        put_unaligned_le16(params->sta_flags_set, cur_byte);
 911}
 912
 913static int handle_remain_on_chan(struct wilc_vif *vif,
 914                                 struct wilc_remain_ch *hif_remain_ch)
 915{
 916        int result;
 917        u8 remain_on_chan_flag;
 918        struct wid wid;
 919        struct host_if_drv *hif_drv = vif->hif_drv;
 920
 921        if (hif_drv->usr_scan_req.scan_result)
 922                return -EBUSY;
 923
 924        if (hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP)
 925                return -EBUSY;
 926
 927        if (vif->obtaining_ip || vif->connecting)
 928                return -EBUSY;
 929
 930        remain_on_chan_flag = true;
 931        wid.id = WID_REMAIN_ON_CHAN;
 932        wid.type = WID_STR;
 933        wid.size = 2;
 934        wid.val = kmalloc(wid.size, GFP_KERNEL);
 935        if (!wid.val)
 936                return -ENOMEM;
 937
 938        wid.val[0] = remain_on_chan_flag;
 939        wid.val[1] = (s8)hif_remain_ch->ch;
 940
 941        result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
 942                                      wilc_get_vif_idx(vif));
 943        kfree(wid.val);
 944        if (result)
 945                return -EBUSY;
 946
 947        hif_drv->remain_on_ch.arg = hif_remain_ch->arg;
 948        hif_drv->remain_on_ch.expired = hif_remain_ch->expired;
 949        hif_drv->remain_on_ch.ch = hif_remain_ch->ch;
 950        hif_drv->remain_on_ch.cookie = hif_remain_ch->cookie;
 951        hif_drv->remain_on_ch_timer_vif = vif;
 952
 953        return 0;
 954}
 955
 956static void handle_listen_state_expired(struct work_struct *work)
 957{
 958        struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
 959        struct wilc_vif *vif = msg->vif;
 960        struct wilc_remain_ch *hif_remain_ch = &msg->body.remain_on_ch;
 961        u8 remain_on_chan_flag;
 962        struct wid wid;
 963        int result;
 964        struct host_if_drv *hif_drv = vif->hif_drv;
 965        struct wilc_priv *priv = wdev_priv(vif->ndev->ieee80211_ptr);
 966
 967        if (priv->p2p_listen_state) {
 968                remain_on_chan_flag = false;
 969                wid.id = WID_REMAIN_ON_CHAN;
 970                wid.type = WID_STR;
 971                wid.size = 2;
 972                wid.val = kmalloc(wid.size, GFP_KERNEL);
 973
 974                if (!wid.val)
 975                        goto free_msg;
 976
 977                wid.val[0] = remain_on_chan_flag;
 978                wid.val[1] = WILC_FALSE_FRMWR_CHANNEL;
 979
 980                result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
 981                                              wilc_get_vif_idx(vif));
 982                kfree(wid.val);
 983                if (result != 0) {
 984                        netdev_err(vif->ndev, "Failed to set remain channel\n");
 985                        goto free_msg;
 986                }
 987
 988                if (hif_drv->remain_on_ch.expired) {
 989                        hif_drv->remain_on_ch.expired(hif_drv->remain_on_ch.arg,
 990                                                      hif_remain_ch->cookie);
 991                }
 992        } else {
 993                netdev_dbg(vif->ndev, "Not in listen state\n");
 994        }
 995
 996free_msg:
 997        kfree(msg);
 998}
 999
1000static void listen_timer_cb(struct timer_list *t)
1001{
1002        struct host_if_drv *hif_drv = from_timer(hif_drv, t,
1003                                                      remain_on_ch_timer);
1004        struct wilc_vif *vif = hif_drv->remain_on_ch_timer_vif;
1005        int result;
1006        struct host_if_msg *msg;
1007
1008        del_timer(&vif->hif_drv->remain_on_ch_timer);
1009
1010        msg = wilc_alloc_work(vif, handle_listen_state_expired, false);
1011        if (IS_ERR(msg))
1012                return;
1013
1014        msg->body.remain_on_ch.cookie = vif->hif_drv->remain_on_ch.cookie;
1015
1016        result = wilc_enqueue_work(msg);
1017        if (result) {
1018                netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__);
1019                kfree(msg);
1020        }
1021}
1022
1023static void handle_set_mcast_filter(struct work_struct *work)
1024{
1025        struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
1026        struct wilc_vif *vif = msg->vif;
1027        struct wilc_set_multicast *set_mc = &msg->body.mc_info;
1028        int result;
1029        struct wid wid;
1030        u8 *cur_byte;
1031
1032        wid.id = WID_SETUP_MULTICAST_FILTER;
1033        wid.type = WID_BIN;
1034        wid.size = sizeof(struct wilc_set_multicast) + (set_mc->cnt * ETH_ALEN);
1035        wid.val = kmalloc(wid.size, GFP_KERNEL);
1036        if (!wid.val)
1037                goto error;
1038
1039        cur_byte = wid.val;
1040        put_unaligned_le32(set_mc->enabled, cur_byte);
1041        cur_byte += 4;
1042
1043        put_unaligned_le32(set_mc->cnt, cur_byte);
1044        cur_byte += 4;
1045
1046        if (set_mc->cnt > 0 && set_mc->mc_list)
1047                memcpy(cur_byte, set_mc->mc_list, set_mc->cnt * ETH_ALEN);
1048
1049        result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
1050                                      wilc_get_vif_idx(vif));
1051        if (result)
1052                netdev_err(vif->ndev, "Failed to send setup multicast\n");
1053
1054error:
1055        kfree(set_mc->mc_list);
1056        kfree(wid.val);
1057        kfree(msg);
1058}
1059
1060static void handle_scan_timer(struct work_struct *work)
1061{
1062        struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
1063
1064        handle_scan_done(msg->vif, SCAN_EVENT_ABORTED);
1065        kfree(msg);
1066}
1067
1068static void handle_scan_complete(struct work_struct *work)
1069{
1070        struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
1071        struct wilc *wilc = msg->vif->wilc;
1072
1073        del_timer(&msg->vif->hif_drv->scan_timer);
1074
1075        if (!wilc_wlan_get_num_conn_ifcs(wilc))
1076                wilc_chip_sleep_manually(wilc);
1077
1078        handle_scan_done(msg->vif, SCAN_EVENT_DONE);
1079
1080        kfree(msg);
1081}
1082
1083static void timer_scan_cb(struct timer_list *t)
1084{
1085        struct host_if_drv *hif_drv = from_timer(hif_drv, t, scan_timer);
1086        struct wilc_vif *vif = hif_drv->scan_timer_vif;
1087        struct host_if_msg *msg;
1088        int result;
1089
1090        msg = wilc_alloc_work(vif, handle_scan_timer, false);
1091        if (IS_ERR(msg))
1092                return;
1093
1094        result = wilc_enqueue_work(msg);
1095        if (result)
1096                kfree(msg);
1097}
1098
1099static void timer_connect_cb(struct timer_list *t)
1100{
1101        struct host_if_drv *hif_drv = from_timer(hif_drv, t,
1102                                                      connect_timer);
1103        struct wilc_vif *vif = hif_drv->connect_timer_vif;
1104        struct host_if_msg *msg;
1105        int result;
1106
1107        msg = wilc_alloc_work(vif, handle_connect_timeout, false);
1108        if (IS_ERR(msg))
1109                return;
1110
1111        result = wilc_enqueue_work(msg);
1112        if (result)
1113                kfree(msg);
1114}
1115
1116int wilc_remove_wep_key(struct wilc_vif *vif, u8 index)
1117{
1118        struct wid wid;
1119        int result;
1120
1121        wid.id = WID_REMOVE_WEP_KEY;
1122        wid.type = WID_STR;
1123        wid.size = sizeof(char);
1124        wid.val = &index;
1125
1126        result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
1127                                      wilc_get_vif_idx(vif));
1128        if (result)
1129                netdev_err(vif->ndev,
1130                           "Failed to send remove wep key config packet\n");
1131        return result;
1132}
1133
1134int wilc_set_wep_default_keyid(struct wilc_vif *vif, u8 index)
1135{
1136        struct wid wid;
1137        int result;
1138
1139        wid.id = WID_KEY_ID;
1140        wid.type = WID_CHAR;
1141        wid.size = sizeof(char);
1142        wid.val = &index;
1143        result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
1144                                      wilc_get_vif_idx(vif));
1145        if (result)
1146                netdev_err(vif->ndev,
1147                           "Failed to send wep default key config packet\n");
1148
1149        return result;
1150}
1151
1152int wilc_add_wep_key_bss_sta(struct wilc_vif *vif, const u8 *key, u8 len,
1153                             u8 index)
1154{
1155        struct wid wid;
1156        int result;
1157        struct wilc_wep_key *wep_key;
1158
1159        wid.id = WID_ADD_WEP_KEY;
1160        wid.type = WID_STR;
1161        wid.size = sizeof(*wep_key) + len;
1162        wep_key = kzalloc(wid.size, GFP_KERNEL);
1163        if (!wep_key)
1164                return -ENOMEM;
1165
1166        wid.val = (u8 *)wep_key;
1167
1168        wep_key->index = index;
1169        wep_key->key_len = len;
1170        memcpy(wep_key->key, key, len);
1171
1172        result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
1173                                      wilc_get_vif_idx(vif));
1174        if (result)
1175                netdev_err(vif->ndev,
1176                           "Failed to add wep key config packet\n");
1177
1178        kfree(wep_key);
1179        return result;
1180}
1181
1182int wilc_add_wep_key_bss_ap(struct wilc_vif *vif, const u8 *key, u8 len,
1183                            u8 index, u8 mode, enum authtype auth_type)
1184{
1185        struct wid wid_list[3];
1186        int result;
1187        struct wilc_wep_key *wep_key;
1188
1189        wid_list[0].id = WID_11I_MODE;
1190        wid_list[0].type = WID_CHAR;
1191        wid_list[0].size = sizeof(char);
1192        wid_list[0].val = &mode;
1193
1194        wid_list[1].id = WID_AUTH_TYPE;
1195        wid_list[1].type = WID_CHAR;
1196        wid_list[1].size = sizeof(char);
1197        wid_list[1].val = (s8 *)&auth_type;
1198
1199        wid_list[2].id = WID_WEP_KEY_VALUE;
1200        wid_list[2].type = WID_STR;
1201        wid_list[2].size = sizeof(*wep_key) + len;
1202        wep_key = kzalloc(wid_list[2].size, GFP_KERNEL);
1203        if (!wep_key)
1204                return -ENOMEM;
1205
1206        wid_list[2].val = (u8 *)wep_key;
1207
1208        wep_key->index = index;
1209        wep_key->key_len = len;
1210        memcpy(wep_key->key, key, len);
1211        result = wilc_send_config_pkt(vif, WILC_SET_CFG, wid_list,
1212                                      ARRAY_SIZE(wid_list),
1213                                      wilc_get_vif_idx(vif));
1214        if (result)
1215                netdev_err(vif->ndev,
1216                           "Failed to add wep ap key config packet\n");
1217
1218        kfree(wep_key);
1219        return result;
1220}
1221
1222int wilc_add_ptk(struct wilc_vif *vif, const u8 *ptk, u8 ptk_key_len,
1223                 const u8 *mac_addr, const u8 *rx_mic, const u8 *tx_mic,
1224                 u8 mode, u8 cipher_mode, u8 index)
1225{
1226        int result = 0;
1227        u8 t_key_len  = ptk_key_len + WILC_RX_MIC_KEY_LEN + WILC_TX_MIC_KEY_LEN;
1228
1229        if (mode == WILC_AP_MODE) {
1230                struct wid wid_list[2];
1231                struct wilc_ap_wpa_ptk *key_buf;
1232
1233                wid_list[0].id = WID_11I_MODE;
1234                wid_list[0].type = WID_CHAR;
1235                wid_list[0].size = sizeof(char);
1236                wid_list[0].val = (s8 *)&cipher_mode;
1237
1238                key_buf = kzalloc(sizeof(*key_buf) + t_key_len, GFP_KERNEL);
1239                if (!key_buf)
1240                        return -ENOMEM;
1241
1242                ether_addr_copy(key_buf->mac_addr, mac_addr);
1243                key_buf->index = index;
1244                key_buf->key_len = t_key_len;
1245                memcpy(&key_buf->key[0], ptk, ptk_key_len);
1246
1247                if (rx_mic)
1248                        memcpy(&key_buf->key[ptk_key_len], rx_mic,
1249                               WILC_RX_MIC_KEY_LEN);
1250
1251                if (tx_mic)
1252                        memcpy(&key_buf->key[ptk_key_len + WILC_RX_MIC_KEY_LEN],
1253                               tx_mic, WILC_TX_MIC_KEY_LEN);
1254
1255                wid_list[1].id = WID_ADD_PTK;
1256                wid_list[1].type = WID_STR;
1257                wid_list[1].size = sizeof(*key_buf) + t_key_len;
1258                wid_list[1].val = (u8 *)key_buf;
1259                result = wilc_send_config_pkt(vif, WILC_SET_CFG, wid_list,
1260                                              ARRAY_SIZE(wid_list),
1261                                              wilc_get_vif_idx(vif));
1262                kfree(key_buf);
1263        } else if (mode == WILC_STATION_MODE) {
1264                struct wid wid;
1265                struct wilc_sta_wpa_ptk *key_buf;
1266
1267                key_buf = kzalloc(sizeof(*key_buf) + t_key_len, GFP_KERNEL);
1268                if (!key_buf)
1269                        return -ENOMEM;
1270
1271                ether_addr_copy(key_buf->mac_addr, mac_addr);
1272                key_buf->key_len = t_key_len;
1273                memcpy(&key_buf->key[0], ptk, ptk_key_len);
1274
1275                if (rx_mic)
1276                        memcpy(&key_buf->key[ptk_key_len], rx_mic,
1277                               WILC_RX_MIC_KEY_LEN);
1278
1279                if (tx_mic)
1280                        memcpy(&key_buf->key[ptk_key_len + WILC_RX_MIC_KEY_LEN],
1281                               tx_mic, WILC_TX_MIC_KEY_LEN);
1282
1283                wid.id = WID_ADD_PTK;
1284                wid.type = WID_STR;
1285                wid.size = sizeof(*key_buf) + t_key_len;
1286                wid.val = (s8 *)key_buf;
1287                result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
1288                                              wilc_get_vif_idx(vif));
1289                kfree(key_buf);
1290        }
1291
1292        return result;
1293}
1294
1295int wilc_add_rx_gtk(struct wilc_vif *vif, const u8 *rx_gtk, u8 gtk_key_len,
1296                    u8 index, u32 key_rsc_len, const u8 *key_rsc,
1297                    const u8 *rx_mic, const u8 *tx_mic, u8 mode,
1298                    u8 cipher_mode)
1299{
1300        int result = 0;
1301        struct wilc_gtk_key *gtk_key;
1302        int t_key_len = gtk_key_len + WILC_RX_MIC_KEY_LEN + WILC_TX_MIC_KEY_LEN;
1303
1304        gtk_key = kzalloc(sizeof(*gtk_key) + t_key_len, GFP_KERNEL);
1305        if (!gtk_key)
1306                return -ENOMEM;
1307
1308        /* fill bssid value only in station mode */
1309        if (mode == WILC_STATION_MODE &&
1310            vif->hif_drv->hif_state == HOST_IF_CONNECTED)
1311                memcpy(gtk_key->mac_addr, vif->hif_drv->assoc_bssid, ETH_ALEN);
1312
1313        if (key_rsc)
1314                memcpy(gtk_key->rsc, key_rsc, 8);
1315        gtk_key->index = index;
1316        gtk_key->key_len = t_key_len;
1317        memcpy(&gtk_key->key[0], rx_gtk, gtk_key_len);
1318
1319        if (rx_mic)
1320                memcpy(&gtk_key->key[gtk_key_len], rx_mic, WILC_RX_MIC_KEY_LEN);
1321
1322        if (tx_mic)
1323                memcpy(&gtk_key->key[gtk_key_len + WILC_RX_MIC_KEY_LEN],
1324                       tx_mic, WILC_TX_MIC_KEY_LEN);
1325
1326        if (mode == WILC_AP_MODE) {
1327                struct wid wid_list[2];
1328
1329                wid_list[0].id = WID_11I_MODE;
1330                wid_list[0].type = WID_CHAR;
1331                wid_list[0].size = sizeof(char);
1332                wid_list[0].val = (s8 *)&cipher_mode;
1333
1334                wid_list[1].id = WID_ADD_RX_GTK;
1335                wid_list[1].type = WID_STR;
1336                wid_list[1].size = sizeof(*gtk_key) + t_key_len;
1337                wid_list[1].val = (u8 *)gtk_key;
1338
1339                result = wilc_send_config_pkt(vif, WILC_SET_CFG, wid_list,
1340                                              ARRAY_SIZE(wid_list),
1341                                              wilc_get_vif_idx(vif));
1342        } else if (mode == WILC_STATION_MODE) {
1343                struct wid wid;
1344
1345                wid.id = WID_ADD_RX_GTK;
1346                wid.type = WID_STR;
1347                wid.size = sizeof(*gtk_key) + t_key_len;
1348                wid.val = (u8 *)gtk_key;
1349                result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
1350                                              wilc_get_vif_idx(vif));
1351        }
1352
1353        kfree(gtk_key);
1354        return result;
1355}
1356
1357int wilc_set_pmkid_info(struct wilc_vif *vif, struct wilc_pmkid_attr *pmkid)
1358{
1359        struct wid wid;
1360
1361        wid.id = WID_PMKID_INFO;
1362        wid.type = WID_STR;
1363        wid.size = (pmkid->numpmkid * sizeof(struct wilc_pmkid)) + 1;
1364        wid.val = (u8 *)pmkid;
1365
1366        return wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
1367                                    wilc_get_vif_idx(vif));
1368}
1369
1370int wilc_get_mac_address(struct wilc_vif *vif, u8 *mac_addr)
1371{
1372        int result;
1373        struct wid wid;
1374
1375        wid.id = WID_MAC_ADDR;
1376        wid.type = WID_STR;
1377        wid.size = ETH_ALEN;
1378        wid.val = mac_addr;
1379
1380        result = wilc_send_config_pkt(vif, WILC_GET_CFG, &wid, 1,
1381                                      wilc_get_vif_idx(vif));
1382        if (result)
1383                netdev_err(vif->ndev, "Failed to get mac address\n");
1384
1385        return result;
1386}
1387
1388int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ies,
1389                      size_t ies_len)
1390{
1391        int result;
1392        struct host_if_drv *hif_drv = vif->hif_drv;
1393        struct wilc_conn_info *conn_info = &hif_drv->conn_info;
1394
1395        if (bssid)
1396                ether_addr_copy(conn_info->bssid, bssid);
1397
1398        if (ies) {
1399                conn_info->req_ies_len = ies_len;
1400                conn_info->req_ies = kmemdup(ies, ies_len, GFP_KERNEL);
1401                if (!conn_info->req_ies)
1402                        return -ENOMEM;
1403        }
1404
1405        result = wilc_send_connect_wid(vif);
1406        if (result)
1407                goto free_ies;
1408
1409        hif_drv->connect_timer_vif = vif;
1410        mod_timer(&hif_drv->connect_timer,
1411                  jiffies + msecs_to_jiffies(WILC_HIF_CONNECT_TIMEOUT_MS));
1412
1413        return 0;
1414
1415free_ies:
1416        kfree(conn_info->req_ies);
1417
1418        return result;
1419}
1420
1421int wilc_set_mac_chnl_num(struct wilc_vif *vif, u8 channel)
1422{
1423        struct wid wid;
1424        int result;
1425
1426        wid.id = WID_CURRENT_CHANNEL;
1427        wid.type = WID_CHAR;
1428        wid.size = sizeof(char);
1429        wid.val = &channel;
1430
1431        result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
1432                                      wilc_get_vif_idx(vif));
1433        if (result)
1434                netdev_err(vif->ndev, "Failed to set channel\n");
1435
1436        return result;
1437}
1438
1439int wilc_set_wfi_drv_handler(struct wilc_vif *vif, int index, u8 mode,
1440                             u8 ifc_id)
1441{
1442        struct wid wid;
1443        struct host_if_drv *hif_drv = vif->hif_drv;
1444        int result;
1445        struct wilc_drv_handler drv;
1446
1447        if (!hif_drv)
1448                return -EFAULT;
1449
1450        wid.id = WID_SET_DRV_HANDLER;
1451        wid.type = WID_STR;
1452        wid.size = sizeof(drv);
1453        wid.val = (u8 *)&drv;
1454
1455        drv.handler = cpu_to_le32(index);
1456        drv.mode = (ifc_id | (mode << 1));
1457
1458        result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
1459                                      hif_drv->driver_handler_id);
1460        if (result)
1461                netdev_err(vif->ndev, "Failed to set driver handler\n");
1462
1463        return result;
1464}
1465
1466int wilc_set_operation_mode(struct wilc_vif *vif, u32 mode)
1467{
1468        struct wid wid;
1469        struct wilc_op_mode op_mode;
1470        int result;
1471
1472        wid.id = WID_SET_OPERATION_MODE;
1473        wid.type = WID_INT;
1474        wid.size = sizeof(op_mode);
1475        wid.val = (u8 *)&op_mode;
1476
1477        op_mode.mode = cpu_to_le32(mode);
1478
1479        result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
1480                                      wilc_get_vif_idx(vif));
1481        if (result)
1482                netdev_err(vif->ndev, "Failed to set operation mode\n");
1483
1484        return result;
1485}
1486
1487s32 wilc_get_inactive_time(struct wilc_vif *vif, const u8 *mac, u32 *out_val)
1488{
1489        struct wid wid;
1490        s32 result;
1491
1492        wid.id = WID_SET_STA_MAC_INACTIVE_TIME;
1493        wid.type = WID_STR;
1494        wid.size = ETH_ALEN;
1495        wid.val = kzalloc(wid.size, GFP_KERNEL);
1496        if (!wid.val)
1497                return -ENOMEM;
1498
1499        ether_addr_copy(wid.val, mac);
1500        result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
1501                                      wilc_get_vif_idx(vif));
1502        kfree(wid.val);
1503        if (result) {
1504                netdev_err(vif->ndev, "Failed to set inactive mac\n");
1505                return result;
1506        }
1507
1508        wid.id = WID_GET_INACTIVE_TIME;
1509        wid.type = WID_INT;
1510        wid.val = (s8 *)out_val;
1511        wid.size = sizeof(u32);
1512        result = wilc_send_config_pkt(vif, WILC_GET_CFG, &wid, 1,
1513                                      wilc_get_vif_idx(vif));
1514        if (result)
1515                netdev_err(vif->ndev, "Failed to get inactive time\n");
1516
1517        return result;
1518}
1519
1520int wilc_get_rssi(struct wilc_vif *vif, s8 *rssi_level)
1521{
1522        struct wid wid;
1523        int result;
1524
1525        if (!rssi_level) {
1526                netdev_err(vif->ndev, "%s: RSSI level is NULL\n", __func__);
1527                return -EFAULT;
1528        }
1529
1530        wid.id = WID_RSSI;
1531        wid.type = WID_CHAR;
1532        wid.size = sizeof(char);
1533        wid.val = rssi_level;
1534        result = wilc_send_config_pkt(vif, WILC_GET_CFG, &wid, 1,
1535                                      wilc_get_vif_idx(vif));
1536        if (result)
1537                netdev_err(vif->ndev, "Failed to get RSSI value\n");
1538
1539        return result;
1540}
1541
1542static int wilc_get_stats_async(struct wilc_vif *vif, struct rf_info *stats)
1543{
1544        int result;
1545        struct host_if_msg *msg;
1546
1547        msg = wilc_alloc_work(vif, handle_get_statistics, false);
1548        if (IS_ERR(msg))
1549                return PTR_ERR(msg);
1550
1551        msg->body.data = (char *)stats;
1552
1553        result = wilc_enqueue_work(msg);
1554        if (result) {
1555                netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__);
1556                kfree(msg);
1557                return result;
1558        }
1559
1560        return result;
1561}
1562
1563int wilc_hif_set_cfg(struct wilc_vif *vif, struct cfg_param_attr *param)
1564{
1565        struct wid wid_list[4];
1566        int i = 0;
1567
1568        if (param->flag & WILC_CFG_PARAM_RETRY_SHORT) {
1569                wid_list[i].id = WID_SHORT_RETRY_LIMIT;
1570                wid_list[i].val = (s8 *)&param->short_retry_limit;
1571                wid_list[i].type = WID_SHORT;
1572                wid_list[i].size = sizeof(u16);
1573                i++;
1574        }
1575        if (param->flag & WILC_CFG_PARAM_RETRY_LONG) {
1576                wid_list[i].id = WID_LONG_RETRY_LIMIT;
1577                wid_list[i].val = (s8 *)&param->long_retry_limit;
1578                wid_list[i].type = WID_SHORT;
1579                wid_list[i].size = sizeof(u16);
1580                i++;
1581        }
1582        if (param->flag & WILC_CFG_PARAM_FRAG_THRESHOLD) {
1583                wid_list[i].id = WID_FRAG_THRESHOLD;
1584                wid_list[i].val = (s8 *)&param->frag_threshold;
1585                wid_list[i].type = WID_SHORT;
1586                wid_list[i].size = sizeof(u16);
1587                i++;
1588        }
1589        if (param->flag & WILC_CFG_PARAM_RTS_THRESHOLD) {
1590                wid_list[i].id = WID_RTS_THRESHOLD;
1591                wid_list[i].val = (s8 *)&param->rts_threshold;
1592                wid_list[i].type = WID_SHORT;
1593                wid_list[i].size = sizeof(u16);
1594                i++;
1595        }
1596
1597        return wilc_send_config_pkt(vif, WILC_SET_CFG, wid_list,
1598                                    i, wilc_get_vif_idx(vif));
1599}
1600
1601static void get_periodic_rssi(struct timer_list *t)
1602{
1603        struct wilc_vif *vif = from_timer(vif, t, periodic_rssi);
1604
1605        if (!vif->hif_drv) {
1606                netdev_err(vif->ndev, "%s: hif driver is NULL", __func__);
1607                return;
1608        }
1609
1610        if (vif->hif_drv->hif_state == HOST_IF_CONNECTED)
1611                wilc_get_stats_async(vif, &vif->periodic_stat);
1612
1613        mod_timer(&vif->periodic_rssi, jiffies + msecs_to_jiffies(5000));
1614}
1615
1616int wilc_init(struct net_device *dev, struct host_if_drv **hif_drv_handler)
1617{
1618        struct host_if_drv *hif_drv;
1619        struct wilc_vif *vif = netdev_priv(dev);
1620        struct wilc *wilc = vif->wilc;
1621        int i;
1622
1623        hif_drv  = kzalloc(sizeof(*hif_drv), GFP_KERNEL);
1624        if (!hif_drv)
1625                return -ENOMEM;
1626
1627        *hif_drv_handler = hif_drv;
1628        for (i = 0; i < wilc->vif_num; i++)
1629                if (dev == wilc->vif[i]->ndev) {
1630                        wilc->vif[i]->hif_drv = hif_drv;
1631                        hif_drv->driver_handler_id = i + 1;
1632                        break;
1633                }
1634
1635        vif->obtaining_ip = false;
1636
1637        if (wilc->clients_count == 0)
1638                mutex_init(&wilc->deinit_lock);
1639
1640        timer_setup(&vif->periodic_rssi, get_periodic_rssi, 0);
1641        mod_timer(&vif->periodic_rssi, jiffies + msecs_to_jiffies(5000));
1642
1643        timer_setup(&hif_drv->scan_timer, timer_scan_cb, 0);
1644        timer_setup(&hif_drv->connect_timer, timer_connect_cb, 0);
1645        timer_setup(&hif_drv->remain_on_ch_timer, listen_timer_cb, 0);
1646
1647        hif_drv->hif_state = HOST_IF_IDLE;
1648
1649        hif_drv->p2p_timeout = 0;
1650
1651        wilc->clients_count++;
1652
1653        return 0;
1654}
1655
1656int wilc_deinit(struct wilc_vif *vif)
1657{
1658        int result = 0;
1659        struct host_if_drv *hif_drv = vif->hif_drv;
1660
1661        if (!hif_drv) {
1662                netdev_err(vif->ndev, "%s: hif driver is NULL", __func__);
1663                return -EFAULT;
1664        }
1665
1666        mutex_lock(&vif->wilc->deinit_lock);
1667
1668        del_timer_sync(&hif_drv->scan_timer);
1669        del_timer_sync(&hif_drv->connect_timer);
1670        del_timer_sync(&vif->periodic_rssi);
1671        del_timer_sync(&hif_drv->remain_on_ch_timer);
1672
1673        wilc_set_wfi_drv_handler(vif, 0, 0, 0);
1674
1675        if (hif_drv->usr_scan_req.scan_result) {
1676                hif_drv->usr_scan_req.scan_result(SCAN_EVENT_ABORTED, NULL,
1677                                                  hif_drv->usr_scan_req.arg);
1678                hif_drv->usr_scan_req.scan_result = NULL;
1679        }
1680
1681        hif_drv->hif_state = HOST_IF_IDLE;
1682
1683        kfree(hif_drv);
1684        vif->hif_drv = NULL;
1685        vif->wilc->clients_count--;
1686        mutex_unlock(&vif->wilc->deinit_lock);
1687        return result;
1688}
1689
1690void wilc_network_info_received(struct wilc *wilc, u8 *buffer, u32 length)
1691{
1692        int result;
1693        struct host_if_msg *msg;
1694        int id;
1695        struct host_if_drv *hif_drv;
1696        struct wilc_vif *vif;
1697
1698        id = get_unaligned_le32(&buffer[length - 4]);
1699        vif = wilc_get_vif_from_idx(wilc, id);
1700        if (!vif)
1701                return;
1702        hif_drv = vif->hif_drv;
1703
1704        if (!hif_drv) {
1705                netdev_err(vif->ndev, "driver not init[%p]\n", hif_drv);
1706                return;
1707        }
1708
1709        msg = wilc_alloc_work(vif, handle_rcvd_ntwrk_info, false);
1710        if (IS_ERR(msg))
1711                return;
1712
1713        msg->body.net_info.frame_len = get_unaligned_le16(&buffer[6]) - 1;
1714        msg->body.net_info.rssi = buffer[8];
1715        msg->body.net_info.mgmt = kmemdup(&buffer[9],
1716                                          msg->body.net_info.frame_len,
1717                                          GFP_KERNEL);
1718        if (!msg->body.net_info.mgmt) {
1719                kfree(msg);
1720                return;
1721        }
1722
1723        result = wilc_enqueue_work(msg);
1724        if (result) {
1725                netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__);
1726                kfree(msg->body.net_info.mgmt);
1727                kfree(msg);
1728        }
1729}
1730
1731void wilc_gnrl_async_info_received(struct wilc *wilc, u8 *buffer, u32 length)
1732{
1733        int result;
1734        struct host_if_msg *msg;
1735        int id;
1736        struct host_if_drv *hif_drv;
1737        struct wilc_vif *vif;
1738
1739        mutex_lock(&wilc->deinit_lock);
1740
1741        id = get_unaligned_le32(&buffer[length - 4]);
1742        vif = wilc_get_vif_from_idx(wilc, id);
1743        if (!vif) {
1744                mutex_unlock(&wilc->deinit_lock);
1745                return;
1746        }
1747
1748        hif_drv = vif->hif_drv;
1749
1750        if (!hif_drv) {
1751                mutex_unlock(&wilc->deinit_lock);
1752                return;
1753        }
1754
1755        if (!hif_drv->conn_info.conn_result) {
1756                netdev_err(vif->ndev, "%s: conn_result is NULL\n", __func__);
1757                mutex_unlock(&wilc->deinit_lock);
1758                return;
1759        }
1760
1761        msg = wilc_alloc_work(vif, handle_rcvd_gnrl_async_info, false);
1762        if (IS_ERR(msg)) {
1763                mutex_unlock(&wilc->deinit_lock);
1764                return;
1765        }
1766
1767        msg->body.mac_info.status = buffer[7];
1768        result = wilc_enqueue_work(msg);
1769        if (result) {
1770                netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__);
1771                kfree(msg);
1772        }
1773
1774        mutex_unlock(&wilc->deinit_lock);
1775}
1776
1777void wilc_scan_complete_received(struct wilc *wilc, u8 *buffer, u32 length)
1778{
1779        int result;
1780        int id;
1781        struct host_if_drv *hif_drv;
1782        struct wilc_vif *vif;
1783
1784        id = get_unaligned_le32(&buffer[length - 4]);
1785        vif = wilc_get_vif_from_idx(wilc, id);
1786        if (!vif)
1787                return;
1788        hif_drv = vif->hif_drv;
1789
1790        if (!hif_drv)
1791                return;
1792
1793        if (hif_drv->usr_scan_req.scan_result) {
1794                struct host_if_msg *msg;
1795
1796                msg = wilc_alloc_work(vif, handle_scan_complete, false);
1797                if (IS_ERR(msg))
1798                        return;
1799
1800                result = wilc_enqueue_work(msg);
1801                if (result) {
1802                        netdev_err(vif->ndev, "%s: enqueue work failed\n",
1803                                   __func__);
1804                        kfree(msg);
1805                }
1806        }
1807}
1808
1809int wilc_remain_on_channel(struct wilc_vif *vif, u64 cookie,
1810                           u32 duration, u16 chan,
1811                           void (*expired)(void *, u64),
1812                           void *user_arg)
1813{
1814        struct wilc_remain_ch roc;
1815        int result;
1816
1817        roc.ch = chan;
1818        roc.expired = expired;
1819        roc.arg = user_arg;
1820        roc.duration = duration;
1821        roc.cookie = cookie;
1822        result = handle_remain_on_chan(vif, &roc);
1823        if (result)
1824                netdev_err(vif->ndev, "%s: failed to set remain on channel\n",
1825                           __func__);
1826
1827        return result;
1828}
1829
1830int wilc_listen_state_expired(struct wilc_vif *vif, u64 cookie)
1831{
1832        int result;
1833        struct host_if_msg *msg;
1834        struct host_if_drv *hif_drv = vif->hif_drv;
1835
1836        if (!hif_drv) {
1837                netdev_err(vif->ndev, "%s: hif driver is NULL", __func__);
1838                return -EFAULT;
1839        }
1840
1841        del_timer(&hif_drv->remain_on_ch_timer);
1842
1843        msg = wilc_alloc_work(vif, handle_listen_state_expired, false);
1844        if (IS_ERR(msg))
1845                return PTR_ERR(msg);
1846
1847        msg->body.remain_on_ch.cookie = cookie;
1848
1849        result = wilc_enqueue_work(msg);
1850        if (result) {
1851                netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__);
1852                kfree(msg);
1853        }
1854
1855        return result;
1856}
1857
1858void wilc_frame_register(struct wilc_vif *vif, u16 frame_type, bool reg)
1859{
1860        struct wid wid;
1861        int result;
1862        struct wilc_reg_frame reg_frame;
1863
1864        wid.id = WID_REGISTER_FRAME;
1865        wid.type = WID_STR;
1866        wid.size = sizeof(reg_frame);
1867        wid.val = (u8 *)&reg_frame;
1868
1869        memset(&reg_frame, 0x0, sizeof(reg_frame));
1870        reg_frame.reg = reg;
1871
1872        switch (frame_type) {
1873        case IEEE80211_STYPE_ACTION:
1874                reg_frame.reg_id = WILC_FW_ACTION_FRM_IDX;
1875                break;
1876
1877        case IEEE80211_STYPE_PROBE_REQ:
1878                reg_frame.reg_id = WILC_FW_PROBE_REQ_IDX;
1879                break;
1880
1881        default:
1882                break;
1883        }
1884        reg_frame.frame_type = cpu_to_le16(frame_type);
1885        result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
1886                                      wilc_get_vif_idx(vif));
1887        if (result)
1888                netdev_err(vif->ndev, "Failed to frame register\n");
1889}
1890
1891int wilc_add_beacon(struct wilc_vif *vif, u32 interval, u32 dtim_period,
1892                    struct cfg80211_beacon_data *params)
1893{
1894        struct wid wid;
1895        int result;
1896        u8 *cur_byte;
1897
1898        wid.id = WID_ADD_BEACON;
1899        wid.type = WID_BIN;
1900        wid.size = params->head_len + params->tail_len + 16;
1901        wid.val = kzalloc(wid.size, GFP_KERNEL);
1902        if (!wid.val)
1903                return -ENOMEM;
1904
1905        cur_byte = wid.val;
1906        put_unaligned_le32(interval, cur_byte);
1907        cur_byte += 4;
1908        put_unaligned_le32(dtim_period, cur_byte);
1909        cur_byte += 4;
1910        put_unaligned_le32(params->head_len, cur_byte);
1911        cur_byte += 4;
1912
1913        if (params->head_len > 0)
1914                memcpy(cur_byte, params->head, params->head_len);
1915        cur_byte += params->head_len;
1916
1917        put_unaligned_le32(params->tail_len, cur_byte);
1918        cur_byte += 4;
1919
1920        if (params->tail_len > 0)
1921                memcpy(cur_byte, params->tail, params->tail_len);
1922
1923        result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
1924                                      wilc_get_vif_idx(vif));
1925        if (result)
1926                netdev_err(vif->ndev, "Failed to send add beacon\n");
1927
1928        kfree(wid.val);
1929
1930        return result;
1931}
1932
1933int wilc_del_beacon(struct wilc_vif *vif)
1934{
1935        int result;
1936        struct wid wid;
1937        u8 del_beacon = 0;
1938
1939        wid.id = WID_DEL_BEACON;
1940        wid.type = WID_CHAR;
1941        wid.size = sizeof(char);
1942        wid.val = &del_beacon;
1943
1944        result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
1945                                      wilc_get_vif_idx(vif));
1946        if (result)
1947                netdev_err(vif->ndev, "Failed to send delete beacon\n");
1948
1949        return result;
1950}
1951
1952int wilc_add_station(struct wilc_vif *vif, const u8 *mac,
1953                     struct station_parameters *params)
1954{
1955        struct wid wid;
1956        int result;
1957        u8 *cur_byte;
1958
1959        wid.id = WID_ADD_STA;
1960        wid.type = WID_BIN;
1961        wid.size = WILC_ADD_STA_LENGTH + params->supported_rates_len;
1962        wid.val = kmalloc(wid.size, GFP_KERNEL);
1963        if (!wid.val)
1964                return -ENOMEM;
1965
1966        cur_byte = wid.val;
1967        wilc_hif_pack_sta_param(cur_byte, mac, params);
1968
1969        result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
1970                                      wilc_get_vif_idx(vif));
1971        if (result != 0)
1972                netdev_err(vif->ndev, "Failed to send add station\n");
1973
1974        kfree(wid.val);
1975
1976        return result;
1977}
1978
1979int wilc_del_station(struct wilc_vif *vif, const u8 *mac_addr)
1980{
1981        struct wid wid;
1982        int result;
1983
1984        wid.id = WID_REMOVE_STA;
1985        wid.type = WID_BIN;
1986        wid.size = ETH_ALEN;
1987        wid.val = kzalloc(wid.size, GFP_KERNEL);
1988        if (!wid.val)
1989                return -ENOMEM;
1990
1991        if (!mac_addr)
1992                eth_broadcast_addr(wid.val);
1993        else
1994                ether_addr_copy(wid.val, mac_addr);
1995
1996        result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
1997                                      wilc_get_vif_idx(vif));
1998        if (result)
1999                netdev_err(vif->ndev, "Failed to del station\n");
2000
2001        kfree(wid.val);
2002
2003        return result;
2004}
2005
2006int wilc_del_allstation(struct wilc_vif *vif, u8 mac_addr[][ETH_ALEN])
2007{
2008        struct wid wid;
2009        int result;
2010        int i;
2011        u8 assoc_sta = 0;
2012        struct wilc_del_all_sta del_sta;
2013
2014        memset(&del_sta, 0x0, sizeof(del_sta));
2015        for (i = 0; i < WILC_MAX_NUM_STA; i++) {
2016                if (!is_zero_ether_addr(mac_addr[i])) {
2017                        assoc_sta++;
2018                        ether_addr_copy(del_sta.mac[i], mac_addr[i]);
2019                }
2020        }
2021
2022        if (!assoc_sta)
2023                return 0;
2024
2025        del_sta.assoc_sta = assoc_sta;
2026
2027        wid.id = WID_DEL_ALL_STA;
2028        wid.type = WID_STR;
2029        wid.size = (assoc_sta * ETH_ALEN) + 1;
2030        wid.val = (u8 *)&del_sta;
2031
2032        result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
2033                                      wilc_get_vif_idx(vif));
2034        if (result)
2035                netdev_err(vif->ndev, "Failed to send delete all station\n");
2036
2037        return result;
2038}
2039
2040int wilc_edit_station(struct wilc_vif *vif, const u8 *mac,
2041                      struct station_parameters *params)
2042{
2043        struct wid wid;
2044        int result;
2045        u8 *cur_byte;
2046
2047        wid.id = WID_EDIT_STA;
2048        wid.type = WID_BIN;
2049        wid.size = WILC_ADD_STA_LENGTH + params->supported_rates_len;
2050        wid.val = kmalloc(wid.size, GFP_KERNEL);
2051        if (!wid.val)
2052                return -ENOMEM;
2053
2054        cur_byte = wid.val;
2055        wilc_hif_pack_sta_param(cur_byte, mac, params);
2056
2057        result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
2058                                      wilc_get_vif_idx(vif));
2059        if (result)
2060                netdev_err(vif->ndev, "Failed to send edit station\n");
2061
2062        kfree(wid.val);
2063        return result;
2064}
2065
2066int wilc_set_power_mgmt(struct wilc_vif *vif, bool enabled, u32 timeout)
2067{
2068        struct wid wid;
2069        int result;
2070        s8 power_mode;
2071
2072        if (wilc_wlan_get_num_conn_ifcs(vif->wilc) == 2 && enabled)
2073                return 0;
2074
2075        if (enabled)
2076                power_mode = WILC_FW_MIN_FAST_PS;
2077        else
2078                power_mode = WILC_FW_NO_POWERSAVE;
2079
2080        wid.id = WID_POWER_MANAGEMENT;
2081        wid.val = &power_mode;
2082        wid.size = sizeof(char);
2083        result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
2084                                      wilc_get_vif_idx(vif));
2085        if (result)
2086                netdev_err(vif->ndev, "Failed to send power management\n");
2087
2088        return result;
2089}
2090
2091int wilc_setup_multicast_filter(struct wilc_vif *vif, u32 enabled, u32 count,
2092                                u8 *mc_list)
2093{
2094        int result;
2095        struct host_if_msg *msg;
2096
2097        msg = wilc_alloc_work(vif, handle_set_mcast_filter, false);
2098        if (IS_ERR(msg))
2099                return PTR_ERR(msg);
2100
2101        msg->body.mc_info.enabled = enabled;
2102        msg->body.mc_info.cnt = count;
2103        msg->body.mc_info.mc_list = mc_list;
2104
2105        result = wilc_enqueue_work(msg);
2106        if (result) {
2107                netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__);
2108                kfree(msg);
2109        }
2110        return result;
2111}
2112
2113int wilc_set_tx_power(struct wilc_vif *vif, u8 tx_power)
2114{
2115        struct wid wid;
2116
2117        wid.id = WID_TX_POWER;
2118        wid.type = WID_CHAR;
2119        wid.val = &tx_power;
2120        wid.size = sizeof(char);
2121
2122        return wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
2123                                   wilc_get_vif_idx(vif));
2124}
2125
2126int wilc_get_tx_power(struct wilc_vif *vif, u8 *tx_power)
2127{
2128        struct wid wid;
2129
2130        wid.id = WID_TX_POWER;
2131        wid.type = WID_CHAR;
2132        wid.val = tx_power;
2133        wid.size = sizeof(char);
2134
2135        return wilc_send_config_pkt(vif, WILC_GET_CFG, &wid, 1,
2136                                    wilc_get_vif_idx(vif));
2137}
2138