cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

main.c (48502B)


      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/module.h>
     20#include <linux/firmware.h>
     21#include <linux/platform_device.h>
     22#include <linux/of_address.h>
     23#include <linux/of_device.h>
     24#include <linux/of_irq.h>
     25#include <linux/rpmsg.h>
     26#include <linux/soc/qcom/smem_state.h>
     27#include <linux/soc/qcom/wcnss_ctrl.h>
     28#include <net/ipv6.h>
     29#include "wcn36xx.h"
     30#include "testmode.h"
     31
     32unsigned int wcn36xx_dbg_mask;
     33module_param_named(debug_mask, wcn36xx_dbg_mask, uint, 0644);
     34MODULE_PARM_DESC(debug_mask, "Debugging mask");
     35
     36#define CHAN2G(_freq, _idx) { \
     37	.band = NL80211_BAND_2GHZ, \
     38	.center_freq = (_freq), \
     39	.hw_value = (_idx), \
     40	.max_power = 25, \
     41}
     42
     43#define CHAN5G(_freq, _idx, _phy_val) { \
     44	.band = NL80211_BAND_5GHZ, \
     45	.center_freq = (_freq), \
     46	.hw_value = (_phy_val) << HW_VALUE_PHY_SHIFT | HW_VALUE_CHANNEL(_idx), \
     47	.max_power = 25, \
     48}
     49
     50/* The wcn firmware expects channel values to matching
     51 * their mnemonic values. So use these for .hw_value. */
     52static struct ieee80211_channel wcn_2ghz_channels[] = {
     53	CHAN2G(2412, 1), /* Channel 1 */
     54	CHAN2G(2417, 2), /* Channel 2 */
     55	CHAN2G(2422, 3), /* Channel 3 */
     56	CHAN2G(2427, 4), /* Channel 4 */
     57	CHAN2G(2432, 5), /* Channel 5 */
     58	CHAN2G(2437, 6), /* Channel 6 */
     59	CHAN2G(2442, 7), /* Channel 7 */
     60	CHAN2G(2447, 8), /* Channel 8 */
     61	CHAN2G(2452, 9), /* Channel 9 */
     62	CHAN2G(2457, 10), /* Channel 10 */
     63	CHAN2G(2462, 11), /* Channel 11 */
     64	CHAN2G(2467, 12), /* Channel 12 */
     65	CHAN2G(2472, 13), /* Channel 13 */
     66	CHAN2G(2484, 14)  /* Channel 14 */
     67
     68};
     69
     70static struct ieee80211_channel wcn_5ghz_channels[] = {
     71	CHAN5G(5180, 36, PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW),
     72	CHAN5G(5200, 40, PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW),
     73	CHAN5G(5220, 44, PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH),
     74	CHAN5G(5240, 48, PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH),
     75	CHAN5G(5260, 52, PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW),
     76	CHAN5G(5280, 56, PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW),
     77	CHAN5G(5300, 60, PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH),
     78	CHAN5G(5320, 64, PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH),
     79	CHAN5G(5500, 100, PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW),
     80	CHAN5G(5520, 104, PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW),
     81	CHAN5G(5540, 108, PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH),
     82	CHAN5G(5560, 112, PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH),
     83	CHAN5G(5580, 116, PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW),
     84	CHAN5G(5600, 120, PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW),
     85	CHAN5G(5620, 124, PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH),
     86	CHAN5G(5640, 128, PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH),
     87	CHAN5G(5660, 132, PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW),
     88	CHAN5G(5680, 136, PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW),
     89	CHAN5G(5700, 140, PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH),
     90	CHAN5G(5720, 144, PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH),
     91	CHAN5G(5745, 149, PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW),
     92	CHAN5G(5765, 153, PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW),
     93	CHAN5G(5785, 157, PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH),
     94	CHAN5G(5805, 161, PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH),
     95	CHAN5G(5825, 165, 0)
     96};
     97
     98#define RATE(_bitrate, _hw_rate, _flags) { \
     99	.bitrate        = (_bitrate),                   \
    100	.flags          = (_flags),                     \
    101	.hw_value       = (_hw_rate),                   \
    102	.hw_value_short = (_hw_rate)  \
    103}
    104
    105static struct ieee80211_rate wcn_2ghz_rates[] = {
    106	RATE(10, HW_RATE_INDEX_1MBPS, 0),
    107	RATE(20, HW_RATE_INDEX_2MBPS, IEEE80211_RATE_SHORT_PREAMBLE),
    108	RATE(55, HW_RATE_INDEX_5_5MBPS, IEEE80211_RATE_SHORT_PREAMBLE),
    109	RATE(110, HW_RATE_INDEX_11MBPS, IEEE80211_RATE_SHORT_PREAMBLE),
    110	RATE(60, HW_RATE_INDEX_6MBPS, 0),
    111	RATE(90, HW_RATE_INDEX_9MBPS, 0),
    112	RATE(120, HW_RATE_INDEX_12MBPS, 0),
    113	RATE(180, HW_RATE_INDEX_18MBPS, 0),
    114	RATE(240, HW_RATE_INDEX_24MBPS, 0),
    115	RATE(360, HW_RATE_INDEX_36MBPS, 0),
    116	RATE(480, HW_RATE_INDEX_48MBPS, 0),
    117	RATE(540, HW_RATE_INDEX_54MBPS, 0)
    118};
    119
    120static struct ieee80211_rate wcn_5ghz_rates[] = {
    121	RATE(60, HW_RATE_INDEX_6MBPS, 0),
    122	RATE(90, HW_RATE_INDEX_9MBPS, 0),
    123	RATE(120, HW_RATE_INDEX_12MBPS, 0),
    124	RATE(180, HW_RATE_INDEX_18MBPS, 0),
    125	RATE(240, HW_RATE_INDEX_24MBPS, 0),
    126	RATE(360, HW_RATE_INDEX_36MBPS, 0),
    127	RATE(480, HW_RATE_INDEX_48MBPS, 0),
    128	RATE(540, HW_RATE_INDEX_54MBPS, 0)
    129};
    130
    131static struct ieee80211_supported_band wcn_band_2ghz = {
    132	.channels	= wcn_2ghz_channels,
    133	.n_channels	= ARRAY_SIZE(wcn_2ghz_channels),
    134	.bitrates	= wcn_2ghz_rates,
    135	.n_bitrates	= ARRAY_SIZE(wcn_2ghz_rates),
    136	.ht_cap		= {
    137		.cap =	IEEE80211_HT_CAP_GRN_FLD |
    138			IEEE80211_HT_CAP_SGI_20 |
    139			IEEE80211_HT_CAP_DSSSCCK40 |
    140			IEEE80211_HT_CAP_LSIG_TXOP_PROT |
    141			IEEE80211_HT_CAP_SGI_40 |
    142			IEEE80211_HT_CAP_SUP_WIDTH_20_40,
    143		.ht_supported = true,
    144		.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
    145		.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
    146		.mcs = {
    147			.rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
    148			.rx_highest = cpu_to_le16(72),
    149			.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
    150		}
    151	}
    152};
    153
    154static struct ieee80211_supported_band wcn_band_5ghz = {
    155	.channels	= wcn_5ghz_channels,
    156	.n_channels	= ARRAY_SIZE(wcn_5ghz_channels),
    157	.bitrates	= wcn_5ghz_rates,
    158	.n_bitrates	= ARRAY_SIZE(wcn_5ghz_rates),
    159	.ht_cap		= {
    160		.cap =	IEEE80211_HT_CAP_GRN_FLD |
    161			IEEE80211_HT_CAP_SGI_20 |
    162			IEEE80211_HT_CAP_DSSSCCK40 |
    163			IEEE80211_HT_CAP_LSIG_TXOP_PROT |
    164			IEEE80211_HT_CAP_SGI_40 |
    165			IEEE80211_HT_CAP_SUP_WIDTH_20_40,
    166		.ht_supported = true,
    167		.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
    168		.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
    169		.mcs = {
    170			.rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
    171			.rx_highest = cpu_to_le16(150),
    172			.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
    173		}
    174	}
    175};
    176
    177#ifdef CONFIG_PM
    178
    179static const struct wiphy_wowlan_support wowlan_support = {
    180	.flags = WIPHY_WOWLAN_ANY	|
    181		 WIPHY_WOWLAN_MAGIC_PKT	|
    182		 WIPHY_WOWLAN_SUPPORTS_GTK_REKEY
    183};
    184
    185#endif
    186
    187static inline u8 get_sta_index(struct ieee80211_vif *vif,
    188			       struct wcn36xx_sta *sta_priv)
    189{
    190	return NL80211_IFTYPE_STATION == vif->type ?
    191	       sta_priv->bss_sta_index :
    192	       sta_priv->sta_index;
    193}
    194
    195#define DEFINE(s) [s] = #s
    196
    197static const char * const wcn36xx_caps_names[] = {
    198	DEFINE(MCC),
    199	DEFINE(P2P),
    200	DEFINE(DOT11AC),
    201	DEFINE(SLM_SESSIONIZATION),
    202	DEFINE(DOT11AC_OPMODE),
    203	DEFINE(SAP32STA),
    204	DEFINE(TDLS),
    205	DEFINE(P2P_GO_NOA_DECOUPLE_INIT_SCAN),
    206	DEFINE(WLANACTIVE_OFFLOAD),
    207	DEFINE(BEACON_OFFLOAD),
    208	DEFINE(SCAN_OFFLOAD),
    209	DEFINE(ROAM_OFFLOAD),
    210	DEFINE(BCN_MISS_OFFLOAD),
    211	DEFINE(STA_POWERSAVE),
    212	DEFINE(STA_ADVANCED_PWRSAVE),
    213	DEFINE(AP_UAPSD),
    214	DEFINE(AP_DFS),
    215	DEFINE(BLOCKACK),
    216	DEFINE(PHY_ERR),
    217	DEFINE(BCN_FILTER),
    218	DEFINE(RTT),
    219	DEFINE(RATECTRL),
    220	DEFINE(WOW),
    221	DEFINE(WLAN_ROAM_SCAN_OFFLOAD),
    222	DEFINE(SPECULATIVE_PS_POLL),
    223	DEFINE(SCAN_SCH),
    224	DEFINE(IBSS_HEARTBEAT_OFFLOAD),
    225	DEFINE(WLAN_SCAN_OFFLOAD),
    226	DEFINE(WLAN_PERIODIC_TX_PTRN),
    227	DEFINE(ADVANCE_TDLS),
    228	DEFINE(BATCH_SCAN),
    229	DEFINE(FW_IN_TX_PATH),
    230	DEFINE(EXTENDED_NSOFFLOAD_SLOT),
    231	DEFINE(CH_SWITCH_V1),
    232	DEFINE(HT40_OBSS_SCAN),
    233	DEFINE(UPDATE_CHANNEL_LIST),
    234	DEFINE(WLAN_MCADDR_FLT),
    235	DEFINE(WLAN_CH144),
    236	DEFINE(NAN),
    237	DEFINE(TDLS_SCAN_COEXISTENCE),
    238	DEFINE(LINK_LAYER_STATS_MEAS),
    239	DEFINE(MU_MIMO),
    240	DEFINE(EXTENDED_SCAN),
    241	DEFINE(DYNAMIC_WMM_PS),
    242	DEFINE(MAC_SPOOFED_SCAN),
    243	DEFINE(BMU_ERROR_GENERIC_RECOVERY),
    244	DEFINE(DISA),
    245	DEFINE(FW_STATS),
    246	DEFINE(WPS_PRBRSP_TMPL),
    247	DEFINE(BCN_IE_FLT_DELTA),
    248	DEFINE(TDLS_OFF_CHANNEL),
    249	DEFINE(RTT3),
    250	DEFINE(MGMT_FRAME_LOGGING),
    251	DEFINE(ENHANCED_TXBD_COMPLETION),
    252	DEFINE(LOGGING_ENHANCEMENT),
    253	DEFINE(EXT_SCAN_ENHANCED),
    254	DEFINE(MEMORY_DUMP_SUPPORTED),
    255	DEFINE(PER_PKT_STATS_SUPPORTED),
    256	DEFINE(EXT_LL_STAT),
    257	DEFINE(WIFI_CONFIG),
    258	DEFINE(ANTENNA_DIVERSITY_SELECTION),
    259};
    260
    261#undef DEFINE
    262
    263static const char *wcn36xx_get_cap_name(enum place_holder_in_cap_bitmap x)
    264{
    265	if (x >= ARRAY_SIZE(wcn36xx_caps_names))
    266		return "UNKNOWN";
    267	return wcn36xx_caps_names[x];
    268}
    269
    270static void wcn36xx_feat_caps_info(struct wcn36xx *wcn)
    271{
    272	int i;
    273
    274	for (i = 0; i < MAX_FEATURE_SUPPORTED; i++) {
    275		if (get_feat_caps(wcn->fw_feat_caps, i))
    276			wcn36xx_dbg(WCN36XX_DBG_MAC, "FW Cap %s\n", wcn36xx_get_cap_name(i));
    277	}
    278}
    279
    280static int wcn36xx_start(struct ieee80211_hw *hw)
    281{
    282	struct wcn36xx *wcn = hw->priv;
    283	int ret;
    284
    285	wcn36xx_dbg(WCN36XX_DBG_MAC, "mac start\n");
    286
    287	/* SMD initialization */
    288	ret = wcn36xx_smd_open(wcn);
    289	if (ret) {
    290		wcn36xx_err("Failed to open smd channel: %d\n", ret);
    291		goto out_err;
    292	}
    293
    294	/* Allocate memory pools for Mgmt BD headers and Data BD headers */
    295	ret = wcn36xx_dxe_allocate_mem_pools(wcn);
    296	if (ret) {
    297		wcn36xx_err("Failed to alloc DXE mempool: %d\n", ret);
    298		goto out_smd_close;
    299	}
    300
    301	ret = wcn36xx_dxe_alloc_ctl_blks(wcn);
    302	if (ret) {
    303		wcn36xx_err("Failed to alloc DXE ctl blocks: %d\n", ret);
    304		goto out_free_dxe_pool;
    305	}
    306
    307	ret = wcn36xx_smd_load_nv(wcn);
    308	if (ret) {
    309		wcn36xx_err("Failed to push NV to chip\n");
    310		goto out_free_dxe_ctl;
    311	}
    312
    313	ret = wcn36xx_smd_start(wcn);
    314	if (ret) {
    315		wcn36xx_err("Failed to start chip\n");
    316		goto out_free_dxe_ctl;
    317	}
    318
    319	if (!wcn36xx_is_fw_version(wcn, 1, 2, 2, 24)) {
    320		ret = wcn36xx_smd_feature_caps_exchange(wcn);
    321		if (ret)
    322			wcn36xx_warn("Exchange feature caps failed\n");
    323		else
    324			wcn36xx_feat_caps_info(wcn);
    325	}
    326
    327	/* DMA channel initialization */
    328	ret = wcn36xx_dxe_init(wcn);
    329	if (ret) {
    330		wcn36xx_err("DXE init failed\n");
    331		goto out_smd_stop;
    332	}
    333
    334	wcn36xx_debugfs_init(wcn);
    335
    336	INIT_LIST_HEAD(&wcn->vif_list);
    337	spin_lock_init(&wcn->dxe_lock);
    338	spin_lock_init(&wcn->survey_lock);
    339
    340	return 0;
    341
    342out_smd_stop:
    343	wcn36xx_smd_stop(wcn);
    344out_free_dxe_ctl:
    345	wcn36xx_dxe_free_ctl_blks(wcn);
    346out_free_dxe_pool:
    347	wcn36xx_dxe_free_mem_pools(wcn);
    348out_smd_close:
    349	wcn36xx_smd_close(wcn);
    350out_err:
    351	return ret;
    352}
    353
    354static void wcn36xx_stop(struct ieee80211_hw *hw)
    355{
    356	struct wcn36xx *wcn = hw->priv;
    357
    358	wcn36xx_dbg(WCN36XX_DBG_MAC, "mac stop\n");
    359
    360	mutex_lock(&wcn->scan_lock);
    361	if (wcn->scan_req) {
    362		struct cfg80211_scan_info scan_info = {
    363			.aborted = true,
    364		};
    365
    366		ieee80211_scan_completed(wcn->hw, &scan_info);
    367	}
    368	wcn->scan_req = NULL;
    369	mutex_unlock(&wcn->scan_lock);
    370
    371	wcn36xx_debugfs_exit(wcn);
    372	wcn36xx_smd_stop(wcn);
    373	wcn36xx_dxe_deinit(wcn);
    374	wcn36xx_smd_close(wcn);
    375
    376	wcn36xx_dxe_free_mem_pools(wcn);
    377	wcn36xx_dxe_free_ctl_blks(wcn);
    378}
    379
    380static void wcn36xx_change_ps(struct wcn36xx *wcn, bool enable)
    381{
    382	struct ieee80211_vif *vif = NULL;
    383	struct wcn36xx_vif *tmp;
    384
    385	list_for_each_entry(tmp, &wcn->vif_list, list) {
    386		vif = wcn36xx_priv_to_vif(tmp);
    387		if (enable && !wcn->sw_scan) {
    388			if (vif->bss_conf.ps) /* ps allowed ? */
    389				wcn36xx_pmc_enter_bmps_state(wcn, vif);
    390		} else {
    391			wcn36xx_pmc_exit_bmps_state(wcn, vif);
    392		}
    393	}
    394}
    395
    396static void wcn36xx_change_opchannel(struct wcn36xx *wcn, int ch)
    397{
    398	struct ieee80211_vif *vif = NULL;
    399	struct wcn36xx_vif *tmp;
    400	struct ieee80211_supported_band *band;
    401	struct ieee80211_channel *channel = NULL;
    402	unsigned long flags;
    403	int i, j;
    404
    405	for (i = 0; i < ARRAY_SIZE(wcn->hw->wiphy->bands); i++) {
    406		band = wcn->hw->wiphy->bands[i];
    407		if (!band)
    408			break;
    409		for (j = 0; j < band->n_channels; j++) {
    410			if (HW_VALUE_CHANNEL(band->channels[j].hw_value) == ch) {
    411				channel = &band->channels[j];
    412				break;
    413			}
    414		}
    415		if (channel)
    416			break;
    417	}
    418
    419	if (!channel) {
    420		wcn36xx_err("Cannot tune to channel %d\n", ch);
    421		return;
    422	}
    423
    424	spin_lock_irqsave(&wcn->survey_lock, flags);
    425	wcn->band = band;
    426	wcn->channel = channel;
    427	spin_unlock_irqrestore(&wcn->survey_lock, flags);
    428
    429	list_for_each_entry(tmp, &wcn->vif_list, list) {
    430		vif = wcn36xx_priv_to_vif(tmp);
    431		wcn36xx_smd_switch_channel(wcn, vif, ch);
    432	}
    433
    434	return;
    435}
    436
    437static int wcn36xx_config(struct ieee80211_hw *hw, u32 changed)
    438{
    439	struct wcn36xx *wcn = hw->priv;
    440	int ret;
    441
    442	wcn36xx_dbg(WCN36XX_DBG_MAC, "mac config changed 0x%08x\n", changed);
    443
    444	mutex_lock(&wcn->conf_mutex);
    445
    446	if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
    447		int ch = WCN36XX_HW_CHANNEL(wcn);
    448		wcn36xx_dbg(WCN36XX_DBG_MAC, "wcn36xx_config channel switch=%d\n",
    449			    ch);
    450
    451		if (wcn->sw_scan_opchannel == ch && wcn->sw_scan_channel) {
    452			/* If channel is the initial operating channel, we may
    453			 * want to receive/transmit regular data packets, then
    454			 * simply stop the scan session and exit PS mode.
    455			 */
    456			if (wcn->sw_scan_channel)
    457				wcn36xx_smd_end_scan(wcn, wcn->sw_scan_channel);
    458			if (wcn->sw_scan_init) {
    459				wcn36xx_smd_finish_scan(wcn, HAL_SYS_MODE_SCAN,
    460							wcn->sw_scan_vif);
    461			}
    462		} else if (wcn->sw_scan) {
    463			/* A scan is ongoing, do not change the operating
    464			 * channel, but start a scan session on the channel.
    465			 */
    466			if (wcn->sw_scan_channel)
    467				wcn36xx_smd_end_scan(wcn, wcn->sw_scan_channel);
    468			if (!wcn->sw_scan_init) {
    469				/* This can fail if we are unable to notify the
    470				 * operating channel.
    471				 */
    472				ret = wcn36xx_smd_init_scan(wcn,
    473							    HAL_SYS_MODE_SCAN,
    474							    wcn->sw_scan_vif);
    475				if (ret) {
    476					mutex_unlock(&wcn->conf_mutex);
    477					return -EIO;
    478				}
    479			}
    480			wcn36xx_smd_start_scan(wcn, ch);
    481		} else {
    482			wcn36xx_change_opchannel(wcn, ch);
    483		}
    484	}
    485
    486	if (changed & IEEE80211_CONF_CHANGE_PS)
    487		wcn36xx_change_ps(wcn, hw->conf.flags & IEEE80211_CONF_PS);
    488
    489	if (changed & IEEE80211_CONF_CHANGE_IDLE) {
    490		if (hw->conf.flags & IEEE80211_CONF_IDLE)
    491			wcn36xx_smd_enter_imps(wcn);
    492		else
    493			wcn36xx_smd_exit_imps(wcn);
    494	}
    495
    496	mutex_unlock(&wcn->conf_mutex);
    497
    498	return 0;
    499}
    500
    501static void wcn36xx_configure_filter(struct ieee80211_hw *hw,
    502				     unsigned int changed,
    503				     unsigned int *total, u64 multicast)
    504{
    505	struct wcn36xx_hal_rcv_flt_mc_addr_list_type *fp;
    506	struct wcn36xx *wcn = hw->priv;
    507	struct wcn36xx_vif *tmp;
    508	struct ieee80211_vif *vif = NULL;
    509
    510	wcn36xx_dbg(WCN36XX_DBG_MAC, "mac configure filter\n");
    511
    512	mutex_lock(&wcn->conf_mutex);
    513
    514	*total &= FIF_ALLMULTI;
    515
    516	fp = (void *)(unsigned long)multicast;
    517	list_for_each_entry(tmp, &wcn->vif_list, list) {
    518		vif = wcn36xx_priv_to_vif(tmp);
    519
    520		/* FW handles MC filtering only when connected as STA */
    521		if (*total & FIF_ALLMULTI)
    522			wcn36xx_smd_set_mc_list(wcn, vif, NULL);
    523		else if (NL80211_IFTYPE_STATION == vif->type && tmp->sta_assoc)
    524			wcn36xx_smd_set_mc_list(wcn, vif, fp);
    525	}
    526
    527	mutex_unlock(&wcn->conf_mutex);
    528	kfree(fp);
    529}
    530
    531static u64 wcn36xx_prepare_multicast(struct ieee80211_hw *hw,
    532				     struct netdev_hw_addr_list *mc_list)
    533{
    534	struct wcn36xx_hal_rcv_flt_mc_addr_list_type *fp;
    535	struct netdev_hw_addr *ha;
    536
    537	wcn36xx_dbg(WCN36XX_DBG_MAC, "mac prepare multicast list\n");
    538	fp = kzalloc(sizeof(*fp), GFP_ATOMIC);
    539	if (!fp) {
    540		wcn36xx_err("Out of memory setting filters.\n");
    541		return 0;
    542	}
    543
    544	fp->mc_addr_count = 0;
    545	/* update multicast filtering parameters */
    546	if (netdev_hw_addr_list_count(mc_list) <=
    547	    WCN36XX_HAL_MAX_NUM_MULTICAST_ADDRESS) {
    548		netdev_hw_addr_list_for_each(ha, mc_list) {
    549			memcpy(fp->mc_addr[fp->mc_addr_count],
    550					ha->addr, ETH_ALEN);
    551			fp->mc_addr_count++;
    552		}
    553	}
    554
    555	return (u64)(unsigned long)fp;
    556}
    557
    558static void wcn36xx_tx(struct ieee80211_hw *hw,
    559		       struct ieee80211_tx_control *control,
    560		       struct sk_buff *skb)
    561{
    562	struct wcn36xx *wcn = hw->priv;
    563	struct wcn36xx_sta *sta_priv = NULL;
    564
    565	if (control->sta)
    566		sta_priv = wcn36xx_sta_to_priv(control->sta);
    567
    568	if (wcn36xx_start_tx(wcn, sta_priv, skb))
    569		ieee80211_free_txskb(wcn->hw, skb);
    570}
    571
    572static int wcn36xx_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
    573			   struct ieee80211_vif *vif,
    574			   struct ieee80211_sta *sta,
    575			   struct ieee80211_key_conf *key_conf)
    576{
    577	struct wcn36xx *wcn = hw->priv;
    578	struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
    579	struct wcn36xx_sta *sta_priv = sta ? wcn36xx_sta_to_priv(sta) : NULL;
    580	int ret = 0;
    581	u8 key[WLAN_MAX_KEY_LEN];
    582
    583	wcn36xx_dbg(WCN36XX_DBG_MAC, "mac80211 set key\n");
    584	wcn36xx_dbg(WCN36XX_DBG_MAC, "Key: cmd=0x%x algo:0x%x, id:%d, len:%d flags 0x%x\n",
    585		    cmd, key_conf->cipher, key_conf->keyidx,
    586		    key_conf->keylen, key_conf->flags);
    587	wcn36xx_dbg_dump(WCN36XX_DBG_MAC, "KEY: ",
    588			 key_conf->key,
    589			 key_conf->keylen);
    590
    591	mutex_lock(&wcn->conf_mutex);
    592
    593	switch (key_conf->cipher) {
    594	case WLAN_CIPHER_SUITE_WEP40:
    595		vif_priv->encrypt_type = WCN36XX_HAL_ED_WEP40;
    596		break;
    597	case WLAN_CIPHER_SUITE_WEP104:
    598		vif_priv->encrypt_type = WCN36XX_HAL_ED_WEP104;
    599		break;
    600	case WLAN_CIPHER_SUITE_CCMP:
    601		vif_priv->encrypt_type = WCN36XX_HAL_ED_CCMP;
    602		break;
    603	case WLAN_CIPHER_SUITE_TKIP:
    604		vif_priv->encrypt_type = WCN36XX_HAL_ED_TKIP;
    605		break;
    606	default:
    607		wcn36xx_err("Unsupported key type 0x%x\n",
    608			      key_conf->cipher);
    609		ret = -EOPNOTSUPP;
    610		goto out;
    611	}
    612
    613	switch (cmd) {
    614	case SET_KEY:
    615		if (WCN36XX_HAL_ED_TKIP == vif_priv->encrypt_type) {
    616			/*
    617			 * Supplicant is sending key in the wrong order:
    618			 * Temporal Key (16 b) - TX MIC (8 b) - RX MIC (8 b)
    619			 * but HW expects it to be in the order as described in
    620			 * IEEE 802.11 spec (see chapter 11.7) like this:
    621			 * Temporal Key (16 b) - RX MIC (8 b) - TX MIC (8 b)
    622			 */
    623			memcpy(key, key_conf->key, 16);
    624			memcpy(key + 16, key_conf->key + 24, 8);
    625			memcpy(key + 24, key_conf->key + 16, 8);
    626		} else {
    627			memcpy(key, key_conf->key, key_conf->keylen);
    628		}
    629
    630		if (IEEE80211_KEY_FLAG_PAIRWISE & key_conf->flags) {
    631			sta_priv->is_data_encrypted = true;
    632			/* Reconfigure bss with encrypt_type */
    633			if (NL80211_IFTYPE_STATION == vif->type) {
    634				wcn36xx_smd_config_bss(wcn,
    635						       vif,
    636						       sta,
    637						       sta->addr,
    638						       true);
    639				wcn36xx_smd_config_sta(wcn, vif, sta);
    640			}
    641
    642			wcn36xx_smd_set_stakey(wcn,
    643				vif_priv->encrypt_type,
    644				key_conf->keyidx,
    645				key_conf->keylen,
    646				key,
    647				get_sta_index(vif, sta_priv));
    648		} else {
    649			wcn36xx_smd_set_bsskey(wcn,
    650				vif_priv->encrypt_type,
    651				vif_priv->bss_index,
    652				key_conf->keyidx,
    653				key_conf->keylen,
    654				key);
    655
    656			if ((WLAN_CIPHER_SUITE_WEP40 == key_conf->cipher) ||
    657			    (WLAN_CIPHER_SUITE_WEP104 == key_conf->cipher)) {
    658				list_for_each_entry(sta_priv,
    659						    &vif_priv->sta_list, list) {
    660					sta_priv->is_data_encrypted = true;
    661					wcn36xx_smd_set_stakey(wcn,
    662						vif_priv->encrypt_type,
    663						key_conf->keyidx,
    664						key_conf->keylen,
    665						key,
    666						get_sta_index(vif, sta_priv));
    667				}
    668			}
    669		}
    670		break;
    671	case DISABLE_KEY:
    672		if (!(IEEE80211_KEY_FLAG_PAIRWISE & key_conf->flags)) {
    673			if (vif_priv->bss_index != WCN36XX_HAL_BSS_INVALID_IDX)
    674				wcn36xx_smd_remove_bsskey(wcn,
    675					vif_priv->encrypt_type,
    676					vif_priv->bss_index,
    677					key_conf->keyidx);
    678
    679			vif_priv->encrypt_type = WCN36XX_HAL_ED_NONE;
    680		} else {
    681			sta_priv->is_data_encrypted = false;
    682			/* do not remove key if disassociated */
    683			if (sta_priv->aid)
    684				wcn36xx_smd_remove_stakey(wcn,
    685					vif_priv->encrypt_type,
    686					key_conf->keyidx,
    687					get_sta_index(vif, sta_priv));
    688		}
    689		break;
    690	default:
    691		wcn36xx_err("Unsupported key cmd 0x%x\n", cmd);
    692		ret = -EOPNOTSUPP;
    693		goto out;
    694	}
    695
    696out:
    697	mutex_unlock(&wcn->conf_mutex);
    698
    699	return ret;
    700}
    701
    702static int wcn36xx_hw_scan(struct ieee80211_hw *hw,
    703			   struct ieee80211_vif *vif,
    704			   struct ieee80211_scan_request *hw_req)
    705{
    706	struct wcn36xx *wcn = hw->priv;
    707
    708	if (!get_feat_caps(wcn->fw_feat_caps, SCAN_OFFLOAD)) {
    709		/* fallback to mac80211 software scan */
    710		return 1;
    711	}
    712
    713	/* Firmware scan offload is limited to 48 channels, fallback to
    714	 * software driven scanning otherwise.
    715	 */
    716	if (hw_req->req.n_channels > 48) {
    717		wcn36xx_warn("Offload scan aborted, n_channels=%u",
    718			     hw_req->req.n_channels);
    719		return 1;
    720	}
    721
    722	mutex_lock(&wcn->scan_lock);
    723	if (wcn->scan_req) {
    724		mutex_unlock(&wcn->scan_lock);
    725		return -EBUSY;
    726	}
    727
    728	wcn->scan_aborted = false;
    729	wcn->scan_req = &hw_req->req;
    730
    731	mutex_unlock(&wcn->scan_lock);
    732
    733	wcn36xx_smd_update_channel_list(wcn, &hw_req->req);
    734	return wcn36xx_smd_start_hw_scan(wcn, vif, &hw_req->req);
    735}
    736
    737static void wcn36xx_cancel_hw_scan(struct ieee80211_hw *hw,
    738				   struct ieee80211_vif *vif)
    739{
    740	struct wcn36xx *wcn = hw->priv;
    741
    742	mutex_lock(&wcn->scan_lock);
    743	wcn->scan_aborted = true;
    744	mutex_unlock(&wcn->scan_lock);
    745
    746	if (get_feat_caps(wcn->fw_feat_caps, SCAN_OFFLOAD)) {
    747		/* ieee80211_scan_completed will be called on FW scan
    748		 * indication */
    749		wcn36xx_smd_stop_hw_scan(wcn);
    750	}
    751}
    752
    753static void wcn36xx_sw_scan_start(struct ieee80211_hw *hw,
    754				  struct ieee80211_vif *vif,
    755				  const u8 *mac_addr)
    756{
    757	struct wcn36xx *wcn = hw->priv;
    758	struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
    759
    760	wcn36xx_dbg(WCN36XX_DBG_MAC, "sw_scan_start");
    761
    762	wcn->sw_scan = true;
    763	wcn->sw_scan_vif = vif;
    764	wcn->sw_scan_channel = 0;
    765	if (vif_priv->sta_assoc)
    766		wcn->sw_scan_opchannel = WCN36XX_HW_CHANNEL(wcn);
    767	else
    768		wcn->sw_scan_opchannel = 0;
    769}
    770
    771static void wcn36xx_sw_scan_complete(struct ieee80211_hw *hw,
    772				     struct ieee80211_vif *vif)
    773{
    774	struct wcn36xx *wcn = hw->priv;
    775
    776	wcn36xx_dbg(WCN36XX_DBG_MAC, "sw_scan_complete");
    777
    778	/* ensure that any scan session is finished */
    779	if (wcn->sw_scan_channel)
    780		wcn36xx_smd_end_scan(wcn, wcn->sw_scan_channel);
    781	if (wcn->sw_scan_init) {
    782		wcn36xx_smd_finish_scan(wcn, HAL_SYS_MODE_SCAN,
    783					wcn->sw_scan_vif);
    784	}
    785	wcn->sw_scan = false;
    786	wcn->sw_scan_opchannel = 0;
    787}
    788
    789static void wcn36xx_update_allowed_rates(struct ieee80211_sta *sta,
    790					 enum nl80211_band band)
    791{
    792	int i, size;
    793	u16 *rates_table;
    794	struct wcn36xx_sta *sta_priv = wcn36xx_sta_to_priv(sta);
    795	u32 rates = sta->deflink.supp_rates[band];
    796
    797	memset(&sta_priv->supported_rates, 0,
    798		sizeof(sta_priv->supported_rates));
    799	sta_priv->supported_rates.op_rate_mode = STA_11n;
    800
    801	size = ARRAY_SIZE(sta_priv->supported_rates.dsss_rates);
    802	rates_table = sta_priv->supported_rates.dsss_rates;
    803	if (band == NL80211_BAND_2GHZ) {
    804		for (i = 0; i < size; i++) {
    805			if (rates & 0x01) {
    806				rates_table[i] = wcn_2ghz_rates[i].hw_value;
    807				rates = rates >> 1;
    808			}
    809		}
    810	}
    811
    812	size = ARRAY_SIZE(sta_priv->supported_rates.ofdm_rates);
    813	rates_table = sta_priv->supported_rates.ofdm_rates;
    814	for (i = 0; i < size; i++) {
    815		if (rates & 0x01) {
    816			rates_table[i] = wcn_5ghz_rates[i].hw_value;
    817			rates = rates >> 1;
    818		}
    819	}
    820
    821	if (sta->deflink.ht_cap.ht_supported) {
    822		BUILD_BUG_ON(sizeof(sta->deflink.ht_cap.mcs.rx_mask) >
    823			     sizeof(sta_priv->supported_rates.supported_mcs_set));
    824		memcpy(sta_priv->supported_rates.supported_mcs_set,
    825		       sta->deflink.ht_cap.mcs.rx_mask,
    826		       sizeof(sta->deflink.ht_cap.mcs.rx_mask));
    827	}
    828
    829	if (sta->deflink.vht_cap.vht_supported) {
    830		sta_priv->supported_rates.op_rate_mode = STA_11ac;
    831		sta_priv->supported_rates.vht_rx_mcs_map =
    832				sta->deflink.vht_cap.vht_mcs.rx_mcs_map;
    833		sta_priv->supported_rates.vht_tx_mcs_map =
    834				sta->deflink.vht_cap.vht_mcs.tx_mcs_map;
    835	}
    836}
    837
    838void wcn36xx_set_default_rates(struct wcn36xx_hal_supported_rates *rates)
    839{
    840	u16 ofdm_rates[WCN36XX_HAL_NUM_OFDM_RATES] = {
    841		HW_RATE_INDEX_6MBPS,
    842		HW_RATE_INDEX_9MBPS,
    843		HW_RATE_INDEX_12MBPS,
    844		HW_RATE_INDEX_18MBPS,
    845		HW_RATE_INDEX_24MBPS,
    846		HW_RATE_INDEX_36MBPS,
    847		HW_RATE_INDEX_48MBPS,
    848		HW_RATE_INDEX_54MBPS
    849	};
    850	u16 dsss_rates[WCN36XX_HAL_NUM_DSSS_RATES] = {
    851		HW_RATE_INDEX_1MBPS,
    852		HW_RATE_INDEX_2MBPS,
    853		HW_RATE_INDEX_5_5MBPS,
    854		HW_RATE_INDEX_11MBPS
    855	};
    856
    857	rates->op_rate_mode = STA_11n;
    858	memcpy(rates->dsss_rates, dsss_rates,
    859		sizeof(*dsss_rates) * WCN36XX_HAL_NUM_DSSS_RATES);
    860	memcpy(rates->ofdm_rates, ofdm_rates,
    861		sizeof(*ofdm_rates) * WCN36XX_HAL_NUM_OFDM_RATES);
    862	rates->supported_mcs_set[0] = 0xFF;
    863}
    864
    865void wcn36xx_set_default_rates_v1(struct wcn36xx_hal_supported_rates_v1 *rates)
    866{
    867	rates->op_rate_mode = STA_11ac;
    868	rates->vht_rx_mcs_map = IEEE80211_VHT_MCS_SUPPORT_0_9;
    869	rates->vht_tx_mcs_map = IEEE80211_VHT_MCS_SUPPORT_0_9;
    870}
    871
    872static void wcn36xx_bss_info_changed(struct ieee80211_hw *hw,
    873				     struct ieee80211_vif *vif,
    874				     struct ieee80211_bss_conf *bss_conf,
    875				     u32 changed)
    876{
    877	struct wcn36xx *wcn = hw->priv;
    878	struct sk_buff *skb = NULL;
    879	u16 tim_off, tim_len;
    880	enum wcn36xx_hal_link_state link_state;
    881	struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
    882
    883	wcn36xx_dbg(WCN36XX_DBG_MAC, "mac bss info changed vif %p changed 0x%08x\n",
    884		    vif, changed);
    885
    886	mutex_lock(&wcn->conf_mutex);
    887
    888	if (changed & BSS_CHANGED_BEACON_INFO) {
    889		wcn36xx_dbg(WCN36XX_DBG_MAC,
    890			    "mac bss changed dtim period %d\n",
    891			    bss_conf->dtim_period);
    892
    893		vif_priv->dtim_period = bss_conf->dtim_period;
    894	}
    895
    896	if (changed & BSS_CHANGED_BSSID) {
    897		wcn36xx_dbg(WCN36XX_DBG_MAC, "mac bss changed_bssid %pM\n",
    898			    bss_conf->bssid);
    899
    900		if (!is_zero_ether_addr(bss_conf->bssid)) {
    901			vif_priv->is_joining = true;
    902			vif_priv->bss_index = WCN36XX_HAL_BSS_INVALID_IDX;
    903			wcn36xx_smd_set_link_st(wcn, bss_conf->bssid, vif->addr,
    904						WCN36XX_HAL_LINK_PREASSOC_STATE);
    905			wcn36xx_smd_join(wcn, bss_conf->bssid,
    906					 vif->addr, WCN36XX_HW_CHANNEL(wcn));
    907			wcn36xx_smd_config_bss(wcn, vif, NULL,
    908					       bss_conf->bssid, false);
    909		} else {
    910			vif_priv->is_joining = false;
    911			wcn36xx_smd_delete_bss(wcn, vif);
    912			wcn36xx_smd_set_link_st(wcn, bss_conf->bssid, vif->addr,
    913						WCN36XX_HAL_LINK_IDLE_STATE);
    914			vif_priv->encrypt_type = WCN36XX_HAL_ED_NONE;
    915		}
    916	}
    917
    918	if (changed & BSS_CHANGED_SSID) {
    919		wcn36xx_dbg(WCN36XX_DBG_MAC,
    920			    "mac bss changed ssid\n");
    921		wcn36xx_dbg_dump(WCN36XX_DBG_MAC, "ssid ",
    922				 bss_conf->ssid, bss_conf->ssid_len);
    923
    924		vif_priv->ssid.length = bss_conf->ssid_len;
    925		memcpy(&vif_priv->ssid.ssid,
    926		       bss_conf->ssid,
    927		       bss_conf->ssid_len);
    928	}
    929
    930	if (changed & BSS_CHANGED_ASSOC) {
    931		vif_priv->is_joining = false;
    932		if (bss_conf->assoc) {
    933			struct ieee80211_sta *sta;
    934			struct wcn36xx_sta *sta_priv;
    935
    936			wcn36xx_dbg(WCN36XX_DBG_MAC,
    937				    "mac assoc bss %pM vif %pM AID=%d\n",
    938				     bss_conf->bssid,
    939				     vif->addr,
    940				     bss_conf->aid);
    941
    942			vif_priv->sta_assoc = true;
    943
    944			/*
    945			 * Holding conf_mutex ensures mutal exclusion with
    946			 * wcn36xx_sta_remove() and as such ensures that sta
    947			 * won't be freed while we're operating on it. As such
    948			 * we do not need to hold the rcu_read_lock().
    949			 */
    950			sta = ieee80211_find_sta(vif, bss_conf->bssid);
    951			if (!sta) {
    952				wcn36xx_err("sta %pM is not found\n",
    953					      bss_conf->bssid);
    954				goto out;
    955			}
    956			sta_priv = wcn36xx_sta_to_priv(sta);
    957
    958			wcn36xx_update_allowed_rates(sta, WCN36XX_BAND(wcn));
    959
    960			wcn36xx_smd_set_link_st(wcn, bss_conf->bssid,
    961				vif->addr,
    962				WCN36XX_HAL_LINK_POSTASSOC_STATE);
    963			wcn36xx_smd_config_bss(wcn, vif, sta,
    964					       bss_conf->bssid,
    965					       true);
    966			sta_priv->aid = bss_conf->aid;
    967			/*
    968			 * config_sta must be called from  because this is the
    969			 * place where AID is available.
    970			 */
    971			wcn36xx_smd_config_sta(wcn, vif, sta);
    972			if (vif->type == NL80211_IFTYPE_STATION)
    973				wcn36xx_smd_add_beacon_filter(wcn, vif);
    974			wcn36xx_enable_keep_alive_null_packet(wcn, vif);
    975		} else {
    976			wcn36xx_dbg(WCN36XX_DBG_MAC,
    977				    "disassociated bss %pM vif %pM AID=%d\n",
    978				    bss_conf->bssid,
    979				    vif->addr,
    980				    bss_conf->aid);
    981			vif_priv->sta_assoc = false;
    982			wcn36xx_smd_set_link_st(wcn,
    983						bss_conf->bssid,
    984						vif->addr,
    985						WCN36XX_HAL_LINK_IDLE_STATE);
    986		}
    987	}
    988
    989	if (changed & BSS_CHANGED_AP_PROBE_RESP) {
    990		wcn36xx_dbg(WCN36XX_DBG_MAC, "mac bss changed ap probe resp\n");
    991		skb = ieee80211_proberesp_get(hw, vif);
    992		if (!skb) {
    993			wcn36xx_err("failed to alloc probereq skb\n");
    994			goto out;
    995		}
    996
    997		wcn36xx_smd_update_proberesp_tmpl(wcn, vif, skb);
    998		dev_kfree_skb(skb);
    999	}
   1000
   1001	if (changed & BSS_CHANGED_BEACON_ENABLED ||
   1002	    changed & BSS_CHANGED_BEACON) {
   1003		wcn36xx_dbg(WCN36XX_DBG_MAC,
   1004			    "mac bss changed beacon enabled %d\n",
   1005			    bss_conf->enable_beacon);
   1006
   1007		if (bss_conf->enable_beacon) {
   1008			vif_priv->dtim_period = bss_conf->dtim_period;
   1009			vif_priv->bss_index = WCN36XX_HAL_BSS_INVALID_IDX;
   1010			wcn36xx_smd_config_bss(wcn, vif, NULL,
   1011					       vif->addr, false);
   1012			skb = ieee80211_beacon_get_tim(hw, vif, &tim_off,
   1013						       &tim_len);
   1014			if (!skb) {
   1015				wcn36xx_err("failed to alloc beacon skb\n");
   1016				goto out;
   1017			}
   1018			wcn36xx_smd_send_beacon(wcn, vif, skb, tim_off, 0);
   1019			dev_kfree_skb(skb);
   1020
   1021			if (vif->type == NL80211_IFTYPE_ADHOC ||
   1022			    vif->type == NL80211_IFTYPE_MESH_POINT)
   1023				link_state = WCN36XX_HAL_LINK_IBSS_STATE;
   1024			else
   1025				link_state = WCN36XX_HAL_LINK_AP_STATE;
   1026
   1027			wcn36xx_smd_set_link_st(wcn, vif->addr, vif->addr,
   1028						link_state);
   1029		} else {
   1030			wcn36xx_smd_delete_bss(wcn, vif);
   1031			wcn36xx_smd_set_link_st(wcn, vif->addr, vif->addr,
   1032						WCN36XX_HAL_LINK_IDLE_STATE);
   1033		}
   1034	}
   1035out:
   1036
   1037	mutex_unlock(&wcn->conf_mutex);
   1038}
   1039
   1040/* this is required when using IEEE80211_HW_HAS_RATE_CONTROL */
   1041static int wcn36xx_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
   1042{
   1043	struct wcn36xx *wcn = hw->priv;
   1044	wcn36xx_dbg(WCN36XX_DBG_MAC, "mac set RTS threshold %d\n", value);
   1045
   1046	mutex_lock(&wcn->conf_mutex);
   1047	wcn36xx_smd_update_cfg(wcn, WCN36XX_HAL_CFG_RTS_THRESHOLD, value);
   1048	mutex_unlock(&wcn->conf_mutex);
   1049
   1050	return 0;
   1051}
   1052
   1053static void wcn36xx_remove_interface(struct ieee80211_hw *hw,
   1054				     struct ieee80211_vif *vif)
   1055{
   1056	struct wcn36xx *wcn = hw->priv;
   1057	struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
   1058	wcn36xx_dbg(WCN36XX_DBG_MAC, "mac remove interface vif %p\n", vif);
   1059
   1060	mutex_lock(&wcn->conf_mutex);
   1061
   1062	list_del(&vif_priv->list);
   1063	wcn36xx_smd_delete_sta_self(wcn, vif->addr);
   1064
   1065	mutex_unlock(&wcn->conf_mutex);
   1066}
   1067
   1068static int wcn36xx_add_interface(struct ieee80211_hw *hw,
   1069				 struct ieee80211_vif *vif)
   1070{
   1071	struct wcn36xx *wcn = hw->priv;
   1072	struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
   1073
   1074	wcn36xx_dbg(WCN36XX_DBG_MAC, "mac add interface vif %p type %d\n",
   1075		    vif, vif->type);
   1076
   1077	if (!(NL80211_IFTYPE_STATION == vif->type ||
   1078	      NL80211_IFTYPE_AP == vif->type ||
   1079	      NL80211_IFTYPE_ADHOC == vif->type ||
   1080	      NL80211_IFTYPE_MESH_POINT == vif->type)) {
   1081		wcn36xx_warn("Unsupported interface type requested: %d\n",
   1082			     vif->type);
   1083		return -EOPNOTSUPP;
   1084	}
   1085
   1086	mutex_lock(&wcn->conf_mutex);
   1087
   1088	vif_priv->bss_index = WCN36XX_HAL_BSS_INVALID_IDX;
   1089	INIT_LIST_HEAD(&vif_priv->sta_list);
   1090	list_add(&vif_priv->list, &wcn->vif_list);
   1091	wcn36xx_smd_add_sta_self(wcn, vif);
   1092
   1093	mutex_unlock(&wcn->conf_mutex);
   1094
   1095	return 0;
   1096}
   1097
   1098static int wcn36xx_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
   1099			   struct ieee80211_sta *sta)
   1100{
   1101	struct wcn36xx *wcn = hw->priv;
   1102	struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
   1103	struct wcn36xx_sta *sta_priv = wcn36xx_sta_to_priv(sta);
   1104	wcn36xx_dbg(WCN36XX_DBG_MAC, "mac sta add vif %p sta %pM\n",
   1105		    vif, sta->addr);
   1106
   1107	mutex_lock(&wcn->conf_mutex);
   1108
   1109	spin_lock_init(&sta_priv->ampdu_lock);
   1110	sta_priv->vif = vif_priv;
   1111	list_add(&sta_priv->list, &vif_priv->sta_list);
   1112
   1113	/*
   1114	 * For STA mode HW will be configured on BSS_CHANGED_ASSOC because
   1115	 * at this stage AID is not available yet.
   1116	 */
   1117	if (NL80211_IFTYPE_STATION != vif->type) {
   1118		wcn36xx_update_allowed_rates(sta, WCN36XX_BAND(wcn));
   1119		sta_priv->aid = sta->aid;
   1120		wcn36xx_smd_config_sta(wcn, vif, sta);
   1121	}
   1122
   1123	mutex_unlock(&wcn->conf_mutex);
   1124
   1125	return 0;
   1126}
   1127
   1128static int wcn36xx_sta_remove(struct ieee80211_hw *hw,
   1129			      struct ieee80211_vif *vif,
   1130			      struct ieee80211_sta *sta)
   1131{
   1132	struct wcn36xx *wcn = hw->priv;
   1133	struct wcn36xx_sta *sta_priv = wcn36xx_sta_to_priv(sta);
   1134
   1135	wcn36xx_dbg(WCN36XX_DBG_MAC, "mac sta remove vif %p sta %pM index %d\n",
   1136		    vif, sta->addr, sta_priv->sta_index);
   1137
   1138	mutex_lock(&wcn->conf_mutex);
   1139
   1140	list_del(&sta_priv->list);
   1141	wcn36xx_smd_delete_sta(wcn, sta_priv->sta_index);
   1142	sta_priv->vif = NULL;
   1143
   1144	mutex_unlock(&wcn->conf_mutex);
   1145
   1146	return 0;
   1147}
   1148
   1149#ifdef CONFIG_PM
   1150
   1151static struct ieee80211_vif *wcn36xx_get_first_assoc_vif(struct wcn36xx *wcn)
   1152{
   1153	struct wcn36xx_vif *vif_priv = NULL;
   1154	struct ieee80211_vif *vif = NULL;
   1155
   1156	list_for_each_entry(vif_priv, &wcn->vif_list, list) {
   1157		if (vif_priv->sta_assoc) {
   1158			vif = wcn36xx_priv_to_vif(vif_priv);
   1159			break;
   1160		}
   1161	}
   1162	return vif;
   1163}
   1164
   1165static int wcn36xx_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wow)
   1166{
   1167	struct wcn36xx *wcn = hw->priv;
   1168	struct ieee80211_vif *vif = NULL;
   1169	int ret = 0;
   1170
   1171	wcn36xx_dbg(WCN36XX_DBG_MAC, "mac suspend\n");
   1172
   1173	mutex_lock(&wcn->conf_mutex);
   1174
   1175	vif = wcn36xx_get_first_assoc_vif(wcn);
   1176	if (vif) {
   1177		ret = wcn36xx_smd_arp_offload(wcn, vif, true);
   1178		if (ret)
   1179			goto out;
   1180		ret = wcn36xx_smd_ipv6_ns_offload(wcn, vif, true);
   1181		if (ret)
   1182			goto out;
   1183		ret = wcn36xx_smd_gtk_offload(wcn, vif, true);
   1184		if (ret)
   1185			goto out;
   1186		ret = wcn36xx_smd_set_power_params(wcn, true);
   1187		if (ret)
   1188			goto out;
   1189		ret = wcn36xx_smd_wlan_host_suspend_ind(wcn);
   1190	}
   1191
   1192	/* Disable IRQ, we don't want to handle any packet before mac80211 is
   1193	 * resumed and ready to receive packets.
   1194	 */
   1195	disable_irq(wcn->tx_irq);
   1196	disable_irq(wcn->rx_irq);
   1197
   1198out:
   1199	mutex_unlock(&wcn->conf_mutex);
   1200	return ret;
   1201}
   1202
   1203static int wcn36xx_resume(struct ieee80211_hw *hw)
   1204{
   1205	struct wcn36xx *wcn = hw->priv;
   1206	struct ieee80211_vif *vif = NULL;
   1207
   1208	wcn36xx_dbg(WCN36XX_DBG_MAC, "mac resume\n");
   1209
   1210	mutex_lock(&wcn->conf_mutex);
   1211	vif = wcn36xx_get_first_assoc_vif(wcn);
   1212	if (vif) {
   1213		wcn36xx_smd_host_resume(wcn);
   1214		wcn36xx_smd_set_power_params(wcn, false);
   1215		wcn36xx_smd_gtk_offload_get_info(wcn, vif);
   1216		wcn36xx_smd_gtk_offload(wcn, vif, false);
   1217		wcn36xx_smd_ipv6_ns_offload(wcn, vif, false);
   1218		wcn36xx_smd_arp_offload(wcn, vif, false);
   1219	}
   1220
   1221	enable_irq(wcn->tx_irq);
   1222	enable_irq(wcn->rx_irq);
   1223
   1224	mutex_unlock(&wcn->conf_mutex);
   1225
   1226	return 0;
   1227}
   1228
   1229static void wcn36xx_set_rekey_data(struct ieee80211_hw *hw,
   1230				   struct ieee80211_vif *vif,
   1231				   struct cfg80211_gtk_rekey_data *data)
   1232{
   1233	struct wcn36xx *wcn = hw->priv;
   1234	struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
   1235
   1236	mutex_lock(&wcn->conf_mutex);
   1237
   1238	memcpy(vif_priv->rekey_data.kek, data->kek, NL80211_KEK_LEN);
   1239	memcpy(vif_priv->rekey_data.kck, data->kck, NL80211_KCK_LEN);
   1240	vif_priv->rekey_data.replay_ctr =
   1241		cpu_to_le64(be64_to_cpup((__be64 *)data->replay_ctr));
   1242	vif_priv->rekey_data.valid = true;
   1243
   1244	mutex_unlock(&wcn->conf_mutex);
   1245}
   1246
   1247#endif
   1248
   1249static int wcn36xx_ampdu_action(struct ieee80211_hw *hw,
   1250		    struct ieee80211_vif *vif,
   1251		    struct ieee80211_ampdu_params *params)
   1252{
   1253	struct wcn36xx *wcn = hw->priv;
   1254	struct wcn36xx_sta *sta_priv = wcn36xx_sta_to_priv(params->sta);
   1255	struct ieee80211_sta *sta = params->sta;
   1256	enum ieee80211_ampdu_mlme_action action = params->action;
   1257	u16 tid = params->tid;
   1258	u16 *ssn = &params->ssn;
   1259	int ret = 0;
   1260	int session;
   1261
   1262	wcn36xx_dbg(WCN36XX_DBG_MAC, "mac ampdu action action %d tid %d\n",
   1263		    action, tid);
   1264
   1265	mutex_lock(&wcn->conf_mutex);
   1266
   1267	switch (action) {
   1268	case IEEE80211_AMPDU_RX_START:
   1269		sta_priv->tid = tid;
   1270		session = wcn36xx_smd_add_ba_session(wcn, sta, tid, ssn, 0,
   1271						     get_sta_index(vif, sta_priv));
   1272		if (session < 0) {
   1273			ret = session;
   1274			goto out;
   1275		}
   1276		wcn36xx_smd_add_ba(wcn, session);
   1277		break;
   1278	case IEEE80211_AMPDU_RX_STOP:
   1279		wcn36xx_smd_del_ba(wcn, tid, 0, get_sta_index(vif, sta_priv));
   1280		break;
   1281	case IEEE80211_AMPDU_TX_START:
   1282		spin_lock_bh(&sta_priv->ampdu_lock);
   1283		sta_priv->ampdu_state[tid] = WCN36XX_AMPDU_START;
   1284		spin_unlock_bh(&sta_priv->ampdu_lock);
   1285
   1286		/* Replace the mac80211 ssn with the firmware one */
   1287		wcn36xx_dbg(WCN36XX_DBG_MAC, "mac ampdu ssn = %u\n", *ssn);
   1288		wcn36xx_smd_trigger_ba(wcn, get_sta_index(vif, sta_priv), tid, ssn);
   1289		wcn36xx_dbg(WCN36XX_DBG_MAC, "mac ampdu fw-ssn = %u\n", *ssn);
   1290
   1291		/* Start BA session */
   1292		session = wcn36xx_smd_add_ba_session(wcn, sta, tid, ssn, 1,
   1293						     get_sta_index(vif, sta_priv));
   1294		if (session < 0) {
   1295			ret = session;
   1296			goto out;
   1297		}
   1298		ret = IEEE80211_AMPDU_TX_START_IMMEDIATE;
   1299		break;
   1300	case IEEE80211_AMPDU_TX_OPERATIONAL:
   1301		spin_lock_bh(&sta_priv->ampdu_lock);
   1302		sta_priv->ampdu_state[tid] = WCN36XX_AMPDU_OPERATIONAL;
   1303		spin_unlock_bh(&sta_priv->ampdu_lock);
   1304
   1305		break;
   1306	case IEEE80211_AMPDU_TX_STOP_FLUSH:
   1307	case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
   1308	case IEEE80211_AMPDU_TX_STOP_CONT:
   1309		spin_lock_bh(&sta_priv->ampdu_lock);
   1310		sta_priv->ampdu_state[tid] = WCN36XX_AMPDU_NONE;
   1311		spin_unlock_bh(&sta_priv->ampdu_lock);
   1312
   1313		wcn36xx_smd_del_ba(wcn, tid, 1, get_sta_index(vif, sta_priv));
   1314		ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
   1315		break;
   1316	default:
   1317		wcn36xx_err("Unknown AMPDU action\n");
   1318	}
   1319
   1320out:
   1321	mutex_unlock(&wcn->conf_mutex);
   1322
   1323	return ret;
   1324}
   1325
   1326#if IS_ENABLED(CONFIG_IPV6)
   1327static void wcn36xx_ipv6_addr_change(struct ieee80211_hw *hw,
   1328				     struct ieee80211_vif *vif,
   1329				     struct inet6_dev *idev)
   1330{
   1331	struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
   1332	struct inet6_ifaddr *ifa;
   1333	int idx = 0;
   1334
   1335	memset(vif_priv->tentative_addrs, 0, sizeof(vif_priv->tentative_addrs));
   1336
   1337	read_lock_bh(&idev->lock);
   1338	list_for_each_entry(ifa, &idev->addr_list, if_list) {
   1339		vif_priv->target_ipv6_addrs[idx] = ifa->addr;
   1340		if (ifa->flags & IFA_F_TENTATIVE)
   1341			__set_bit(idx, vif_priv->tentative_addrs);
   1342		idx++;
   1343		if (idx >= WCN36XX_HAL_IPV6_OFFLOAD_ADDR_MAX)
   1344			break;
   1345		wcn36xx_dbg(WCN36XX_DBG_MAC, "%pI6 %s\n", &ifa->addr,
   1346			    (ifa->flags & IFA_F_TENTATIVE) ? "tentative" : NULL);
   1347	}
   1348	read_unlock_bh(&idev->lock);
   1349
   1350	vif_priv->num_target_ipv6_addrs = idx;
   1351}
   1352#endif
   1353
   1354static void wcn36xx_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
   1355			  u32 queues, bool drop)
   1356{
   1357	struct wcn36xx *wcn = hw->priv;
   1358
   1359	if (wcn36xx_dxe_tx_flush(wcn)) {
   1360		wcn36xx_err("Failed to flush hardware tx queues\n");
   1361	}
   1362}
   1363
   1364static int wcn36xx_get_survey(struct ieee80211_hw *hw, int idx,
   1365			      struct survey_info *survey)
   1366{
   1367	struct wcn36xx *wcn = hw->priv;
   1368	struct ieee80211_supported_band *sband;
   1369	struct wcn36xx_chan_survey *chan_survey;
   1370	int band_idx;
   1371	unsigned long flags;
   1372
   1373	sband = wcn->hw->wiphy->bands[NL80211_BAND_2GHZ];
   1374	band_idx = idx;
   1375	if (band_idx >= sband->n_channels) {
   1376		band_idx -= sband->n_channels;
   1377		sband = wcn->hw->wiphy->bands[NL80211_BAND_5GHZ];
   1378	}
   1379
   1380	if (!sband || band_idx >= sband->n_channels)
   1381		return -ENOENT;
   1382
   1383	spin_lock_irqsave(&wcn->survey_lock, flags);
   1384
   1385	chan_survey = &wcn->chan_survey[idx];
   1386	survey->channel = &sband->channels[band_idx];
   1387	survey->noise = chan_survey->rssi - chan_survey->snr;
   1388	survey->filled = 0;
   1389
   1390	if (chan_survey->rssi > -100 && chan_survey->rssi < 0)
   1391		survey->filled |= SURVEY_INFO_NOISE_DBM;
   1392
   1393	if (survey->channel == wcn->channel)
   1394		survey->filled |= SURVEY_INFO_IN_USE;
   1395
   1396	spin_unlock_irqrestore(&wcn->survey_lock, flags);
   1397
   1398	wcn36xx_dbg(WCN36XX_DBG_MAC,
   1399		    "ch %d rssi %d snr %d noise %d filled %x freq %d\n",
   1400		    HW_VALUE_CHANNEL(survey->channel->hw_value),
   1401		    chan_survey->rssi, chan_survey->snr, survey->noise,
   1402		    survey->filled, survey->channel->center_freq);
   1403
   1404	return 0;
   1405}
   1406
   1407static void wcn36xx_sta_statistics(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
   1408				   struct ieee80211_sta *sta, struct station_info *sinfo)
   1409{
   1410	struct wcn36xx *wcn;
   1411	u8 sta_index;
   1412	int status;
   1413
   1414	wcn = hw->priv;
   1415	sta_index = get_sta_index(vif, wcn36xx_sta_to_priv(sta));
   1416	status = wcn36xx_smd_get_stats(wcn, sta_index, HAL_GLOBAL_CLASS_A_STATS_INFO, sinfo);
   1417
   1418	if (status)
   1419		wcn36xx_err("wcn36xx_smd_get_stats failed\n");
   1420}
   1421
   1422static const struct ieee80211_ops wcn36xx_ops = {
   1423	.start			= wcn36xx_start,
   1424	.stop			= wcn36xx_stop,
   1425	.add_interface		= wcn36xx_add_interface,
   1426	.remove_interface	= wcn36xx_remove_interface,
   1427#ifdef CONFIG_PM
   1428	.suspend		= wcn36xx_suspend,
   1429	.resume			= wcn36xx_resume,
   1430	.set_rekey_data		= wcn36xx_set_rekey_data,
   1431#endif
   1432	.config			= wcn36xx_config,
   1433	.prepare_multicast	= wcn36xx_prepare_multicast,
   1434	.configure_filter       = wcn36xx_configure_filter,
   1435	.tx			= wcn36xx_tx,
   1436	.set_key		= wcn36xx_set_key,
   1437	.hw_scan		= wcn36xx_hw_scan,
   1438	.cancel_hw_scan		= wcn36xx_cancel_hw_scan,
   1439	.sw_scan_start		= wcn36xx_sw_scan_start,
   1440	.sw_scan_complete	= wcn36xx_sw_scan_complete,
   1441	.bss_info_changed	= wcn36xx_bss_info_changed,
   1442	.set_rts_threshold	= wcn36xx_set_rts_threshold,
   1443	.sta_add		= wcn36xx_sta_add,
   1444	.sta_remove		= wcn36xx_sta_remove,
   1445	.sta_statistics		= wcn36xx_sta_statistics,
   1446	.ampdu_action		= wcn36xx_ampdu_action,
   1447#if IS_ENABLED(CONFIG_IPV6)
   1448	.ipv6_addr_change	= wcn36xx_ipv6_addr_change,
   1449#endif
   1450	.flush			= wcn36xx_flush,
   1451	.get_survey		= wcn36xx_get_survey,
   1452
   1453	CFG80211_TESTMODE_CMD(wcn36xx_tm_cmd)
   1454};
   1455
   1456static void
   1457wcn36xx_set_ieee80211_vht_caps(struct ieee80211_sta_vht_cap *vht_cap)
   1458{
   1459	vht_cap->vht_supported = true;
   1460
   1461	vht_cap->cap = (IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895 |
   1462			IEEE80211_VHT_CAP_SHORT_GI_80 |
   1463			IEEE80211_VHT_CAP_RXSTBC_1 |
   1464			IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE |
   1465			IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE |
   1466			3 << IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT |
   1467			7 << IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT);
   1468
   1469	vht_cap->vht_mcs.rx_mcs_map =
   1470		cpu_to_le16(IEEE80211_VHT_MCS_SUPPORT_0_9 |
   1471			    IEEE80211_VHT_MCS_NOT_SUPPORTED << 2 |
   1472			    IEEE80211_VHT_MCS_NOT_SUPPORTED << 4 |
   1473			    IEEE80211_VHT_MCS_NOT_SUPPORTED << 6 |
   1474			    IEEE80211_VHT_MCS_NOT_SUPPORTED << 8 |
   1475			    IEEE80211_VHT_MCS_NOT_SUPPORTED << 10 |
   1476			    IEEE80211_VHT_MCS_NOT_SUPPORTED << 12 |
   1477			    IEEE80211_VHT_MCS_NOT_SUPPORTED << 14);
   1478
   1479	vht_cap->vht_mcs.rx_highest = cpu_to_le16(433);
   1480	vht_cap->vht_mcs.tx_highest = vht_cap->vht_mcs.rx_highest;
   1481
   1482	vht_cap->vht_mcs.tx_mcs_map = vht_cap->vht_mcs.rx_mcs_map;
   1483}
   1484
   1485static int wcn36xx_init_ieee80211(struct wcn36xx *wcn)
   1486{
   1487	static const u32 cipher_suites[] = {
   1488		WLAN_CIPHER_SUITE_WEP40,
   1489		WLAN_CIPHER_SUITE_WEP104,
   1490		WLAN_CIPHER_SUITE_TKIP,
   1491		WLAN_CIPHER_SUITE_CCMP,
   1492	};
   1493
   1494	ieee80211_hw_set(wcn->hw, TIMING_BEACON_ONLY);
   1495	ieee80211_hw_set(wcn->hw, AMPDU_AGGREGATION);
   1496	ieee80211_hw_set(wcn->hw, SUPPORTS_PS);
   1497	ieee80211_hw_set(wcn->hw, SIGNAL_DBM);
   1498	ieee80211_hw_set(wcn->hw, HAS_RATE_CONTROL);
   1499	ieee80211_hw_set(wcn->hw, SINGLE_SCAN_ON_ALL_BANDS);
   1500	ieee80211_hw_set(wcn->hw, REPORTS_TX_ACK_STATUS);
   1501
   1502	wcn->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
   1503		BIT(NL80211_IFTYPE_AP) |
   1504		BIT(NL80211_IFTYPE_ADHOC) |
   1505		BIT(NL80211_IFTYPE_MESH_POINT);
   1506
   1507	wcn->hw->wiphy->bands[NL80211_BAND_2GHZ] = &wcn_band_2ghz;
   1508	if (wcn->rf_id != RF_IRIS_WCN3620)
   1509		wcn->hw->wiphy->bands[NL80211_BAND_5GHZ] = &wcn_band_5ghz;
   1510
   1511	if (wcn->rf_id == RF_IRIS_WCN3680)
   1512		wcn36xx_set_ieee80211_vht_caps(&wcn_band_5ghz.vht_cap);
   1513
   1514	wcn->hw->wiphy->max_scan_ssids = WCN36XX_MAX_SCAN_SSIDS;
   1515	wcn->hw->wiphy->max_scan_ie_len = WCN36XX_MAX_SCAN_IE_LEN;
   1516
   1517	wcn->hw->wiphy->cipher_suites = cipher_suites;
   1518	wcn->hw->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
   1519
   1520#ifdef CONFIG_PM
   1521	wcn->hw->wiphy->wowlan = &wowlan_support;
   1522#endif
   1523
   1524	wcn->hw->max_listen_interval = 200;
   1525
   1526	wcn->hw->queues = 4;
   1527
   1528	SET_IEEE80211_DEV(wcn->hw, wcn->dev);
   1529
   1530	wcn->hw->sta_data_size = sizeof(struct wcn36xx_sta);
   1531	wcn->hw->vif_data_size = sizeof(struct wcn36xx_vif);
   1532
   1533	wiphy_ext_feature_set(wcn->hw->wiphy,
   1534			      NL80211_EXT_FEATURE_CQM_RSSI_LIST);
   1535
   1536	return 0;
   1537}
   1538
   1539static int wcn36xx_platform_get_resources(struct wcn36xx *wcn,
   1540					  struct platform_device *pdev)
   1541{
   1542	struct device_node *mmio_node;
   1543	struct device_node *iris_node;
   1544	int index;
   1545	int ret;
   1546
   1547	/* Set TX IRQ */
   1548	ret = platform_get_irq_byname(pdev, "tx");
   1549	if (ret < 0)
   1550		return ret;
   1551	wcn->tx_irq = ret;
   1552
   1553	/* Set RX IRQ */
   1554	ret = platform_get_irq_byname(pdev, "rx");
   1555	if (ret < 0)
   1556		return ret;
   1557	wcn->rx_irq = ret;
   1558
   1559	/* Acquire SMSM tx enable handle */
   1560	wcn->tx_enable_state = qcom_smem_state_get(&pdev->dev,
   1561			"tx-enable", &wcn->tx_enable_state_bit);
   1562	if (IS_ERR(wcn->tx_enable_state)) {
   1563		wcn36xx_err("failed to get tx-enable state\n");
   1564		return PTR_ERR(wcn->tx_enable_state);
   1565	}
   1566
   1567	/* Acquire SMSM tx rings empty handle */
   1568	wcn->tx_rings_empty_state = qcom_smem_state_get(&pdev->dev,
   1569			"tx-rings-empty", &wcn->tx_rings_empty_state_bit);
   1570	if (IS_ERR(wcn->tx_rings_empty_state)) {
   1571		wcn36xx_err("failed to get tx-rings-empty state\n");
   1572		return PTR_ERR(wcn->tx_rings_empty_state);
   1573	}
   1574
   1575	mmio_node = of_parse_phandle(pdev->dev.parent->of_node, "qcom,mmio", 0);
   1576	if (!mmio_node) {
   1577		wcn36xx_err("failed to acquire qcom,mmio reference\n");
   1578		return -EINVAL;
   1579	}
   1580
   1581	wcn->is_pronto = !!of_device_is_compatible(mmio_node, "qcom,pronto");
   1582
   1583	/* Map the CCU memory */
   1584	index = of_property_match_string(mmio_node, "reg-names", "ccu");
   1585	wcn->ccu_base = of_iomap(mmio_node, index);
   1586	if (!wcn->ccu_base) {
   1587		wcn36xx_err("failed to map ccu memory\n");
   1588		ret = -ENOMEM;
   1589		goto put_mmio_node;
   1590	}
   1591
   1592	/* Map the DXE memory */
   1593	index = of_property_match_string(mmio_node, "reg-names", "dxe");
   1594	wcn->dxe_base = of_iomap(mmio_node, index);
   1595	if (!wcn->dxe_base) {
   1596		wcn36xx_err("failed to map dxe memory\n");
   1597		ret = -ENOMEM;
   1598		goto unmap_ccu;
   1599	}
   1600
   1601	/* External RF module */
   1602	iris_node = of_get_child_by_name(mmio_node, "iris");
   1603	if (iris_node) {
   1604		if (of_device_is_compatible(iris_node, "qcom,wcn3620"))
   1605			wcn->rf_id = RF_IRIS_WCN3620;
   1606		if (of_device_is_compatible(iris_node, "qcom,wcn3660") ||
   1607		    of_device_is_compatible(iris_node, "qcom,wcn3660b"))
   1608			wcn->rf_id = RF_IRIS_WCN3660;
   1609		if (of_device_is_compatible(iris_node, "qcom,wcn3680"))
   1610			wcn->rf_id = RF_IRIS_WCN3680;
   1611		of_node_put(iris_node);
   1612	}
   1613
   1614	of_node_put(mmio_node);
   1615	return 0;
   1616
   1617unmap_ccu:
   1618	iounmap(wcn->ccu_base);
   1619put_mmio_node:
   1620	of_node_put(mmio_node);
   1621	return ret;
   1622}
   1623
   1624static int wcn36xx_probe(struct platform_device *pdev)
   1625{
   1626	struct ieee80211_hw *hw;
   1627	struct wcn36xx *wcn;
   1628	void *wcnss;
   1629	int ret;
   1630	const u8 *addr;
   1631	int n_channels;
   1632
   1633	wcn36xx_dbg(WCN36XX_DBG_MAC, "platform probe\n");
   1634
   1635	wcnss = dev_get_drvdata(pdev->dev.parent);
   1636
   1637	hw = ieee80211_alloc_hw(sizeof(struct wcn36xx), &wcn36xx_ops);
   1638	if (!hw) {
   1639		wcn36xx_err("failed to alloc hw\n");
   1640		ret = -ENOMEM;
   1641		goto out_err;
   1642	}
   1643	platform_set_drvdata(pdev, hw);
   1644	wcn = hw->priv;
   1645	wcn->hw = hw;
   1646	wcn->dev = &pdev->dev;
   1647	wcn->first_boot = true;
   1648	mutex_init(&wcn->conf_mutex);
   1649	mutex_init(&wcn->hal_mutex);
   1650	mutex_init(&wcn->scan_lock);
   1651	__skb_queue_head_init(&wcn->amsdu);
   1652
   1653	wcn->hal_buf = devm_kmalloc(wcn->dev, WCN36XX_HAL_BUF_SIZE, GFP_KERNEL);
   1654	if (!wcn->hal_buf) {
   1655		ret = -ENOMEM;
   1656		goto out_wq;
   1657	}
   1658
   1659	n_channels = wcn_band_2ghz.n_channels + wcn_band_5ghz.n_channels;
   1660	wcn->chan_survey = devm_kmalloc(wcn->dev, n_channels, GFP_KERNEL);
   1661	if (!wcn->chan_survey) {
   1662		ret = -ENOMEM;
   1663		goto out_wq;
   1664	}
   1665
   1666	ret = dma_set_mask_and_coherent(wcn->dev, DMA_BIT_MASK(32));
   1667	if (ret < 0) {
   1668		wcn36xx_err("failed to set DMA mask: %d\n", ret);
   1669		goto out_wq;
   1670	}
   1671
   1672	wcn->nv_file = WLAN_NV_FILE;
   1673	ret = of_property_read_string(wcn->dev->parent->of_node, "firmware-name", &wcn->nv_file);
   1674	if (ret < 0 && ret != -EINVAL) {
   1675		wcn36xx_err("failed to read \"firmware-name\" property: %d\n", ret);
   1676		goto out_wq;
   1677	}
   1678
   1679	wcn->smd_channel = qcom_wcnss_open_channel(wcnss, "WLAN_CTRL", wcn36xx_smd_rsp_process, hw);
   1680	if (IS_ERR(wcn->smd_channel)) {
   1681		wcn36xx_err("failed to open WLAN_CTRL channel\n");
   1682		ret = PTR_ERR(wcn->smd_channel);
   1683		goto out_wq;
   1684	}
   1685
   1686	addr = of_get_property(pdev->dev.of_node, "local-mac-address", &ret);
   1687	if (addr && ret != ETH_ALEN) {
   1688		wcn36xx_err("invalid local-mac-address\n");
   1689		ret = -EINVAL;
   1690		goto out_destroy_ept;
   1691	} else if (addr) {
   1692		wcn36xx_info("mac address: %pM\n", addr);
   1693		SET_IEEE80211_PERM_ADDR(wcn->hw, addr);
   1694	}
   1695
   1696	ret = wcn36xx_platform_get_resources(wcn, pdev);
   1697	if (ret)
   1698		goto out_destroy_ept;
   1699
   1700	wcn36xx_init_ieee80211(wcn);
   1701	ret = ieee80211_register_hw(wcn->hw);
   1702	if (ret)
   1703		goto out_unmap;
   1704
   1705	return 0;
   1706
   1707out_unmap:
   1708	iounmap(wcn->ccu_base);
   1709	iounmap(wcn->dxe_base);
   1710out_destroy_ept:
   1711	rpmsg_destroy_ept(wcn->smd_channel);
   1712out_wq:
   1713	ieee80211_free_hw(hw);
   1714out_err:
   1715	return ret;
   1716}
   1717
   1718static int wcn36xx_remove(struct platform_device *pdev)
   1719{
   1720	struct ieee80211_hw *hw = platform_get_drvdata(pdev);
   1721	struct wcn36xx *wcn = hw->priv;
   1722	wcn36xx_dbg(WCN36XX_DBG_MAC, "platform remove\n");
   1723
   1724	release_firmware(wcn->nv);
   1725
   1726	ieee80211_unregister_hw(hw);
   1727
   1728	qcom_smem_state_put(wcn->tx_enable_state);
   1729	qcom_smem_state_put(wcn->tx_rings_empty_state);
   1730
   1731	rpmsg_destroy_ept(wcn->smd_channel);
   1732
   1733	iounmap(wcn->dxe_base);
   1734	iounmap(wcn->ccu_base);
   1735
   1736	__skb_queue_purge(&wcn->amsdu);
   1737
   1738	mutex_destroy(&wcn->hal_mutex);
   1739	ieee80211_free_hw(hw);
   1740
   1741	return 0;
   1742}
   1743
   1744static const struct of_device_id wcn36xx_of_match[] = {
   1745	{ .compatible = "qcom,wcnss-wlan" },
   1746	{}
   1747};
   1748MODULE_DEVICE_TABLE(of, wcn36xx_of_match);
   1749
   1750static struct platform_driver wcn36xx_driver = {
   1751	.probe      = wcn36xx_probe,
   1752	.remove     = wcn36xx_remove,
   1753	.driver         = {
   1754		.name   = "wcn36xx",
   1755		.of_match_table = wcn36xx_of_match,
   1756	},
   1757};
   1758
   1759module_platform_driver(wcn36xx_driver);
   1760
   1761MODULE_LICENSE("Dual BSD/GPL");
   1762MODULE_AUTHOR("Eugene Krasnikov k.eugene.e@gmail.com");
   1763MODULE_FIRMWARE(WLAN_NV_FILE);