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