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