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