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 hif_drv->hif_state = HOST_IF_WAITING_CONN_RESP; 310 } 311 312 return 0; 313 314 error: 315 316 kfree(conn_attr->req_ies); 317 conn_attr->req_ies = NULL; 318 319 return result; 320 } 321 322 static 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 360 out: 361 kfree(msg); 362 } 363 364 void *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 499 static 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 529 done: 530 kfree(rcvd_info->mgmt); 531 kfree(msg); 532 } 533 534 static 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 557 static 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 579 static 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 628 static 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 651 static 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 679 free_msg: 680 kfree(msg); 681 } 682 683 int 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 733 int 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 783 static 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 794 static 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 823 static 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 865 static 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 903 static 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 911 static 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 934 static 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 964 error: 965 kfree(set_mc->mc_list); 966 kfree(wid.val); 967 kfree(msg); 968 } 969 970 void 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 989 static 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 997 static 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 1008 static 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 1024 static 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 1041 int wilc_add_ptk(struct wilc_vif *vif, const u8 *ptk, u8 ptk_key_len, 1042 const u8 *mac_addr, const u8 *rx_mic, const u8 *tx_mic, 1043 u8 mode, u8 cipher_mode, u8 index) 1044 { 1045 int result = 0; 1046 u8 t_key_len = ptk_key_len + WILC_RX_MIC_KEY_LEN + WILC_TX_MIC_KEY_LEN; 1047 1048 if (mode == WILC_AP_MODE) { 1049 struct wid wid_list[2]; 1050 struct wilc_ap_wpa_ptk *key_buf; 1051 1052 wid_list[0].id = WID_11I_MODE; 1053 wid_list[0].type = WID_CHAR; 1054 wid_list[0].size = sizeof(char); 1055 wid_list[0].val = (s8 *)&cipher_mode; 1056 1057 key_buf = kzalloc(sizeof(*key_buf) + t_key_len, GFP_KERNEL); 1058 if (!key_buf) 1059 return -ENOMEM; 1060 1061 ether_addr_copy(key_buf->mac_addr, mac_addr); 1062 key_buf->index = index; 1063 key_buf->key_len = t_key_len; 1064 memcpy(&key_buf->key[0], ptk, ptk_key_len); 1065 1066 if (rx_mic) 1067 memcpy(&key_buf->key[ptk_key_len], rx_mic, 1068 WILC_RX_MIC_KEY_LEN); 1069 1070 if (tx_mic) 1071 memcpy(&key_buf->key[ptk_key_len + WILC_RX_MIC_KEY_LEN], 1072 tx_mic, WILC_TX_MIC_KEY_LEN); 1073 1074 wid_list[1].id = WID_ADD_PTK; 1075 wid_list[1].type = WID_STR; 1076 wid_list[1].size = sizeof(*key_buf) + t_key_len; 1077 wid_list[1].val = (u8 *)key_buf; 1078 result = wilc_send_config_pkt(vif, WILC_SET_CFG, wid_list, 1079 ARRAY_SIZE(wid_list)); 1080 kfree(key_buf); 1081 } else if (mode == WILC_STATION_MODE) { 1082 struct wid wid; 1083 struct wilc_sta_wpa_ptk *key_buf; 1084 1085 key_buf = kzalloc(sizeof(*key_buf) + t_key_len, GFP_KERNEL); 1086 if (!key_buf) 1087 return -ENOMEM; 1088 1089 ether_addr_copy(key_buf->mac_addr, mac_addr); 1090 key_buf->key_len = t_key_len; 1091 memcpy(&key_buf->key[0], ptk, ptk_key_len); 1092 1093 if (rx_mic) 1094 memcpy(&key_buf->key[ptk_key_len], rx_mic, 1095 WILC_RX_MIC_KEY_LEN); 1096 1097 if (tx_mic) 1098 memcpy(&key_buf->key[ptk_key_len + WILC_RX_MIC_KEY_LEN], 1099 tx_mic, WILC_TX_MIC_KEY_LEN); 1100 1101 wid.id = WID_ADD_PTK; 1102 wid.type = WID_STR; 1103 wid.size = sizeof(*key_buf) + t_key_len; 1104 wid.val = (s8 *)key_buf; 1105 result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1); 1106 kfree(key_buf); 1107 } 1108 1109 return result; 1110 } 1111 1112 int wilc_add_rx_gtk(struct wilc_vif *vif, const u8 *rx_gtk, u8 gtk_key_len, 1113 u8 index, u32 key_rsc_len, const u8 *key_rsc, 1114 const u8 *rx_mic, const u8 *tx_mic, u8 mode, 1115 u8 cipher_mode) 1116 { 1117 int result = 0; 1118 struct wilc_gtk_key *gtk_key; 1119 int t_key_len = gtk_key_len + WILC_RX_MIC_KEY_LEN + WILC_TX_MIC_KEY_LEN; 1120 1121 gtk_key = kzalloc(sizeof(*gtk_key) + t_key_len, GFP_KERNEL); 1122 if (!gtk_key) 1123 return -ENOMEM; 1124 1125 /* fill bssid value only in station mode */ 1126 if (mode == WILC_STATION_MODE && 1127 vif->hif_drv->hif_state == HOST_IF_CONNECTED) 1128 memcpy(gtk_key->mac_addr, vif->hif_drv->assoc_bssid, ETH_ALEN); 1129 1130 if (key_rsc) 1131 memcpy(gtk_key->rsc, key_rsc, 8); 1132 gtk_key->index = index; 1133 gtk_key->key_len = t_key_len; 1134 memcpy(>k_key->key[0], rx_gtk, gtk_key_len); 1135 1136 if (rx_mic) 1137 memcpy(>k_key->key[gtk_key_len], rx_mic, WILC_RX_MIC_KEY_LEN); 1138 1139 if (tx_mic) 1140 memcpy(>k_key->key[gtk_key_len + WILC_RX_MIC_KEY_LEN], 1141 tx_mic, WILC_TX_MIC_KEY_LEN); 1142 1143 if (mode == WILC_AP_MODE) { 1144 struct wid wid_list[2]; 1145 1146 wid_list[0].id = WID_11I_MODE; 1147 wid_list[0].type = WID_CHAR; 1148 wid_list[0].size = sizeof(char); 1149 wid_list[0].val = (s8 *)&cipher_mode; 1150 1151 wid_list[1].id = WID_ADD_RX_GTK; 1152 wid_list[1].type = WID_STR; 1153 wid_list[1].size = sizeof(*gtk_key) + t_key_len; 1154 wid_list[1].val = (u8 *)gtk_key; 1155 1156 result = wilc_send_config_pkt(vif, WILC_SET_CFG, wid_list, 1157 ARRAY_SIZE(wid_list)); 1158 } else if (mode == WILC_STATION_MODE) { 1159 struct wid wid; 1160 1161 wid.id = WID_ADD_RX_GTK; 1162 wid.type = WID_STR; 1163 wid.size = sizeof(*gtk_key) + t_key_len; 1164 wid.val = (u8 *)gtk_key; 1165 result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1); 1166 } 1167 1168 kfree(gtk_key); 1169 return result; 1170 } 1171 1172 int wilc_set_pmkid_info(struct wilc_vif *vif, struct wilc_pmkid_attr *pmkid) 1173 { 1174 struct wid wid; 1175 1176 wid.id = WID_PMKID_INFO; 1177 wid.type = WID_STR; 1178 wid.size = (pmkid->numpmkid * sizeof(struct wilc_pmkid)) + 1; 1179 wid.val = (u8 *)pmkid; 1180 1181 return wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1); 1182 } 1183 1184 int wilc_get_mac_address(struct wilc_vif *vif, u8 *mac_addr) 1185 { 1186 int result; 1187 struct wid wid; 1188 1189 wid.id = WID_MAC_ADDR; 1190 wid.type = WID_STR; 1191 wid.size = ETH_ALEN; 1192 wid.val = mac_addr; 1193 1194 result = wilc_send_config_pkt(vif, WILC_GET_CFG, &wid, 1); 1195 if (result) 1196 netdev_err(vif->ndev, "Failed to get mac address\n"); 1197 1198 return result; 1199 } 1200 1201 int wilc_set_mac_address(struct wilc_vif *vif, u8 *mac_addr) 1202 { 1203 struct wid wid; 1204 int result; 1205 1206 wid.id = WID_MAC_ADDR; 1207 wid.type = WID_STR; 1208 wid.size = ETH_ALEN; 1209 wid.val = mac_addr; 1210 1211 result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1); 1212 if (result) 1213 netdev_err(vif->ndev, "Failed to set mac address\n"); 1214 1215 return result; 1216 } 1217 1218 int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ies, 1219 size_t ies_len) 1220 { 1221 int result; 1222 struct host_if_drv *hif_drv = vif->hif_drv; 1223 struct wilc_conn_info *conn_info = &hif_drv->conn_info; 1224 1225 if (bssid) 1226 ether_addr_copy(conn_info->bssid, bssid); 1227 1228 if (ies) { 1229 conn_info->req_ies_len = ies_len; 1230 conn_info->req_ies = kmemdup(ies, ies_len, GFP_KERNEL); 1231 if (!conn_info->req_ies) 1232 return -ENOMEM; 1233 } 1234 1235 result = wilc_send_connect_wid(vif); 1236 if (result) 1237 goto free_ies; 1238 1239 hif_drv->connect_timer_vif = vif; 1240 mod_timer(&hif_drv->connect_timer, 1241 jiffies + msecs_to_jiffies(WILC_HIF_CONNECT_TIMEOUT_MS)); 1242 1243 return 0; 1244 1245 free_ies: 1246 kfree(conn_info->req_ies); 1247 1248 return result; 1249 } 1250 1251 int wilc_set_mac_chnl_num(struct wilc_vif *vif, u8 channel) 1252 { 1253 struct wid wid; 1254 int result; 1255 1256 wid.id = WID_CURRENT_CHANNEL; 1257 wid.type = WID_CHAR; 1258 wid.size = sizeof(char); 1259 wid.val = &channel; 1260 1261 result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1); 1262 if (result) 1263 netdev_err(vif->ndev, "Failed to set channel\n"); 1264 1265 return result; 1266 } 1267 1268 int wilc_set_operation_mode(struct wilc_vif *vif, int index, u8 mode, 1269 u8 ifc_id) 1270 { 1271 struct wid wid; 1272 int result; 1273 struct wilc_drv_handler drv; 1274 1275 wid.id = WID_SET_OPERATION_MODE; 1276 wid.type = WID_STR; 1277 wid.size = sizeof(drv); 1278 wid.val = (u8 *)&drv; 1279 1280 drv.handler = cpu_to_le32(index); 1281 drv.mode = (ifc_id | (mode << 1)); 1282 1283 result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1); 1284 if (result) 1285 netdev_err(vif->ndev, "Failed to set driver handler\n"); 1286 1287 return result; 1288 } 1289 1290 s32 wilc_get_inactive_time(struct wilc_vif *vif, const u8 *mac, u32 *out_val) 1291 { 1292 struct wid wid; 1293 s32 result; 1294 1295 wid.id = WID_SET_STA_MAC_INACTIVE_TIME; 1296 wid.type = WID_STR; 1297 wid.size = ETH_ALEN; 1298 wid.val = kzalloc(wid.size, GFP_KERNEL); 1299 if (!wid.val) 1300 return -ENOMEM; 1301 1302 ether_addr_copy(wid.val, mac); 1303 result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1); 1304 kfree(wid.val); 1305 if (result) { 1306 netdev_err(vif->ndev, "Failed to set inactive mac\n"); 1307 return result; 1308 } 1309 1310 wid.id = WID_GET_INACTIVE_TIME; 1311 wid.type = WID_INT; 1312 wid.val = (s8 *)out_val; 1313 wid.size = sizeof(u32); 1314 result = wilc_send_config_pkt(vif, WILC_GET_CFG, &wid, 1); 1315 if (result) 1316 netdev_err(vif->ndev, "Failed to get inactive time\n"); 1317 1318 return result; 1319 } 1320 1321 int wilc_get_rssi(struct wilc_vif *vif, s8 *rssi_level) 1322 { 1323 struct wid wid; 1324 int result; 1325 1326 if (!rssi_level) { 1327 netdev_err(vif->ndev, "%s: RSSI level is NULL\n", __func__); 1328 return -EFAULT; 1329 } 1330 1331 wid.id = WID_RSSI; 1332 wid.type = WID_CHAR; 1333 wid.size = sizeof(char); 1334 wid.val = rssi_level; 1335 result = wilc_send_config_pkt(vif, WILC_GET_CFG, &wid, 1); 1336 if (result) 1337 netdev_err(vif->ndev, "Failed to get RSSI value\n"); 1338 1339 return result; 1340 } 1341 1342 static int wilc_get_stats_async(struct wilc_vif *vif, struct rf_info *stats) 1343 { 1344 int result; 1345 struct host_if_msg *msg; 1346 1347 msg = wilc_alloc_work(vif, handle_get_statistics, false); 1348 if (IS_ERR(msg)) 1349 return PTR_ERR(msg); 1350 1351 msg->body.data = (char *)stats; 1352 1353 result = wilc_enqueue_work(msg); 1354 if (result) { 1355 netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__); 1356 kfree(msg); 1357 return result; 1358 } 1359 1360 return result; 1361 } 1362 1363 int wilc_hif_set_cfg(struct wilc_vif *vif, struct cfg_param_attr *param) 1364 { 1365 struct wid wid_list[4]; 1366 int i = 0; 1367 1368 if (param->flag & WILC_CFG_PARAM_RETRY_SHORT) { 1369 wid_list[i].id = WID_SHORT_RETRY_LIMIT; 1370 wid_list[i].val = (s8 *)¶m->short_retry_limit; 1371 wid_list[i].type = WID_SHORT; 1372 wid_list[i].size = sizeof(u16); 1373 i++; 1374 } 1375 if (param->flag & WILC_CFG_PARAM_RETRY_LONG) { 1376 wid_list[i].id = WID_LONG_RETRY_LIMIT; 1377 wid_list[i].val = (s8 *)¶m->long_retry_limit; 1378 wid_list[i].type = WID_SHORT; 1379 wid_list[i].size = sizeof(u16); 1380 i++; 1381 } 1382 if (param->flag & WILC_CFG_PARAM_FRAG_THRESHOLD) { 1383 wid_list[i].id = WID_FRAG_THRESHOLD; 1384 wid_list[i].val = (s8 *)¶m->frag_threshold; 1385 wid_list[i].type = WID_SHORT; 1386 wid_list[i].size = sizeof(u16); 1387 i++; 1388 } 1389 if (param->flag & WILC_CFG_PARAM_RTS_THRESHOLD) { 1390 wid_list[i].id = WID_RTS_THRESHOLD; 1391 wid_list[i].val = (s8 *)¶m->rts_threshold; 1392 wid_list[i].type = WID_SHORT; 1393 wid_list[i].size = sizeof(u16); 1394 i++; 1395 } 1396 1397 return wilc_send_config_pkt(vif, WILC_SET_CFG, wid_list, i); 1398 } 1399 1400 static void get_periodic_rssi(struct timer_list *t) 1401 { 1402 struct wilc_vif *vif = from_timer(vif, t, periodic_rssi); 1403 1404 if (!vif->hif_drv) { 1405 netdev_err(vif->ndev, "%s: hif driver is NULL", __func__); 1406 return; 1407 } 1408 1409 if (vif->hif_drv->hif_state == HOST_IF_CONNECTED) 1410 wilc_get_stats_async(vif, &vif->periodic_stat); 1411 1412 mod_timer(&vif->periodic_rssi, jiffies + msecs_to_jiffies(5000)); 1413 } 1414 1415 int wilc_init(struct net_device *dev, struct host_if_drv **hif_drv_handler) 1416 { 1417 struct host_if_drv *hif_drv; 1418 struct wilc_vif *vif = netdev_priv(dev); 1419 1420 hif_drv = kzalloc(sizeof(*hif_drv), GFP_KERNEL); 1421 if (!hif_drv) 1422 return -ENOMEM; 1423 1424 *hif_drv_handler = hif_drv; 1425 1426 vif->hif_drv = hif_drv; 1427 1428 timer_setup(&vif->periodic_rssi, get_periodic_rssi, 0); 1429 mod_timer(&vif->periodic_rssi, jiffies + msecs_to_jiffies(5000)); 1430 1431 timer_setup(&hif_drv->scan_timer, timer_scan_cb, 0); 1432 timer_setup(&hif_drv->connect_timer, timer_connect_cb, 0); 1433 timer_setup(&hif_drv->remain_on_ch_timer, listen_timer_cb, 0); 1434 1435 hif_drv->hif_state = HOST_IF_IDLE; 1436 1437 hif_drv->p2p_timeout = 0; 1438 1439 return 0; 1440 } 1441 1442 int wilc_deinit(struct wilc_vif *vif) 1443 { 1444 int result = 0; 1445 struct host_if_drv *hif_drv = vif->hif_drv; 1446 1447 if (!hif_drv) { 1448 netdev_err(vif->ndev, "%s: hif driver is NULL", __func__); 1449 return -EFAULT; 1450 } 1451 1452 mutex_lock(&vif->wilc->deinit_lock); 1453 1454 del_timer_sync(&hif_drv->scan_timer); 1455 del_timer_sync(&hif_drv->connect_timer); 1456 del_timer_sync(&vif->periodic_rssi); 1457 del_timer_sync(&hif_drv->remain_on_ch_timer); 1458 1459 if (hif_drv->usr_scan_req.scan_result) { 1460 hif_drv->usr_scan_req.scan_result(SCAN_EVENT_ABORTED, NULL, 1461 hif_drv->usr_scan_req.arg); 1462 hif_drv->usr_scan_req.scan_result = NULL; 1463 } 1464 1465 hif_drv->hif_state = HOST_IF_IDLE; 1466 1467 kfree(hif_drv); 1468 vif->hif_drv = NULL; 1469 mutex_unlock(&vif->wilc->deinit_lock); 1470 return result; 1471 } 1472 1473 void wilc_network_info_received(struct wilc *wilc, u8 *buffer, u32 length) 1474 { 1475 int result; 1476 struct host_if_msg *msg; 1477 int id; 1478 struct host_if_drv *hif_drv; 1479 struct wilc_vif *vif; 1480 1481 id = get_unaligned_le32(&buffer[length - 4]); 1482 vif = wilc_get_vif_from_idx(wilc, id); 1483 if (!vif) 1484 return; 1485 hif_drv = vif->hif_drv; 1486 1487 if (!hif_drv) { 1488 netdev_err(vif->ndev, "driver not init[%p]\n", hif_drv); 1489 return; 1490 } 1491 1492 msg = wilc_alloc_work(vif, handle_rcvd_ntwrk_info, false); 1493 if (IS_ERR(msg)) 1494 return; 1495 1496 msg->body.net_info.frame_len = get_unaligned_le16(&buffer[6]) - 1; 1497 msg->body.net_info.rssi = buffer[8]; 1498 msg->body.net_info.mgmt = kmemdup(&buffer[9], 1499 msg->body.net_info.frame_len, 1500 GFP_KERNEL); 1501 if (!msg->body.net_info.mgmt) { 1502 kfree(msg); 1503 return; 1504 } 1505 1506 result = wilc_enqueue_work(msg); 1507 if (result) { 1508 netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__); 1509 kfree(msg->body.net_info.mgmt); 1510 kfree(msg); 1511 } 1512 } 1513 1514 void wilc_gnrl_async_info_received(struct wilc *wilc, u8 *buffer, u32 length) 1515 { 1516 int result; 1517 struct host_if_msg *msg; 1518 int id; 1519 struct host_if_drv *hif_drv; 1520 struct wilc_vif *vif; 1521 1522 mutex_lock(&wilc->deinit_lock); 1523 1524 id = get_unaligned_le32(&buffer[length - 4]); 1525 vif = wilc_get_vif_from_idx(wilc, id); 1526 if (!vif) { 1527 mutex_unlock(&wilc->deinit_lock); 1528 return; 1529 } 1530 1531 hif_drv = vif->hif_drv; 1532 1533 if (!hif_drv) { 1534 mutex_unlock(&wilc->deinit_lock); 1535 return; 1536 } 1537 1538 if (!hif_drv->conn_info.conn_result) { 1539 netdev_err(vif->ndev, "%s: conn_result is NULL\n", __func__); 1540 mutex_unlock(&wilc->deinit_lock); 1541 return; 1542 } 1543 1544 msg = wilc_alloc_work(vif, handle_rcvd_gnrl_async_info, false); 1545 if (IS_ERR(msg)) { 1546 mutex_unlock(&wilc->deinit_lock); 1547 return; 1548 } 1549 1550 msg->body.mac_info.status = buffer[7]; 1551 result = wilc_enqueue_work(msg); 1552 if (result) { 1553 netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__); 1554 kfree(msg); 1555 } 1556 1557 mutex_unlock(&wilc->deinit_lock); 1558 } 1559 1560 void wilc_scan_complete_received(struct wilc *wilc, u8 *buffer, u32 length) 1561 { 1562 int result; 1563 int id; 1564 struct host_if_drv *hif_drv; 1565 struct wilc_vif *vif; 1566 1567 id = get_unaligned_le32(&buffer[length - 4]); 1568 vif = wilc_get_vif_from_idx(wilc, id); 1569 if (!vif) 1570 return; 1571 hif_drv = vif->hif_drv; 1572 1573 if (!hif_drv) 1574 return; 1575 1576 if (hif_drv->usr_scan_req.scan_result) { 1577 struct host_if_msg *msg; 1578 1579 msg = wilc_alloc_work(vif, handle_scan_complete, false); 1580 if (IS_ERR(msg)) 1581 return; 1582 1583 result = wilc_enqueue_work(msg); 1584 if (result) { 1585 netdev_err(vif->ndev, "%s: enqueue work failed\n", 1586 __func__); 1587 kfree(msg); 1588 } 1589 } 1590 } 1591 1592 int wilc_remain_on_channel(struct wilc_vif *vif, u64 cookie, 1593 u32 duration, u16 chan, 1594 void (*expired)(void *, u64), 1595 void *user_arg) 1596 { 1597 struct wilc_remain_ch roc; 1598 int result; 1599 1600 roc.ch = chan; 1601 roc.expired = expired; 1602 roc.arg = user_arg; 1603 roc.duration = duration; 1604 roc.cookie = cookie; 1605 result = handle_remain_on_chan(vif, &roc); 1606 if (result) 1607 netdev_err(vif->ndev, "%s: failed to set remain on channel\n", 1608 __func__); 1609 1610 return result; 1611 } 1612 1613 int wilc_listen_state_expired(struct wilc_vif *vif, u64 cookie) 1614 { 1615 if (!vif->hif_drv) { 1616 netdev_err(vif->ndev, "%s: hif driver is NULL", __func__); 1617 return -EFAULT; 1618 } 1619 1620 del_timer(&vif->hif_drv->remain_on_ch_timer); 1621 1622 return wilc_handle_roc_expired(vif, cookie); 1623 } 1624 1625 void wilc_frame_register(struct wilc_vif *vif, u16 frame_type, bool reg) 1626 { 1627 struct wid wid; 1628 int result; 1629 struct wilc_reg_frame reg_frame; 1630 1631 wid.id = WID_REGISTER_FRAME; 1632 wid.type = WID_STR; 1633 wid.size = sizeof(reg_frame); 1634 wid.val = (u8 *)®_frame; 1635 1636 memset(®_frame, 0x0, sizeof(reg_frame)); 1637 1638 if (reg) 1639 reg_frame.reg = 1; 1640 1641 switch (frame_type) { 1642 case IEEE80211_STYPE_ACTION: 1643 reg_frame.reg_id = WILC_FW_ACTION_FRM_IDX; 1644 break; 1645 1646 case IEEE80211_STYPE_PROBE_REQ: 1647 reg_frame.reg_id = WILC_FW_PROBE_REQ_IDX; 1648 break; 1649 1650 default: 1651 break; 1652 } 1653 reg_frame.frame_type = cpu_to_le16(frame_type); 1654 result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1); 1655 if (result) 1656 netdev_err(vif->ndev, "Failed to frame register\n"); 1657 } 1658 1659 int wilc_add_beacon(struct wilc_vif *vif, u32 interval, u32 dtim_period, 1660 struct cfg80211_beacon_data *params) 1661 { 1662 struct wid wid; 1663 int result; 1664 u8 *cur_byte; 1665 1666 wid.id = WID_ADD_BEACON; 1667 wid.type = WID_BIN; 1668 wid.size = params->head_len + params->tail_len + 16; 1669 wid.val = kzalloc(wid.size, GFP_KERNEL); 1670 if (!wid.val) 1671 return -ENOMEM; 1672 1673 cur_byte = wid.val; 1674 put_unaligned_le32(interval, cur_byte); 1675 cur_byte += 4; 1676 put_unaligned_le32(dtim_period, cur_byte); 1677 cur_byte += 4; 1678 put_unaligned_le32(params->head_len, cur_byte); 1679 cur_byte += 4; 1680 1681 if (params->head_len > 0) 1682 memcpy(cur_byte, params->head, params->head_len); 1683 cur_byte += params->head_len; 1684 1685 put_unaligned_le32(params->tail_len, cur_byte); 1686 cur_byte += 4; 1687 1688 if (params->tail_len > 0) 1689 memcpy(cur_byte, params->tail, params->tail_len); 1690 1691 result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1); 1692 if (result) 1693 netdev_err(vif->ndev, "Failed to send add beacon\n"); 1694 1695 kfree(wid.val); 1696 1697 return result; 1698 } 1699 1700 int wilc_del_beacon(struct wilc_vif *vif) 1701 { 1702 int result; 1703 struct wid wid; 1704 u8 del_beacon = 0; 1705 1706 wid.id = WID_DEL_BEACON; 1707 wid.type = WID_CHAR; 1708 wid.size = sizeof(char); 1709 wid.val = &del_beacon; 1710 1711 result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1); 1712 if (result) 1713 netdev_err(vif->ndev, "Failed to send delete beacon\n"); 1714 1715 return result; 1716 } 1717 1718 int wilc_add_station(struct wilc_vif *vif, const u8 *mac, 1719 struct station_parameters *params) 1720 { 1721 struct wid wid; 1722 int result; 1723 u8 *cur_byte; 1724 1725 wid.id = WID_ADD_STA; 1726 wid.type = WID_BIN; 1727 wid.size = WILC_ADD_STA_LENGTH + params->supported_rates_len; 1728 wid.val = kmalloc(wid.size, GFP_KERNEL); 1729 if (!wid.val) 1730 return -ENOMEM; 1731 1732 cur_byte = wid.val; 1733 wilc_hif_pack_sta_param(cur_byte, mac, params); 1734 1735 result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1); 1736 if (result != 0) 1737 netdev_err(vif->ndev, "Failed to send add station\n"); 1738 1739 kfree(wid.val); 1740 1741 return result; 1742 } 1743 1744 int wilc_del_station(struct wilc_vif *vif, const u8 *mac_addr) 1745 { 1746 struct wid wid; 1747 int result; 1748 1749 wid.id = WID_REMOVE_STA; 1750 wid.type = WID_BIN; 1751 wid.size = ETH_ALEN; 1752 wid.val = kzalloc(wid.size, GFP_KERNEL); 1753 if (!wid.val) 1754 return -ENOMEM; 1755 1756 if (!mac_addr) 1757 eth_broadcast_addr(wid.val); 1758 else 1759 ether_addr_copy(wid.val, mac_addr); 1760 1761 result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1); 1762 if (result) 1763 netdev_err(vif->ndev, "Failed to del station\n"); 1764 1765 kfree(wid.val); 1766 1767 return result; 1768 } 1769 1770 int wilc_del_allstation(struct wilc_vif *vif, u8 mac_addr[][ETH_ALEN]) 1771 { 1772 struct wid wid; 1773 int result; 1774 int i; 1775 u8 assoc_sta = 0; 1776 struct wilc_del_all_sta del_sta; 1777 1778 memset(&del_sta, 0x0, sizeof(del_sta)); 1779 for (i = 0; i < WILC_MAX_NUM_STA; i++) { 1780 if (!is_zero_ether_addr(mac_addr[i])) { 1781 assoc_sta++; 1782 ether_addr_copy(del_sta.mac[i], mac_addr[i]); 1783 } 1784 } 1785 1786 if (!assoc_sta) 1787 return 0; 1788 1789 del_sta.assoc_sta = assoc_sta; 1790 1791 wid.id = WID_DEL_ALL_STA; 1792 wid.type = WID_STR; 1793 wid.size = (assoc_sta * ETH_ALEN) + 1; 1794 wid.val = (u8 *)&del_sta; 1795 1796 result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1); 1797 if (result) 1798 netdev_err(vif->ndev, "Failed to send delete all station\n"); 1799 1800 return result; 1801 } 1802 1803 int wilc_edit_station(struct wilc_vif *vif, const u8 *mac, 1804 struct station_parameters *params) 1805 { 1806 struct wid wid; 1807 int result; 1808 u8 *cur_byte; 1809 1810 wid.id = WID_EDIT_STA; 1811 wid.type = WID_BIN; 1812 wid.size = WILC_ADD_STA_LENGTH + params->supported_rates_len; 1813 wid.val = kmalloc(wid.size, GFP_KERNEL); 1814 if (!wid.val) 1815 return -ENOMEM; 1816 1817 cur_byte = wid.val; 1818 wilc_hif_pack_sta_param(cur_byte, mac, params); 1819 1820 result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1); 1821 if (result) 1822 netdev_err(vif->ndev, "Failed to send edit station\n"); 1823 1824 kfree(wid.val); 1825 return result; 1826 } 1827 1828 int wilc_set_power_mgmt(struct wilc_vif *vif, bool enabled, u32 timeout) 1829 { 1830 struct wilc *wilc = vif->wilc; 1831 struct wid wid; 1832 int result; 1833 s8 power_mode; 1834 1835 if (enabled) 1836 power_mode = WILC_FW_MIN_FAST_PS; 1837 else 1838 power_mode = WILC_FW_NO_POWERSAVE; 1839 1840 wid.id = WID_POWER_MANAGEMENT; 1841 wid.val = &power_mode; 1842 wid.size = sizeof(char); 1843 result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1); 1844 if (result) 1845 netdev_err(vif->ndev, "Failed to send power management\n"); 1846 else 1847 wilc->power_save_mode = enabled; 1848 1849 return result; 1850 } 1851 1852 int wilc_setup_multicast_filter(struct wilc_vif *vif, u32 enabled, u32 count, 1853 u8 *mc_list) 1854 { 1855 int result; 1856 struct host_if_msg *msg; 1857 1858 msg = wilc_alloc_work(vif, handle_set_mcast_filter, false); 1859 if (IS_ERR(msg)) 1860 return PTR_ERR(msg); 1861 1862 msg->body.mc_info.enabled = enabled; 1863 msg->body.mc_info.cnt = count; 1864 msg->body.mc_info.mc_list = mc_list; 1865 1866 result = wilc_enqueue_work(msg); 1867 if (result) { 1868 netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__); 1869 kfree(msg); 1870 } 1871 return result; 1872 } 1873 1874 int wilc_set_tx_power(struct wilc_vif *vif, u8 tx_power) 1875 { 1876 struct wid wid; 1877 1878 wid.id = WID_TX_POWER; 1879 wid.type = WID_CHAR; 1880 wid.val = &tx_power; 1881 wid.size = sizeof(char); 1882 1883 return wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1); 1884 } 1885 1886 int wilc_get_tx_power(struct wilc_vif *vif, u8 *tx_power) 1887 { 1888 struct wid wid; 1889 1890 wid.id = WID_TX_POWER; 1891 wid.type = WID_CHAR; 1892 wid.val = tx_power; 1893 wid.size = sizeof(char); 1894 1895 return wilc_send_config_pkt(vif, WILC_GET_CFG, &wid, 1); 1896 } 1897