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