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