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