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