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