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; 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; 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; 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; 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; 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; 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; 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; 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; 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; 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; 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; 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; 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; 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; 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; 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; 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, 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; 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; 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 if (enc_type == WCN36XX_HAL_ED_WEP104 || 1712 enc_type == WCN36XX_HAL_ED_WEP40) { 1713 /* Use bss key for wep (static) */ 1714 msg_body.set_sta_key_params.def_wep_idx = keyidx; 1715 msg_body.set_sta_key_params.wep_type = 0; 1716 } else { 1717 msg_body.set_sta_key_params.key[0].id = keyidx; 1718 msg_body.set_sta_key_params.key[0].unicast = 1; 1719 msg_body.set_sta_key_params.key[0].direction = WCN36XX_HAL_TX_RX; 1720 msg_body.set_sta_key_params.key[0].pae_role = 0; 1721 msg_body.set_sta_key_params.key[0].length = keylen; 1722 memcpy(msg_body.set_sta_key_params.key[0].key, key, keylen); 1723 } 1724 1725 msg_body.set_sta_key_params.single_tid_rc = 1; 1726 1727 PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 1728 1729 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 1730 if (ret) { 1731 wcn36xx_err("Sending hal_set_stakey failed\n"); 1732 goto out; 1733 } 1734 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); 1735 if (ret) { 1736 wcn36xx_err("hal_set_stakey response failed err=%d\n", ret); 1737 goto out; 1738 } 1739 out: 1740 mutex_unlock(&wcn->hal_mutex); 1741 return ret; 1742 } 1743 1744 int wcn36xx_smd_set_bsskey(struct wcn36xx *wcn, 1745 enum ani_ed_type enc_type, 1746 u8 bssidx, 1747 u8 keyidx, 1748 u8 keylen, 1749 u8 *key) 1750 { 1751 struct wcn36xx_hal_set_bss_key_req_msg msg_body; 1752 int ret; 1753 1754 mutex_lock(&wcn->hal_mutex); 1755 INIT_HAL_MSG(msg_body, WCN36XX_HAL_SET_BSSKEY_REQ); 1756 msg_body.bss_idx = bssidx; 1757 msg_body.enc_type = enc_type; 1758 msg_body.num_keys = 1; 1759 msg_body.keys[0].id = keyidx; 1760 msg_body.keys[0].unicast = 0; 1761 msg_body.keys[0].direction = WCN36XX_HAL_RX_ONLY; 1762 msg_body.keys[0].pae_role = 0; 1763 msg_body.keys[0].length = keylen; 1764 memcpy(msg_body.keys[0].key, key, keylen); 1765 1766 PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 1767 1768 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 1769 if (ret) { 1770 wcn36xx_err("Sending hal_set_bsskey failed\n"); 1771 goto out; 1772 } 1773 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); 1774 if (ret) { 1775 wcn36xx_err("hal_set_bsskey response failed err=%d\n", ret); 1776 goto out; 1777 } 1778 out: 1779 mutex_unlock(&wcn->hal_mutex); 1780 return ret; 1781 } 1782 1783 int wcn36xx_smd_remove_stakey(struct wcn36xx *wcn, 1784 enum ani_ed_type enc_type, 1785 u8 keyidx, 1786 u8 sta_index) 1787 { 1788 struct wcn36xx_hal_remove_sta_key_req_msg msg_body; 1789 int ret; 1790 1791 mutex_lock(&wcn->hal_mutex); 1792 INIT_HAL_MSG(msg_body, WCN36XX_HAL_RMV_STAKEY_REQ); 1793 1794 msg_body.sta_idx = sta_index; 1795 msg_body.enc_type = enc_type; 1796 msg_body.key_id = keyidx; 1797 1798 PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 1799 1800 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 1801 if (ret) { 1802 wcn36xx_err("Sending hal_remove_stakey failed\n"); 1803 goto out; 1804 } 1805 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); 1806 if (ret) { 1807 wcn36xx_err("hal_remove_stakey response failed err=%d\n", ret); 1808 goto out; 1809 } 1810 out: 1811 mutex_unlock(&wcn->hal_mutex); 1812 return ret; 1813 } 1814 1815 int wcn36xx_smd_remove_bsskey(struct wcn36xx *wcn, 1816 enum ani_ed_type enc_type, 1817 u8 bssidx, 1818 u8 keyidx) 1819 { 1820 struct wcn36xx_hal_remove_bss_key_req_msg msg_body; 1821 int ret; 1822 1823 mutex_lock(&wcn->hal_mutex); 1824 INIT_HAL_MSG(msg_body, WCN36XX_HAL_RMV_BSSKEY_REQ); 1825 msg_body.bss_idx = bssidx; 1826 msg_body.enc_type = enc_type; 1827 msg_body.key_id = keyidx; 1828 1829 PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 1830 1831 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 1832 if (ret) { 1833 wcn36xx_err("Sending hal_remove_bsskey failed\n"); 1834 goto out; 1835 } 1836 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); 1837 if (ret) { 1838 wcn36xx_err("hal_remove_bsskey response failed err=%d\n", ret); 1839 goto out; 1840 } 1841 out: 1842 mutex_unlock(&wcn->hal_mutex); 1843 return ret; 1844 } 1845 1846 int wcn36xx_smd_enter_bmps(struct wcn36xx *wcn, struct ieee80211_vif *vif) 1847 { 1848 struct wcn36xx_hal_enter_bmps_req_msg msg_body; 1849 struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif); 1850 int ret; 1851 1852 mutex_lock(&wcn->hal_mutex); 1853 INIT_HAL_MSG(msg_body, WCN36XX_HAL_ENTER_BMPS_REQ); 1854 1855 msg_body.bss_index = vif_priv->bss_index; 1856 msg_body.tbtt = vif->bss_conf.sync_tsf; 1857 msg_body.dtim_period = vif_priv->dtim_period; 1858 1859 PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 1860 1861 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 1862 if (ret) { 1863 wcn36xx_err("Sending hal_enter_bmps failed\n"); 1864 goto out; 1865 } 1866 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); 1867 if (ret) { 1868 wcn36xx_err("hal_enter_bmps response failed err=%d\n", ret); 1869 goto out; 1870 } 1871 out: 1872 mutex_unlock(&wcn->hal_mutex); 1873 return ret; 1874 } 1875 1876 int wcn36xx_smd_exit_bmps(struct wcn36xx *wcn, struct ieee80211_vif *vif) 1877 { 1878 struct wcn36xx_hal_exit_bmps_req_msg msg_body; 1879 struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif); 1880 int ret; 1881 1882 mutex_lock(&wcn->hal_mutex); 1883 INIT_HAL_MSG(msg_body, WCN36XX_HAL_EXIT_BMPS_REQ); 1884 1885 msg_body.bss_index = vif_priv->bss_index; 1886 1887 PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 1888 1889 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 1890 if (ret) { 1891 wcn36xx_err("Sending hal_exit_bmps failed\n"); 1892 goto out; 1893 } 1894 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); 1895 if (ret) { 1896 wcn36xx_err("hal_exit_bmps response failed err=%d\n", ret); 1897 goto out; 1898 } 1899 out: 1900 mutex_unlock(&wcn->hal_mutex); 1901 return ret; 1902 } 1903 int wcn36xx_smd_set_power_params(struct wcn36xx *wcn, bool ignore_dtim) 1904 { 1905 struct wcn36xx_hal_set_power_params_req_msg msg_body; 1906 int ret; 1907 1908 mutex_lock(&wcn->hal_mutex); 1909 INIT_HAL_MSG(msg_body, WCN36XX_HAL_SET_POWER_PARAMS_REQ); 1910 1911 /* 1912 * When host is down ignore every second dtim 1913 */ 1914 if (ignore_dtim) { 1915 msg_body.ignore_dtim = 1; 1916 msg_body.dtim_period = 2; 1917 } 1918 msg_body.listen_interval = WCN36XX_LISTEN_INTERVAL(wcn); 1919 1920 PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 1921 1922 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 1923 if (ret) { 1924 wcn36xx_err("Sending hal_set_power_params failed\n"); 1925 goto out; 1926 } 1927 1928 out: 1929 mutex_unlock(&wcn->hal_mutex); 1930 return ret; 1931 } 1932 /* Notice: This function should be called after associated, or else it 1933 * will be invalid 1934 */ 1935 int wcn36xx_smd_keep_alive_req(struct wcn36xx *wcn, 1936 struct ieee80211_vif *vif, 1937 int packet_type) 1938 { 1939 struct wcn36xx_hal_keep_alive_req_msg msg_body; 1940 struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif); 1941 int ret; 1942 1943 mutex_lock(&wcn->hal_mutex); 1944 INIT_HAL_MSG(msg_body, WCN36XX_HAL_KEEP_ALIVE_REQ); 1945 1946 if (packet_type == WCN36XX_HAL_KEEP_ALIVE_NULL_PKT) { 1947 msg_body.bss_index = vif_priv->bss_index; 1948 msg_body.packet_type = WCN36XX_HAL_KEEP_ALIVE_NULL_PKT; 1949 msg_body.time_period = WCN36XX_KEEP_ALIVE_TIME_PERIOD; 1950 } else if (packet_type == WCN36XX_HAL_KEEP_ALIVE_UNSOLICIT_ARP_RSP) { 1951 /* TODO: it also support ARP response type */ 1952 } else { 1953 wcn36xx_warn("unknown keep alive packet type %d\n", packet_type); 1954 ret = -EINVAL; 1955 goto out; 1956 } 1957 1958 PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 1959 1960 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 1961 if (ret) { 1962 wcn36xx_err("Sending hal_keep_alive failed\n"); 1963 goto out; 1964 } 1965 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); 1966 if (ret) { 1967 wcn36xx_err("hal_keep_alive response failed err=%d\n", ret); 1968 goto out; 1969 } 1970 out: 1971 mutex_unlock(&wcn->hal_mutex); 1972 return ret; 1973 } 1974 1975 int wcn36xx_smd_dump_cmd_req(struct wcn36xx *wcn, u32 arg1, u32 arg2, 1976 u32 arg3, u32 arg4, u32 arg5) 1977 { 1978 struct wcn36xx_hal_dump_cmd_req_msg msg_body; 1979 int ret; 1980 1981 mutex_lock(&wcn->hal_mutex); 1982 INIT_HAL_MSG(msg_body, WCN36XX_HAL_DUMP_COMMAND_REQ); 1983 1984 msg_body.arg1 = arg1; 1985 msg_body.arg2 = arg2; 1986 msg_body.arg3 = arg3; 1987 msg_body.arg4 = arg4; 1988 msg_body.arg5 = arg5; 1989 1990 PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 1991 1992 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 1993 if (ret) { 1994 wcn36xx_err("Sending hal_dump_cmd failed\n"); 1995 goto out; 1996 } 1997 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); 1998 if (ret) { 1999 wcn36xx_err("hal_dump_cmd response failed err=%d\n", ret); 2000 goto out; 2001 } 2002 out: 2003 mutex_unlock(&wcn->hal_mutex); 2004 return ret; 2005 } 2006 2007 void set_feat_caps(u32 *bitmap, enum place_holder_in_cap_bitmap cap) 2008 { 2009 int arr_idx, bit_idx; 2010 2011 if (cap < 0 || cap > 127) { 2012 wcn36xx_warn("error cap idx %d\n", cap); 2013 return; 2014 } 2015 2016 arr_idx = cap / 32; 2017 bit_idx = cap % 32; 2018 bitmap[arr_idx] |= (1 << bit_idx); 2019 } 2020 2021 int get_feat_caps(u32 *bitmap, enum place_holder_in_cap_bitmap cap) 2022 { 2023 int arr_idx, bit_idx; 2024 2025 if (cap < 0 || cap > 127) { 2026 wcn36xx_warn("error cap idx %d\n", cap); 2027 return -EINVAL; 2028 } 2029 2030 arr_idx = cap / 32; 2031 bit_idx = cap % 32; 2032 2033 return (bitmap[arr_idx] & (1 << bit_idx)) ? 1 : 0; 2034 } 2035 2036 void clear_feat_caps(u32 *bitmap, enum place_holder_in_cap_bitmap cap) 2037 { 2038 int arr_idx, bit_idx; 2039 2040 if (cap < 0 || cap > 127) { 2041 wcn36xx_warn("error cap idx %d\n", cap); 2042 return; 2043 } 2044 2045 arr_idx = cap / 32; 2046 bit_idx = cap % 32; 2047 bitmap[arr_idx] &= ~(1 << bit_idx); 2048 } 2049 2050 int wcn36xx_smd_feature_caps_exchange(struct wcn36xx *wcn) 2051 { 2052 struct wcn36xx_hal_feat_caps_msg msg_body, *rsp; 2053 int ret, i; 2054 2055 mutex_lock(&wcn->hal_mutex); 2056 INIT_HAL_MSG(msg_body, WCN36XX_HAL_FEATURE_CAPS_EXCHANGE_REQ); 2057 2058 set_feat_caps(msg_body.feat_caps, STA_POWERSAVE); 2059 2060 PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 2061 2062 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 2063 if (ret) { 2064 wcn36xx_err("Sending hal_feature_caps_exchange failed\n"); 2065 goto out; 2066 } 2067 if (wcn->hal_rsp_len != sizeof(*rsp)) { 2068 wcn36xx_err("Invalid hal_feature_caps_exchange response"); 2069 goto out; 2070 } 2071 2072 rsp = (struct wcn36xx_hal_feat_caps_msg *) wcn->hal_buf; 2073 2074 for (i = 0; i < WCN36XX_HAL_CAPS_SIZE; i++) 2075 wcn->fw_feat_caps[i] = rsp->feat_caps[i]; 2076 out: 2077 mutex_unlock(&wcn->hal_mutex); 2078 return ret; 2079 } 2080 2081 int wcn36xx_smd_add_ba_session(struct wcn36xx *wcn, 2082 struct ieee80211_sta *sta, 2083 u16 tid, 2084 u16 *ssn, 2085 u8 direction, 2086 u8 sta_index) 2087 { 2088 struct wcn36xx_hal_add_ba_session_req_msg msg_body; 2089 int ret; 2090 2091 mutex_lock(&wcn->hal_mutex); 2092 INIT_HAL_MSG(msg_body, WCN36XX_HAL_ADD_BA_SESSION_REQ); 2093 2094 msg_body.sta_index = sta_index; 2095 memcpy(&msg_body.mac_addr, sta->addr, ETH_ALEN); 2096 msg_body.dialog_token = 0x10; 2097 msg_body.tid = tid; 2098 2099 /* Immediate BA because Delayed BA is not supported */ 2100 msg_body.policy = 1; 2101 msg_body.buffer_size = WCN36XX_AGGR_BUFFER_SIZE; 2102 msg_body.timeout = 0; 2103 if (ssn) 2104 msg_body.ssn = *ssn; 2105 msg_body.direction = direction; 2106 2107 PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 2108 2109 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 2110 if (ret) { 2111 wcn36xx_err("Sending hal_add_ba_session failed\n"); 2112 goto out; 2113 } 2114 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); 2115 if (ret) { 2116 wcn36xx_err("hal_add_ba_session response failed err=%d\n", ret); 2117 goto out; 2118 } 2119 out: 2120 mutex_unlock(&wcn->hal_mutex); 2121 return ret; 2122 } 2123 2124 int wcn36xx_smd_add_ba(struct wcn36xx *wcn) 2125 { 2126 struct wcn36xx_hal_add_ba_req_msg msg_body; 2127 int ret; 2128 2129 mutex_lock(&wcn->hal_mutex); 2130 INIT_HAL_MSG(msg_body, WCN36XX_HAL_ADD_BA_REQ); 2131 2132 msg_body.session_id = 0; 2133 msg_body.win_size = WCN36XX_AGGR_BUFFER_SIZE; 2134 2135 PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 2136 2137 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 2138 if (ret) { 2139 wcn36xx_err("Sending hal_add_ba failed\n"); 2140 goto out; 2141 } 2142 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); 2143 if (ret) { 2144 wcn36xx_err("hal_add_ba response failed err=%d\n", ret); 2145 goto out; 2146 } 2147 out: 2148 mutex_unlock(&wcn->hal_mutex); 2149 return ret; 2150 } 2151 2152 int wcn36xx_smd_del_ba(struct wcn36xx *wcn, u16 tid, u8 sta_index) 2153 { 2154 struct wcn36xx_hal_del_ba_req_msg msg_body; 2155 int ret; 2156 2157 mutex_lock(&wcn->hal_mutex); 2158 INIT_HAL_MSG(msg_body, WCN36XX_HAL_DEL_BA_REQ); 2159 2160 msg_body.sta_index = sta_index; 2161 msg_body.tid = tid; 2162 msg_body.direction = 0; 2163 PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 2164 2165 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 2166 if (ret) { 2167 wcn36xx_err("Sending hal_del_ba failed\n"); 2168 goto out; 2169 } 2170 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); 2171 if (ret) { 2172 wcn36xx_err("hal_del_ba response failed err=%d\n", ret); 2173 goto out; 2174 } 2175 out: 2176 mutex_unlock(&wcn->hal_mutex); 2177 return ret; 2178 } 2179 2180 static int wcn36xx_smd_trigger_ba_rsp(void *buf, int len) 2181 { 2182 struct wcn36xx_hal_trigger_ba_rsp_msg *rsp; 2183 2184 if (len < sizeof(*rsp)) 2185 return -EINVAL; 2186 2187 rsp = (struct wcn36xx_hal_trigger_ba_rsp_msg *) buf; 2188 return rsp->status; 2189 } 2190 2191 int wcn36xx_smd_trigger_ba(struct wcn36xx *wcn, u8 sta_index) 2192 { 2193 struct wcn36xx_hal_trigger_ba_req_msg msg_body; 2194 struct wcn36xx_hal_trigger_ba_req_candidate *candidate; 2195 int ret; 2196 2197 mutex_lock(&wcn->hal_mutex); 2198 INIT_HAL_MSG(msg_body, WCN36XX_HAL_TRIGGER_BA_REQ); 2199 2200 msg_body.session_id = 0; 2201 msg_body.candidate_cnt = 1; 2202 msg_body.header.len += sizeof(*candidate); 2203 PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 2204 2205 candidate = (struct wcn36xx_hal_trigger_ba_req_candidate *) 2206 (wcn->hal_buf + sizeof(msg_body)); 2207 candidate->sta_index = sta_index; 2208 candidate->tid_bitmap = 1; 2209 2210 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 2211 if (ret) { 2212 wcn36xx_err("Sending hal_trigger_ba failed\n"); 2213 goto out; 2214 } 2215 ret = wcn36xx_smd_trigger_ba_rsp(wcn->hal_buf, wcn->hal_rsp_len); 2216 if (ret) { 2217 wcn36xx_err("hal_trigger_ba response failed err=%d\n", ret); 2218 goto out; 2219 } 2220 out: 2221 mutex_unlock(&wcn->hal_mutex); 2222 return ret; 2223 } 2224 2225 static int wcn36xx_smd_tx_compl_ind(struct wcn36xx *wcn, void *buf, size_t len) 2226 { 2227 struct wcn36xx_hal_tx_compl_ind_msg *rsp = buf; 2228 2229 if (len != sizeof(*rsp)) { 2230 wcn36xx_warn("Bad TX complete indication\n"); 2231 return -EIO; 2232 } 2233 2234 wcn36xx_dxe_tx_ack_ind(wcn, rsp->status); 2235 2236 return 0; 2237 } 2238 2239 static int wcn36xx_smd_hw_scan_ind(struct wcn36xx *wcn, void *buf, size_t len) 2240 { 2241 struct wcn36xx_hal_scan_offload_ind *rsp = buf; 2242 struct cfg80211_scan_info scan_info = {}; 2243 2244 if (len != sizeof(*rsp)) { 2245 wcn36xx_warn("Corrupted delete scan indication\n"); 2246 return -EIO; 2247 } 2248 2249 wcn36xx_dbg(WCN36XX_DBG_HAL, "scan indication (type %x)\n", rsp->type); 2250 2251 switch (rsp->type) { 2252 case WCN36XX_HAL_SCAN_IND_FAILED: 2253 case WCN36XX_HAL_SCAN_IND_DEQUEUED: 2254 scan_info.aborted = true; 2255 /* fall through */ 2256 case WCN36XX_HAL_SCAN_IND_COMPLETED: 2257 mutex_lock(&wcn->scan_lock); 2258 wcn->scan_req = NULL; 2259 if (wcn->scan_aborted) 2260 scan_info.aborted = true; 2261 mutex_unlock(&wcn->scan_lock); 2262 ieee80211_scan_completed(wcn->hw, &scan_info); 2263 break; 2264 case WCN36XX_HAL_SCAN_IND_STARTED: 2265 case WCN36XX_HAL_SCAN_IND_FOREIGN_CHANNEL: 2266 case WCN36XX_HAL_SCAN_IND_PREEMPTED: 2267 case WCN36XX_HAL_SCAN_IND_RESTARTED: 2268 break; 2269 default: 2270 wcn36xx_warn("Unknown scan indication type %x\n", rsp->type); 2271 } 2272 2273 return 0; 2274 } 2275 2276 static int wcn36xx_smd_missed_beacon_ind(struct wcn36xx *wcn, 2277 void *buf, 2278 size_t len) 2279 { 2280 struct wcn36xx_hal_missed_beacon_ind_msg *rsp = buf; 2281 struct ieee80211_vif *vif = NULL; 2282 struct wcn36xx_vif *tmp; 2283 2284 /* Old FW does not have bss index */ 2285 if (wcn36xx_is_fw_version(wcn, 1, 2, 2, 24)) { 2286 list_for_each_entry(tmp, &wcn->vif_list, list) { 2287 wcn36xx_dbg(WCN36XX_DBG_HAL, "beacon missed bss_index %d\n", 2288 tmp->bss_index); 2289 vif = wcn36xx_priv_to_vif(tmp); 2290 ieee80211_connection_loss(vif); 2291 } 2292 return 0; 2293 } 2294 2295 if (len != sizeof(*rsp)) { 2296 wcn36xx_warn("Corrupted missed beacon indication\n"); 2297 return -EIO; 2298 } 2299 2300 list_for_each_entry(tmp, &wcn->vif_list, list) { 2301 if (tmp->bss_index == rsp->bss_index) { 2302 wcn36xx_dbg(WCN36XX_DBG_HAL, "beacon missed bss_index %d\n", 2303 rsp->bss_index); 2304 vif = wcn36xx_priv_to_vif(tmp); 2305 ieee80211_connection_loss(vif); 2306 return 0; 2307 } 2308 } 2309 2310 wcn36xx_warn("BSS index %d not found\n", rsp->bss_index); 2311 return -ENOENT; 2312 } 2313 2314 static int wcn36xx_smd_delete_sta_context_ind(struct wcn36xx *wcn, 2315 void *buf, 2316 size_t len) 2317 { 2318 struct wcn36xx_hal_delete_sta_context_ind_msg *rsp = buf; 2319 struct wcn36xx_vif *tmp; 2320 struct ieee80211_sta *sta; 2321 2322 if (len != sizeof(*rsp)) { 2323 wcn36xx_warn("Corrupted delete sta indication\n"); 2324 return -EIO; 2325 } 2326 2327 wcn36xx_dbg(WCN36XX_DBG_HAL, "delete station indication %pM index %d\n", 2328 rsp->addr2, rsp->sta_id); 2329 2330 list_for_each_entry(tmp, &wcn->vif_list, list) { 2331 rcu_read_lock(); 2332 sta = ieee80211_find_sta(wcn36xx_priv_to_vif(tmp), rsp->addr2); 2333 if (sta) 2334 ieee80211_report_low_ack(sta, 0); 2335 rcu_read_unlock(); 2336 if (sta) 2337 return 0; 2338 } 2339 2340 wcn36xx_warn("STA with addr %pM and index %d not found\n", 2341 rsp->addr2, 2342 rsp->sta_id); 2343 return -ENOENT; 2344 } 2345 2346 static int wcn36xx_smd_print_reg_info_ind(struct wcn36xx *wcn, 2347 void *buf, 2348 size_t len) 2349 { 2350 struct wcn36xx_hal_print_reg_info_ind *rsp = buf; 2351 int i; 2352 2353 if (len < sizeof(*rsp)) { 2354 wcn36xx_warn("Corrupted print reg info indication\n"); 2355 return -EIO; 2356 } 2357 2358 wcn36xx_dbg(WCN36XX_DBG_HAL, 2359 "reginfo indication, scenario: 0x%x reason: 0x%x\n", 2360 rsp->scenario, rsp->reason); 2361 2362 for (i = 0; i < rsp->count; i++) { 2363 wcn36xx_dbg(WCN36XX_DBG_HAL, "\t0x%x: 0x%x\n", 2364 rsp->regs[i].addr, rsp->regs[i].value); 2365 } 2366 2367 return 0; 2368 } 2369 2370 int wcn36xx_smd_update_cfg(struct wcn36xx *wcn, u32 cfg_id, u32 value) 2371 { 2372 struct wcn36xx_hal_update_cfg_req_msg msg_body, *body; 2373 size_t len; 2374 int ret; 2375 2376 mutex_lock(&wcn->hal_mutex); 2377 INIT_HAL_MSG(msg_body, WCN36XX_HAL_UPDATE_CFG_REQ); 2378 2379 PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 2380 2381 body = (struct wcn36xx_hal_update_cfg_req_msg *) wcn->hal_buf; 2382 len = msg_body.header.len; 2383 2384 put_cfg_tlv_u32(wcn, &len, cfg_id, value); 2385 body->header.len = len; 2386 body->len = len - sizeof(*body); 2387 2388 ret = wcn36xx_smd_send_and_wait(wcn, body->header.len); 2389 if (ret) { 2390 wcn36xx_err("Sending hal_update_cfg failed\n"); 2391 goto out; 2392 } 2393 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); 2394 if (ret) { 2395 wcn36xx_err("hal_update_cfg response failed err=%d\n", ret); 2396 goto out; 2397 } 2398 out: 2399 mutex_unlock(&wcn->hal_mutex); 2400 return ret; 2401 } 2402 2403 int wcn36xx_smd_set_mc_list(struct wcn36xx *wcn, 2404 struct ieee80211_vif *vif, 2405 struct wcn36xx_hal_rcv_flt_mc_addr_list_type *fp) 2406 { 2407 struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif); 2408 struct wcn36xx_hal_rcv_flt_pkt_set_mc_list_req_msg *msg_body = NULL; 2409 int ret; 2410 2411 mutex_lock(&wcn->hal_mutex); 2412 2413 msg_body = (struct wcn36xx_hal_rcv_flt_pkt_set_mc_list_req_msg *) 2414 wcn->hal_buf; 2415 init_hal_msg(&msg_body->header, WCN36XX_HAL_8023_MULTICAST_LIST_REQ, 2416 sizeof(msg_body->mc_addr_list)); 2417 2418 /* An empty list means all mc traffic will be received */ 2419 if (fp) 2420 memcpy(&msg_body->mc_addr_list, fp, 2421 sizeof(msg_body->mc_addr_list)); 2422 else 2423 msg_body->mc_addr_list.mc_addr_count = 0; 2424 2425 msg_body->mc_addr_list.bss_index = vif_priv->bss_index; 2426 2427 ret = wcn36xx_smd_send_and_wait(wcn, msg_body->header.len); 2428 if (ret) { 2429 wcn36xx_err("Sending HAL_8023_MULTICAST_LIST failed\n"); 2430 goto out; 2431 } 2432 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); 2433 if (ret) { 2434 wcn36xx_err("HAL_8023_MULTICAST_LIST rsp failed err=%d\n", ret); 2435 goto out; 2436 } 2437 out: 2438 mutex_unlock(&wcn->hal_mutex); 2439 return ret; 2440 } 2441 2442 int wcn36xx_smd_rsp_process(struct rpmsg_device *rpdev, 2443 void *buf, int len, void *priv, u32 addr) 2444 { 2445 const struct wcn36xx_hal_msg_header *msg_header = buf; 2446 struct ieee80211_hw *hw = priv; 2447 struct wcn36xx *wcn = hw->priv; 2448 struct wcn36xx_hal_ind_msg *msg_ind; 2449 wcn36xx_dbg_dump(WCN36XX_DBG_SMD_DUMP, "SMD <<< ", buf, len); 2450 2451 switch (msg_header->msg_type) { 2452 case WCN36XX_HAL_START_RSP: 2453 case WCN36XX_HAL_CONFIG_STA_RSP: 2454 case WCN36XX_HAL_CONFIG_BSS_RSP: 2455 case WCN36XX_HAL_ADD_STA_SELF_RSP: 2456 case WCN36XX_HAL_STOP_RSP: 2457 case WCN36XX_HAL_DEL_STA_SELF_RSP: 2458 case WCN36XX_HAL_DELETE_STA_RSP: 2459 case WCN36XX_HAL_INIT_SCAN_RSP: 2460 case WCN36XX_HAL_START_SCAN_RSP: 2461 case WCN36XX_HAL_END_SCAN_RSP: 2462 case WCN36XX_HAL_FINISH_SCAN_RSP: 2463 case WCN36XX_HAL_DOWNLOAD_NV_RSP: 2464 case WCN36XX_HAL_DELETE_BSS_RSP: 2465 case WCN36XX_HAL_SEND_BEACON_RSP: 2466 case WCN36XX_HAL_SET_LINK_ST_RSP: 2467 case WCN36XX_HAL_UPDATE_PROBE_RSP_TEMPLATE_RSP: 2468 case WCN36XX_HAL_SET_BSSKEY_RSP: 2469 case WCN36XX_HAL_SET_STAKEY_RSP: 2470 case WCN36XX_HAL_RMV_STAKEY_RSP: 2471 case WCN36XX_HAL_RMV_BSSKEY_RSP: 2472 case WCN36XX_HAL_ENTER_BMPS_RSP: 2473 case WCN36XX_HAL_SET_POWER_PARAMS_RSP: 2474 case WCN36XX_HAL_EXIT_BMPS_RSP: 2475 case WCN36XX_HAL_KEEP_ALIVE_RSP: 2476 case WCN36XX_HAL_DUMP_COMMAND_RSP: 2477 case WCN36XX_HAL_ADD_BA_SESSION_RSP: 2478 case WCN36XX_HAL_ADD_BA_RSP: 2479 case WCN36XX_HAL_DEL_BA_RSP: 2480 case WCN36XX_HAL_TRIGGER_BA_RSP: 2481 case WCN36XX_HAL_UPDATE_CFG_RSP: 2482 case WCN36XX_HAL_JOIN_RSP: 2483 case WCN36XX_HAL_UPDATE_SCAN_PARAM_RSP: 2484 case WCN36XX_HAL_CH_SWITCH_RSP: 2485 case WCN36XX_HAL_PROCESS_PTT_RSP: 2486 case WCN36XX_HAL_FEATURE_CAPS_EXCHANGE_RSP: 2487 case WCN36XX_HAL_8023_MULTICAST_LIST_RSP: 2488 case WCN36XX_HAL_START_SCAN_OFFLOAD_RSP: 2489 case WCN36XX_HAL_STOP_SCAN_OFFLOAD_RSP: 2490 memcpy(wcn->hal_buf, buf, len); 2491 wcn->hal_rsp_len = len; 2492 complete(&wcn->hal_rsp_compl); 2493 break; 2494 2495 case WCN36XX_HAL_COEX_IND: 2496 case WCN36XX_HAL_AVOID_FREQ_RANGE_IND: 2497 case WCN36XX_HAL_DEL_BA_IND: 2498 case WCN36XX_HAL_OTA_TX_COMPL_IND: 2499 case WCN36XX_HAL_MISSED_BEACON_IND: 2500 case WCN36XX_HAL_DELETE_STA_CONTEXT_IND: 2501 case WCN36XX_HAL_PRINT_REG_INFO_IND: 2502 case WCN36XX_HAL_SCAN_OFFLOAD_IND: 2503 msg_ind = kmalloc(sizeof(*msg_ind) + len, GFP_ATOMIC); 2504 if (!msg_ind) { 2505 wcn36xx_err("Run out of memory while handling SMD_EVENT (%d)\n", 2506 msg_header->msg_type); 2507 return -ENOMEM; 2508 } 2509 2510 msg_ind->msg_len = len; 2511 memcpy(msg_ind->msg, buf, len); 2512 2513 spin_lock(&wcn->hal_ind_lock); 2514 list_add_tail(&msg_ind->list, &wcn->hal_ind_queue); 2515 queue_work(wcn->hal_ind_wq, &wcn->hal_ind_work); 2516 spin_unlock(&wcn->hal_ind_lock); 2517 wcn36xx_dbg(WCN36XX_DBG_HAL, "indication arrived\n"); 2518 break; 2519 default: 2520 wcn36xx_err("SMD_EVENT (%d) not supported\n", 2521 msg_header->msg_type); 2522 } 2523 2524 return 0; 2525 } 2526 2527 static void wcn36xx_ind_smd_work(struct work_struct *work) 2528 { 2529 struct wcn36xx *wcn = 2530 container_of(work, struct wcn36xx, hal_ind_work); 2531 2532 for (;;) { 2533 struct wcn36xx_hal_msg_header *msg_header; 2534 struct wcn36xx_hal_ind_msg *hal_ind_msg; 2535 unsigned long flags; 2536 2537 spin_lock_irqsave(&wcn->hal_ind_lock, flags); 2538 2539 if (list_empty(&wcn->hal_ind_queue)) { 2540 spin_unlock_irqrestore(&wcn->hal_ind_lock, flags); 2541 return; 2542 } 2543 2544 hal_ind_msg = list_first_entry(&wcn->hal_ind_queue, 2545 struct wcn36xx_hal_ind_msg, 2546 list); 2547 list_del(&hal_ind_msg->list); 2548 spin_unlock_irqrestore(&wcn->hal_ind_lock, flags); 2549 2550 msg_header = (struct wcn36xx_hal_msg_header *)hal_ind_msg->msg; 2551 2552 switch (msg_header->msg_type) { 2553 case WCN36XX_HAL_COEX_IND: 2554 case WCN36XX_HAL_DEL_BA_IND: 2555 case WCN36XX_HAL_AVOID_FREQ_RANGE_IND: 2556 break; 2557 case WCN36XX_HAL_OTA_TX_COMPL_IND: 2558 wcn36xx_smd_tx_compl_ind(wcn, 2559 hal_ind_msg->msg, 2560 hal_ind_msg->msg_len); 2561 break; 2562 case WCN36XX_HAL_MISSED_BEACON_IND: 2563 wcn36xx_smd_missed_beacon_ind(wcn, 2564 hal_ind_msg->msg, 2565 hal_ind_msg->msg_len); 2566 break; 2567 case WCN36XX_HAL_DELETE_STA_CONTEXT_IND: 2568 wcn36xx_smd_delete_sta_context_ind(wcn, 2569 hal_ind_msg->msg, 2570 hal_ind_msg->msg_len); 2571 break; 2572 case WCN36XX_HAL_PRINT_REG_INFO_IND: 2573 wcn36xx_smd_print_reg_info_ind(wcn, 2574 hal_ind_msg->msg, 2575 hal_ind_msg->msg_len); 2576 break; 2577 case WCN36XX_HAL_SCAN_OFFLOAD_IND: 2578 wcn36xx_smd_hw_scan_ind(wcn, hal_ind_msg->msg, 2579 hal_ind_msg->msg_len); 2580 break; 2581 default: 2582 wcn36xx_err("SMD_EVENT (%d) not supported\n", 2583 msg_header->msg_type); 2584 } 2585 2586 kfree(hal_ind_msg); 2587 } 2588 } 2589 int wcn36xx_smd_open(struct wcn36xx *wcn) 2590 { 2591 wcn->hal_ind_wq = create_freezable_workqueue("wcn36xx_smd_ind"); 2592 if (!wcn->hal_ind_wq) 2593 return -ENOMEM; 2594 2595 INIT_WORK(&wcn->hal_ind_work, wcn36xx_ind_smd_work); 2596 INIT_LIST_HEAD(&wcn->hal_ind_queue); 2597 spin_lock_init(&wcn->hal_ind_lock); 2598 2599 return 0; 2600 } 2601 2602 void wcn36xx_smd_close(struct wcn36xx *wcn) 2603 { 2604 struct wcn36xx_hal_ind_msg *msg, *tmp; 2605 2606 cancel_work_sync(&wcn->hal_ind_work); 2607 destroy_workqueue(wcn->hal_ind_wq); 2608 2609 list_for_each_entry_safe(msg, tmp, &wcn->hal_ind_queue, list) 2610 kfree(msg); 2611 } 2612