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