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