1 /* 2 * Copyright (c) 2013 Eugene Krasnikov <k.eugene.e@gmail.com> 3 * 4 * Permission to use, copy, modify, and/or distribute this software for any 5 * purpose with or without fee is hereby granted, provided that the above 6 * copyright notice and this permission notice appear in all copies. 7 * 8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 11 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 13 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 14 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 */ 16 17 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 18 19 #include <linux/etherdevice.h> 20 #include <linux/firmware.h> 21 #include <linux/bitops.h> 22 #include "smd.h" 23 24 static int put_cfg_tlv_u32(struct wcn36xx *wcn, size_t *len, u32 id, u32 value) 25 { 26 struct wcn36xx_hal_cfg *entry; 27 u32 *val; 28 29 if (*len + sizeof(*entry) + sizeof(u32) >= WCN36XX_HAL_BUF_SIZE) { 30 wcn36xx_err("Not enough room for TLV entry\n"); 31 return -ENOMEM; 32 } 33 34 entry = (struct wcn36xx_hal_cfg *) (wcn->hal_buf + *len); 35 entry->id = id; 36 entry->len = sizeof(u32); 37 entry->pad_bytes = 0; 38 entry->reserve = 0; 39 40 val = (u32 *) (entry + 1); 41 *val = value; 42 43 *len += sizeof(*entry) + sizeof(u32); 44 45 return 0; 46 } 47 48 static void wcn36xx_smd_set_bss_nw_type(struct wcn36xx *wcn, 49 struct ieee80211_sta *sta, 50 struct wcn36xx_hal_config_bss_params *bss_params) 51 { 52 if (IEEE80211_BAND_5GHZ == WCN36XX_BAND(wcn)) 53 bss_params->nw_type = WCN36XX_HAL_11A_NW_TYPE; 54 else if (sta && sta->ht_cap.ht_supported) 55 bss_params->nw_type = WCN36XX_HAL_11N_NW_TYPE; 56 else if (sta && (sta->supp_rates[IEEE80211_BAND_2GHZ] & 0x7f)) 57 bss_params->nw_type = WCN36XX_HAL_11G_NW_TYPE; 58 else 59 bss_params->nw_type = WCN36XX_HAL_11B_NW_TYPE; 60 } 61 62 static inline u8 is_cap_supported(unsigned long caps, unsigned long flag) 63 { 64 return caps & flag ? 1 : 0; 65 } 66 static void wcn36xx_smd_set_bss_ht_params(struct ieee80211_vif *vif, 67 struct ieee80211_sta *sta, 68 struct wcn36xx_hal_config_bss_params *bss_params) 69 { 70 if (sta && sta->ht_cap.ht_supported) { 71 unsigned long caps = sta->ht_cap.cap; 72 bss_params->ht = sta->ht_cap.ht_supported; 73 bss_params->tx_channel_width_set = is_cap_supported(caps, 74 IEEE80211_HT_CAP_SUP_WIDTH_20_40); 75 bss_params->lsig_tx_op_protection_full_support = 76 is_cap_supported(caps, 77 IEEE80211_HT_CAP_LSIG_TXOP_PROT); 78 79 bss_params->ht_oper_mode = vif->bss_conf.ht_operation_mode; 80 bss_params->lln_non_gf_coexist = 81 !!(vif->bss_conf.ht_operation_mode & 82 IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT); 83 /* IEEE80211_HT_STBC_PARAM_DUAL_CTS_PROT */ 84 bss_params->dual_cts_protection = 0; 85 /* IEEE80211_HT_OP_MODE_PROTECTION_20MHZ */ 86 bss_params->ht20_coexist = 0; 87 } 88 } 89 90 static void wcn36xx_smd_set_sta_ht_params(struct ieee80211_sta *sta, 91 struct wcn36xx_hal_config_sta_params *sta_params) 92 { 93 if (sta->ht_cap.ht_supported) { 94 unsigned long caps = sta->ht_cap.cap; 95 sta_params->ht_capable = sta->ht_cap.ht_supported; 96 sta_params->tx_channel_width_set = is_cap_supported(caps, 97 IEEE80211_HT_CAP_SUP_WIDTH_20_40); 98 sta_params->lsig_txop_protection = is_cap_supported(caps, 99 IEEE80211_HT_CAP_LSIG_TXOP_PROT); 100 101 sta_params->max_ampdu_size = sta->ht_cap.ampdu_factor; 102 sta_params->max_ampdu_density = sta->ht_cap.ampdu_density; 103 sta_params->max_amsdu_size = is_cap_supported(caps, 104 IEEE80211_HT_CAP_MAX_AMSDU); 105 sta_params->sgi_20Mhz = is_cap_supported(caps, 106 IEEE80211_HT_CAP_SGI_20); 107 sta_params->sgi_40mhz = is_cap_supported(caps, 108 IEEE80211_HT_CAP_SGI_40); 109 sta_params->green_field_capable = is_cap_supported(caps, 110 IEEE80211_HT_CAP_GRN_FLD); 111 sta_params->delayed_ba_support = is_cap_supported(caps, 112 IEEE80211_HT_CAP_DELAY_BA); 113 sta_params->dsss_cck_mode_40mhz = is_cap_supported(caps, 114 IEEE80211_HT_CAP_DSSSCCK40); 115 } 116 } 117 118 static void wcn36xx_smd_set_sta_params(struct wcn36xx *wcn, 119 struct ieee80211_vif *vif, 120 struct ieee80211_sta *sta, 121 struct wcn36xx_hal_config_sta_params *sta_params) 122 { 123 struct wcn36xx_vif *priv_vif = (struct wcn36xx_vif *)vif->drv_priv; 124 struct wcn36xx_sta *priv_sta = NULL; 125 if (vif->type == NL80211_IFTYPE_ADHOC || 126 vif->type == NL80211_IFTYPE_AP || 127 vif->type == NL80211_IFTYPE_MESH_POINT) { 128 sta_params->type = 1; 129 sta_params->sta_index = 0xFF; 130 } else { 131 sta_params->type = 0; 132 sta_params->sta_index = 1; 133 } 134 135 sta_params->listen_interval = WCN36XX_LISTEN_INTERVAL(wcn); 136 137 /* 138 * In STA mode ieee80211_sta contains bssid and ieee80211_vif 139 * contains our mac address. In AP mode we are bssid so vif 140 * contains bssid and ieee80211_sta contains mac. 141 */ 142 if (NL80211_IFTYPE_STATION == vif->type) 143 memcpy(&sta_params->mac, vif->addr, ETH_ALEN); 144 else 145 memcpy(&sta_params->bssid, vif->addr, ETH_ALEN); 146 147 sta_params->encrypt_type = priv_vif->encrypt_type; 148 sta_params->short_preamble_supported = 149 !(WCN36XX_FLAGS(wcn) & 150 IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE); 151 152 sta_params->rifs_mode = 0; 153 sta_params->rmf = 0; 154 sta_params->action = 0; 155 sta_params->uapsd = 0; 156 sta_params->mimo_ps = WCN36XX_HAL_HT_MIMO_PS_STATIC; 157 sta_params->max_ampdu_duration = 0; 158 sta_params->bssid_index = priv_vif->bss_index; 159 sta_params->p2p = 0; 160 161 if (sta) { 162 priv_sta = (struct wcn36xx_sta *)sta->drv_priv; 163 if (NL80211_IFTYPE_STATION == vif->type) 164 memcpy(&sta_params->bssid, sta->addr, ETH_ALEN); 165 else 166 memcpy(&sta_params->mac, sta->addr, ETH_ALEN); 167 sta_params->wmm_enabled = sta->wme; 168 sta_params->max_sp_len = sta->max_sp; 169 sta_params->aid = priv_sta->aid; 170 wcn36xx_smd_set_sta_ht_params(sta, sta_params); 171 memcpy(&sta_params->supported_rates, &priv_sta->supported_rates, 172 sizeof(priv_sta->supported_rates)); 173 } else { 174 wcn36xx_set_default_rates(&sta_params->supported_rates); 175 } 176 } 177 178 static int wcn36xx_smd_send_and_wait(struct wcn36xx *wcn, size_t len) 179 { 180 int ret = 0; 181 wcn36xx_dbg_dump(WCN36XX_DBG_SMD_DUMP, "HAL >>> ", wcn->hal_buf, len); 182 183 init_completion(&wcn->hal_rsp_compl); 184 ret = wcn->ctrl_ops->tx(wcn->hal_buf, len); 185 if (ret) { 186 wcn36xx_err("HAL TX failed\n"); 187 goto out; 188 } 189 if (wait_for_completion_timeout(&wcn->hal_rsp_compl, 190 msecs_to_jiffies(HAL_MSG_TIMEOUT)) <= 0) { 191 wcn36xx_err("Timeout while waiting SMD response\n"); 192 ret = -ETIME; 193 goto out; 194 } 195 out: 196 return ret; 197 } 198 199 #define INIT_HAL_MSG(msg_body, type) \ 200 do { \ 201 memset(&msg_body, 0, sizeof(msg_body)); \ 202 msg_body.header.msg_type = type; \ 203 msg_body.header.msg_version = WCN36XX_HAL_MSG_VERSION0; \ 204 msg_body.header.len = sizeof(msg_body); \ 205 } while (0) \ 206 207 #define PREPARE_HAL_BUF(send_buf, msg_body) \ 208 do { \ 209 memset(send_buf, 0, msg_body.header.len); \ 210 memcpy(send_buf, &msg_body, sizeof(msg_body)); \ 211 } while (0) \ 212 213 static int wcn36xx_smd_rsp_status_check(void *buf, size_t len) 214 { 215 struct wcn36xx_fw_msg_status_rsp *rsp; 216 217 if (len < sizeof(struct wcn36xx_hal_msg_header) + 218 sizeof(struct wcn36xx_fw_msg_status_rsp)) 219 return -EIO; 220 221 rsp = (struct wcn36xx_fw_msg_status_rsp *) 222 (buf + sizeof(struct wcn36xx_hal_msg_header)); 223 224 if (WCN36XX_FW_MSG_RESULT_SUCCESS != rsp->status) 225 return rsp->status; 226 227 return 0; 228 } 229 230 int wcn36xx_smd_load_nv(struct wcn36xx *wcn) 231 { 232 const struct firmware *nv; 233 struct nv_data *nv_d; 234 struct wcn36xx_hal_nv_img_download_req_msg msg_body; 235 int fw_bytes_left; 236 int ret; 237 u16 fm_offset = 0; 238 239 ret = request_firmware(&nv, WLAN_NV_FILE, wcn->dev); 240 if (ret) { 241 wcn36xx_err("Failed to load nv file %s: %d\n", 242 WLAN_NV_FILE, ret); 243 goto out_free_nv; 244 } 245 246 nv_d = (struct nv_data *)nv->data; 247 INIT_HAL_MSG(msg_body, WCN36XX_HAL_DOWNLOAD_NV_REQ); 248 249 msg_body.header.len += WCN36XX_NV_FRAGMENT_SIZE; 250 251 msg_body.frag_number = 0; 252 /* hal_buf must be protected with mutex */ 253 mutex_lock(&wcn->hal_mutex); 254 255 do { 256 fw_bytes_left = nv->size - fm_offset - 4; 257 if (fw_bytes_left > WCN36XX_NV_FRAGMENT_SIZE) { 258 msg_body.last_fragment = 0; 259 msg_body.nv_img_buffer_size = WCN36XX_NV_FRAGMENT_SIZE; 260 } else { 261 msg_body.last_fragment = 1; 262 msg_body.nv_img_buffer_size = fw_bytes_left; 263 264 /* Do not forget update general message len */ 265 msg_body.header.len = sizeof(msg_body) + fw_bytes_left; 266 267 } 268 269 /* Add load NV request message header */ 270 memcpy(wcn->hal_buf, &msg_body, sizeof(msg_body)); 271 272 /* Add NV body itself */ 273 memcpy(wcn->hal_buf + sizeof(msg_body), 274 &nv_d->table + fm_offset, 275 msg_body.nv_img_buffer_size); 276 277 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 278 if (ret) 279 goto out_unlock; 280 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, 281 wcn->hal_rsp_len); 282 if (ret) { 283 wcn36xx_err("hal_load_nv response failed err=%d\n", 284 ret); 285 goto out_unlock; 286 } 287 msg_body.frag_number++; 288 fm_offset += WCN36XX_NV_FRAGMENT_SIZE; 289 290 } while (msg_body.last_fragment != 1); 291 292 out_unlock: 293 mutex_unlock(&wcn->hal_mutex); 294 out_free_nv: 295 release_firmware(nv); 296 297 return ret; 298 } 299 300 static int wcn36xx_smd_start_rsp(struct wcn36xx *wcn, void *buf, size_t len) 301 { 302 struct wcn36xx_hal_mac_start_rsp_msg *rsp; 303 304 if (len < sizeof(*rsp)) 305 return -EIO; 306 307 rsp = (struct wcn36xx_hal_mac_start_rsp_msg *)buf; 308 309 if (WCN36XX_FW_MSG_RESULT_SUCCESS != rsp->start_rsp_params.status) 310 return -EIO; 311 312 memcpy(wcn->crm_version, rsp->start_rsp_params.crm_version, 313 WCN36XX_HAL_VERSION_LENGTH); 314 memcpy(wcn->wlan_version, rsp->start_rsp_params.wlan_version, 315 WCN36XX_HAL_VERSION_LENGTH); 316 317 /* null terminate the strings, just in case */ 318 wcn->crm_version[WCN36XX_HAL_VERSION_LENGTH] = '\0'; 319 wcn->wlan_version[WCN36XX_HAL_VERSION_LENGTH] = '\0'; 320 321 wcn->fw_revision = rsp->start_rsp_params.version.revision; 322 wcn->fw_version = rsp->start_rsp_params.version.version; 323 wcn->fw_minor = rsp->start_rsp_params.version.minor; 324 wcn->fw_major = rsp->start_rsp_params.version.major; 325 326 wcn36xx_info("firmware WLAN version '%s' and CRM version '%s'\n", 327 wcn->wlan_version, wcn->crm_version); 328 329 wcn36xx_info("firmware API %u.%u.%u.%u, %u stations, %u bssids\n", 330 wcn->fw_major, wcn->fw_minor, 331 wcn->fw_version, wcn->fw_revision, 332 rsp->start_rsp_params.stations, 333 rsp->start_rsp_params.bssids); 334 335 return 0; 336 } 337 338 int wcn36xx_smd_start(struct wcn36xx *wcn) 339 { 340 struct wcn36xx_hal_mac_start_req_msg msg_body; 341 int ret = 0; 342 343 mutex_lock(&wcn->hal_mutex); 344 INIT_HAL_MSG(msg_body, WCN36XX_HAL_START_REQ); 345 346 msg_body.params.type = DRIVER_TYPE_PRODUCTION; 347 msg_body.params.len = 0; 348 349 PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 350 351 wcn36xx_dbg(WCN36XX_DBG_HAL, "hal start type %d\n", 352 msg_body.params.type); 353 354 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 355 if (ret) { 356 wcn36xx_err("Sending hal_start failed\n"); 357 goto out; 358 } 359 360 ret = wcn36xx_smd_start_rsp(wcn, wcn->hal_buf, wcn->hal_rsp_len); 361 if (ret) { 362 wcn36xx_err("hal_start response failed err=%d\n", ret); 363 goto out; 364 } 365 366 out: 367 mutex_unlock(&wcn->hal_mutex); 368 return ret; 369 } 370 371 int wcn36xx_smd_stop(struct wcn36xx *wcn) 372 { 373 struct wcn36xx_hal_mac_stop_req_msg msg_body; 374 int ret = 0; 375 376 mutex_lock(&wcn->hal_mutex); 377 INIT_HAL_MSG(msg_body, WCN36XX_HAL_STOP_REQ); 378 379 msg_body.stop_req_params.reason = HAL_STOP_TYPE_RF_KILL; 380 381 PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 382 383 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 384 if (ret) { 385 wcn36xx_err("Sending hal_stop failed\n"); 386 goto out; 387 } 388 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); 389 if (ret) { 390 wcn36xx_err("hal_stop response failed err=%d\n", ret); 391 goto out; 392 } 393 out: 394 mutex_unlock(&wcn->hal_mutex); 395 return ret; 396 } 397 398 int wcn36xx_smd_init_scan(struct wcn36xx *wcn, enum wcn36xx_hal_sys_mode mode) 399 { 400 struct wcn36xx_hal_init_scan_req_msg msg_body; 401 int ret = 0; 402 403 mutex_lock(&wcn->hal_mutex); 404 INIT_HAL_MSG(msg_body, WCN36XX_HAL_INIT_SCAN_REQ); 405 406 msg_body.mode = mode; 407 408 PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 409 410 wcn36xx_dbg(WCN36XX_DBG_HAL, "hal init scan mode %d\n", msg_body.mode); 411 412 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 413 if (ret) { 414 wcn36xx_err("Sending hal_init_scan failed\n"); 415 goto out; 416 } 417 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); 418 if (ret) { 419 wcn36xx_err("hal_init_scan response failed err=%d\n", ret); 420 goto out; 421 } 422 out: 423 mutex_unlock(&wcn->hal_mutex); 424 return ret; 425 } 426 427 int wcn36xx_smd_start_scan(struct wcn36xx *wcn) 428 { 429 struct wcn36xx_hal_start_scan_req_msg msg_body; 430 int ret = 0; 431 432 mutex_lock(&wcn->hal_mutex); 433 INIT_HAL_MSG(msg_body, WCN36XX_HAL_START_SCAN_REQ); 434 435 msg_body.scan_channel = WCN36XX_HW_CHANNEL(wcn); 436 437 PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 438 439 wcn36xx_dbg(WCN36XX_DBG_HAL, "hal start scan channel %d\n", 440 msg_body.scan_channel); 441 442 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 443 if (ret) { 444 wcn36xx_err("Sending hal_start_scan failed\n"); 445 goto out; 446 } 447 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); 448 if (ret) { 449 wcn36xx_err("hal_start_scan response failed err=%d\n", ret); 450 goto out; 451 } 452 out: 453 mutex_unlock(&wcn->hal_mutex); 454 return ret; 455 } 456 457 int wcn36xx_smd_end_scan(struct wcn36xx *wcn) 458 { 459 struct wcn36xx_hal_end_scan_req_msg msg_body; 460 int ret = 0; 461 462 mutex_lock(&wcn->hal_mutex); 463 INIT_HAL_MSG(msg_body, WCN36XX_HAL_END_SCAN_REQ); 464 465 msg_body.scan_channel = WCN36XX_HW_CHANNEL(wcn); 466 467 PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 468 469 wcn36xx_dbg(WCN36XX_DBG_HAL, "hal end scan channel %d\n", 470 msg_body.scan_channel); 471 472 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 473 if (ret) { 474 wcn36xx_err("Sending hal_end_scan failed\n"); 475 goto out; 476 } 477 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); 478 if (ret) { 479 wcn36xx_err("hal_end_scan response failed err=%d\n", ret); 480 goto out; 481 } 482 out: 483 mutex_unlock(&wcn->hal_mutex); 484 return ret; 485 } 486 487 int wcn36xx_smd_finish_scan(struct wcn36xx *wcn, 488 enum wcn36xx_hal_sys_mode mode) 489 { 490 struct wcn36xx_hal_finish_scan_req_msg msg_body; 491 int ret = 0; 492 493 mutex_lock(&wcn->hal_mutex); 494 INIT_HAL_MSG(msg_body, WCN36XX_HAL_FINISH_SCAN_REQ); 495 496 msg_body.mode = mode; 497 498 PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 499 500 wcn36xx_dbg(WCN36XX_DBG_HAL, "hal finish scan mode %d\n", 501 msg_body.mode); 502 503 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 504 if (ret) { 505 wcn36xx_err("Sending hal_finish_scan failed\n"); 506 goto out; 507 } 508 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); 509 if (ret) { 510 wcn36xx_err("hal_finish_scan response failed err=%d\n", ret); 511 goto out; 512 } 513 out: 514 mutex_unlock(&wcn->hal_mutex); 515 return ret; 516 } 517 518 static int wcn36xx_smd_switch_channel_rsp(void *buf, size_t len) 519 { 520 struct wcn36xx_hal_switch_channel_rsp_msg *rsp; 521 int ret = 0; 522 523 ret = wcn36xx_smd_rsp_status_check(buf, len); 524 if (ret) 525 return ret; 526 rsp = (struct wcn36xx_hal_switch_channel_rsp_msg *)buf; 527 wcn36xx_dbg(WCN36XX_DBG_HAL, "channel switched to: %d, status: %d\n", 528 rsp->channel_number, rsp->status); 529 return ret; 530 } 531 532 int wcn36xx_smd_switch_channel(struct wcn36xx *wcn, 533 struct ieee80211_vif *vif, int ch) 534 { 535 struct wcn36xx_hal_switch_channel_req_msg msg_body; 536 int ret = 0; 537 538 mutex_lock(&wcn->hal_mutex); 539 INIT_HAL_MSG(msg_body, WCN36XX_HAL_CH_SWITCH_REQ); 540 541 msg_body.channel_number = (u8)ch; 542 msg_body.tx_mgmt_power = 0xbf; 543 msg_body.max_tx_power = 0xbf; 544 memcpy(msg_body.self_sta_mac_addr, vif->addr, ETH_ALEN); 545 546 PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 547 548 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 549 if (ret) { 550 wcn36xx_err("Sending hal_switch_channel failed\n"); 551 goto out; 552 } 553 ret = wcn36xx_smd_switch_channel_rsp(wcn->hal_buf, wcn->hal_rsp_len); 554 if (ret) { 555 wcn36xx_err("hal_switch_channel response failed err=%d\n", ret); 556 goto out; 557 } 558 out: 559 mutex_unlock(&wcn->hal_mutex); 560 return ret; 561 } 562 563 static int wcn36xx_smd_update_scan_params_rsp(void *buf, size_t len) 564 { 565 struct wcn36xx_hal_update_scan_params_resp *rsp; 566 567 rsp = (struct wcn36xx_hal_update_scan_params_resp *)buf; 568 569 /* Remove the PNO version bit */ 570 rsp->status &= (~(WCN36XX_FW_MSG_PNO_VERSION_MASK)); 571 572 if (WCN36XX_FW_MSG_RESULT_SUCCESS != rsp->status) { 573 wcn36xx_warn("error response from update scan\n"); 574 return rsp->status; 575 } 576 577 return 0; 578 } 579 580 int wcn36xx_smd_update_scan_params(struct wcn36xx *wcn) 581 { 582 struct wcn36xx_hal_update_scan_params_req msg_body; 583 int ret = 0; 584 585 mutex_lock(&wcn->hal_mutex); 586 INIT_HAL_MSG(msg_body, WCN36XX_HAL_UPDATE_SCAN_PARAM_REQ); 587 588 msg_body.dot11d_enabled = 0; 589 msg_body.dot11d_resolved = 0; 590 msg_body.channel_count = 26; 591 msg_body.active_min_ch_time = 60; 592 msg_body.active_max_ch_time = 120; 593 msg_body.passive_min_ch_time = 60; 594 msg_body.passive_max_ch_time = 110; 595 msg_body.state = 0; 596 597 PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 598 599 wcn36xx_dbg(WCN36XX_DBG_HAL, 600 "hal update scan params channel_count %d\n", 601 msg_body.channel_count); 602 603 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 604 if (ret) { 605 wcn36xx_err("Sending hal_update_scan_params failed\n"); 606 goto out; 607 } 608 ret = wcn36xx_smd_update_scan_params_rsp(wcn->hal_buf, 609 wcn->hal_rsp_len); 610 if (ret) { 611 wcn36xx_err("hal_update_scan_params response failed err=%d\n", 612 ret); 613 goto out; 614 } 615 out: 616 mutex_unlock(&wcn->hal_mutex); 617 return ret; 618 } 619 620 static int wcn36xx_smd_add_sta_self_rsp(struct wcn36xx *wcn, 621 struct ieee80211_vif *vif, 622 void *buf, 623 size_t len) 624 { 625 struct wcn36xx_hal_add_sta_self_rsp_msg *rsp; 626 struct wcn36xx_vif *priv_vif = (struct wcn36xx_vif *)vif->drv_priv; 627 628 if (len < sizeof(*rsp)) 629 return -EINVAL; 630 631 rsp = (struct wcn36xx_hal_add_sta_self_rsp_msg *)buf; 632 633 if (rsp->status != WCN36XX_FW_MSG_RESULT_SUCCESS) { 634 wcn36xx_warn("hal add sta self failure: %d\n", 635 rsp->status); 636 return rsp->status; 637 } 638 639 wcn36xx_dbg(WCN36XX_DBG_HAL, 640 "hal add sta self status %d self_sta_index %d dpu_index %d\n", 641 rsp->status, rsp->self_sta_index, rsp->dpu_index); 642 643 priv_vif->self_sta_index = rsp->self_sta_index; 644 priv_vif->self_dpu_desc_index = rsp->dpu_index; 645 646 return 0; 647 } 648 649 int wcn36xx_smd_add_sta_self(struct wcn36xx *wcn, struct ieee80211_vif *vif) 650 { 651 struct wcn36xx_hal_add_sta_self_req msg_body; 652 int ret = 0; 653 654 mutex_lock(&wcn->hal_mutex); 655 INIT_HAL_MSG(msg_body, WCN36XX_HAL_ADD_STA_SELF_REQ); 656 657 memcpy(&msg_body.self_addr, vif->addr, ETH_ALEN); 658 659 PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 660 661 wcn36xx_dbg(WCN36XX_DBG_HAL, 662 "hal add sta self self_addr %pM status %d\n", 663 msg_body.self_addr, msg_body.status); 664 665 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 666 if (ret) { 667 wcn36xx_err("Sending hal_add_sta_self failed\n"); 668 goto out; 669 } 670 ret = wcn36xx_smd_add_sta_self_rsp(wcn, 671 vif, 672 wcn->hal_buf, 673 wcn->hal_rsp_len); 674 if (ret) { 675 wcn36xx_err("hal_add_sta_self response failed err=%d\n", ret); 676 goto out; 677 } 678 out: 679 mutex_unlock(&wcn->hal_mutex); 680 return ret; 681 } 682 683 int wcn36xx_smd_delete_sta_self(struct wcn36xx *wcn, u8 *addr) 684 { 685 struct wcn36xx_hal_del_sta_self_req_msg msg_body; 686 int ret = 0; 687 688 mutex_lock(&wcn->hal_mutex); 689 INIT_HAL_MSG(msg_body, WCN36XX_HAL_DEL_STA_SELF_REQ); 690 691 memcpy(&msg_body.self_addr, addr, ETH_ALEN); 692 693 PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 694 695 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 696 if (ret) { 697 wcn36xx_err("Sending hal_delete_sta_self failed\n"); 698 goto out; 699 } 700 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); 701 if (ret) { 702 wcn36xx_err("hal_delete_sta_self response failed err=%d\n", 703 ret); 704 goto out; 705 } 706 out: 707 mutex_unlock(&wcn->hal_mutex); 708 return ret; 709 } 710 711 int wcn36xx_smd_delete_sta(struct wcn36xx *wcn, u8 sta_index) 712 { 713 struct wcn36xx_hal_delete_sta_req_msg msg_body; 714 int ret = 0; 715 716 mutex_lock(&wcn->hal_mutex); 717 INIT_HAL_MSG(msg_body, WCN36XX_HAL_DELETE_STA_REQ); 718 719 msg_body.sta_index = sta_index; 720 721 PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 722 723 wcn36xx_dbg(WCN36XX_DBG_HAL, 724 "hal delete sta sta_index %d\n", 725 msg_body.sta_index); 726 727 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 728 if (ret) { 729 wcn36xx_err("Sending hal_delete_sta failed\n"); 730 goto out; 731 } 732 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); 733 if (ret) { 734 wcn36xx_err("hal_delete_sta response failed err=%d\n", ret); 735 goto out; 736 } 737 out: 738 mutex_unlock(&wcn->hal_mutex); 739 return ret; 740 } 741 742 static int wcn36xx_smd_join_rsp(void *buf, size_t len) 743 { 744 struct wcn36xx_hal_join_rsp_msg *rsp; 745 746 if (wcn36xx_smd_rsp_status_check(buf, len)) 747 return -EIO; 748 749 rsp = (struct wcn36xx_hal_join_rsp_msg *)buf; 750 751 wcn36xx_dbg(WCN36XX_DBG_HAL, 752 "hal rsp join status %d tx_mgmt_power %d\n", 753 rsp->status, rsp->tx_mgmt_power); 754 755 return 0; 756 } 757 758 int wcn36xx_smd_join(struct wcn36xx *wcn, const u8 *bssid, u8 *vif, u8 ch) 759 { 760 struct wcn36xx_hal_join_req_msg msg_body; 761 int ret = 0; 762 763 mutex_lock(&wcn->hal_mutex); 764 INIT_HAL_MSG(msg_body, WCN36XX_HAL_JOIN_REQ); 765 766 memcpy(&msg_body.bssid, bssid, ETH_ALEN); 767 memcpy(&msg_body.self_sta_mac_addr, vif, ETH_ALEN); 768 msg_body.channel = ch; 769 770 if (conf_is_ht40_minus(&wcn->hw->conf)) 771 msg_body.secondary_channel_offset = 772 PHY_DOUBLE_CHANNEL_HIGH_PRIMARY; 773 else if (conf_is_ht40_plus(&wcn->hw->conf)) 774 msg_body.secondary_channel_offset = 775 PHY_DOUBLE_CHANNEL_LOW_PRIMARY; 776 else 777 msg_body.secondary_channel_offset = 778 PHY_SINGLE_CHANNEL_CENTERED; 779 780 msg_body.link_state = WCN36XX_HAL_LINK_PREASSOC_STATE; 781 782 msg_body.max_tx_power = 0xbf; 783 PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 784 785 wcn36xx_dbg(WCN36XX_DBG_HAL, 786 "hal join req bssid %pM self_sta_mac_addr %pM channel %d link_state %d\n", 787 msg_body.bssid, msg_body.self_sta_mac_addr, 788 msg_body.channel, msg_body.link_state); 789 790 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 791 if (ret) { 792 wcn36xx_err("Sending hal_join failed\n"); 793 goto out; 794 } 795 ret = wcn36xx_smd_join_rsp(wcn->hal_buf, wcn->hal_rsp_len); 796 if (ret) { 797 wcn36xx_err("hal_join response failed err=%d\n", ret); 798 goto out; 799 } 800 out: 801 mutex_unlock(&wcn->hal_mutex); 802 return ret; 803 } 804 805 int wcn36xx_smd_set_link_st(struct wcn36xx *wcn, const u8 *bssid, 806 const u8 *sta_mac, 807 enum wcn36xx_hal_link_state state) 808 { 809 struct wcn36xx_hal_set_link_state_req_msg msg_body; 810 int ret = 0; 811 812 mutex_lock(&wcn->hal_mutex); 813 INIT_HAL_MSG(msg_body, WCN36XX_HAL_SET_LINK_ST_REQ); 814 815 memcpy(&msg_body.bssid, bssid, ETH_ALEN); 816 memcpy(&msg_body.self_mac_addr, sta_mac, ETH_ALEN); 817 msg_body.state = state; 818 819 PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 820 821 wcn36xx_dbg(WCN36XX_DBG_HAL, 822 "hal set link state bssid %pM self_mac_addr %pM state %d\n", 823 msg_body.bssid, msg_body.self_mac_addr, msg_body.state); 824 825 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 826 if (ret) { 827 wcn36xx_err("Sending hal_set_link_st failed\n"); 828 goto out; 829 } 830 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); 831 if (ret) { 832 wcn36xx_err("hal_set_link_st response failed err=%d\n", ret); 833 goto out; 834 } 835 out: 836 mutex_unlock(&wcn->hal_mutex); 837 return ret; 838 } 839 840 static void wcn36xx_smd_convert_sta_to_v1(struct wcn36xx *wcn, 841 const struct wcn36xx_hal_config_sta_params *orig, 842 struct wcn36xx_hal_config_sta_params_v1 *v1) 843 { 844 /* convert orig to v1 format */ 845 memcpy(&v1->bssid, orig->bssid, ETH_ALEN); 846 memcpy(&v1->mac, orig->mac, ETH_ALEN); 847 v1->aid = orig->aid; 848 v1->type = orig->type; 849 v1->listen_interval = orig->listen_interval; 850 v1->ht_capable = orig->ht_capable; 851 852 v1->max_ampdu_size = orig->max_ampdu_size; 853 v1->max_ampdu_density = orig->max_ampdu_density; 854 v1->sgi_40mhz = orig->sgi_40mhz; 855 v1->sgi_20Mhz = orig->sgi_20Mhz; 856 857 memcpy(&v1->supported_rates, &orig->supported_rates, 858 sizeof(orig->supported_rates)); 859 v1->sta_index = orig->sta_index; 860 } 861 862 static int wcn36xx_smd_config_sta_rsp(struct wcn36xx *wcn, 863 struct ieee80211_sta *sta, 864 void *buf, 865 size_t len) 866 { 867 struct wcn36xx_hal_config_sta_rsp_msg *rsp; 868 struct config_sta_rsp_params *params; 869 struct wcn36xx_sta *sta_priv = (struct wcn36xx_sta *)sta->drv_priv; 870 871 if (len < sizeof(*rsp)) 872 return -EINVAL; 873 874 rsp = (struct wcn36xx_hal_config_sta_rsp_msg *)buf; 875 params = &rsp->params; 876 877 if (params->status != WCN36XX_FW_MSG_RESULT_SUCCESS) { 878 wcn36xx_warn("hal config sta response failure: %d\n", 879 params->status); 880 return -EIO; 881 } 882 883 sta_priv->sta_index = params->sta_index; 884 sta_priv->dpu_desc_index = params->dpu_index; 885 886 wcn36xx_dbg(WCN36XX_DBG_HAL, 887 "hal config sta rsp status %d sta_index %d bssid_index %d p2p %d\n", 888 params->status, params->sta_index, params->bssid_index, 889 params->p2p); 890 891 return 0; 892 } 893 894 static int wcn36xx_smd_config_sta_v1(struct wcn36xx *wcn, 895 const struct wcn36xx_hal_config_sta_req_msg *orig) 896 { 897 struct wcn36xx_hal_config_sta_req_msg_v1 msg_body; 898 struct wcn36xx_hal_config_sta_params_v1 *sta = &msg_body.sta_params; 899 900 INIT_HAL_MSG(msg_body, WCN36XX_HAL_CONFIG_STA_REQ); 901 902 wcn36xx_smd_convert_sta_to_v1(wcn, &orig->sta_params, 903 &msg_body.sta_params); 904 905 PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 906 907 wcn36xx_dbg(WCN36XX_DBG_HAL, 908 "hal config sta v1 action %d sta_index %d bssid_index %d bssid %pM type %d mac %pM aid %d\n", 909 sta->action, sta->sta_index, sta->bssid_index, 910 sta->bssid, sta->type, sta->mac, sta->aid); 911 912 return wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 913 } 914 915 int wcn36xx_smd_config_sta(struct wcn36xx *wcn, struct ieee80211_vif *vif, 916 struct ieee80211_sta *sta) 917 { 918 struct wcn36xx_hal_config_sta_req_msg msg; 919 struct wcn36xx_hal_config_sta_params *sta_params; 920 int ret = 0; 921 922 mutex_lock(&wcn->hal_mutex); 923 INIT_HAL_MSG(msg, WCN36XX_HAL_CONFIG_STA_REQ); 924 925 sta_params = &msg.sta_params; 926 927 wcn36xx_smd_set_sta_params(wcn, vif, sta, sta_params); 928 929 if (!wcn36xx_is_fw_version(wcn, 1, 2, 2, 24)) { 930 ret = wcn36xx_smd_config_sta_v1(wcn, &msg); 931 } else { 932 PREPARE_HAL_BUF(wcn->hal_buf, msg); 933 934 wcn36xx_dbg(WCN36XX_DBG_HAL, 935 "hal config sta action %d sta_index %d bssid_index %d bssid %pM type %d mac %pM aid %d\n", 936 sta_params->action, sta_params->sta_index, 937 sta_params->bssid_index, sta_params->bssid, 938 sta_params->type, sta_params->mac, sta_params->aid); 939 940 ret = wcn36xx_smd_send_and_wait(wcn, msg.header.len); 941 } 942 if (ret) { 943 wcn36xx_err("Sending hal_config_sta failed\n"); 944 goto out; 945 } 946 ret = wcn36xx_smd_config_sta_rsp(wcn, 947 sta, 948 wcn->hal_buf, 949 wcn->hal_rsp_len); 950 if (ret) { 951 wcn36xx_err("hal_config_sta response failed err=%d\n", ret); 952 goto out; 953 } 954 out: 955 mutex_unlock(&wcn->hal_mutex); 956 return ret; 957 } 958 959 static int wcn36xx_smd_config_bss_v1(struct wcn36xx *wcn, 960 const struct wcn36xx_hal_config_bss_req_msg *orig) 961 { 962 struct wcn36xx_hal_config_bss_req_msg_v1 msg_body; 963 struct wcn36xx_hal_config_bss_params_v1 *bss = &msg_body.bss_params; 964 struct wcn36xx_hal_config_sta_params_v1 *sta = &bss->sta; 965 966 INIT_HAL_MSG(msg_body, WCN36XX_HAL_CONFIG_BSS_REQ); 967 968 /* convert orig to v1 */ 969 memcpy(&msg_body.bss_params.bssid, 970 &orig->bss_params.bssid, ETH_ALEN); 971 memcpy(&msg_body.bss_params.self_mac_addr, 972 &orig->bss_params.self_mac_addr, ETH_ALEN); 973 974 msg_body.bss_params.bss_type = orig->bss_params.bss_type; 975 msg_body.bss_params.oper_mode = orig->bss_params.oper_mode; 976 msg_body.bss_params.nw_type = orig->bss_params.nw_type; 977 978 msg_body.bss_params.short_slot_time_supported = 979 orig->bss_params.short_slot_time_supported; 980 msg_body.bss_params.lla_coexist = orig->bss_params.lla_coexist; 981 msg_body.bss_params.llb_coexist = orig->bss_params.llb_coexist; 982 msg_body.bss_params.llg_coexist = orig->bss_params.llg_coexist; 983 msg_body.bss_params.ht20_coexist = orig->bss_params.ht20_coexist; 984 msg_body.bss_params.lln_non_gf_coexist = 985 orig->bss_params.lln_non_gf_coexist; 986 987 msg_body.bss_params.lsig_tx_op_protection_full_support = 988 orig->bss_params.lsig_tx_op_protection_full_support; 989 msg_body.bss_params.rifs_mode = orig->bss_params.rifs_mode; 990 msg_body.bss_params.beacon_interval = orig->bss_params.beacon_interval; 991 msg_body.bss_params.dtim_period = orig->bss_params.dtim_period; 992 msg_body.bss_params.tx_channel_width_set = 993 orig->bss_params.tx_channel_width_set; 994 msg_body.bss_params.oper_channel = orig->bss_params.oper_channel; 995 msg_body.bss_params.ext_channel = orig->bss_params.ext_channel; 996 997 msg_body.bss_params.reserved = orig->bss_params.reserved; 998 999 memcpy(&msg_body.bss_params.ssid, 1000 &orig->bss_params.ssid, 1001 sizeof(orig->bss_params.ssid)); 1002 1003 msg_body.bss_params.action = orig->bss_params.action; 1004 msg_body.bss_params.rateset = orig->bss_params.rateset; 1005 msg_body.bss_params.ht = orig->bss_params.ht; 1006 msg_body.bss_params.obss_prot_enabled = 1007 orig->bss_params.obss_prot_enabled; 1008 msg_body.bss_params.rmf = orig->bss_params.rmf; 1009 msg_body.bss_params.ht_oper_mode = orig->bss_params.ht_oper_mode; 1010 msg_body.bss_params.dual_cts_protection = 1011 orig->bss_params.dual_cts_protection; 1012 1013 msg_body.bss_params.max_probe_resp_retry_limit = 1014 orig->bss_params.max_probe_resp_retry_limit; 1015 msg_body.bss_params.hidden_ssid = orig->bss_params.hidden_ssid; 1016 msg_body.bss_params.proxy_probe_resp = 1017 orig->bss_params.proxy_probe_resp; 1018 msg_body.bss_params.edca_params_valid = 1019 orig->bss_params.edca_params_valid; 1020 1021 memcpy(&msg_body.bss_params.acbe, 1022 &orig->bss_params.acbe, 1023 sizeof(orig->bss_params.acbe)); 1024 memcpy(&msg_body.bss_params.acbk, 1025 &orig->bss_params.acbk, 1026 sizeof(orig->bss_params.acbk)); 1027 memcpy(&msg_body.bss_params.acvi, 1028 &orig->bss_params.acvi, 1029 sizeof(orig->bss_params.acvi)); 1030 memcpy(&msg_body.bss_params.acvo, 1031 &orig->bss_params.acvo, 1032 sizeof(orig->bss_params.acvo)); 1033 1034 msg_body.bss_params.ext_set_sta_key_param_valid = 1035 orig->bss_params.ext_set_sta_key_param_valid; 1036 1037 memcpy(&msg_body.bss_params.ext_set_sta_key_param, 1038 &orig->bss_params.ext_set_sta_key_param, 1039 sizeof(orig->bss_params.acvo)); 1040 1041 msg_body.bss_params.wcn36xx_hal_persona = 1042 orig->bss_params.wcn36xx_hal_persona; 1043 msg_body.bss_params.spectrum_mgt_enable = 1044 orig->bss_params.spectrum_mgt_enable; 1045 msg_body.bss_params.tx_mgmt_power = orig->bss_params.tx_mgmt_power; 1046 msg_body.bss_params.max_tx_power = orig->bss_params.max_tx_power; 1047 1048 wcn36xx_smd_convert_sta_to_v1(wcn, &orig->bss_params.sta, 1049 &msg_body.bss_params.sta); 1050 1051 PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 1052 1053 wcn36xx_dbg(WCN36XX_DBG_HAL, 1054 "hal config bss v1 bssid %pM self_mac_addr %pM bss_type %d oper_mode %d nw_type %d\n", 1055 bss->bssid, bss->self_mac_addr, bss->bss_type, 1056 bss->oper_mode, bss->nw_type); 1057 1058 wcn36xx_dbg(WCN36XX_DBG_HAL, 1059 "- sta bssid %pM action %d sta_index %d bssid_index %d aid %d type %d mac %pM\n", 1060 sta->bssid, sta->action, sta->sta_index, 1061 sta->bssid_index, sta->aid, sta->type, sta->mac); 1062 1063 return wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 1064 } 1065 1066 1067 static int wcn36xx_smd_config_bss_rsp(struct wcn36xx *wcn, 1068 struct ieee80211_vif *vif, 1069 void *buf, 1070 size_t len) 1071 { 1072 struct wcn36xx_hal_config_bss_rsp_msg *rsp; 1073 struct wcn36xx_hal_config_bss_rsp_params *params; 1074 struct wcn36xx_vif *priv_vif = (struct wcn36xx_vif *)vif->drv_priv; 1075 1076 if (len < sizeof(*rsp)) 1077 return -EINVAL; 1078 1079 rsp = (struct wcn36xx_hal_config_bss_rsp_msg *)buf; 1080 params = &rsp->bss_rsp_params; 1081 1082 if (params->status != WCN36XX_FW_MSG_RESULT_SUCCESS) { 1083 wcn36xx_warn("hal config bss response failure: %d\n", 1084 params->status); 1085 return -EIO; 1086 } 1087 1088 wcn36xx_dbg(WCN36XX_DBG_HAL, 1089 "hal config bss rsp status %d bss_idx %d dpu_desc_index %d" 1090 " sta_idx %d self_idx %d bcast_idx %d mac %pM" 1091 " power %d ucast_dpu_signature %d\n", 1092 params->status, params->bss_index, params->dpu_desc_index, 1093 params->bss_sta_index, params->bss_self_sta_index, 1094 params->bss_bcast_sta_idx, params->mac, 1095 params->tx_mgmt_power, params->ucast_dpu_signature); 1096 1097 priv_vif->bss_index = params->bss_index; 1098 1099 if (priv_vif->sta) { 1100 priv_vif->sta->bss_sta_index = params->bss_sta_index; 1101 priv_vif->sta->bss_dpu_desc_index = params->dpu_desc_index; 1102 } 1103 1104 priv_vif->ucast_dpu_signature = params->ucast_dpu_signature; 1105 1106 return 0; 1107 } 1108 1109 int wcn36xx_smd_config_bss(struct wcn36xx *wcn, struct ieee80211_vif *vif, 1110 struct ieee80211_sta *sta, const u8 *bssid, 1111 bool update) 1112 { 1113 struct wcn36xx_hal_config_bss_req_msg msg; 1114 struct wcn36xx_hal_config_bss_params *bss; 1115 struct wcn36xx_hal_config_sta_params *sta_params; 1116 struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; 1117 int ret = 0; 1118 1119 mutex_lock(&wcn->hal_mutex); 1120 INIT_HAL_MSG(msg, WCN36XX_HAL_CONFIG_BSS_REQ); 1121 1122 bss = &msg.bss_params; 1123 sta_params = &bss->sta; 1124 1125 WARN_ON(is_zero_ether_addr(bssid)); 1126 1127 memcpy(&bss->bssid, bssid, ETH_ALEN); 1128 1129 memcpy(bss->self_mac_addr, vif->addr, ETH_ALEN); 1130 1131 if (vif->type == NL80211_IFTYPE_STATION) { 1132 bss->bss_type = WCN36XX_HAL_INFRASTRUCTURE_MODE; 1133 1134 /* STA */ 1135 bss->oper_mode = 1; 1136 bss->wcn36xx_hal_persona = WCN36XX_HAL_STA_MODE; 1137 } else if (vif->type == NL80211_IFTYPE_AP) { 1138 bss->bss_type = WCN36XX_HAL_INFRA_AP_MODE; 1139 1140 /* AP */ 1141 bss->oper_mode = 0; 1142 bss->wcn36xx_hal_persona = WCN36XX_HAL_STA_SAP_MODE; 1143 } else if (vif->type == NL80211_IFTYPE_ADHOC || 1144 vif->type == NL80211_IFTYPE_MESH_POINT) { 1145 bss->bss_type = WCN36XX_HAL_IBSS_MODE; 1146 1147 /* STA */ 1148 bss->oper_mode = 1; 1149 } else { 1150 wcn36xx_warn("Unknown type for bss config: %d\n", vif->type); 1151 } 1152 1153 if (vif->type == NL80211_IFTYPE_STATION) 1154 wcn36xx_smd_set_bss_nw_type(wcn, sta, bss); 1155 else 1156 bss->nw_type = WCN36XX_HAL_11N_NW_TYPE; 1157 1158 bss->short_slot_time_supported = vif->bss_conf.use_short_slot; 1159 bss->lla_coexist = 0; 1160 bss->llb_coexist = 0; 1161 bss->llg_coexist = 0; 1162 bss->rifs_mode = 0; 1163 bss->beacon_interval = vif->bss_conf.beacon_int; 1164 bss->dtim_period = vif_priv->dtim_period; 1165 1166 wcn36xx_smd_set_bss_ht_params(vif, sta, bss); 1167 1168 bss->oper_channel = WCN36XX_HW_CHANNEL(wcn); 1169 1170 if (conf_is_ht40_minus(&wcn->hw->conf)) 1171 bss->ext_channel = IEEE80211_HT_PARAM_CHA_SEC_BELOW; 1172 else if (conf_is_ht40_plus(&wcn->hw->conf)) 1173 bss->ext_channel = IEEE80211_HT_PARAM_CHA_SEC_ABOVE; 1174 else 1175 bss->ext_channel = IEEE80211_HT_PARAM_CHA_SEC_NONE; 1176 1177 bss->reserved = 0; 1178 wcn36xx_smd_set_sta_params(wcn, vif, sta, sta_params); 1179 1180 /* wcn->ssid is only valid in AP and IBSS mode */ 1181 bss->ssid.length = vif_priv->ssid.length; 1182 memcpy(bss->ssid.ssid, vif_priv->ssid.ssid, vif_priv->ssid.length); 1183 1184 bss->obss_prot_enabled = 0; 1185 bss->rmf = 0; 1186 bss->max_probe_resp_retry_limit = 0; 1187 bss->hidden_ssid = vif->bss_conf.hidden_ssid; 1188 bss->proxy_probe_resp = 0; 1189 bss->edca_params_valid = 0; 1190 1191 /* FIXME: set acbe, acbk, acvi and acvo */ 1192 1193 bss->ext_set_sta_key_param_valid = 0; 1194 1195 /* FIXME: set ext_set_sta_key_param */ 1196 1197 bss->spectrum_mgt_enable = 0; 1198 bss->tx_mgmt_power = 0; 1199 bss->max_tx_power = WCN36XX_MAX_POWER(wcn); 1200 1201 bss->action = update; 1202 1203 wcn36xx_dbg(WCN36XX_DBG_HAL, 1204 "hal config bss bssid %pM self_mac_addr %pM bss_type %d oper_mode %d nw_type %d\n", 1205 bss->bssid, bss->self_mac_addr, bss->bss_type, 1206 bss->oper_mode, bss->nw_type); 1207 1208 wcn36xx_dbg(WCN36XX_DBG_HAL, 1209 "- sta bssid %pM action %d sta_index %d bssid_index %d aid %d type %d mac %pM\n", 1210 sta_params->bssid, sta_params->action, 1211 sta_params->sta_index, sta_params->bssid_index, 1212 sta_params->aid, sta_params->type, 1213 sta_params->mac); 1214 1215 if (!wcn36xx_is_fw_version(wcn, 1, 2, 2, 24)) { 1216 ret = wcn36xx_smd_config_bss_v1(wcn, &msg); 1217 } else { 1218 PREPARE_HAL_BUF(wcn->hal_buf, msg); 1219 1220 ret = wcn36xx_smd_send_and_wait(wcn, msg.header.len); 1221 } 1222 if (ret) { 1223 wcn36xx_err("Sending hal_config_bss failed\n"); 1224 goto out; 1225 } 1226 ret = wcn36xx_smd_config_bss_rsp(wcn, 1227 vif, 1228 wcn->hal_buf, 1229 wcn->hal_rsp_len); 1230 if (ret) { 1231 wcn36xx_err("hal_config_bss response failed err=%d\n", ret); 1232 goto out; 1233 } 1234 out: 1235 mutex_unlock(&wcn->hal_mutex); 1236 return ret; 1237 } 1238 1239 int wcn36xx_smd_delete_bss(struct wcn36xx *wcn, struct ieee80211_vif *vif) 1240 { 1241 struct wcn36xx_hal_delete_bss_req_msg msg_body; 1242 struct wcn36xx_vif *priv_vif = (struct wcn36xx_vif *)vif->drv_priv; 1243 int ret = 0; 1244 1245 mutex_lock(&wcn->hal_mutex); 1246 INIT_HAL_MSG(msg_body, WCN36XX_HAL_DELETE_BSS_REQ); 1247 1248 msg_body.bss_index = priv_vif->bss_index; 1249 1250 PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 1251 1252 wcn36xx_dbg(WCN36XX_DBG_HAL, "hal delete bss %d\n", msg_body.bss_index); 1253 1254 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 1255 if (ret) { 1256 wcn36xx_err("Sending hal_delete_bss failed\n"); 1257 goto out; 1258 } 1259 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); 1260 if (ret) { 1261 wcn36xx_err("hal_delete_bss response failed err=%d\n", ret); 1262 goto out; 1263 } 1264 out: 1265 mutex_unlock(&wcn->hal_mutex); 1266 return ret; 1267 } 1268 1269 int wcn36xx_smd_send_beacon(struct wcn36xx *wcn, struct ieee80211_vif *vif, 1270 struct sk_buff *skb_beacon, u16 tim_off, 1271 u16 p2p_off) 1272 { 1273 struct wcn36xx_hal_send_beacon_req_msg msg_body; 1274 int ret = 0; 1275 1276 mutex_lock(&wcn->hal_mutex); 1277 INIT_HAL_MSG(msg_body, WCN36XX_HAL_SEND_BEACON_REQ); 1278 1279 /* TODO need to find out why this is needed? */ 1280 msg_body.beacon_length = skb_beacon->len + 6; 1281 1282 if (BEACON_TEMPLATE_SIZE > msg_body.beacon_length) { 1283 memcpy(&msg_body.beacon, &skb_beacon->len, sizeof(u32)); 1284 memcpy(&(msg_body.beacon[4]), skb_beacon->data, 1285 skb_beacon->len); 1286 } else { 1287 wcn36xx_err("Beacon is to big: beacon size=%d\n", 1288 msg_body.beacon_length); 1289 ret = -ENOMEM; 1290 goto out; 1291 } 1292 memcpy(msg_body.bssid, vif->addr, ETH_ALEN); 1293 1294 /* TODO need to find out why this is needed? */ 1295 msg_body.tim_ie_offset = tim_off+4; 1296 msg_body.p2p_ie_offset = p2p_off; 1297 PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 1298 1299 wcn36xx_dbg(WCN36XX_DBG_HAL, 1300 "hal send beacon beacon_length %d\n", 1301 msg_body.beacon_length); 1302 1303 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 1304 if (ret) { 1305 wcn36xx_err("Sending hal_send_beacon failed\n"); 1306 goto out; 1307 } 1308 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); 1309 if (ret) { 1310 wcn36xx_err("hal_send_beacon response failed err=%d\n", ret); 1311 goto out; 1312 } 1313 out: 1314 mutex_unlock(&wcn->hal_mutex); 1315 return ret; 1316 } 1317 1318 int wcn36xx_smd_update_proberesp_tmpl(struct wcn36xx *wcn, 1319 struct ieee80211_vif *vif, 1320 struct sk_buff *skb) 1321 { 1322 struct wcn36xx_hal_send_probe_resp_req_msg msg; 1323 int ret = 0; 1324 1325 mutex_lock(&wcn->hal_mutex); 1326 INIT_HAL_MSG(msg, WCN36XX_HAL_UPDATE_PROBE_RSP_TEMPLATE_REQ); 1327 1328 if (skb->len > BEACON_TEMPLATE_SIZE) { 1329 wcn36xx_warn("probe response template is too big: %d\n", 1330 skb->len); 1331 ret = -E2BIG; 1332 goto out; 1333 } 1334 1335 msg.probe_resp_template_len = skb->len; 1336 memcpy(&msg.probe_resp_template, skb->data, skb->len); 1337 1338 memcpy(msg.bssid, vif->addr, ETH_ALEN); 1339 1340 PREPARE_HAL_BUF(wcn->hal_buf, msg); 1341 1342 wcn36xx_dbg(WCN36XX_DBG_HAL, 1343 "hal update probe rsp len %d bssid %pM\n", 1344 msg.probe_resp_template_len, msg.bssid); 1345 1346 ret = wcn36xx_smd_send_and_wait(wcn, msg.header.len); 1347 if (ret) { 1348 wcn36xx_err("Sending hal_update_proberesp_tmpl failed\n"); 1349 goto out; 1350 } 1351 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); 1352 if (ret) { 1353 wcn36xx_err("hal_update_proberesp_tmpl response failed err=%d\n", 1354 ret); 1355 goto out; 1356 } 1357 out: 1358 mutex_unlock(&wcn->hal_mutex); 1359 return ret; 1360 } 1361 1362 int wcn36xx_smd_set_stakey(struct wcn36xx *wcn, 1363 enum ani_ed_type enc_type, 1364 u8 keyidx, 1365 u8 keylen, 1366 u8 *key, 1367 u8 sta_index) 1368 { 1369 struct wcn36xx_hal_set_sta_key_req_msg msg_body; 1370 int ret = 0; 1371 1372 mutex_lock(&wcn->hal_mutex); 1373 INIT_HAL_MSG(msg_body, WCN36XX_HAL_SET_STAKEY_REQ); 1374 1375 msg_body.set_sta_key_params.sta_index = sta_index; 1376 msg_body.set_sta_key_params.enc_type = enc_type; 1377 1378 msg_body.set_sta_key_params.key[0].id = keyidx; 1379 msg_body.set_sta_key_params.key[0].unicast = 1; 1380 msg_body.set_sta_key_params.key[0].direction = WCN36XX_HAL_TX_RX; 1381 msg_body.set_sta_key_params.key[0].pae_role = 0; 1382 msg_body.set_sta_key_params.key[0].length = keylen; 1383 memcpy(msg_body.set_sta_key_params.key[0].key, key, keylen); 1384 msg_body.set_sta_key_params.single_tid_rc = 1; 1385 1386 PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 1387 1388 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 1389 if (ret) { 1390 wcn36xx_err("Sending hal_set_stakey failed\n"); 1391 goto out; 1392 } 1393 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); 1394 if (ret) { 1395 wcn36xx_err("hal_set_stakey response failed err=%d\n", ret); 1396 goto out; 1397 } 1398 out: 1399 mutex_unlock(&wcn->hal_mutex); 1400 return ret; 1401 } 1402 1403 int wcn36xx_smd_set_bsskey(struct wcn36xx *wcn, 1404 enum ani_ed_type enc_type, 1405 u8 keyidx, 1406 u8 keylen, 1407 u8 *key) 1408 { 1409 struct wcn36xx_hal_set_bss_key_req_msg msg_body; 1410 int ret = 0; 1411 1412 mutex_lock(&wcn->hal_mutex); 1413 INIT_HAL_MSG(msg_body, WCN36XX_HAL_SET_BSSKEY_REQ); 1414 msg_body.bss_idx = 0; 1415 msg_body.enc_type = enc_type; 1416 msg_body.num_keys = 1; 1417 msg_body.keys[0].id = keyidx; 1418 msg_body.keys[0].unicast = 0; 1419 msg_body.keys[0].direction = WCN36XX_HAL_RX_ONLY; 1420 msg_body.keys[0].pae_role = 0; 1421 msg_body.keys[0].length = keylen; 1422 memcpy(msg_body.keys[0].key, key, keylen); 1423 1424 PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 1425 1426 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 1427 if (ret) { 1428 wcn36xx_err("Sending hal_set_bsskey failed\n"); 1429 goto out; 1430 } 1431 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); 1432 if (ret) { 1433 wcn36xx_err("hal_set_bsskey response failed err=%d\n", ret); 1434 goto out; 1435 } 1436 out: 1437 mutex_unlock(&wcn->hal_mutex); 1438 return ret; 1439 } 1440 1441 int wcn36xx_smd_remove_stakey(struct wcn36xx *wcn, 1442 enum ani_ed_type enc_type, 1443 u8 keyidx, 1444 u8 sta_index) 1445 { 1446 struct wcn36xx_hal_remove_sta_key_req_msg msg_body; 1447 int ret = 0; 1448 1449 mutex_lock(&wcn->hal_mutex); 1450 INIT_HAL_MSG(msg_body, WCN36XX_HAL_RMV_STAKEY_REQ); 1451 1452 msg_body.sta_idx = sta_index; 1453 msg_body.enc_type = enc_type; 1454 msg_body.key_id = keyidx; 1455 1456 PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 1457 1458 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 1459 if (ret) { 1460 wcn36xx_err("Sending hal_remove_stakey failed\n"); 1461 goto out; 1462 } 1463 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); 1464 if (ret) { 1465 wcn36xx_err("hal_remove_stakey response failed err=%d\n", ret); 1466 goto out; 1467 } 1468 out: 1469 mutex_unlock(&wcn->hal_mutex); 1470 return ret; 1471 } 1472 1473 int wcn36xx_smd_remove_bsskey(struct wcn36xx *wcn, 1474 enum ani_ed_type enc_type, 1475 u8 keyidx) 1476 { 1477 struct wcn36xx_hal_remove_bss_key_req_msg msg_body; 1478 int ret = 0; 1479 1480 mutex_lock(&wcn->hal_mutex); 1481 INIT_HAL_MSG(msg_body, WCN36XX_HAL_RMV_BSSKEY_REQ); 1482 msg_body.bss_idx = 0; 1483 msg_body.enc_type = enc_type; 1484 msg_body.key_id = keyidx; 1485 1486 PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 1487 1488 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 1489 if (ret) { 1490 wcn36xx_err("Sending hal_remove_bsskey failed\n"); 1491 goto out; 1492 } 1493 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); 1494 if (ret) { 1495 wcn36xx_err("hal_remove_bsskey response failed err=%d\n", ret); 1496 goto out; 1497 } 1498 out: 1499 mutex_unlock(&wcn->hal_mutex); 1500 return ret; 1501 } 1502 1503 int wcn36xx_smd_enter_bmps(struct wcn36xx *wcn, struct ieee80211_vif *vif) 1504 { 1505 struct wcn36xx_hal_enter_bmps_req_msg msg_body; 1506 struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; 1507 int ret = 0; 1508 1509 mutex_lock(&wcn->hal_mutex); 1510 INIT_HAL_MSG(msg_body, WCN36XX_HAL_ENTER_BMPS_REQ); 1511 1512 msg_body.bss_index = vif_priv->bss_index; 1513 msg_body.tbtt = vif->bss_conf.sync_tsf; 1514 msg_body.dtim_period = vif_priv->dtim_period; 1515 1516 PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 1517 1518 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 1519 if (ret) { 1520 wcn36xx_err("Sending hal_enter_bmps failed\n"); 1521 goto out; 1522 } 1523 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); 1524 if (ret) { 1525 wcn36xx_err("hal_enter_bmps response failed err=%d\n", ret); 1526 goto out; 1527 } 1528 out: 1529 mutex_unlock(&wcn->hal_mutex); 1530 return ret; 1531 } 1532 1533 int wcn36xx_smd_exit_bmps(struct wcn36xx *wcn, struct ieee80211_vif *vif) 1534 { 1535 struct wcn36xx_hal_enter_bmps_req_msg msg_body; 1536 struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; 1537 int ret = 0; 1538 1539 mutex_lock(&wcn->hal_mutex); 1540 INIT_HAL_MSG(msg_body, WCN36XX_HAL_EXIT_BMPS_REQ); 1541 1542 msg_body.bss_index = vif_priv->bss_index; 1543 1544 PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 1545 1546 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 1547 if (ret) { 1548 wcn36xx_err("Sending hal_exit_bmps failed\n"); 1549 goto out; 1550 } 1551 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); 1552 if (ret) { 1553 wcn36xx_err("hal_exit_bmps response failed err=%d\n", ret); 1554 goto out; 1555 } 1556 out: 1557 mutex_unlock(&wcn->hal_mutex); 1558 return ret; 1559 } 1560 int wcn36xx_smd_set_power_params(struct wcn36xx *wcn, bool ignore_dtim) 1561 { 1562 struct wcn36xx_hal_set_power_params_req_msg msg_body; 1563 int ret = 0; 1564 1565 mutex_lock(&wcn->hal_mutex); 1566 INIT_HAL_MSG(msg_body, WCN36XX_HAL_SET_POWER_PARAMS_REQ); 1567 1568 /* 1569 * When host is down ignore every second dtim 1570 */ 1571 if (ignore_dtim) { 1572 msg_body.ignore_dtim = 1; 1573 msg_body.dtim_period = 2; 1574 } 1575 msg_body.listen_interval = WCN36XX_LISTEN_INTERVAL(wcn); 1576 1577 PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 1578 1579 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 1580 if (ret) { 1581 wcn36xx_err("Sending hal_set_power_params failed\n"); 1582 goto out; 1583 } 1584 1585 out: 1586 mutex_unlock(&wcn->hal_mutex); 1587 return ret; 1588 } 1589 /* Notice: This function should be called after associated, or else it 1590 * will be invalid 1591 */ 1592 int wcn36xx_smd_keep_alive_req(struct wcn36xx *wcn, 1593 struct ieee80211_vif *vif, 1594 int packet_type) 1595 { 1596 struct wcn36xx_hal_keep_alive_req_msg msg_body; 1597 struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; 1598 int ret = 0; 1599 1600 mutex_lock(&wcn->hal_mutex); 1601 INIT_HAL_MSG(msg_body, WCN36XX_HAL_KEEP_ALIVE_REQ); 1602 1603 if (packet_type == WCN36XX_HAL_KEEP_ALIVE_NULL_PKT) { 1604 msg_body.bss_index = vif_priv->bss_index; 1605 msg_body.packet_type = WCN36XX_HAL_KEEP_ALIVE_NULL_PKT; 1606 msg_body.time_period = WCN36XX_KEEP_ALIVE_TIME_PERIOD; 1607 } else if (packet_type == WCN36XX_HAL_KEEP_ALIVE_UNSOLICIT_ARP_RSP) { 1608 /* TODO: it also support ARP response type */ 1609 } else { 1610 wcn36xx_warn("unknow keep alive packet type %d\n", packet_type); 1611 ret = -EINVAL; 1612 goto out; 1613 } 1614 1615 PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 1616 1617 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 1618 if (ret) { 1619 wcn36xx_err("Sending hal_exit_bmps failed\n"); 1620 goto out; 1621 } 1622 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); 1623 if (ret) { 1624 wcn36xx_err("hal_exit_bmps response failed err=%d\n", ret); 1625 goto out; 1626 } 1627 out: 1628 mutex_unlock(&wcn->hal_mutex); 1629 return ret; 1630 } 1631 1632 int wcn36xx_smd_dump_cmd_req(struct wcn36xx *wcn, u32 arg1, u32 arg2, 1633 u32 arg3, u32 arg4, u32 arg5) 1634 { 1635 struct wcn36xx_hal_dump_cmd_req_msg msg_body; 1636 int ret = 0; 1637 1638 mutex_lock(&wcn->hal_mutex); 1639 INIT_HAL_MSG(msg_body, WCN36XX_HAL_DUMP_COMMAND_REQ); 1640 1641 msg_body.arg1 = arg1; 1642 msg_body.arg2 = arg2; 1643 msg_body.arg3 = arg3; 1644 msg_body.arg4 = arg4; 1645 msg_body.arg5 = arg5; 1646 1647 PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 1648 1649 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 1650 if (ret) { 1651 wcn36xx_err("Sending hal_dump_cmd failed\n"); 1652 goto out; 1653 } 1654 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); 1655 if (ret) { 1656 wcn36xx_err("hal_dump_cmd response failed err=%d\n", ret); 1657 goto out; 1658 } 1659 out: 1660 mutex_unlock(&wcn->hal_mutex); 1661 return ret; 1662 } 1663 1664 static inline void set_feat_caps(u32 *bitmap, 1665 enum place_holder_in_cap_bitmap cap) 1666 { 1667 int arr_idx, bit_idx; 1668 1669 if (cap < 0 || cap > 127) { 1670 wcn36xx_warn("error cap idx %d\n", cap); 1671 return; 1672 } 1673 1674 arr_idx = cap / 32; 1675 bit_idx = cap % 32; 1676 bitmap[arr_idx] |= (1 << bit_idx); 1677 } 1678 1679 static inline int get_feat_caps(u32 *bitmap, 1680 enum place_holder_in_cap_bitmap cap) 1681 { 1682 int arr_idx, bit_idx; 1683 int ret = 0; 1684 1685 if (cap < 0 || cap > 127) { 1686 wcn36xx_warn("error cap idx %d\n", cap); 1687 return -EINVAL; 1688 } 1689 1690 arr_idx = cap / 32; 1691 bit_idx = cap % 32; 1692 ret = (bitmap[arr_idx] & (1 << bit_idx)) ? 1 : 0; 1693 return ret; 1694 } 1695 1696 static inline void clear_feat_caps(u32 *bitmap, 1697 enum place_holder_in_cap_bitmap cap) 1698 { 1699 int arr_idx, bit_idx; 1700 1701 if (cap < 0 || cap > 127) { 1702 wcn36xx_warn("error cap idx %d\n", cap); 1703 return; 1704 } 1705 1706 arr_idx = cap / 32; 1707 bit_idx = cap % 32; 1708 bitmap[arr_idx] &= ~(1 << bit_idx); 1709 } 1710 1711 int wcn36xx_smd_feature_caps_exchange(struct wcn36xx *wcn) 1712 { 1713 struct wcn36xx_hal_feat_caps_msg msg_body; 1714 int ret = 0; 1715 1716 mutex_lock(&wcn->hal_mutex); 1717 INIT_HAL_MSG(msg_body, WCN36XX_HAL_FEATURE_CAPS_EXCHANGE_REQ); 1718 1719 set_feat_caps(msg_body.feat_caps, STA_POWERSAVE); 1720 1721 PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 1722 1723 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 1724 if (ret) { 1725 wcn36xx_err("Sending hal_feature_caps_exchange failed\n"); 1726 goto out; 1727 } 1728 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); 1729 if (ret) { 1730 wcn36xx_err("hal_feature_caps_exchange response failed err=%d\n", 1731 ret); 1732 goto out; 1733 } 1734 out: 1735 mutex_unlock(&wcn->hal_mutex); 1736 return ret; 1737 } 1738 1739 int wcn36xx_smd_add_ba_session(struct wcn36xx *wcn, 1740 struct ieee80211_sta *sta, 1741 u16 tid, 1742 u16 *ssn, 1743 u8 direction, 1744 u8 sta_index) 1745 { 1746 struct wcn36xx_hal_add_ba_session_req_msg msg_body; 1747 int ret = 0; 1748 1749 mutex_lock(&wcn->hal_mutex); 1750 INIT_HAL_MSG(msg_body, WCN36XX_HAL_ADD_BA_SESSION_REQ); 1751 1752 msg_body.sta_index = sta_index; 1753 memcpy(&msg_body.mac_addr, sta->addr, ETH_ALEN); 1754 msg_body.dialog_token = 0x10; 1755 msg_body.tid = tid; 1756 1757 /* Immediate BA because Delayed BA is not supported */ 1758 msg_body.policy = 1; 1759 msg_body.buffer_size = WCN36XX_AGGR_BUFFER_SIZE; 1760 msg_body.timeout = 0; 1761 if (ssn) 1762 msg_body.ssn = *ssn; 1763 msg_body.direction = direction; 1764 1765 PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 1766 1767 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 1768 if (ret) { 1769 wcn36xx_err("Sending hal_add_ba_session failed\n"); 1770 goto out; 1771 } 1772 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); 1773 if (ret) { 1774 wcn36xx_err("hal_add_ba_session response failed err=%d\n", ret); 1775 goto out; 1776 } 1777 out: 1778 mutex_unlock(&wcn->hal_mutex); 1779 return ret; 1780 } 1781 1782 int wcn36xx_smd_add_ba(struct wcn36xx *wcn) 1783 { 1784 struct wcn36xx_hal_add_ba_req_msg msg_body; 1785 int ret = 0; 1786 1787 mutex_lock(&wcn->hal_mutex); 1788 INIT_HAL_MSG(msg_body, WCN36XX_HAL_ADD_BA_REQ); 1789 1790 msg_body.session_id = 0; 1791 msg_body.win_size = WCN36XX_AGGR_BUFFER_SIZE; 1792 1793 PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 1794 1795 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 1796 if (ret) { 1797 wcn36xx_err("Sending hal_add_ba failed\n"); 1798 goto out; 1799 } 1800 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); 1801 if (ret) { 1802 wcn36xx_err("hal_add_ba response failed err=%d\n", ret); 1803 goto out; 1804 } 1805 out: 1806 mutex_unlock(&wcn->hal_mutex); 1807 return ret; 1808 } 1809 1810 int wcn36xx_smd_del_ba(struct wcn36xx *wcn, u16 tid, u8 sta_index) 1811 { 1812 struct wcn36xx_hal_del_ba_req_msg msg_body; 1813 int ret = 0; 1814 1815 mutex_lock(&wcn->hal_mutex); 1816 INIT_HAL_MSG(msg_body, WCN36XX_HAL_DEL_BA_REQ); 1817 1818 msg_body.sta_index = sta_index; 1819 msg_body.tid = tid; 1820 msg_body.direction = 0; 1821 PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 1822 1823 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 1824 if (ret) { 1825 wcn36xx_err("Sending hal_del_ba failed\n"); 1826 goto out; 1827 } 1828 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); 1829 if (ret) { 1830 wcn36xx_err("hal_del_ba response failed err=%d\n", ret); 1831 goto out; 1832 } 1833 out: 1834 mutex_unlock(&wcn->hal_mutex); 1835 return ret; 1836 } 1837 1838 int wcn36xx_smd_trigger_ba(struct wcn36xx *wcn, u8 sta_index) 1839 { 1840 struct wcn36xx_hal_trigger_ba_req_msg msg_body; 1841 struct wcn36xx_hal_trigget_ba_req_candidate *candidate; 1842 int ret = 0; 1843 1844 mutex_lock(&wcn->hal_mutex); 1845 INIT_HAL_MSG(msg_body, WCN36XX_HAL_TRIGGER_BA_REQ); 1846 1847 msg_body.session_id = 0; 1848 msg_body.candidate_cnt = 1; 1849 msg_body.header.len += sizeof(*candidate); 1850 PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 1851 1852 candidate = (struct wcn36xx_hal_trigget_ba_req_candidate *) 1853 (wcn->hal_buf + sizeof(msg_body)); 1854 candidate->sta_index = sta_index; 1855 candidate->tid_bitmap = 1; 1856 1857 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 1858 if (ret) { 1859 wcn36xx_err("Sending hal_trigger_ba failed\n"); 1860 goto out; 1861 } 1862 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); 1863 if (ret) { 1864 wcn36xx_err("hal_trigger_ba response failed err=%d\n", ret); 1865 goto out; 1866 } 1867 out: 1868 mutex_unlock(&wcn->hal_mutex); 1869 return ret; 1870 } 1871 1872 static int wcn36xx_smd_tx_compl_ind(struct wcn36xx *wcn, void *buf, size_t len) 1873 { 1874 struct wcn36xx_hal_tx_compl_ind_msg *rsp = buf; 1875 1876 if (len != sizeof(*rsp)) { 1877 wcn36xx_warn("Bad TX complete indication\n"); 1878 return -EIO; 1879 } 1880 1881 wcn36xx_dxe_tx_ack_ind(wcn, rsp->status); 1882 1883 return 0; 1884 } 1885 1886 static int wcn36xx_smd_missed_beacon_ind(struct wcn36xx *wcn, 1887 void *buf, 1888 size_t len) 1889 { 1890 struct wcn36xx_hal_missed_beacon_ind_msg *rsp = buf; 1891 struct ieee80211_vif *vif = NULL; 1892 struct wcn36xx_vif *tmp; 1893 1894 /* Old FW does not have bss index */ 1895 if (wcn36xx_is_fw_version(wcn, 1, 2, 2, 24)) { 1896 list_for_each_entry(tmp, &wcn->vif_list, list) { 1897 wcn36xx_dbg(WCN36XX_DBG_HAL, "beacon missed bss_index %d\n", 1898 tmp->bss_index); 1899 vif = container_of((void *)tmp, 1900 struct ieee80211_vif, 1901 drv_priv); 1902 ieee80211_connection_loss(vif); 1903 } 1904 return 0; 1905 } 1906 1907 if (len != sizeof(*rsp)) { 1908 wcn36xx_warn("Corrupted missed beacon indication\n"); 1909 return -EIO; 1910 } 1911 1912 list_for_each_entry(tmp, &wcn->vif_list, list) { 1913 if (tmp->bss_index == rsp->bss_index) { 1914 wcn36xx_dbg(WCN36XX_DBG_HAL, "beacon missed bss_index %d\n", 1915 rsp->bss_index); 1916 vif = container_of((void *)tmp, 1917 struct ieee80211_vif, 1918 drv_priv); 1919 ieee80211_connection_loss(vif); 1920 return 0; 1921 } 1922 } 1923 1924 wcn36xx_warn("BSS index %d not found\n", rsp->bss_index); 1925 return -ENOENT; 1926 } 1927 1928 static int wcn36xx_smd_delete_sta_context_ind(struct wcn36xx *wcn, 1929 void *buf, 1930 size_t len) 1931 { 1932 struct wcn36xx_hal_delete_sta_context_ind_msg *rsp = buf; 1933 struct wcn36xx_vif *tmp; 1934 struct ieee80211_sta *sta = NULL; 1935 1936 if (len != sizeof(*rsp)) { 1937 wcn36xx_warn("Corrupted delete sta indication\n"); 1938 return -EIO; 1939 } 1940 1941 list_for_each_entry(tmp, &wcn->vif_list, list) { 1942 if (sta && (tmp->sta->sta_index == rsp->sta_id)) { 1943 sta = container_of((void *)tmp->sta, 1944 struct ieee80211_sta, 1945 drv_priv); 1946 wcn36xx_dbg(WCN36XX_DBG_HAL, 1947 "delete station indication %pM index %d\n", 1948 rsp->addr2, 1949 rsp->sta_id); 1950 ieee80211_report_low_ack(sta, 0); 1951 return 0; 1952 } 1953 } 1954 1955 wcn36xx_warn("STA with addr %pM and index %d not found\n", 1956 rsp->addr2, 1957 rsp->sta_id); 1958 return -ENOENT; 1959 } 1960 1961 int wcn36xx_smd_update_cfg(struct wcn36xx *wcn, u32 cfg_id, u32 value) 1962 { 1963 struct wcn36xx_hal_update_cfg_req_msg msg_body, *body; 1964 size_t len; 1965 int ret = 0; 1966 1967 mutex_lock(&wcn->hal_mutex); 1968 INIT_HAL_MSG(msg_body, WCN36XX_HAL_UPDATE_CFG_REQ); 1969 1970 PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 1971 1972 body = (struct wcn36xx_hal_update_cfg_req_msg *) wcn->hal_buf; 1973 len = msg_body.header.len; 1974 1975 put_cfg_tlv_u32(wcn, &len, cfg_id, value); 1976 body->header.len = len; 1977 body->len = len - sizeof(*body); 1978 1979 ret = wcn36xx_smd_send_and_wait(wcn, body->header.len); 1980 if (ret) { 1981 wcn36xx_err("Sending hal_update_cfg failed\n"); 1982 goto out; 1983 } 1984 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); 1985 if (ret) { 1986 wcn36xx_err("hal_update_cfg response failed err=%d\n", ret); 1987 goto out; 1988 } 1989 out: 1990 mutex_unlock(&wcn->hal_mutex); 1991 return ret; 1992 } 1993 static void wcn36xx_smd_rsp_process(struct wcn36xx *wcn, void *buf, size_t len) 1994 { 1995 struct wcn36xx_hal_msg_header *msg_header = buf; 1996 struct wcn36xx_hal_ind_msg *msg_ind; 1997 wcn36xx_dbg_dump(WCN36XX_DBG_SMD_DUMP, "SMD <<< ", buf, len); 1998 1999 switch (msg_header->msg_type) { 2000 case WCN36XX_HAL_START_RSP: 2001 case WCN36XX_HAL_CONFIG_STA_RSP: 2002 case WCN36XX_HAL_CONFIG_BSS_RSP: 2003 case WCN36XX_HAL_ADD_STA_SELF_RSP: 2004 case WCN36XX_HAL_STOP_RSP: 2005 case WCN36XX_HAL_DEL_STA_SELF_RSP: 2006 case WCN36XX_HAL_DELETE_STA_RSP: 2007 case WCN36XX_HAL_INIT_SCAN_RSP: 2008 case WCN36XX_HAL_START_SCAN_RSP: 2009 case WCN36XX_HAL_END_SCAN_RSP: 2010 case WCN36XX_HAL_FINISH_SCAN_RSP: 2011 case WCN36XX_HAL_DOWNLOAD_NV_RSP: 2012 case WCN36XX_HAL_DELETE_BSS_RSP: 2013 case WCN36XX_HAL_SEND_BEACON_RSP: 2014 case WCN36XX_HAL_SET_LINK_ST_RSP: 2015 case WCN36XX_HAL_UPDATE_PROBE_RSP_TEMPLATE_RSP: 2016 case WCN36XX_HAL_SET_BSSKEY_RSP: 2017 case WCN36XX_HAL_SET_STAKEY_RSP: 2018 case WCN36XX_HAL_RMV_STAKEY_RSP: 2019 case WCN36XX_HAL_RMV_BSSKEY_RSP: 2020 case WCN36XX_HAL_ENTER_BMPS_RSP: 2021 case WCN36XX_HAL_SET_POWER_PARAMS_RSP: 2022 case WCN36XX_HAL_EXIT_BMPS_RSP: 2023 case WCN36XX_HAL_KEEP_ALIVE_RSP: 2024 case WCN36XX_HAL_DUMP_COMMAND_RSP: 2025 case WCN36XX_HAL_ADD_BA_SESSION_RSP: 2026 case WCN36XX_HAL_ADD_BA_RSP: 2027 case WCN36XX_HAL_DEL_BA_RSP: 2028 case WCN36XX_HAL_TRIGGER_BA_RSP: 2029 case WCN36XX_HAL_UPDATE_CFG_RSP: 2030 case WCN36XX_HAL_JOIN_RSP: 2031 case WCN36XX_HAL_UPDATE_SCAN_PARAM_RSP: 2032 case WCN36XX_HAL_CH_SWITCH_RSP: 2033 case WCN36XX_HAL_FEATURE_CAPS_EXCHANGE_RSP: 2034 memcpy(wcn->hal_buf, buf, len); 2035 wcn->hal_rsp_len = len; 2036 complete(&wcn->hal_rsp_compl); 2037 break; 2038 2039 case WCN36XX_HAL_OTA_TX_COMPL_IND: 2040 case WCN36XX_HAL_MISSED_BEACON_IND: 2041 case WCN36XX_HAL_DELETE_STA_CONTEXT_IND: 2042 mutex_lock(&wcn->hal_ind_mutex); 2043 msg_ind = kmalloc(sizeof(*msg_ind), GFP_KERNEL); 2044 if (msg_ind) { 2045 msg_ind->msg_len = len; 2046 msg_ind->msg = kmalloc(len, GFP_KERNEL); 2047 memcpy(msg_ind->msg, buf, len); 2048 list_add_tail(&msg_ind->list, &wcn->hal_ind_queue); 2049 queue_work(wcn->hal_ind_wq, &wcn->hal_ind_work); 2050 wcn36xx_dbg(WCN36XX_DBG_HAL, "indication arrived\n"); 2051 } 2052 mutex_unlock(&wcn->hal_ind_mutex); 2053 if (msg_ind) 2054 break; 2055 /* FIXME: Do something smarter then just printing an error. */ 2056 wcn36xx_err("Run out of memory while handling SMD_EVENT (%d)\n", 2057 msg_header->msg_type); 2058 break; 2059 default: 2060 wcn36xx_err("SMD_EVENT (%d) not supported\n", 2061 msg_header->msg_type); 2062 } 2063 } 2064 static void wcn36xx_ind_smd_work(struct work_struct *work) 2065 { 2066 struct wcn36xx *wcn = 2067 container_of(work, struct wcn36xx, hal_ind_work); 2068 struct wcn36xx_hal_msg_header *msg_header; 2069 struct wcn36xx_hal_ind_msg *hal_ind_msg; 2070 2071 mutex_lock(&wcn->hal_ind_mutex); 2072 2073 hal_ind_msg = list_first_entry(&wcn->hal_ind_queue, 2074 struct wcn36xx_hal_ind_msg, 2075 list); 2076 2077 msg_header = (struct wcn36xx_hal_msg_header *)hal_ind_msg->msg; 2078 2079 switch (msg_header->msg_type) { 2080 case WCN36XX_HAL_OTA_TX_COMPL_IND: 2081 wcn36xx_smd_tx_compl_ind(wcn, 2082 hal_ind_msg->msg, 2083 hal_ind_msg->msg_len); 2084 break; 2085 case WCN36XX_HAL_MISSED_BEACON_IND: 2086 wcn36xx_smd_missed_beacon_ind(wcn, 2087 hal_ind_msg->msg, 2088 hal_ind_msg->msg_len); 2089 break; 2090 case WCN36XX_HAL_DELETE_STA_CONTEXT_IND: 2091 wcn36xx_smd_delete_sta_context_ind(wcn, 2092 hal_ind_msg->msg, 2093 hal_ind_msg->msg_len); 2094 break; 2095 default: 2096 wcn36xx_err("SMD_EVENT (%d) not supported\n", 2097 msg_header->msg_type); 2098 } 2099 list_del(wcn->hal_ind_queue.next); 2100 kfree(hal_ind_msg->msg); 2101 kfree(hal_ind_msg); 2102 mutex_unlock(&wcn->hal_ind_mutex); 2103 } 2104 int wcn36xx_smd_open(struct wcn36xx *wcn) 2105 { 2106 int ret = 0; 2107 wcn->hal_ind_wq = create_freezable_workqueue("wcn36xx_smd_ind"); 2108 if (!wcn->hal_ind_wq) { 2109 wcn36xx_err("failed to allocate wq\n"); 2110 ret = -ENOMEM; 2111 goto out; 2112 } 2113 INIT_WORK(&wcn->hal_ind_work, wcn36xx_ind_smd_work); 2114 INIT_LIST_HEAD(&wcn->hal_ind_queue); 2115 mutex_init(&wcn->hal_ind_mutex); 2116 2117 ret = wcn->ctrl_ops->open(wcn, wcn36xx_smd_rsp_process); 2118 if (ret) { 2119 wcn36xx_err("failed to open control channel\n"); 2120 goto free_wq; 2121 } 2122 2123 return ret; 2124 2125 free_wq: 2126 destroy_workqueue(wcn->hal_ind_wq); 2127 out: 2128 return ret; 2129 } 2130 2131 void wcn36xx_smd_close(struct wcn36xx *wcn) 2132 { 2133 wcn->ctrl_ops->close(); 2134 destroy_workqueue(wcn->hal_ind_wq); 2135 mutex_destroy(&wcn->hal_ind_mutex); 2136 } 2137