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