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