Linux Audio

Check our new training course

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