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 HOST_IF_SCAN_TIMEOUT                    4000
  10#define HOST_IF_CONNECT_TIMEOUT                 9500
  11
  12#define FALSE_FRMWR_CHANNEL                     100
  13
  14#define REAL_JOIN_REQ                           0
  15
  16struct host_if_wpa_attr {
  17        u8 *key;
  18        const u8 *mac_addr;
  19        u8 *seq;
  20        u8 seq_len;
  21        u8 index;
  22        u8 key_len;
  23        u8 mode;
  24};
  25
  26struct host_if_wep_attr {
  27        u8 *key;
  28        u8 key_len;
  29        u8 index;
  30        u8 mode;
  31        enum authtype auth_type;
  32};
  33
  34union host_if_key_attr {
  35        struct host_if_wep_attr wep;
  36        struct host_if_wpa_attr wpa;
  37        struct host_if_pmkid_attr pmkid;
  38};
  39
  40struct key_attr {
  41        enum KEY_TYPE type;
  42        u8 action;
  43        union host_if_key_attr attr;
  44};
  45
  46struct scan_attr {
  47        u8 src;
  48        u8 type;
  49        u8 *ch_freq_list;
  50        u8 ch_list_len;
  51        u8 *ies;
  52        size_t ies_len;
  53        wilc_scan_result result;
  54        void *arg;
  55        struct hidden_network hidden_network;
  56};
  57
  58struct connect_attr {
  59        u8 *bssid;
  60        u8 *ssid;
  61        size_t ssid_len;
  62        u8 *ies;
  63        size_t ies_len;
  64        u8 security;
  65        wilc_connect_result result;
  66        void *arg;
  67        enum authtype auth_type;
  68        u8 ch;
  69        void *params;
  70};
  71
  72struct rcvd_async_info {
  73        u8 *buffer;
  74        u32 len;
  75};
  76
  77struct channel_attr {
  78        u8 set_ch;
  79};
  80
  81struct beacon_attr {
  82        u32 interval;
  83        u32 dtim_period;
  84        u32 head_len;
  85        u8 *head;
  86        u32 tail_len;
  87        u8 *tail;
  88};
  89
  90struct set_multicast {
  91        bool enabled;
  92        u32 cnt;
  93};
  94
  95struct del_all_sta {
  96        u8 del_all_sta[MAX_NUM_STA][ETH_ALEN];
  97        u8 assoc_sta;
  98};
  99
 100struct del_sta {
 101        u8 mac_addr[ETH_ALEN];
 102};
 103
 104struct power_mgmt_param {
 105        bool enabled;
 106        u32 timeout;
 107};
 108
 109struct set_ip_addr {
 110        u8 *ip_addr;
 111        u8 idx;
 112};
 113
 114struct sta_inactive_t {
 115        u32 inactive_time;
 116        u8 mac[6];
 117};
 118
 119struct tx_power {
 120        u8 tx_pwr;
 121};
 122
 123union message_body {
 124        struct scan_attr scan_info;
 125        struct connect_attr con_info;
 126        struct rcvd_net_info net_info;
 127        struct rcvd_async_info async_info;
 128        struct key_attr key_info;
 129        struct cfg_param_attr cfg_info;
 130        struct channel_attr channel_info;
 131        struct beacon_attr beacon_info;
 132        struct add_sta_param add_sta_info;
 133        struct del_sta del_sta_info;
 134        struct add_sta_param edit_sta_info;
 135        struct power_mgmt_param pwr_mgmt_info;
 136        struct sta_inactive_t mac_info;
 137        struct set_ip_addr ip_info;
 138        struct drv_handler drv;
 139        struct set_multicast multicast_info;
 140        struct op_mode mode;
 141        struct get_mac_addr get_mac_info;
 142        struct ba_session_info session_info;
 143        struct remain_ch remain_on_ch;
 144        struct reg_frame reg_frame;
 145        char *data;
 146        struct del_all_sta del_all_sta_info;
 147        struct tx_power tx_power;
 148};
 149
 150struct host_if_msg {
 151        union message_body body;
 152        struct wilc_vif *vif;
 153        struct work_struct work;
 154        void (*fn)(struct work_struct *ws);
 155        struct completion work_comp;
 156        bool is_sync;
 157};
 158
 159struct join_bss_param {
 160        enum bss_types bss_type;
 161        u8 dtim_period;
 162        u16 beacon_period;
 163        u16 cap_info;
 164        u8 bssid[6];
 165        char ssid[MAX_SSID_LEN];
 166        u8 ssid_len;
 167        u8 supp_rates[MAX_RATES_SUPPORTED + 1];
 168        u8 ht_capable;
 169        u8 wmm_cap;
 170        u8 uapsd_cap;
 171        bool rsn_found;
 172        u8 rsn_grp_policy;
 173        u8 mode_802_11i;
 174        u8 rsn_pcip_policy[3];
 175        u8 rsn_auth_policy[3];
 176        u8 rsn_cap[2];
 177        u32 tsf;
 178        u8 noa_enabled;
 179        u8 opp_enabled;
 180        u8 ct_window;
 181        u8 cnt;
 182        u8 idx;
 183        u8 duration[4];
 184        u8 interval[4];
 185        u8 start_time[4];
 186};
 187
 188static struct host_if_drv *terminated_handle;
 189bool wilc_optaining_ip;
 190static u8 p2p_listen_state;
 191static struct workqueue_struct *hif_workqueue;
 192static struct completion hif_driver_comp;
 193static struct mutex hif_deinit_lock;
 194static struct timer_list periodic_rssi;
 195static struct wilc_vif *periodic_rssi_vif;
 196
 197u8 wilc_multicast_mac_addr_list[WILC_MULTICAST_TABLE_SIZE][ETH_ALEN];
 198
 199static u8 rcv_assoc_resp[MAX_ASSOC_RESP_FRAME_SIZE];
 200
 201static u8 set_ip[2][4];
 202static u8 get_ip[2][4];
 203static u32 clients_count;
 204
 205static int host_int_get_ipaddress(struct wilc_vif *vif, u8 *ip_addr, u8 idx);
 206
 207/* 'msg' should be free by the caller for syc */
 208static struct host_if_msg*
 209wilc_alloc_work(struct wilc_vif *vif, void (*work_fun)(struct work_struct *),
 210                bool is_sync)
 211{
 212        struct host_if_msg *msg;
 213
 214        if (!work_fun)
 215                return ERR_PTR(-EINVAL);
 216
 217        msg = kzalloc(sizeof(*msg), GFP_ATOMIC);
 218        if (!msg)
 219                return ERR_PTR(-ENOMEM);
 220        msg->fn = work_fun;
 221        msg->vif = vif;
 222        msg->is_sync = is_sync;
 223        if (is_sync)
 224                init_completion(&msg->work_comp);
 225
 226        return msg;
 227}
 228
 229static int wilc_enqueue_work(struct host_if_msg *msg)
 230{
 231        INIT_WORK(&msg->work, msg->fn);
 232        if (!hif_workqueue || !queue_work(hif_workqueue, &msg->work))
 233                return -EINVAL;
 234
 235        return 0;
 236}
 237
 238/* The idx starts from 0 to (NUM_CONCURRENT_IFC - 1), but 0 index used as
 239 * special purpose in wilc device, so we add 1 to the index to starts from 1.
 240 * As a result, the returned index will be 1 to NUM_CONCURRENT_IFC.
 241 */
 242int wilc_get_vif_idx(struct wilc_vif *vif)
 243{
 244        return vif->idx + 1;
 245}
 246
 247/* We need to minus 1 from idx which is from wilc device to get real index
 248 * of wilc->vif[], because we add 1 when pass to wilc device in the function
 249 * wilc_get_vif_idx.
 250 * As a result, the index should be between 0 and (NUM_CONCURRENT_IFC - 1).
 251 */
 252static struct wilc_vif *wilc_get_vif_from_idx(struct wilc *wilc, int idx)
 253{
 254        int index = idx - 1;
 255
 256        if (index < 0 || index >= NUM_CONCURRENT_IFC)
 257                return NULL;
 258
 259        return wilc->vif[index];
 260}
 261
 262static void handle_set_channel(struct work_struct *work)
 263{
 264        struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
 265        struct wilc_vif *vif = msg->vif;
 266        struct channel_attr *hif_set_ch = &msg->body.channel_info;
 267        int ret;
 268        struct wid wid;
 269
 270        wid.id = WID_CURRENT_CHANNEL;
 271        wid.type = WID_CHAR;
 272        wid.val = (char *)&hif_set_ch->set_ch;
 273        wid.size = sizeof(char);
 274
 275        ret = wilc_send_config_pkt(vif, SET_CFG, &wid, 1,
 276                                   wilc_get_vif_idx(vif));
 277
 278        if (ret)
 279                netdev_err(vif->ndev, "Failed to set channel\n");
 280        kfree(msg);
 281}
 282
 283static void handle_set_wfi_drv_handler(struct work_struct *work)
 284{
 285        struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
 286        struct wilc_vif *vif = msg->vif;
 287        struct drv_handler *hif_drv_handler = &msg->body.drv;
 288        int ret;
 289        struct wid wid;
 290        u8 *currbyte, *buffer;
 291        struct host_if_drv *hif_drv;
 292
 293        if (!vif->hif_drv || !hif_drv_handler)
 294                goto free_msg;
 295
 296        hif_drv = vif->hif_drv;
 297
 298        buffer = kzalloc(DRV_HANDLER_SIZE, GFP_KERNEL);
 299        if (!buffer)
 300                goto free_msg;
 301
 302        currbyte = buffer;
 303        *currbyte = hif_drv->driver_handler_id & DRV_HANDLER_MASK;
 304        currbyte++;
 305        *currbyte = (u32)0 & DRV_HANDLER_MASK;
 306        currbyte++;
 307        *currbyte = (u32)0 & DRV_HANDLER_MASK;
 308        currbyte++;
 309        *currbyte = (u32)0 & DRV_HANDLER_MASK;
 310        currbyte++;
 311        *currbyte = (hif_drv_handler->name | (hif_drv_handler->mode << 1));
 312
 313        wid.id = WID_SET_DRV_HANDLER;
 314        wid.type = WID_STR;
 315        wid.val = (s8 *)buffer;
 316        wid.size = DRV_HANDLER_SIZE;
 317
 318        ret = wilc_send_config_pkt(vif, SET_CFG, &wid, 1,
 319                                   hif_drv->driver_handler_id);
 320        if (ret)
 321                netdev_err(vif->ndev, "Failed to set driver handler\n");
 322
 323        complete(&hif_driver_comp);
 324        kfree(buffer);
 325
 326free_msg:
 327        kfree(msg);
 328}
 329
 330static void handle_set_operation_mode(struct work_struct *work)
 331{
 332        struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
 333        struct wilc_vif *vif = msg->vif;
 334        struct op_mode *hif_op_mode = &msg->body.mode;
 335        int ret;
 336        struct wid wid;
 337
 338        wid.id = WID_SET_OPERATION_MODE;
 339        wid.type = WID_INT;
 340        wid.val = (s8 *)&hif_op_mode->mode;
 341        wid.size = sizeof(u32);
 342
 343        ret = wilc_send_config_pkt(vif, SET_CFG, &wid, 1,
 344                                   wilc_get_vif_idx(vif));
 345
 346        if (hif_op_mode->mode == IDLE_MODE)
 347                complete(&hif_driver_comp);
 348
 349        if (ret)
 350                netdev_err(vif->ndev, "Failed to set operation mode\n");
 351
 352        kfree(msg);
 353}
 354
 355static void handle_set_ip_address(struct work_struct *work)
 356{
 357        struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
 358        struct wilc_vif *vif = msg->vif;
 359        u8 *ip_addr = msg->body.ip_info.ip_addr;
 360        u8 idx = msg->body.ip_info.idx;
 361        int ret;
 362        struct wid wid;
 363        char firmware_ip_addr[4] = {0};
 364
 365        if (ip_addr[0] < 192)
 366                ip_addr[0] = 0;
 367
 368        memcpy(set_ip[idx], ip_addr, IP_ALEN);
 369
 370        wid.id = WID_IP_ADDRESS;
 371        wid.type = WID_STR;
 372        wid.val = ip_addr;
 373        wid.size = IP_ALEN;
 374
 375        ret = wilc_send_config_pkt(vif, SET_CFG, &wid, 1,
 376                                   wilc_get_vif_idx(vif));
 377
 378        host_int_get_ipaddress(vif, firmware_ip_addr, idx);
 379
 380        if (ret)
 381                netdev_err(vif->ndev, "Failed to set IP address\n");
 382        kfree(msg);
 383}
 384
 385static void handle_get_ip_address(struct work_struct *work)
 386{
 387        struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
 388        struct wilc_vif *vif = msg->vif;
 389        u8 idx = msg->body.ip_info.idx;
 390        int ret;
 391        struct wid wid;
 392
 393        wid.id = WID_IP_ADDRESS;
 394        wid.type = WID_STR;
 395        wid.val = kmalloc(IP_ALEN, GFP_KERNEL);
 396        wid.size = IP_ALEN;
 397
 398        ret = wilc_send_config_pkt(vif, GET_CFG, &wid, 1,
 399                                   wilc_get_vif_idx(vif));
 400
 401        memcpy(get_ip[idx], wid.val, IP_ALEN);
 402
 403        kfree(wid.val);
 404
 405        if (memcmp(get_ip[idx], set_ip[idx], IP_ALEN) != 0)
 406                wilc_setup_ipaddress(vif, set_ip[idx], idx);
 407
 408        if (ret)
 409                netdev_err(vif->ndev, "Failed to get IP address\n");
 410        kfree(msg);
 411}
 412
 413static void handle_get_mac_address(struct work_struct *work)
 414{
 415        struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
 416        struct wilc_vif *vif = msg->vif;
 417        struct get_mac_addr *get_mac_addr = &msg->body.get_mac_info;
 418        int ret;
 419        struct wid wid;
 420
 421        wid.id = WID_MAC_ADDR;
 422        wid.type = WID_STR;
 423        wid.val = get_mac_addr->mac_addr;
 424        wid.size = ETH_ALEN;
 425
 426        ret = wilc_send_config_pkt(vif, GET_CFG, &wid, 1,
 427                                   wilc_get_vif_idx(vif));
 428
 429        if (ret)
 430                netdev_err(vif->ndev, "Failed to get mac address\n");
 431        complete(&msg->work_comp);
 432        /* free 'msg' data later, in caller */
 433}
 434
 435static void handle_cfg_param(struct work_struct *work)
 436{
 437        struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
 438        struct wilc_vif *vif = msg->vif;
 439        struct cfg_param_attr *param = &msg->body.cfg_info;
 440        int ret;
 441        struct wid wid_list[32];
 442        struct host_if_drv *hif_drv = vif->hif_drv;
 443        int i = 0;
 444
 445        mutex_lock(&hif_drv->cfg_values_lock);
 446
 447        if (param->flag & BSS_TYPE) {
 448                u8 bss_type = param->bss_type;
 449
 450                if (bss_type < 6) {
 451                        wid_list[i].id = WID_BSS_TYPE;
 452                        wid_list[i].val = (s8 *)&param->bss_type;
 453                        wid_list[i].type = WID_CHAR;
 454                        wid_list[i].size = sizeof(char);
 455                        hif_drv->cfg_values.bss_type = bss_type;
 456                } else {
 457                        netdev_err(vif->ndev, "check value 6 over\n");
 458                        goto unlock;
 459                }
 460                i++;
 461        }
 462        if (param->flag & AUTH_TYPE) {
 463                u8 auth_type = param->auth_type;
 464
 465                if (auth_type == 1 || auth_type == 2 || auth_type == 5) {
 466                        wid_list[i].id = WID_AUTH_TYPE;
 467                        wid_list[i].val = (s8 *)&param->auth_type;
 468                        wid_list[i].type = WID_CHAR;
 469                        wid_list[i].size = sizeof(char);
 470                        hif_drv->cfg_values.auth_type = auth_type;
 471                } else {
 472                        netdev_err(vif->ndev, "Impossible value\n");
 473                        goto unlock;
 474                }
 475                i++;
 476        }
 477        if (param->flag & AUTHEN_TIMEOUT) {
 478                if (param->auth_timeout > 0) {
 479                        wid_list[i].id = WID_AUTH_TIMEOUT;
 480                        wid_list[i].val = (s8 *)&param->auth_timeout;
 481                        wid_list[i].type = WID_SHORT;
 482                        wid_list[i].size = sizeof(u16);
 483                        hif_drv->cfg_values.auth_timeout = param->auth_timeout;
 484                } else {
 485                        netdev_err(vif->ndev, "Range(1 ~ 65535) over\n");
 486                        goto unlock;
 487                }
 488                i++;
 489        }
 490        if (param->flag & POWER_MANAGEMENT) {
 491                u8 pm_mode = param->power_mgmt_mode;
 492
 493                if (pm_mode < 5) {
 494                        wid_list[i].id = WID_POWER_MANAGEMENT;
 495                        wid_list[i].val = (s8 *)&param->power_mgmt_mode;
 496                        wid_list[i].type = WID_CHAR;
 497                        wid_list[i].size = sizeof(char);
 498                        hif_drv->cfg_values.power_mgmt_mode = pm_mode;
 499                } else {
 500                        netdev_err(vif->ndev, "Invalid power mode\n");
 501                        goto unlock;
 502                }
 503                i++;
 504        }
 505        if (param->flag & RETRY_SHORT) {
 506                u16 retry_limit = param->short_retry_limit;
 507
 508                if (retry_limit > 0 && retry_limit < 256) {
 509                        wid_list[i].id = WID_SHORT_RETRY_LIMIT;
 510                        wid_list[i].val = (s8 *)&param->short_retry_limit;
 511                        wid_list[i].type = WID_SHORT;
 512                        wid_list[i].size = sizeof(u16);
 513                        hif_drv->cfg_values.short_retry_limit = retry_limit;
 514                } else {
 515                        netdev_err(vif->ndev, "Range(1~256) over\n");
 516                        goto unlock;
 517                }
 518                i++;
 519        }
 520        if (param->flag & RETRY_LONG) {
 521                u16 limit = param->long_retry_limit;
 522
 523                if (limit > 0 && limit < 256) {
 524                        wid_list[i].id = WID_LONG_RETRY_LIMIT;
 525                        wid_list[i].val = (s8 *)&param->long_retry_limit;
 526                        wid_list[i].type = WID_SHORT;
 527                        wid_list[i].size = sizeof(u16);
 528                        hif_drv->cfg_values.long_retry_limit = limit;
 529                } else {
 530                        netdev_err(vif->ndev, "Range(1~256) over\n");
 531                        goto unlock;
 532                }
 533                i++;
 534        }
 535        if (param->flag & FRAG_THRESHOLD) {
 536                u16 frag_th = param->frag_threshold;
 537
 538                if (frag_th > 255 && frag_th < 7937) {
 539                        wid_list[i].id = WID_FRAG_THRESHOLD;
 540                        wid_list[i].val = (s8 *)&param->frag_threshold;
 541                        wid_list[i].type = WID_SHORT;
 542                        wid_list[i].size = sizeof(u16);
 543                        hif_drv->cfg_values.frag_threshold = frag_th;
 544                } else {
 545                        netdev_err(vif->ndev, "Threshold Range fail\n");
 546                        goto unlock;
 547                }
 548                i++;
 549        }
 550        if (param->flag & RTS_THRESHOLD) {
 551                u16 rts_th = param->rts_threshold;
 552
 553                if (rts_th > 255) {
 554                        wid_list[i].id = WID_RTS_THRESHOLD;
 555                        wid_list[i].val = (s8 *)&param->rts_threshold;
 556                        wid_list[i].type = WID_SHORT;
 557                        wid_list[i].size = sizeof(u16);
 558                        hif_drv->cfg_values.rts_threshold = rts_th;
 559                } else {
 560                        netdev_err(vif->ndev, "Threshold Range fail\n");
 561                        goto unlock;
 562                }
 563                i++;
 564        }
 565        if (param->flag & PREAMBLE) {
 566                u16 preamble_type = param->preamble_type;
 567
 568                if (param->preamble_type < 3) {
 569                        wid_list[i].id = WID_PREAMBLE;
 570                        wid_list[i].val = (s8 *)&param->preamble_type;
 571                        wid_list[i].type = WID_CHAR;
 572                        wid_list[i].size = sizeof(char);
 573                        hif_drv->cfg_values.preamble_type = preamble_type;
 574                } else {
 575                        netdev_err(vif->ndev, "Preamble Range(0~2) over\n");
 576                        goto unlock;
 577                }
 578                i++;
 579        }
 580        if (param->flag & SHORT_SLOT_ALLOWED) {
 581                u8 slot_allowed = param->short_slot_allowed;
 582
 583                if (slot_allowed < 2) {
 584                        wid_list[i].id = WID_SHORT_SLOT_ALLOWED;
 585                        wid_list[i].val = (s8 *)&param->short_slot_allowed;
 586                        wid_list[i].type = WID_CHAR;
 587                        wid_list[i].size = sizeof(char);
 588                        hif_drv->cfg_values.short_slot_allowed = slot_allowed;
 589                } else {
 590                        netdev_err(vif->ndev, "Short slot(2) over\n");
 591                        goto unlock;
 592                }
 593                i++;
 594        }
 595        if (param->flag & TXOP_PROT_DISABLE) {
 596                u8 prot_disabled = param->txop_prot_disabled;
 597
 598                if (param->txop_prot_disabled < 2) {
 599                        wid_list[i].id = WID_11N_TXOP_PROT_DISABLE;
 600                        wid_list[i].val = (s8 *)&param->txop_prot_disabled;
 601                        wid_list[i].type = WID_CHAR;
 602                        wid_list[i].size = sizeof(char);
 603                        hif_drv->cfg_values.txop_prot_disabled = prot_disabled;
 604                } else {
 605                        netdev_err(vif->ndev, "TXOP prot disable\n");
 606                        goto unlock;
 607                }
 608                i++;
 609        }
 610        if (param->flag & BEACON_INTERVAL) {
 611                u16 beacon_interval = param->beacon_interval;
 612
 613                if (beacon_interval > 0) {
 614                        wid_list[i].id = WID_BEACON_INTERVAL;
 615                        wid_list[i].val = (s8 *)&param->beacon_interval;
 616                        wid_list[i].type = WID_SHORT;
 617                        wid_list[i].size = sizeof(u16);
 618                        hif_drv->cfg_values.beacon_interval = beacon_interval;
 619                } else {
 620                        netdev_err(vif->ndev, "Beacon interval(1~65535)fail\n");
 621                        goto unlock;
 622                }
 623                i++;
 624        }
 625        if (param->flag & DTIM_PERIOD) {
 626                if (param->dtim_period > 0 && param->dtim_period < 256) {
 627                        wid_list[i].id = WID_DTIM_PERIOD;
 628                        wid_list[i].val = (s8 *)&param->dtim_period;
 629                        wid_list[i].type = WID_CHAR;
 630                        wid_list[i].size = sizeof(char);
 631                        hif_drv->cfg_values.dtim_period = param->dtim_period;
 632                } else {
 633                        netdev_err(vif->ndev, "DTIM range(1~255) fail\n");
 634                        goto unlock;
 635                }
 636                i++;
 637        }
 638        if (param->flag & SITE_SURVEY) {
 639                enum site_survey enabled = param->site_survey_enabled;
 640
 641                if (enabled < 3) {
 642                        wid_list[i].id = WID_SITE_SURVEY;
 643                        wid_list[i].val = (s8 *)&param->site_survey_enabled;
 644                        wid_list[i].type = WID_CHAR;
 645                        wid_list[i].size = sizeof(char);
 646                        hif_drv->cfg_values.site_survey_enabled = enabled;
 647                } else {
 648                        netdev_err(vif->ndev, "Site survey disable\n");
 649                        goto unlock;
 650                }
 651                i++;
 652        }
 653        if (param->flag & SITE_SURVEY_SCAN_TIME) {
 654                u16 scan_time = param->site_survey_scan_time;
 655
 656                if (scan_time > 0) {
 657                        wid_list[i].id = WID_SITE_SURVEY_SCAN_TIME;
 658                        wid_list[i].val = (s8 *)&param->site_survey_scan_time;
 659                        wid_list[i].type = WID_SHORT;
 660                        wid_list[i].size = sizeof(u16);
 661                        hif_drv->cfg_values.site_survey_scan_time = scan_time;
 662                } else {
 663                        netdev_err(vif->ndev, "Site scan time(1~65535) over\n");
 664                        goto unlock;
 665                }
 666                i++;
 667        }
 668        if (param->flag & ACTIVE_SCANTIME) {
 669                u16 active_scan_time = param->active_scan_time;
 670
 671                if (active_scan_time > 0) {
 672                        wid_list[i].id = WID_ACTIVE_SCAN_TIME;
 673                        wid_list[i].val = (s8 *)&param->active_scan_time;
 674                        wid_list[i].type = WID_SHORT;
 675                        wid_list[i].size = sizeof(u16);
 676                        hif_drv->cfg_values.active_scan_time = active_scan_time;
 677                } else {
 678                        netdev_err(vif->ndev, "Active time(1~65535) over\n");
 679                        goto unlock;
 680                }
 681                i++;
 682        }
 683        if (param->flag & PASSIVE_SCANTIME) {
 684                u16 time = param->passive_scan_time;
 685
 686                if (time > 0) {
 687                        wid_list[i].id = WID_PASSIVE_SCAN_TIME;
 688                        wid_list[i].val = (s8 *)&param->passive_scan_time;
 689                        wid_list[i].type = WID_SHORT;
 690                        wid_list[i].size = sizeof(u16);
 691                        hif_drv->cfg_values.passive_scan_time = time;
 692                } else {
 693                        netdev_err(vif->ndev, "Passive time(1~65535) over\n");
 694                        goto unlock;
 695                }
 696                i++;
 697        }
 698        if (param->flag & CURRENT_TX_RATE) {
 699                enum current_tx_rate curr_tx_rate = param->curr_tx_rate;
 700
 701                if (curr_tx_rate == AUTORATE || curr_tx_rate == MBPS_1 ||
 702                    curr_tx_rate == MBPS_2 || curr_tx_rate == MBPS_5_5 ||
 703                    curr_tx_rate == MBPS_11 || curr_tx_rate == MBPS_6 ||
 704                    curr_tx_rate == MBPS_9 || curr_tx_rate == MBPS_12 ||
 705                    curr_tx_rate == MBPS_18 || curr_tx_rate == MBPS_24 ||
 706                    curr_tx_rate == MBPS_36 || curr_tx_rate == MBPS_48 ||
 707                    curr_tx_rate == MBPS_54) {
 708                        wid_list[i].id = WID_CURRENT_TX_RATE;
 709                        wid_list[i].val = (s8 *)&curr_tx_rate;
 710                        wid_list[i].type = WID_SHORT;
 711                        wid_list[i].size = sizeof(u16);
 712                        hif_drv->cfg_values.curr_tx_rate = (u8)curr_tx_rate;
 713                } else {
 714                        netdev_err(vif->ndev, "out of TX rate\n");
 715                        goto unlock;
 716                }
 717                i++;
 718        }
 719
 720        ret = wilc_send_config_pkt(vif, SET_CFG, wid_list,
 721                                   i, wilc_get_vif_idx(vif));
 722
 723        if (ret)
 724                netdev_err(vif->ndev, "Error in setting CFG params\n");
 725
 726unlock:
 727        mutex_unlock(&hif_drv->cfg_values_lock);
 728        kfree(msg);
 729}
 730
 731static int handle_scan_done(struct wilc_vif *vif, enum scan_event evt)
 732{
 733        int result = 0;
 734        u8 abort_running_scan;
 735        struct wid wid;
 736        struct host_if_drv *hif_drv = vif->hif_drv;
 737        struct user_scan_req *scan_req;
 738
 739        if (evt == SCAN_EVENT_ABORTED) {
 740                abort_running_scan = 1;
 741                wid.id = WID_ABORT_RUNNING_SCAN;
 742                wid.type = WID_CHAR;
 743                wid.val = (s8 *)&abort_running_scan;
 744                wid.size = sizeof(char);
 745
 746                result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1,
 747                                              wilc_get_vif_idx(vif));
 748
 749                if (result) {
 750                        netdev_err(vif->ndev, "Failed to set abort running\n");
 751                        result = -EFAULT;
 752                }
 753        }
 754
 755        if (!hif_drv) {
 756                netdev_err(vif->ndev, "%s: hif driver is NULL\n", __func__);
 757                return result;
 758        }
 759
 760        scan_req = &hif_drv->usr_scan_req;
 761        if (scan_req->scan_result) {
 762                scan_req->scan_result(evt, NULL, scan_req->arg, NULL);
 763                scan_req->scan_result = NULL;
 764        }
 765
 766        return result;
 767}
 768
 769static void handle_scan(struct work_struct *work)
 770{
 771        struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
 772        struct wilc_vif *vif = msg->vif;
 773        struct scan_attr *scan_info = &msg->body.scan_info;
 774        int result = 0;
 775        struct wid wid_list[5];
 776        u32 index = 0;
 777        u32 i;
 778        u8 *buffer;
 779        u8 valuesize = 0;
 780        u8 *hdn_ntwk_wid_val = NULL;
 781        struct host_if_drv *hif_drv = vif->hif_drv;
 782        struct hidden_network *hidden_net = &scan_info->hidden_network;
 783
 784        hif_drv->usr_scan_req.scan_result = scan_info->result;
 785        hif_drv->usr_scan_req.arg = scan_info->arg;
 786
 787        if (hif_drv->hif_state >= HOST_IF_SCANNING &&
 788            hif_drv->hif_state < HOST_IF_CONNECTED) {
 789                netdev_err(vif->ndev, "Already scan\n");
 790                result = -EBUSY;
 791                goto error;
 792        }
 793
 794        if (wilc_optaining_ip || wilc_connecting) {
 795                netdev_err(vif->ndev, "Don't do obss scan\n");
 796                result = -EBUSY;
 797                goto error;
 798        }
 799
 800        hif_drv->usr_scan_req.ch_cnt = 0;
 801
 802        wid_list[index].id = WID_SSID_PROBE_REQ;
 803        wid_list[index].type = WID_STR;
 804
 805        for (i = 0; i < hidden_net->n_ssids; i++)
 806                valuesize += ((hidden_net->net_info[i].ssid_len) + 1);
 807        hdn_ntwk_wid_val = kmalloc(valuesize + 1, GFP_KERNEL);
 808        wid_list[index].val = hdn_ntwk_wid_val;
 809        if (wid_list[index].val) {
 810                buffer = wid_list[index].val;
 811
 812                *buffer++ = hidden_net->n_ssids;
 813
 814                for (i = 0; i < hidden_net->n_ssids; i++) {
 815                        *buffer++ = hidden_net->net_info[i].ssid_len;
 816                        memcpy(buffer, hidden_net->net_info[i].ssid,
 817                               hidden_net->net_info[i].ssid_len);
 818                        buffer += hidden_net->net_info[i].ssid_len;
 819                }
 820
 821                wid_list[index].size = (s32)(valuesize + 1);
 822                index++;
 823        }
 824
 825        wid_list[index].id = WID_INFO_ELEMENT_PROBE;
 826        wid_list[index].type = WID_BIN_DATA;
 827        wid_list[index].val = scan_info->ies;
 828        wid_list[index].size = scan_info->ies_len;
 829        index++;
 830
 831        wid_list[index].id = WID_SCAN_TYPE;
 832        wid_list[index].type = WID_CHAR;
 833        wid_list[index].size = sizeof(char);
 834        wid_list[index].val = (s8 *)&scan_info->type;
 835        index++;
 836
 837        wid_list[index].id = WID_SCAN_CHANNEL_LIST;
 838        wid_list[index].type = WID_BIN_DATA;
 839
 840        if (scan_info->ch_freq_list &&
 841            scan_info->ch_list_len > 0) {
 842                int i;
 843
 844                for (i = 0; i < scan_info->ch_list_len; i++) {
 845                        if (scan_info->ch_freq_list[i] > 0)
 846                                scan_info->ch_freq_list[i] -= 1;
 847                }
 848        }
 849
 850        wid_list[index].val = scan_info->ch_freq_list;
 851        wid_list[index].size = scan_info->ch_list_len;
 852        index++;
 853
 854        wid_list[index].id = WID_START_SCAN_REQ;
 855        wid_list[index].type = WID_CHAR;
 856        wid_list[index].size = sizeof(char);
 857        wid_list[index].val = (s8 *)&scan_info->src;
 858        index++;
 859
 860        result = wilc_send_config_pkt(vif, SET_CFG, wid_list,
 861                                      index,
 862                                      wilc_get_vif_idx(vif));
 863
 864        if (result)
 865                netdev_err(vif->ndev, "Failed to send scan parameters\n");
 866
 867error:
 868        if (result) {
 869                del_timer(&hif_drv->scan_timer);
 870                handle_scan_done(vif, SCAN_EVENT_ABORTED);
 871        }
 872
 873        kfree(scan_info->ch_freq_list);
 874        scan_info->ch_freq_list = NULL;
 875
 876        kfree(scan_info->ies);
 877        scan_info->ies = NULL;
 878        kfree(scan_info->hidden_network.net_info);
 879        scan_info->hidden_network.net_info = NULL;
 880
 881        kfree(hdn_ntwk_wid_val);
 882
 883        kfree(msg);
 884}
 885
 886u8 wilc_connected_ssid[6] = {0};
 887static void handle_connect(struct work_struct *work)
 888{
 889        struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
 890        struct wilc_vif *vif = msg->vif;
 891        struct connect_attr *conn_attr = &msg->body.con_info;
 892        int result = 0;
 893        struct wid wid_list[8];
 894        u32 wid_cnt = 0, dummyval = 0;
 895        u8 *cur_byte = NULL;
 896        struct join_bss_param *bss_param;
 897        struct host_if_drv *hif_drv = vif->hif_drv;
 898
 899        if (msg->vif->hif_drv->usr_scan_req.scan_result) {
 900                result = wilc_enqueue_work(msg);
 901                if (result)
 902                        goto error;
 903
 904                usleep_range(2 * 1000, 2 * 1000);
 905                return;
 906        }
 907
 908        if (memcmp(conn_attr->bssid, wilc_connected_ssid, ETH_ALEN) == 0) {
 909                netdev_err(vif->ndev, "Discard connect request\n");
 910                goto error;
 911        }
 912
 913        bss_param = conn_attr->params;
 914        if (!bss_param) {
 915                netdev_err(vif->ndev, "Required BSSID not found\n");
 916                result = -ENOENT;
 917                goto error;
 918        }
 919
 920        if (conn_attr->bssid) {
 921                hif_drv->usr_conn_req.bssid = kmemdup(conn_attr->bssid, 6,
 922                                                      GFP_KERNEL);
 923                if (!hif_drv->usr_conn_req.bssid) {
 924                        result = -ENOMEM;
 925                        goto error;
 926                }
 927        }
 928
 929        hif_drv->usr_conn_req.ssid_len = conn_attr->ssid_len;
 930        if (conn_attr->ssid) {
 931                hif_drv->usr_conn_req.ssid = kmalloc(conn_attr->ssid_len + 1,
 932                                                     GFP_KERNEL);
 933                if (!hif_drv->usr_conn_req.ssid) {
 934                        result = -ENOMEM;
 935                        goto error;
 936                }
 937                memcpy(hif_drv->usr_conn_req.ssid,
 938                       conn_attr->ssid,
 939                       conn_attr->ssid_len);
 940                hif_drv->usr_conn_req.ssid[conn_attr->ssid_len] = '\0';
 941        }
 942
 943        hif_drv->usr_conn_req.ies_len = conn_attr->ies_len;
 944        if (conn_attr->ies) {
 945                hif_drv->usr_conn_req.ies = kmemdup(conn_attr->ies,
 946                                                    conn_attr->ies_len,
 947                                                    GFP_KERNEL);
 948                if (!hif_drv->usr_conn_req.ies) {
 949                        result = -ENOMEM;
 950                        goto error;
 951                }
 952        }
 953
 954        hif_drv->usr_conn_req.security = conn_attr->security;
 955        hif_drv->usr_conn_req.auth_type = conn_attr->auth_type;
 956        hif_drv->usr_conn_req.conn_result = conn_attr->result;
 957        hif_drv->usr_conn_req.arg = conn_attr->arg;
 958
 959        wid_list[wid_cnt].id = WID_SUCCESS_FRAME_COUNT;
 960        wid_list[wid_cnt].type = WID_INT;
 961        wid_list[wid_cnt].size = sizeof(u32);
 962        wid_list[wid_cnt].val = (s8 *)(&(dummyval));
 963        wid_cnt++;
 964
 965        wid_list[wid_cnt].id = WID_RECEIVED_FRAGMENT_COUNT;
 966        wid_list[wid_cnt].type = WID_INT;
 967        wid_list[wid_cnt].size = sizeof(u32);
 968        wid_list[wid_cnt].val = (s8 *)(&(dummyval));
 969        wid_cnt++;
 970
 971        wid_list[wid_cnt].id = WID_FAILED_COUNT;
 972        wid_list[wid_cnt].type = WID_INT;
 973        wid_list[wid_cnt].size = sizeof(u32);
 974        wid_list[wid_cnt].val = (s8 *)(&(dummyval));
 975        wid_cnt++;
 976
 977        wid_list[wid_cnt].id = WID_INFO_ELEMENT_ASSOCIATE;
 978        wid_list[wid_cnt].type = WID_BIN_DATA;
 979        wid_list[wid_cnt].val = hif_drv->usr_conn_req.ies;
 980        wid_list[wid_cnt].size = hif_drv->usr_conn_req.ies_len;
 981        wid_cnt++;
 982
 983        wid_list[wid_cnt].id = WID_11I_MODE;
 984        wid_list[wid_cnt].type = WID_CHAR;
 985        wid_list[wid_cnt].size = sizeof(char);
 986        wid_list[wid_cnt].val = (s8 *)&hif_drv->usr_conn_req.security;
 987        wid_cnt++;
 988
 989        wid_list[wid_cnt].id = WID_AUTH_TYPE;
 990        wid_list[wid_cnt].type = WID_CHAR;
 991        wid_list[wid_cnt].size = sizeof(char);
 992        wid_list[wid_cnt].val = (s8 *)&hif_drv->usr_conn_req.auth_type;
 993        wid_cnt++;
 994
 995        wid_list[wid_cnt].id = WID_JOIN_REQ_EXTENDED;
 996        wid_list[wid_cnt].type = WID_STR;
 997        wid_list[wid_cnt].size = 112;
 998        wid_list[wid_cnt].val = kmalloc(wid_list[wid_cnt].size, GFP_KERNEL);
 999
1000        if (!wid_list[wid_cnt].val) {
1001                result = -EFAULT;
1002                goto error;
1003        }
1004
1005        cur_byte = wid_list[wid_cnt].val;
1006
1007        if (conn_attr->ssid) {
1008                memcpy(cur_byte, conn_attr->ssid, conn_attr->ssid_len);
1009                cur_byte[conn_attr->ssid_len] = '\0';
1010        }
1011        cur_byte += MAX_SSID_LEN;
1012        *(cur_byte++) = INFRASTRUCTURE;
1013
1014        if (conn_attr->ch >= 1 && conn_attr->ch <= 14) {
1015                *(cur_byte++) = conn_attr->ch;
1016        } else {
1017                netdev_err(vif->ndev, "Channel out of range\n");
1018                *(cur_byte++) = 0xFF;
1019        }
1020        *(cur_byte++)  = (bss_param->cap_info) & 0xFF;
1021        *(cur_byte++)  = ((bss_param->cap_info) >> 8) & 0xFF;
1022
1023        if (conn_attr->bssid)
1024                memcpy(cur_byte, conn_attr->bssid, 6);
1025        cur_byte += 6;
1026
1027        if (conn_attr->bssid)
1028                memcpy(cur_byte, conn_attr->bssid, 6);
1029        cur_byte += 6;
1030
1031        *(cur_byte++)  = (bss_param->beacon_period) & 0xFF;
1032        *(cur_byte++)  = ((bss_param->beacon_period) >> 8) & 0xFF;
1033        *(cur_byte++)  =  bss_param->dtim_period;
1034
1035        memcpy(cur_byte, bss_param->supp_rates, MAX_RATES_SUPPORTED + 1);
1036        cur_byte += (MAX_RATES_SUPPORTED + 1);
1037
1038        *(cur_byte++)  =  bss_param->wmm_cap;
1039        *(cur_byte++)  = bss_param->uapsd_cap;
1040
1041        *(cur_byte++)  = bss_param->ht_capable;
1042        hif_drv->usr_conn_req.ht_capable = bss_param->ht_capable;
1043
1044        *(cur_byte++)  =  bss_param->rsn_found;
1045        *(cur_byte++)  =  bss_param->rsn_grp_policy;
1046        *(cur_byte++) =  bss_param->mode_802_11i;
1047
1048        memcpy(cur_byte, bss_param->rsn_pcip_policy,
1049               sizeof(bss_param->rsn_pcip_policy));
1050        cur_byte += sizeof(bss_param->rsn_pcip_policy);
1051
1052        memcpy(cur_byte, bss_param->rsn_auth_policy,
1053               sizeof(bss_param->rsn_auth_policy));
1054        cur_byte += sizeof(bss_param->rsn_auth_policy);
1055
1056        memcpy(cur_byte, bss_param->rsn_cap, sizeof(bss_param->rsn_cap));
1057        cur_byte += sizeof(bss_param->rsn_cap);
1058
1059        *(cur_byte++) = REAL_JOIN_REQ;
1060        *(cur_byte++) = bss_param->noa_enabled;
1061
1062        if (bss_param->noa_enabled) {
1063                *(cur_byte++) = (bss_param->tsf) & 0xFF;
1064                *(cur_byte++) = ((bss_param->tsf) >> 8) & 0xFF;
1065                *(cur_byte++) = ((bss_param->tsf) >> 16) & 0xFF;
1066                *(cur_byte++) = ((bss_param->tsf) >> 24) & 0xFF;
1067
1068                *(cur_byte++) = bss_param->opp_enabled;
1069                *(cur_byte++) = bss_param->idx;
1070
1071                if (bss_param->opp_enabled)
1072                        *(cur_byte++) = bss_param->ct_window;
1073
1074                *(cur_byte++) = bss_param->cnt;
1075
1076                memcpy(cur_byte, bss_param->duration,
1077                       sizeof(bss_param->duration));
1078                cur_byte += sizeof(bss_param->duration);
1079
1080                memcpy(cur_byte, bss_param->interval,
1081                       sizeof(bss_param->interval));
1082                cur_byte += sizeof(bss_param->interval);
1083
1084                memcpy(cur_byte, bss_param->start_time,
1085                       sizeof(bss_param->start_time));
1086                cur_byte += sizeof(bss_param->start_time);
1087        }
1088
1089        cur_byte = wid_list[wid_cnt].val;
1090        wid_cnt++;
1091
1092        if (conn_attr->bssid)
1093                memcpy(wilc_connected_ssid,
1094                       conn_attr->bssid, ETH_ALEN);
1095
1096        result = wilc_send_config_pkt(vif, SET_CFG, wid_list,
1097                                      wid_cnt,
1098                                      wilc_get_vif_idx(vif));
1099        if (result) {
1100                netdev_err(vif->ndev, "failed to send config packet\n");
1101                result = -EFAULT;
1102                goto error;
1103        } else {
1104                hif_drv->hif_state = HOST_IF_WAITING_CONN_RESP;
1105        }
1106
1107error:
1108        if (result) {
1109                struct connect_info conn_info;
1110
1111                del_timer(&hif_drv->connect_timer);
1112
1113                memset(&conn_info, 0, sizeof(struct connect_info));
1114
1115                if (conn_attr->result) {
1116                        if (conn_attr->bssid)
1117                                memcpy(conn_info.bssid, conn_attr->bssid, 6);
1118
1119                        if (conn_attr->ies) {
1120                                conn_info.req_ies_len = conn_attr->ies_len;
1121                                conn_info.req_ies = kmalloc(conn_attr->ies_len,
1122                                                            GFP_KERNEL);
1123                                memcpy(conn_info.req_ies,
1124                                       conn_attr->ies,
1125                                       conn_attr->ies_len);
1126                        }
1127
1128                        conn_attr->result(CONN_DISCONN_EVENT_CONN_RESP,
1129                                          &conn_info, MAC_STATUS_DISCONNECTED,
1130                                          NULL, conn_attr->arg);
1131                        hif_drv->hif_state = HOST_IF_IDLE;
1132                        kfree(conn_info.req_ies);
1133                        conn_info.req_ies = NULL;
1134
1135                } else {
1136                        netdev_err(vif->ndev, "Connect callback is NULL\n");
1137                }
1138        }
1139
1140        kfree(conn_attr->bssid);
1141        conn_attr->bssid = NULL;
1142
1143        kfree(conn_attr->ssid);
1144        conn_attr->ssid = NULL;
1145
1146        kfree(conn_attr->ies);
1147        conn_attr->ies = NULL;
1148
1149        kfree(cur_byte);
1150        kfree(msg);
1151}
1152
1153static void handle_connect_timeout(struct work_struct *work)
1154{
1155        struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
1156        struct wilc_vif *vif = msg->vif;
1157        int result;
1158        struct connect_info info;
1159        struct wid wid;
1160        u16 dummy_reason_code = 0;
1161        struct host_if_drv *hif_drv = vif->hif_drv;
1162
1163        if (!hif_drv) {
1164                netdev_err(vif->ndev, "%s: hif driver is NULL\n", __func__);
1165                goto out;
1166        }
1167
1168        hif_drv->hif_state = HOST_IF_IDLE;
1169
1170        memset(&info, 0, sizeof(struct connect_info));
1171
1172        if (hif_drv->usr_conn_req.conn_result) {
1173                if (hif_drv->usr_conn_req.bssid) {
1174                        memcpy(info.bssid,
1175                               hif_drv->usr_conn_req.bssid, 6);
1176                }
1177
1178                if (hif_drv->usr_conn_req.ies) {
1179                        info.req_ies_len = hif_drv->usr_conn_req.ies_len;
1180                        info.req_ies = kmemdup(hif_drv->usr_conn_req.ies,
1181                                               hif_drv->usr_conn_req.ies_len,
1182                                               GFP_KERNEL);
1183                        if (!info.req_ies)
1184                                goto out;
1185                }
1186
1187                hif_drv->usr_conn_req.conn_result(CONN_DISCONN_EVENT_CONN_RESP,
1188                                                  &info,
1189                                                  MAC_STATUS_DISCONNECTED,
1190                                                  NULL,
1191                                                  hif_drv->usr_conn_req.arg);
1192
1193                kfree(info.req_ies);
1194                info.req_ies = NULL;
1195        } else {
1196                netdev_err(vif->ndev, "%s: conn_result is NULL\n", __func__);
1197        }
1198
1199        wid.id = WID_DISCONNECT;
1200        wid.type = WID_CHAR;
1201        wid.val = (s8 *)&dummy_reason_code;
1202        wid.size = sizeof(char);
1203
1204        result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1,
1205                                      wilc_get_vif_idx(vif));
1206        if (result)
1207                netdev_err(vif->ndev, "Failed to send disconnect\n");
1208
1209        hif_drv->usr_conn_req.ssid_len = 0;
1210        kfree(hif_drv->usr_conn_req.ssid);
1211        hif_drv->usr_conn_req.ssid = NULL;
1212        kfree(hif_drv->usr_conn_req.bssid);
1213        hif_drv->usr_conn_req.bssid = NULL;
1214        hif_drv->usr_conn_req.ies_len = 0;
1215        kfree(hif_drv->usr_conn_req.ies);
1216        hif_drv->usr_conn_req.ies = NULL;
1217
1218        eth_zero_addr(wilc_connected_ssid);
1219
1220out:
1221        kfree(msg);
1222}
1223
1224static void host_int_fill_join_bss_param(struct join_bss_param *param, u8 *ies,
1225                                         u16 *out_index, u8 *pcipher_tc,
1226                                         u8 *auth_total_cnt, u32 tsf_lo,
1227                                         u8 *rates_no)
1228{
1229        u8 ext_rates_no;
1230        u16 offset;
1231        u8 pcipher_cnt;
1232        u8 auth_cnt;
1233        u8 i, j;
1234        u16 index = *out_index;
1235
1236        if (ies[index] == WLAN_EID_SUPP_RATES) {
1237                *rates_no = ies[index + 1];
1238                param->supp_rates[0] = *rates_no;
1239                index += 2;
1240
1241                for (i = 0; i < *rates_no; i++)
1242                        param->supp_rates[i + 1] = ies[index + i];
1243
1244                index += *rates_no;
1245        } else if (ies[index] == WLAN_EID_EXT_SUPP_RATES) {
1246                ext_rates_no = ies[index + 1];
1247                if (ext_rates_no > (MAX_RATES_SUPPORTED - *rates_no))
1248                        param->supp_rates[0] = MAX_RATES_SUPPORTED;
1249                else
1250                        param->supp_rates[0] += ext_rates_no;
1251                index += 2;
1252                for (i = 0; i < (param->supp_rates[0] - *rates_no); i++)
1253                        param->supp_rates[*rates_no + i + 1] = ies[index + i];
1254
1255                index += ext_rates_no;
1256        } else if (ies[index] == WLAN_EID_HT_CAPABILITY) {
1257                param->ht_capable = true;
1258                index += ies[index + 1] + 2;
1259        } else if ((ies[index] == WLAN_EID_VENDOR_SPECIFIC) &&
1260                   (ies[index + 2] == 0x00) && (ies[index + 3] == 0x50) &&
1261                   (ies[index + 4] == 0xF2) && (ies[index + 5] == 0x02) &&
1262                   ((ies[index + 6] == 0x00) || (ies[index + 6] == 0x01)) &&
1263                   (ies[index + 7] == 0x01)) {
1264                param->wmm_cap = true;
1265
1266                if (ies[index + 8] & BIT(7))
1267                        param->uapsd_cap = true;
1268                index += ies[index + 1] + 2;
1269        } else if ((ies[index] == WLAN_EID_VENDOR_SPECIFIC) &&
1270                 (ies[index + 2] == 0x50) && (ies[index + 3] == 0x6f) &&
1271                 (ies[index + 4] == 0x9a) &&
1272                 (ies[index + 5] == 0x09) && (ies[index + 6] == 0x0c)) {
1273                u16 p2p_cnt;
1274
1275                param->tsf = tsf_lo;
1276                param->noa_enabled = 1;
1277                param->idx = ies[index + 9];
1278
1279                if (ies[index + 10] & BIT(7)) {
1280                        param->opp_enabled = 1;
1281                        param->ct_window = ies[index + 10];
1282                } else {
1283                        param->opp_enabled = 0;
1284                }
1285
1286                param->cnt = ies[index + 11];
1287                p2p_cnt = index + 12;
1288
1289                memcpy(param->duration, ies + p2p_cnt, 4);
1290                p2p_cnt += 4;
1291
1292                memcpy(param->interval, ies + p2p_cnt, 4);
1293                p2p_cnt += 4;
1294
1295                memcpy(param->start_time, ies + p2p_cnt, 4);
1296
1297                index += ies[index + 1] + 2;
1298        } else if ((ies[index] == WLAN_EID_RSN) ||
1299                 ((ies[index] == WLAN_EID_VENDOR_SPECIFIC) &&
1300                  (ies[index + 2] == 0x00) &&
1301                  (ies[index + 3] == 0x50) && (ies[index + 4] == 0xF2) &&
1302                  (ies[index + 5] == 0x01))) {
1303                u16 rsn_idx = index;
1304
1305                if (ies[rsn_idx] == WLAN_EID_RSN) {
1306                        param->mode_802_11i = 2;
1307                } else {
1308                        if (param->mode_802_11i == 0)
1309                                param->mode_802_11i = 1;
1310                        rsn_idx += 4;
1311                }
1312
1313                rsn_idx += 7;
1314                param->rsn_grp_policy = ies[rsn_idx];
1315                rsn_idx++;
1316                offset = ies[rsn_idx] * 4;
1317                pcipher_cnt = (ies[rsn_idx] > 3) ? 3 : ies[rsn_idx];
1318                rsn_idx += 2;
1319
1320                i = *pcipher_tc;
1321                j = 0;
1322                for (; i < (pcipher_cnt + *pcipher_tc) && i < 3; i++, j++) {
1323                        u8 *policy =  &param->rsn_pcip_policy[i];
1324
1325                        *policy = ies[rsn_idx + ((j + 1) * 4) - 1];
1326                }
1327
1328                *pcipher_tc += pcipher_cnt;
1329                rsn_idx += offset;
1330
1331                offset = ies[rsn_idx] * 4;
1332
1333                auth_cnt = (ies[rsn_idx] > 3) ? 3 : ies[rsn_idx];
1334                rsn_idx += 2;
1335                i = *auth_total_cnt;
1336                j = 0;
1337                for (; i < (*auth_total_cnt + auth_cnt); i++, j++) {
1338                        u8 *policy =  &param->rsn_auth_policy[i];
1339
1340                        *policy = ies[rsn_idx + ((j + 1) * 4) - 1];
1341                }
1342
1343                *auth_total_cnt += auth_cnt;
1344                rsn_idx += offset;
1345
1346                if (ies[index] == WLAN_EID_RSN) {
1347                        param->rsn_cap[0] = ies[rsn_idx];
1348                        param->rsn_cap[1] = ies[rsn_idx + 1];
1349                        rsn_idx += 2;
1350                }
1351                param->rsn_found = true;
1352                index += ies[index + 1] + 2;
1353        } else {
1354                index += ies[index + 1] + 2;
1355        }
1356
1357        *out_index = index;
1358}
1359
1360static void *host_int_parse_join_bss_param(struct network_info *info)
1361{
1362        struct join_bss_param *param;
1363        u16 index = 0;
1364        u8 rates_no = 0;
1365        u8 pcipher_total_cnt = 0;
1366        u8 auth_total_cnt = 0;
1367
1368        param = kzalloc(sizeof(*param), GFP_KERNEL);
1369        if (!param)
1370                return NULL;
1371
1372        param->dtim_period = info->dtim_period;
1373        param->beacon_period = info->beacon_period;
1374        param->cap_info = info->cap_info;
1375        memcpy(param->bssid, info->bssid, 6);
1376        memcpy((u8 *)param->ssid, info->ssid, info->ssid_len + 1);
1377        param->ssid_len = info->ssid_len;
1378        memset(param->rsn_pcip_policy, 0xFF, 3);
1379        memset(param->rsn_auth_policy, 0xFF, 3);
1380
1381        while (index < info->ies_len)
1382                host_int_fill_join_bss_param(param, info->ies, &index,
1383                                             &pcipher_total_cnt,
1384                                             &auth_total_cnt, info->tsf_lo,
1385                                             &rates_no);
1386
1387        return (void *)param;
1388}
1389
1390static void handle_rcvd_ntwrk_info(struct work_struct *work)
1391{
1392        struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
1393        struct wilc_vif *vif = msg->vif;
1394        struct rcvd_net_info *rcvd_info = &msg->body.net_info;
1395        u32 i;
1396        bool found;
1397        struct network_info *info = NULL;
1398        void *params;
1399        struct host_if_drv *hif_drv = vif->hif_drv;
1400        struct user_scan_req *scan_req = &hif_drv->usr_scan_req;
1401
1402        found = true;
1403
1404        if (!scan_req->scan_result)
1405                goto done;
1406
1407        wilc_parse_network_info(rcvd_info->buffer, &info);
1408        if (!info || !scan_req->scan_result) {
1409                netdev_err(vif->ndev, "%s: info or scan result NULL\n",
1410                           __func__);
1411                goto done;
1412        }
1413
1414        for (i = 0; i < scan_req->ch_cnt; i++) {
1415                if (memcmp(scan_req->net_info[i].bssid, info->bssid, 6) == 0) {
1416                        if (info->rssi <= scan_req->net_info[i].rssi) {
1417                                goto done;
1418                        } else {
1419                                scan_req->net_info[i].rssi = info->rssi;
1420                                found = false;
1421                                break;
1422                        }
1423                }
1424        }
1425
1426        if (found) {
1427                if (scan_req->ch_cnt < MAX_NUM_SCANNED_NETWORKS) {
1428                        scan_req->net_info[scan_req->ch_cnt].rssi = info->rssi;
1429
1430                        memcpy(scan_req->net_info[scan_req->ch_cnt].bssid,
1431                               info->bssid, 6);
1432
1433                        scan_req->ch_cnt++;
1434
1435                        info->new_network = true;
1436                        params = host_int_parse_join_bss_param(info);
1437
1438                        scan_req->scan_result(SCAN_EVENT_NETWORK_FOUND, info,
1439                                               scan_req->arg, params);
1440                }
1441        } else {
1442                info->new_network = false;
1443                scan_req->scan_result(SCAN_EVENT_NETWORK_FOUND, info,
1444                                      scan_req->arg, NULL);
1445        }
1446
1447done:
1448        kfree(rcvd_info->buffer);
1449        rcvd_info->buffer = NULL;
1450
1451        if (info) {
1452                kfree(info->ies);
1453                kfree(info);
1454        }
1455
1456        kfree(msg);
1457}
1458
1459static s32 host_int_get_assoc_res_info(struct wilc_vif *vif,
1460                                       u8 *assoc_resp_info,
1461                                       u32 max_assoc_resp_info_len,
1462                                       u32 *rcvd_assoc_resp_info_len)
1463{
1464        int result;
1465        struct wid wid;
1466
1467        wid.id = WID_ASSOC_RES_INFO;
1468        wid.type = WID_STR;
1469        wid.val = assoc_resp_info;
1470        wid.size = max_assoc_resp_info_len;
1471
1472        result = wilc_send_config_pkt(vif, GET_CFG, &wid, 1,
1473                                      wilc_get_vif_idx(vif));
1474        if (result) {
1475                *rcvd_assoc_resp_info_len = 0;
1476                netdev_err(vif->ndev, "Failed to send association response\n");
1477                return -EINVAL;
1478        }
1479
1480        *rcvd_assoc_resp_info_len = wid.size;
1481        return result;
1482}
1483
1484static inline void host_int_free_user_conn_req(struct host_if_drv *hif_drv)
1485{
1486        hif_drv->usr_conn_req.ssid_len = 0;
1487        kfree(hif_drv->usr_conn_req.ssid);
1488        hif_drv->usr_conn_req.ssid = NULL;
1489        kfree(hif_drv->usr_conn_req.bssid);
1490        hif_drv->usr_conn_req.bssid = NULL;
1491        hif_drv->usr_conn_req.ies_len = 0;
1492        kfree(hif_drv->usr_conn_req.ies);
1493        hif_drv->usr_conn_req.ies = NULL;
1494}
1495
1496static inline void host_int_parse_assoc_resp_info(struct wilc_vif *vif,
1497                                                  u8 mac_status)
1498{
1499        struct connect_info conn_info;
1500        struct host_if_drv *hif_drv = vif->hif_drv;
1501
1502        memset(&conn_info, 0, sizeof(struct connect_info));
1503
1504        if (mac_status == MAC_STATUS_CONNECTED) {
1505                u32 assoc_resp_info_len;
1506
1507                memset(rcv_assoc_resp, 0, MAX_ASSOC_RESP_FRAME_SIZE);
1508
1509                host_int_get_assoc_res_info(vif, rcv_assoc_resp,
1510                                            MAX_ASSOC_RESP_FRAME_SIZE,
1511                                            &assoc_resp_info_len);
1512
1513                if (assoc_resp_info_len != 0) {
1514                        s32 err = 0;
1515
1516                        err = wilc_parse_assoc_resp_info(rcv_assoc_resp,
1517                                                         assoc_resp_info_len,
1518                                                         &conn_info);
1519                        if (err)
1520                                netdev_err(vif->ndev,
1521                                           "wilc_parse_assoc_resp_info() returned error %d\n",
1522                                           err);
1523                }
1524        }
1525
1526        if (mac_status == MAC_STATUS_CONNECTED &&
1527            conn_info.status != WLAN_STATUS_SUCCESS) {
1528                netdev_err(vif->ndev,
1529                           "Received MAC status is MAC_STATUS_CONNECTED, Assoc Resp is not SUCCESS\n");
1530                eth_zero_addr(wilc_connected_ssid);
1531        } else if (mac_status == MAC_STATUS_DISCONNECTED)    {
1532                netdev_err(vif->ndev, "Received MAC status is MAC_STATUS_DISCONNECTED\n");
1533                eth_zero_addr(wilc_connected_ssid);
1534        }
1535
1536        if (hif_drv->usr_conn_req.bssid) {
1537                memcpy(conn_info.bssid, hif_drv->usr_conn_req.bssid, 6);
1538
1539                if (mac_status == MAC_STATUS_CONNECTED &&
1540                    conn_info.status == WLAN_STATUS_SUCCESS) {
1541                        memcpy(hif_drv->assoc_bssid,
1542                               hif_drv->usr_conn_req.bssid, ETH_ALEN);
1543                }
1544        }
1545
1546        if (hif_drv->usr_conn_req.ies) {
1547                conn_info.req_ies = kmemdup(hif_drv->usr_conn_req.ies,
1548                                            hif_drv->usr_conn_req.ies_len,
1549                                            GFP_KERNEL);
1550                if (conn_info.req_ies)
1551                        conn_info.req_ies_len = hif_drv->usr_conn_req.ies_len;
1552        }
1553
1554        del_timer(&hif_drv->connect_timer);
1555        hif_drv->usr_conn_req.conn_result(CONN_DISCONN_EVENT_CONN_RESP,
1556                                          &conn_info, mac_status, NULL,
1557                                          hif_drv->usr_conn_req.arg);
1558
1559        if (mac_status == MAC_STATUS_CONNECTED &&
1560            conn_info.status == WLAN_STATUS_SUCCESS) {
1561                wilc_set_power_mgmt(vif, 0, 0);
1562
1563                hif_drv->hif_state = HOST_IF_CONNECTED;
1564
1565                wilc_optaining_ip = true;
1566                mod_timer(&wilc_during_ip_timer,
1567                          jiffies + msecs_to_jiffies(10000));
1568        } else {
1569                hif_drv->hif_state = HOST_IF_IDLE;
1570        }
1571
1572        kfree(conn_info.resp_ies);
1573        conn_info.resp_ies = NULL;
1574
1575        kfree(conn_info.req_ies);
1576        conn_info.req_ies = NULL;
1577        host_int_free_user_conn_req(hif_drv);
1578}
1579
1580static inline void host_int_handle_disconnect(struct wilc_vif *vif)
1581{
1582        struct disconnect_info disconn_info;
1583        struct host_if_drv *hif_drv = vif->hif_drv;
1584        wilc_connect_result conn_result = hif_drv->usr_conn_req.conn_result;
1585
1586        memset(&disconn_info, 0, sizeof(struct disconnect_info));
1587
1588        if (hif_drv->usr_scan_req.scan_result) {
1589                del_timer(&hif_drv->scan_timer);
1590                handle_scan_done(vif, SCAN_EVENT_ABORTED);
1591        }
1592
1593        disconn_info.reason = 0;
1594        disconn_info.ie = NULL;
1595        disconn_info.ie_len = 0;
1596
1597        if (conn_result) {
1598                wilc_optaining_ip = false;
1599                wilc_set_power_mgmt(vif, 0, 0);
1600
1601                conn_result(CONN_DISCONN_EVENT_DISCONN_NOTIF, NULL, 0,
1602                            &disconn_info, hif_drv->usr_conn_req.arg);
1603        } else {
1604                netdev_err(vif->ndev, "%s: conn_result is NULL\n", __func__);
1605        }
1606
1607        eth_zero_addr(hif_drv->assoc_bssid);
1608
1609        host_int_free_user_conn_req(hif_drv);
1610        hif_drv->hif_state = HOST_IF_IDLE;
1611}
1612
1613static void handle_rcvd_gnrl_async_info(struct work_struct *work)
1614{
1615        struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
1616        struct wilc_vif *vif = msg->vif;
1617        struct rcvd_async_info *rcvd_info = &msg->body.async_info;
1618        u8 msg_type;
1619        u8 mac_status;
1620        struct host_if_drv *hif_drv = vif->hif_drv;
1621
1622        if (!rcvd_info->buffer) {
1623                netdev_err(vif->ndev, "%s: buffer is NULL\n", __func__);
1624                goto free_msg;
1625        }
1626
1627        if (!hif_drv) {
1628                netdev_err(vif->ndev, "%s: hif driver is NULL\n", __func__);
1629                goto free_rcvd_info;
1630        }
1631
1632        if (hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP ||
1633            hif_drv->hif_state == HOST_IF_CONNECTED ||
1634            hif_drv->usr_scan_req.scan_result) {
1635                if (!hif_drv->usr_conn_req.conn_result) {
1636                        netdev_err(vif->ndev, "%s: conn_result is NULL\n",
1637                                   __func__);
1638                        goto free_rcvd_info;
1639                }
1640
1641                msg_type = rcvd_info->buffer[0];
1642
1643                if ('I' != msg_type) {
1644                        netdev_err(vif->ndev, "Received Message incorrect.\n");
1645                        goto free_rcvd_info;
1646                }
1647
1648                mac_status  = rcvd_info->buffer[7];
1649                if (hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP) {
1650                        host_int_parse_assoc_resp_info(vif, mac_status);
1651                } else if ((mac_status == MAC_STATUS_DISCONNECTED) &&
1652                           (hif_drv->hif_state == HOST_IF_CONNECTED)) {
1653                        host_int_handle_disconnect(vif);
1654                } else if ((mac_status == MAC_STATUS_DISCONNECTED) &&
1655                           (hif_drv->usr_scan_req.scan_result)) {
1656                        del_timer(&hif_drv->scan_timer);
1657                        if (hif_drv->usr_scan_req.scan_result)
1658                                handle_scan_done(vif, SCAN_EVENT_ABORTED);
1659                }
1660        }
1661
1662free_rcvd_info:
1663        kfree(rcvd_info->buffer);
1664        rcvd_info->buffer = NULL;
1665
1666free_msg:
1667        kfree(msg);
1668}
1669
1670static int wilc_pmksa_key_copy(struct wilc_vif *vif, struct key_attr *hif_key)
1671{
1672        int i;
1673        int ret;
1674        struct wid wid;
1675        u8 *key_buf;
1676
1677        key_buf = kmalloc((hif_key->attr.pmkid.numpmkid * PMKSA_KEY_LEN) + 1,
1678                          GFP_KERNEL);
1679        if (!key_buf)
1680                return -ENOMEM;
1681
1682        key_buf[0] = hif_key->attr.pmkid.numpmkid;
1683
1684        for (i = 0; i < hif_key->attr.pmkid.numpmkid; i++) {
1685                memcpy(key_buf + ((PMKSA_KEY_LEN * i) + 1),
1686                       hif_key->attr.pmkid.pmkidlist[i].bssid, ETH_ALEN);
1687                memcpy(key_buf + ((PMKSA_KEY_LEN * i) + ETH_ALEN + 1),
1688                       hif_key->attr.pmkid.pmkidlist[i].pmkid, PMKID_LEN);
1689        }
1690
1691        wid.id = WID_PMKID_INFO;
1692        wid.type = WID_STR;
1693        wid.val = (s8 *)key_buf;
1694        wid.size = (hif_key->attr.pmkid.numpmkid * PMKSA_KEY_LEN) + 1;
1695
1696        ret = wilc_send_config_pkt(vif, SET_CFG, &wid, 1,
1697                                   wilc_get_vif_idx(vif));
1698
1699        kfree(key_buf);
1700
1701        return ret;
1702}
1703
1704static void handle_key(struct work_struct *work)
1705{
1706        struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
1707        struct wilc_vif *vif = msg->vif;
1708        struct key_attr *hif_key = &msg->body.key_info;
1709        int result = 0;
1710        struct wid wid;
1711        struct wid wid_list[5];
1712        u8 *key_buf;
1713        struct host_if_drv *hif_drv = vif->hif_drv;
1714
1715        switch (hif_key->type) {
1716        case WEP:
1717
1718                if (hif_key->action & ADDKEY_AP) {
1719                        wid_list[0].id = WID_11I_MODE;
1720                        wid_list[0].type = WID_CHAR;
1721                        wid_list[0].size = sizeof(char);
1722                        wid_list[0].val = (s8 *)&hif_key->attr.wep.mode;
1723
1724                        wid_list[1].id = WID_AUTH_TYPE;
1725                        wid_list[1].type = WID_CHAR;
1726                        wid_list[1].size = sizeof(char);
1727                        wid_list[1].val = (s8 *)&hif_key->attr.wep.auth_type;
1728
1729                        key_buf = kmalloc(hif_key->attr.wep.key_len + 2,
1730                                          GFP_KERNEL);
1731                        if (!key_buf) {
1732                                result = -ENOMEM;
1733                                goto out_wep;
1734                        }
1735
1736                        key_buf[0] = hif_key->attr.wep.index;
1737                        key_buf[1] = hif_key->attr.wep.key_len;
1738
1739                        memcpy(&key_buf[2], hif_key->attr.wep.key,
1740                               hif_key->attr.wep.key_len);
1741
1742                        wid_list[2].id = WID_WEP_KEY_VALUE;
1743                        wid_list[2].type = WID_STR;
1744                        wid_list[2].size = hif_key->attr.wep.key_len + 2;
1745                        wid_list[2].val = (s8 *)key_buf;
1746
1747                        result = wilc_send_config_pkt(vif, SET_CFG,
1748                                                      wid_list, 3,
1749                                                      wilc_get_vif_idx(vif));
1750                        kfree(key_buf);
1751                } else if (hif_key->action & ADDKEY) {
1752                        key_buf = kmalloc(hif_key->attr.wep.key_len + 2,
1753                                          GFP_KERNEL);
1754                        if (!key_buf) {
1755                                result = -ENOMEM;
1756                                goto out_wep;
1757                        }
1758                        key_buf[0] = hif_key->attr.wep.index;
1759                        memcpy(key_buf + 1, &hif_key->attr.wep.key_len, 1);
1760                        memcpy(key_buf + 2, hif_key->attr.wep.key,
1761                               hif_key->attr.wep.key_len);
1762
1763                        wid.id = WID_ADD_WEP_KEY;
1764                        wid.type = WID_STR;
1765                        wid.val = (s8 *)key_buf;
1766                        wid.size = hif_key->attr.wep.key_len + 2;
1767
1768                        result = wilc_send_config_pkt(vif, SET_CFG,
1769                                                      &wid, 1,
1770                                                      wilc_get_vif_idx(vif));
1771                        kfree(key_buf);
1772                } else if (hif_key->action & REMOVEKEY) {
1773                        wid.id = WID_REMOVE_WEP_KEY;
1774                        wid.type = WID_STR;
1775
1776                        wid.val = (s8 *)&hif_key->attr.wep.index;
1777                        wid.size = 1;
1778
1779                        result = wilc_send_config_pkt(vif, SET_CFG,
1780                                                      &wid, 1,
1781                                                      wilc_get_vif_idx(vif));
1782                } else if (hif_key->action & DEFAULTKEY) {
1783                        wid.id = WID_KEY_ID;
1784                        wid.type = WID_CHAR;
1785                        wid.val = (s8 *)&hif_key->attr.wep.index;
1786                        wid.size = sizeof(char);
1787
1788                        result = wilc_send_config_pkt(vif, SET_CFG,
1789                                                      &wid, 1,
1790                                                      wilc_get_vif_idx(vif));
1791                }
1792out_wep:
1793                complete(&msg->work_comp);
1794                break;
1795
1796        case WPA_RX_GTK:
1797                if (hif_key->action & ADDKEY_AP) {
1798                        key_buf = kzalloc(RX_MIC_KEY_MSG_LEN, GFP_KERNEL);
1799                        if (!key_buf) {
1800                                result = -ENOMEM;
1801                                goto out_wpa_rx_gtk;
1802                        }
1803
1804                        if (hif_key->attr.wpa.seq)
1805                                memcpy(key_buf + 6, hif_key->attr.wpa.seq, 8);
1806
1807                        memcpy(key_buf + 14, &hif_key->attr.wpa.index, 1);
1808                        memcpy(key_buf + 15, &hif_key->attr.wpa.key_len, 1);
1809                        memcpy(key_buf + 16, hif_key->attr.wpa.key,
1810                               hif_key->attr.wpa.key_len);
1811
1812                        wid_list[0].id = WID_11I_MODE;
1813                        wid_list[0].type = WID_CHAR;
1814                        wid_list[0].size = sizeof(char);
1815                        wid_list[0].val = (s8 *)&hif_key->attr.wpa.mode;
1816
1817                        wid_list[1].id = WID_ADD_RX_GTK;
1818                        wid_list[1].type = WID_STR;
1819                        wid_list[1].val = (s8 *)key_buf;
1820                        wid_list[1].size = RX_MIC_KEY_MSG_LEN;
1821
1822                        result = wilc_send_config_pkt(vif, SET_CFG,
1823                                                      wid_list, 2,
1824                                                      wilc_get_vif_idx(vif));
1825
1826                        kfree(key_buf);
1827                } else if (hif_key->action & ADDKEY) {
1828                        key_buf = kzalloc(RX_MIC_KEY_MSG_LEN, GFP_KERNEL);
1829                        if (!key_buf) {
1830                                result = -ENOMEM;
1831                                goto out_wpa_rx_gtk;
1832                        }
1833
1834                        if (hif_drv->hif_state == HOST_IF_CONNECTED)
1835                                memcpy(key_buf, hif_drv->assoc_bssid, ETH_ALEN);
1836                        else
1837                                netdev_err(vif->ndev, "Couldn't handle\n");
1838
1839                        memcpy(key_buf + 6, hif_key->attr.wpa.seq, 8);
1840                        memcpy(key_buf + 14, &hif_key->attr.wpa.index, 1);
1841                        memcpy(key_buf + 15, &hif_key->attr.wpa.key_len, 1);
1842                        memcpy(key_buf + 16, hif_key->attr.wpa.key,
1843                               hif_key->attr.wpa.key_len);
1844
1845                        wid.id = WID_ADD_RX_GTK;
1846                        wid.type = WID_STR;
1847                        wid.val = (s8 *)key_buf;
1848                        wid.size = RX_MIC_KEY_MSG_LEN;
1849
1850                        result = wilc_send_config_pkt(vif, SET_CFG,
1851                                                      &wid, 1,
1852                                                      wilc_get_vif_idx(vif));
1853
1854                        kfree(key_buf);
1855                }
1856out_wpa_rx_gtk:
1857                complete(&msg->work_comp);
1858                break;
1859
1860        case WPA_PTK:
1861                if (hif_key->action & ADDKEY_AP) {
1862                        key_buf = kmalloc(PTK_KEY_MSG_LEN + 1, GFP_KERNEL);
1863                        if (!key_buf) {
1864                                result = -ENOMEM;
1865                                goto out_wpa_ptk;
1866                        }
1867
1868                        memcpy(key_buf, hif_key->attr.wpa.mac_addr, 6);
1869                        memcpy(key_buf + 6, &hif_key->attr.wpa.index, 1);
1870                        memcpy(key_buf + 7, &hif_key->attr.wpa.key_len, 1);
1871                        memcpy(key_buf + 8, hif_key->attr.wpa.key,
1872                               hif_key->attr.wpa.key_len);
1873
1874                        wid_list[0].id = WID_11I_MODE;
1875                        wid_list[0].type = WID_CHAR;
1876                        wid_list[0].size = sizeof(char);
1877                        wid_list[0].val = (s8 *)&hif_key->attr.wpa.mode;
1878
1879                        wid_list[1].id = WID_ADD_PTK;
1880                        wid_list[1].type = WID_STR;
1881                        wid_list[1].val = (s8 *)key_buf;
1882                        wid_list[1].size = PTK_KEY_MSG_LEN + 1;
1883
1884                        result = wilc_send_config_pkt(vif, SET_CFG,
1885                                                      wid_list, 2,
1886                                                      wilc_get_vif_idx(vif));
1887                        kfree(key_buf);
1888                } else if (hif_key->action & ADDKEY) {
1889                        key_buf = kmalloc(PTK_KEY_MSG_LEN, GFP_KERNEL);
1890                        if (!key_buf) {
1891                                result = -ENOMEM;
1892                                goto out_wpa_ptk;
1893                        }
1894
1895                        memcpy(key_buf, hif_key->attr.wpa.mac_addr, 6);
1896                        memcpy(key_buf + 6, &hif_key->attr.wpa.key_len, 1);
1897                        memcpy(key_buf + 7, hif_key->attr.wpa.key,
1898                               hif_key->attr.wpa.key_len);
1899
1900                        wid.id = WID_ADD_PTK;
1901                        wid.type = WID_STR;
1902                        wid.val = (s8 *)key_buf;
1903                        wid.size = PTK_KEY_MSG_LEN;
1904
1905                        result = wilc_send_config_pkt(vif, SET_CFG,
1906                                                      &wid, 1,
1907                                                      wilc_get_vif_idx(vif));
1908                        kfree(key_buf);
1909                }
1910
1911out_wpa_ptk:
1912                complete(&msg->work_comp);
1913                break;
1914
1915        case PMKSA:
1916                result = wilc_pmksa_key_copy(vif, hif_key);
1917                /*free 'msg', this case it not a sync call*/
1918                kfree(msg);
1919                break;
1920        }
1921
1922        if (result)
1923                netdev_err(vif->ndev, "Failed to send key config packet\n");
1924
1925        /* free 'msg' data in caller sync call */
1926}
1927
1928static void handle_disconnect(struct work_struct *work)
1929{
1930        struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
1931        struct wilc_vif *vif = msg->vif;
1932        struct wid wid;
1933        struct host_if_drv *hif_drv = vif->hif_drv;
1934        struct disconnect_info disconn_info;
1935        struct user_scan_req *scan_req;
1936        struct user_conn_req *conn_req;
1937        int result;
1938        u16 dummy_reason_code = 0;
1939
1940        wid.id = WID_DISCONNECT;
1941        wid.type = WID_CHAR;
1942        wid.val = (s8 *)&dummy_reason_code;
1943        wid.size = sizeof(char);
1944
1945        wilc_optaining_ip = false;
1946        wilc_set_power_mgmt(vif, 0, 0);
1947
1948        eth_zero_addr(wilc_connected_ssid);
1949
1950        result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1,
1951                                      wilc_get_vif_idx(vif));
1952
1953        if (result) {
1954                netdev_err(vif->ndev, "Failed to send dissconect\n");
1955                goto out;
1956        }
1957
1958        memset(&disconn_info, 0, sizeof(struct disconnect_info));
1959
1960        disconn_info.reason = 0;
1961        disconn_info.ie = NULL;
1962        disconn_info.ie_len = 0;
1963        scan_req = &hif_drv->usr_scan_req;
1964        conn_req = &hif_drv->usr_conn_req;
1965
1966        if (scan_req->scan_result) {
1967                del_timer(&hif_drv->scan_timer);
1968                scan_req->scan_result(SCAN_EVENT_ABORTED, NULL, scan_req->arg,
1969                                      NULL);
1970                scan_req->scan_result = NULL;
1971        }
1972
1973        if (conn_req->conn_result) {
1974                if (hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP)
1975                        del_timer(&hif_drv->connect_timer);
1976
1977                conn_req->conn_result(CONN_DISCONN_EVENT_DISCONN_NOTIF, NULL,
1978                                      0, &disconn_info, conn_req->arg);
1979        } else {
1980                netdev_err(vif->ndev, "%s: conn_result is NULL\n", __func__);
1981        }
1982
1983        hif_drv->hif_state = HOST_IF_IDLE;
1984
1985        eth_zero_addr(hif_drv->assoc_bssid);
1986
1987        conn_req->ssid_len = 0;
1988        kfree(conn_req->ssid);
1989        conn_req->ssid = NULL;
1990        kfree(conn_req->bssid);
1991        conn_req->bssid = NULL;
1992        conn_req->ies_len = 0;
1993        kfree(conn_req->ies);
1994        conn_req->ies = NULL;
1995
1996out:
1997
1998        complete(&msg->work_comp);
1999        /* free 'msg' in caller after receiving completion */
2000}
2001
2002void wilc_resolve_disconnect_aberration(struct wilc_vif *vif)
2003{
2004        if (!vif->hif_drv)
2005                return;
2006        if (vif->hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP ||
2007            vif->hif_drv->hif_state == HOST_IF_CONNECTING)
2008                wilc_disconnect(vif, 1);
2009}
2010
2011static void handle_get_rssi(struct work_struct *work)
2012{
2013        struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
2014        struct wilc_vif *vif = msg->vif;
2015        int result;
2016        struct wid wid;
2017
2018        wid.id = WID_RSSI;
2019        wid.type = WID_CHAR;
2020        wid.val = msg->body.data;
2021        wid.size = sizeof(char);
2022
2023        result = wilc_send_config_pkt(vif, GET_CFG, &wid, 1,
2024                                      wilc_get_vif_idx(vif));
2025        if (result)
2026                netdev_err(vif->ndev, "Failed to get RSSI value\n");
2027
2028        complete(&msg->work_comp);
2029        /* free 'msg' data in caller */
2030}
2031
2032static void handle_get_statistics(struct work_struct *work)
2033{
2034        struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
2035        struct wilc_vif *vif = msg->vif;
2036        struct wid wid_list[5];
2037        u32 wid_cnt = 0, result;
2038        struct rf_info *stats = (struct rf_info *)msg->body.data;
2039
2040        wid_list[wid_cnt].id = WID_LINKSPEED;
2041        wid_list[wid_cnt].type = WID_CHAR;
2042        wid_list[wid_cnt].size = sizeof(char);
2043        wid_list[wid_cnt].val = (s8 *)&stats->link_speed;
2044        wid_cnt++;
2045
2046        wid_list[wid_cnt].id = WID_RSSI;
2047        wid_list[wid_cnt].type = WID_CHAR;
2048        wid_list[wid_cnt].size = sizeof(char);
2049        wid_list[wid_cnt].val = (s8 *)&stats->rssi;
2050        wid_cnt++;
2051
2052        wid_list[wid_cnt].id = WID_SUCCESS_FRAME_COUNT;
2053        wid_list[wid_cnt].type = WID_INT;
2054        wid_list[wid_cnt].size = sizeof(u32);
2055        wid_list[wid_cnt].val = (s8 *)&stats->tx_cnt;
2056        wid_cnt++;
2057
2058        wid_list[wid_cnt].id = WID_RECEIVED_FRAGMENT_COUNT;
2059        wid_list[wid_cnt].type = WID_INT;
2060        wid_list[wid_cnt].size = sizeof(u32);
2061        wid_list[wid_cnt].val = (s8 *)&stats->rx_cnt;
2062        wid_cnt++;
2063
2064        wid_list[wid_cnt].id = WID_FAILED_COUNT;
2065        wid_list[wid_cnt].type = WID_INT;
2066        wid_list[wid_cnt].size = sizeof(u32);
2067        wid_list[wid_cnt].val = (s8 *)&stats->tx_fail_cnt;
2068        wid_cnt++;
2069
2070        result = wilc_send_config_pkt(vif, GET_CFG, wid_list,
2071                                      wid_cnt,
2072                                      wilc_get_vif_idx(vif));
2073
2074        if (result)
2075                netdev_err(vif->ndev, "Failed to send scan parameters\n");
2076
2077        if (stats->link_speed > TCP_ACK_FILTER_LINK_SPEED_THRESH &&
2078            stats->link_speed != DEFAULT_LINK_SPEED)
2079                wilc_enable_tcp_ack_filter(true);
2080        else if (stats->link_speed != DEFAULT_LINK_SPEED)
2081                wilc_enable_tcp_ack_filter(false);
2082
2083        /* free 'msg' for async command, for sync caller will free it */
2084        if (msg->is_sync)
2085                complete(&msg->work_comp);
2086        else
2087                kfree(msg);
2088}
2089
2090static void handle_get_inactive_time(struct work_struct *work)
2091{
2092        struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
2093        struct wilc_vif *vif = msg->vif;
2094        struct sta_inactive_t *hif_sta_inactive = &msg->body.mac_info;
2095        int result;
2096        struct wid wid;
2097
2098        wid.id = WID_SET_STA_MAC_INACTIVE_TIME;
2099        wid.type = WID_STR;
2100        wid.size = ETH_ALEN;
2101        wid.val = kmalloc(wid.size, GFP_KERNEL);
2102        if (!wid.val)
2103                goto out;
2104
2105        ether_addr_copy(wid.val, hif_sta_inactive->mac);
2106
2107        result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1,
2108                                      wilc_get_vif_idx(vif));
2109        kfree(wid.val);
2110
2111        if (result) {
2112                netdev_err(vif->ndev, "Failed to set inactive mac\n");
2113                goto out;
2114        }
2115
2116        wid.id = WID_GET_INACTIVE_TIME;
2117        wid.type = WID_INT;
2118        wid.val = (s8 *)&hif_sta_inactive->inactive_time;
2119        wid.size = sizeof(u32);
2120
2121        result = wilc_send_config_pkt(vif, GET_CFG, &wid, 1,
2122                                      wilc_get_vif_idx(vif));
2123
2124        if (result)
2125                netdev_err(vif->ndev, "Failed to get inactive time\n");
2126
2127out:
2128        /* free 'msg' data in caller */
2129        complete(&msg->work_comp);
2130}
2131
2132static void handle_add_beacon(struct work_struct *work)
2133{
2134        struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
2135        struct wilc_vif *vif = msg->vif;
2136        struct beacon_attr *param = &msg->body.beacon_info;
2137        int result;
2138        struct wid wid;
2139        u8 *cur_byte;
2140
2141        wid.id = WID_ADD_BEACON;
2142        wid.type = WID_BIN;
2143        wid.size = param->head_len + param->tail_len + 16;
2144        wid.val = kmalloc(wid.size, GFP_KERNEL);
2145        if (!wid.val)
2146                goto error;
2147
2148        cur_byte = wid.val;
2149        *cur_byte++ = (param->interval & 0xFF);
2150        *cur_byte++ = ((param->interval >> 8) & 0xFF);
2151        *cur_byte++ = ((param->interval >> 16) & 0xFF);
2152        *cur_byte++ = ((param->interval >> 24) & 0xFF);
2153
2154        *cur_byte++ = (param->dtim_period & 0xFF);
2155        *cur_byte++ = ((param->dtim_period >> 8) & 0xFF);
2156        *cur_byte++ = ((param->dtim_period >> 16) & 0xFF);
2157        *cur_byte++ = ((param->dtim_period >> 24) & 0xFF);
2158
2159        *cur_byte++ = (param->head_len & 0xFF);
2160        *cur_byte++ = ((param->head_len >> 8) & 0xFF);
2161        *cur_byte++ = ((param->head_len >> 16) & 0xFF);
2162        *cur_byte++ = ((param->head_len >> 24) & 0xFF);
2163
2164        memcpy(cur_byte, param->head, param->head_len);
2165        cur_byte += param->head_len;
2166
2167        *cur_byte++ = (param->tail_len & 0xFF);
2168        *cur_byte++ = ((param->tail_len >> 8) & 0xFF);
2169        *cur_byte++ = ((param->tail_len >> 16) & 0xFF);
2170        *cur_byte++ = ((param->tail_len >> 24) & 0xFF);
2171
2172        if (param->tail)
2173                memcpy(cur_byte, param->tail, param->tail_len);
2174        cur_byte += param->tail_len;
2175
2176        result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1,
2177                                      wilc_get_vif_idx(vif));
2178        if (result)
2179                netdev_err(vif->ndev, "Failed to send add beacon\n");
2180
2181error:
2182        kfree(wid.val);
2183        kfree(param->head);
2184        kfree(param->tail);
2185        kfree(msg);
2186}
2187
2188static void handle_del_beacon(struct work_struct *work)
2189{
2190        struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
2191        struct wilc_vif *vif = msg->vif;
2192        int result;
2193        struct wid wid;
2194        u8 del_beacon = 0;
2195
2196        wid.id = WID_DEL_BEACON;
2197        wid.type = WID_CHAR;
2198        wid.size = sizeof(char);
2199        wid.val = &del_beacon;
2200
2201        result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1,
2202                                      wilc_get_vif_idx(vif));
2203        if (result)
2204                netdev_err(vif->ndev, "Failed to send delete beacon\n");
2205        kfree(msg);
2206}
2207
2208static u32 wilc_hif_pack_sta_param(u8 *buff, struct add_sta_param *param)
2209{
2210        u8 *cur_byte;
2211
2212        cur_byte = buff;
2213
2214        memcpy(cur_byte, param->bssid, ETH_ALEN);
2215        cur_byte +=  ETH_ALEN;
2216
2217        *cur_byte++ = param->aid & 0xFF;
2218        *cur_byte++ = (param->aid >> 8) & 0xFF;
2219
2220        *cur_byte++ = param->rates_len;
2221        if (param->rates_len > 0)
2222                memcpy(cur_byte, param->rates, param->rates_len);
2223        cur_byte += param->rates_len;
2224
2225        *cur_byte++ = param->ht_supported;
2226        memcpy(cur_byte, &param->ht_capa, sizeof(struct ieee80211_ht_cap));
2227        cur_byte += sizeof(struct ieee80211_ht_cap);
2228
2229        *cur_byte++ = param->flags_mask & 0xFF;
2230        *cur_byte++ = (param->flags_mask >> 8) & 0xFF;
2231
2232        *cur_byte++ = param->flags_set & 0xFF;
2233        *cur_byte++ = (param->flags_set >> 8) & 0xFF;
2234
2235        return cur_byte - buff;
2236}
2237
2238static void handle_add_station(struct work_struct *work)
2239{
2240        struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
2241        struct wilc_vif *vif = msg->vif;
2242        struct add_sta_param *param = &msg->body.add_sta_info;
2243        int result;
2244        struct wid wid;
2245        u8 *cur_byte;
2246
2247        wid.id = WID_ADD_STA;
2248        wid.type = WID_BIN;
2249        wid.size = WILC_ADD_STA_LENGTH + param->rates_len;
2250
2251        wid.val = kmalloc(wid.size, GFP_KERNEL);
2252        if (!wid.val)
2253                goto error;
2254
2255        cur_byte = wid.val;
2256        cur_byte += wilc_hif_pack_sta_param(cur_byte, param);
2257
2258        result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1,
2259                                      wilc_get_vif_idx(vif));
2260        if (result != 0)
2261                netdev_err(vif->ndev, "Failed to send add station\n");
2262
2263error:
2264        kfree(param->rates);
2265        kfree(wid.val);
2266        kfree(msg);
2267}
2268
2269static void handle_del_all_sta(struct work_struct *work)
2270{
2271        struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
2272        struct wilc_vif *vif = msg->vif;
2273        struct del_all_sta *param = &msg->body.del_all_sta_info;
2274        int result;
2275        struct wid wid;
2276        u8 *curr_byte;
2277        u8 i;
2278        u8 zero_buff[6] = {0};
2279
2280        wid.id = WID_DEL_ALL_STA;
2281        wid.type = WID_STR;
2282        wid.size = (param->assoc_sta * ETH_ALEN) + 1;
2283
2284        wid.val = kmalloc((param->assoc_sta * ETH_ALEN) + 1, GFP_KERNEL);
2285        if (!wid.val)
2286                goto error;
2287
2288        curr_byte = wid.val;
2289
2290        *(curr_byte++) = param->assoc_sta;
2291
2292        for (i = 0; i < MAX_NUM_STA; i++) {
2293                if (memcmp(param->del_all_sta[i], zero_buff, ETH_ALEN))
2294                        memcpy(curr_byte, param->del_all_sta[i], ETH_ALEN);
2295                else
2296                        continue;
2297
2298                curr_byte += ETH_ALEN;
2299        }
2300
2301        result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1,
2302                                      wilc_get_vif_idx(vif));
2303        if (result)
2304                netdev_err(vif->ndev, "Failed to send delete all station\n");
2305
2306error:
2307        kfree(wid.val);
2308
2309        /* free 'msg' data in caller */
2310        complete(&msg->work_comp);
2311}
2312
2313static void handle_del_station(struct work_struct *work)
2314{
2315        struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
2316        struct wilc_vif *vif = msg->vif;
2317        struct del_sta *param = &msg->body.del_sta_info;
2318        int result;
2319        struct wid wid;
2320
2321        wid.id = WID_REMOVE_STA;
2322        wid.type = WID_BIN;
2323        wid.size = ETH_ALEN;
2324
2325        wid.val = kmalloc(wid.size, GFP_KERNEL);
2326        if (!wid.val)
2327                goto error;
2328
2329        ether_addr_copy(wid.val, param->mac_addr);
2330
2331        result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1,
2332                                      wilc_get_vif_idx(vif));
2333        if (result)
2334                netdev_err(vif->ndev, "Failed to del station\n");
2335
2336error:
2337        kfree(wid.val);
2338        kfree(msg);
2339}
2340
2341static void handle_edit_station(struct work_struct *work)
2342{
2343        struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
2344        struct wilc_vif *vif = msg->vif;
2345        struct add_sta_param *param = &msg->body.edit_sta_info;
2346        int result;
2347        struct wid wid;
2348        u8 *cur_byte;
2349
2350        wid.id = WID_EDIT_STA;
2351        wid.type = WID_BIN;
2352        wid.size = WILC_ADD_STA_LENGTH + param->rates_len;
2353
2354        wid.val = kmalloc(wid.size, GFP_KERNEL);
2355        if (!wid.val)
2356                goto error;
2357
2358        cur_byte = wid.val;
2359        cur_byte += wilc_hif_pack_sta_param(cur_byte, param);
2360
2361        result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1,
2362                                      wilc_get_vif_idx(vif));
2363        if (result)
2364                netdev_err(vif->ndev, "Failed to send edit station\n");
2365
2366error:
2367        kfree(param->rates);
2368        kfree(wid.val);
2369        kfree(msg);
2370}
2371
2372static int handle_remain_on_chan(struct wilc_vif *vif,
2373                                 struct remain_ch *hif_remain_ch)
2374{
2375        int result;
2376        u8 remain_on_chan_flag;
2377        struct wid wid;
2378        struct host_if_drv *hif_drv = vif->hif_drv;
2379
2380        if (!hif_drv->remain_on_ch_pending) {
2381                hif_drv->remain_on_ch.arg = hif_remain_ch->arg;
2382                hif_drv->remain_on_ch.expired = hif_remain_ch->expired;
2383                hif_drv->remain_on_ch.ready = hif_remain_ch->ready;
2384                hif_drv->remain_on_ch.ch = hif_remain_ch->ch;
2385                hif_drv->remain_on_ch.id = hif_remain_ch->id;
2386        } else {
2387                hif_remain_ch->ch = hif_drv->remain_on_ch.ch;
2388        }
2389
2390        if (hif_drv->usr_scan_req.scan_result) {
2391                hif_drv->remain_on_ch_pending = 1;
2392                result = -EBUSY;
2393                goto error;
2394        }
2395        if (hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP) {
2396                result = -EBUSY;
2397                goto error;
2398        }
2399
2400        if (wilc_optaining_ip || wilc_connecting) {
2401                result = -EBUSY;
2402                goto error;
2403        }
2404
2405        remain_on_chan_flag = true;
2406        wid.id = WID_REMAIN_ON_CHAN;
2407        wid.type = WID_STR;
2408        wid.size = 2;
2409        wid.val = kmalloc(wid.size, GFP_KERNEL);
2410        if (!wid.val) {
2411                result = -ENOMEM;
2412                goto error;
2413        }
2414
2415        wid.val[0] = remain_on_chan_flag;
2416        wid.val[1] = (s8)hif_remain_ch->ch;
2417
2418        result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1,
2419                                      wilc_get_vif_idx(vif));
2420        kfree(wid.val);
2421        if (result != 0)
2422                netdev_err(vif->ndev, "Failed to set remain on channel\n");
2423
2424error:
2425        p2p_listen_state = 1;
2426        hif_drv->remain_on_ch_timer_vif = vif;
2427        mod_timer(&hif_drv->remain_on_ch_timer,
2428                  jiffies + msecs_to_jiffies(hif_remain_ch->duration));
2429
2430        if (hif_drv->remain_on_ch.ready)
2431                hif_drv->remain_on_ch.ready(hif_drv->remain_on_ch.arg);
2432
2433        if (hif_drv->remain_on_ch_pending)
2434                hif_drv->remain_on_ch_pending = 0;
2435
2436        return result;
2437}
2438
2439static void handle_register_frame(struct work_struct *work)
2440{
2441        struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
2442        struct wilc_vif *vif = msg->vif;
2443        struct reg_frame *hif_reg_frame = &msg->body.reg_frame;
2444        int result;
2445        struct wid wid;
2446        u8 *cur_byte;
2447
2448        wid.id = WID_REGISTER_FRAME;
2449        wid.type = WID_STR;
2450        wid.val = kmalloc(sizeof(u16) + 2, GFP_KERNEL);
2451        if (!wid.val)
2452                goto out;
2453
2454        cur_byte = wid.val;
2455
2456        *cur_byte++ = hif_reg_frame->reg;
2457        *cur_byte++ = hif_reg_frame->reg_id;
2458        memcpy(cur_byte, &hif_reg_frame->frame_type, sizeof(u16));
2459
2460        wid.size = sizeof(u16) + 2;
2461
2462        result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1,
2463                                      wilc_get_vif_idx(vif));
2464        kfree(wid.val);
2465        if (result)
2466                netdev_err(vif->ndev, "Failed to frame register\n");
2467
2468out:
2469        kfree(msg);
2470}
2471
2472static void handle_listen_state_expired(struct work_struct *work)
2473{
2474        struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
2475        struct wilc_vif *vif = msg->vif;
2476        struct remain_ch *hif_remain_ch = &msg->body.remain_on_ch;
2477        u8 remain_on_chan_flag;
2478        struct wid wid;
2479        int result;
2480        struct host_if_drv *hif_drv = vif->hif_drv;
2481
2482        if (p2p_listen_state) {
2483                remain_on_chan_flag = false;
2484                wid.id = WID_REMAIN_ON_CHAN;
2485                wid.type = WID_STR;
2486                wid.size = 2;
2487                wid.val = kmalloc(wid.size, GFP_KERNEL);
2488
2489                if (!wid.val)
2490                        goto free_msg;
2491
2492                wid.val[0] = remain_on_chan_flag;
2493                wid.val[1] = FALSE_FRMWR_CHANNEL;
2494
2495                result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1,
2496                                              wilc_get_vif_idx(vif));
2497                kfree(wid.val);
2498                if (result != 0) {
2499                        netdev_err(vif->ndev, "Failed to set remain channel\n");
2500                        goto free_msg;
2501                }
2502
2503                if (hif_drv->remain_on_ch.expired) {
2504                        hif_drv->remain_on_ch.expired(hif_drv->remain_on_ch.arg,
2505                                                      hif_remain_ch->id);
2506                }
2507                p2p_listen_state = 0;
2508        } else {
2509                netdev_dbg(vif->ndev, "Not in listen state\n");
2510        }
2511
2512free_msg:
2513        kfree(msg);
2514}
2515
2516static void listen_timer_cb(struct timer_list *t)
2517{
2518        struct host_if_drv *hif_drv = from_timer(hif_drv, t,
2519                                                      remain_on_ch_timer);
2520        struct wilc_vif *vif = hif_drv->remain_on_ch_timer_vif;
2521        int result;
2522        struct host_if_msg *msg;
2523
2524        del_timer(&vif->hif_drv->remain_on_ch_timer);
2525
2526        msg = wilc_alloc_work(vif, handle_listen_state_expired, false);
2527        if (IS_ERR(msg))
2528                return;
2529
2530        msg->body.remain_on_ch.id = vif->hif_drv->remain_on_ch.id;
2531
2532        result = wilc_enqueue_work(msg);
2533        if (result) {
2534                netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__);
2535                kfree(msg);
2536        }
2537}
2538
2539static void handle_power_management(struct work_struct *work)
2540{
2541        struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
2542        struct wilc_vif *vif = msg->vif;
2543        struct power_mgmt_param *pm_param = &msg->body.pwr_mgmt_info;
2544        int result;
2545        struct wid wid;
2546        s8 power_mode;
2547
2548        wid.id = WID_POWER_MANAGEMENT;
2549
2550        if (pm_param->enabled)
2551                power_mode = MIN_FAST_PS;
2552        else
2553                power_mode = NO_POWERSAVE;
2554
2555        wid.val = &power_mode;
2556        wid.size = sizeof(char);
2557
2558        result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1,
2559                                      wilc_get_vif_idx(vif));
2560        if (result)
2561                netdev_err(vif->ndev, "Failed to send power management\n");
2562        kfree(msg);
2563}
2564
2565static void handle_set_mcast_filter(struct work_struct *work)
2566{
2567        struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
2568        struct wilc_vif *vif = msg->vif;
2569        struct set_multicast *hif_set_mc = &msg->body.multicast_info;
2570        int result;
2571        struct wid wid;
2572        u8 *cur_byte;
2573
2574        wid.id = WID_SETUP_MULTICAST_FILTER;
2575        wid.type = WID_BIN;
2576        wid.size = sizeof(struct set_multicast) + (hif_set_mc->cnt * ETH_ALEN);
2577        wid.val = kmalloc(wid.size, GFP_KERNEL);
2578        if (!wid.val)
2579                goto error;
2580
2581        cur_byte = wid.val;
2582        *cur_byte++ = (hif_set_mc->enabled & 0xFF);
2583        *cur_byte++ = 0;
2584        *cur_byte++ = 0;
2585        *cur_byte++ = 0;
2586
2587        *cur_byte++ = (hif_set_mc->cnt & 0xFF);
2588        *cur_byte++ = ((hif_set_mc->cnt >> 8) & 0xFF);
2589        *cur_byte++ = ((hif_set_mc->cnt >> 16) & 0xFF);
2590        *cur_byte++ = ((hif_set_mc->cnt >> 24) & 0xFF);
2591
2592        if (hif_set_mc->cnt > 0)
2593                memcpy(cur_byte, wilc_multicast_mac_addr_list,
2594                       ((hif_set_mc->cnt) * ETH_ALEN));
2595
2596        result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1,
2597                                      wilc_get_vif_idx(vif));
2598        if (result)
2599                netdev_err(vif->ndev, "Failed to send setup multicast\n");
2600
2601error:
2602        kfree(wid.val);
2603        kfree(msg);
2604}
2605
2606static void handle_set_tx_pwr(struct work_struct *work)
2607{
2608        struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
2609        struct wilc_vif *vif = msg->vif;
2610        u8 tx_pwr = msg->body.tx_power.tx_pwr;
2611        int ret;
2612        struct wid wid;
2613
2614        wid.id = WID_TX_POWER;
2615        wid.type = WID_CHAR;
2616        wid.val = &tx_pwr;
2617        wid.size = sizeof(char);
2618
2619        ret = wilc_send_config_pkt(vif, SET_CFG, &wid, 1,
2620                                   wilc_get_vif_idx(vif));
2621        if (ret)
2622                netdev_err(vif->ndev, "Failed to set TX PWR\n");
2623        kfree(msg);
2624}
2625
2626/* Note: 'msg' will be free after using data */
2627static void handle_get_tx_pwr(struct work_struct *work)
2628{
2629        struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
2630        struct wilc_vif *vif = msg->vif;
2631        u8 *tx_pwr = &msg->body.tx_power.tx_pwr;
2632        int ret;
2633        struct wid wid;
2634
2635        wid.id = WID_TX_POWER;
2636        wid.type = WID_CHAR;
2637        wid.val = (s8 *)tx_pwr;
2638        wid.size = sizeof(char);
2639
2640        ret = wilc_send_config_pkt(vif, GET_CFG, &wid, 1,
2641                                   wilc_get_vif_idx(vif));
2642        if (ret)
2643                netdev_err(vif->ndev, "Failed to get TX PWR\n");
2644
2645        complete(&msg->work_comp);
2646}
2647
2648static void handle_scan_timer(struct work_struct *work)
2649{
2650        struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
2651
2652        handle_scan_done(msg->vif, SCAN_EVENT_ABORTED);
2653        kfree(msg);
2654}
2655
2656static void handle_remain_on_chan_work(struct work_struct *work)
2657{
2658        struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
2659
2660        handle_remain_on_chan(msg->vif, &msg->body.remain_on_ch);
2661        kfree(msg);
2662}
2663
2664static void handle_hif_exit_work(struct work_struct *work)
2665{
2666        struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
2667
2668        /* free 'msg' data in caller */
2669        complete(&msg->work_comp);
2670}
2671
2672static void handle_scan_complete(struct work_struct *work)
2673{
2674        struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
2675        struct wilc *wilc = msg->vif->wilc;
2676
2677        del_timer(&msg->vif->hif_drv->scan_timer);
2678
2679        if (!wilc_wlan_get_num_conn_ifcs(wilc))
2680                wilc_chip_sleep_manually(wilc);
2681
2682        handle_scan_done(msg->vif, SCAN_EVENT_DONE);
2683
2684        if (msg->vif->hif_drv->remain_on_ch_pending)
2685                handle_remain_on_chan(msg->vif, &msg->body.remain_on_ch);
2686        kfree(msg);
2687}
2688
2689static void timer_scan_cb(struct timer_list *t)
2690{
2691        struct host_if_drv *hif_drv = from_timer(hif_drv, t, scan_timer);
2692        struct wilc_vif *vif = hif_drv->scan_timer_vif;
2693        struct host_if_msg *msg;
2694        int result;
2695
2696        msg = wilc_alloc_work(vif, handle_scan_timer, false);
2697        if (IS_ERR(msg))
2698                return;
2699
2700        result = wilc_enqueue_work(msg);
2701        if (result)
2702                kfree(msg);
2703}
2704
2705static void timer_connect_cb(struct timer_list *t)
2706{
2707        struct host_if_drv *hif_drv = from_timer(hif_drv, t,
2708                                                      connect_timer);
2709        struct wilc_vif *vif = hif_drv->connect_timer_vif;
2710        struct host_if_msg *msg;
2711        int result;
2712
2713        msg = wilc_alloc_work(vif, handle_connect_timeout, false);
2714        if (IS_ERR(msg))
2715                return;
2716
2717        result = wilc_enqueue_work(msg);
2718        if (result)
2719                kfree(msg);
2720}
2721
2722int wilc_remove_wep_key(struct wilc_vif *vif, u8 index)
2723{
2724        int result;
2725        struct host_if_msg *msg;
2726        struct host_if_drv *hif_drv = vif->hif_drv;
2727
2728        if (!hif_drv) {
2729                result = -EFAULT;
2730                netdev_err(vif->ndev, "%s: hif driver is NULL", __func__);
2731                return result;
2732        }
2733
2734        msg = wilc_alloc_work(vif, handle_key, true);
2735        if (IS_ERR(msg))
2736                return PTR_ERR(msg);
2737
2738        msg->body.key_info.type = WEP;
2739        msg->body.key_info.action = REMOVEKEY;
2740        msg->body.key_info.attr.wep.index = index;
2741
2742        result = wilc_enqueue_work(msg);
2743        if (result)
2744                netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__);
2745        else
2746                wait_for_completion(&msg->work_comp);
2747
2748        kfree(msg);
2749        return result;
2750}
2751
2752int wilc_set_wep_default_keyid(struct wilc_vif *vif, u8 index)
2753{
2754        int result;
2755        struct host_if_msg *msg;
2756        struct host_if_drv *hif_drv = vif->hif_drv;
2757
2758        if (!hif_drv) {
2759                result = -EFAULT;
2760                netdev_err(vif->ndev, "%s: hif driver is NULL\n", __func__);
2761                return result;
2762        }
2763
2764        msg = wilc_alloc_work(vif, handle_key, true);
2765        if (IS_ERR(msg))
2766                return PTR_ERR(msg);
2767
2768        msg->body.key_info.type = WEP;
2769        msg->body.key_info.action = DEFAULTKEY;
2770        msg->body.key_info.attr.wep.index = index;
2771
2772        result = wilc_enqueue_work(msg);
2773        if (result)
2774                netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__);
2775        else
2776                wait_for_completion(&msg->work_comp);
2777
2778        kfree(msg);
2779        return result;
2780}
2781
2782int wilc_add_wep_key_bss_sta(struct wilc_vif *vif, const u8 *key, u8 len,
2783                             u8 index)
2784{
2785        int result;
2786        struct host_if_msg *msg;
2787        struct host_if_drv *hif_drv = vif->hif_drv;
2788
2789        if (!hif_drv) {
2790                netdev_err(vif->ndev, "%s: hif driver is NULL", __func__);
2791                return -EFAULT;
2792        }
2793
2794        msg = wilc_alloc_work(vif, handle_key, true);
2795        if (IS_ERR(msg))
2796                return PTR_ERR(msg);
2797
2798        msg->body.key_info.type = WEP;
2799        msg->body.key_info.action = ADDKEY;
2800        msg->body.key_info.attr.wep.key = kmemdup(key, len, GFP_KERNEL);
2801        if (!msg->body.key_info.attr.wep.key) {
2802                result = -ENOMEM;
2803                goto free_msg;
2804        }
2805
2806        msg->body.key_info.attr.wep.key_len = len;
2807        msg->body.key_info.attr.wep.index = index;
2808
2809        result = wilc_enqueue_work(msg);
2810        if (result)
2811                goto free_key;
2812
2813        wait_for_completion(&msg->work_comp);
2814
2815free_key:
2816        kfree(msg->body.key_info.attr.wep.key);
2817
2818free_msg:
2819        kfree(msg);
2820        return result;
2821}
2822
2823int wilc_add_wep_key_bss_ap(struct wilc_vif *vif, const u8 *key, u8 len,
2824                            u8 index, u8 mode, enum authtype auth_type)
2825{
2826        int result;
2827        struct host_if_msg *msg;
2828        struct host_if_drv *hif_drv = vif->hif_drv;
2829
2830        if (!hif_drv) {
2831                netdev_err(vif->ndev, "%s: hif driver is NULL\n", __func__);
2832                return -EFAULT;
2833        }
2834
2835        msg = wilc_alloc_work(vif, handle_key, true);
2836        if (IS_ERR(msg))
2837                return PTR_ERR(msg);
2838
2839        msg->body.key_info.type = WEP;
2840        msg->body.key_info.action = ADDKEY_AP;
2841        msg->body.key_info.attr.wep.key = kmemdup(key, len, GFP_KERNEL);
2842        if (!msg->body.key_info.attr.wep.key) {
2843                result = -ENOMEM;
2844                goto free_msg;
2845        }
2846
2847        msg->body.key_info.attr.wep.key_len = len;
2848        msg->body.key_info.attr.wep.index = index;
2849        msg->body.key_info.attr.wep.mode = mode;
2850        msg->body.key_info.attr.wep.auth_type = auth_type;
2851
2852        result = wilc_enqueue_work(msg);
2853        if (result)
2854                goto free_key;
2855
2856        wait_for_completion(&msg->work_comp);
2857
2858free_key:
2859        kfree(msg->body.key_info.attr.wep.key);
2860
2861free_msg:
2862        kfree(msg);
2863        return result;
2864}
2865
2866int wilc_add_ptk(struct wilc_vif *vif, const u8 *ptk, u8 ptk_key_len,
2867                 const u8 *mac_addr, const u8 *rx_mic, const u8 *tx_mic,
2868                 u8 mode, u8 cipher_mode, u8 index)
2869{
2870        int result;
2871        struct host_if_msg *msg;
2872        struct host_if_drv *hif_drv = vif->hif_drv;
2873        u8 key_len = ptk_key_len;
2874
2875        if (!hif_drv) {
2876                netdev_err(vif->ndev, "%s: hif driver is NULL", __func__);
2877                return -EFAULT;
2878        }
2879
2880        if (rx_mic)
2881                key_len += RX_MIC_KEY_LEN;
2882
2883        if (tx_mic)
2884                key_len += TX_MIC_KEY_LEN;
2885
2886        msg = wilc_alloc_work(vif, handle_key, true);
2887        if (IS_ERR(msg))
2888                return PTR_ERR(msg);
2889
2890        msg->body.key_info.type = WPA_PTK;
2891        if (mode == AP_MODE) {
2892                msg->body.key_info.action = ADDKEY_AP;
2893                msg->body.key_info.attr.wpa.index = index;
2894        }
2895        if (mode == STATION_MODE)
2896                msg->body.key_info.action = ADDKEY;
2897
2898        msg->body.key_info.attr.wpa.key = kmemdup(ptk, ptk_key_len, GFP_KERNEL);
2899        if (!msg->body.key_info.attr.wpa.key) {
2900                result = -ENOMEM;
2901                goto free_msg;
2902        }
2903
2904        if (rx_mic)
2905                memcpy(msg->body.key_info.attr.wpa.key + 16, rx_mic,
2906                       RX_MIC_KEY_LEN);
2907
2908        if (tx_mic)
2909                memcpy(msg->body.key_info.attr.wpa.key + 24, tx_mic,
2910                       TX_MIC_KEY_LEN);
2911
2912        msg->body.key_info.attr.wpa.key_len = key_len;
2913        msg->body.key_info.attr.wpa.mac_addr = mac_addr;
2914        msg->body.key_info.attr.wpa.mode = cipher_mode;
2915
2916        result = wilc_enqueue_work(msg);
2917        if (result) {
2918                netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__);
2919                goto free_key;
2920        }
2921
2922        wait_for_completion(&msg->work_comp);
2923
2924free_key:
2925        kfree(msg->body.key_info.attr.wpa.key);
2926
2927free_msg:
2928        kfree(msg);
2929        return result;
2930}
2931
2932int wilc_add_rx_gtk(struct wilc_vif *vif, const u8 *rx_gtk, u8 gtk_key_len,
2933                    u8 index, u32 key_rsc_len, const u8 *key_rsc,
2934                    const u8 *rx_mic, const u8 *tx_mic, u8 mode,
2935                    u8 cipher_mode)
2936{
2937        int result;
2938        struct host_if_msg *msg;
2939        struct host_if_drv *hif_drv = vif->hif_drv;
2940        u8 key_len = gtk_key_len;
2941
2942        if (!hif_drv) {
2943                netdev_err(vif->ndev, "%s: hif driver is NULL", __func__);
2944                return -EFAULT;
2945        }
2946
2947        msg = wilc_alloc_work(vif, handle_key, true);
2948        if (IS_ERR(msg))
2949                return PTR_ERR(msg);
2950
2951        if (rx_mic)
2952                key_len += RX_MIC_KEY_LEN;
2953
2954        if (tx_mic)
2955                key_len += TX_MIC_KEY_LEN;
2956
2957        if (key_rsc) {
2958                msg->body.key_info.attr.wpa.seq = kmemdup(key_rsc,
2959                                                          key_rsc_len,
2960                                                          GFP_KERNEL);
2961                if (!msg->body.key_info.attr.wpa.seq) {
2962                        result = -ENOMEM;
2963                        goto free_msg;
2964                }
2965        }
2966
2967        msg->body.key_info.type = WPA_RX_GTK;
2968
2969        if (mode == AP_MODE) {
2970                msg->body.key_info.action = ADDKEY_AP;
2971                msg->body.key_info.attr.wpa.mode = cipher_mode;
2972        }
2973        if (mode == STATION_MODE)
2974                msg->body.key_info.action = ADDKEY;
2975
2976        msg->body.key_info.attr.wpa.key = kmemdup(rx_gtk, key_len, GFP_KERNEL);
2977        if (!msg->body.key_info.attr.wpa.key) {
2978                result = -ENOMEM;
2979                goto free_seq;
2980        }
2981
2982        if (rx_mic)
2983                memcpy(msg->body.key_info.attr.wpa.key + 16, rx_mic,
2984                       RX_MIC_KEY_LEN);
2985
2986        if (tx_mic)
2987                memcpy(msg->body.key_info.attr.wpa.key + 24, tx_mic,
2988                       TX_MIC_KEY_LEN);
2989
2990        msg->body.key_info.attr.wpa.index = index;
2991        msg->body.key_info.attr.wpa.key_len = key_len;
2992        msg->body.key_info.attr.wpa.seq_len = key_rsc_len;
2993
2994        result = wilc_enqueue_work(msg);
2995        if (result) {
2996                netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__);
2997                goto free_key;
2998        }
2999
3000        wait_for_completion(&msg->work_comp);
3001
3002free_key:
3003        kfree(msg->body.key_info.attr.wpa.key);
3004
3005free_seq:
3006        kfree(msg->body.key_info.attr.wpa.seq);
3007
3008free_msg:
3009        kfree(msg);
3010        return result;
3011}
3012
3013int wilc_set_pmkid_info(struct wilc_vif *vif,
3014                        struct host_if_pmkid_attr *pmkid)
3015{
3016        int result;
3017        struct host_if_msg *msg;
3018        int i;
3019
3020        msg = wilc_alloc_work(vif, handle_key, false);
3021        if (IS_ERR(msg))
3022                return PTR_ERR(msg);
3023
3024        msg->body.key_info.type = PMKSA;
3025        msg->body.key_info.action = ADDKEY;
3026
3027        for (i = 0; i < pmkid->numpmkid; i++) {
3028                memcpy(msg->body.key_info.attr.pmkid.pmkidlist[i].bssid,
3029                       &pmkid->pmkidlist[i].bssid, ETH_ALEN);
3030                memcpy(msg->body.key_info.attr.pmkid.pmkidlist[i].pmkid,
3031                       &pmkid->pmkidlist[i].pmkid, PMKID_LEN);
3032        }
3033
3034        result = wilc_enqueue_work(msg);
3035        if (result) {
3036                netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__);
3037                kfree(msg);
3038        }
3039
3040        return result;
3041}
3042
3043int wilc_get_mac_address(struct wilc_vif *vif, u8 *mac_addr)
3044{
3045        int result;
3046        struct host_if_msg *msg;
3047
3048        msg = wilc_alloc_work(vif, handle_get_mac_address, true);
3049        if (IS_ERR(msg))
3050                return PTR_ERR(msg);
3051
3052        msg->body.get_mac_info.mac_addr = mac_addr;
3053
3054        result = wilc_enqueue_work(msg);
3055        if (result)
3056                netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__);
3057        else
3058                wait_for_completion(&msg->work_comp);
3059
3060        kfree(msg);
3061
3062        return result;
3063}
3064
3065int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ssid,
3066                      size_t ssid_len, const u8 *ies, size_t ies_len,
3067                      wilc_connect_result connect_result, void *user_arg,
3068                      u8 security, enum authtype auth_type,
3069                      u8 channel, void *join_params)
3070{
3071        int result;
3072        struct host_if_msg *msg;
3073        struct host_if_drv *hif_drv = vif->hif_drv;
3074
3075        if (!hif_drv || !connect_result) {
3076                netdev_err(vif->ndev,
3077                           "%s: hif driver or connect result is NULL",
3078                           __func__);
3079                return -EFAULT;
3080        }
3081
3082        if (!join_params) {
3083                netdev_err(vif->ndev, "%s: joinparams is NULL\n", __func__);
3084                return -EFAULT;
3085        }
3086
3087        msg = wilc_alloc_work(vif, handle_connect, false);
3088        if (IS_ERR(msg))
3089                return PTR_ERR(msg);
3090
3091        msg->body.con_info.security = security;
3092        msg->body.con_info.auth_type = auth_type;
3093        msg->body.con_info.ch = channel;
3094        msg->body.con_info.result = connect_result;
3095        msg->body.con_info.arg = user_arg;
3096        msg->body.con_info.params = join_params;
3097
3098        if (bssid) {
3099                msg->body.con_info.bssid = kmemdup(bssid, 6, GFP_KERNEL);
3100                if (!msg->body.con_info.bssid) {
3101                        result = -ENOMEM;
3102                        goto free_msg;
3103                }
3104        }
3105
3106        if (ssid) {
3107                msg->body.con_info.ssid_len = ssid_len;
3108                msg->body.con_info.ssid = kmemdup(ssid, ssid_len, GFP_KERNEL);
3109                if (!msg->body.con_info.ssid) {
3110                        result = -ENOMEM;
3111                        goto free_bssid;
3112                }
3113        }
3114
3115        if (ies) {
3116                msg->body.con_info.ies_len = ies_len;
3117                msg->body.con_info.ies = kmemdup(ies, ies_len, GFP_KERNEL);
3118                if (!msg->body.con_info.ies) {
3119                        result = -ENOMEM;
3120                        goto free_ssid;
3121                }
3122        }
3123        if (hif_drv->hif_state < HOST_IF_CONNECTING)
3124                hif_drv->hif_state = HOST_IF_CONNECTING;
3125
3126        result = wilc_enqueue_work(msg);
3127        if (result) {
3128                netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__);
3129                goto free_ies;
3130        }
3131
3132        hif_drv->connect_timer_vif = vif;
3133        mod_timer(&hif_drv->connect_timer,
3134                  jiffies + msecs_to_jiffies(HOST_IF_CONNECT_TIMEOUT));
3135
3136        return 0;
3137
3138free_ies:
3139        kfree(msg->body.con_info.ies);
3140
3141free_ssid:
3142        kfree(msg->body.con_info.ssid);
3143
3144free_bssid:
3145        kfree(msg->body.con_info.bssid);
3146
3147free_msg:
3148        kfree(msg);
3149        return result;
3150}
3151
3152int wilc_disconnect(struct wilc_vif *vif, u16 reason_code)
3153{
3154        int result;
3155        struct host_if_msg *msg;
3156        struct host_if_drv *hif_drv = vif->hif_drv;
3157
3158        if (!hif_drv) {
3159                netdev_err(vif->ndev, "%s: hif driver is NULL", __func__);
3160                return -EFAULT;
3161        }
3162
3163        msg = wilc_alloc_work(vif, handle_disconnect, true);
3164        if (IS_ERR(msg))
3165                return PTR_ERR(msg);
3166
3167        result = wilc_enqueue_work(msg);
3168        if (result)
3169                netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__);
3170        else
3171                wait_for_completion(&msg->work_comp);
3172
3173        kfree(msg);
3174        return result;
3175}
3176
3177int wilc_set_mac_chnl_num(struct wilc_vif *vif, u8 channel)
3178{
3179        int result;
3180        struct host_if_msg *msg;
3181
3182        msg = wilc_alloc_work(vif, handle_set_channel, false);
3183        if (IS_ERR(msg))
3184                return PTR_ERR(msg);
3185
3186        msg->body.channel_info.set_ch = channel;
3187
3188        result = wilc_enqueue_work(msg);
3189        if (result) {
3190                netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__);
3191                kfree(msg);
3192        }
3193
3194        return result;
3195}
3196
3197int wilc_set_wfi_drv_handler(struct wilc_vif *vif, int index, u8 mode,
3198                             u8 ifc_id)
3199{
3200        int result;
3201        struct host_if_msg *msg;
3202
3203        msg = wilc_alloc_work(vif, handle_set_wfi_drv_handler, false);
3204        if (IS_ERR(msg))
3205                return PTR_ERR(msg);
3206
3207        msg->body.drv.handler = index;
3208        msg->body.drv.mode = mode;
3209        msg->body.drv.name = ifc_id;
3210
3211        result = wilc_enqueue_work(msg);
3212        if (result) {
3213                netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__);
3214                kfree(msg);
3215        }
3216
3217        return result;
3218}
3219
3220int wilc_set_operation_mode(struct wilc_vif *vif, u32 mode)
3221{
3222        int result;
3223        struct host_if_msg *msg;
3224
3225        msg  = wilc_alloc_work(vif, handle_set_operation_mode, false);
3226        if (IS_ERR(msg))
3227                return PTR_ERR(msg);
3228
3229        msg->body.mode.mode = mode;
3230        result = wilc_enqueue_work(msg);
3231        if (result) {
3232                netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__);
3233                kfree(msg);
3234        }
3235
3236        return result;
3237}
3238
3239s32 wilc_get_inactive_time(struct wilc_vif *vif, const u8 *mac,
3240                           u32 *out_val)
3241{
3242        s32 result;
3243        struct host_if_msg *msg;
3244        struct host_if_drv *hif_drv = vif->hif_drv;
3245
3246        if (!hif_drv) {
3247                netdev_err(vif->ndev, "%s: hif driver is NULL", __func__);
3248                return -EFAULT;
3249        }
3250
3251        msg = wilc_alloc_work(vif, handle_get_inactive_time, true);
3252        if (IS_ERR(msg))
3253                return PTR_ERR(msg);
3254
3255        memcpy(msg->body.mac_info.mac, mac, ETH_ALEN);
3256
3257        result = wilc_enqueue_work(msg);
3258        if (result)
3259                netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__);
3260        else
3261                wait_for_completion(&msg->work_comp);
3262
3263        *out_val = msg->body.mac_info.inactive_time;
3264        kfree(msg);
3265
3266        return result;
3267}
3268
3269int wilc_get_rssi(struct wilc_vif *vif, s8 *rssi_level)
3270{
3271        int result;
3272        struct host_if_msg *msg;
3273
3274        if (!rssi_level) {
3275                netdev_err(vif->ndev, "%s: RSSI level is NULL\n", __func__);
3276                return -EFAULT;
3277        }
3278
3279        msg = wilc_alloc_work(vif, handle_get_rssi, true);
3280        if (IS_ERR(msg))
3281                return PTR_ERR(msg);
3282
3283        msg->body.data = kzalloc(sizeof(s8), GFP_KERNEL);
3284        if (!msg->body.data) {
3285                kfree(msg);
3286                return -ENOMEM;
3287        }
3288
3289        result = wilc_enqueue_work(msg);
3290        if (result) {
3291                netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__);
3292        } else {
3293                wait_for_completion(&msg->work_comp);
3294                *rssi_level = *msg->body.data;
3295        }
3296
3297        kfree(msg->body.data);
3298        kfree(msg);
3299
3300        return result;
3301}
3302
3303int
3304wilc_get_statistics(struct wilc_vif *vif, struct rf_info *stats, bool is_sync)
3305{
3306        int result;
3307        struct host_if_msg *msg;
3308
3309        msg = wilc_alloc_work(vif, handle_get_statistics, is_sync);
3310        if (IS_ERR(msg))
3311                return PTR_ERR(msg);
3312
3313        msg->body.data = (char *)stats;
3314
3315        result = wilc_enqueue_work(msg);
3316        if (result) {
3317                netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__);
3318                kfree(msg);
3319                return result;
3320        }
3321
3322        if (is_sync) {
3323                wait_for_completion(&msg->work_comp);
3324                kfree(msg);
3325        }
3326
3327        return result;
3328}
3329
3330int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type,
3331              u8 *ch_freq_list, u8 ch_list_len, const u8 *ies,
3332              size_t ies_len, wilc_scan_result scan_result, void *user_arg,
3333              struct hidden_network *hidden_network)
3334{
3335        int result;
3336        struct host_if_msg *msg;
3337        struct scan_attr *scan_info;
3338        struct host_if_drv *hif_drv = vif->hif_drv;
3339
3340        if (!hif_drv || !scan_result) {
3341                netdev_err(vif->ndev, "hif_drv or scan_result = NULL\n");
3342                return -EFAULT;
3343        }
3344
3345        msg = wilc_alloc_work(vif, handle_scan, false);
3346        if (IS_ERR(msg))
3347                return PTR_ERR(msg);
3348
3349        scan_info = &msg->body.scan_info;
3350
3351        if (hidden_network) {
3352                scan_info->hidden_network.net_info = hidden_network->net_info;
3353                scan_info->hidden_network.n_ssids = hidden_network->n_ssids;
3354        }
3355
3356        scan_info->src = scan_source;
3357        scan_info->type = scan_type;
3358        scan_info->result = scan_result;
3359        scan_info->arg = user_arg;
3360
3361        scan_info->ch_list_len = ch_list_len;
3362        scan_info->ch_freq_list = kmemdup(ch_freq_list,
3363                                          ch_list_len,
3364                                          GFP_KERNEL);
3365        if (!scan_info->ch_freq_list) {
3366                result = -ENOMEM;
3367                goto free_msg;
3368        }
3369
3370        scan_info->ies_len = ies_len;
3371        scan_info->ies = kmemdup(ies, ies_len, GFP_KERNEL);
3372        if (!scan_info->ies) {
3373                result = -ENOMEM;
3374                goto free_freq_list;
3375        }
3376
3377        result = wilc_enqueue_work(msg);
3378        if (result) {
3379                netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__);
3380                goto free_ies;
3381        }
3382
3383        hif_drv->scan_timer_vif = vif;
3384        mod_timer(&hif_drv->scan_timer,
3385                  jiffies + msecs_to_jiffies(HOST_IF_SCAN_TIMEOUT));
3386
3387        return 0;
3388
3389free_ies:
3390        kfree(scan_info->ies);
3391
3392free_freq_list:
3393        kfree(scan_info->ch_freq_list);
3394
3395free_msg:
3396        kfree(msg);
3397        return result;
3398}
3399
3400int wilc_hif_set_cfg(struct wilc_vif *vif,
3401                     struct cfg_param_attr *cfg_param)
3402{
3403        struct host_if_msg *msg;
3404        struct host_if_drv *hif_drv = vif->hif_drv;
3405        int result;
3406
3407        if (!hif_drv) {
3408                netdev_err(vif->ndev, "%s: hif driver is NULL", __func__);
3409                return -EFAULT;
3410        }
3411
3412        msg = wilc_alloc_work(vif, handle_cfg_param, false);
3413        if (IS_ERR(msg))
3414                return PTR_ERR(msg);
3415
3416        msg->body.cfg_info = *cfg_param;
3417        result = wilc_enqueue_work(msg);
3418        if (result)
3419                kfree(msg);
3420
3421        return result;
3422}
3423
3424static void get_periodic_rssi(struct timer_list *unused)
3425{
3426        struct wilc_vif *vif = periodic_rssi_vif;
3427
3428        if (!vif->hif_drv) {
3429                netdev_err(vif->ndev, "%s: hif driver is NULL", __func__);
3430                return;
3431        }
3432
3433        if (vif->hif_drv->hif_state == HOST_IF_CONNECTED)
3434                wilc_get_statistics(vif, &vif->wilc->dummy_statistics, false);
3435
3436        mod_timer(&periodic_rssi, jiffies + msecs_to_jiffies(5000));
3437}
3438
3439int wilc_init(struct net_device *dev, struct host_if_drv **hif_drv_handler)
3440{
3441        struct host_if_drv *hif_drv;
3442        struct wilc_vif *vif = netdev_priv(dev);
3443        struct wilc *wilc = vif->wilc;
3444        int i;
3445
3446        hif_drv  = kzalloc(sizeof(*hif_drv), GFP_KERNEL);
3447        if (!hif_drv)
3448                return -ENOMEM;
3449
3450        *hif_drv_handler = hif_drv;
3451        for (i = 0; i < wilc->vif_num; i++)
3452                if (dev == wilc->vif[i]->ndev) {
3453                        wilc->vif[i]->hif_drv = hif_drv;
3454                        hif_drv->driver_handler_id = i + 1;
3455                        break;
3456                }
3457
3458        wilc_optaining_ip = false;
3459
3460        if (clients_count == 0) {
3461                init_completion(&hif_driver_comp);
3462                mutex_init(&hif_deinit_lock);
3463        }
3464
3465        if (clients_count == 0) {
3466                hif_workqueue = create_singlethread_workqueue("WILC_wq");
3467                if (!hif_workqueue) {
3468                        netdev_err(vif->ndev, "Failed to create workqueue\n");
3469                        kfree(hif_drv);
3470                        return -ENOMEM;
3471                }
3472
3473                periodic_rssi_vif = vif;
3474                timer_setup(&periodic_rssi, get_periodic_rssi, 0);
3475                mod_timer(&periodic_rssi, jiffies + msecs_to_jiffies(5000));
3476        }
3477
3478        timer_setup(&hif_drv->scan_timer, timer_scan_cb, 0);
3479        timer_setup(&hif_drv->connect_timer, timer_connect_cb, 0);
3480        timer_setup(&hif_drv->remain_on_ch_timer, listen_timer_cb, 0);
3481
3482        mutex_init(&hif_drv->cfg_values_lock);
3483        mutex_lock(&hif_drv->cfg_values_lock);
3484
3485        hif_drv->hif_state = HOST_IF_IDLE;
3486        hif_drv->cfg_values.site_survey_enabled = SITE_SURVEY_OFF;
3487        hif_drv->cfg_values.scan_source = DEFAULT_SCAN;
3488        hif_drv->cfg_values.active_scan_time = ACTIVE_SCAN_TIME;
3489        hif_drv->cfg_values.passive_scan_time = PASSIVE_SCAN_TIME;
3490        hif_drv->cfg_values.curr_tx_rate = AUTORATE;
3491
3492        hif_drv->p2p_timeout = 0;
3493
3494        mutex_unlock(&hif_drv->cfg_values_lock);
3495
3496        clients_count++;
3497
3498        return 0;
3499}
3500
3501int wilc_deinit(struct wilc_vif *vif)
3502{
3503        int result = 0;
3504        struct host_if_drv *hif_drv = vif->hif_drv;
3505
3506        if (!hif_drv) {
3507                netdev_err(vif->ndev, "%s: hif driver is NULL", __func__);
3508                return -EFAULT;
3509        }
3510
3511        mutex_lock(&hif_deinit_lock);
3512
3513        terminated_handle = hif_drv;
3514
3515        del_timer_sync(&hif_drv->scan_timer);
3516        del_timer_sync(&hif_drv->connect_timer);
3517        del_timer_sync(&periodic_rssi);
3518        del_timer_sync(&hif_drv->remain_on_ch_timer);
3519
3520        wilc_set_wfi_drv_handler(vif, 0, 0, 0);
3521        wait_for_completion(&hif_driver_comp);
3522
3523        if (hif_drv->usr_scan_req.scan_result) {
3524                hif_drv->usr_scan_req.scan_result(SCAN_EVENT_ABORTED, NULL,
3525                                                  hif_drv->usr_scan_req.arg,
3526                                                  NULL);
3527                hif_drv->usr_scan_req.scan_result = NULL;
3528        }
3529
3530        hif_drv->hif_state = HOST_IF_IDLE;
3531
3532        if (clients_count == 1) {
3533                struct host_if_msg *msg;
3534
3535                msg = wilc_alloc_work(vif, handle_hif_exit_work, true);
3536                if (!IS_ERR(msg)) {
3537                        result = wilc_enqueue_work(msg);
3538                        if (result)
3539                                netdev_err(vif->ndev, "deinit : Error(%d)\n",
3540                                           result);
3541                        else
3542                                wait_for_completion(&msg->work_comp);
3543                        kfree(msg);
3544                }
3545                destroy_workqueue(hif_workqueue);
3546        }
3547
3548        kfree(hif_drv);
3549
3550        clients_count--;
3551        terminated_handle = NULL;
3552        mutex_unlock(&hif_deinit_lock);
3553        return result;
3554}
3555
3556void wilc_network_info_received(struct wilc *wilc, u8 *buffer, u32 length)
3557{
3558        int result;
3559        struct host_if_msg *msg;
3560        int id;
3561        struct host_if_drv *hif_drv;
3562        struct wilc_vif *vif;
3563
3564        id = buffer[length - 4];
3565        id |= (buffer[length - 3] << 8);
3566        id |= (buffer[length - 2] << 16);
3567        id |= (buffer[length - 1] << 24);
3568        vif = wilc_get_vif_from_idx(wilc, id);
3569        if (!vif)
3570                return;
3571        hif_drv = vif->hif_drv;
3572
3573        if (!hif_drv || hif_drv == terminated_handle) {
3574                netdev_err(vif->ndev, "driver not init[%p]\n", hif_drv);
3575                return;
3576        }
3577
3578        msg = wilc_alloc_work(vif, handle_rcvd_ntwrk_info, false);
3579        if (IS_ERR(msg))
3580                return;
3581
3582        msg->body.net_info.len = length;
3583        msg->body.net_info.buffer = kmemdup(buffer, length, GFP_KERNEL);
3584        if (!msg->body.net_info.buffer) {
3585                kfree(msg);
3586                return;
3587        }
3588
3589        result = wilc_enqueue_work(msg);
3590        if (result) {
3591                netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__);
3592                kfree(msg->body.net_info.buffer);
3593                kfree(msg);
3594        }
3595}
3596
3597void wilc_gnrl_async_info_received(struct wilc *wilc, u8 *buffer, u32 length)
3598{
3599        int result;
3600        struct host_if_msg *msg;
3601        int id;
3602        struct host_if_drv *hif_drv;
3603        struct wilc_vif *vif;
3604
3605        mutex_lock(&hif_deinit_lock);
3606
3607        id = buffer[length - 4];
3608        id |= (buffer[length - 3] << 8);
3609        id |= (buffer[length - 2] << 16);
3610        id |= (buffer[length - 1] << 24);
3611        vif = wilc_get_vif_from_idx(wilc, id);
3612        if (!vif) {
3613                mutex_unlock(&hif_deinit_lock);
3614                return;
3615        }
3616
3617        hif_drv = vif->hif_drv;
3618
3619        if (!hif_drv || hif_drv == terminated_handle) {
3620                mutex_unlock(&hif_deinit_lock);
3621                return;
3622        }
3623
3624        if (!hif_drv->usr_conn_req.conn_result) {
3625                netdev_err(vif->ndev, "%s: conn_result is NULL\n", __func__);
3626                mutex_unlock(&hif_deinit_lock);
3627                return;
3628        }
3629
3630        msg = wilc_alloc_work(vif, handle_rcvd_gnrl_async_info, false);
3631        if (IS_ERR(msg)) {
3632                mutex_unlock(&hif_deinit_lock);
3633                return;
3634        }
3635
3636        msg->body.async_info.len = length;
3637        msg->body.async_info.buffer = kmemdup(buffer, length, GFP_KERNEL);
3638        if (!msg->body.async_info.buffer) {
3639                kfree(msg);
3640                mutex_unlock(&hif_deinit_lock);
3641                return;
3642        }
3643
3644        result = wilc_enqueue_work(msg);
3645        if (result) {
3646                netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__);
3647                kfree(msg->body.async_info.buffer);
3648                kfree(msg);
3649        }
3650
3651        mutex_unlock(&hif_deinit_lock);
3652}
3653
3654void wilc_scan_complete_received(struct wilc *wilc, u8 *buffer, u32 length)
3655{
3656        int result;
3657        int id;
3658        struct host_if_drv *hif_drv;
3659        struct wilc_vif *vif;
3660
3661        id = buffer[length - 4];
3662        id |= buffer[length - 3] << 8;
3663        id |= buffer[length - 2] << 16;
3664        id |= buffer[length - 1] << 24;
3665        vif = wilc_get_vif_from_idx(wilc, id);
3666        if (!vif)
3667                return;
3668        hif_drv = vif->hif_drv;
3669
3670        if (!hif_drv || hif_drv == terminated_handle)
3671                return;
3672
3673        if (hif_drv->usr_scan_req.scan_result) {
3674                struct host_if_msg *msg;
3675
3676                msg = wilc_alloc_work(vif, handle_scan_complete, false);
3677                if (IS_ERR(msg))
3678                        return;
3679
3680                result = wilc_enqueue_work(msg);
3681                if (result) {
3682                        netdev_err(vif->ndev, "%s: enqueue work failed\n",
3683                                   __func__);
3684                        kfree(msg);
3685                }
3686        }
3687}
3688
3689int wilc_remain_on_channel(struct wilc_vif *vif, u32 session_id,
3690                           u32 duration, u16 chan,
3691                           wilc_remain_on_chan_expired expired,
3692                           wilc_remain_on_chan_ready ready,
3693                           void *user_arg)
3694{
3695        int result;
3696        struct host_if_msg *msg;
3697
3698        msg = wilc_alloc_work(vif, handle_remain_on_chan_work, false);
3699        if (IS_ERR(msg))
3700                return PTR_ERR(msg);
3701
3702        msg->body.remain_on_ch.ch = chan;
3703        msg->body.remain_on_ch.expired = expired;
3704        msg->body.remain_on_ch.ready = ready;
3705        msg->body.remain_on_ch.arg = user_arg;
3706        msg->body.remain_on_ch.duration = duration;
3707        msg->body.remain_on_ch.id = session_id;
3708
3709        result = wilc_enqueue_work(msg);
3710        if (result) {
3711                netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__);
3712                kfree(msg);
3713        }
3714
3715        return result;
3716}
3717
3718int wilc_listen_state_expired(struct wilc_vif *vif, u32 session_id)
3719{
3720        int result;
3721        struct host_if_msg *msg;
3722        struct host_if_drv *hif_drv = vif->hif_drv;
3723
3724        if (!hif_drv) {
3725                netdev_err(vif->ndev, "%s: hif driver is NULL", __func__);
3726                return -EFAULT;
3727        }
3728
3729        del_timer(&hif_drv->remain_on_ch_timer);
3730
3731        msg = wilc_alloc_work(vif, handle_listen_state_expired, false);
3732        if (IS_ERR(msg))
3733                return PTR_ERR(msg);
3734
3735        msg->body.remain_on_ch.id = session_id;
3736
3737        result = wilc_enqueue_work(msg);
3738        if (result) {
3739                netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__);
3740                kfree(msg);
3741        }
3742
3743        return result;
3744}
3745
3746int wilc_frame_register(struct wilc_vif *vif, u16 frame_type, bool reg)
3747{
3748        int result;
3749        struct host_if_msg *msg;
3750
3751        msg = wilc_alloc_work(vif, handle_register_frame, false);
3752        if (IS_ERR(msg))
3753                return PTR_ERR(msg);
3754
3755        switch (frame_type) {
3756        case ACTION:
3757                msg->body.reg_frame.reg_id = ACTION_FRM_IDX;
3758                break;
3759
3760        case PROBE_REQ:
3761                msg->body.reg_frame.reg_id = PROBE_REQ_IDX;
3762                break;
3763
3764        default:
3765                break;
3766        }
3767        msg->body.reg_frame.frame_type = frame_type;
3768        msg->body.reg_frame.reg = reg;
3769
3770        result = wilc_enqueue_work(msg);
3771        if (result) {
3772                netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__);
3773                kfree(msg);
3774        }
3775
3776        return result;
3777}
3778
3779int wilc_add_beacon(struct wilc_vif *vif, u32 interval, u32 dtim_period,
3780                    u32 head_len, u8 *head, u32 tail_len, u8 *tail)
3781{
3782        int result;
3783        struct host_if_msg *msg;
3784        struct beacon_attr *beacon_info;
3785
3786        msg = wilc_alloc_work(vif, handle_add_beacon, false);
3787        if (IS_ERR(msg))
3788                return PTR_ERR(msg);
3789
3790        beacon_info = &msg->body.beacon_info;
3791        beacon_info->interval = interval;
3792        beacon_info->dtim_period = dtim_period;
3793        beacon_info->head_len = head_len;
3794        beacon_info->head = kmemdup(head, head_len, GFP_KERNEL);
3795        if (!beacon_info->head) {
3796                result = -ENOMEM;
3797                goto error;
3798        }
3799        beacon_info->tail_len = tail_len;
3800
3801        if (tail_len > 0) {
3802                beacon_info->tail = kmemdup(tail, tail_len, GFP_KERNEL);
3803                if (!beacon_info->tail) {
3804                        result = -ENOMEM;
3805                        goto error;
3806                }
3807        } else {
3808                beacon_info->tail = NULL;
3809        }
3810
3811        result = wilc_enqueue_work(msg);
3812        if (result)
3813                netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__);
3814
3815error:
3816        if (result) {
3817                kfree(beacon_info->head);
3818                kfree(beacon_info->tail);
3819                kfree(msg);
3820        }
3821
3822        return result;
3823}
3824
3825int wilc_del_beacon(struct wilc_vif *vif)
3826{
3827        int result;
3828        struct host_if_msg *msg;
3829
3830        msg = wilc_alloc_work(vif, handle_del_beacon, false);
3831        if (IS_ERR(msg))
3832                return PTR_ERR(msg);
3833
3834        result = wilc_enqueue_work(msg);
3835        if (result) {
3836                netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__);
3837                kfree(msg);
3838        }
3839
3840        return result;
3841}
3842
3843int wilc_add_station(struct wilc_vif *vif, struct add_sta_param *sta_param)
3844{
3845        int result;
3846        struct host_if_msg *msg;
3847        struct add_sta_param *add_sta_info;
3848
3849        msg = wilc_alloc_work(vif, handle_add_station, false);
3850        if (IS_ERR(msg))
3851                return PTR_ERR(msg);
3852
3853        add_sta_info = &msg->body.add_sta_info;
3854        memcpy(add_sta_info, sta_param, sizeof(struct add_sta_param));
3855        if (add_sta_info->rates_len > 0) {
3856                add_sta_info->rates = kmemdup(sta_param->rates,
3857                                              add_sta_info->rates_len,
3858                                              GFP_KERNEL);
3859                if (!add_sta_info->rates) {
3860                        kfree(msg);
3861                        return -ENOMEM;
3862                }
3863        }
3864
3865        result = wilc_enqueue_work(msg);
3866        if (result) {
3867                netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__);
3868                kfree(add_sta_info->rates);
3869                kfree(msg);
3870        }
3871        return result;
3872}
3873
3874int wilc_del_station(struct wilc_vif *vif, const u8 *mac_addr)
3875{
3876        int result;
3877        struct host_if_msg *msg;
3878        struct del_sta *del_sta_info;
3879
3880        msg = wilc_alloc_work(vif, handle_del_station, false);
3881        if (IS_ERR(msg))
3882                return PTR_ERR(msg);
3883
3884        del_sta_info = &msg->body.del_sta_info;
3885
3886        if (!mac_addr)
3887                eth_broadcast_addr(del_sta_info->mac_addr);
3888        else
3889                memcpy(del_sta_info->mac_addr, mac_addr, ETH_ALEN);
3890
3891        result = wilc_enqueue_work(msg);
3892        if (result) {
3893                netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__);
3894                kfree(msg);
3895        }
3896        return result;
3897}
3898
3899int wilc_del_allstation(struct wilc_vif *vif, u8 mac_addr[][ETH_ALEN])
3900{
3901        int result;
3902        struct host_if_msg *msg;
3903        struct del_all_sta *del_all_sta_info;
3904        u8 zero_addr[ETH_ALEN] = {0};
3905        int i;
3906        u8 assoc_sta = 0;
3907
3908        msg = wilc_alloc_work(vif, handle_del_all_sta, true);
3909        if (IS_ERR(msg))
3910                return PTR_ERR(msg);
3911
3912        del_all_sta_info = &msg->body.del_all_sta_info;
3913
3914        for (i = 0; i < MAX_NUM_STA; i++) {
3915                if (memcmp(mac_addr[i], zero_addr, ETH_ALEN)) {
3916                        memcpy(del_all_sta_info->del_all_sta[i], mac_addr[i],
3917                               ETH_ALEN);
3918                        assoc_sta++;
3919                }
3920        }
3921        if (!assoc_sta) {
3922                kfree(msg);
3923                return 0;
3924        }
3925
3926        del_all_sta_info->assoc_sta = assoc_sta;
3927        result = wilc_enqueue_work(msg);
3928
3929        if (result)
3930                netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__);
3931        else
3932                wait_for_completion(&msg->work_comp);
3933
3934        kfree(msg);
3935
3936        return result;
3937}
3938
3939int wilc_edit_station(struct wilc_vif *vif,
3940                      struct add_sta_param *sta_param)
3941{
3942        int result;
3943        struct host_if_msg *msg;
3944        struct add_sta_param *add_sta_info;
3945
3946        msg = wilc_alloc_work(vif, handle_edit_station, false);
3947        if (IS_ERR(msg))
3948                return PTR_ERR(msg);
3949
3950        add_sta_info = &msg->body.add_sta_info;
3951        memcpy(add_sta_info, sta_param, sizeof(*add_sta_info));
3952        if (add_sta_info->rates_len > 0) {
3953                add_sta_info->rates = kmemdup(sta_param->rates,
3954                                              add_sta_info->rates_len,
3955                                              GFP_KERNEL);
3956                if (!add_sta_info->rates) {
3957                        kfree(msg);
3958                        return -ENOMEM;
3959                }
3960        }
3961
3962        result = wilc_enqueue_work(msg);
3963        if (result) {
3964                netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__);
3965                kfree(add_sta_info->rates);
3966                kfree(msg);
3967        }
3968
3969        return result;
3970}
3971
3972int wilc_set_power_mgmt(struct wilc_vif *vif, bool enabled, u32 timeout)
3973{
3974        int result;
3975        struct host_if_msg *msg;
3976
3977        if (wilc_wlan_get_num_conn_ifcs(vif->wilc) == 2 && enabled)
3978                return 0;
3979
3980        msg = wilc_alloc_work(vif, handle_power_management, false);
3981        if (IS_ERR(msg))
3982                return PTR_ERR(msg);
3983
3984        msg->body.pwr_mgmt_info.enabled = enabled;
3985        msg->body.pwr_mgmt_info.timeout = timeout;
3986
3987        result = wilc_enqueue_work(msg);
3988        if (result) {
3989                netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__);
3990                kfree(msg);
3991        }
3992        return result;
3993}
3994
3995int wilc_setup_multicast_filter(struct wilc_vif *vif, bool enabled,
3996                                u32 count)
3997{
3998        int result;
3999        struct host_if_msg *msg;
4000
4001        msg = wilc_alloc_work(vif, handle_set_mcast_filter, false);
4002        if (IS_ERR(msg))
4003                return PTR_ERR(msg);
4004
4005        msg->body.multicast_info.enabled = enabled;
4006        msg->body.multicast_info.cnt = count;
4007
4008        result = wilc_enqueue_work(msg);
4009        if (result) {
4010                netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__);
4011                kfree(msg);
4012        }
4013        return result;
4014}
4015
4016int wilc_setup_ipaddress(struct wilc_vif *vif, u8 *ip_addr, u8 idx)
4017{
4018        int result;
4019        struct host_if_msg *msg;
4020
4021        msg = wilc_alloc_work(vif, handle_set_ip_address, false);
4022        if (IS_ERR(msg))
4023                return PTR_ERR(msg);
4024
4025        msg->body.ip_info.ip_addr = ip_addr;
4026        msg->body.ip_info.idx = idx;
4027
4028        result = wilc_enqueue_work(msg);
4029        if (result) {
4030                netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__);
4031                kfree(msg);
4032        }
4033
4034        return result;
4035}
4036
4037static int host_int_get_ipaddress(struct wilc_vif *vif, u8 *ip_addr, u8 idx)
4038{
4039        int result;
4040        struct host_if_msg *msg;
4041
4042        msg = wilc_alloc_work(vif, handle_get_ip_address, false);
4043        if (IS_ERR(msg))
4044                return PTR_ERR(msg);
4045
4046        msg->body.ip_info.ip_addr = ip_addr;
4047        msg->body.ip_info.idx = idx;
4048
4049        result = wilc_enqueue_work(msg);
4050        if (result) {
4051                netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__);
4052                kfree(msg);
4053        }
4054
4055        return result;
4056}
4057
4058int wilc_set_tx_power(struct wilc_vif *vif, u8 tx_power)
4059{
4060        int ret;
4061        struct host_if_msg *msg;
4062
4063        msg = wilc_alloc_work(vif, handle_set_tx_pwr, false);
4064        if (IS_ERR(msg))
4065                return PTR_ERR(msg);
4066
4067        msg->body.tx_power.tx_pwr = tx_power;
4068
4069        ret = wilc_enqueue_work(msg);
4070        if (ret) {
4071                netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__);
4072                kfree(msg);
4073        }
4074
4075        return ret;
4076}
4077
4078int wilc_get_tx_power(struct wilc_vif *vif, u8 *tx_power)
4079{
4080        int ret;
4081        struct host_if_msg *msg;
4082
4083        msg = wilc_alloc_work(vif, handle_get_tx_pwr, true);
4084        if (IS_ERR(msg))
4085                return PTR_ERR(msg);
4086
4087        ret = wilc_enqueue_work(msg);
4088        if (ret) {
4089                netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__);
4090        } else {
4091                wait_for_completion(&msg->work_comp);
4092                *tx_power = msg->body.tx_power.tx_pwr;
4093        }
4094
4095        /* free 'msg' after copying data */
4096        kfree(msg);
4097        return ret;
4098}
4099