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