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