root/drivers/staging/wilc1000/wilc_hif.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. wilc_alloc_work
  2. wilc_enqueue_work
  3. wilc_get_vif_idx
  4. wilc_get_vif_from_idx
  5. handle_scan_done
  6. wilc_scan
  7. wilc_send_connect_wid
  8. handle_connect_timeout
  9. wilc_parse_join_bss_param
  10. handle_rcvd_ntwrk_info
  11. host_int_get_assoc_res_info
  12. wilc_parse_assoc_resp_info
  13. host_int_parse_assoc_resp_info
  14. host_int_handle_disconnect
  15. handle_rcvd_gnrl_async_info
  16. wilc_disconnect
  17. wilc_get_statistics
  18. handle_get_statistics
  19. wilc_hif_pack_sta_param
  20. handle_remain_on_chan
  21. wilc_handle_roc_expired
  22. wilc_handle_listen_state_expired
  23. listen_timer_cb
  24. handle_set_mcast_filter
  25. handle_scan_timer
  26. handle_scan_complete
  27. timer_scan_cb
  28. timer_connect_cb
  29. wilc_remove_wep_key
  30. wilc_set_wep_default_keyid
  31. wilc_add_wep_key_bss_sta
  32. wilc_add_wep_key_bss_ap
  33. wilc_add_ptk
  34. wilc_add_rx_gtk
  35. wilc_set_pmkid_info
  36. wilc_get_mac_address
  37. wilc_set_join_req
  38. wilc_set_mac_chnl_num
  39. wilc_set_operation_mode
  40. wilc_get_inactive_time
  41. wilc_get_rssi
  42. wilc_get_stats_async
  43. wilc_hif_set_cfg
  44. get_periodic_rssi
  45. wilc_init
  46. wilc_deinit
  47. wilc_network_info_received
  48. wilc_gnrl_async_info_received
  49. wilc_scan_complete_received
  50. wilc_remain_on_channel
  51. wilc_listen_state_expired
  52. wilc_frame_register
  53. wilc_add_beacon
  54. wilc_del_beacon
  55. wilc_add_station
  56. wilc_del_station
  57. wilc_del_allstation
  58. wilc_edit_station
  59. wilc_set_power_mgmt
  60. wilc_setup_multicast_filter
  61. wilc_set_tx_power
  62. wilc_get_tx_power

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

/* [<][>][^][v][top][bottom][index][help] */