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