Path: blob/main/sys/contrib/dev/athk/ath12k/mac.c
105380 views
// SPDX-License-Identifier: BSD-3-Clause-Clear1/*2* Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.3* Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.4*/56#include <net/mac80211.h>7#include <linux/etherdevice.h>8#include "mac.h"9#include "core.h"10#include "debug.h"11#include "wmi.h"12#include "hw.h"13#include "dp_tx.h"14#include "dp_rx.h"15#include "peer.h"1617#define CHAN2G(_channel, _freq, _flags) { \18.band = NL80211_BAND_2GHZ, \19.hw_value = (_channel), \20.center_freq = (_freq), \21.flags = (_flags), \22.max_antenna_gain = 0, \23.max_power = 30, \24}2526#define CHAN5G(_channel, _freq, _flags) { \27.band = NL80211_BAND_5GHZ, \28.hw_value = (_channel), \29.center_freq = (_freq), \30.flags = (_flags), \31.max_antenna_gain = 0, \32.max_power = 30, \33}3435#define CHAN6G(_channel, _freq, _flags) { \36.band = NL80211_BAND_6GHZ, \37.hw_value = (_channel), \38.center_freq = (_freq), \39.flags = (_flags), \40.max_antenna_gain = 0, \41.max_power = 30, \42}4344static const struct ieee80211_channel ath12k_2ghz_channels[] = {45CHAN2G(1, 2412, 0),46CHAN2G(2, 2417, 0),47CHAN2G(3, 2422, 0),48CHAN2G(4, 2427, 0),49CHAN2G(5, 2432, 0),50CHAN2G(6, 2437, 0),51CHAN2G(7, 2442, 0),52CHAN2G(8, 2447, 0),53CHAN2G(9, 2452, 0),54CHAN2G(10, 2457, 0),55CHAN2G(11, 2462, 0),56CHAN2G(12, 2467, 0),57CHAN2G(13, 2472, 0),58CHAN2G(14, 2484, 0),59};6061static const struct ieee80211_channel ath12k_5ghz_channels[] = {62CHAN5G(36, 5180, 0),63CHAN5G(40, 5200, 0),64CHAN5G(44, 5220, 0),65CHAN5G(48, 5240, 0),66CHAN5G(52, 5260, 0),67CHAN5G(56, 5280, 0),68CHAN5G(60, 5300, 0),69CHAN5G(64, 5320, 0),70CHAN5G(100, 5500, 0),71CHAN5G(104, 5520, 0),72CHAN5G(108, 5540, 0),73CHAN5G(112, 5560, 0),74CHAN5G(116, 5580, 0),75CHAN5G(120, 5600, 0),76CHAN5G(124, 5620, 0),77CHAN5G(128, 5640, 0),78CHAN5G(132, 5660, 0),79CHAN5G(136, 5680, 0),80CHAN5G(140, 5700, 0),81CHAN5G(144, 5720, 0),82CHAN5G(149, 5745, 0),83CHAN5G(153, 5765, 0),84CHAN5G(157, 5785, 0),85CHAN5G(161, 5805, 0),86CHAN5G(165, 5825, 0),87CHAN5G(169, 5845, 0),88CHAN5G(173, 5865, 0),89};9091static const struct ieee80211_channel ath12k_6ghz_channels[] = {92CHAN6G(1, 5955, 0),93CHAN6G(5, 5975, 0),94CHAN6G(9, 5995, 0),95CHAN6G(13, 6015, 0),96CHAN6G(17, 6035, 0),97CHAN6G(21, 6055, 0),98CHAN6G(25, 6075, 0),99CHAN6G(29, 6095, 0),100CHAN6G(33, 6115, 0),101CHAN6G(37, 6135, 0),102CHAN6G(41, 6155, 0),103CHAN6G(45, 6175, 0),104CHAN6G(49, 6195, 0),105CHAN6G(53, 6215, 0),106CHAN6G(57, 6235, 0),107CHAN6G(61, 6255, 0),108CHAN6G(65, 6275, 0),109CHAN6G(69, 6295, 0),110CHAN6G(73, 6315, 0),111CHAN6G(77, 6335, 0),112CHAN6G(81, 6355, 0),113CHAN6G(85, 6375, 0),114CHAN6G(89, 6395, 0),115CHAN6G(93, 6415, 0),116CHAN6G(97, 6435, 0),117CHAN6G(101, 6455, 0),118CHAN6G(105, 6475, 0),119CHAN6G(109, 6495, 0),120CHAN6G(113, 6515, 0),121CHAN6G(117, 6535, 0),122CHAN6G(121, 6555, 0),123CHAN6G(125, 6575, 0),124CHAN6G(129, 6595, 0),125CHAN6G(133, 6615, 0),126CHAN6G(137, 6635, 0),127CHAN6G(141, 6655, 0),128CHAN6G(145, 6675, 0),129CHAN6G(149, 6695, 0),130CHAN6G(153, 6715, 0),131CHAN6G(157, 6735, 0),132CHAN6G(161, 6755, 0),133CHAN6G(165, 6775, 0),134CHAN6G(169, 6795, 0),135CHAN6G(173, 6815, 0),136CHAN6G(177, 6835, 0),137CHAN6G(181, 6855, 0),138CHAN6G(185, 6875, 0),139CHAN6G(189, 6895, 0),140CHAN6G(193, 6915, 0),141CHAN6G(197, 6935, 0),142CHAN6G(201, 6955, 0),143CHAN6G(205, 6975, 0),144CHAN6G(209, 6995, 0),145CHAN6G(213, 7015, 0),146CHAN6G(217, 7035, 0),147CHAN6G(221, 7055, 0),148CHAN6G(225, 7075, 0),149CHAN6G(229, 7095, 0),150CHAN6G(233, 7115, 0),151};152153static struct ieee80211_rate ath12k_legacy_rates[] = {154{ .bitrate = 10,155.hw_value = ATH12K_HW_RATE_CCK_LP_1M },156{ .bitrate = 20,157.hw_value = ATH12K_HW_RATE_CCK_LP_2M,158.hw_value_short = ATH12K_HW_RATE_CCK_SP_2M,159.flags = IEEE80211_RATE_SHORT_PREAMBLE },160{ .bitrate = 55,161.hw_value = ATH12K_HW_RATE_CCK_LP_5_5M,162.hw_value_short = ATH12K_HW_RATE_CCK_SP_5_5M,163.flags = IEEE80211_RATE_SHORT_PREAMBLE },164{ .bitrate = 110,165.hw_value = ATH12K_HW_RATE_CCK_LP_11M,166.hw_value_short = ATH12K_HW_RATE_CCK_SP_11M,167.flags = IEEE80211_RATE_SHORT_PREAMBLE },168169{ .bitrate = 60, .hw_value = ATH12K_HW_RATE_OFDM_6M },170{ .bitrate = 90, .hw_value = ATH12K_HW_RATE_OFDM_9M },171{ .bitrate = 120, .hw_value = ATH12K_HW_RATE_OFDM_12M },172{ .bitrate = 180, .hw_value = ATH12K_HW_RATE_OFDM_18M },173{ .bitrate = 240, .hw_value = ATH12K_HW_RATE_OFDM_24M },174{ .bitrate = 360, .hw_value = ATH12K_HW_RATE_OFDM_36M },175{ .bitrate = 480, .hw_value = ATH12K_HW_RATE_OFDM_48M },176{ .bitrate = 540, .hw_value = ATH12K_HW_RATE_OFDM_54M },177};178179static const int180ath12k_phymodes[NUM_NL80211_BANDS][ATH12K_CHAN_WIDTH_NUM] = {181[NL80211_BAND_2GHZ] = {182[NL80211_CHAN_WIDTH_5] = MODE_UNKNOWN,183[NL80211_CHAN_WIDTH_10] = MODE_UNKNOWN,184[NL80211_CHAN_WIDTH_20_NOHT] = MODE_11BE_EHT20_2G,185[NL80211_CHAN_WIDTH_20] = MODE_11BE_EHT20_2G,186[NL80211_CHAN_WIDTH_40] = MODE_11BE_EHT40_2G,187[NL80211_CHAN_WIDTH_80] = MODE_UNKNOWN,188[NL80211_CHAN_WIDTH_80P80] = MODE_UNKNOWN,189[NL80211_CHAN_WIDTH_160] = MODE_UNKNOWN,190[NL80211_CHAN_WIDTH_320] = MODE_UNKNOWN,191},192[NL80211_BAND_5GHZ] = {193[NL80211_CHAN_WIDTH_5] = MODE_UNKNOWN,194[NL80211_CHAN_WIDTH_10] = MODE_UNKNOWN,195[NL80211_CHAN_WIDTH_20_NOHT] = MODE_11BE_EHT20,196[NL80211_CHAN_WIDTH_20] = MODE_11BE_EHT20,197[NL80211_CHAN_WIDTH_40] = MODE_11BE_EHT40,198[NL80211_CHAN_WIDTH_80] = MODE_11BE_EHT80,199[NL80211_CHAN_WIDTH_160] = MODE_11BE_EHT160,200[NL80211_CHAN_WIDTH_80P80] = MODE_11BE_EHT80_80,201[NL80211_CHAN_WIDTH_320] = MODE_11BE_EHT320,202},203[NL80211_BAND_6GHZ] = {204[NL80211_CHAN_WIDTH_5] = MODE_UNKNOWN,205[NL80211_CHAN_WIDTH_10] = MODE_UNKNOWN,206[NL80211_CHAN_WIDTH_20_NOHT] = MODE_11BE_EHT20,207[NL80211_CHAN_WIDTH_20] = MODE_11BE_EHT20,208[NL80211_CHAN_WIDTH_40] = MODE_11BE_EHT40,209[NL80211_CHAN_WIDTH_80] = MODE_11BE_EHT80,210[NL80211_CHAN_WIDTH_160] = MODE_11BE_EHT160,211[NL80211_CHAN_WIDTH_80P80] = MODE_11BE_EHT80_80,212[NL80211_CHAN_WIDTH_320] = MODE_11BE_EHT320,213},214215};216217const struct htt_rx_ring_tlv_filter ath12k_mac_mon_status_filter_default = {218.rx_filter = HTT_RX_FILTER_TLV_FLAGS_MPDU_START |219HTT_RX_FILTER_TLV_FLAGS_PPDU_END |220HTT_RX_FILTER_TLV_FLAGS_PPDU_END_STATUS_DONE,221.pkt_filter_flags0 = HTT_RX_FP_MGMT_FILTER_FLAGS0,222.pkt_filter_flags1 = HTT_RX_FP_MGMT_FILTER_FLAGS1,223.pkt_filter_flags2 = HTT_RX_FP_CTRL_FILTER_FLASG2,224.pkt_filter_flags3 = HTT_RX_FP_DATA_FILTER_FLASG3 |225HTT_RX_FP_CTRL_FILTER_FLASG3226};227228#define ATH12K_MAC_FIRST_OFDM_RATE_IDX 4229#define ath12k_g_rates ath12k_legacy_rates230#define ath12k_g_rates_size (ARRAY_SIZE(ath12k_legacy_rates))231#define ath12k_a_rates (ath12k_legacy_rates + 4)232#define ath12k_a_rates_size (ARRAY_SIZE(ath12k_legacy_rates) - 4)233234#define ATH12K_MAC_SCAN_TIMEOUT_MSECS 200 /* in msecs */235236static const u32 ath12k_smps_map[] = {237[WLAN_HT_CAP_SM_PS_STATIC] = WMI_PEER_SMPS_STATIC,238[WLAN_HT_CAP_SM_PS_DYNAMIC] = WMI_PEER_SMPS_DYNAMIC,239[WLAN_HT_CAP_SM_PS_INVALID] = WMI_PEER_SMPS_PS_NONE,240[WLAN_HT_CAP_SM_PS_DISABLED] = WMI_PEER_SMPS_PS_NONE,241};242243static int ath12k_start_vdev_delay(struct ieee80211_hw *hw,244struct ieee80211_vif *vif);245246static const char *ath12k_mac_phymode_str(enum wmi_phy_mode mode)247{248switch (mode) {249case MODE_11A:250return "11a";251case MODE_11G:252return "11g";253case MODE_11B:254return "11b";255case MODE_11GONLY:256return "11gonly";257case MODE_11NA_HT20:258return "11na-ht20";259case MODE_11NG_HT20:260return "11ng-ht20";261case MODE_11NA_HT40:262return "11na-ht40";263case MODE_11NG_HT40:264return "11ng-ht40";265case MODE_11AC_VHT20:266return "11ac-vht20";267case MODE_11AC_VHT40:268return "11ac-vht40";269case MODE_11AC_VHT80:270return "11ac-vht80";271case MODE_11AC_VHT160:272return "11ac-vht160";273case MODE_11AC_VHT80_80:274return "11ac-vht80+80";275case MODE_11AC_VHT20_2G:276return "11ac-vht20-2g";277case MODE_11AC_VHT40_2G:278return "11ac-vht40-2g";279case MODE_11AC_VHT80_2G:280return "11ac-vht80-2g";281case MODE_11AX_HE20:282return "11ax-he20";283case MODE_11AX_HE40:284return "11ax-he40";285case MODE_11AX_HE80:286return "11ax-he80";287case MODE_11AX_HE80_80:288return "11ax-he80+80";289case MODE_11AX_HE160:290return "11ax-he160";291case MODE_11AX_HE20_2G:292return "11ax-he20-2g";293case MODE_11AX_HE40_2G:294return "11ax-he40-2g";295case MODE_11AX_HE80_2G:296return "11ax-he80-2g";297case MODE_11BE_EHT20:298return "11be-eht20";299case MODE_11BE_EHT40:300return "11be-eht40";301case MODE_11BE_EHT80:302return "11be-eht80";303case MODE_11BE_EHT80_80:304return "11be-eht80+80";305case MODE_11BE_EHT160:306return "11be-eht160";307case MODE_11BE_EHT160_160:308return "11be-eht160+160";309case MODE_11BE_EHT320:310return "11be-eht320";311case MODE_11BE_EHT20_2G:312return "11be-eht20-2g";313case MODE_11BE_EHT40_2G:314return "11be-eht40-2g";315case MODE_UNKNOWN:316/* skip */317break;318319/* no default handler to allow compiler to check that the320* enum is fully handled321*/322}323324return "<unknown>";325}326327enum rate_info_bw328ath12k_mac_bw_to_mac80211_bw(enum ath12k_supported_bw bw)329{330u8 ret = RATE_INFO_BW_20;331332switch (bw) {333case ATH12K_BW_20:334ret = RATE_INFO_BW_20;335break;336case ATH12K_BW_40:337ret = RATE_INFO_BW_40;338break;339case ATH12K_BW_80:340ret = RATE_INFO_BW_80;341break;342case ATH12K_BW_160:343ret = RATE_INFO_BW_160;344break;345}346347return ret;348}349350enum ath12k_supported_bw ath12k_mac_mac80211_bw_to_ath12k_bw(enum rate_info_bw bw)351{352switch (bw) {353case RATE_INFO_BW_20:354return ATH12K_BW_20;355case RATE_INFO_BW_40:356return ATH12K_BW_40;357case RATE_INFO_BW_80:358return ATH12K_BW_80;359case RATE_INFO_BW_160:360return ATH12K_BW_160;361default:362return ATH12K_BW_20;363}364}365366int ath12k_mac_hw_ratecode_to_legacy_rate(u8 hw_rc, u8 preamble, u8 *rateidx,367u16 *rate)368{369/* As default, it is OFDM rates */370int i = ATH12K_MAC_FIRST_OFDM_RATE_IDX;371int max_rates_idx = ath12k_g_rates_size;372373if (preamble == WMI_RATE_PREAMBLE_CCK) {374hw_rc &= ~ATH12K_HW_RATECODE_CCK_SHORT_PREAM_MASK;375i = 0;376max_rates_idx = ATH12K_MAC_FIRST_OFDM_RATE_IDX;377}378379while (i < max_rates_idx) {380if (hw_rc == ath12k_legacy_rates[i].hw_value) {381*rateidx = i;382*rate = ath12k_legacy_rates[i].bitrate;383return 0;384}385i++;386}387388return -EINVAL;389}390391u8 ath12k_mac_bitrate_to_idx(const struct ieee80211_supported_band *sband,392u32 bitrate)393{394int i;395396for (i = 0; i < sband->n_bitrates; i++)397if (sband->bitrates[i].bitrate == bitrate)398return i;399400return 0;401}402403static u32404ath12k_mac_max_ht_nss(const u8 *ht_mcs_mask)405{406int nss;407408for (nss = IEEE80211_HT_MCS_MASK_LEN - 1; nss >= 0; nss--)409if (ht_mcs_mask[nss])410return nss + 1;411412return 1;413}414415static u32416ath12k_mac_max_vht_nss(const u16 *vht_mcs_mask)417{418int nss;419420for (nss = NL80211_VHT_NSS_MAX - 1; nss >= 0; nss--)421if (vht_mcs_mask[nss])422return nss + 1;423424return 1;425}426427static u8 ath12k_parse_mpdudensity(u8 mpdudensity)428{429/* From IEEE Std 802.11-2020 defined values for "Minimum MPDU Start Spacing":430* 0 for no restriction431* 1 for 1/4 us432* 2 for 1/2 us433* 3 for 1 us434* 4 for 2 us435* 5 for 4 us436* 6 for 8 us437* 7 for 16 us438*/439switch (mpdudensity) {440case 0:441return 0;442case 1:443case 2:444case 3:445/* Our lower layer calculations limit our precision to446* 1 microsecond447*/448return 1;449case 4:450return 2;451case 5:452return 4;453case 6:454return 8;455case 7:456return 16;457default:458return 0;459}460}461462static int ath12k_mac_vif_chan(struct ieee80211_vif *vif,463struct cfg80211_chan_def *def)464{465struct ieee80211_chanctx_conf *conf;466467rcu_read_lock();468conf = rcu_dereference(vif->bss_conf.chanctx_conf);469if (!conf) {470rcu_read_unlock();471return -ENOENT;472}473474*def = conf->def;475rcu_read_unlock();476477return 0;478}479480static bool ath12k_mac_bitrate_is_cck(int bitrate)481{482switch (bitrate) {483case 10:484case 20:485case 55:486case 110:487return true;488}489490return false;491}492493u8 ath12k_mac_hw_rate_to_idx(const struct ieee80211_supported_band *sband,494u8 hw_rate, bool cck)495{496const struct ieee80211_rate *rate;497int i;498499for (i = 0; i < sband->n_bitrates; i++) {500rate = &sband->bitrates[i];501502if (ath12k_mac_bitrate_is_cck(rate->bitrate) != cck)503continue;504505if (rate->hw_value == hw_rate)506return i;507else if (rate->flags & IEEE80211_RATE_SHORT_PREAMBLE &&508rate->hw_value_short == hw_rate)509return i;510}511512return 0;513}514515static u8 ath12k_mac_bitrate_to_rate(int bitrate)516{517return DIV_ROUND_UP(bitrate, 5) |518(ath12k_mac_bitrate_is_cck(bitrate) ? BIT(7) : 0);519}520521static void ath12k_get_arvif_iter(void *data, u8 *mac,522struct ieee80211_vif *vif)523{524struct ath12k_vif_iter *arvif_iter = data;525struct ath12k_vif *arvif = (void *)vif->drv_priv;526527if (arvif->vdev_id == arvif_iter->vdev_id)528arvif_iter->arvif = arvif;529}530531struct ath12k_vif *ath12k_mac_get_arvif(struct ath12k *ar, u32 vdev_id)532{533struct ath12k_vif_iter arvif_iter = {};534u32 flags;535536arvif_iter.vdev_id = vdev_id;537538flags = IEEE80211_IFACE_ITER_RESUME_ALL;539ieee80211_iterate_active_interfaces_atomic(ar->hw,540flags,541ath12k_get_arvif_iter,542&arvif_iter);543if (!arvif_iter.arvif) {544ath12k_warn(ar->ab, "No VIF found for vdev %d\n", vdev_id);545return NULL;546}547548return arvif_iter.arvif;549}550551struct ath12k_vif *ath12k_mac_get_arvif_by_vdev_id(struct ath12k_base *ab,552u32 vdev_id)553{554int i;555struct ath12k_pdev *pdev;556struct ath12k_vif *arvif;557558for (i = 0; i < ab->num_radios; i++) {559pdev = rcu_dereference(ab->pdevs_active[i]);560if (pdev && pdev->ar) {561arvif = ath12k_mac_get_arvif(pdev->ar, vdev_id);562if (arvif)563return arvif;564}565}566567return NULL;568}569570struct ath12k *ath12k_mac_get_ar_by_vdev_id(struct ath12k_base *ab, u32 vdev_id)571{572int i;573struct ath12k_pdev *pdev;574575for (i = 0; i < ab->num_radios; i++) {576pdev = rcu_dereference(ab->pdevs_active[i]);577if (pdev && pdev->ar) {578if (pdev->ar->allocated_vdev_map & (1LL << vdev_id))579return pdev->ar;580}581}582583return NULL;584}585586struct ath12k *ath12k_mac_get_ar_by_pdev_id(struct ath12k_base *ab, u32 pdev_id)587{588int i;589struct ath12k_pdev *pdev;590591if (ab->hw_params->single_pdev_only) {592pdev = rcu_dereference(ab->pdevs_active[0]);593return pdev ? pdev->ar : NULL;594}595596if (WARN_ON(pdev_id > ab->num_radios))597return NULL;598599for (i = 0; i < ab->num_radios; i++) {600pdev = rcu_dereference(ab->pdevs_active[i]);601602if (pdev && pdev->pdev_id == pdev_id)603return (pdev->ar ? pdev->ar : NULL);604}605606return NULL;607}608609static void ath12k_pdev_caps_update(struct ath12k *ar)610{611struct ath12k_base *ab = ar->ab;612613ar->max_tx_power = ab->target_caps.hw_max_tx_power;614615/* FIXME: Set min_tx_power to ab->target_caps.hw_min_tx_power.616* But since the received value in svcrdy is same as hw_max_tx_power,617* we can set ar->min_tx_power to 0 currently until618* this is fixed in firmware619*/620ar->min_tx_power = 0;621622ar->txpower_limit_2g = ar->max_tx_power;623ar->txpower_limit_5g = ar->max_tx_power;624ar->txpower_scale = WMI_HOST_TP_SCALE_MAX;625}626627static int ath12k_mac_txpower_recalc(struct ath12k *ar)628{629struct ath12k_pdev *pdev = ar->pdev;630struct ath12k_vif *arvif;631int ret, txpower = -1;632u32 param;633634lockdep_assert_held(&ar->conf_mutex);635636list_for_each_entry(arvif, &ar->arvifs, list) {637if (arvif->txpower <= 0)638continue;639640if (txpower == -1)641txpower = arvif->txpower;642else643txpower = min(txpower, arvif->txpower);644}645646if (txpower == -1)647return 0;648649/* txpwr is set as 2 units per dBm in FW*/650txpower = min_t(u32, max_t(u32, ar->min_tx_power, txpower),651ar->max_tx_power) * 2;652653ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "txpower to set in hw %d\n",654txpower / 2);655656if ((pdev->cap.supported_bands & WMI_HOST_WLAN_2G_CAP) &&657ar->txpower_limit_2g != txpower) {658param = WMI_PDEV_PARAM_TXPOWER_LIMIT2G;659ret = ath12k_wmi_pdev_set_param(ar, param,660txpower, ar->pdev->pdev_id);661if (ret)662goto fail;663ar->txpower_limit_2g = txpower;664}665666if ((pdev->cap.supported_bands & WMI_HOST_WLAN_5G_CAP) &&667ar->txpower_limit_5g != txpower) {668param = WMI_PDEV_PARAM_TXPOWER_LIMIT5G;669ret = ath12k_wmi_pdev_set_param(ar, param,670txpower, ar->pdev->pdev_id);671if (ret)672goto fail;673ar->txpower_limit_5g = txpower;674}675676return 0;677678fail:679ath12k_warn(ar->ab, "failed to recalc txpower limit %d using pdev param %d: %d\n",680txpower / 2, param, ret);681return ret;682}683684static int ath12k_recalc_rtscts_prot(struct ath12k_vif *arvif)685{686struct ath12k *ar = arvif->ar;687u32 vdev_param, rts_cts;688int ret;689690lockdep_assert_held(&ar->conf_mutex);691692vdev_param = WMI_VDEV_PARAM_ENABLE_RTSCTS;693694/* Enable RTS/CTS protection for sw retries (when legacy stations695* are in BSS) or by default only for second rate series.696* TODO: Check if we need to enable CTS 2 Self in any case697*/698rts_cts = WMI_USE_RTS_CTS;699700if (arvif->num_legacy_stations > 0)701rts_cts |= WMI_RTSCTS_ACROSS_SW_RETRIES << 4;702else703rts_cts |= WMI_RTSCTS_FOR_SECOND_RATESERIES << 4;704705/* Need not send duplicate param value to firmware */706if (arvif->rtscts_prot_mode == rts_cts)707return 0;708709arvif->rtscts_prot_mode = rts_cts;710711ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac vdev %d recalc rts/cts prot %d\n",712arvif->vdev_id, rts_cts);713714ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,715vdev_param, rts_cts);716if (ret)717ath12k_warn(ar->ab, "failed to recalculate rts/cts prot for vdev %d: %d\n",718arvif->vdev_id, ret);719720return ret;721}722723static int ath12k_mac_set_kickout(struct ath12k_vif *arvif)724{725struct ath12k *ar = arvif->ar;726u32 param;727int ret;728729ret = ath12k_wmi_pdev_set_param(ar, WMI_PDEV_PARAM_STA_KICKOUT_TH,730ATH12K_KICKOUT_THRESHOLD,731ar->pdev->pdev_id);732if (ret) {733ath12k_warn(ar->ab, "failed to set kickout threshold on vdev %i: %d\n",734arvif->vdev_id, ret);735return ret;736}737738param = WMI_VDEV_PARAM_AP_KEEPALIVE_MIN_IDLE_INACTIVE_TIME_SECS;739ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id, param,740ATH12K_KEEPALIVE_MIN_IDLE);741if (ret) {742ath12k_warn(ar->ab, "failed to set keepalive minimum idle time on vdev %i: %d\n",743arvif->vdev_id, ret);744return ret;745}746747param = WMI_VDEV_PARAM_AP_KEEPALIVE_MAX_IDLE_INACTIVE_TIME_SECS;748ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id, param,749ATH12K_KEEPALIVE_MAX_IDLE);750if (ret) {751ath12k_warn(ar->ab, "failed to set keepalive maximum idle time on vdev %i: %d\n",752arvif->vdev_id, ret);753return ret;754}755756param = WMI_VDEV_PARAM_AP_KEEPALIVE_MAX_UNRESPONSIVE_TIME_SECS;757ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id, param,758ATH12K_KEEPALIVE_MAX_UNRESPONSIVE);759if (ret) {760ath12k_warn(ar->ab, "failed to set keepalive maximum unresponsive time on vdev %i: %d\n",761arvif->vdev_id, ret);762return ret;763}764765return 0;766}767768void ath12k_mac_peer_cleanup_all(struct ath12k *ar)769{770struct ath12k_peer *peer, *tmp;771struct ath12k_base *ab = ar->ab;772773lockdep_assert_held(&ar->conf_mutex);774775spin_lock_bh(&ab->base_lock);776list_for_each_entry_safe(peer, tmp, &ab->peers, list) {777ath12k_dp_rx_peer_tid_cleanup(ar, peer);778list_del(&peer->list);779kfree(peer);780}781spin_unlock_bh(&ab->base_lock);782783ar->num_peers = 0;784ar->num_stations = 0;785}786787static int ath12k_mac_vdev_setup_sync(struct ath12k *ar)788{789lockdep_assert_held(&ar->conf_mutex);790791if (test_bit(ATH12K_FLAG_CRASH_FLUSH, &ar->ab->dev_flags))792return -ESHUTDOWN;793794ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "vdev setup timeout %d\n",795ATH12K_VDEV_SETUP_TIMEOUT_HZ);796797if (!wait_for_completion_timeout(&ar->vdev_setup_done,798ATH12K_VDEV_SETUP_TIMEOUT_HZ))799return -ETIMEDOUT;800801return ar->last_wmi_vdev_start_status ? -EINVAL : 0;802}803804static int ath12k_monitor_vdev_up(struct ath12k *ar, int vdev_id)805{806int ret;807808ret = ath12k_wmi_vdev_up(ar, vdev_id, 0, ar->mac_addr);809if (ret) {810ath12k_warn(ar->ab, "failed to put up monitor vdev %i: %d\n",811vdev_id, ret);812return ret;813}814815ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac monitor vdev %i started\n",816vdev_id);817return 0;818}819820static int ath12k_mac_monitor_vdev_start(struct ath12k *ar, int vdev_id,821struct cfg80211_chan_def *chandef)822{823struct ieee80211_channel *channel;824struct wmi_vdev_start_req_arg arg = {};825int ret;826827lockdep_assert_held(&ar->conf_mutex);828829channel = chandef->chan;830arg.vdev_id = vdev_id;831arg.freq = channel->center_freq;832arg.band_center_freq1 = chandef->center_freq1;833arg.band_center_freq2 = chandef->center_freq2;834arg.mode = ath12k_phymodes[chandef->chan->band][chandef->width];835arg.chan_radar = !!(channel->flags & IEEE80211_CHAN_RADAR);836837arg.min_power = 0;838arg.max_power = channel->max_power;839arg.max_reg_power = channel->max_reg_power;840arg.max_antenna_gain = channel->max_antenna_gain;841842arg.pref_tx_streams = ar->num_tx_chains;843arg.pref_rx_streams = ar->num_rx_chains;844arg.punct_bitmap = 0xFFFFFFFF;845846arg.passive |= !!(chandef->chan->flags & IEEE80211_CHAN_NO_IR);847848reinit_completion(&ar->vdev_setup_done);849reinit_completion(&ar->vdev_delete_done);850851ret = ath12k_wmi_vdev_start(ar, &arg, false);852if (ret) {853ath12k_warn(ar->ab, "failed to request monitor vdev %i start: %d\n",854vdev_id, ret);855return ret;856}857858ret = ath12k_mac_vdev_setup_sync(ar);859if (ret) {860ath12k_warn(ar->ab, "failed to synchronize setup for monitor vdev %i start: %d\n",861vdev_id, ret);862return ret;863}864865ret = ath12k_wmi_vdev_up(ar, vdev_id, 0, ar->mac_addr);866if (ret) {867ath12k_warn(ar->ab, "failed to put up monitor vdev %i: %d\n",868vdev_id, ret);869goto vdev_stop;870}871872ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac monitor vdev %i started\n",873vdev_id);874return 0;875876vdev_stop:877ret = ath12k_wmi_vdev_stop(ar, vdev_id);878if (ret)879ath12k_warn(ar->ab, "failed to stop monitor vdev %i after start failure: %d\n",880vdev_id, ret);881return ret;882}883884static int ath12k_mac_monitor_vdev_stop(struct ath12k *ar)885{886int ret;887888lockdep_assert_held(&ar->conf_mutex);889890reinit_completion(&ar->vdev_setup_done);891892ret = ath12k_wmi_vdev_stop(ar, ar->monitor_vdev_id);893if (ret)894ath12k_warn(ar->ab, "failed to request monitor vdev %i stop: %d\n",895ar->monitor_vdev_id, ret);896897ret = ath12k_mac_vdev_setup_sync(ar);898if (ret)899ath12k_warn(ar->ab, "failed to synchronize monitor vdev %i stop: %d\n",900ar->monitor_vdev_id, ret);901902ret = ath12k_wmi_vdev_down(ar, ar->monitor_vdev_id);903if (ret)904ath12k_warn(ar->ab, "failed to put down monitor vdev %i: %d\n",905ar->monitor_vdev_id, ret);906907ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac monitor vdev %i stopped\n",908ar->monitor_vdev_id);909return ret;910}911912static int ath12k_mac_monitor_vdev_create(struct ath12k *ar)913{914struct ath12k_pdev *pdev = ar->pdev;915struct ath12k_wmi_vdev_create_arg arg = {};916int bit, ret;917u8 tmp_addr[6];918u16 nss;919920lockdep_assert_held(&ar->conf_mutex);921922if (ar->monitor_vdev_created)923return 0;924925if (ar->ab->free_vdev_map == 0) {926ath12k_warn(ar->ab, "failed to find free vdev id for monitor vdev\n");927return -ENOMEM;928}929930bit = __ffs64(ar->ab->free_vdev_map);931932ar->monitor_vdev_id = bit;933934arg.if_id = ar->monitor_vdev_id;935arg.type = WMI_VDEV_TYPE_MONITOR;936arg.subtype = WMI_VDEV_SUBTYPE_NONE;937arg.pdev_id = pdev->pdev_id;938arg.if_stats_id = ATH12K_INVAL_VDEV_STATS_ID;939940if (pdev->cap.supported_bands & WMI_HOST_WLAN_2G_CAP) {941arg.chains[NL80211_BAND_2GHZ].tx = ar->num_tx_chains;942arg.chains[NL80211_BAND_2GHZ].rx = ar->num_rx_chains;943}944945if (pdev->cap.supported_bands & WMI_HOST_WLAN_5G_CAP) {946arg.chains[NL80211_BAND_5GHZ].tx = ar->num_tx_chains;947arg.chains[NL80211_BAND_5GHZ].rx = ar->num_rx_chains;948}949950ret = ath12k_wmi_vdev_create(ar, tmp_addr, &arg);951if (ret) {952ath12k_warn(ar->ab, "failed to request monitor vdev %i creation: %d\n",953ar->monitor_vdev_id, ret);954ar->monitor_vdev_id = -1;955return ret;956}957958nss = hweight32(ar->cfg_tx_chainmask) ? : 1;959ret = ath12k_wmi_vdev_set_param_cmd(ar, ar->monitor_vdev_id,960WMI_VDEV_PARAM_NSS, nss);961if (ret) {962ath12k_warn(ar->ab, "failed to set vdev %d chainmask 0x%x, nss %d :%d\n",963ar->monitor_vdev_id, ar->cfg_tx_chainmask, nss, ret);964return ret;965}966967ret = ath12k_mac_txpower_recalc(ar);968if (ret)969return ret;970971ar->allocated_vdev_map |= 1LL << ar->monitor_vdev_id;972ar->ab->free_vdev_map &= ~(1LL << ar->monitor_vdev_id);973ar->num_created_vdevs++;974ar->monitor_vdev_created = true;975ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac monitor vdev %d created\n",976ar->monitor_vdev_id);977978return 0;979}980981static int ath12k_mac_monitor_vdev_delete(struct ath12k *ar)982{983int ret;984unsigned long time_left;985986lockdep_assert_held(&ar->conf_mutex);987988if (!ar->monitor_vdev_created)989return 0;990991reinit_completion(&ar->vdev_delete_done);992993ret = ath12k_wmi_vdev_delete(ar, ar->monitor_vdev_id);994if (ret) {995ath12k_warn(ar->ab, "failed to request wmi monitor vdev %i removal: %d\n",996ar->monitor_vdev_id, ret);997return ret;998}9991000time_left = wait_for_completion_timeout(&ar->vdev_delete_done,1001ATH12K_VDEV_DELETE_TIMEOUT_HZ);1002if (time_left == 0) {1003ath12k_warn(ar->ab, "Timeout in receiving vdev delete response\n");1004} else {1005ar->allocated_vdev_map &= ~(1LL << ar->monitor_vdev_id);1006ar->ab->free_vdev_map |= 1LL << (ar->monitor_vdev_id);1007ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac monitor vdev %d deleted\n",1008ar->monitor_vdev_id);1009ar->num_created_vdevs--;1010ar->monitor_vdev_id = -1;1011ar->monitor_vdev_created = false;1012}10131014return ret;1015}10161017static void1018ath12k_mac_get_any_chandef_iter(struct ieee80211_hw *hw,1019struct ieee80211_chanctx_conf *conf,1020void *data)1021{1022struct cfg80211_chan_def **def = data;10231024*def = &conf->def;1025}10261027static int ath12k_mac_monitor_start(struct ath12k *ar)1028{1029struct cfg80211_chan_def *chandef = NULL;1030int ret;10311032lockdep_assert_held(&ar->conf_mutex);10331034if (ar->monitor_started)1035return 0;10361037ieee80211_iter_chan_contexts_atomic(ar->hw,1038ath12k_mac_get_any_chandef_iter,1039&chandef);1040if (!chandef)1041return 0;10421043ret = ath12k_mac_monitor_vdev_start(ar, ar->monitor_vdev_id, chandef);1044if (ret) {1045ath12k_warn(ar->ab, "failed to start monitor vdev: %d\n", ret);1046ath12k_mac_monitor_vdev_delete(ar);1047return ret;1048}10491050ar->monitor_started = true;1051ar->num_started_vdevs++;1052ret = ath12k_dp_tx_htt_monitor_mode_ring_config(ar, false);1053ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac monitor started ret %d\n", ret);10541055return ret;1056}10571058static int ath12k_mac_monitor_stop(struct ath12k *ar)1059{1060int ret;10611062lockdep_assert_held(&ar->conf_mutex);10631064if (!ar->monitor_started)1065return 0;10661067ret = ath12k_mac_monitor_vdev_stop(ar);1068if (ret) {1069ath12k_warn(ar->ab, "failed to stop monitor vdev: %d\n", ret);1070return ret;1071}10721073ar->monitor_started = false;1074ar->num_started_vdevs--;1075ret = ath12k_dp_tx_htt_monitor_mode_ring_config(ar, true);1076ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac monitor stopped ret %d\n", ret);1077return ret;1078}10791080static int ath12k_mac_op_config(struct ieee80211_hw *hw, u32 changed)1081{1082struct ath12k *ar = hw->priv;1083struct ieee80211_conf *conf = &hw->conf;1084int ret = 0;10851086mutex_lock(&ar->conf_mutex);10871088if (changed & IEEE80211_CONF_CHANGE_MONITOR) {1089ar->monitor_conf_enabled = conf->flags & IEEE80211_CONF_MONITOR;1090if (ar->monitor_conf_enabled) {1091if (ar->monitor_vdev_created)1092goto exit;1093ret = ath12k_mac_monitor_vdev_create(ar);1094if (ret)1095goto exit;1096ret = ath12k_mac_monitor_start(ar);1097if (ret)1098goto err_mon_del;1099} else {1100if (!ar->monitor_vdev_created)1101goto exit;1102ret = ath12k_mac_monitor_stop(ar);1103if (ret)1104goto exit;1105ath12k_mac_monitor_vdev_delete(ar);1106}1107}11081109exit:1110mutex_unlock(&ar->conf_mutex);1111return ret;11121113err_mon_del:1114ath12k_mac_monitor_vdev_delete(ar);1115mutex_unlock(&ar->conf_mutex);1116return ret;1117}11181119static int ath12k_mac_setup_bcn_tmpl(struct ath12k_vif *arvif)1120{1121struct ath12k *ar = arvif->ar;1122struct ath12k_base *ab = ar->ab;1123struct ieee80211_hw *hw = ar->hw;1124struct ieee80211_vif *vif = arvif->vif;1125struct ieee80211_mutable_offsets offs = {};1126struct sk_buff *bcn;1127struct ieee80211_mgmt *mgmt;1128u8 *ies;1129int ret;11301131if (arvif->vdev_type != WMI_VDEV_TYPE_AP)1132return 0;11331134bcn = ieee80211_beacon_get_template(hw, vif, &offs, 0);1135if (!bcn) {1136ath12k_warn(ab, "failed to get beacon template from mac80211\n");1137return -EPERM;1138}11391140ies = bcn->data + ieee80211_get_hdrlen_from_skb(bcn);1141ies += sizeof(mgmt->u.beacon);11421143if (cfg80211_find_ie(WLAN_EID_RSN, ies, (skb_tail_pointer(bcn) - ies)))1144arvif->rsnie_present = true;11451146if (cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,1147WLAN_OUI_TYPE_MICROSOFT_WPA,1148ies, (skb_tail_pointer(bcn) - ies)))1149arvif->wpaie_present = true;11501151ret = ath12k_wmi_bcn_tmpl(ar, arvif->vdev_id, &offs, bcn);11521153kfree_skb(bcn);11541155if (ret)1156ath12k_warn(ab, "failed to submit beacon template command: %d\n",1157ret);11581159return ret;1160}11611162static void ath12k_control_beaconing(struct ath12k_vif *arvif,1163struct ieee80211_bss_conf *info)1164{1165struct ath12k *ar = arvif->ar;1166int ret;11671168lockdep_assert_held(&arvif->ar->conf_mutex);11691170if (!info->enable_beacon) {1171ret = ath12k_wmi_vdev_down(ar, arvif->vdev_id);1172if (ret)1173ath12k_warn(ar->ab, "failed to down vdev_id %i: %d\n",1174arvif->vdev_id, ret);11751176arvif->is_up = false;1177return;1178}11791180/* Install the beacon template to the FW */1181ret = ath12k_mac_setup_bcn_tmpl(arvif);1182if (ret) {1183ath12k_warn(ar->ab, "failed to update bcn tmpl during vdev up: %d\n",1184ret);1185return;1186}11871188arvif->aid = 0;11891190ether_addr_copy(arvif->bssid, info->bssid);11911192ret = ath12k_wmi_vdev_up(arvif->ar, arvif->vdev_id, arvif->aid,1193arvif->bssid);1194if (ret) {1195ath12k_warn(ar->ab, "failed to bring up vdev %d: %i\n",1196arvif->vdev_id, ret);1197return;1198}11991200arvif->is_up = true;12011202ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac vdev %d up\n", arvif->vdev_id);1203}12041205static void ath12k_peer_assoc_h_basic(struct ath12k *ar,1206struct ieee80211_vif *vif,1207struct ieee80211_sta *sta,1208struct ath12k_wmi_peer_assoc_arg *arg)1209{1210struct ath12k_vif *arvif = (void *)vif->drv_priv;1211u32 aid;12121213lockdep_assert_held(&ar->conf_mutex);12141215if (vif->type == NL80211_IFTYPE_STATION)1216aid = vif->cfg.aid;1217else1218aid = sta->aid;12191220ether_addr_copy(arg->peer_mac, sta->addr);1221arg->vdev_id = arvif->vdev_id;1222arg->peer_associd = aid;1223arg->auth_flag = true;1224/* TODO: STA WAR in ath10k for listen interval required? */1225arg->peer_listen_intval = ar->hw->conf.listen_interval;1226arg->peer_nss = 1;1227arg->peer_caps = vif->bss_conf.assoc_capability;1228}12291230static void ath12k_peer_assoc_h_crypto(struct ath12k *ar,1231struct ieee80211_vif *vif,1232struct ieee80211_sta *sta,1233struct ath12k_wmi_peer_assoc_arg *arg)1234{1235struct ieee80211_bss_conf *info = &vif->bss_conf;1236struct cfg80211_chan_def def;1237struct cfg80211_bss *bss;1238struct ath12k_vif *arvif = (struct ath12k_vif *)vif->drv_priv;1239const u8 *rsnie = NULL;1240const u8 *wpaie = NULL;12411242lockdep_assert_held(&ar->conf_mutex);12431244if (WARN_ON(ath12k_mac_vif_chan(vif, &def)))1245return;12461247bss = cfg80211_get_bss(ar->hw->wiphy, def.chan, info->bssid, NULL, 0,1248IEEE80211_BSS_TYPE_ANY, IEEE80211_PRIVACY_ANY);12491250if (arvif->rsnie_present || arvif->wpaie_present) {1251arg->need_ptk_4_way = true;1252if (arvif->wpaie_present)1253arg->need_gtk_2_way = true;1254} else if (bss) {1255const struct cfg80211_bss_ies *ies;12561257rcu_read_lock();1258rsnie = ieee80211_bss_get_ie(bss, WLAN_EID_RSN);12591260ies = rcu_dereference(bss->ies);12611262wpaie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,1263WLAN_OUI_TYPE_MICROSOFT_WPA,1264ies->data,1265ies->len);1266rcu_read_unlock();1267cfg80211_put_bss(ar->hw->wiphy, bss);1268}12691270/* FIXME: base on RSN IE/WPA IE is a correct idea? */1271if (rsnie || wpaie) {1272ath12k_dbg(ar->ab, ATH12K_DBG_WMI,1273"%s: rsn ie found\n", __func__);1274arg->need_ptk_4_way = true;1275}12761277if (wpaie) {1278ath12k_dbg(ar->ab, ATH12K_DBG_WMI,1279"%s: wpa ie found\n", __func__);1280arg->need_gtk_2_way = true;1281}12821283if (sta->mfp) {1284/* TODO: Need to check if FW supports PMF? */1285arg->is_pmf_enabled = true;1286}12871288/* TODO: safe_mode_enabled (bypass 4-way handshake) flag req? */1289}12901291static void ath12k_peer_assoc_h_rates(struct ath12k *ar,1292struct ieee80211_vif *vif,1293struct ieee80211_sta *sta,1294struct ath12k_wmi_peer_assoc_arg *arg)1295{1296struct ath12k_vif *arvif = (void *)vif->drv_priv;1297struct wmi_rate_set_arg *rateset = &arg->peer_legacy_rates;1298struct cfg80211_chan_def def;1299const struct ieee80211_supported_band *sband;1300const struct ieee80211_rate *rates;1301enum nl80211_band band;1302u32 ratemask;1303u8 rate;1304int i;13051306lockdep_assert_held(&ar->conf_mutex);13071308if (WARN_ON(ath12k_mac_vif_chan(vif, &def)))1309return;13101311band = def.chan->band;1312sband = ar->hw->wiphy->bands[band];1313ratemask = sta->deflink.supp_rates[band];1314ratemask &= arvif->bitrate_mask.control[band].legacy;1315rates = sband->bitrates;13161317rateset->num_rates = 0;13181319for (i = 0; i < 32; i++, ratemask >>= 1, rates++) {1320if (!(ratemask & 1))1321continue;13221323rate = ath12k_mac_bitrate_to_rate(rates->bitrate);1324rateset->rates[rateset->num_rates] = rate;1325rateset->num_rates++;1326}1327}13281329static bool1330ath12k_peer_assoc_h_ht_masked(const u8 *ht_mcs_mask)1331{1332int nss;13331334for (nss = 0; nss < IEEE80211_HT_MCS_MASK_LEN; nss++)1335if (ht_mcs_mask[nss])1336return false;13371338return true;1339}13401341static bool1342ath12k_peer_assoc_h_vht_masked(const u16 *vht_mcs_mask)1343{1344int nss;13451346for (nss = 0; nss < NL80211_VHT_NSS_MAX; nss++)1347if (vht_mcs_mask[nss])1348return false;13491350return true;1351}13521353static void ath12k_peer_assoc_h_ht(struct ath12k *ar,1354struct ieee80211_vif *vif,1355struct ieee80211_sta *sta,1356struct ath12k_wmi_peer_assoc_arg *arg)1357{1358const struct ieee80211_sta_ht_cap *ht_cap = &sta->deflink.ht_cap;1359struct ath12k_vif *arvif = (void *)vif->drv_priv;1360struct cfg80211_chan_def def;1361enum nl80211_band band;1362const u8 *ht_mcs_mask;1363int i, n;1364u8 max_nss;1365u32 stbc;13661367lockdep_assert_held(&ar->conf_mutex);13681369if (WARN_ON(ath12k_mac_vif_chan(vif, &def)))1370return;13711372if (!ht_cap->ht_supported)1373return;13741375band = def.chan->band;1376ht_mcs_mask = arvif->bitrate_mask.control[band].ht_mcs;13771378if (ath12k_peer_assoc_h_ht_masked(ht_mcs_mask))1379return;13801381arg->ht_flag = true;13821383arg->peer_max_mpdu = (1 << (IEEE80211_HT_MAX_AMPDU_FACTOR +1384ht_cap->ampdu_factor)) - 1;13851386arg->peer_mpdu_density =1387ath12k_parse_mpdudensity(ht_cap->ampdu_density);13881389arg->peer_ht_caps = ht_cap->cap;1390arg->peer_rate_caps |= WMI_HOST_RC_HT_FLAG;13911392if (ht_cap->cap & IEEE80211_HT_CAP_LDPC_CODING)1393arg->ldpc_flag = true;13941395if (sta->deflink.bandwidth >= IEEE80211_STA_RX_BW_40) {1396arg->bw_40 = true;1397arg->peer_rate_caps |= WMI_HOST_RC_CW40_FLAG;1398}13991400if (arvif->bitrate_mask.control[band].gi != NL80211_TXRATE_FORCE_LGI) {1401if (ht_cap->cap & (IEEE80211_HT_CAP_SGI_20 |1402IEEE80211_HT_CAP_SGI_40))1403arg->peer_rate_caps |= WMI_HOST_RC_SGI_FLAG;1404}14051406if (ht_cap->cap & IEEE80211_HT_CAP_TX_STBC) {1407arg->peer_rate_caps |= WMI_HOST_RC_TX_STBC_FLAG;1408arg->stbc_flag = true;1409}14101411if (ht_cap->cap & IEEE80211_HT_CAP_RX_STBC) {1412stbc = ht_cap->cap & IEEE80211_HT_CAP_RX_STBC;1413stbc = stbc >> IEEE80211_HT_CAP_RX_STBC_SHIFT;1414stbc = stbc << WMI_HOST_RC_RX_STBC_FLAG_S;1415arg->peer_rate_caps |= stbc;1416arg->stbc_flag = true;1417}14181419if (ht_cap->mcs.rx_mask[1] && ht_cap->mcs.rx_mask[2])1420arg->peer_rate_caps |= WMI_HOST_RC_TS_FLAG;1421else if (ht_cap->mcs.rx_mask[1])1422arg->peer_rate_caps |= WMI_HOST_RC_DS_FLAG;14231424for (i = 0, n = 0, max_nss = 0; i < IEEE80211_HT_MCS_MASK_LEN * 8; i++)1425if ((ht_cap->mcs.rx_mask[i / 8] & BIT(i % 8)) &&1426(ht_mcs_mask[i / 8] & BIT(i % 8))) {1427max_nss = (i / 8) + 1;1428arg->peer_ht_rates.rates[n++] = i;1429}14301431/* This is a workaround for HT-enabled STAs which break the spec1432* and have no HT capabilities RX mask (no HT RX MCS map).1433*1434* As per spec, in section 20.3.5 Modulation and coding scheme (MCS),1435* MCS 0 through 7 are mandatory in 20MHz with 800 ns GI at all STAs.1436*1437* Firmware asserts if such situation occurs.1438*/1439if (n == 0) {1440arg->peer_ht_rates.num_rates = 8;1441for (i = 0; i < arg->peer_ht_rates.num_rates; i++)1442arg->peer_ht_rates.rates[i] = i;1443} else {1444arg->peer_ht_rates.num_rates = n;1445arg->peer_nss = min(sta->deflink.rx_nss, max_nss);1446}14471448ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac ht peer %pM mcs cnt %d nss %d\n",1449arg->peer_mac,1450arg->peer_ht_rates.num_rates,1451arg->peer_nss);1452}14531454static int ath12k_mac_get_max_vht_mcs_map(u16 mcs_map, int nss)1455{1456switch ((mcs_map >> (2 * nss)) & 0x3) {1457case IEEE80211_VHT_MCS_SUPPORT_0_7: return BIT(8) - 1;1458case IEEE80211_VHT_MCS_SUPPORT_0_8: return BIT(9) - 1;1459case IEEE80211_VHT_MCS_SUPPORT_0_9: return BIT(10) - 1;1460}1461return 0;1462}14631464static u161465ath12k_peer_assoc_h_vht_limit(u16 tx_mcs_set,1466const u16 vht_mcs_limit[NL80211_VHT_NSS_MAX])1467{1468int idx_limit;1469int nss;1470u16 mcs_map;1471u16 mcs;14721473for (nss = 0; nss < NL80211_VHT_NSS_MAX; nss++) {1474mcs_map = ath12k_mac_get_max_vht_mcs_map(tx_mcs_set, nss) &1475vht_mcs_limit[nss];14761477if (mcs_map)1478idx_limit = fls(mcs_map) - 1;1479else1480idx_limit = -1;14811482switch (idx_limit) {1483case 0:1484case 1:1485case 2:1486case 3:1487case 4:1488case 5:1489case 6:1490case 7:1491mcs = IEEE80211_VHT_MCS_SUPPORT_0_7;1492break;1493case 8:1494mcs = IEEE80211_VHT_MCS_SUPPORT_0_8;1495break;1496case 9:1497mcs = IEEE80211_VHT_MCS_SUPPORT_0_9;1498break;1499default:1500WARN_ON(1);1501fallthrough;1502case -1:1503mcs = IEEE80211_VHT_MCS_NOT_SUPPORTED;1504break;1505}15061507tx_mcs_set &= ~(0x3 << (nss * 2));1508tx_mcs_set |= mcs << (nss * 2);1509}15101511return tx_mcs_set;1512}15131514static void ath12k_peer_assoc_h_vht(struct ath12k *ar,1515struct ieee80211_vif *vif,1516struct ieee80211_sta *sta,1517struct ath12k_wmi_peer_assoc_arg *arg)1518{1519const struct ieee80211_sta_vht_cap *vht_cap = &sta->deflink.vht_cap;1520struct ath12k_vif *arvif = (void *)vif->drv_priv;1521struct cfg80211_chan_def def;1522enum nl80211_band band;1523const u16 *vht_mcs_mask;1524u16 tx_mcs_map;1525u8 ampdu_factor;1526u8 max_nss, vht_mcs;1527int i;15281529if (WARN_ON(ath12k_mac_vif_chan(vif, &def)))1530return;15311532if (!vht_cap->vht_supported)1533return;15341535band = def.chan->band;1536vht_mcs_mask = arvif->bitrate_mask.control[band].vht_mcs;15371538if (ath12k_peer_assoc_h_vht_masked(vht_mcs_mask))1539return;15401541arg->vht_flag = true;15421543/* TODO: similar flags required? */1544arg->vht_capable = true;15451546if (def.chan->band == NL80211_BAND_2GHZ)1547arg->vht_ng_flag = true;15481549arg->peer_vht_caps = vht_cap->cap;15501551ampdu_factor = (vht_cap->cap &1552IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK) >>1553IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT;15541555/* Workaround: Some Netgear/Linksys 11ac APs set Rx A-MPDU factor to1556* zero in VHT IE. Using it would result in degraded throughput.1557* arg->peer_max_mpdu at this point contains HT max_mpdu so keep1558* it if VHT max_mpdu is smaller.1559*/1560arg->peer_max_mpdu = max(arg->peer_max_mpdu,1561(1U << (IEEE80211_HT_MAX_AMPDU_FACTOR +1562ampdu_factor)) - 1);15631564if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_80)1565arg->bw_80 = true;15661567if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_160)1568arg->bw_160 = true;15691570/* Calculate peer NSS capability from VHT capabilities if STA1571* supports VHT.1572*/1573for (i = 0, max_nss = 0, vht_mcs = 0; i < NL80211_VHT_NSS_MAX; i++) {1574vht_mcs = __le16_to_cpu(vht_cap->vht_mcs.rx_mcs_map) >>1575(2 * i) & 3;15761577if (vht_mcs != IEEE80211_VHT_MCS_NOT_SUPPORTED &&1578vht_mcs_mask[i])1579max_nss = i + 1;1580}1581arg->peer_nss = min(sta->deflink.rx_nss, max_nss);1582arg->rx_max_rate = __le16_to_cpu(vht_cap->vht_mcs.rx_highest);1583arg->rx_mcs_set = __le16_to_cpu(vht_cap->vht_mcs.rx_mcs_map);1584arg->tx_max_rate = __le16_to_cpu(vht_cap->vht_mcs.tx_highest);15851586tx_mcs_map = __le16_to_cpu(vht_cap->vht_mcs.tx_mcs_map);1587arg->tx_mcs_set = ath12k_peer_assoc_h_vht_limit(tx_mcs_map, vht_mcs_mask);15881589/* In QCN9274 platform, VHT MCS rate 10 and 11 is enabled by default.1590* VHT MCS rate 10 and 11 is not supported in 11ac standard.1591* so explicitly disable the VHT MCS rate 10 and 11 in 11ac mode.1592*/1593arg->tx_mcs_set &= ~IEEE80211_VHT_MCS_SUPPORT_0_11_MASK;1594arg->tx_mcs_set |= IEEE80211_DISABLE_VHT_MCS_SUPPORT_0_11;15951596if ((arg->tx_mcs_set & IEEE80211_VHT_MCS_NOT_SUPPORTED) ==1597IEEE80211_VHT_MCS_NOT_SUPPORTED)1598arg->peer_vht_caps &= ~IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE;15991600/* TODO: Check */1601arg->tx_max_mcs_nss = 0xFF;16021603ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac vht peer %pM max_mpdu %d flags 0x%x\n",1604sta->addr, arg->peer_max_mpdu, arg->peer_flags);16051606/* TODO: rxnss_override */1607}16081609static void ath12k_peer_assoc_h_he(struct ath12k *ar,1610struct ieee80211_vif *vif,1611struct ieee80211_sta *sta,1612struct ath12k_wmi_peer_assoc_arg *arg)1613{1614const struct ieee80211_sta_he_cap *he_cap = &sta->deflink.he_cap;1615int i;1616u8 ampdu_factor, rx_mcs_80, rx_mcs_160, max_nss;1617u16 mcs_160_map, mcs_80_map;1618bool support_160;1619u16 v;16201621if (!he_cap->has_he)1622return;16231624arg->he_flag = true;16251626support_160 = !!(he_cap->he_cap_elem.phy_cap_info[0] &1627IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G);16281629/* Supported HE-MCS and NSS Set of peer he_cap is intersection with self he_cp */1630mcs_160_map = le16_to_cpu(he_cap->he_mcs_nss_supp.rx_mcs_160);1631mcs_80_map = le16_to_cpu(he_cap->he_mcs_nss_supp.rx_mcs_80);16321633if (support_160) {1634for (i = 7; i >= 0; i--) {1635u8 mcs_160 = (mcs_160_map >> (2 * i)) & 3;16361637if (mcs_160 != IEEE80211_HE_MCS_NOT_SUPPORTED) {1638rx_mcs_160 = i + 1;1639break;1640}1641}1642}16431644for (i = 7; i >= 0; i--) {1645u8 mcs_80 = (mcs_80_map >> (2 * i)) & 3;16461647if (mcs_80 != IEEE80211_HE_MCS_NOT_SUPPORTED) {1648rx_mcs_80 = i + 1;1649break;1650}1651}16521653if (support_160)1654max_nss = min(rx_mcs_80, rx_mcs_160);1655else1656max_nss = rx_mcs_80;16571658arg->peer_nss = min(sta->deflink.rx_nss, max_nss);16591660memcpy(&arg->peer_he_cap_macinfo, he_cap->he_cap_elem.mac_cap_info,1661sizeof(he_cap->he_cap_elem.mac_cap_info));1662memcpy(&arg->peer_he_cap_phyinfo, he_cap->he_cap_elem.phy_cap_info,1663sizeof(he_cap->he_cap_elem.phy_cap_info));1664arg->peer_he_ops = vif->bss_conf.he_oper.params;16651666/* the top most byte is used to indicate BSS color info */1667arg->peer_he_ops &= 0xffffff;16681669/* As per section 26.6.1 IEEE Std 802.11ax‐2022, if the Max AMPDU1670* Exponent Extension in HE cap is zero, use the arg->peer_max_mpdu1671* as calculated while parsing VHT caps(if VHT caps is present)1672* or HT caps (if VHT caps is not present).1673*1674* For non-zero value of Max AMPDU Exponent Extension in HE MAC caps,1675* if a HE STA sends VHT cap and HE cap IE in assoc request then, use1676* MAX_AMPDU_LEN_FACTOR as 20 to calculate max_ampdu length.1677* If a HE STA that does not send VHT cap, but HE and HT cap in assoc1678* request, then use MAX_AMPDU_LEN_FACTOR as 16 to calculate max_ampdu1679* length.1680*/1681ampdu_factor = (he_cap->he_cap_elem.mac_cap_info[3] &1682IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_MASK) >>1683IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_MASK;16841685if (ampdu_factor) {1686if (sta->deflink.vht_cap.vht_supported)1687arg->peer_max_mpdu = (1 << (IEEE80211_HE_VHT_MAX_AMPDU_FACTOR +1688ampdu_factor)) - 1;1689else if (sta->deflink.ht_cap.ht_supported)1690arg->peer_max_mpdu = (1 << (IEEE80211_HE_HT_MAX_AMPDU_FACTOR +1691ampdu_factor)) - 1;1692}16931694if (he_cap->he_cap_elem.phy_cap_info[6] &1695IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT) {1696int bit = 7;1697int nss, ru;16981699arg->peer_ppet.numss_m1 = he_cap->ppe_thres[0] &1700IEEE80211_PPE_THRES_NSS_MASK;1701arg->peer_ppet.ru_bit_mask =1702(he_cap->ppe_thres[0] &1703IEEE80211_PPE_THRES_RU_INDEX_BITMASK_MASK) >>1704IEEE80211_PPE_THRES_RU_INDEX_BITMASK_POS;17051706for (nss = 0; nss <= arg->peer_ppet.numss_m1; nss++) {1707for (ru = 0; ru < 4; ru++) {1708u32 val = 0;1709int i;17101711if ((arg->peer_ppet.ru_bit_mask & BIT(ru)) == 0)1712continue;1713for (i = 0; i < 6; i++) {1714val >>= 1;1715val |= ((he_cap->ppe_thres[bit / 8] >>1716(bit % 8)) & 0x1) << 5;1717bit++;1718}1719arg->peer_ppet.ppet16_ppet8_ru3_ru0[nss] |=1720val << (ru * 6);1721}1722}1723}17241725if (he_cap->he_cap_elem.mac_cap_info[0] & IEEE80211_HE_MAC_CAP0_TWT_RES)1726arg->twt_responder = true;1727if (he_cap->he_cap_elem.mac_cap_info[0] & IEEE80211_HE_MAC_CAP0_TWT_REQ)1728arg->twt_requester = true;17291730switch (sta->deflink.bandwidth) {1731case IEEE80211_STA_RX_BW_160:1732if (he_cap->he_cap_elem.phy_cap_info[0] &1733IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G) {1734v = le16_to_cpu(he_cap->he_mcs_nss_supp.rx_mcs_80p80);1735arg->peer_he_rx_mcs_set[WMI_HECAP_TXRX_MCS_NSS_IDX_80_80] = v;17361737v = le16_to_cpu(he_cap->he_mcs_nss_supp.tx_mcs_80p80);1738arg->peer_he_tx_mcs_set[WMI_HECAP_TXRX_MCS_NSS_IDX_80_80] = v;17391740arg->peer_he_mcs_count++;1741}1742v = le16_to_cpu(he_cap->he_mcs_nss_supp.rx_mcs_160);1743arg->peer_he_rx_mcs_set[WMI_HECAP_TXRX_MCS_NSS_IDX_160] = v;17441745v = le16_to_cpu(he_cap->he_mcs_nss_supp.tx_mcs_160);1746arg->peer_he_tx_mcs_set[WMI_HECAP_TXRX_MCS_NSS_IDX_160] = v;17471748arg->peer_he_mcs_count++;1749fallthrough;17501751default:1752v = le16_to_cpu(he_cap->he_mcs_nss_supp.rx_mcs_80);1753arg->peer_he_rx_mcs_set[WMI_HECAP_TXRX_MCS_NSS_IDX_80] = v;17541755v = le16_to_cpu(he_cap->he_mcs_nss_supp.tx_mcs_80);1756arg->peer_he_tx_mcs_set[WMI_HECAP_TXRX_MCS_NSS_IDX_80] = v;17571758arg->peer_he_mcs_count++;1759break;1760}1761}17621763static void ath12k_peer_assoc_h_smps(struct ieee80211_sta *sta,1764struct ath12k_wmi_peer_assoc_arg *arg)1765{1766const struct ieee80211_sta_ht_cap *ht_cap = &sta->deflink.ht_cap;1767int smps;17681769if (!ht_cap->ht_supported)1770return;17711772smps = ht_cap->cap & IEEE80211_HT_CAP_SM_PS;1773smps >>= IEEE80211_HT_CAP_SM_PS_SHIFT;17741775switch (smps) {1776case WLAN_HT_CAP_SM_PS_STATIC:1777arg->static_mimops_flag = true;1778break;1779case WLAN_HT_CAP_SM_PS_DYNAMIC:1780arg->dynamic_mimops_flag = true;1781break;1782case WLAN_HT_CAP_SM_PS_DISABLED:1783arg->spatial_mux_flag = true;1784break;1785default:1786break;1787}1788}17891790static void ath12k_peer_assoc_h_qos(struct ath12k *ar,1791struct ieee80211_vif *vif,1792struct ieee80211_sta *sta,1793struct ath12k_wmi_peer_assoc_arg *arg)1794{1795struct ath12k_vif *arvif = (void *)vif->drv_priv;17961797switch (arvif->vdev_type) {1798case WMI_VDEV_TYPE_AP:1799if (sta->wme) {1800/* TODO: Check WME vs QoS */1801arg->is_wme_set = true;1802arg->qos_flag = true;1803}18041805if (sta->wme && sta->uapsd_queues) {1806/* TODO: Check WME vs QoS */1807arg->is_wme_set = true;1808arg->apsd_flag = true;1809arg->peer_rate_caps |= WMI_HOST_RC_UAPSD_FLAG;1810}1811break;1812case WMI_VDEV_TYPE_STA:1813if (sta->wme) {1814arg->is_wme_set = true;1815arg->qos_flag = true;1816}1817break;1818default:1819break;1820}18211822ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac peer %pM qos %d\n",1823sta->addr, arg->qos_flag);1824}18251826static int ath12k_peer_assoc_qos_ap(struct ath12k *ar,1827struct ath12k_vif *arvif,1828struct ieee80211_sta *sta)1829{1830struct ath12k_wmi_ap_ps_arg arg;1831u32 max_sp;1832u32 uapsd;1833int ret;18341835lockdep_assert_held(&ar->conf_mutex);18361837arg.vdev_id = arvif->vdev_id;18381839ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac uapsd_queues 0x%x max_sp %d\n",1840sta->uapsd_queues, sta->max_sp);18411842uapsd = 0;1843if (sta->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_VO)1844uapsd |= WMI_AP_PS_UAPSD_AC3_DELIVERY_EN |1845WMI_AP_PS_UAPSD_AC3_TRIGGER_EN;1846if (sta->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_VI)1847uapsd |= WMI_AP_PS_UAPSD_AC2_DELIVERY_EN |1848WMI_AP_PS_UAPSD_AC2_TRIGGER_EN;1849if (sta->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_BK)1850uapsd |= WMI_AP_PS_UAPSD_AC1_DELIVERY_EN |1851WMI_AP_PS_UAPSD_AC1_TRIGGER_EN;1852if (sta->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_BE)1853uapsd |= WMI_AP_PS_UAPSD_AC0_DELIVERY_EN |1854WMI_AP_PS_UAPSD_AC0_TRIGGER_EN;18551856max_sp = 0;1857if (sta->max_sp < MAX_WMI_AP_PS_PEER_PARAM_MAX_SP)1858max_sp = sta->max_sp;18591860arg.param = WMI_AP_PS_PEER_PARAM_UAPSD;1861arg.value = uapsd;1862ret = ath12k_wmi_send_set_ap_ps_param_cmd(ar, sta->addr, &arg);1863if (ret)1864goto err;18651866arg.param = WMI_AP_PS_PEER_PARAM_MAX_SP;1867arg.value = max_sp;1868ret = ath12k_wmi_send_set_ap_ps_param_cmd(ar, sta->addr, &arg);1869if (ret)1870goto err;18711872/* TODO: revisit during testing */1873arg.param = WMI_AP_PS_PEER_PARAM_SIFS_RESP_FRMTYPE;1874arg.value = DISABLE_SIFS_RESPONSE_TRIGGER;1875ret = ath12k_wmi_send_set_ap_ps_param_cmd(ar, sta->addr, &arg);1876if (ret)1877goto err;18781879arg.param = WMI_AP_PS_PEER_PARAM_SIFS_RESP_UAPSD;1880arg.value = DISABLE_SIFS_RESPONSE_TRIGGER;1881ret = ath12k_wmi_send_set_ap_ps_param_cmd(ar, sta->addr, &arg);1882if (ret)1883goto err;18841885return 0;18861887err:1888ath12k_warn(ar->ab, "failed to set ap ps peer param %d for vdev %i: %d\n",1889arg.param, arvif->vdev_id, ret);1890return ret;1891}18921893static bool ath12k_mac_sta_has_ofdm_only(struct ieee80211_sta *sta)1894{1895return sta->deflink.supp_rates[NL80211_BAND_2GHZ] >>1896ATH12K_MAC_FIRST_OFDM_RATE_IDX;1897}18981899static enum wmi_phy_mode ath12k_mac_get_phymode_vht(struct ath12k *ar,1900struct ieee80211_sta *sta)1901{1902if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_160) {1903switch (sta->deflink.vht_cap.cap &1904IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK) {1905case IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ:1906return MODE_11AC_VHT160;1907case IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ:1908return MODE_11AC_VHT80_80;1909default:1910/* not sure if this is a valid case? */1911return MODE_11AC_VHT160;1912}1913}19141915if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_80)1916return MODE_11AC_VHT80;19171918if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_40)1919return MODE_11AC_VHT40;19201921if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_20)1922return MODE_11AC_VHT20;19231924return MODE_UNKNOWN;1925}19261927static enum wmi_phy_mode ath12k_mac_get_phymode_he(struct ath12k *ar,1928struct ieee80211_sta *sta)1929{1930if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_160) {1931if (sta->deflink.he_cap.he_cap_elem.phy_cap_info[0] &1932IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G)1933return MODE_11AX_HE160;1934else if (sta->deflink.he_cap.he_cap_elem.phy_cap_info[0] &1935IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G)1936return MODE_11AX_HE80_80;1937/* not sure if this is a valid case? */1938return MODE_11AX_HE160;1939}19401941if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_80)1942return MODE_11AX_HE80;19431944if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_40)1945return MODE_11AX_HE40;19461947if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_20)1948return MODE_11AX_HE20;19491950return MODE_UNKNOWN;1951}19521953static enum wmi_phy_mode ath12k_mac_get_phymode_eht(struct ath12k *ar,1954struct ieee80211_sta *sta)1955{1956if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_320)1957if (sta->deflink.eht_cap.eht_cap_elem.phy_cap_info[0] &1958IEEE80211_EHT_PHY_CAP0_320MHZ_IN_6GHZ)1959return MODE_11BE_EHT320;19601961if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_160) {1962if (sta->deflink.he_cap.he_cap_elem.phy_cap_info[0] &1963IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G)1964return MODE_11BE_EHT160;19651966if (sta->deflink.he_cap.he_cap_elem.phy_cap_info[0] &1967IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G)1968return MODE_11BE_EHT80_80;19691970ath12k_warn(ar->ab, "invalid EHT PHY capability info for 160 Mhz: %d\n",1971sta->deflink.he_cap.he_cap_elem.phy_cap_info[0]);19721973return MODE_11BE_EHT160;1974}19751976if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_80)1977return MODE_11BE_EHT80;19781979if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_40)1980return MODE_11BE_EHT40;19811982if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_20)1983return MODE_11BE_EHT20;19841985return MODE_UNKNOWN;1986}19871988static void ath12k_peer_assoc_h_phymode(struct ath12k *ar,1989struct ieee80211_vif *vif,1990struct ieee80211_sta *sta,1991struct ath12k_wmi_peer_assoc_arg *arg)1992{1993struct ath12k_vif *arvif = (void *)vif->drv_priv;1994struct cfg80211_chan_def def;1995enum nl80211_band band;1996const u8 *ht_mcs_mask;1997const u16 *vht_mcs_mask;1998enum wmi_phy_mode phymode = MODE_UNKNOWN;19992000if (WARN_ON(ath12k_mac_vif_chan(vif, &def)))2001return;20022003band = def.chan->band;2004ht_mcs_mask = arvif->bitrate_mask.control[band].ht_mcs;2005vht_mcs_mask = arvif->bitrate_mask.control[band].vht_mcs;20062007switch (band) {2008case NL80211_BAND_2GHZ:2009if (sta->deflink.eht_cap.has_eht) {2010if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_40)2011phymode = MODE_11BE_EHT40_2G;2012else2013phymode = MODE_11BE_EHT20_2G;2014} else if (sta->deflink.he_cap.has_he) {2015if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_80)2016phymode = MODE_11AX_HE80_2G;2017else if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_40)2018phymode = MODE_11AX_HE40_2G;2019else2020phymode = MODE_11AX_HE20_2G;2021} else if (sta->deflink.vht_cap.vht_supported &&2022!ath12k_peer_assoc_h_vht_masked(vht_mcs_mask)) {2023if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_40)2024phymode = MODE_11AC_VHT40;2025else2026phymode = MODE_11AC_VHT20;2027} else if (sta->deflink.ht_cap.ht_supported &&2028!ath12k_peer_assoc_h_ht_masked(ht_mcs_mask)) {2029if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_40)2030phymode = MODE_11NG_HT40;2031else2032phymode = MODE_11NG_HT20;2033} else if (ath12k_mac_sta_has_ofdm_only(sta)) {2034phymode = MODE_11G;2035} else {2036phymode = MODE_11B;2037}2038break;2039case NL80211_BAND_5GHZ:2040case NL80211_BAND_6GHZ:2041/* Check EHT first */2042if (sta->deflink.eht_cap.has_eht) {2043phymode = ath12k_mac_get_phymode_eht(ar, sta);2044} else if (sta->deflink.he_cap.has_he) {2045phymode = ath12k_mac_get_phymode_he(ar, sta);2046} else if (sta->deflink.vht_cap.vht_supported &&2047!ath12k_peer_assoc_h_vht_masked(vht_mcs_mask)) {2048phymode = ath12k_mac_get_phymode_vht(ar, sta);2049} else if (sta->deflink.ht_cap.ht_supported &&2050!ath12k_peer_assoc_h_ht_masked(ht_mcs_mask)) {2051if (sta->deflink.bandwidth >= IEEE80211_STA_RX_BW_40)2052phymode = MODE_11NA_HT40;2053else2054phymode = MODE_11NA_HT20;2055} else {2056phymode = MODE_11A;2057}2058break;2059default:2060break;2061}20622063ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac peer %pM phymode %s\n",2064sta->addr, ath12k_mac_phymode_str(phymode));20652066arg->peer_phymode = phymode;2067WARN_ON(phymode == MODE_UNKNOWN);2068}20692070static void ath12k_mac_set_eht_mcs(u8 rx_tx_mcs7, u8 rx_tx_mcs9,2071u8 rx_tx_mcs11, u8 rx_tx_mcs13,2072u32 *rx_mcs, u32 *tx_mcs)2073{2074*rx_mcs = 0;2075u32p_replace_bits(rx_mcs,2076u8_get_bits(rx_tx_mcs7, IEEE80211_EHT_MCS_NSS_RX),2077WMI_EHT_MCS_NSS_0_7);2078u32p_replace_bits(rx_mcs,2079u8_get_bits(rx_tx_mcs9, IEEE80211_EHT_MCS_NSS_RX),2080WMI_EHT_MCS_NSS_8_9);2081u32p_replace_bits(rx_mcs,2082u8_get_bits(rx_tx_mcs11, IEEE80211_EHT_MCS_NSS_RX),2083WMI_EHT_MCS_NSS_10_11);2084u32p_replace_bits(rx_mcs,2085u8_get_bits(rx_tx_mcs13, IEEE80211_EHT_MCS_NSS_RX),2086WMI_EHT_MCS_NSS_12_13);20872088*tx_mcs = 0;2089u32p_replace_bits(tx_mcs,2090u8_get_bits(rx_tx_mcs7, IEEE80211_EHT_MCS_NSS_TX),2091WMI_EHT_MCS_NSS_0_7);2092u32p_replace_bits(tx_mcs,2093u8_get_bits(rx_tx_mcs9, IEEE80211_EHT_MCS_NSS_TX),2094WMI_EHT_MCS_NSS_8_9);2095u32p_replace_bits(tx_mcs,2096u8_get_bits(rx_tx_mcs11, IEEE80211_EHT_MCS_NSS_TX),2097WMI_EHT_MCS_NSS_10_11);2098u32p_replace_bits(tx_mcs,2099u8_get_bits(rx_tx_mcs13, IEEE80211_EHT_MCS_NSS_TX),2100WMI_EHT_MCS_NSS_12_13);2101}21022103static void ath12k_mac_set_eht_ppe_threshold(const u8 *ppe_thres,2104struct ath12k_wmi_ppe_threshold_arg *ppet)2105{2106u32 bit_pos = IEEE80211_EHT_PPE_THRES_INFO_HEADER_SIZE, val;2107u8 nss, ru, i;2108u8 ppet_bit_len_per_ru = IEEE80211_EHT_PPE_THRES_INFO_PPET_SIZE * 2;21092110ppet->numss_m1 = u8_get_bits(ppe_thres[0], IEEE80211_EHT_PPE_THRES_NSS_MASK);2111ppet->ru_bit_mask = u16_get_bits(get_unaligned_le16(ppe_thres),2112IEEE80211_EHT_PPE_THRES_RU_INDEX_BITMASK_MASK);21132114for (nss = 0; nss <= ppet->numss_m1; nss++) {2115for (ru = 0;2116ru < hweight16(IEEE80211_EHT_PPE_THRES_RU_INDEX_BITMASK_MASK);2117ru++) {2118if ((ppet->ru_bit_mask & BIT(ru)) == 0)2119continue;21202121val = 0;2122for (i = 0; i < ppet_bit_len_per_ru; i++) {2123val |= (((ppe_thres[bit_pos / 8] >>2124(bit_pos % 8)) & 0x1) << i);2125bit_pos++;2126}2127ppet->ppet16_ppet8_ru3_ru0[nss] |=2128(val << (ru * ppet_bit_len_per_ru));2129}2130}2131}21322133static void ath12k_peer_assoc_h_eht(struct ath12k *ar,2134struct ieee80211_vif *vif,2135struct ieee80211_sta *sta,2136struct ath12k_wmi_peer_assoc_arg *arg)2137{2138const struct ieee80211_sta_eht_cap *eht_cap = &sta->deflink.eht_cap;2139const struct ieee80211_sta_he_cap *he_cap = &sta->deflink.he_cap;2140const struct ieee80211_eht_mcs_nss_supp_20mhz_only *bw_20;2141const struct ieee80211_eht_mcs_nss_supp_bw *bw;2142struct ath12k_vif *arvif = (struct ath12k_vif *)vif->drv_priv;2143u32 *rx_mcs, *tx_mcs;21442145if (!sta->deflink.he_cap.has_he || !eht_cap->has_eht)2146return;21472148arg->eht_flag = true;21492150if ((eht_cap->eht_cap_elem.phy_cap_info[5] &2151IEEE80211_EHT_PHY_CAP5_PPE_THRESHOLD_PRESENT) &&2152eht_cap->eht_ppe_thres[0] != 0)2153ath12k_mac_set_eht_ppe_threshold(eht_cap->eht_ppe_thres,2154&arg->peer_eht_ppet);21552156memcpy(arg->peer_eht_cap_mac, eht_cap->eht_cap_elem.mac_cap_info,2157sizeof(eht_cap->eht_cap_elem.mac_cap_info));2158memcpy(arg->peer_eht_cap_phy, eht_cap->eht_cap_elem.phy_cap_info,2159sizeof(eht_cap->eht_cap_elem.phy_cap_info));21602161rx_mcs = arg->peer_eht_rx_mcs_set;2162tx_mcs = arg->peer_eht_tx_mcs_set;21632164switch (sta->deflink.bandwidth) {2165case IEEE80211_STA_RX_BW_320:2166bw = &eht_cap->eht_mcs_nss_supp.bw._320;2167ath12k_mac_set_eht_mcs(bw->rx_tx_mcs9_max_nss,2168bw->rx_tx_mcs9_max_nss,2169bw->rx_tx_mcs11_max_nss,2170bw->rx_tx_mcs13_max_nss,2171&rx_mcs[WMI_EHTCAP_TXRX_MCS_NSS_IDX_320],2172&tx_mcs[WMI_EHTCAP_TXRX_MCS_NSS_IDX_320]);2173arg->peer_eht_mcs_count++;2174fallthrough;2175case IEEE80211_STA_RX_BW_160:2176bw = &eht_cap->eht_mcs_nss_supp.bw._160;2177ath12k_mac_set_eht_mcs(bw->rx_tx_mcs9_max_nss,2178bw->rx_tx_mcs9_max_nss,2179bw->rx_tx_mcs11_max_nss,2180bw->rx_tx_mcs13_max_nss,2181&rx_mcs[WMI_EHTCAP_TXRX_MCS_NSS_IDX_160],2182&tx_mcs[WMI_EHTCAP_TXRX_MCS_NSS_IDX_160]);2183arg->peer_eht_mcs_count++;2184fallthrough;2185default:2186if ((he_cap->he_cap_elem.phy_cap_info[0] &2187(IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G |2188IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G |2189IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G |2190IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G)) == 0) {2191bw_20 = &eht_cap->eht_mcs_nss_supp.only_20mhz;21922193ath12k_mac_set_eht_mcs(bw_20->rx_tx_mcs7_max_nss,2194bw_20->rx_tx_mcs9_max_nss,2195bw_20->rx_tx_mcs11_max_nss,2196bw_20->rx_tx_mcs13_max_nss,2197&rx_mcs[WMI_EHTCAP_TXRX_MCS_NSS_IDX_80],2198&tx_mcs[WMI_EHTCAP_TXRX_MCS_NSS_IDX_80]);2199} else {2200bw = &eht_cap->eht_mcs_nss_supp.bw._80;2201ath12k_mac_set_eht_mcs(bw->rx_tx_mcs9_max_nss,2202bw->rx_tx_mcs9_max_nss,2203bw->rx_tx_mcs11_max_nss,2204bw->rx_tx_mcs13_max_nss,2205&rx_mcs[WMI_EHTCAP_TXRX_MCS_NSS_IDX_80],2206&tx_mcs[WMI_EHTCAP_TXRX_MCS_NSS_IDX_80]);2207}22082209arg->peer_eht_mcs_count++;2210break;2211}22122213arg->punct_bitmap = ~arvif->punct_bitmap;2214}22152216static void ath12k_peer_assoc_prepare(struct ath12k *ar,2217struct ieee80211_vif *vif,2218struct ieee80211_sta *sta,2219struct ath12k_wmi_peer_assoc_arg *arg,2220bool reassoc)2221{2222lockdep_assert_held(&ar->conf_mutex);22232224memset(arg, 0, sizeof(*arg));22252226reinit_completion(&ar->peer_assoc_done);22272228arg->peer_new_assoc = !reassoc;2229ath12k_peer_assoc_h_basic(ar, vif, sta, arg);2230ath12k_peer_assoc_h_crypto(ar, vif, sta, arg);2231ath12k_peer_assoc_h_rates(ar, vif, sta, arg);2232ath12k_peer_assoc_h_ht(ar, vif, sta, arg);2233ath12k_peer_assoc_h_vht(ar, vif, sta, arg);2234ath12k_peer_assoc_h_he(ar, vif, sta, arg);2235ath12k_peer_assoc_h_eht(ar, vif, sta, arg);2236ath12k_peer_assoc_h_qos(ar, vif, sta, arg);2237ath12k_peer_assoc_h_phymode(ar, vif, sta, arg);2238ath12k_peer_assoc_h_smps(sta, arg);22392240/* TODO: amsdu_disable req? */2241}22422243static int ath12k_setup_peer_smps(struct ath12k *ar, struct ath12k_vif *arvif,2244const u8 *addr,2245const struct ieee80211_sta_ht_cap *ht_cap)2246{2247int smps;22482249if (!ht_cap->ht_supported)2250return 0;22512252smps = ht_cap->cap & IEEE80211_HT_CAP_SM_PS;2253smps >>= IEEE80211_HT_CAP_SM_PS_SHIFT;22542255if (smps >= ARRAY_SIZE(ath12k_smps_map))2256return -EINVAL;22572258return ath12k_wmi_set_peer_param(ar, addr, arvif->vdev_id,2259WMI_PEER_MIMO_PS_STATE,2260ath12k_smps_map[smps]);2261}22622263static void ath12k_bss_assoc(struct ieee80211_hw *hw,2264struct ieee80211_vif *vif,2265struct ieee80211_bss_conf *bss_conf)2266{2267struct ath12k *ar = hw->priv;2268struct ath12k_vif *arvif = (void *)vif->drv_priv;2269struct ath12k_wmi_peer_assoc_arg peer_arg;2270struct ieee80211_sta *ap_sta;2271struct ath12k_peer *peer;2272bool is_auth = false;2273int ret;22742275lockdep_assert_held(&ar->conf_mutex);22762277ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac vdev %i assoc bssid %pM aid %d\n",2278arvif->vdev_id, arvif->bssid, arvif->aid);22792280rcu_read_lock();22812282ap_sta = ieee80211_find_sta(vif, bss_conf->bssid);2283if (!ap_sta) {2284ath12k_warn(ar->ab, "failed to find station entry for bss %pM vdev %i\n",2285bss_conf->bssid, arvif->vdev_id);2286rcu_read_unlock();2287return;2288}22892290ath12k_peer_assoc_prepare(ar, vif, ap_sta, &peer_arg, false);22912292rcu_read_unlock();22932294ret = ath12k_wmi_send_peer_assoc_cmd(ar, &peer_arg);2295if (ret) {2296ath12k_warn(ar->ab, "failed to run peer assoc for %pM vdev %i: %d\n",2297bss_conf->bssid, arvif->vdev_id, ret);2298return;2299}23002301if (!wait_for_completion_timeout(&ar->peer_assoc_done, 1 * HZ)) {2302ath12k_warn(ar->ab, "failed to get peer assoc conf event for %pM vdev %i\n",2303bss_conf->bssid, arvif->vdev_id);2304return;2305}23062307ret = ath12k_setup_peer_smps(ar, arvif, bss_conf->bssid,2308&ap_sta->deflink.ht_cap);2309if (ret) {2310ath12k_warn(ar->ab, "failed to setup peer SMPS for vdev %d: %d\n",2311arvif->vdev_id, ret);2312return;2313}23142315WARN_ON(arvif->is_up);23162317arvif->aid = vif->cfg.aid;2318ether_addr_copy(arvif->bssid, bss_conf->bssid);23192320ret = ath12k_wmi_vdev_up(ar, arvif->vdev_id, arvif->aid, arvif->bssid);2321if (ret) {2322ath12k_warn(ar->ab, "failed to set vdev %d up: %d\n",2323arvif->vdev_id, ret);2324return;2325}23262327arvif->is_up = true;23282329ath12k_dbg(ar->ab, ATH12K_DBG_MAC,2330"mac vdev %d up (associated) bssid %pM aid %d\n",2331arvif->vdev_id, bss_conf->bssid, vif->cfg.aid);23322333spin_lock_bh(&ar->ab->base_lock);23342335peer = ath12k_peer_find(ar->ab, arvif->vdev_id, arvif->bssid);2336if (peer && peer->is_authorized)2337is_auth = true;23382339spin_unlock_bh(&ar->ab->base_lock);23402341/* Authorize BSS Peer */2342if (is_auth) {2343ret = ath12k_wmi_set_peer_param(ar, arvif->bssid,2344arvif->vdev_id,2345WMI_PEER_AUTHORIZE,23461);2347if (ret)2348ath12k_warn(ar->ab, "Unable to authorize BSS peer: %d\n", ret);2349}23502351ret = ath12k_wmi_send_obss_spr_cmd(ar, arvif->vdev_id,2352&bss_conf->he_obss_pd);2353if (ret)2354ath12k_warn(ar->ab, "failed to set vdev %i OBSS PD parameters: %d\n",2355arvif->vdev_id, ret);2356}23572358static void ath12k_bss_disassoc(struct ieee80211_hw *hw,2359struct ieee80211_vif *vif)2360{2361struct ath12k *ar = hw->priv;2362struct ath12k_vif *arvif = (void *)vif->drv_priv;2363int ret;23642365lockdep_assert_held(&ar->conf_mutex);23662367ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac vdev %i disassoc bssid %pM\n",2368arvif->vdev_id, arvif->bssid);23692370ret = ath12k_wmi_vdev_down(ar, arvif->vdev_id);2371if (ret)2372ath12k_warn(ar->ab, "failed to down vdev %i: %d\n",2373arvif->vdev_id, ret);23742375arvif->is_up = false;23762377/* TODO: cancel connection_loss_work */2378}23792380static u32 ath12k_mac_get_rate_hw_value(int bitrate)2381{2382u32 preamble;2383u16 hw_value;2384int rate;2385size_t i;23862387if (ath12k_mac_bitrate_is_cck(bitrate))2388preamble = WMI_RATE_PREAMBLE_CCK;2389else2390preamble = WMI_RATE_PREAMBLE_OFDM;23912392for (i = 0; i < ARRAY_SIZE(ath12k_legacy_rates); i++) {2393if (ath12k_legacy_rates[i].bitrate != bitrate)2394continue;23952396hw_value = ath12k_legacy_rates[i].hw_value;2397rate = ATH12K_HW_RATE_CODE(hw_value, 0, preamble);23982399return rate;2400}24012402return -EINVAL;2403}24042405static void ath12k_recalculate_mgmt_rate(struct ath12k *ar,2406struct ieee80211_vif *vif,2407struct cfg80211_chan_def *def)2408{2409struct ath12k_vif *arvif = (void *)vif->drv_priv;2410const struct ieee80211_supported_band *sband;2411u8 basic_rate_idx;2412int hw_rate_code;2413u32 vdev_param;2414u16 bitrate;2415int ret;24162417lockdep_assert_held(&ar->conf_mutex);24182419sband = ar->hw->wiphy->bands[def->chan->band];2420basic_rate_idx = ffs(vif->bss_conf.basic_rates) - 1;2421bitrate = sband->bitrates[basic_rate_idx].bitrate;24222423hw_rate_code = ath12k_mac_get_rate_hw_value(bitrate);2424if (hw_rate_code < 0) {2425ath12k_warn(ar->ab, "bitrate not supported %d\n", bitrate);2426return;2427}24282429vdev_param = WMI_VDEV_PARAM_MGMT_RATE;2430ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id, vdev_param,2431hw_rate_code);2432if (ret)2433ath12k_warn(ar->ab, "failed to set mgmt tx rate %d\n", ret);24342435vdev_param = WMI_VDEV_PARAM_BEACON_RATE;2436ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id, vdev_param,2437hw_rate_code);2438if (ret)2439ath12k_warn(ar->ab, "failed to set beacon tx rate %d\n", ret);2440}24412442static int ath12k_mac_fils_discovery(struct ath12k_vif *arvif,2443struct ieee80211_bss_conf *info)2444{2445struct ath12k *ar = arvif->ar;2446struct sk_buff *tmpl;2447int ret;2448u32 interval;2449bool unsol_bcast_probe_resp_enabled = false;24502451if (info->fils_discovery.max_interval) {2452interval = info->fils_discovery.max_interval;24532454tmpl = ieee80211_get_fils_discovery_tmpl(ar->hw, arvif->vif);2455if (tmpl)2456ret = ath12k_wmi_fils_discovery_tmpl(ar, arvif->vdev_id,2457tmpl);2458} else if (info->unsol_bcast_probe_resp_interval) {2459unsol_bcast_probe_resp_enabled = 1;2460interval = info->unsol_bcast_probe_resp_interval;24612462tmpl = ieee80211_get_unsol_bcast_probe_resp_tmpl(ar->hw,2463arvif->vif);2464if (tmpl)2465ret = ath12k_wmi_probe_resp_tmpl(ar, arvif->vdev_id,2466tmpl);2467} else { /* Disable */2468return ath12k_wmi_fils_discovery(ar, arvif->vdev_id, 0, false);2469}24702471if (!tmpl) {2472ath12k_warn(ar->ab,2473"mac vdev %i failed to retrieve %s template\n",2474arvif->vdev_id, (unsol_bcast_probe_resp_enabled ?2475"unsolicited broadcast probe response" :2476"FILS discovery"));2477return -EPERM;2478}2479kfree_skb(tmpl);24802481if (!ret)2482ret = ath12k_wmi_fils_discovery(ar, arvif->vdev_id, interval,2483unsol_bcast_probe_resp_enabled);24842485return ret;2486}24872488static void ath12k_mac_op_bss_info_changed(struct ieee80211_hw *hw,2489struct ieee80211_vif *vif,2490struct ieee80211_bss_conf *info,2491u64 changed)2492{2493struct ath12k *ar = hw->priv;2494struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);2495struct cfg80211_chan_def def;2496u32 param_id, param_value;2497enum nl80211_band band;2498u32 vdev_param;2499int mcast_rate;2500u32 preamble;2501u16 hw_value;2502u16 bitrate;2503int ret;2504u8 rateidx;2505u32 rate;25062507mutex_lock(&ar->conf_mutex);25082509if (changed & BSS_CHANGED_BEACON_INT) {2510arvif->beacon_interval = info->beacon_int;25112512param_id = WMI_VDEV_PARAM_BEACON_INTERVAL;2513ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,2514param_id,2515arvif->beacon_interval);2516if (ret)2517ath12k_warn(ar->ab, "Failed to set beacon interval for VDEV: %d\n",2518arvif->vdev_id);2519else2520ath12k_dbg(ar->ab, ATH12K_DBG_MAC,2521"Beacon interval: %d set for VDEV: %d\n",2522arvif->beacon_interval, arvif->vdev_id);2523}25242525if (changed & BSS_CHANGED_BEACON) {2526param_id = WMI_PDEV_PARAM_BEACON_TX_MODE;2527param_value = WMI_BEACON_STAGGERED_MODE;2528ret = ath12k_wmi_pdev_set_param(ar, param_id,2529param_value, ar->pdev->pdev_id);2530if (ret)2531ath12k_warn(ar->ab, "Failed to set beacon mode for VDEV: %d\n",2532arvif->vdev_id);2533else2534ath12k_dbg(ar->ab, ATH12K_DBG_MAC,2535"Set staggered beacon mode for VDEV: %d\n",2536arvif->vdev_id);25372538ret = ath12k_mac_setup_bcn_tmpl(arvif);2539if (ret)2540ath12k_warn(ar->ab, "failed to update bcn template: %d\n",2541ret);2542}25432544if (changed & (BSS_CHANGED_BEACON_INFO | BSS_CHANGED_BEACON)) {2545arvif->dtim_period = info->dtim_period;25462547param_id = WMI_VDEV_PARAM_DTIM_PERIOD;2548ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,2549param_id,2550arvif->dtim_period);25512552if (ret)2553ath12k_warn(ar->ab, "Failed to set dtim period for VDEV %d: %i\n",2554arvif->vdev_id, ret);2555else2556ath12k_dbg(ar->ab, ATH12K_DBG_MAC,2557"DTIM period: %d set for VDEV: %d\n",2558arvif->dtim_period, arvif->vdev_id);2559}25602561if (changed & BSS_CHANGED_SSID &&2562vif->type == NL80211_IFTYPE_AP) {2563arvif->u.ap.ssid_len = vif->cfg.ssid_len;2564if (vif->cfg.ssid_len)2565memcpy(arvif->u.ap.ssid, vif->cfg.ssid, vif->cfg.ssid_len);2566arvif->u.ap.hidden_ssid = info->hidden_ssid;2567}25682569if (changed & BSS_CHANGED_BSSID && !is_zero_ether_addr(info->bssid))2570ether_addr_copy(arvif->bssid, info->bssid);25712572if (changed & BSS_CHANGED_BEACON_ENABLED) {2573ath12k_control_beaconing(arvif, info);25742575if (arvif->is_up && vif->bss_conf.he_support &&2576vif->bss_conf.he_oper.params) {2577/* TODO: Extend to support 1024 BA Bitmap size */2578ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,2579WMI_VDEV_PARAM_BA_MODE,2580WMI_BA_MODE_BUFFER_SIZE_256);2581if (ret)2582ath12k_warn(ar->ab,2583"failed to set BA BUFFER SIZE 256 for vdev: %d\n",2584arvif->vdev_id);25852586param_id = WMI_VDEV_PARAM_HEOPS_0_31;2587param_value = vif->bss_conf.he_oper.params;2588ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,2589param_id, param_value);2590ath12k_dbg(ar->ab, ATH12K_DBG_MAC,2591"he oper param: %x set for VDEV: %d\n",2592param_value, arvif->vdev_id);25932594if (ret)2595ath12k_warn(ar->ab, "Failed to set he oper params %x for VDEV %d: %i\n",2596param_value, arvif->vdev_id, ret);2597}2598}25992600if (changed & BSS_CHANGED_ERP_CTS_PROT) {2601u32 cts_prot;26022603cts_prot = !!(info->use_cts_prot);2604param_id = WMI_VDEV_PARAM_PROTECTION_MODE;26052606if (arvif->is_started) {2607ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,2608param_id, cts_prot);2609if (ret)2610ath12k_warn(ar->ab, "Failed to set CTS prot for VDEV: %d\n",2611arvif->vdev_id);2612else2613ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "Set CTS prot: %d for VDEV: %d\n",2614cts_prot, arvif->vdev_id);2615} else {2616ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "defer protection mode setup, vdev is not ready yet\n");2617}2618}26192620if (changed & BSS_CHANGED_ERP_SLOT) {2621u32 slottime;26222623if (info->use_short_slot)2624slottime = WMI_VDEV_SLOT_TIME_SHORT; /* 9us */26252626else2627slottime = WMI_VDEV_SLOT_TIME_LONG; /* 20us */26282629param_id = WMI_VDEV_PARAM_SLOT_TIME;2630ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,2631param_id, slottime);2632if (ret)2633ath12k_warn(ar->ab, "Failed to set erp slot for VDEV: %d\n",2634arvif->vdev_id);2635else2636ath12k_dbg(ar->ab, ATH12K_DBG_MAC,2637"Set slottime: %d for VDEV: %d\n",2638slottime, arvif->vdev_id);2639}26402641if (changed & BSS_CHANGED_ERP_PREAMBLE) {2642u32 preamble;26432644if (info->use_short_preamble)2645preamble = WMI_VDEV_PREAMBLE_SHORT;2646else2647preamble = WMI_VDEV_PREAMBLE_LONG;26482649param_id = WMI_VDEV_PARAM_PREAMBLE;2650ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,2651param_id, preamble);2652if (ret)2653ath12k_warn(ar->ab, "Failed to set preamble for VDEV: %d\n",2654arvif->vdev_id);2655else2656ath12k_dbg(ar->ab, ATH12K_DBG_MAC,2657"Set preamble: %d for VDEV: %d\n",2658preamble, arvif->vdev_id);2659}26602661if (changed & BSS_CHANGED_ASSOC) {2662if (vif->cfg.assoc)2663ath12k_bss_assoc(hw, vif, info);2664else2665ath12k_bss_disassoc(hw, vif);2666}26672668if (changed & BSS_CHANGED_TXPOWER) {2669ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac vdev_id %i txpower %d\n",2670arvif->vdev_id, info->txpower);26712672arvif->txpower = info->txpower;2673ath12k_mac_txpower_recalc(ar);2674}26752676if (changed & BSS_CHANGED_MCAST_RATE &&2677!ath12k_mac_vif_chan(arvif->vif, &def)) {2678band = def.chan->band;2679mcast_rate = vif->bss_conf.mcast_rate[band];26802681if (mcast_rate > 0)2682rateidx = mcast_rate - 1;2683else2684rateidx = ffs(vif->bss_conf.basic_rates) - 1;26852686if (ar->pdev->cap.supported_bands & WMI_HOST_WLAN_5G_CAP)2687rateidx += ATH12K_MAC_FIRST_OFDM_RATE_IDX;26882689bitrate = ath12k_legacy_rates[rateidx].bitrate;2690hw_value = ath12k_legacy_rates[rateidx].hw_value;26912692if (ath12k_mac_bitrate_is_cck(bitrate))2693preamble = WMI_RATE_PREAMBLE_CCK;2694else2695preamble = WMI_RATE_PREAMBLE_OFDM;26962697rate = ATH12K_HW_RATE_CODE(hw_value, 0, preamble);26982699ath12k_dbg(ar->ab, ATH12K_DBG_MAC,2700"mac vdev %d mcast_rate %x\n",2701arvif->vdev_id, rate);27022703vdev_param = WMI_VDEV_PARAM_MCAST_DATA_RATE;2704ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,2705vdev_param, rate);2706if (ret)2707ath12k_warn(ar->ab,2708"failed to set mcast rate on vdev %i: %d\n",2709arvif->vdev_id, ret);27102711vdev_param = WMI_VDEV_PARAM_BCAST_DATA_RATE;2712ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,2713vdev_param, rate);2714if (ret)2715ath12k_warn(ar->ab,2716"failed to set bcast rate on vdev %i: %d\n",2717arvif->vdev_id, ret);2718}27192720if (changed & BSS_CHANGED_BASIC_RATES &&2721!ath12k_mac_vif_chan(arvif->vif, &def))2722ath12k_recalculate_mgmt_rate(ar, vif, &def);27232724if (changed & BSS_CHANGED_TWT) {2725if (info->twt_requester || info->twt_responder)2726ath12k_wmi_send_twt_enable_cmd(ar, ar->pdev->pdev_id);2727else2728ath12k_wmi_send_twt_disable_cmd(ar, ar->pdev->pdev_id);2729}27302731if (changed & BSS_CHANGED_HE_OBSS_PD)2732ath12k_wmi_send_obss_spr_cmd(ar, arvif->vdev_id,2733&info->he_obss_pd);27342735if (changed & BSS_CHANGED_HE_BSS_COLOR) {2736if (vif->type == NL80211_IFTYPE_AP) {2737ret = ath12k_wmi_obss_color_cfg_cmd(ar,2738arvif->vdev_id,2739info->he_bss_color.color,2740ATH12K_BSS_COLOR_AP_PERIODS,2741info->he_bss_color.enabled);2742if (ret)2743ath12k_warn(ar->ab, "failed to set bss color collision on vdev %i: %d\n",2744arvif->vdev_id, ret);2745} else if (vif->type == NL80211_IFTYPE_STATION) {2746ret = ath12k_wmi_send_bss_color_change_enable_cmd(ar,2747arvif->vdev_id,27481);2749if (ret)2750ath12k_warn(ar->ab, "failed to enable bss color change on vdev %i: %d\n",2751arvif->vdev_id, ret);2752ret = ath12k_wmi_obss_color_cfg_cmd(ar,2753arvif->vdev_id,27540,2755ATH12K_BSS_COLOR_STA_PERIODS,27561);2757if (ret)2758ath12k_warn(ar->ab, "failed to set bss color collision on vdev %i: %d\n",2759arvif->vdev_id, ret);2760}2761}27622763if (changed & BSS_CHANGED_FILS_DISCOVERY ||2764changed & BSS_CHANGED_UNSOL_BCAST_PROBE_RESP)2765ath12k_mac_fils_discovery(arvif, info);27662767if (changed & BSS_CHANGED_EHT_PUNCTURING)2768arvif->punct_bitmap = info->eht_puncturing;27692770mutex_unlock(&ar->conf_mutex);2771}27722773void __ath12k_mac_scan_finish(struct ath12k *ar)2774{2775lockdep_assert_held(&ar->data_lock);27762777switch (ar->scan.state) {2778case ATH12K_SCAN_IDLE:2779break;2780case ATH12K_SCAN_RUNNING:2781case ATH12K_SCAN_ABORTING:2782if (!ar->scan.is_roc) {2783struct cfg80211_scan_info info = {2784.aborted = (ar->scan.state ==2785ATH12K_SCAN_ABORTING),2786};27872788ieee80211_scan_completed(ar->hw, &info);2789} else if (ar->scan.roc_notify) {2790ieee80211_remain_on_channel_expired(ar->hw);2791}2792fallthrough;2793case ATH12K_SCAN_STARTING:2794ar->scan.state = ATH12K_SCAN_IDLE;2795ar->scan_channel = NULL;2796ar->scan.roc_freq = 0;2797cancel_delayed_work(&ar->scan.timeout);2798complete(&ar->scan.completed);2799break;2800}2801}28022803void ath12k_mac_scan_finish(struct ath12k *ar)2804{2805spin_lock_bh(&ar->data_lock);2806__ath12k_mac_scan_finish(ar);2807spin_unlock_bh(&ar->data_lock);2808}28092810static int ath12k_scan_stop(struct ath12k *ar)2811{2812struct ath12k_wmi_scan_cancel_arg arg = {2813.req_type = WLAN_SCAN_CANCEL_SINGLE,2814.scan_id = ATH12K_SCAN_ID,2815};2816int ret;28172818lockdep_assert_held(&ar->conf_mutex);28192820/* TODO: Fill other STOP Params */2821arg.pdev_id = ar->pdev->pdev_id;28222823ret = ath12k_wmi_send_scan_stop_cmd(ar, &arg);2824if (ret) {2825ath12k_warn(ar->ab, "failed to stop wmi scan: %d\n", ret);2826goto out;2827}28282829ret = wait_for_completion_timeout(&ar->scan.completed, 3 * HZ);2830if (ret == 0) {2831ath12k_warn(ar->ab,2832"failed to receive scan abort comple: timed out\n");2833ret = -ETIMEDOUT;2834} else if (ret > 0) {2835ret = 0;2836}28372838out:2839/* Scan state should be updated upon scan completion but in case2840* firmware fails to deliver the event (for whatever reason) it is2841* desired to clean up scan state anyway. Firmware may have just2842* dropped the scan completion event delivery due to transport pipe2843* being overflown with data and/or it can recover on its own before2844* next scan request is submitted.2845*/2846spin_lock_bh(&ar->data_lock);2847if (ar->scan.state != ATH12K_SCAN_IDLE)2848__ath12k_mac_scan_finish(ar);2849spin_unlock_bh(&ar->data_lock);28502851return ret;2852}28532854static void ath12k_scan_abort(struct ath12k *ar)2855{2856int ret;28572858lockdep_assert_held(&ar->conf_mutex);28592860spin_lock_bh(&ar->data_lock);28612862switch (ar->scan.state) {2863case ATH12K_SCAN_IDLE:2864/* This can happen if timeout worker kicked in and called2865* abortion while scan completion was being processed.2866*/2867break;2868case ATH12K_SCAN_STARTING:2869case ATH12K_SCAN_ABORTING:2870ath12k_warn(ar->ab, "refusing scan abortion due to invalid scan state: %d\n",2871ar->scan.state);2872break;2873case ATH12K_SCAN_RUNNING:2874ar->scan.state = ATH12K_SCAN_ABORTING;2875spin_unlock_bh(&ar->data_lock);28762877ret = ath12k_scan_stop(ar);2878if (ret)2879ath12k_warn(ar->ab, "failed to abort scan: %d\n", ret);28802881spin_lock_bh(&ar->data_lock);2882break;2883}28842885spin_unlock_bh(&ar->data_lock);2886}28872888static void ath12k_scan_timeout_work(struct work_struct *work)2889{2890struct ath12k *ar = container_of(work, struct ath12k,2891scan.timeout.work);28922893mutex_lock(&ar->conf_mutex);2894ath12k_scan_abort(ar);2895mutex_unlock(&ar->conf_mutex);2896}28972898static int ath12k_start_scan(struct ath12k *ar,2899struct ath12k_wmi_scan_req_arg *arg)2900{2901int ret;29022903lockdep_assert_held(&ar->conf_mutex);29042905ret = ath12k_wmi_send_scan_start_cmd(ar, arg);2906if (ret)2907return ret;29082909ret = wait_for_completion_timeout(&ar->scan.started, 1 * HZ);2910if (ret == 0) {2911ret = ath12k_scan_stop(ar);2912if (ret)2913ath12k_warn(ar->ab, "failed to stop scan: %d\n", ret);29142915return -ETIMEDOUT;2916}29172918/* If we failed to start the scan, return error code at2919* this point. This is probably due to some issue in the2920* firmware, but no need to wedge the driver due to that...2921*/2922spin_lock_bh(&ar->data_lock);2923if (ar->scan.state == ATH12K_SCAN_IDLE) {2924spin_unlock_bh(&ar->data_lock);2925return -EINVAL;2926}2927spin_unlock_bh(&ar->data_lock);29282929return 0;2930}29312932static int ath12k_mac_op_hw_scan(struct ieee80211_hw *hw,2933struct ieee80211_vif *vif,2934struct ieee80211_scan_request *hw_req)2935{2936struct ath12k *ar = hw->priv;2937struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);2938struct cfg80211_scan_request *req = &hw_req->req;2939struct ath12k_wmi_scan_req_arg arg = {};2940int ret;2941int i;29422943mutex_lock(&ar->conf_mutex);29442945spin_lock_bh(&ar->data_lock);2946switch (ar->scan.state) {2947case ATH12K_SCAN_IDLE:2948reinit_completion(&ar->scan.started);2949reinit_completion(&ar->scan.completed);2950ar->scan.state = ATH12K_SCAN_STARTING;2951ar->scan.is_roc = false;2952ar->scan.vdev_id = arvif->vdev_id;2953ret = 0;2954break;2955case ATH12K_SCAN_STARTING:2956case ATH12K_SCAN_RUNNING:2957case ATH12K_SCAN_ABORTING:2958ret = -EBUSY;2959break;2960}2961spin_unlock_bh(&ar->data_lock);29622963if (ret)2964goto exit;29652966ath12k_wmi_start_scan_init(ar, &arg);2967arg.vdev_id = arvif->vdev_id;2968arg.scan_id = ATH12K_SCAN_ID;29692970if (req->ie_len) {2971arg.extraie.ptr = kmemdup(req->ie, req->ie_len, GFP_KERNEL);2972if (!arg.extraie.ptr) {2973ret = -ENOMEM;2974goto exit;2975}2976arg.extraie.len = req->ie_len;2977}29782979if (req->n_ssids) {2980arg.num_ssids = req->n_ssids;2981for (i = 0; i < arg.num_ssids; i++)2982arg.ssid[i] = req->ssids[i];2983} else {2984arg.scan_flags |= WMI_SCAN_FLAG_PASSIVE;2985}29862987if (req->n_channels) {2988arg.num_chan = req->n_channels;2989arg.chan_list = kcalloc(arg.num_chan, sizeof(*arg.chan_list),2990GFP_KERNEL);29912992if (!arg.chan_list) {2993ret = -ENOMEM;2994goto exit;2995}29962997for (i = 0; i < arg.num_chan; i++)2998arg.chan_list[i] = req->channels[i]->center_freq;2999}30003001ret = ath12k_start_scan(ar, &arg);3002if (ret) {3003ath12k_warn(ar->ab, "failed to start hw scan: %d\n", ret);3004spin_lock_bh(&ar->data_lock);3005ar->scan.state = ATH12K_SCAN_IDLE;3006spin_unlock_bh(&ar->data_lock);3007}30083009/* Add a margin to account for event/command processing */3010ieee80211_queue_delayed_work(ar->hw, &ar->scan.timeout,3011msecs_to_jiffies(arg.max_scan_time +3012ATH12K_MAC_SCAN_TIMEOUT_MSECS));30133014exit:3015kfree(arg.chan_list);30163017if (req->ie_len)3018kfree(arg.extraie.ptr);30193020mutex_unlock(&ar->conf_mutex);3021return ret;3022}30233024static void ath12k_mac_op_cancel_hw_scan(struct ieee80211_hw *hw,3025struct ieee80211_vif *vif)3026{3027struct ath12k *ar = hw->priv;30283029mutex_lock(&ar->conf_mutex);3030ath12k_scan_abort(ar);3031mutex_unlock(&ar->conf_mutex);30323033cancel_delayed_work_sync(&ar->scan.timeout);3034}30353036static int ath12k_install_key(struct ath12k_vif *arvif,3037struct ieee80211_key_conf *key,3038enum set_key_cmd cmd,3039const u8 *macaddr, u32 flags)3040{3041int ret;3042struct ath12k *ar = arvif->ar;3043struct wmi_vdev_install_key_arg arg = {3044.vdev_id = arvif->vdev_id,3045.key_idx = key->keyidx,3046.key_len = key->keylen,3047.key_data = key->key,3048.key_flags = flags,3049.macaddr = macaddr,3050};30513052lockdep_assert_held(&arvif->ar->conf_mutex);30533054reinit_completion(&ar->install_key_done);30553056if (test_bit(ATH12K_FLAG_HW_CRYPTO_DISABLED, &ar->ab->dev_flags))3057return 0;30583059if (cmd == DISABLE_KEY) {3060/* TODO: Check if FW expects value other than NONE for del */3061/* arg.key_cipher = WMI_CIPHER_NONE; */3062arg.key_len = 0;3063arg.key_data = NULL;3064goto install;3065}30663067switch (key->cipher) {3068case WLAN_CIPHER_SUITE_CCMP:3069arg.key_cipher = WMI_CIPHER_AES_CCM;3070/* TODO: Re-check if flag is valid */3071key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV_MGMT;3072break;3073case WLAN_CIPHER_SUITE_TKIP:3074arg.key_cipher = WMI_CIPHER_TKIP;3075arg.key_txmic_len = 8;3076arg.key_rxmic_len = 8;3077break;3078case WLAN_CIPHER_SUITE_CCMP_256:3079arg.key_cipher = WMI_CIPHER_AES_CCM;3080break;3081case WLAN_CIPHER_SUITE_GCMP:3082case WLAN_CIPHER_SUITE_GCMP_256:3083arg.key_cipher = WMI_CIPHER_AES_GCM;3084break;3085default:3086ath12k_warn(ar->ab, "cipher %d is not supported\n", key->cipher);3087return -EOPNOTSUPP;3088}30893090if (test_bit(ATH12K_FLAG_RAW_MODE, &ar->ab->dev_flags))3091key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV |3092IEEE80211_KEY_FLAG_RESERVE_TAILROOM;30933094install:3095ret = ath12k_wmi_vdev_install_key(arvif->ar, &arg);30963097if (ret)3098return ret;30993100if (!wait_for_completion_timeout(&ar->install_key_done, 1 * HZ))3101return -ETIMEDOUT;31023103if (ether_addr_equal(macaddr, arvif->vif->addr))3104arvif->key_cipher = key->cipher;31053106return ar->install_key_status ? -EINVAL : 0;3107}31083109static int ath12k_clear_peer_keys(struct ath12k_vif *arvif,3110const u8 *addr)3111{3112struct ath12k *ar = arvif->ar;3113struct ath12k_base *ab = ar->ab;3114struct ath12k_peer *peer;3115int first_errno = 0;3116int ret;3117int i;3118u32 flags = 0;31193120lockdep_assert_held(&ar->conf_mutex);31213122spin_lock_bh(&ab->base_lock);3123peer = ath12k_peer_find(ab, arvif->vdev_id, addr);3124spin_unlock_bh(&ab->base_lock);31253126if (!peer)3127return -ENOENT;31283129for (i = 0; i < ARRAY_SIZE(peer->keys); i++) {3130if (!peer->keys[i])3131continue;31323133/* key flags are not required to delete the key */3134ret = ath12k_install_key(arvif, peer->keys[i],3135DISABLE_KEY, addr, flags);3136if (ret < 0 && first_errno == 0)3137first_errno = ret;31383139if (ret < 0)3140ath12k_warn(ab, "failed to remove peer key %d: %d\n",3141i, ret);31423143spin_lock_bh(&ab->base_lock);3144peer->keys[i] = NULL;3145spin_unlock_bh(&ab->base_lock);3146}31473148return first_errno;3149}31503151static int ath12k_mac_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,3152struct ieee80211_vif *vif, struct ieee80211_sta *sta,3153struct ieee80211_key_conf *key)3154{3155struct ath12k *ar = hw->priv;3156struct ath12k_base *ab = ar->ab;3157struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);3158struct ath12k_peer *peer;3159struct ath12k_sta *arsta;3160const u8 *peer_addr;3161int ret = 0;3162u32 flags = 0;31633164/* BIP needs to be done in software */3165if (key->cipher == WLAN_CIPHER_SUITE_AES_CMAC ||3166key->cipher == WLAN_CIPHER_SUITE_BIP_GMAC_128 ||3167key->cipher == WLAN_CIPHER_SUITE_BIP_GMAC_256 ||3168key->cipher == WLAN_CIPHER_SUITE_BIP_CMAC_256)3169return 1;31703171if (test_bit(ATH12K_FLAG_HW_CRYPTO_DISABLED, &ar->ab->dev_flags))3172return 1;31733174if (key->keyidx > WMI_MAX_KEY_INDEX)3175return -ENOSPC;31763177mutex_lock(&ar->conf_mutex);31783179if (sta)3180peer_addr = sta->addr;3181else if (arvif->vdev_type == WMI_VDEV_TYPE_STA)3182peer_addr = vif->bss_conf.bssid;3183else3184peer_addr = vif->addr;31853186key->hw_key_idx = key->keyidx;31873188/* the peer should not disappear in mid-way (unless FW goes awry) since3189* we already hold conf_mutex. we just make sure its there now.3190*/3191spin_lock_bh(&ab->base_lock);3192peer = ath12k_peer_find(ab, arvif->vdev_id, peer_addr);3193spin_unlock_bh(&ab->base_lock);31943195if (!peer) {3196if (cmd == SET_KEY) {3197ath12k_warn(ab, "cannot install key for non-existent peer %pM\n",3198peer_addr);3199ret = -EOPNOTSUPP;3200goto exit;3201} else {3202/* if the peer doesn't exist there is no key to disable3203* anymore3204*/3205goto exit;3206}3207}32083209if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE)3210flags |= WMI_KEY_PAIRWISE;3211else3212flags |= WMI_KEY_GROUP;32133214ret = ath12k_install_key(arvif, key, cmd, peer_addr, flags);3215if (ret) {3216ath12k_warn(ab, "ath12k_install_key failed (%d)\n", ret);3217goto exit;3218}32193220ret = ath12k_dp_rx_peer_pn_replay_config(arvif, peer_addr, cmd, key);3221if (ret) {3222ath12k_warn(ab, "failed to offload PN replay detection %d\n", ret);3223goto exit;3224}32253226spin_lock_bh(&ab->base_lock);3227peer = ath12k_peer_find(ab, arvif->vdev_id, peer_addr);3228if (peer && cmd == SET_KEY) {3229peer->keys[key->keyidx] = key;3230if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) {3231peer->ucast_keyidx = key->keyidx;3232peer->sec_type = ath12k_dp_tx_get_encrypt_type(key->cipher);3233} else {3234peer->mcast_keyidx = key->keyidx;3235peer->sec_type_grp = ath12k_dp_tx_get_encrypt_type(key->cipher);3236}3237} else if (peer && cmd == DISABLE_KEY) {3238peer->keys[key->keyidx] = NULL;3239if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE)3240peer->ucast_keyidx = 0;3241else3242peer->mcast_keyidx = 0;3243} else if (!peer)3244/* impossible unless FW goes crazy */3245ath12k_warn(ab, "peer %pM disappeared!\n", peer_addr);32463247if (sta) {3248arsta = (struct ath12k_sta *)sta->drv_priv;32493250switch (key->cipher) {3251case WLAN_CIPHER_SUITE_TKIP:3252case WLAN_CIPHER_SUITE_CCMP:3253case WLAN_CIPHER_SUITE_CCMP_256:3254case WLAN_CIPHER_SUITE_GCMP:3255case WLAN_CIPHER_SUITE_GCMP_256:3256if (cmd == SET_KEY)3257arsta->pn_type = HAL_PN_TYPE_WPA;3258else3259arsta->pn_type = HAL_PN_TYPE_NONE;3260break;3261default:3262arsta->pn_type = HAL_PN_TYPE_NONE;3263break;3264}3265}32663267spin_unlock_bh(&ab->base_lock);32683269exit:3270mutex_unlock(&ar->conf_mutex);3271return ret;3272}32733274static int3275ath12k_mac_bitrate_mask_num_vht_rates(struct ath12k *ar,3276enum nl80211_band band,3277const struct cfg80211_bitrate_mask *mask)3278{3279int num_rates = 0;3280int i;32813282for (i = 0; i < ARRAY_SIZE(mask->control[band].vht_mcs); i++)3283num_rates += hweight16(mask->control[band].vht_mcs[i]);32843285return num_rates;3286}32873288static int3289ath12k_mac_set_peer_vht_fixed_rate(struct ath12k_vif *arvif,3290struct ieee80211_sta *sta,3291const struct cfg80211_bitrate_mask *mask,3292enum nl80211_band band)3293{3294struct ath12k *ar = arvif->ar;3295u8 vht_rate, nss;3296u32 rate_code;3297int ret, i;32983299lockdep_assert_held(&ar->conf_mutex);33003301nss = 0;33023303for (i = 0; i < ARRAY_SIZE(mask->control[band].vht_mcs); i++) {3304if (hweight16(mask->control[band].vht_mcs[i]) == 1) {3305nss = i + 1;3306vht_rate = ffs(mask->control[band].vht_mcs[i]) - 1;3307}3308}33093310if (!nss) {3311ath12k_warn(ar->ab, "No single VHT Fixed rate found to set for %pM",3312sta->addr);3313return -EINVAL;3314}33153316ath12k_dbg(ar->ab, ATH12K_DBG_MAC,3317"Setting Fixed VHT Rate for peer %pM. Device will not switch to any other selected rates",3318sta->addr);33193320rate_code = ATH12K_HW_RATE_CODE(vht_rate, nss - 1,3321WMI_RATE_PREAMBLE_VHT);3322ret = ath12k_wmi_set_peer_param(ar, sta->addr,3323arvif->vdev_id,3324WMI_PEER_PARAM_FIXED_RATE,3325rate_code);3326if (ret)3327ath12k_warn(ar->ab,3328"failed to update STA %pM Fixed Rate %d: %d\n",3329sta->addr, rate_code, ret);33303331return ret;3332}33333334static int ath12k_station_assoc(struct ath12k *ar,3335struct ieee80211_vif *vif,3336struct ieee80211_sta *sta,3337bool reassoc)3338{3339struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);3340struct ath12k_wmi_peer_assoc_arg peer_arg;3341int ret;3342struct cfg80211_chan_def def;3343enum nl80211_band band;3344struct cfg80211_bitrate_mask *mask;3345u8 num_vht_rates;33463347lockdep_assert_held(&ar->conf_mutex);33483349if (WARN_ON(ath12k_mac_vif_chan(vif, &def)))3350return -EPERM;33513352band = def.chan->band;3353mask = &arvif->bitrate_mask;33543355ath12k_peer_assoc_prepare(ar, vif, sta, &peer_arg, reassoc);33563357ret = ath12k_wmi_send_peer_assoc_cmd(ar, &peer_arg);3358if (ret) {3359ath12k_warn(ar->ab, "failed to run peer assoc for STA %pM vdev %i: %d\n",3360sta->addr, arvif->vdev_id, ret);3361return ret;3362}33633364if (!wait_for_completion_timeout(&ar->peer_assoc_done, 1 * HZ)) {3365ath12k_warn(ar->ab, "failed to get peer assoc conf event for %pM vdev %i\n",3366sta->addr, arvif->vdev_id);3367return -ETIMEDOUT;3368}33693370num_vht_rates = ath12k_mac_bitrate_mask_num_vht_rates(ar, band, mask);33713372/* If single VHT rate is configured (by set_bitrate_mask()),3373* peer_assoc will disable VHT. This is now enabled by a peer specific3374* fixed param.3375* Note that all other rates and NSS will be disabled for this peer.3376*/3377if (sta->deflink.vht_cap.vht_supported && num_vht_rates == 1) {3378ret = ath12k_mac_set_peer_vht_fixed_rate(arvif, sta, mask,3379band);3380if (ret)3381return ret;3382}33833384/* Re-assoc is run only to update supported rates for given station. It3385* doesn't make much sense to reconfigure the peer completely.3386*/3387if (reassoc)3388return 0;33893390ret = ath12k_setup_peer_smps(ar, arvif, sta->addr,3391&sta->deflink.ht_cap);3392if (ret) {3393ath12k_warn(ar->ab, "failed to setup peer SMPS for vdev %d: %d\n",3394arvif->vdev_id, ret);3395return ret;3396}33973398if (!sta->wme) {3399arvif->num_legacy_stations++;3400ret = ath12k_recalc_rtscts_prot(arvif);3401if (ret)3402return ret;3403}34043405if (sta->wme && sta->uapsd_queues) {3406ret = ath12k_peer_assoc_qos_ap(ar, arvif, sta);3407if (ret) {3408ath12k_warn(ar->ab, "failed to set qos params for STA %pM for vdev %i: %d\n",3409sta->addr, arvif->vdev_id, ret);3410return ret;3411}3412}34133414return 0;3415}34163417static int ath12k_station_disassoc(struct ath12k *ar,3418struct ieee80211_vif *vif,3419struct ieee80211_sta *sta)3420{3421struct ath12k_vif *arvif = (void *)vif->drv_priv;3422int ret;34233424lockdep_assert_held(&ar->conf_mutex);34253426if (!sta->wme) {3427arvif->num_legacy_stations--;3428ret = ath12k_recalc_rtscts_prot(arvif);3429if (ret)3430return ret;3431}34323433ret = ath12k_clear_peer_keys(arvif, sta->addr);3434if (ret) {3435ath12k_warn(ar->ab, "failed to clear all peer keys for vdev %i: %d\n",3436arvif->vdev_id, ret);3437return ret;3438}3439return 0;3440}34413442static void ath12k_sta_rc_update_wk(struct work_struct *wk)3443{3444struct ath12k *ar;3445struct ath12k_vif *arvif;3446struct ath12k_sta *arsta;3447struct ieee80211_sta *sta;3448struct cfg80211_chan_def def;3449enum nl80211_band band;3450const u8 *ht_mcs_mask;3451const u16 *vht_mcs_mask;3452u32 changed, bw, nss, smps, bw_prev;3453int err, num_vht_rates;3454const struct cfg80211_bitrate_mask *mask;3455struct ath12k_wmi_peer_assoc_arg peer_arg;3456enum wmi_phy_mode peer_phymode;34573458arsta = container_of(wk, struct ath12k_sta, update_wk);3459sta = container_of((void *)arsta, struct ieee80211_sta, drv_priv);3460arvif = arsta->arvif;3461ar = arvif->ar;34623463if (WARN_ON(ath12k_mac_vif_chan(arvif->vif, &def)))3464return;34653466band = def.chan->band;3467ht_mcs_mask = arvif->bitrate_mask.control[band].ht_mcs;3468vht_mcs_mask = arvif->bitrate_mask.control[band].vht_mcs;34693470spin_lock_bh(&ar->data_lock);34713472changed = arsta->changed;3473arsta->changed = 0;34743475bw = arsta->bw;3476bw_prev = arsta->bw_prev;3477nss = arsta->nss;3478smps = arsta->smps;34793480spin_unlock_bh(&ar->data_lock);34813482mutex_lock(&ar->conf_mutex);34833484nss = max_t(u32, 1, nss);3485nss = min(nss, max(ath12k_mac_max_ht_nss(ht_mcs_mask),3486ath12k_mac_max_vht_nss(vht_mcs_mask)));34873488if (changed & IEEE80211_RC_BW_CHANGED) {3489ath12k_peer_assoc_h_phymode(ar, arvif->vif, sta, &peer_arg);3490peer_phymode = peer_arg.peer_phymode;34913492if (bw > bw_prev) {3493/* Phymode shows maximum supported channel width, if we3494* upgrade bandwidth then due to sanity check of firmware,3495* we have to send WMI_PEER_PHYMODE followed by3496* WMI_PEER_CHWIDTH3497*/3498ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac bandwidth upgrade for sta %pM new %d old %d\n",3499sta->addr, bw, bw_prev);3500err = ath12k_wmi_set_peer_param(ar, sta->addr,3501arvif->vdev_id, WMI_PEER_PHYMODE,3502peer_phymode);3503if (err) {3504ath12k_warn(ar->ab, "failed to update STA %pM to peer phymode %d: %d\n",3505sta->addr, peer_phymode, err);3506goto err_rc_bw_changed;3507}3508err = ath12k_wmi_set_peer_param(ar, sta->addr,3509arvif->vdev_id, WMI_PEER_CHWIDTH,3510bw);3511if (err)3512ath12k_warn(ar->ab, "failed to update STA %pM to peer bandwidth %d: %d\n",3513sta->addr, bw, err);3514} else {3515/* When we downgrade bandwidth this will conflict with phymode3516* and cause to trigger firmware crash. In this case we send3517* WMI_PEER_CHWIDTH followed by WMI_PEER_PHYMODE3518*/3519ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac bandwidth downgrade for sta %pM new %d old %d\n",3520sta->addr, bw, bw_prev);3521err = ath12k_wmi_set_peer_param(ar, sta->addr,3522arvif->vdev_id, WMI_PEER_CHWIDTH,3523bw);3524if (err) {3525ath12k_warn(ar->ab, "failed to update STA %pM peer to bandwidth %d: %d\n",3526sta->addr, bw, err);3527goto err_rc_bw_changed;3528}3529err = ath12k_wmi_set_peer_param(ar, sta->addr,3530arvif->vdev_id, WMI_PEER_PHYMODE,3531peer_phymode);3532if (err)3533ath12k_warn(ar->ab, "failed to update STA %pM to peer phymode %d: %d\n",3534sta->addr, peer_phymode, err);3535}3536}35373538if (changed & IEEE80211_RC_NSS_CHANGED) {3539ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac update sta %pM nss %d\n",3540sta->addr, nss);35413542err = ath12k_wmi_set_peer_param(ar, sta->addr, arvif->vdev_id,3543WMI_PEER_NSS, nss);3544if (err)3545ath12k_warn(ar->ab, "failed to update STA %pM nss %d: %d\n",3546sta->addr, nss, err);3547}35483549if (changed & IEEE80211_RC_SMPS_CHANGED) {3550ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac update sta %pM smps %d\n",3551sta->addr, smps);35523553err = ath12k_wmi_set_peer_param(ar, sta->addr, arvif->vdev_id,3554WMI_PEER_MIMO_PS_STATE, smps);3555if (err)3556ath12k_warn(ar->ab, "failed to update STA %pM smps %d: %d\n",3557sta->addr, smps, err);3558}35593560if (changed & IEEE80211_RC_SUPP_RATES_CHANGED) {3561mask = &arvif->bitrate_mask;3562num_vht_rates = ath12k_mac_bitrate_mask_num_vht_rates(ar, band,3563mask);35643565/* Peer_assoc_prepare will reject vht rates in3566* bitrate_mask if its not available in range format and3567* sets vht tx_rateset as unsupported. So multiple VHT MCS3568* setting(eg. MCS 4,5,6) per peer is not supported here.3569* But, Single rate in VHT mask can be set as per-peer3570* fixed rate. But even if any HT rates are configured in3571* the bitrate mask, device will not switch to those rates3572* when per-peer Fixed rate is set.3573* TODO: Check RATEMASK_CMDID to support auto rates selection3574* across HT/VHT and for multiple VHT MCS support.3575*/3576if (sta->deflink.vht_cap.vht_supported && num_vht_rates == 1) {3577ath12k_mac_set_peer_vht_fixed_rate(arvif, sta, mask,3578band);3579} else {3580/* If the peer is non-VHT or no fixed VHT rate3581* is provided in the new bitrate mask we set the3582* other rates using peer_assoc command.3583*/3584ath12k_peer_assoc_prepare(ar, arvif->vif, sta,3585&peer_arg, true);35863587err = ath12k_wmi_send_peer_assoc_cmd(ar, &peer_arg);3588if (err)3589ath12k_warn(ar->ab, "failed to run peer assoc for STA %pM vdev %i: %d\n",3590sta->addr, arvif->vdev_id, err);35913592if (!wait_for_completion_timeout(&ar->peer_assoc_done, 1 * HZ))3593ath12k_warn(ar->ab, "failed to get peer assoc conf event for %pM vdev %i\n",3594sta->addr, arvif->vdev_id);3595}3596}3597err_rc_bw_changed:3598mutex_unlock(&ar->conf_mutex);3599}36003601static int ath12k_mac_inc_num_stations(struct ath12k_vif *arvif,3602struct ieee80211_sta *sta)3603{3604struct ath12k *ar = arvif->ar;36053606lockdep_assert_held(&ar->conf_mutex);36073608if (arvif->vdev_type == WMI_VDEV_TYPE_STA && !sta->tdls)3609return 0;36103611if (ar->num_stations >= ar->max_num_stations)3612return -ENOBUFS;36133614ar->num_stations++;36153616return 0;3617}36183619static void ath12k_mac_dec_num_stations(struct ath12k_vif *arvif,3620struct ieee80211_sta *sta)3621{3622struct ath12k *ar = arvif->ar;36233624lockdep_assert_held(&ar->conf_mutex);36253626if (arvif->vdev_type == WMI_VDEV_TYPE_STA && !sta->tdls)3627return;36283629ar->num_stations--;3630}36313632static int ath12k_mac_station_add(struct ath12k *ar,3633struct ieee80211_vif *vif,3634struct ieee80211_sta *sta)3635{3636struct ath12k_base *ab = ar->ab;3637struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);3638struct ath12k_sta *arsta = (struct ath12k_sta *)sta->drv_priv;3639struct ath12k_wmi_peer_create_arg peer_param;3640int ret;36413642lockdep_assert_held(&ar->conf_mutex);36433644ret = ath12k_mac_inc_num_stations(arvif, sta);3645if (ret) {3646ath12k_warn(ab, "refusing to associate station: too many connected already (%d)\n",3647ar->max_num_stations);3648goto exit;3649}36503651arsta->rx_stats = kzalloc(sizeof(*arsta->rx_stats), GFP_KERNEL);3652if (!arsta->rx_stats) {3653ret = -ENOMEM;3654goto dec_num_station;3655}36563657peer_param.vdev_id = arvif->vdev_id;3658peer_param.peer_addr = sta->addr;3659peer_param.peer_type = WMI_PEER_TYPE_DEFAULT;36603661ret = ath12k_peer_create(ar, arvif, sta, &peer_param);3662if (ret) {3663ath12k_warn(ab, "Failed to add peer: %pM for VDEV: %d\n",3664sta->addr, arvif->vdev_id);3665goto free_peer;3666}36673668ath12k_dbg(ab, ATH12K_DBG_MAC, "Added peer: %pM for VDEV: %d\n",3669sta->addr, arvif->vdev_id);36703671if (ieee80211_vif_is_mesh(vif)) {3672ret = ath12k_wmi_set_peer_param(ar, sta->addr,3673arvif->vdev_id,3674WMI_PEER_USE_4ADDR, 1);3675if (ret) {3676ath12k_warn(ab, "failed to STA %pM 4addr capability: %d\n",3677sta->addr, ret);3678goto free_peer;3679}3680}36813682ret = ath12k_dp_peer_setup(ar, arvif->vdev_id, sta->addr);3683if (ret) {3684ath12k_warn(ab, "failed to setup dp for peer %pM on vdev %i (%d)\n",3685sta->addr, arvif->vdev_id, ret);3686goto free_peer;3687}36883689if (ab->hw_params->vdev_start_delay &&3690!arvif->is_started &&3691arvif->vdev_type != WMI_VDEV_TYPE_AP) {3692ret = ath12k_start_vdev_delay(ar->hw, vif);3693if (ret) {3694ath12k_warn(ab, "failed to delay vdev start: %d\n", ret);3695goto free_peer;3696}3697}36983699return 0;37003701free_peer:3702ath12k_peer_delete(ar, arvif->vdev_id, sta->addr);3703dec_num_station:3704ath12k_mac_dec_num_stations(arvif, sta);3705exit:3706return ret;3707}37083709static u32 ath12k_mac_ieee80211_sta_bw_to_wmi(struct ath12k *ar,3710struct ieee80211_sta *sta)3711{3712u32 bw = WMI_PEER_CHWIDTH_20MHZ;37133714switch (sta->deflink.bandwidth) {3715case IEEE80211_STA_RX_BW_20:3716bw = WMI_PEER_CHWIDTH_20MHZ;3717break;3718case IEEE80211_STA_RX_BW_40:3719bw = WMI_PEER_CHWIDTH_40MHZ;3720break;3721case IEEE80211_STA_RX_BW_80:3722bw = WMI_PEER_CHWIDTH_80MHZ;3723break;3724case IEEE80211_STA_RX_BW_160:3725bw = WMI_PEER_CHWIDTH_160MHZ;3726break;3727default:3728ath12k_warn(ar->ab, "Invalid bandwidth %d in rc update for %pM\n",3729sta->deflink.bandwidth, sta->addr);3730bw = WMI_PEER_CHWIDTH_20MHZ;3731break;3732}37333734return bw;3735}37363737static int ath12k_mac_op_sta_state(struct ieee80211_hw *hw,3738struct ieee80211_vif *vif,3739struct ieee80211_sta *sta,3740enum ieee80211_sta_state old_state,3741enum ieee80211_sta_state new_state)3742{3743struct ath12k *ar = hw->priv;3744struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);3745struct ath12k_sta *arsta = (struct ath12k_sta *)sta->drv_priv;3746struct ath12k_peer *peer;3747int ret = 0;37483749/* cancel must be done outside the mutex to avoid deadlock */3750if ((old_state == IEEE80211_STA_NONE &&3751new_state == IEEE80211_STA_NOTEXIST))3752cancel_work_sync(&arsta->update_wk);37533754mutex_lock(&ar->conf_mutex);37553756if (old_state == IEEE80211_STA_NOTEXIST &&3757new_state == IEEE80211_STA_NONE) {3758memset(arsta, 0, sizeof(*arsta));3759arsta->arvif = arvif;3760INIT_WORK(&arsta->update_wk, ath12k_sta_rc_update_wk);37613762ret = ath12k_mac_station_add(ar, vif, sta);3763if (ret)3764ath12k_warn(ar->ab, "Failed to add station: %pM for VDEV: %d\n",3765sta->addr, arvif->vdev_id);3766} else if ((old_state == IEEE80211_STA_NONE &&3767new_state == IEEE80211_STA_NOTEXIST)) {3768ath12k_dp_peer_cleanup(ar, arvif->vdev_id, sta->addr);37693770ret = ath12k_peer_delete(ar, arvif->vdev_id, sta->addr);3771if (ret)3772ath12k_warn(ar->ab, "Failed to delete peer: %pM for VDEV: %d\n",3773sta->addr, arvif->vdev_id);3774else3775ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "Removed peer: %pM for VDEV: %d\n",3776sta->addr, arvif->vdev_id);37773778ath12k_mac_dec_num_stations(arvif, sta);3779spin_lock_bh(&ar->ab->base_lock);3780peer = ath12k_peer_find(ar->ab, arvif->vdev_id, sta->addr);3781if (peer && peer->sta == sta) {3782ath12k_warn(ar->ab, "Found peer entry %pM n vdev %i after it was supposedly removed\n",3783vif->addr, arvif->vdev_id);3784peer->sta = NULL;3785list_del(&peer->list);3786kfree(peer);3787ar->num_peers--;3788}3789spin_unlock_bh(&ar->ab->base_lock);37903791kfree(arsta->rx_stats);3792arsta->rx_stats = NULL;3793} else if (old_state == IEEE80211_STA_AUTH &&3794new_state == IEEE80211_STA_ASSOC &&3795(vif->type == NL80211_IFTYPE_AP ||3796vif->type == NL80211_IFTYPE_MESH_POINT ||3797vif->type == NL80211_IFTYPE_ADHOC)) {3798ret = ath12k_station_assoc(ar, vif, sta, false);3799if (ret)3800ath12k_warn(ar->ab, "Failed to associate station: %pM\n",3801sta->addr);38023803spin_lock_bh(&ar->data_lock);38043805arsta->bw = ath12k_mac_ieee80211_sta_bw_to_wmi(ar, sta);3806arsta->bw_prev = sta->deflink.bandwidth;38073808spin_unlock_bh(&ar->data_lock);3809} else if (old_state == IEEE80211_STA_ASSOC &&3810new_state == IEEE80211_STA_AUTHORIZED) {3811spin_lock_bh(&ar->ab->base_lock);38123813peer = ath12k_peer_find(ar->ab, arvif->vdev_id, sta->addr);3814if (peer)3815peer->is_authorized = true;38163817spin_unlock_bh(&ar->ab->base_lock);38183819if (vif->type == NL80211_IFTYPE_STATION && arvif->is_up) {3820ret = ath12k_wmi_set_peer_param(ar, sta->addr,3821arvif->vdev_id,3822WMI_PEER_AUTHORIZE,38231);3824if (ret)3825ath12k_warn(ar->ab, "Unable to authorize peer %pM vdev %d: %d\n",3826sta->addr, arvif->vdev_id, ret);3827}3828} else if (old_state == IEEE80211_STA_AUTHORIZED &&3829new_state == IEEE80211_STA_ASSOC) {3830spin_lock_bh(&ar->ab->base_lock);38313832peer = ath12k_peer_find(ar->ab, arvif->vdev_id, sta->addr);3833if (peer)3834peer->is_authorized = false;38353836spin_unlock_bh(&ar->ab->base_lock);3837} else if (old_state == IEEE80211_STA_ASSOC &&3838new_state == IEEE80211_STA_AUTH &&3839(vif->type == NL80211_IFTYPE_AP ||3840vif->type == NL80211_IFTYPE_MESH_POINT ||3841vif->type == NL80211_IFTYPE_ADHOC)) {3842ret = ath12k_station_disassoc(ar, vif, sta);3843if (ret)3844ath12k_warn(ar->ab, "Failed to disassociate station: %pM\n",3845sta->addr);3846}38473848mutex_unlock(&ar->conf_mutex);3849return ret;3850}38513852static int ath12k_mac_op_sta_set_txpwr(struct ieee80211_hw *hw,3853struct ieee80211_vif *vif,3854struct ieee80211_sta *sta)3855{3856struct ath12k *ar = hw->priv;3857struct ath12k_vif *arvif = (void *)vif->drv_priv;3858int ret;3859s16 txpwr;38603861if (sta->deflink.txpwr.type == NL80211_TX_POWER_AUTOMATIC) {3862txpwr = 0;3863} else {3864txpwr = sta->deflink.txpwr.power;3865if (!txpwr)3866return -EINVAL;3867}38683869if (txpwr > ATH12K_TX_POWER_MAX_VAL || txpwr < ATH12K_TX_POWER_MIN_VAL)3870return -EINVAL;38713872mutex_lock(&ar->conf_mutex);38733874ret = ath12k_wmi_set_peer_param(ar, sta->addr, arvif->vdev_id,3875WMI_PEER_USE_FIXED_PWR, txpwr);3876if (ret) {3877ath12k_warn(ar->ab, "failed to set tx power for station ret: %d\n",3878ret);3879goto out;3880}38813882out:3883mutex_unlock(&ar->conf_mutex);3884return ret;3885}38863887static void ath12k_mac_op_sta_rc_update(struct ieee80211_hw *hw,3888struct ieee80211_vif *vif,3889struct ieee80211_sta *sta,3890u32 changed)3891{3892struct ath12k *ar = hw->priv;3893struct ath12k_sta *arsta = (struct ath12k_sta *)sta->drv_priv;3894struct ath12k_vif *arvif = (void *)vif->drv_priv;3895struct ath12k_peer *peer;3896u32 bw, smps;38973898spin_lock_bh(&ar->ab->base_lock);38993900peer = ath12k_peer_find(ar->ab, arvif->vdev_id, sta->addr);3901if (!peer) {3902spin_unlock_bh(&ar->ab->base_lock);3903ath12k_warn(ar->ab, "mac sta rc update failed to find peer %pM on vdev %i\n",3904sta->addr, arvif->vdev_id);3905return;3906}39073908spin_unlock_bh(&ar->ab->base_lock);39093910ath12k_dbg(ar->ab, ATH12K_DBG_MAC,3911"mac sta rc update for %pM changed %08x bw %d nss %d smps %d\n",3912sta->addr, changed, sta->deflink.bandwidth, sta->deflink.rx_nss,3913sta->deflink.smps_mode);39143915spin_lock_bh(&ar->data_lock);39163917if (changed & IEEE80211_RC_BW_CHANGED) {3918bw = ath12k_mac_ieee80211_sta_bw_to_wmi(ar, sta);3919arsta->bw_prev = arsta->bw;3920arsta->bw = bw;3921}39223923if (changed & IEEE80211_RC_NSS_CHANGED)3924arsta->nss = sta->deflink.rx_nss;39253926if (changed & IEEE80211_RC_SMPS_CHANGED) {3927smps = WMI_PEER_SMPS_PS_NONE;39283929switch (sta->deflink.smps_mode) {3930case IEEE80211_SMPS_AUTOMATIC:3931case IEEE80211_SMPS_OFF:3932smps = WMI_PEER_SMPS_PS_NONE;3933break;3934case IEEE80211_SMPS_STATIC:3935smps = WMI_PEER_SMPS_STATIC;3936break;3937case IEEE80211_SMPS_DYNAMIC:3938smps = WMI_PEER_SMPS_DYNAMIC;3939break;3940default:3941ath12k_warn(ar->ab, "Invalid smps %d in sta rc update for %pM\n",3942sta->deflink.smps_mode, sta->addr);3943smps = WMI_PEER_SMPS_PS_NONE;3944break;3945}39463947arsta->smps = smps;3948}39493950arsta->changed |= changed;39513952spin_unlock_bh(&ar->data_lock);39533954ieee80211_queue_work(hw, &arsta->update_wk);3955}39563957static int ath12k_conf_tx_uapsd(struct ath12k *ar, struct ieee80211_vif *vif,3958u16 ac, bool enable)3959{3960struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);3961u32 value;3962int ret;39633964if (arvif->vdev_type != WMI_VDEV_TYPE_STA)3965return 0;39663967switch (ac) {3968case IEEE80211_AC_VO:3969value = WMI_STA_PS_UAPSD_AC3_DELIVERY_EN |3970WMI_STA_PS_UAPSD_AC3_TRIGGER_EN;3971break;3972case IEEE80211_AC_VI:3973value = WMI_STA_PS_UAPSD_AC2_DELIVERY_EN |3974WMI_STA_PS_UAPSD_AC2_TRIGGER_EN;3975break;3976case IEEE80211_AC_BE:3977value = WMI_STA_PS_UAPSD_AC1_DELIVERY_EN |3978WMI_STA_PS_UAPSD_AC1_TRIGGER_EN;3979break;3980case IEEE80211_AC_BK:3981value = WMI_STA_PS_UAPSD_AC0_DELIVERY_EN |3982WMI_STA_PS_UAPSD_AC0_TRIGGER_EN;3983break;3984}39853986if (enable)3987arvif->u.sta.uapsd |= value;3988else3989arvif->u.sta.uapsd &= ~value;39903991ret = ath12k_wmi_set_sta_ps_param(ar, arvif->vdev_id,3992WMI_STA_PS_PARAM_UAPSD,3993arvif->u.sta.uapsd);3994if (ret) {3995ath12k_warn(ar->ab, "could not set uapsd params %d\n", ret);3996goto exit;3997}39983999if (arvif->u.sta.uapsd)4000value = WMI_STA_PS_RX_WAKE_POLICY_POLL_UAPSD;4001else4002value = WMI_STA_PS_RX_WAKE_POLICY_WAKE;40034004ret = ath12k_wmi_set_sta_ps_param(ar, arvif->vdev_id,4005WMI_STA_PS_PARAM_RX_WAKE_POLICY,4006value);4007if (ret)4008ath12k_warn(ar->ab, "could not set rx wake param %d\n", ret);40094010exit:4011return ret;4012}40134014static int ath12k_mac_op_conf_tx(struct ieee80211_hw *hw,4015struct ieee80211_vif *vif,4016unsigned int link_id, u16 ac,4017const struct ieee80211_tx_queue_params *params)4018{4019struct ath12k *ar = hw->priv;4020struct ath12k_vif *arvif = (void *)vif->drv_priv;4021struct wmi_wmm_params_arg *p = NULL;4022int ret;40234024mutex_lock(&ar->conf_mutex);40254026switch (ac) {4027case IEEE80211_AC_VO:4028p = &arvif->wmm_params.ac_vo;4029break;4030case IEEE80211_AC_VI:4031p = &arvif->wmm_params.ac_vi;4032break;4033case IEEE80211_AC_BE:4034p = &arvif->wmm_params.ac_be;4035break;4036case IEEE80211_AC_BK:4037p = &arvif->wmm_params.ac_bk;4038break;4039}40404041if (WARN_ON(!p)) {4042ret = -EINVAL;4043goto exit;4044}40454046p->cwmin = params->cw_min;4047p->cwmax = params->cw_max;4048p->aifs = params->aifs;4049p->txop = params->txop;40504051ret = ath12k_wmi_send_wmm_update_cmd(ar, arvif->vdev_id,4052&arvif->wmm_params);4053if (ret) {4054ath12k_warn(ar->ab, "failed to set wmm params: %d\n", ret);4055goto exit;4056}40574058ret = ath12k_conf_tx_uapsd(ar, vif, ac, params->uapsd);40594060if (ret)4061ath12k_warn(ar->ab, "failed to set sta uapsd: %d\n", ret);40624063exit:4064mutex_unlock(&ar->conf_mutex);4065return ret;4066}40674068static struct ieee80211_sta_ht_cap4069ath12k_create_ht_cap(struct ath12k *ar, u32 ar_ht_cap, u32 rate_cap_rx_chainmask)4070{4071int i;4072struct ieee80211_sta_ht_cap ht_cap = {0};4073u32 ar_vht_cap = ar->pdev->cap.vht_cap;40744075if (!(ar_ht_cap & WMI_HT_CAP_ENABLED))4076return ht_cap;40774078ht_cap.ht_supported = 1;4079ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;4080ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_NONE;4081ht_cap.cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40;4082ht_cap.cap |= IEEE80211_HT_CAP_DSSSCCK40;4083ht_cap.cap |= WLAN_HT_CAP_SM_PS_STATIC << IEEE80211_HT_CAP_SM_PS_SHIFT;40844085if (ar_ht_cap & WMI_HT_CAP_HT20_SGI)4086ht_cap.cap |= IEEE80211_HT_CAP_SGI_20;40874088if (ar_ht_cap & WMI_HT_CAP_HT40_SGI)4089ht_cap.cap |= IEEE80211_HT_CAP_SGI_40;40904091if (ar_ht_cap & WMI_HT_CAP_DYNAMIC_SMPS) {4092u32 smps;40934094smps = WLAN_HT_CAP_SM_PS_DYNAMIC;4095smps <<= IEEE80211_HT_CAP_SM_PS_SHIFT;40964097ht_cap.cap |= smps;4098}40994100if (ar_ht_cap & WMI_HT_CAP_TX_STBC)4101ht_cap.cap |= IEEE80211_HT_CAP_TX_STBC;41024103if (ar_ht_cap & WMI_HT_CAP_RX_STBC) {4104u32 stbc;41054106stbc = ar_ht_cap;4107stbc &= WMI_HT_CAP_RX_STBC;4108stbc >>= WMI_HT_CAP_RX_STBC_MASK_SHIFT;4109stbc <<= IEEE80211_HT_CAP_RX_STBC_SHIFT;4110stbc &= IEEE80211_HT_CAP_RX_STBC;41114112ht_cap.cap |= stbc;4113}41144115if (ar_ht_cap & WMI_HT_CAP_RX_LDPC)4116ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING;41174118if (ar_ht_cap & WMI_HT_CAP_L_SIG_TXOP_PROT)4119ht_cap.cap |= IEEE80211_HT_CAP_LSIG_TXOP_PROT;41204121if (ar_vht_cap & WMI_VHT_CAP_MAX_MPDU_LEN_MASK)4122ht_cap.cap |= IEEE80211_HT_CAP_MAX_AMSDU;41234124for (i = 0; i < ar->num_rx_chains; i++) {4125if (rate_cap_rx_chainmask & BIT(i))4126ht_cap.mcs.rx_mask[i] = 0xFF;4127}41284129ht_cap.mcs.tx_params |= IEEE80211_HT_MCS_TX_DEFINED;41304131return ht_cap;4132}41334134static int ath12k_mac_set_txbf_conf(struct ath12k_vif *arvif)4135{4136u32 value = 0;4137struct ath12k *ar = arvif->ar;4138int nsts;4139int sound_dim;4140u32 vht_cap = ar->pdev->cap.vht_cap;4141u32 vdev_param = WMI_VDEV_PARAM_TXBF;41424143if (vht_cap & (IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE)) {4144nsts = vht_cap & IEEE80211_VHT_CAP_BEAMFORMEE_STS_MASK;4145nsts >>= IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT;4146value |= SM(nsts, WMI_TXBF_STS_CAP_OFFSET);4147}41484149if (vht_cap & (IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE)) {4150sound_dim = vht_cap &4151IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK;4152sound_dim >>= IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_SHIFT;4153if (sound_dim > (ar->num_tx_chains - 1))4154sound_dim = ar->num_tx_chains - 1;4155value |= SM(sound_dim, WMI_BF_SOUND_DIM_OFFSET);4156}41574158if (!value)4159return 0;41604161if (vht_cap & IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE) {4162value |= WMI_VDEV_PARAM_TXBF_SU_TX_BFER;41634164if ((vht_cap & IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE) &&4165arvif->vdev_type == WMI_VDEV_TYPE_AP)4166value |= WMI_VDEV_PARAM_TXBF_MU_TX_BFER;4167}41684169if (vht_cap & IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE) {4170value |= WMI_VDEV_PARAM_TXBF_SU_TX_BFEE;41714172if ((vht_cap & IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE) &&4173arvif->vdev_type == WMI_VDEV_TYPE_STA)4174value |= WMI_VDEV_PARAM_TXBF_MU_TX_BFEE;4175}41764177return ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,4178vdev_param, value);4179}41804181static void ath12k_set_vht_txbf_cap(struct ath12k *ar, u32 *vht_cap)4182{4183bool subfer, subfee;4184int sound_dim = 0;41854186subfer = !!(*vht_cap & (IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE));4187subfee = !!(*vht_cap & (IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE));41884189if (ar->num_tx_chains < 2) {4190*vht_cap &= ~(IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE);4191subfer = false;4192}41934194/* If SU Beaformer is not set, then disable MU Beamformer Capability */4195if (!subfer)4196*vht_cap &= ~(IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE);41974198/* If SU Beaformee is not set, then disable MU Beamformee Capability */4199if (!subfee)4200*vht_cap &= ~(IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE);42014202sound_dim = u32_get_bits(*vht_cap,4203IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK);4204*vht_cap = u32_replace_bits(*vht_cap, 0,4205IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK);42064207/* TODO: Need to check invalid STS and Sound_dim values set by FW? */42084209/* Enable Sounding Dimension Field only if SU BF is enabled */4210if (subfer) {4211if (sound_dim > (ar->num_tx_chains - 1))4212sound_dim = ar->num_tx_chains - 1;42134214*vht_cap = u32_replace_bits(*vht_cap, sound_dim,4215IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK);4216}42174218/* Use the STS advertised by FW unless SU Beamformee is not supported*/4219if (!subfee)4220*vht_cap &= ~(IEEE80211_VHT_CAP_BEAMFORMEE_STS_MASK);4221}42224223static struct ieee80211_sta_vht_cap4224ath12k_create_vht_cap(struct ath12k *ar, u32 rate_cap_tx_chainmask,4225u32 rate_cap_rx_chainmask)4226{4227struct ieee80211_sta_vht_cap vht_cap = {0};4228u16 txmcs_map, rxmcs_map;4229int i;42304231vht_cap.vht_supported = 1;4232vht_cap.cap = ar->pdev->cap.vht_cap;42334234ath12k_set_vht_txbf_cap(ar, &vht_cap.cap);42354236/* TODO: Enable back VHT160 mode once association issues are fixed */4237/* Disabling VHT160 and VHT80+80 modes */4238vht_cap.cap &= ~IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK;4239vht_cap.cap &= ~IEEE80211_VHT_CAP_SHORT_GI_160;42404241rxmcs_map = 0;4242txmcs_map = 0;4243for (i = 0; i < 8; i++) {4244if (i < ar->num_tx_chains && rate_cap_tx_chainmask & BIT(i))4245txmcs_map |= IEEE80211_VHT_MCS_SUPPORT_0_9 << (i * 2);4246else4247txmcs_map |= IEEE80211_VHT_MCS_NOT_SUPPORTED << (i * 2);42484249if (i < ar->num_rx_chains && rate_cap_rx_chainmask & BIT(i))4250rxmcs_map |= IEEE80211_VHT_MCS_SUPPORT_0_9 << (i * 2);4251else4252rxmcs_map |= IEEE80211_VHT_MCS_NOT_SUPPORTED << (i * 2);4253}42544255if (rate_cap_tx_chainmask <= 1)4256vht_cap.cap &= ~IEEE80211_VHT_CAP_TXSTBC;42574258vht_cap.vht_mcs.rx_mcs_map = cpu_to_le16(rxmcs_map);4259vht_cap.vht_mcs.tx_mcs_map = cpu_to_le16(txmcs_map);42604261return vht_cap;4262}42634264static void ath12k_mac_setup_ht_vht_cap(struct ath12k *ar,4265struct ath12k_pdev_cap *cap,4266u32 *ht_cap_info)4267{4268struct ieee80211_supported_band *band;4269u32 rate_cap_tx_chainmask;4270u32 rate_cap_rx_chainmask;4271u32 ht_cap;42724273rate_cap_tx_chainmask = ar->cfg_tx_chainmask >> cap->tx_chain_mask_shift;4274rate_cap_rx_chainmask = ar->cfg_rx_chainmask >> cap->rx_chain_mask_shift;42754276if (cap->supported_bands & WMI_HOST_WLAN_2G_CAP) {4277band = &ar->mac.sbands[NL80211_BAND_2GHZ];4278ht_cap = cap->band[NL80211_BAND_2GHZ].ht_cap_info;4279if (ht_cap_info)4280*ht_cap_info = ht_cap;4281band->ht_cap = ath12k_create_ht_cap(ar, ht_cap,4282rate_cap_rx_chainmask);4283}42844285if (cap->supported_bands & WMI_HOST_WLAN_5G_CAP &&4286(ar->ab->hw_params->single_pdev_only ||4287!ar->supports_6ghz)) {4288band = &ar->mac.sbands[NL80211_BAND_5GHZ];4289ht_cap = cap->band[NL80211_BAND_5GHZ].ht_cap_info;4290if (ht_cap_info)4291*ht_cap_info = ht_cap;4292band->ht_cap = ath12k_create_ht_cap(ar, ht_cap,4293rate_cap_rx_chainmask);4294band->vht_cap = ath12k_create_vht_cap(ar, rate_cap_tx_chainmask,4295rate_cap_rx_chainmask);4296}4297}42984299static int ath12k_check_chain_mask(struct ath12k *ar, u32 ant, bool is_tx_ant)4300{4301/* TODO: Check the request chainmask against the supported4302* chainmask table which is advertised in extented_service_ready event4303*/43044305return 0;4306}43074308static void ath12k_gen_ppe_thresh(struct ath12k_wmi_ppe_threshold_arg *fw_ppet,4309u8 *he_ppet)4310{4311int nss, ru;4312u8 bit = 7;43134314he_ppet[0] = fw_ppet->numss_m1 & IEEE80211_PPE_THRES_NSS_MASK;4315he_ppet[0] |= (fw_ppet->ru_bit_mask <<4316IEEE80211_PPE_THRES_RU_INDEX_BITMASK_POS) &4317IEEE80211_PPE_THRES_RU_INDEX_BITMASK_MASK;4318for (nss = 0; nss <= fw_ppet->numss_m1; nss++) {4319for (ru = 0; ru < 4; ru++) {4320u8 val;4321int i;43224323if ((fw_ppet->ru_bit_mask & BIT(ru)) == 0)4324continue;4325val = (fw_ppet->ppet16_ppet8_ru3_ru0[nss] >> (ru * 6)) &43260x3f;4327val = ((val >> 3) & 0x7) | ((val & 0x7) << 3);4328for (i = 5; i >= 0; i--) {4329he_ppet[bit / 8] |=4330((val >> i) & 0x1) << ((bit % 8));4331bit++;4332}4333}4334}4335}43364337static void4338ath12k_mac_filter_he_cap_mesh(struct ieee80211_he_cap_elem *he_cap_elem)4339{4340u8 m;43414342m = IEEE80211_HE_MAC_CAP0_TWT_RES |4343IEEE80211_HE_MAC_CAP0_TWT_REQ;4344he_cap_elem->mac_cap_info[0] &= ~m;43454346m = IEEE80211_HE_MAC_CAP2_TRS |4347IEEE80211_HE_MAC_CAP2_BCAST_TWT |4348IEEE80211_HE_MAC_CAP2_MU_CASCADING;4349he_cap_elem->mac_cap_info[2] &= ~m;43504351m = IEEE80211_HE_MAC_CAP3_FLEX_TWT_SCHED |4352IEEE80211_HE_MAC_CAP2_BCAST_TWT |4353IEEE80211_HE_MAC_CAP2_MU_CASCADING;4354he_cap_elem->mac_cap_info[3] &= ~m;43554356m = IEEE80211_HE_MAC_CAP4_BSRP_BQRP_A_MPDU_AGG |4357IEEE80211_HE_MAC_CAP4_BQR;4358he_cap_elem->mac_cap_info[4] &= ~m;43594360m = IEEE80211_HE_MAC_CAP5_SUBCHAN_SELECTIVE_TRANSMISSION |4361IEEE80211_HE_MAC_CAP5_UL_2x996_TONE_RU |4362IEEE80211_HE_MAC_CAP5_PUNCTURED_SOUNDING |4363IEEE80211_HE_MAC_CAP5_HT_VHT_TRIG_FRAME_RX;4364he_cap_elem->mac_cap_info[5] &= ~m;43654366m = IEEE80211_HE_PHY_CAP2_UL_MU_FULL_MU_MIMO |4367IEEE80211_HE_PHY_CAP2_UL_MU_PARTIAL_MU_MIMO;4368he_cap_elem->phy_cap_info[2] &= ~m;43694370m = IEEE80211_HE_PHY_CAP3_RX_PARTIAL_BW_SU_IN_20MHZ_MU |4371IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_MASK |4372IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_MASK;4373he_cap_elem->phy_cap_info[3] &= ~m;43744375m = IEEE80211_HE_PHY_CAP4_MU_BEAMFORMER;4376he_cap_elem->phy_cap_info[4] &= ~m;43774378m = IEEE80211_HE_PHY_CAP5_NG16_MU_FEEDBACK;4379he_cap_elem->phy_cap_info[5] &= ~m;43804381m = IEEE80211_HE_PHY_CAP6_CODEBOOK_SIZE_75_MU |4382IEEE80211_HE_PHY_CAP6_TRIG_MU_BEAMFORMING_PARTIAL_BW_FB |4383IEEE80211_HE_PHY_CAP6_TRIG_CQI_FB |4384IEEE80211_HE_PHY_CAP6_PARTIAL_BANDWIDTH_DL_MUMIMO;4385he_cap_elem->phy_cap_info[6] &= ~m;43864387m = IEEE80211_HE_PHY_CAP7_PSR_BASED_SR |4388IEEE80211_HE_PHY_CAP7_POWER_BOOST_FACTOR_SUPP |4389IEEE80211_HE_PHY_CAP7_STBC_TX_ABOVE_80MHZ |4390IEEE80211_HE_PHY_CAP7_STBC_RX_ABOVE_80MHZ;4391he_cap_elem->phy_cap_info[7] &= ~m;43924393m = IEEE80211_HE_PHY_CAP8_HE_ER_SU_PPDU_4XLTF_AND_08_US_GI |4394IEEE80211_HE_PHY_CAP8_20MHZ_IN_40MHZ_HE_PPDU_IN_2G |4395IEEE80211_HE_PHY_CAP8_20MHZ_IN_160MHZ_HE_PPDU |4396IEEE80211_HE_PHY_CAP8_80MHZ_IN_160MHZ_HE_PPDU;4397he_cap_elem->phy_cap_info[8] &= ~m;43984399m = IEEE80211_HE_PHY_CAP9_LONGER_THAN_16_SIGB_OFDM_SYM |4400IEEE80211_HE_PHY_CAP9_NON_TRIGGERED_CQI_FEEDBACK |4401IEEE80211_HE_PHY_CAP9_RX_1024_QAM_LESS_THAN_242_TONE_RU |4402IEEE80211_HE_PHY_CAP9_TX_1024_QAM_LESS_THAN_242_TONE_RU |4403IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_COMP_SIGB |4404IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_NON_COMP_SIGB;4405he_cap_elem->phy_cap_info[9] &= ~m;4406}44074408static __le16 ath12k_mac_setup_he_6ghz_cap(struct ath12k_pdev_cap *pcap,4409struct ath12k_band_cap *bcap)4410{4411u8 val;44124413bcap->he_6ghz_capa = IEEE80211_HT_MPDU_DENSITY_NONE;4414if (bcap->ht_cap_info & WMI_HT_CAP_DYNAMIC_SMPS)4415bcap->he_6ghz_capa |=4416u32_encode_bits(WLAN_HT_CAP_SM_PS_DYNAMIC,4417IEEE80211_HE_6GHZ_CAP_SM_PS);4418else4419bcap->he_6ghz_capa |=4420u32_encode_bits(WLAN_HT_CAP_SM_PS_DISABLED,4421IEEE80211_HE_6GHZ_CAP_SM_PS);4422val = u32_get_bits(pcap->vht_cap,4423IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK);4424bcap->he_6ghz_capa |=4425u32_encode_bits(val, IEEE80211_HE_6GHZ_CAP_MAX_AMPDU_LEN_EXP);4426val = u32_get_bits(pcap->vht_cap,4427IEEE80211_VHT_CAP_MAX_MPDU_MASK);4428bcap->he_6ghz_capa |=4429u32_encode_bits(val, IEEE80211_HE_6GHZ_CAP_MAX_MPDU_LEN);4430if (pcap->vht_cap & IEEE80211_VHT_CAP_RX_ANTENNA_PATTERN)4431bcap->he_6ghz_capa |= IEEE80211_HE_6GHZ_CAP_RX_ANTPAT_CONS;4432if (pcap->vht_cap & IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN)4433bcap->he_6ghz_capa |= IEEE80211_HE_6GHZ_CAP_TX_ANTPAT_CONS;44344435return cpu_to_le16(bcap->he_6ghz_capa);4436}44374438static void ath12k_mac_copy_he_cap(struct ath12k_band_cap *band_cap,4439int iftype, u8 num_tx_chains,4440struct ieee80211_sta_he_cap *he_cap)4441{4442struct ieee80211_he_cap_elem *he_cap_elem = &he_cap->he_cap_elem;4443struct ieee80211_he_mcs_nss_supp *mcs_nss = &he_cap->he_mcs_nss_supp;44444445he_cap->has_he = true;4446memcpy(he_cap_elem->mac_cap_info, band_cap->he_cap_info,4447sizeof(he_cap_elem->mac_cap_info));4448memcpy(he_cap_elem->phy_cap_info, band_cap->he_cap_phy_info,4449sizeof(he_cap_elem->phy_cap_info));44504451he_cap_elem->mac_cap_info[1] &=4452IEEE80211_HE_MAC_CAP1_TF_MAC_PAD_DUR_MASK;44534454he_cap_elem->phy_cap_info[5] &=4455~IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_MASK;4456he_cap_elem->phy_cap_info[5] &=4457~IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ_MASK;4458he_cap_elem->phy_cap_info[5] |= num_tx_chains - 1;44594460switch (iftype) {4461case NL80211_IFTYPE_AP:4462he_cap_elem->phy_cap_info[3] &=4463~IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_MASK;4464he_cap_elem->phy_cap_info[9] |=4465IEEE80211_HE_PHY_CAP9_RX_1024_QAM_LESS_THAN_242_TONE_RU;4466break;4467case NL80211_IFTYPE_STATION:4468he_cap_elem->mac_cap_info[0] &= ~IEEE80211_HE_MAC_CAP0_TWT_RES;4469he_cap_elem->mac_cap_info[0] |= IEEE80211_HE_MAC_CAP0_TWT_REQ;4470he_cap_elem->phy_cap_info[9] |=4471IEEE80211_HE_PHY_CAP9_TX_1024_QAM_LESS_THAN_242_TONE_RU;4472break;4473case NL80211_IFTYPE_MESH_POINT:4474ath12k_mac_filter_he_cap_mesh(he_cap_elem);4475break;4476}44774478mcs_nss->rx_mcs_80 = cpu_to_le16(band_cap->he_mcs & 0xffff);4479mcs_nss->tx_mcs_80 = cpu_to_le16(band_cap->he_mcs & 0xffff);4480mcs_nss->rx_mcs_160 = cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff);4481mcs_nss->tx_mcs_160 = cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff);4482mcs_nss->rx_mcs_80p80 = cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff);4483mcs_nss->tx_mcs_80p80 = cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff);44844485memset(he_cap->ppe_thres, 0, sizeof(he_cap->ppe_thres));4486if (he_cap_elem->phy_cap_info[6] &4487IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT)4488ath12k_gen_ppe_thresh(&band_cap->he_ppet, he_cap->ppe_thres);4489}44904491static void4492ath12k_mac_copy_eht_mcs_nss(struct ath12k_band_cap *band_cap,4493struct ieee80211_eht_mcs_nss_supp *mcs_nss,4494const struct ieee80211_he_cap_elem *he_cap,4495const struct ieee80211_eht_cap_elem_fixed *eht_cap)4496{4497if ((he_cap->phy_cap_info[0] &4498(IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G |4499IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G |4500IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G |4501IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G)) == 0)4502memcpy(&mcs_nss->only_20mhz, &band_cap->eht_mcs_20_only,4503sizeof(struct ieee80211_eht_mcs_nss_supp_20mhz_only));45044505if (he_cap->phy_cap_info[0] &4506(IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G |4507IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G))4508memcpy(&mcs_nss->bw._80, &band_cap->eht_mcs_80,4509sizeof(struct ieee80211_eht_mcs_nss_supp_bw));45104511if (he_cap->phy_cap_info[0] &4512IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G)4513memcpy(&mcs_nss->bw._160, &band_cap->eht_mcs_160,4514sizeof(struct ieee80211_eht_mcs_nss_supp_bw));45154516if (eht_cap->phy_cap_info[0] & IEEE80211_EHT_PHY_CAP0_320MHZ_IN_6GHZ)4517memcpy(&mcs_nss->bw._320, &band_cap->eht_mcs_320,4518sizeof(struct ieee80211_eht_mcs_nss_supp_bw));4519}45204521static void ath12k_mac_copy_eht_ppe_thresh(struct ath12k_wmi_ppe_threshold_arg *fw_ppet,4522struct ieee80211_sta_eht_cap *cap)4523{4524u16 bit = IEEE80211_EHT_PPE_THRES_INFO_HEADER_SIZE;4525u8 i, nss, ru, ppet_bit_len_per_ru = IEEE80211_EHT_PPE_THRES_INFO_PPET_SIZE * 2;45264527u8p_replace_bits(&cap->eht_ppe_thres[0], fw_ppet->numss_m1,4528IEEE80211_EHT_PPE_THRES_NSS_MASK);45294530u16p_replace_bits((u16 *)&cap->eht_ppe_thres[0], fw_ppet->ru_bit_mask,4531IEEE80211_EHT_PPE_THRES_RU_INDEX_BITMASK_MASK);45324533for (nss = 0; nss <= fw_ppet->numss_m1; nss++) {4534for (ru = 0;4535ru < hweight16(IEEE80211_EHT_PPE_THRES_RU_INDEX_BITMASK_MASK);4536ru++) {4537u32 val = 0;45384539if ((fw_ppet->ru_bit_mask & BIT(ru)) == 0)4540continue;45414542u32p_replace_bits(&val, fw_ppet->ppet16_ppet8_ru3_ru0[nss] >>4543(ru * ppet_bit_len_per_ru),4544GENMASK(ppet_bit_len_per_ru - 1, 0));45454546for (i = 0; i < ppet_bit_len_per_ru; i++) {4547cap->eht_ppe_thres[bit / 8] |=4548(((val >> i) & 0x1) << ((bit % 8)));4549bit++;4550}4551}4552}4553}45544555static void ath12k_mac_copy_eht_cap(struct ath12k_band_cap *band_cap,4556struct ieee80211_he_cap_elem *he_cap_elem,4557int iftype,4558struct ieee80211_sta_eht_cap *eht_cap)4559{4560struct ieee80211_eht_cap_elem_fixed *eht_cap_elem = &eht_cap->eht_cap_elem;45614562memset(eht_cap, 0, sizeof(struct ieee80211_sta_eht_cap));4563eht_cap->has_eht = true;4564memcpy(eht_cap_elem->mac_cap_info, band_cap->eht_cap_mac_info,4565sizeof(eht_cap_elem->mac_cap_info));4566memcpy(eht_cap_elem->phy_cap_info, band_cap->eht_cap_phy_info,4567sizeof(eht_cap_elem->phy_cap_info));45684569switch (iftype) {4570case NL80211_IFTYPE_AP:4571eht_cap_elem->phy_cap_info[0] &=4572~IEEE80211_EHT_PHY_CAP0_242_TONE_RU_GT20MHZ;4573eht_cap_elem->phy_cap_info[4] &=4574~IEEE80211_EHT_PHY_CAP4_PART_BW_DL_MU_MIMO;4575eht_cap_elem->phy_cap_info[5] &=4576~IEEE80211_EHT_PHY_CAP5_TX_LESS_242_TONE_RU_SUPP;4577break;4578case NL80211_IFTYPE_STATION:4579eht_cap_elem->phy_cap_info[7] &=4580~(IEEE80211_EHT_PHY_CAP7_NON_OFDMA_UL_MU_MIMO_80MHZ |4581IEEE80211_EHT_PHY_CAP7_NON_OFDMA_UL_MU_MIMO_160MHZ |4582IEEE80211_EHT_PHY_CAP7_NON_OFDMA_UL_MU_MIMO_320MHZ);4583eht_cap_elem->phy_cap_info[7] &=4584~(IEEE80211_EHT_PHY_CAP7_MU_BEAMFORMER_80MHZ |4585IEEE80211_EHT_PHY_CAP7_MU_BEAMFORMER_160MHZ |4586IEEE80211_EHT_PHY_CAP7_MU_BEAMFORMER_320MHZ);4587break;4588default:4589break;4590}45914592ath12k_mac_copy_eht_mcs_nss(band_cap, &eht_cap->eht_mcs_nss_supp,4593he_cap_elem, eht_cap_elem);45944595if (eht_cap_elem->phy_cap_info[5] &4596IEEE80211_EHT_PHY_CAP5_PPE_THRESHOLD_PRESENT)4597ath12k_mac_copy_eht_ppe_thresh(&band_cap->eht_ppet, eht_cap);4598}45994600static int ath12k_mac_copy_sband_iftype_data(struct ath12k *ar,4601struct ath12k_pdev_cap *cap,4602struct ieee80211_sband_iftype_data *data,4603int band)4604{4605struct ath12k_band_cap *band_cap = &cap->band[band];4606int i, idx = 0;46074608for (i = 0; i < NUM_NL80211_IFTYPES; i++) {4609struct ieee80211_sta_he_cap *he_cap = &data[idx].he_cap;46104611switch (i) {4612case NL80211_IFTYPE_STATION:4613case NL80211_IFTYPE_AP:4614case NL80211_IFTYPE_MESH_POINT:4615break;46164617default:4618continue;4619}46204621data[idx].types_mask = BIT(i);46224623ath12k_mac_copy_he_cap(band_cap, i, ar->num_tx_chains, he_cap);4624if (band == NL80211_BAND_6GHZ) {4625data[idx].he_6ghz_capa.capa =4626ath12k_mac_setup_he_6ghz_cap(cap, band_cap);4627}4628ath12k_mac_copy_eht_cap(band_cap, &he_cap->he_cap_elem, i,4629&data[idx].eht_cap);4630idx++;4631}46324633return idx;4634}46354636static void ath12k_mac_setup_sband_iftype_data(struct ath12k *ar,4637struct ath12k_pdev_cap *cap)4638{4639struct ieee80211_supported_band *sband;4640enum nl80211_band band;4641int count;46424643if (cap->supported_bands & WMI_HOST_WLAN_2G_CAP) {4644band = NL80211_BAND_2GHZ;4645count = ath12k_mac_copy_sband_iftype_data(ar, cap,4646ar->mac.iftype[band],4647band);4648sband = &ar->mac.sbands[band];4649sband->iftype_data = ar->mac.iftype[band];4650sband->n_iftype_data = count;4651}46524653if (cap->supported_bands & WMI_HOST_WLAN_5G_CAP) {4654band = NL80211_BAND_5GHZ;4655count = ath12k_mac_copy_sband_iftype_data(ar, cap,4656ar->mac.iftype[band],4657band);4658sband = &ar->mac.sbands[band];4659sband->iftype_data = ar->mac.iftype[band];4660sband->n_iftype_data = count;4661}46624663if (cap->supported_bands & WMI_HOST_WLAN_5G_CAP &&4664ar->supports_6ghz) {4665band = NL80211_BAND_6GHZ;4666count = ath12k_mac_copy_sband_iftype_data(ar, cap,4667ar->mac.iftype[band],4668band);4669sband = &ar->mac.sbands[band];4670sband->iftype_data = ar->mac.iftype[band];4671sband->n_iftype_data = count;4672}4673}46744675static int __ath12k_set_antenna(struct ath12k *ar, u32 tx_ant, u32 rx_ant)4676{4677int ret;46784679lockdep_assert_held(&ar->conf_mutex);46804681if (ath12k_check_chain_mask(ar, tx_ant, true))4682return -EINVAL;46834684if (ath12k_check_chain_mask(ar, rx_ant, false))4685return -EINVAL;46864687ar->cfg_tx_chainmask = tx_ant;4688ar->cfg_rx_chainmask = rx_ant;46894690if (ar->state != ATH12K_STATE_ON &&4691ar->state != ATH12K_STATE_RESTARTED)4692return 0;46934694ret = ath12k_wmi_pdev_set_param(ar, WMI_PDEV_PARAM_TX_CHAIN_MASK,4695tx_ant, ar->pdev->pdev_id);4696if (ret) {4697ath12k_warn(ar->ab, "failed to set tx-chainmask: %d, req 0x%x\n",4698ret, tx_ant);4699return ret;4700}47014702ar->num_tx_chains = hweight32(tx_ant);47034704ret = ath12k_wmi_pdev_set_param(ar, WMI_PDEV_PARAM_RX_CHAIN_MASK,4705rx_ant, ar->pdev->pdev_id);4706if (ret) {4707ath12k_warn(ar->ab, "failed to set rx-chainmask: %d, req 0x%x\n",4708ret, rx_ant);4709return ret;4710}47114712ar->num_rx_chains = hweight32(rx_ant);47134714/* Reload HT/VHT/HE capability */4715ath12k_mac_setup_ht_vht_cap(ar, &ar->pdev->cap, NULL);4716ath12k_mac_setup_sband_iftype_data(ar, &ar->pdev->cap);47174718return 0;4719}47204721static void ath12k_mgmt_over_wmi_tx_drop(struct ath12k *ar, struct sk_buff *skb)4722{4723int num_mgmt;47244725ieee80211_free_txskb(ar->hw, skb);47264727num_mgmt = atomic_dec_if_positive(&ar->num_pending_mgmt_tx);47284729if (num_mgmt < 0)4730WARN_ON_ONCE(1);47314732if (!num_mgmt)4733wake_up(&ar->txmgmt_empty_waitq);4734}47354736int ath12k_mac_tx_mgmt_pending_free(int buf_id, void *skb, void *ctx)4737{4738struct sk_buff *msdu = skb;4739struct ieee80211_tx_info *info;4740struct ath12k *ar = ctx;4741struct ath12k_base *ab = ar->ab;47424743spin_lock_bh(&ar->txmgmt_idr_lock);4744idr_remove(&ar->txmgmt_idr, buf_id);4745spin_unlock_bh(&ar->txmgmt_idr_lock);4746dma_unmap_single(ab->dev, ATH12K_SKB_CB(msdu)->paddr, msdu->len,4747DMA_TO_DEVICE);47484749info = IEEE80211_SKB_CB(msdu);4750memset(&info->status, 0, sizeof(info->status));47514752ath12k_mgmt_over_wmi_tx_drop(ar, skb);47534754return 0;4755}47564757static int ath12k_mac_vif_txmgmt_idr_remove(int buf_id, void *skb, void *ctx)4758{4759struct ieee80211_vif *vif = ctx;4760struct ath12k_skb_cb *skb_cb = ATH12K_SKB_CB(skb);4761struct sk_buff *msdu = skb;4762struct ath12k *ar = skb_cb->ar;4763struct ath12k_base *ab = ar->ab;47644765if (skb_cb->vif == vif) {4766spin_lock_bh(&ar->txmgmt_idr_lock);4767idr_remove(&ar->txmgmt_idr, buf_id);4768spin_unlock_bh(&ar->txmgmt_idr_lock);4769dma_unmap_single(ab->dev, skb_cb->paddr, msdu->len,4770DMA_TO_DEVICE);4771}47724773return 0;4774}47754776static int ath12k_mac_mgmt_tx_wmi(struct ath12k *ar, struct ath12k_vif *arvif,4777struct sk_buff *skb)4778{4779struct ath12k_base *ab = ar->ab;4780struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;4781struct ieee80211_tx_info *info;4782dma_addr_t paddr;4783int buf_id;4784int ret;47854786ATH12K_SKB_CB(skb)->ar = ar;4787spin_lock_bh(&ar->txmgmt_idr_lock);4788buf_id = idr_alloc(&ar->txmgmt_idr, skb, 0,4789ATH12K_TX_MGMT_NUM_PENDING_MAX, GFP_ATOMIC);4790spin_unlock_bh(&ar->txmgmt_idr_lock);4791if (buf_id < 0)4792return -ENOSPC;47934794info = IEEE80211_SKB_CB(skb);4795if (!(info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP)) {4796if ((ieee80211_is_action(hdr->frame_control) ||4797ieee80211_is_deauth(hdr->frame_control) ||4798ieee80211_is_disassoc(hdr->frame_control)) &&4799ieee80211_has_protected(hdr->frame_control)) {4800skb_put(skb, IEEE80211_CCMP_MIC_LEN);4801}4802}48034804paddr = dma_map_single(ab->dev, skb->data, skb->len, DMA_TO_DEVICE);4805if (dma_mapping_error(ab->dev, paddr)) {4806ath12k_warn(ab, "failed to DMA map mgmt Tx buffer\n");4807ret = -EIO;4808goto err_free_idr;4809}48104811ATH12K_SKB_CB(skb)->paddr = paddr;48124813ret = ath12k_wmi_mgmt_send(ar, arvif->vdev_id, buf_id, skb);4814if (ret) {4815ath12k_warn(ar->ab, "failed to send mgmt frame: %d\n", ret);4816goto err_unmap_buf;4817}48184819return 0;48204821err_unmap_buf:4822dma_unmap_single(ab->dev, ATH12K_SKB_CB(skb)->paddr,4823skb->len, DMA_TO_DEVICE);4824err_free_idr:4825spin_lock_bh(&ar->txmgmt_idr_lock);4826idr_remove(&ar->txmgmt_idr, buf_id);4827spin_unlock_bh(&ar->txmgmt_idr_lock);48284829return ret;4830}48314832static void ath12k_mgmt_over_wmi_tx_purge(struct ath12k *ar)4833{4834struct sk_buff *skb;48354836while ((skb = skb_dequeue(&ar->wmi_mgmt_tx_queue)) != NULL)4837ath12k_mgmt_over_wmi_tx_drop(ar, skb);4838}48394840static void ath12k_mgmt_over_wmi_tx_work(struct work_struct *work)4841{4842struct ath12k *ar = container_of(work, struct ath12k, wmi_mgmt_tx_work);4843struct ath12k_skb_cb *skb_cb;4844struct ath12k_vif *arvif;4845struct sk_buff *skb;4846int ret;48474848while ((skb = skb_dequeue(&ar->wmi_mgmt_tx_queue)) != NULL) {4849skb_cb = ATH12K_SKB_CB(skb);4850if (!skb_cb->vif) {4851ath12k_warn(ar->ab, "no vif found for mgmt frame\n");4852ath12k_mgmt_over_wmi_tx_drop(ar, skb);4853continue;4854}48554856arvif = ath12k_vif_to_arvif(skb_cb->vif);4857if (ar->allocated_vdev_map & (1LL << arvif->vdev_id) &&4858arvif->is_started) {4859ret = ath12k_mac_mgmt_tx_wmi(ar, arvif, skb);4860if (ret) {4861ath12k_warn(ar->ab, "failed to tx mgmt frame, vdev_id %d :%d\n",4862arvif->vdev_id, ret);4863ath12k_mgmt_over_wmi_tx_drop(ar, skb);4864}4865} else {4866ath12k_warn(ar->ab,4867"dropping mgmt frame for vdev %d, is_started %d\n",4868arvif->vdev_id,4869arvif->is_started);4870ath12k_mgmt_over_wmi_tx_drop(ar, skb);4871}4872}4873}48744875static int ath12k_mac_mgmt_tx(struct ath12k *ar, struct sk_buff *skb,4876bool is_prb_rsp)4877{4878struct sk_buff_head *q = &ar->wmi_mgmt_tx_queue;48794880if (test_bit(ATH12K_FLAG_CRASH_FLUSH, &ar->ab->dev_flags))4881return -ESHUTDOWN;48824883/* Drop probe response packets when the pending management tx4884* count has reached a certain threshold, so as to prioritize4885* other mgmt packets like auth and assoc to be sent on time4886* for establishing successful connections.4887*/4888if (is_prb_rsp &&4889atomic_read(&ar->num_pending_mgmt_tx) > ATH12K_PRB_RSP_DROP_THRESHOLD) {4890ath12k_warn(ar->ab,4891"dropping probe response as pending queue is almost full\n");4892return -ENOSPC;4893}48944895if (skb_queue_len_lockless(q) >= ATH12K_TX_MGMT_NUM_PENDING_MAX) {4896ath12k_warn(ar->ab, "mgmt tx queue is full\n");4897return -ENOSPC;4898}48994900skb_queue_tail(q, skb);4901atomic_inc(&ar->num_pending_mgmt_tx);4902ieee80211_queue_work(ar->hw, &ar->wmi_mgmt_tx_work);49034904return 0;4905}49064907static void ath12k_mac_op_tx(struct ieee80211_hw *hw,4908struct ieee80211_tx_control *control,4909struct sk_buff *skb)4910{4911struct ath12k_skb_cb *skb_cb = ATH12K_SKB_CB(skb);4912struct ath12k *ar = hw->priv;4913struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);4914struct ieee80211_vif *vif = info->control.vif;4915struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);4916struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;4917struct ieee80211_key_conf *key = info->control.hw_key;4918u32 info_flags = info->flags;4919bool is_prb_rsp;4920int ret;49214922memset(skb_cb, 0, sizeof(*skb_cb));4923skb_cb->vif = vif;49244925if (key) {4926skb_cb->cipher = key->cipher;4927skb_cb->flags |= ATH12K_SKB_CIPHER_SET;4928}49294930if (info_flags & IEEE80211_TX_CTL_HW_80211_ENCAP) {4931skb_cb->flags |= ATH12K_SKB_HW_80211_ENCAP;4932} else if (ieee80211_is_mgmt(hdr->frame_control)) {4933is_prb_rsp = ieee80211_is_probe_resp(hdr->frame_control);4934ret = ath12k_mac_mgmt_tx(ar, skb, is_prb_rsp);4935if (ret) {4936ath12k_warn(ar->ab, "failed to queue management frame %d\n",4937ret);4938ieee80211_free_txskb(ar->hw, skb);4939}4940return;4941}49424943ret = ath12k_dp_tx(ar, arvif, skb);4944if (ret) {4945ath12k_warn(ar->ab, "failed to transmit frame %d\n", ret);4946ieee80211_free_txskb(ar->hw, skb);4947}4948}49494950void ath12k_mac_drain_tx(struct ath12k *ar)4951{4952/* make sure rcu-protected mac80211 tx path itself is drained */4953synchronize_net();49544955cancel_work_sync(&ar->wmi_mgmt_tx_work);4956ath12k_mgmt_over_wmi_tx_purge(ar);4957}49584959static int ath12k_mac_config_mon_status_default(struct ath12k *ar, bool enable)4960{4961return -ENOTSUPP;4962/* TODO: Need to support new monitor mode */4963}49644965static void ath12k_mac_wait_reconfigure(struct ath12k_base *ab)4966{4967int recovery_start_count;49684969if (!ab->is_reset)4970return;49714972recovery_start_count = atomic_inc_return(&ab->recovery_start_count);49734974ath12k_dbg(ab, ATH12K_DBG_MAC, "recovery start count %d\n", recovery_start_count);49754976if (recovery_start_count == ab->num_radios) {4977complete(&ab->recovery_start);4978ath12k_dbg(ab, ATH12K_DBG_MAC, "recovery started success\n");4979}49804981ath12k_dbg(ab, ATH12K_DBG_MAC, "waiting reconfigure...\n");49824983wait_for_completion_timeout(&ab->reconfigure_complete,4984ATH12K_RECONFIGURE_TIMEOUT_HZ);4985}49864987static int ath12k_mac_op_start(struct ieee80211_hw *hw)4988{4989struct ath12k *ar = hw->priv;4990struct ath12k_base *ab = ar->ab;4991struct ath12k_pdev *pdev = ar->pdev;4992int ret;49934994ath12k_mac_drain_tx(ar);4995mutex_lock(&ar->conf_mutex);49964997switch (ar->state) {4998case ATH12K_STATE_OFF:4999ar->state = ATH12K_STATE_ON;5000break;5001case ATH12K_STATE_RESTARTING:5002ar->state = ATH12K_STATE_RESTARTED;5003ath12k_mac_wait_reconfigure(ab);5004break;5005case ATH12K_STATE_RESTARTED:5006case ATH12K_STATE_WEDGED:5007case ATH12K_STATE_ON:5008WARN_ON(1);5009ret = -EINVAL;5010goto err;5011}50125013ret = ath12k_wmi_pdev_set_param(ar, WMI_PDEV_PARAM_PMF_QOS,50141, pdev->pdev_id);50155016if (ret) {5017ath12k_err(ar->ab, "failed to enable PMF QOS: (%d\n", ret);5018goto err;5019}50205021ret = ath12k_wmi_pdev_set_param(ar, WMI_PDEV_PARAM_DYNAMIC_BW, 1,5022pdev->pdev_id);5023if (ret) {5024ath12k_err(ar->ab, "failed to enable dynamic bw: %d\n", ret);5025goto err;5026}50275028ret = ath12k_wmi_pdev_set_param(ar, WMI_PDEV_PARAM_ARP_AC_OVERRIDE,50290, pdev->pdev_id);5030if (ret) {5031ath12k_err(ab, "failed to set ac override for ARP: %d\n",5032ret);5033goto err;5034}50355036ret = ath12k_wmi_send_dfs_phyerr_offload_enable_cmd(ar, pdev->pdev_id);5037if (ret) {5038ath12k_err(ab, "failed to offload radar detection: %d\n",5039ret);5040goto err;5041}50425043ret = ath12k_dp_tx_htt_h2t_ppdu_stats_req(ar,5044HTT_PPDU_STATS_TAG_DEFAULT);5045if (ret) {5046ath12k_err(ab, "failed to req ppdu stats: %d\n", ret);5047goto err;5048}50495050ret = ath12k_wmi_pdev_set_param(ar, WMI_PDEV_PARAM_MESH_MCAST_ENABLE,50511, pdev->pdev_id);50525053if (ret) {5054ath12k_err(ar->ab, "failed to enable MESH MCAST ENABLE: (%d\n", ret);5055goto err;5056}50575058__ath12k_set_antenna(ar, ar->cfg_tx_chainmask, ar->cfg_rx_chainmask);50595060/* TODO: Do we need to enable ANI? */50615062ath12k_reg_update_chan_list(ar);50635064ar->num_started_vdevs = 0;5065ar->num_created_vdevs = 0;5066ar->num_peers = 0;5067ar->allocated_vdev_map = 0;50685069/* Configure monitor status ring with default rx_filter to get rx status5070* such as rssi, rx_duration.5071*/5072ret = ath12k_mac_config_mon_status_default(ar, true);5073if (ret && (ret != -ENOTSUPP)) {5074ath12k_err(ab, "failed to configure monitor status ring with default rx_filter: (%d)\n",5075ret);5076goto err;5077}50785079if (ret == -ENOTSUPP)5080ath12k_dbg(ar->ab, ATH12K_DBG_MAC,5081"monitor status config is not yet supported");50825083/* Configure the hash seed for hash based reo dest ring selection */5084ath12k_wmi_pdev_lro_cfg(ar, ar->pdev->pdev_id);50855086/* allow device to enter IMPS */5087if (ab->hw_params->idle_ps) {5088ret = ath12k_wmi_pdev_set_param(ar, WMI_PDEV_PARAM_IDLE_PS_CONFIG,50891, pdev->pdev_id);5090if (ret) {5091ath12k_err(ab, "failed to enable idle ps: %d\n", ret);5092goto err;5093}5094}50955096mutex_unlock(&ar->conf_mutex);50975098rcu_assign_pointer(ab->pdevs_active[ar->pdev_idx],5099&ab->pdevs[ar->pdev_idx]);51005101return 0;51025103err:5104ar->state = ATH12K_STATE_OFF;5105mutex_unlock(&ar->conf_mutex);51065107return ret;5108}51095110static void ath12k_mac_op_stop(struct ieee80211_hw *hw)5111{5112struct ath12k *ar = hw->priv;5113struct htt_ppdu_stats_info *ppdu_stats, *tmp;5114int ret;51155116ath12k_mac_drain_tx(ar);51175118mutex_lock(&ar->conf_mutex);5119ret = ath12k_mac_config_mon_status_default(ar, false);5120if (ret && (ret != -ENOTSUPP))5121ath12k_err(ar->ab, "failed to clear rx_filter for monitor status ring: (%d)\n",5122ret);51235124clear_bit(ATH12K_CAC_RUNNING, &ar->dev_flags);5125ar->state = ATH12K_STATE_OFF;5126mutex_unlock(&ar->conf_mutex);51275128cancel_delayed_work_sync(&ar->scan.timeout);5129cancel_work_sync(&ar->regd_update_work);51305131spin_lock_bh(&ar->data_lock);5132list_for_each_entry_safe(ppdu_stats, tmp, &ar->ppdu_stats_info, list) {5133list_del(&ppdu_stats->list);5134kfree(ppdu_stats);5135}5136spin_unlock_bh(&ar->data_lock);51375138rcu_assign_pointer(ar->ab->pdevs_active[ar->pdev_idx], NULL);51395140synchronize_rcu();51415142atomic_set(&ar->num_pending_mgmt_tx, 0);5143}51445145static u85146ath12k_mac_get_vdev_stats_id(struct ath12k_vif *arvif)5147{5148struct ath12k_base *ab = arvif->ar->ab;5149u8 vdev_stats_id = 0;51505151do {5152if (ab->free_vdev_stats_id_map & (1LL << vdev_stats_id)) {5153vdev_stats_id++;5154if (vdev_stats_id <= ATH12K_INVAL_VDEV_STATS_ID) {5155vdev_stats_id = ATH12K_INVAL_VDEV_STATS_ID;5156break;5157}5158} else {5159ab->free_vdev_stats_id_map |= (1LL << vdev_stats_id);5160break;5161}5162} while (vdev_stats_id);51635164arvif->vdev_stats_id = vdev_stats_id;5165return vdev_stats_id;5166}51675168static void ath12k_mac_setup_vdev_create_arg(struct ath12k_vif *arvif,5169struct ath12k_wmi_vdev_create_arg *arg)5170{5171struct ath12k *ar = arvif->ar;5172struct ath12k_pdev *pdev = ar->pdev;51735174arg->if_id = arvif->vdev_id;5175arg->type = arvif->vdev_type;5176arg->subtype = arvif->vdev_subtype;5177arg->pdev_id = pdev->pdev_id;51785179if (pdev->cap.supported_bands & WMI_HOST_WLAN_2G_CAP) {5180arg->chains[NL80211_BAND_2GHZ].tx = ar->num_tx_chains;5181arg->chains[NL80211_BAND_2GHZ].rx = ar->num_rx_chains;5182}5183if (pdev->cap.supported_bands & WMI_HOST_WLAN_5G_CAP) {5184arg->chains[NL80211_BAND_5GHZ].tx = ar->num_tx_chains;5185arg->chains[NL80211_BAND_5GHZ].rx = ar->num_rx_chains;5186}5187if (pdev->cap.supported_bands & WMI_HOST_WLAN_5G_CAP &&5188ar->supports_6ghz) {5189arg->chains[NL80211_BAND_6GHZ].tx = ar->num_tx_chains;5190arg->chains[NL80211_BAND_6GHZ].rx = ar->num_rx_chains;5191}51925193arg->if_stats_id = ath12k_mac_get_vdev_stats_id(arvif);5194}51955196static u325197ath12k_mac_prepare_he_mode(struct ath12k_pdev *pdev, u32 viftype)5198{5199struct ath12k_pdev_cap *pdev_cap = &pdev->cap;5200struct ath12k_band_cap *cap_band = NULL;5201u32 *hecap_phy_ptr = NULL;5202u32 hemode;52035204if (pdev->cap.supported_bands & WMI_HOST_WLAN_2G_CAP)5205cap_band = &pdev_cap->band[NL80211_BAND_2GHZ];5206else5207cap_band = &pdev_cap->band[NL80211_BAND_5GHZ];52085209hecap_phy_ptr = &cap_band->he_cap_phy_info[0];52105211hemode = u32_encode_bits(HE_SU_BFEE_ENABLE, HE_MODE_SU_TX_BFEE) |5212u32_encode_bits(HECAP_PHY_SUBFMR_GET(hecap_phy_ptr),5213HE_MODE_SU_TX_BFER) |5214u32_encode_bits(HECAP_PHY_ULMUMIMO_GET(hecap_phy_ptr),5215HE_MODE_UL_MUMIMO);52165217/* TODO: WDS and other modes */5218if (viftype == NL80211_IFTYPE_AP) {5219hemode |= u32_encode_bits(HECAP_PHY_MUBFMR_GET(hecap_phy_ptr),5220HE_MODE_MU_TX_BFER) |5221u32_encode_bits(HE_DL_MUOFDMA_ENABLE, HE_MODE_DL_OFDMA) |5222u32_encode_bits(HE_UL_MUOFDMA_ENABLE, HE_MODE_UL_OFDMA);5223} else {5224hemode |= u32_encode_bits(HE_MU_BFEE_ENABLE, HE_MODE_MU_TX_BFEE);5225}52265227return hemode;5228}52295230static int ath12k_set_he_mu_sounding_mode(struct ath12k *ar,5231struct ath12k_vif *arvif)5232{5233u32 param_id, param_value;5234struct ath12k_base *ab = ar->ab;5235int ret;52365237param_id = WMI_VDEV_PARAM_SET_HEMU_MODE;5238param_value = ath12k_mac_prepare_he_mode(ar->pdev, arvif->vif->type);5239ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,5240param_id, param_value);5241if (ret) {5242ath12k_warn(ab, "failed to set vdev %d HE MU mode: %d param_value %x\n",5243arvif->vdev_id, ret, param_value);5244return ret;5245}5246param_id = WMI_VDEV_PARAM_SET_HE_SOUNDING_MODE;5247param_value =5248u32_encode_bits(HE_VHT_SOUNDING_MODE_ENABLE, HE_VHT_SOUNDING_MODE) |5249u32_encode_bits(HE_TRIG_NONTRIG_SOUNDING_MODE_ENABLE,5250HE_TRIG_NONTRIG_SOUNDING_MODE);5251ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,5252param_id, param_value);5253if (ret) {5254ath12k_warn(ab, "failed to set vdev %d HE MU mode: %d\n",5255arvif->vdev_id, ret);5256return ret;5257}5258return ret;5259}52605261static void ath12k_mac_op_update_vif_offload(struct ieee80211_hw *hw,5262struct ieee80211_vif *vif)5263{5264struct ath12k *ar = hw->priv;5265struct ath12k_base *ab = ar->ab;5266struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);5267u32 param_id, param_value;5268int ret;52695270param_id = WMI_VDEV_PARAM_TX_ENCAP_TYPE;5271if (vif->type != NL80211_IFTYPE_STATION &&5272vif->type != NL80211_IFTYPE_AP)5273vif->offload_flags &= ~(IEEE80211_OFFLOAD_ENCAP_ENABLED |5274IEEE80211_OFFLOAD_DECAP_ENABLED);52755276if (vif->offload_flags & IEEE80211_OFFLOAD_ENCAP_ENABLED)5277arvif->tx_encap_type = ATH12K_HW_TXRX_ETHERNET;5278else if (test_bit(ATH12K_FLAG_RAW_MODE, &ab->dev_flags))5279arvif->tx_encap_type = ATH12K_HW_TXRX_RAW;5280else5281arvif->tx_encap_type = ATH12K_HW_TXRX_NATIVE_WIFI;52825283ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,5284param_id, arvif->tx_encap_type);5285if (ret) {5286ath12k_warn(ab, "failed to set vdev %d tx encap mode: %d\n",5287arvif->vdev_id, ret);5288vif->offload_flags &= ~IEEE80211_OFFLOAD_ENCAP_ENABLED;5289}52905291param_id = WMI_VDEV_PARAM_RX_DECAP_TYPE;5292if (vif->offload_flags & IEEE80211_OFFLOAD_DECAP_ENABLED)5293param_value = ATH12K_HW_TXRX_ETHERNET;5294else if (test_bit(ATH12K_FLAG_RAW_MODE, &ab->dev_flags))5295param_value = ATH12K_HW_TXRX_RAW;5296else5297param_value = ATH12K_HW_TXRX_NATIVE_WIFI;52985299ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,5300param_id, param_value);5301if (ret) {5302ath12k_warn(ab, "failed to set vdev %d rx decap mode: %d\n",5303arvif->vdev_id, ret);5304vif->offload_flags &= ~IEEE80211_OFFLOAD_DECAP_ENABLED;5305}5306}53075308static int ath12k_mac_op_add_interface(struct ieee80211_hw *hw,5309struct ieee80211_vif *vif)5310{5311struct ath12k *ar = hw->priv;5312struct ath12k_base *ab = ar->ab;5313struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);5314struct ath12k_wmi_vdev_create_arg vdev_arg = {0};5315struct ath12k_wmi_peer_create_arg peer_param;5316u32 param_id, param_value;5317u16 nss;5318int i;5319int ret;5320int bit;53215322vif->driver_flags |= IEEE80211_VIF_SUPPORTS_UAPSD;53235324mutex_lock(&ar->conf_mutex);53255326if (vif->type == NL80211_IFTYPE_AP &&5327ar->num_peers > (ar->max_num_peers - 1)) {5328ath12k_warn(ab, "failed to create vdev due to insufficient peer entry resource in firmware\n");5329ret = -ENOBUFS;5330goto err;5331}53325333if (ar->num_created_vdevs > (TARGET_NUM_VDEVS - 1)) {5334ath12k_warn(ab, "failed to create vdev, reached max vdev limit %d\n",5335TARGET_NUM_VDEVS);5336ret = -EBUSY;5337goto err;5338}53395340memset(arvif, 0, sizeof(*arvif));53415342arvif->ar = ar;5343arvif->vif = vif;53445345INIT_LIST_HEAD(&arvif->list);53465347/* Should we initialize any worker to handle connection loss indication5348* from firmware in sta mode?5349*/53505351for (i = 0; i < ARRAY_SIZE(arvif->bitrate_mask.control); i++) {5352arvif->bitrate_mask.control[i].legacy = 0xffffffff;5353memset(arvif->bitrate_mask.control[i].ht_mcs, 0xff,5354sizeof(arvif->bitrate_mask.control[i].ht_mcs));5355memset(arvif->bitrate_mask.control[i].vht_mcs, 0xff,5356sizeof(arvif->bitrate_mask.control[i].vht_mcs));5357}53585359bit = __ffs64(ab->free_vdev_map);53605361arvif->vdev_id = bit;5362arvif->vdev_subtype = WMI_VDEV_SUBTYPE_NONE;53635364switch (vif->type) {5365case NL80211_IFTYPE_UNSPECIFIED:5366case NL80211_IFTYPE_STATION:5367arvif->vdev_type = WMI_VDEV_TYPE_STA;5368break;5369case NL80211_IFTYPE_MESH_POINT:5370arvif->vdev_subtype = WMI_VDEV_SUBTYPE_MESH_11S;5371fallthrough;5372case NL80211_IFTYPE_AP:5373arvif->vdev_type = WMI_VDEV_TYPE_AP;5374break;5375case NL80211_IFTYPE_MONITOR:5376arvif->vdev_type = WMI_VDEV_TYPE_MONITOR;5377ar->monitor_vdev_id = bit;5378break;5379default:5380WARN_ON(1);5381break;5382}53835384ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac add interface id %d type %d subtype %d map %llx\n",5385arvif->vdev_id, arvif->vdev_type, arvif->vdev_subtype,5386ab->free_vdev_map);53875388vif->cab_queue = arvif->vdev_id % (ATH12K_HW_MAX_QUEUES - 1);5389for (i = 0; i < ARRAY_SIZE(vif->hw_queue); i++)5390vif->hw_queue[i] = i % (ATH12K_HW_MAX_QUEUES - 1);53915392ath12k_mac_setup_vdev_create_arg(arvif, &vdev_arg);53935394ret = ath12k_wmi_vdev_create(ar, vif->addr, &vdev_arg);5395if (ret) {5396ath12k_warn(ab, "failed to create WMI vdev %d: %d\n",5397arvif->vdev_id, ret);5398goto err;5399}54005401ar->num_created_vdevs++;5402ath12k_dbg(ab, ATH12K_DBG_MAC, "vdev %pM created, vdev_id %d\n",5403vif->addr, arvif->vdev_id);5404ar->allocated_vdev_map |= 1LL << arvif->vdev_id;5405ab->free_vdev_map &= ~(1LL << arvif->vdev_id);54065407spin_lock_bh(&ar->data_lock);5408list_add(&arvif->list, &ar->arvifs);5409spin_unlock_bh(&ar->data_lock);54105411ath12k_mac_op_update_vif_offload(hw, vif);54125413nss = hweight32(ar->cfg_tx_chainmask) ? : 1;5414ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,5415WMI_VDEV_PARAM_NSS, nss);5416if (ret) {5417ath12k_warn(ab, "failed to set vdev %d chainmask 0x%x, nss %d :%d\n",5418arvif->vdev_id, ar->cfg_tx_chainmask, nss, ret);5419goto err_vdev_del;5420}54215422switch (arvif->vdev_type) {5423case WMI_VDEV_TYPE_AP:5424peer_param.vdev_id = arvif->vdev_id;5425peer_param.peer_addr = vif->addr;5426peer_param.peer_type = WMI_PEER_TYPE_DEFAULT;5427ret = ath12k_peer_create(ar, arvif, NULL, &peer_param);5428if (ret) {5429ath12k_warn(ab, "failed to vdev %d create peer for AP: %d\n",5430arvif->vdev_id, ret);5431goto err_vdev_del;5432}54335434ret = ath12k_mac_set_kickout(arvif);5435if (ret) {5436ath12k_warn(ar->ab, "failed to set vdev %i kickout parameters: %d\n",5437arvif->vdev_id, ret);5438goto err_peer_del;5439}5440break;5441case WMI_VDEV_TYPE_STA:5442param_id = WMI_STA_PS_PARAM_RX_WAKE_POLICY;5443param_value = WMI_STA_PS_RX_WAKE_POLICY_WAKE;5444ret = ath12k_wmi_set_sta_ps_param(ar, arvif->vdev_id,5445param_id, param_value);5446if (ret) {5447ath12k_warn(ar->ab, "failed to set vdev %d RX wake policy: %d\n",5448arvif->vdev_id, ret);5449goto err_peer_del;5450}54515452param_id = WMI_STA_PS_PARAM_TX_WAKE_THRESHOLD;5453param_value = WMI_STA_PS_TX_WAKE_THRESHOLD_ALWAYS;5454ret = ath12k_wmi_set_sta_ps_param(ar, arvif->vdev_id,5455param_id, param_value);5456if (ret) {5457ath12k_warn(ar->ab, "failed to set vdev %d TX wake threshold: %d\n",5458arvif->vdev_id, ret);5459goto err_peer_del;5460}54615462param_id = WMI_STA_PS_PARAM_PSPOLL_COUNT;5463param_value = WMI_STA_PS_PSPOLL_COUNT_NO_MAX;5464ret = ath12k_wmi_set_sta_ps_param(ar, arvif->vdev_id,5465param_id, param_value);5466if (ret) {5467ath12k_warn(ar->ab, "failed to set vdev %d pspoll count: %d\n",5468arvif->vdev_id, ret);5469goto err_peer_del;5470}54715472ret = ath12k_wmi_pdev_set_ps_mode(ar, arvif->vdev_id, false);5473if (ret) {5474ath12k_warn(ar->ab, "failed to disable vdev %d ps mode: %d\n",5475arvif->vdev_id, ret);5476goto err_peer_del;5477}5478break;5479default:5480break;5481}54825483arvif->txpower = vif->bss_conf.txpower;5484ret = ath12k_mac_txpower_recalc(ar);5485if (ret)5486goto err_peer_del;54875488param_id = WMI_VDEV_PARAM_RTS_THRESHOLD;5489param_value = ar->hw->wiphy->rts_threshold;5490ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,5491param_id, param_value);5492if (ret) {5493ath12k_warn(ar->ab, "failed to set rts threshold for vdev %d: %d\n",5494arvif->vdev_id, ret);5495}54965497ath12k_dp_vdev_tx_attach(ar, arvif);54985499if (vif->type != NL80211_IFTYPE_MONITOR && ar->monitor_conf_enabled)5500ath12k_mac_monitor_vdev_create(ar);55015502mutex_unlock(&ar->conf_mutex);55035504return ret;55055506err_peer_del:5507if (arvif->vdev_type == WMI_VDEV_TYPE_AP) {5508reinit_completion(&ar->peer_delete_done);55095510ret = ath12k_wmi_send_peer_delete_cmd(ar, vif->addr,5511arvif->vdev_id);5512if (ret) {5513ath12k_warn(ar->ab, "failed to delete peer vdev_id %d addr %pM\n",5514arvif->vdev_id, vif->addr);5515goto err;5516}55175518ret = ath12k_wait_for_peer_delete_done(ar, arvif->vdev_id,5519vif->addr);5520if (ret)5521goto err;55225523ar->num_peers--;5524}55255526err_vdev_del:5527ath12k_wmi_vdev_delete(ar, arvif->vdev_id);5528ar->num_created_vdevs--;5529ar->allocated_vdev_map &= ~(1LL << arvif->vdev_id);5530ab->free_vdev_map |= 1LL << arvif->vdev_id;5531ab->free_vdev_stats_id_map &= ~(1LL << arvif->vdev_stats_id);5532spin_lock_bh(&ar->data_lock);5533list_del(&arvif->list);5534spin_unlock_bh(&ar->data_lock);55355536err:5537mutex_unlock(&ar->conf_mutex);55385539return ret;5540}55415542static void ath12k_mac_vif_unref(struct ath12k_dp *dp, struct ieee80211_vif *vif)5543{5544struct ath12k_tx_desc_info *tx_desc_info;5545struct ath12k_skb_cb *skb_cb;5546struct sk_buff *skb;5547int i;55485549for (i = 0; i < ATH12K_HW_MAX_QUEUES; i++) {5550spin_lock_bh(&dp->tx_desc_lock[i]);55515552list_for_each_entry(tx_desc_info, &dp->tx_desc_used_list[i],5553list) {5554skb = tx_desc_info->skb;5555if (!skb)5556continue;55575558skb_cb = ATH12K_SKB_CB(skb);5559if (skb_cb->vif == vif)5560skb_cb->vif = NULL;5561}55625563spin_unlock_bh(&dp->tx_desc_lock[i]);5564}5565}55665567static void ath12k_mac_op_remove_interface(struct ieee80211_hw *hw,5568struct ieee80211_vif *vif)5569{5570struct ath12k *ar = hw->priv;5571struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);5572struct ath12k_base *ab = ar->ab;5573unsigned long time_left;5574int ret;55755576mutex_lock(&ar->conf_mutex);55775578ath12k_dbg(ab, ATH12K_DBG_MAC, "mac remove interface (vdev %d)\n",5579arvif->vdev_id);55805581if (arvif->vdev_type == WMI_VDEV_TYPE_AP) {5582ret = ath12k_peer_delete(ar, arvif->vdev_id, vif->addr);5583if (ret)5584ath12k_warn(ab, "failed to submit AP self-peer removal on vdev %d: %d\n",5585arvif->vdev_id, ret);5586}55875588reinit_completion(&ar->vdev_delete_done);55895590ret = ath12k_wmi_vdev_delete(ar, arvif->vdev_id);5591if (ret) {5592ath12k_warn(ab, "failed to delete WMI vdev %d: %d\n",5593arvif->vdev_id, ret);5594goto err_vdev_del;5595}55965597time_left = wait_for_completion_timeout(&ar->vdev_delete_done,5598ATH12K_VDEV_DELETE_TIMEOUT_HZ);5599if (time_left == 0) {5600ath12k_warn(ab, "Timeout in receiving vdev delete response\n");5601goto err_vdev_del;5602}56035604if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR) {5605ar->monitor_vdev_id = -1;5606ar->monitor_vdev_created = false;5607} else if (ar->monitor_vdev_created && !ar->monitor_started) {5608ret = ath12k_mac_monitor_vdev_delete(ar);5609}56105611ab->free_vdev_map |= 1LL << (arvif->vdev_id);5612ar->allocated_vdev_map &= ~(1LL << arvif->vdev_id);5613ab->free_vdev_stats_id_map &= ~(1LL << arvif->vdev_stats_id);5614ar->num_created_vdevs--;56155616ath12k_dbg(ab, ATH12K_DBG_MAC, "vdev %pM deleted, vdev_id %d\n",5617vif->addr, arvif->vdev_id);56185619err_vdev_del:5620spin_lock_bh(&ar->data_lock);5621list_del(&arvif->list);5622spin_unlock_bh(&ar->data_lock);56235624ath12k_peer_cleanup(ar, arvif->vdev_id);56255626idr_for_each(&ar->txmgmt_idr,5627ath12k_mac_vif_txmgmt_idr_remove, vif);56285629ath12k_mac_vif_unref(&ab->dp, vif);5630ath12k_dp_tx_put_bank_profile(&ab->dp, arvif->bank_id);56315632/* Recalc txpower for remaining vdev */5633ath12k_mac_txpower_recalc(ar);5634clear_bit(ATH12K_FLAG_MONITOR_ENABLED, &ar->monitor_flags);56355636/* TODO: recal traffic pause state based on the available vdevs */56375638mutex_unlock(&ar->conf_mutex);5639}56405641/* FIXME: Has to be verified. */5642#define SUPPORTED_FILTERS \5643(FIF_ALLMULTI | \5644FIF_CONTROL | \5645FIF_PSPOLL | \5646FIF_OTHER_BSS | \5647FIF_BCN_PRBRESP_PROMISC | \5648FIF_PROBE_REQ | \5649FIF_FCSFAIL)56505651static void ath12k_mac_op_configure_filter(struct ieee80211_hw *hw,5652unsigned int changed_flags,5653unsigned int *total_flags,5654u64 multicast)5655{5656struct ath12k *ar = hw->priv;5657bool reset_flag;5658int ret;56595660mutex_lock(&ar->conf_mutex);56615662changed_flags &= SUPPORTED_FILTERS;5663*total_flags &= SUPPORTED_FILTERS;5664ar->filter_flags = *total_flags;56655666/* For monitor mode */5667reset_flag = !(ar->filter_flags & FIF_BCN_PRBRESP_PROMISC);56685669ret = ath12k_dp_tx_htt_monitor_mode_ring_config(ar, reset_flag);5670if (!ret) {5671if (!reset_flag)5672set_bit(ATH12K_FLAG_MONITOR_ENABLED, &ar->monitor_flags);5673else5674clear_bit(ATH12K_FLAG_MONITOR_ENABLED, &ar->monitor_flags);5675} else {5676ath12k_warn(ar->ab,5677"fail to set monitor filter: %d\n", ret);5678}5679ath12k_dbg(ar->ab, ATH12K_DBG_MAC,5680"changed_flags:0x%x, total_flags:0x%x, reset_flag:%d\n",5681changed_flags, *total_flags, reset_flag);56825683mutex_unlock(&ar->conf_mutex);5684}56855686static int ath12k_mac_op_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant)5687{5688struct ath12k *ar = hw->priv;56895690mutex_lock(&ar->conf_mutex);56915692*tx_ant = ar->cfg_tx_chainmask;5693*rx_ant = ar->cfg_rx_chainmask;56945695mutex_unlock(&ar->conf_mutex);56965697return 0;5698}56995700static int ath12k_mac_op_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant)5701{5702struct ath12k *ar = hw->priv;5703int ret;57045705mutex_lock(&ar->conf_mutex);5706ret = __ath12k_set_antenna(ar, tx_ant, rx_ant);5707mutex_unlock(&ar->conf_mutex);57085709return ret;5710}57115712static int ath12k_mac_op_ampdu_action(struct ieee80211_hw *hw,5713struct ieee80211_vif *vif,5714struct ieee80211_ampdu_params *params)5715{5716struct ath12k *ar = hw->priv;5717int ret = -EINVAL;57185719mutex_lock(&ar->conf_mutex);57205721switch (params->action) {5722case IEEE80211_AMPDU_RX_START:5723ret = ath12k_dp_rx_ampdu_start(ar, params);5724break;5725case IEEE80211_AMPDU_RX_STOP:5726ret = ath12k_dp_rx_ampdu_stop(ar, params);5727break;5728case IEEE80211_AMPDU_TX_START:5729case IEEE80211_AMPDU_TX_STOP_CONT:5730case IEEE80211_AMPDU_TX_STOP_FLUSH:5731case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:5732case IEEE80211_AMPDU_TX_OPERATIONAL:5733/* Tx A-MPDU aggregation offloaded to hw/fw so deny mac802115734* Tx aggregation requests.5735*/5736ret = -EOPNOTSUPP;5737break;5738}57395740mutex_unlock(&ar->conf_mutex);57415742return ret;5743}57445745static int ath12k_mac_op_add_chanctx(struct ieee80211_hw *hw,5746struct ieee80211_chanctx_conf *ctx)5747{5748struct ath12k *ar = hw->priv;5749struct ath12k_base *ab = ar->ab;57505751ath12k_dbg(ab, ATH12K_DBG_MAC,5752"mac chanctx add freq %u width %d ptr %pK\n",5753ctx->def.chan->center_freq, ctx->def.width, ctx);57545755mutex_lock(&ar->conf_mutex);57565757spin_lock_bh(&ar->data_lock);5758/* TODO: In case of multiple channel context, populate rx_channel from5759* Rx PPDU desc information.5760*/5761ar->rx_channel = ctx->def.chan;5762spin_unlock_bh(&ar->data_lock);57635764mutex_unlock(&ar->conf_mutex);57655766return 0;5767}57685769static void ath12k_mac_op_remove_chanctx(struct ieee80211_hw *hw,5770struct ieee80211_chanctx_conf *ctx)5771{5772struct ath12k *ar = hw->priv;5773struct ath12k_base *ab = ar->ab;57745775ath12k_dbg(ab, ATH12K_DBG_MAC,5776"mac chanctx remove freq %u width %d ptr %pK\n",5777ctx->def.chan->center_freq, ctx->def.width, ctx);57785779mutex_lock(&ar->conf_mutex);57805781spin_lock_bh(&ar->data_lock);5782/* TODO: In case of there is one more channel context left, populate5783* rx_channel with the channel of that remaining channel context.5784*/5785ar->rx_channel = NULL;5786spin_unlock_bh(&ar->data_lock);57875788mutex_unlock(&ar->conf_mutex);5789}57905791static int5792ath12k_mac_vdev_start_restart(struct ath12k_vif *arvif,5793const struct cfg80211_chan_def *chandef,5794bool restart)5795{5796struct ath12k *ar = arvif->ar;5797struct ath12k_base *ab = ar->ab;5798struct wmi_vdev_start_req_arg arg = {};5799int he_support = arvif->vif->bss_conf.he_support;5800int ret;58015802lockdep_assert_held(&ar->conf_mutex);58035804reinit_completion(&ar->vdev_setup_done);58055806arg.vdev_id = arvif->vdev_id;5807arg.dtim_period = arvif->dtim_period;5808arg.bcn_intval = arvif->beacon_interval;5809arg.punct_bitmap = ~arvif->punct_bitmap;58105811arg.freq = chandef->chan->center_freq;5812arg.band_center_freq1 = chandef->center_freq1;5813arg.band_center_freq2 = chandef->center_freq2;5814arg.mode = ath12k_phymodes[chandef->chan->band][chandef->width];58155816arg.min_power = 0;5817arg.max_power = chandef->chan->max_power * 2;5818arg.max_reg_power = chandef->chan->max_reg_power * 2;5819arg.max_antenna_gain = chandef->chan->max_antenna_gain * 2;58205821arg.pref_tx_streams = ar->num_tx_chains;5822arg.pref_rx_streams = ar->num_rx_chains;58235824if (arvif->vdev_type == WMI_VDEV_TYPE_AP) {5825arg.ssid = arvif->u.ap.ssid;5826arg.ssid_len = arvif->u.ap.ssid_len;5827arg.hidden_ssid = arvif->u.ap.hidden_ssid;58285829/* For now allow DFS for AP mode */5830arg.chan_radar = !!(chandef->chan->flags & IEEE80211_CHAN_RADAR);58315832arg.passive = arg.chan_radar;58335834spin_lock_bh(&ab->base_lock);5835arg.regdomain = ar->ab->dfs_region;5836spin_unlock_bh(&ab->base_lock);58375838/* TODO: Notify if secondary 80Mhz also needs radar detection */5839if (he_support) {5840ret = ath12k_set_he_mu_sounding_mode(ar, arvif);5841if (ret) {5842ath12k_warn(ar->ab, "failed to set he mode vdev %i\n",5843arg.vdev_id);5844return ret;5845}5846}5847}58485849arg.passive |= !!(chandef->chan->flags & IEEE80211_CHAN_NO_IR);58505851ath12k_dbg(ab, ATH12K_DBG_MAC,5852"mac vdev %d start center_freq %d phymode %s punct_bitmap 0x%x\n",5853arg.vdev_id, arg.freq,5854ath12k_mac_phymode_str(arg.mode), arg.punct_bitmap);58555856ret = ath12k_wmi_vdev_start(ar, &arg, restart);5857if (ret) {5858ath12k_warn(ar->ab, "failed to %s WMI vdev %i\n",5859restart ? "restart" : "start", arg.vdev_id);5860return ret;5861}58625863ret = ath12k_mac_vdev_setup_sync(ar);5864if (ret) {5865ath12k_warn(ab, "failed to synchronize setup for vdev %i %s: %d\n",5866arg.vdev_id, restart ? "restart" : "start", ret);5867return ret;5868}58695870ar->num_started_vdevs++;5871ath12k_dbg(ab, ATH12K_DBG_MAC, "vdev %pM started, vdev_id %d\n",5872arvif->vif->addr, arvif->vdev_id);58735874/* Enable CAC Flag in the driver by checking the channel DFS cac time,5875* i.e dfs_cac_ms value which will be valid only for radar channels5876* and state as NL80211_DFS_USABLE which indicates CAC needs to be5877* done before channel usage. This flags is used to drop rx packets.5878* during CAC.5879*/5880/* TODO: Set the flag for other interface types as required */5881if (arvif->vdev_type == WMI_VDEV_TYPE_AP &&5882chandef->chan->dfs_cac_ms &&5883chandef->chan->dfs_state == NL80211_DFS_USABLE) {5884set_bit(ATH12K_CAC_RUNNING, &ar->dev_flags);5885ath12k_dbg(ab, ATH12K_DBG_MAC,5886"CAC Started in chan_freq %d for vdev %d\n",5887arg.freq, arg.vdev_id);5888}58895890ret = ath12k_mac_set_txbf_conf(arvif);5891if (ret)5892ath12k_warn(ab, "failed to set txbf conf for vdev %d: %d\n",5893arvif->vdev_id, ret);58945895return 0;5896}58975898static int ath12k_mac_vdev_stop(struct ath12k_vif *arvif)5899{5900struct ath12k *ar = arvif->ar;5901int ret;59025903lockdep_assert_held(&ar->conf_mutex);59045905reinit_completion(&ar->vdev_setup_done);59065907ret = ath12k_wmi_vdev_stop(ar, arvif->vdev_id);5908if (ret) {5909ath12k_warn(ar->ab, "failed to stop WMI vdev %i: %d\n",5910arvif->vdev_id, ret);5911goto err;5912}59135914ret = ath12k_mac_vdev_setup_sync(ar);5915if (ret) {5916ath12k_warn(ar->ab, "failed to synchronize setup for vdev %i: %d\n",5917arvif->vdev_id, ret);5918goto err;5919}59205921WARN_ON(ar->num_started_vdevs == 0);59225923ar->num_started_vdevs--;5924ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "vdev %pM stopped, vdev_id %d\n",5925arvif->vif->addr, arvif->vdev_id);59265927if (test_bit(ATH12K_CAC_RUNNING, &ar->dev_flags)) {5928clear_bit(ATH12K_CAC_RUNNING, &ar->dev_flags);5929ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "CAC Stopped for vdev %d\n",5930arvif->vdev_id);5931}59325933return 0;5934err:5935return ret;5936}59375938static int ath12k_mac_vdev_start(struct ath12k_vif *arvif,5939const struct cfg80211_chan_def *chandef)5940{5941return ath12k_mac_vdev_start_restart(arvif, chandef, false);5942}59435944static int ath12k_mac_vdev_restart(struct ath12k_vif *arvif,5945const struct cfg80211_chan_def *chandef)5946{5947return ath12k_mac_vdev_start_restart(arvif, chandef, true);5948}59495950struct ath12k_mac_change_chanctx_arg {5951struct ieee80211_chanctx_conf *ctx;5952struct ieee80211_vif_chanctx_switch *vifs;5953int n_vifs;5954int next_vif;5955};59565957static void5958ath12k_mac_change_chanctx_cnt_iter(void *data, u8 *mac,5959struct ieee80211_vif *vif)5960{5961struct ath12k_mac_change_chanctx_arg *arg = data;59625963if (rcu_access_pointer(vif->bss_conf.chanctx_conf) != arg->ctx)5964return;59655966arg->n_vifs++;5967}59685969static void5970ath12k_mac_change_chanctx_fill_iter(void *data, u8 *mac,5971struct ieee80211_vif *vif)5972{5973struct ath12k_mac_change_chanctx_arg *arg = data;5974struct ieee80211_chanctx_conf *ctx;59755976ctx = rcu_access_pointer(vif->bss_conf.chanctx_conf);5977if (ctx != arg->ctx)5978return;59795980if (WARN_ON(arg->next_vif == arg->n_vifs))5981return;59825983arg->vifs[arg->next_vif].vif = vif;5984arg->vifs[arg->next_vif].old_ctx = ctx;5985arg->vifs[arg->next_vif].new_ctx = ctx;5986arg->next_vif++;5987}59885989static void5990ath12k_mac_update_vif_chan(struct ath12k *ar,5991struct ieee80211_vif_chanctx_switch *vifs,5992int n_vifs)5993{5994struct ath12k_base *ab = ar->ab;5995struct ath12k_vif *arvif;5996int ret;5997int i;5998bool monitor_vif = false;59996000lockdep_assert_held(&ar->conf_mutex);60016002for (i = 0; i < n_vifs; i++) {6003arvif = (void *)vifs[i].vif->drv_priv;60046005if (vifs[i].vif->type == NL80211_IFTYPE_MONITOR)6006monitor_vif = true;60076008ath12k_dbg(ab, ATH12K_DBG_MAC,6009"mac chanctx switch vdev_id %i freq %u->%u width %d->%d\n",6010arvif->vdev_id,6011vifs[i].old_ctx->def.chan->center_freq,6012vifs[i].new_ctx->def.chan->center_freq,6013vifs[i].old_ctx->def.width,6014vifs[i].new_ctx->def.width);60156016if (WARN_ON(!arvif->is_started))6017continue;60186019if (WARN_ON(!arvif->is_up))6020continue;60216022ret = ath12k_wmi_vdev_down(ar, arvif->vdev_id);6023if (ret) {6024ath12k_warn(ab, "failed to down vdev %d: %d\n",6025arvif->vdev_id, ret);6026continue;6027}6028}60296030/* All relevant vdevs are downed and associated channel resources6031* should be available for the channel switch now.6032*/60336034/* TODO: Update ar->rx_channel */60356036for (i = 0; i < n_vifs; i++) {6037arvif = (void *)vifs[i].vif->drv_priv;60386039if (WARN_ON(!arvif->is_started))6040continue;60416042if (WARN_ON(!arvif->is_up))6043continue;60446045ret = ath12k_mac_vdev_restart(arvif, &vifs[i].new_ctx->def);6046if (ret) {6047ath12k_warn(ab, "failed to restart vdev %d: %d\n",6048arvif->vdev_id, ret);6049continue;6050}60516052ret = ath12k_mac_setup_bcn_tmpl(arvif);6053if (ret)6054ath12k_warn(ab, "failed to update bcn tmpl during csa: %d\n",6055ret);60566057ret = ath12k_wmi_vdev_up(arvif->ar, arvif->vdev_id, arvif->aid,6058arvif->bssid);6059if (ret) {6060ath12k_warn(ab, "failed to bring vdev up %d: %d\n",6061arvif->vdev_id, ret);6062continue;6063}6064}60656066/* Restart the internal monitor vdev on new channel */6067if (!monitor_vif && ar->monitor_vdev_created) {6068if (!ath12k_mac_monitor_stop(ar))6069ath12k_mac_monitor_start(ar);6070}6071}60726073static void6074ath12k_mac_update_active_vif_chan(struct ath12k *ar,6075struct ieee80211_chanctx_conf *ctx)6076{6077struct ath12k_mac_change_chanctx_arg arg = { .ctx = ctx };60786079lockdep_assert_held(&ar->conf_mutex);60806081ieee80211_iterate_active_interfaces_atomic(ar->hw,6082IEEE80211_IFACE_ITER_NORMAL,6083ath12k_mac_change_chanctx_cnt_iter,6084&arg);6085if (arg.n_vifs == 0)6086return;60876088arg.vifs = kcalloc(arg.n_vifs, sizeof(arg.vifs[0]), GFP_KERNEL);6089if (!arg.vifs)6090return;60916092ieee80211_iterate_active_interfaces_atomic(ar->hw,6093IEEE80211_IFACE_ITER_NORMAL,6094ath12k_mac_change_chanctx_fill_iter,6095&arg);60966097ath12k_mac_update_vif_chan(ar, arg.vifs, arg.n_vifs);60986099kfree(arg.vifs);6100}61016102static void ath12k_mac_op_change_chanctx(struct ieee80211_hw *hw,6103struct ieee80211_chanctx_conf *ctx,6104u32 changed)6105{6106struct ath12k *ar = hw->priv;6107struct ath12k_base *ab = ar->ab;61086109mutex_lock(&ar->conf_mutex);61106111ath12k_dbg(ab, ATH12K_DBG_MAC,6112"mac chanctx change freq %u width %d ptr %pK changed %x\n",6113ctx->def.chan->center_freq, ctx->def.width, ctx, changed);61146115/* This shouldn't really happen because channel switching should use6116* switch_vif_chanctx().6117*/6118if (WARN_ON(changed & IEEE80211_CHANCTX_CHANGE_CHANNEL))6119goto unlock;61206121if (changed & IEEE80211_CHANCTX_CHANGE_WIDTH)6122ath12k_mac_update_active_vif_chan(ar, ctx);61236124/* TODO: Recalc radar detection */61256126unlock:6127mutex_unlock(&ar->conf_mutex);6128}61296130static int ath12k_start_vdev_delay(struct ieee80211_hw *hw,6131struct ieee80211_vif *vif)6132{6133struct ath12k *ar = hw->priv;6134struct ath12k_base *ab = ar->ab;6135struct ath12k_vif *arvif = (void *)vif->drv_priv;6136int ret;61376138if (WARN_ON(arvif->is_started))6139return -EBUSY;61406141ret = ath12k_mac_vdev_start(arvif, &arvif->chanctx.def);6142if (ret) {6143ath12k_warn(ab, "failed to start vdev %i addr %pM on freq %d: %d\n",6144arvif->vdev_id, vif->addr,6145arvif->chanctx.def.chan->center_freq, ret);6146return ret;6147}61486149if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR) {6150ret = ath12k_monitor_vdev_up(ar, arvif->vdev_id);6151if (ret) {6152ath12k_warn(ab, "failed put monitor up: %d\n", ret);6153return ret;6154}6155}61566157arvif->is_started = true;61586159/* TODO: Setup ps and cts/rts protection */6160return 0;6161}61626163static int6164ath12k_mac_op_assign_vif_chanctx(struct ieee80211_hw *hw,6165struct ieee80211_vif *vif,6166struct ieee80211_bss_conf *link_conf,6167struct ieee80211_chanctx_conf *ctx)6168{6169struct ath12k *ar = hw->priv;6170struct ath12k_base *ab = ar->ab;6171struct ath12k_vif *arvif = (void *)vif->drv_priv;6172int ret;6173struct ath12k_wmi_peer_create_arg param;61746175mutex_lock(&ar->conf_mutex);61766177ath12k_dbg(ab, ATH12K_DBG_MAC,6178"mac chanctx assign ptr %pK vdev_id %i\n",6179ctx, arvif->vdev_id);61806181arvif->punct_bitmap = link_conf->eht_puncturing;61826183/* for some targets bss peer must be created before vdev_start */6184if (ab->hw_params->vdev_start_delay &&6185arvif->vdev_type != WMI_VDEV_TYPE_AP &&6186arvif->vdev_type != WMI_VDEV_TYPE_MONITOR &&6187!ath12k_peer_exist_by_vdev_id(ab, arvif->vdev_id)) {6188memcpy(&arvif->chanctx, ctx, sizeof(*ctx));6189ret = 0;6190goto out;6191}61926193if (WARN_ON(arvif->is_started)) {6194ret = -EBUSY;6195goto out;6196}61976198if (ab->hw_params->vdev_start_delay &&6199(arvif->vdev_type == WMI_VDEV_TYPE_AP ||6200arvif->vdev_type == WMI_VDEV_TYPE_MONITOR)) {6201param.vdev_id = arvif->vdev_id;6202param.peer_type = WMI_PEER_TYPE_DEFAULT;6203param.peer_addr = ar->mac_addr;62046205ret = ath12k_peer_create(ar, arvif, NULL, ¶m);6206if (ret) {6207ath12k_warn(ab, "failed to create peer after vdev start delay: %d",6208ret);6209goto out;6210}6211}62126213if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR) {6214ret = ath12k_mac_monitor_start(ar);6215if (ret)6216goto out;6217arvif->is_started = true;6218goto out;6219}62206221ret = ath12k_mac_vdev_start(arvif, &ctx->def);6222if (ret) {6223ath12k_warn(ab, "failed to start vdev %i addr %pM on freq %d: %d\n",6224arvif->vdev_id, vif->addr,6225ctx->def.chan->center_freq, ret);6226goto out;6227}62286229if (arvif->vdev_type != WMI_VDEV_TYPE_MONITOR && ar->monitor_vdev_created)6230ath12k_mac_monitor_start(ar);62316232arvif->is_started = true;62336234/* TODO: Setup ps and cts/rts protection */62356236out:6237mutex_unlock(&ar->conf_mutex);62386239return ret;6240}62416242static void6243ath12k_mac_op_unassign_vif_chanctx(struct ieee80211_hw *hw,6244struct ieee80211_vif *vif,6245struct ieee80211_bss_conf *link_conf,6246struct ieee80211_chanctx_conf *ctx)6247{6248struct ath12k *ar = hw->priv;6249struct ath12k_base *ab = ar->ab;6250struct ath12k_vif *arvif = (void *)vif->drv_priv;6251int ret;62526253mutex_lock(&ar->conf_mutex);62546255ath12k_dbg(ab, ATH12K_DBG_MAC,6256"mac chanctx unassign ptr %pK vdev_id %i\n",6257ctx, arvif->vdev_id);62586259WARN_ON(!arvif->is_started);62606261if (ab->hw_params->vdev_start_delay &&6262arvif->vdev_type == WMI_VDEV_TYPE_MONITOR &&6263ath12k_peer_find_by_addr(ab, ar->mac_addr))6264ath12k_peer_delete(ar, arvif->vdev_id, ar->mac_addr);62656266if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR) {6267ret = ath12k_mac_monitor_stop(ar);6268if (ret) {6269mutex_unlock(&ar->conf_mutex);6270return;6271}62726273arvif->is_started = false;6274}62756276ret = ath12k_mac_vdev_stop(arvif);6277if (ret)6278ath12k_warn(ab, "failed to stop vdev %i: %d\n",6279arvif->vdev_id, ret);62806281arvif->is_started = false;62826283if (ab->hw_params->vdev_start_delay &&6284arvif->vdev_type == WMI_VDEV_TYPE_MONITOR)6285ath12k_wmi_vdev_down(ar, arvif->vdev_id);62866287if (arvif->vdev_type != WMI_VDEV_TYPE_MONITOR &&6288ar->num_started_vdevs == 1 && ar->monitor_vdev_created)6289ath12k_mac_monitor_stop(ar);62906291mutex_unlock(&ar->conf_mutex);6292}62936294static int6295ath12k_mac_op_switch_vif_chanctx(struct ieee80211_hw *hw,6296struct ieee80211_vif_chanctx_switch *vifs,6297int n_vifs,6298enum ieee80211_chanctx_switch_mode mode)6299{6300struct ath12k *ar = hw->priv;63016302mutex_lock(&ar->conf_mutex);63036304ath12k_dbg(ar->ab, ATH12K_DBG_MAC,6305"mac chanctx switch n_vifs %d mode %d\n",6306n_vifs, mode);6307ath12k_mac_update_vif_chan(ar, vifs, n_vifs);63086309mutex_unlock(&ar->conf_mutex);63106311return 0;6312}63136314static int6315ath12k_set_vdev_param_to_all_vifs(struct ath12k *ar, int param, u32 value)6316{6317struct ath12k_vif *arvif;6318int ret = 0;63196320mutex_lock(&ar->conf_mutex);6321list_for_each_entry(arvif, &ar->arvifs, list) {6322ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "setting mac vdev %d param %d value %d\n",6323param, arvif->vdev_id, value);63246325ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,6326param, value);6327if (ret) {6328ath12k_warn(ar->ab, "failed to set param %d for vdev %d: %d\n",6329param, arvif->vdev_id, ret);6330break;6331}6332}6333mutex_unlock(&ar->conf_mutex);6334return ret;6335}63366337/* mac80211 stores device specific RTS/Fragmentation threshold value,6338* this is set interface specific to firmware from ath12k driver6339*/6340static int ath12k_mac_op_set_rts_threshold(struct ieee80211_hw *hw, u32 value)6341{6342struct ath12k *ar = hw->priv;6343int param_id = WMI_VDEV_PARAM_RTS_THRESHOLD;63446345return ath12k_set_vdev_param_to_all_vifs(ar, param_id, value);6346}63476348static int ath12k_mac_op_set_frag_threshold(struct ieee80211_hw *hw, u32 value)6349{6350/* Even though there's a WMI vdev param for fragmentation threshold no6351* known firmware actually implements it. Moreover it is not possible to6352* rely frame fragmentation to mac80211 because firmware clears the6353* "more fragments" bit in frame control making it impossible for remote6354* devices to reassemble frames.6355*6356* Hence implement a dummy callback just to say fragmentation isn't6357* supported. This effectively prevents mac80211 from doing frame6358* fragmentation in software.6359*/6360return -EOPNOTSUPP;6361}63626363static void ath12k_mac_op_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,6364u32 queues, bool drop)6365{6366struct ath12k *ar = hw->priv;6367long time_left;63686369if (drop)6370return;63716372time_left = wait_event_timeout(ar->dp.tx_empty_waitq,6373(atomic_read(&ar->dp.num_tx_pending) == 0),6374ATH12K_FLUSH_TIMEOUT);6375if (time_left == 0)6376ath12k_warn(ar->ab, "failed to flush transmit queue %ld\n", time_left);63776378time_left = wait_event_timeout(ar->txmgmt_empty_waitq,6379(atomic_read(&ar->num_pending_mgmt_tx) == 0),6380ATH12K_FLUSH_TIMEOUT);6381if (time_left == 0)6382ath12k_warn(ar->ab, "failed to flush mgmt transmit queue %ld\n",6383time_left);6384}63856386static int6387ath12k_mac_bitrate_mask_num_ht_rates(struct ath12k *ar,6388enum nl80211_band band,6389const struct cfg80211_bitrate_mask *mask)6390{6391int num_rates = 0;6392int i;63936394for (i = 0; i < ARRAY_SIZE(mask->control[band].ht_mcs); i++)6395num_rates += hweight16(mask->control[band].ht_mcs[i]);63966397return num_rates;6398}63996400static bool6401ath12k_mac_has_single_legacy_rate(struct ath12k *ar,6402enum nl80211_band band,6403const struct cfg80211_bitrate_mask *mask)6404{6405int num_rates = 0;64066407num_rates = hweight32(mask->control[band].legacy);64086409if (ath12k_mac_bitrate_mask_num_ht_rates(ar, band, mask))6410return false;64116412if (ath12k_mac_bitrate_mask_num_vht_rates(ar, band, mask))6413return false;64146415return num_rates == 1;6416}64176418static bool6419ath12k_mac_bitrate_mask_get_single_nss(struct ath12k *ar,6420enum nl80211_band band,6421const struct cfg80211_bitrate_mask *mask,6422int *nss)6423{6424struct ieee80211_supported_band *sband = &ar->mac.sbands[band];6425u16 vht_mcs_map = le16_to_cpu(sband->vht_cap.vht_mcs.tx_mcs_map);6426u8 ht_nss_mask = 0;6427u8 vht_nss_mask = 0;6428int i;64296430/* No need to consider legacy here. Basic rates are always present6431* in bitrate mask6432*/64336434for (i = 0; i < ARRAY_SIZE(mask->control[band].ht_mcs); i++) {6435if (mask->control[band].ht_mcs[i] == 0)6436continue;6437else if (mask->control[band].ht_mcs[i] ==6438sband->ht_cap.mcs.rx_mask[i])6439ht_nss_mask |= BIT(i);6440else6441return false;6442}64436444for (i = 0; i < ARRAY_SIZE(mask->control[band].vht_mcs); i++) {6445if (mask->control[band].vht_mcs[i] == 0)6446continue;6447else if (mask->control[band].vht_mcs[i] ==6448ath12k_mac_get_max_vht_mcs_map(vht_mcs_map, i))6449vht_nss_mask |= BIT(i);6450else6451return false;6452}64536454if (ht_nss_mask != vht_nss_mask)6455return false;64566457if (ht_nss_mask == 0)6458return false;64596460if (BIT(fls(ht_nss_mask)) - 1 != ht_nss_mask)6461return false;64626463*nss = fls(ht_nss_mask);64646465return true;6466}64676468static int6469ath12k_mac_get_single_legacy_rate(struct ath12k *ar,6470enum nl80211_band band,6471const struct cfg80211_bitrate_mask *mask,6472u32 *rate, u8 *nss)6473{6474int rate_idx;6475u16 bitrate;6476u8 preamble;6477u8 hw_rate;64786479if (hweight32(mask->control[band].legacy) != 1)6480return -EINVAL;64816482rate_idx = ffs(mask->control[band].legacy) - 1;64836484if (band == NL80211_BAND_5GHZ || band == NL80211_BAND_6GHZ)6485rate_idx += ATH12K_MAC_FIRST_OFDM_RATE_IDX;64866487hw_rate = ath12k_legacy_rates[rate_idx].hw_value;6488bitrate = ath12k_legacy_rates[rate_idx].bitrate;64896490if (ath12k_mac_bitrate_is_cck(bitrate))6491preamble = WMI_RATE_PREAMBLE_CCK;6492else6493preamble = WMI_RATE_PREAMBLE_OFDM;64946495*nss = 1;6496*rate = ATH12K_HW_RATE_CODE(hw_rate, 0, preamble);64976498return 0;6499}65006501static int ath12k_mac_set_fixed_rate_params(struct ath12k_vif *arvif,6502u32 rate, u8 nss, u8 sgi, u8 ldpc)6503{6504struct ath12k *ar = arvif->ar;6505u32 vdev_param;6506int ret;65076508lockdep_assert_held(&ar->conf_mutex);65096510ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac set fixed rate params vdev %i rate 0x%02x nss %u sgi %u\n",6511arvif->vdev_id, rate, nss, sgi);65126513vdev_param = WMI_VDEV_PARAM_FIXED_RATE;6514ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,6515vdev_param, rate);6516if (ret) {6517ath12k_warn(ar->ab, "failed to set fixed rate param 0x%02x: %d\n",6518rate, ret);6519return ret;6520}65216522vdev_param = WMI_VDEV_PARAM_NSS;6523ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,6524vdev_param, nss);6525if (ret) {6526ath12k_warn(ar->ab, "failed to set nss param %d: %d\n",6527nss, ret);6528return ret;6529}65306531vdev_param = WMI_VDEV_PARAM_SGI;6532ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,6533vdev_param, sgi);6534if (ret) {6535ath12k_warn(ar->ab, "failed to set sgi param %d: %d\n",6536sgi, ret);6537return ret;6538}65396540vdev_param = WMI_VDEV_PARAM_LDPC;6541ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,6542vdev_param, ldpc);6543if (ret) {6544ath12k_warn(ar->ab, "failed to set ldpc param %d: %d\n",6545ldpc, ret);6546return ret;6547}65486549return 0;6550}65516552static bool6553ath12k_mac_vht_mcs_range_present(struct ath12k *ar,6554enum nl80211_band band,6555const struct cfg80211_bitrate_mask *mask)6556{6557int i;6558u16 vht_mcs;65596560for (i = 0; i < NL80211_VHT_NSS_MAX; i++) {6561vht_mcs = mask->control[band].vht_mcs[i];65626563switch (vht_mcs) {6564case 0:6565case BIT(8) - 1:6566case BIT(9) - 1:6567case BIT(10) - 1:6568break;6569default:6570return false;6571}6572}65736574return true;6575}65766577static void ath12k_mac_set_bitrate_mask_iter(void *data,6578struct ieee80211_sta *sta)6579{6580struct ath12k_vif *arvif = data;6581struct ath12k_sta *arsta = (struct ath12k_sta *)sta->drv_priv;6582struct ath12k *ar = arvif->ar;65836584spin_lock_bh(&ar->data_lock);6585arsta->changed |= IEEE80211_RC_SUPP_RATES_CHANGED;6586spin_unlock_bh(&ar->data_lock);65876588ieee80211_queue_work(ar->hw, &arsta->update_wk);6589}65906591static void ath12k_mac_disable_peer_fixed_rate(void *data,6592struct ieee80211_sta *sta)6593{6594struct ath12k_vif *arvif = data;6595struct ath12k *ar = arvif->ar;6596int ret;65976598ret = ath12k_wmi_set_peer_param(ar, sta->addr,6599arvif->vdev_id,6600WMI_PEER_PARAM_FIXED_RATE,6601WMI_FIXED_RATE_NONE);6602if (ret)6603ath12k_warn(ar->ab,6604"failed to disable peer fixed rate for STA %pM ret %d\n",6605sta->addr, ret);6606}66076608static int6609ath12k_mac_op_set_bitrate_mask(struct ieee80211_hw *hw,6610struct ieee80211_vif *vif,6611const struct cfg80211_bitrate_mask *mask)6612{6613struct ath12k_vif *arvif = (void *)vif->drv_priv;6614struct cfg80211_chan_def def;6615struct ath12k *ar = arvif->ar;6616enum nl80211_band band;6617const u8 *ht_mcs_mask;6618const u16 *vht_mcs_mask;6619u32 rate;6620u8 nss;6621u8 sgi;6622u8 ldpc;6623int single_nss;6624int ret;6625int num_rates;66266627if (ath12k_mac_vif_chan(vif, &def))6628return -EPERM;66296630band = def.chan->band;6631ht_mcs_mask = mask->control[band].ht_mcs;6632vht_mcs_mask = mask->control[band].vht_mcs;6633ldpc = !!(ar->ht_cap_info & WMI_HT_CAP_LDPC);66346635sgi = mask->control[band].gi;6636if (sgi == NL80211_TXRATE_FORCE_LGI)6637return -EINVAL;66386639/* mac80211 doesn't support sending a fixed HT/VHT MCS alone, rather it6640* requires passing at least one of used basic rates along with them.6641* Fixed rate setting across different preambles(legacy, HT, VHT) is6642* not supported by the FW. Hence use of FIXED_RATE vdev param is not6643* suitable for setting single HT/VHT rates.6644* But, there could be a single basic rate passed from userspace which6645* can be done through the FIXED_RATE param.6646*/6647if (ath12k_mac_has_single_legacy_rate(ar, band, mask)) {6648ret = ath12k_mac_get_single_legacy_rate(ar, band, mask, &rate,6649&nss);6650if (ret) {6651ath12k_warn(ar->ab, "failed to get single legacy rate for vdev %i: %d\n",6652arvif->vdev_id, ret);6653return ret;6654}6655ieee80211_iterate_stations_atomic(ar->hw,6656ath12k_mac_disable_peer_fixed_rate,6657arvif);6658} else if (ath12k_mac_bitrate_mask_get_single_nss(ar, band, mask,6659&single_nss)) {6660rate = WMI_FIXED_RATE_NONE;6661nss = single_nss;6662} else {6663rate = WMI_FIXED_RATE_NONE;6664nss = min_t(u32, ar->num_tx_chains,6665max(ath12k_mac_max_ht_nss(ht_mcs_mask),6666ath12k_mac_max_vht_nss(vht_mcs_mask)));66676668/* If multiple rates across different preambles are given6669* we can reconfigure this info with all peers using PEER_ASSOC6670* command with the below exception cases.6671* - Single VHT Rate : peer_assoc command accommodates only MCS6672* range values i.e 0-7, 0-8, 0-9 for VHT. Though mac802116673* mandates passing basic rates along with HT/VHT rates, FW6674* doesn't allow switching from VHT to Legacy. Hence instead of6675* setting legacy and VHT rates using RATEMASK_CMD vdev cmd,6676* we could set this VHT rate as peer fixed rate param, which6677* will override FIXED rate and FW rate control algorithm.6678* If single VHT rate is passed along with HT rates, we select6679* the VHT rate as fixed rate for vht peers.6680* - Multiple VHT Rates : When Multiple VHT rates are given,this6681* can be set using RATEMASK CMD which uses FW rate-ctl alg.6682* TODO: Setting multiple VHT MCS and replacing peer_assoc with6683* RATEMASK_CMDID can cover all use cases of setting rates6684* across multiple preambles and rates within same type.6685* But requires more validation of the command at this point.6686*/66876688num_rates = ath12k_mac_bitrate_mask_num_vht_rates(ar, band,6689mask);66906691if (!ath12k_mac_vht_mcs_range_present(ar, band, mask) &&6692num_rates > 1) {6693/* TODO: Handle multiple VHT MCS values setting using6694* RATEMASK CMD6695*/6696ath12k_warn(ar->ab,6697"Setting more than one MCS Value in bitrate mask not supported\n");6698return -EINVAL;6699}67006701ieee80211_iterate_stations_atomic(ar->hw,6702ath12k_mac_disable_peer_fixed_rate,6703arvif);67046705mutex_lock(&ar->conf_mutex);67066707arvif->bitrate_mask = *mask;6708ieee80211_iterate_stations_atomic(ar->hw,6709ath12k_mac_set_bitrate_mask_iter,6710arvif);67116712mutex_unlock(&ar->conf_mutex);6713}67146715mutex_lock(&ar->conf_mutex);67166717ret = ath12k_mac_set_fixed_rate_params(arvif, rate, nss, sgi, ldpc);6718if (ret) {6719ath12k_warn(ar->ab, "failed to set fixed rate params on vdev %i: %d\n",6720arvif->vdev_id, ret);6721}67226723mutex_unlock(&ar->conf_mutex);67246725return ret;6726}67276728static void6729ath12k_mac_op_reconfig_complete(struct ieee80211_hw *hw,6730enum ieee80211_reconfig_type reconfig_type)6731{6732struct ath12k *ar = hw->priv;6733struct ath12k_base *ab = ar->ab;6734struct ath12k_vif *arvif;6735int recovery_count;67366737if (reconfig_type != IEEE80211_RECONFIG_TYPE_RESTART)6738return;67396740mutex_lock(&ar->conf_mutex);67416742if (ar->state == ATH12K_STATE_RESTARTED) {6743ath12k_warn(ar->ab, "pdev %d successfully recovered\n",6744ar->pdev->pdev_id);6745ar->state = ATH12K_STATE_ON;6746ieee80211_wake_queues(ar->hw);67476748if (ab->is_reset) {6749recovery_count = atomic_inc_return(&ab->recovery_count);6750ath12k_dbg(ab, ATH12K_DBG_BOOT, "recovery count %d\n",6751recovery_count);6752/* When there are multiple radios in an SOC,6753* the recovery has to be done for each radio6754*/6755if (recovery_count == ab->num_radios) {6756atomic_dec(&ab->reset_count);6757complete(&ab->reset_complete);6758ab->is_reset = false;6759atomic_set(&ab->fail_cont_count, 0);6760ath12k_dbg(ab, ATH12K_DBG_BOOT, "reset success\n");6761}6762}67636764list_for_each_entry(arvif, &ar->arvifs, list) {6765ath12k_dbg(ab, ATH12K_DBG_BOOT,6766"reconfig cipher %d up %d vdev type %d\n",6767arvif->key_cipher,6768arvif->is_up,6769arvif->vdev_type);6770/* After trigger disconnect, then upper layer will6771* trigger connect again, then the PN number of6772* upper layer will be reset to keep up with AP6773* side, hence PN number mis-match will not happened.6774*/6775if (arvif->is_up &&6776arvif->vdev_type == WMI_VDEV_TYPE_STA &&6777arvif->vdev_subtype == WMI_VDEV_SUBTYPE_NONE) {6778ieee80211_hw_restart_disconnect(arvif->vif);6779ath12k_dbg(ab, ATH12K_DBG_BOOT,6780"restart disconnect\n");6781}6782}6783}67846785mutex_unlock(&ar->conf_mutex);6786}67876788static void6789ath12k_mac_update_bss_chan_survey(struct ath12k *ar,6790struct ieee80211_channel *channel)6791{6792int ret;6793enum wmi_bss_chan_info_req_type type = WMI_BSS_SURVEY_REQ_TYPE_READ;67946795lockdep_assert_held(&ar->conf_mutex);67966797if (!test_bit(WMI_TLV_SERVICE_BSS_CHANNEL_INFO_64, ar->ab->wmi_ab.svc_map) ||6798ar->rx_channel != channel)6799return;68006801if (ar->scan.state != ATH12K_SCAN_IDLE) {6802ath12k_dbg(ar->ab, ATH12K_DBG_MAC,6803"ignoring bss chan info req while scanning..\n");6804return;6805}68066807reinit_completion(&ar->bss_survey_done);68086809ret = ath12k_wmi_pdev_bss_chan_info_request(ar, type);6810if (ret) {6811ath12k_warn(ar->ab, "failed to send pdev bss chan info request\n");6812return;6813}68146815ret = wait_for_completion_timeout(&ar->bss_survey_done, 3 * HZ);6816if (ret == 0)6817ath12k_warn(ar->ab, "bss channel survey timed out\n");6818}68196820static int ath12k_mac_op_get_survey(struct ieee80211_hw *hw, int idx,6821struct survey_info *survey)6822{6823struct ath12k *ar = hw->priv;6824struct ieee80211_supported_band *sband;6825struct survey_info *ar_survey;6826int ret = 0;68276828if (idx >= ATH12K_NUM_CHANS)6829return -ENOENT;68306831ar_survey = &ar->survey[idx];68326833mutex_lock(&ar->conf_mutex);68346835sband = hw->wiphy->bands[NL80211_BAND_2GHZ];6836if (sband && idx >= sband->n_channels) {6837idx -= sband->n_channels;6838sband = NULL;6839}68406841if (!sband)6842sband = hw->wiphy->bands[NL80211_BAND_5GHZ];68436844if (!sband || idx >= sband->n_channels) {6845ret = -ENOENT;6846goto exit;6847}68486849ath12k_mac_update_bss_chan_survey(ar, &sband->channels[idx]);68506851spin_lock_bh(&ar->data_lock);6852memcpy(survey, ar_survey, sizeof(*survey));6853spin_unlock_bh(&ar->data_lock);68546855survey->channel = &sband->channels[idx];68566857if (ar->rx_channel == survey->channel)6858survey->filled |= SURVEY_INFO_IN_USE;68596860exit:6861mutex_unlock(&ar->conf_mutex);6862return ret;6863}68646865static void ath12k_mac_op_sta_statistics(struct ieee80211_hw *hw,6866struct ieee80211_vif *vif,6867struct ieee80211_sta *sta,6868struct station_info *sinfo)6869{6870struct ath12k_sta *arsta = (struct ath12k_sta *)sta->drv_priv;68716872sinfo->rx_duration = arsta->rx_duration;6873sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_DURATION);68746875sinfo->tx_duration = arsta->tx_duration;6876sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_DURATION);68776878if (!arsta->txrate.legacy && !arsta->txrate.nss)6879return;68806881if (arsta->txrate.legacy) {6882sinfo->txrate.legacy = arsta->txrate.legacy;6883} else {6884sinfo->txrate.mcs = arsta->txrate.mcs;6885sinfo->txrate.nss = arsta->txrate.nss;6886sinfo->txrate.bw = arsta->txrate.bw;6887sinfo->txrate.he_gi = arsta->txrate.he_gi;6888sinfo->txrate.he_dcm = arsta->txrate.he_dcm;6889sinfo->txrate.he_ru_alloc = arsta->txrate.he_ru_alloc;6890}6891sinfo->txrate.flags = arsta->txrate.flags;6892sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE);68936894/* TODO: Use real NF instead of default one. */6895sinfo->signal = arsta->rssi_comb + ATH12K_DEFAULT_NOISE_FLOOR;6896sinfo->filled |= BIT_ULL(NL80211_STA_INFO_SIGNAL);6897}68986899static const struct ieee80211_ops ath12k_ops = {6900.tx = ath12k_mac_op_tx,6901.wake_tx_queue = ieee80211_handle_wake_tx_queue,6902.start = ath12k_mac_op_start,6903.stop = ath12k_mac_op_stop,6904.reconfig_complete = ath12k_mac_op_reconfig_complete,6905.add_interface = ath12k_mac_op_add_interface,6906.remove_interface = ath12k_mac_op_remove_interface,6907.update_vif_offload = ath12k_mac_op_update_vif_offload,6908.config = ath12k_mac_op_config,6909.bss_info_changed = ath12k_mac_op_bss_info_changed,6910.configure_filter = ath12k_mac_op_configure_filter,6911.hw_scan = ath12k_mac_op_hw_scan,6912.cancel_hw_scan = ath12k_mac_op_cancel_hw_scan,6913.set_key = ath12k_mac_op_set_key,6914.sta_state = ath12k_mac_op_sta_state,6915.sta_set_txpwr = ath12k_mac_op_sta_set_txpwr,6916.sta_rc_update = ath12k_mac_op_sta_rc_update,6917.conf_tx = ath12k_mac_op_conf_tx,6918.set_antenna = ath12k_mac_op_set_antenna,6919.get_antenna = ath12k_mac_op_get_antenna,6920.ampdu_action = ath12k_mac_op_ampdu_action,6921.add_chanctx = ath12k_mac_op_add_chanctx,6922.remove_chanctx = ath12k_mac_op_remove_chanctx,6923.change_chanctx = ath12k_mac_op_change_chanctx,6924.assign_vif_chanctx = ath12k_mac_op_assign_vif_chanctx,6925.unassign_vif_chanctx = ath12k_mac_op_unassign_vif_chanctx,6926.switch_vif_chanctx = ath12k_mac_op_switch_vif_chanctx,6927.set_rts_threshold = ath12k_mac_op_set_rts_threshold,6928.set_frag_threshold = ath12k_mac_op_set_frag_threshold,6929.set_bitrate_mask = ath12k_mac_op_set_bitrate_mask,6930.get_survey = ath12k_mac_op_get_survey,6931.flush = ath12k_mac_op_flush,6932.sta_statistics = ath12k_mac_op_sta_statistics,6933};69346935static void ath12k_mac_update_ch_list(struct ath12k *ar,6936struct ieee80211_supported_band *band,6937u32 freq_low, u32 freq_high)6938{6939int i;69406941if (!(freq_low && freq_high))6942return;69436944for (i = 0; i < band->n_channels; i++) {6945if (band->channels[i].center_freq < freq_low ||6946band->channels[i].center_freq > freq_high)6947band->channels[i].flags |= IEEE80211_CHAN_DISABLED;6948}6949}69506951static u32 ath12k_get_phy_id(struct ath12k *ar, u32 band)6952{6953struct ath12k_pdev *pdev = ar->pdev;6954struct ath12k_pdev_cap *pdev_cap = &pdev->cap;69556956if (band == WMI_HOST_WLAN_2G_CAP)6957return pdev_cap->band[NL80211_BAND_2GHZ].phy_id;69586959if (band == WMI_HOST_WLAN_5G_CAP)6960return pdev_cap->band[NL80211_BAND_5GHZ].phy_id;69616962ath12k_warn(ar->ab, "unsupported phy cap:%d\n", band);69636964return 0;6965}69666967static int ath12k_mac_setup_channels_rates(struct ath12k *ar,6968u32 supported_bands)6969{6970struct ieee80211_supported_band *band;6971struct ath12k_wmi_hal_reg_capabilities_ext_arg *reg_cap;6972void *channels;6973u32 phy_id;69746975BUILD_BUG_ON((ARRAY_SIZE(ath12k_2ghz_channels) +6976ARRAY_SIZE(ath12k_5ghz_channels) +6977ARRAY_SIZE(ath12k_6ghz_channels)) !=6978ATH12K_NUM_CHANS);69796980reg_cap = &ar->ab->hal_reg_cap[ar->pdev_idx];69816982if (supported_bands & WMI_HOST_WLAN_2G_CAP) {6983channels = kmemdup(ath12k_2ghz_channels,6984sizeof(ath12k_2ghz_channels),6985GFP_KERNEL);6986if (!channels)6987return -ENOMEM;69886989band = &ar->mac.sbands[NL80211_BAND_2GHZ];6990band->band = NL80211_BAND_2GHZ;6991band->n_channels = ARRAY_SIZE(ath12k_2ghz_channels);6992band->channels = channels;6993band->n_bitrates = ath12k_g_rates_size;6994band->bitrates = ath12k_g_rates;6995ar->hw->wiphy->bands[NL80211_BAND_2GHZ] = band;69966997if (ar->ab->hw_params->single_pdev_only) {6998phy_id = ath12k_get_phy_id(ar, WMI_HOST_WLAN_2G_CAP);6999reg_cap = &ar->ab->hal_reg_cap[phy_id];7000}7001ath12k_mac_update_ch_list(ar, band,7002reg_cap->low_2ghz_chan,7003reg_cap->high_2ghz_chan);7004}70057006if (supported_bands & WMI_HOST_WLAN_5G_CAP) {7007if (reg_cap->high_5ghz_chan >= ATH12K_MAX_6G_FREQ) {7008channels = kmemdup(ath12k_6ghz_channels,7009sizeof(ath12k_6ghz_channels), GFP_KERNEL);7010if (!channels) {7011kfree(ar->mac.sbands[NL80211_BAND_2GHZ].channels);7012return -ENOMEM;7013}70147015ar->supports_6ghz = true;7016band = &ar->mac.sbands[NL80211_BAND_6GHZ];7017band->band = NL80211_BAND_6GHZ;7018band->n_channels = ARRAY_SIZE(ath12k_6ghz_channels);7019band->channels = channels;7020band->n_bitrates = ath12k_a_rates_size;7021band->bitrates = ath12k_a_rates;7022ar->hw->wiphy->bands[NL80211_BAND_6GHZ] = band;7023ath12k_mac_update_ch_list(ar, band,7024reg_cap->low_5ghz_chan,7025reg_cap->high_5ghz_chan);7026}70277028if (reg_cap->low_5ghz_chan < ATH12K_MIN_6G_FREQ) {7029channels = kmemdup(ath12k_5ghz_channels,7030sizeof(ath12k_5ghz_channels),7031GFP_KERNEL);7032if (!channels) {7033kfree(ar->mac.sbands[NL80211_BAND_2GHZ].channels);7034kfree(ar->mac.sbands[NL80211_BAND_6GHZ].channels);7035return -ENOMEM;7036}70377038band = &ar->mac.sbands[NL80211_BAND_5GHZ];7039band->band = NL80211_BAND_5GHZ;7040band->n_channels = ARRAY_SIZE(ath12k_5ghz_channels);7041band->channels = channels;7042band->n_bitrates = ath12k_a_rates_size;7043band->bitrates = ath12k_a_rates;7044ar->hw->wiphy->bands[NL80211_BAND_5GHZ] = band;70457046if (ar->ab->hw_params->single_pdev_only) {7047phy_id = ath12k_get_phy_id(ar, WMI_HOST_WLAN_5G_CAP);7048reg_cap = &ar->ab->hal_reg_cap[phy_id];7049}70507051ath12k_mac_update_ch_list(ar, band,7052reg_cap->low_5ghz_chan,7053reg_cap->high_5ghz_chan);7054}7055}70567057return 0;7058}70597060static int ath12k_mac_setup_iface_combinations(struct ath12k *ar)7061{7062struct ath12k_base *ab = ar->ab;7063struct ieee80211_iface_combination *combinations;7064struct ieee80211_iface_limit *limits;7065int n_limits, max_interfaces;7066bool ap, mesh;70677068ap = ab->hw_params->interface_modes & BIT(NL80211_IFTYPE_AP);70697070mesh = IS_ENABLED(CONFIG_MAC80211_MESH) &&7071ab->hw_params->interface_modes & BIT(NL80211_IFTYPE_MESH_POINT);70727073combinations = kzalloc(sizeof(*combinations), GFP_KERNEL);7074if (!combinations)7075return -ENOMEM;70767077if (ap || mesh) {7078n_limits = 2;7079max_interfaces = 16;7080} else {7081n_limits = 1;7082max_interfaces = 1;7083}70847085limits = kcalloc(n_limits, sizeof(*limits), GFP_KERNEL);7086if (!limits) {7087kfree(combinations);7088return -ENOMEM;7089}70907091limits[0].max = 1;7092limits[0].types |= BIT(NL80211_IFTYPE_STATION);70937094if (ap) {7095limits[1].max = max_interfaces;7096limits[1].types |= BIT(NL80211_IFTYPE_AP);7097}70987099if (mesh)7100limits[1].types |= BIT(NL80211_IFTYPE_MESH_POINT);71017102combinations[0].limits = limits;7103combinations[0].n_limits = n_limits;7104combinations[0].max_interfaces = max_interfaces;7105combinations[0].num_different_channels = 1;7106combinations[0].beacon_int_infra_match = true;7107combinations[0].beacon_int_min_gcd = 100;7108combinations[0].radar_detect_widths = BIT(NL80211_CHAN_WIDTH_20_NOHT) |7109BIT(NL80211_CHAN_WIDTH_20) |7110BIT(NL80211_CHAN_WIDTH_40) |7111BIT(NL80211_CHAN_WIDTH_80);71127113ar->hw->wiphy->iface_combinations = combinations;7114ar->hw->wiphy->n_iface_combinations = 1;71157116return 0;7117}71187119static const u8 ath12k_if_types_ext_capa[] = {7120[0] = WLAN_EXT_CAPA1_EXT_CHANNEL_SWITCHING,7121[7] = WLAN_EXT_CAPA8_OPMODE_NOTIF,7122};71237124static const u8 ath12k_if_types_ext_capa_sta[] = {7125[0] = WLAN_EXT_CAPA1_EXT_CHANNEL_SWITCHING,7126[7] = WLAN_EXT_CAPA8_OPMODE_NOTIF,7127[9] = WLAN_EXT_CAPA10_TWT_REQUESTER_SUPPORT,7128};71297130static const u8 ath12k_if_types_ext_capa_ap[] = {7131[0] = WLAN_EXT_CAPA1_EXT_CHANNEL_SWITCHING,7132[7] = WLAN_EXT_CAPA8_OPMODE_NOTIF,7133[9] = WLAN_EXT_CAPA10_TWT_RESPONDER_SUPPORT,7134};71357136static const struct wiphy_iftype_ext_capab ath12k_iftypes_ext_capa[] = {7137{7138.extended_capabilities = ath12k_if_types_ext_capa,7139.extended_capabilities_mask = ath12k_if_types_ext_capa,7140.extended_capabilities_len = sizeof(ath12k_if_types_ext_capa),7141}, {7142.iftype = NL80211_IFTYPE_STATION,7143.extended_capabilities = ath12k_if_types_ext_capa_sta,7144.extended_capabilities_mask = ath12k_if_types_ext_capa_sta,7145.extended_capabilities_len =7146sizeof(ath12k_if_types_ext_capa_sta),7147}, {7148.iftype = NL80211_IFTYPE_AP,7149.extended_capabilities = ath12k_if_types_ext_capa_ap,7150.extended_capabilities_mask = ath12k_if_types_ext_capa_ap,7151.extended_capabilities_len =7152sizeof(ath12k_if_types_ext_capa_ap),7153},7154};71557156static void __ath12k_mac_unregister(struct ath12k *ar)7157{7158cancel_work_sync(&ar->regd_update_work);71597160ieee80211_unregister_hw(ar->hw);71617162idr_for_each(&ar->txmgmt_idr, ath12k_mac_tx_mgmt_pending_free, ar);7163idr_destroy(&ar->txmgmt_idr);71647165kfree(ar->mac.sbands[NL80211_BAND_2GHZ].channels);7166kfree(ar->mac.sbands[NL80211_BAND_5GHZ].channels);7167kfree(ar->mac.sbands[NL80211_BAND_6GHZ].channels);71687169kfree(ar->hw->wiphy->iface_combinations[0].limits);7170kfree(ar->hw->wiphy->iface_combinations);71717172SET_IEEE80211_DEV(ar->hw, NULL);7173}71747175void ath12k_mac_unregister(struct ath12k_base *ab)7176{7177struct ath12k *ar;7178struct ath12k_pdev *pdev;7179int i;71807181for (i = 0; i < ab->num_radios; i++) {7182pdev = &ab->pdevs[i];7183ar = pdev->ar;7184if (!ar)7185continue;71867187__ath12k_mac_unregister(ar);7188}7189}71907191static int __ath12k_mac_register(struct ath12k *ar)7192{7193struct ath12k_base *ab = ar->ab;7194struct ath12k_pdev_cap *cap = &ar->pdev->cap;7195static const u32 cipher_suites[] = {7196WLAN_CIPHER_SUITE_TKIP,7197WLAN_CIPHER_SUITE_CCMP,7198WLAN_CIPHER_SUITE_AES_CMAC,7199WLAN_CIPHER_SUITE_BIP_CMAC_256,7200WLAN_CIPHER_SUITE_BIP_GMAC_128,7201WLAN_CIPHER_SUITE_BIP_GMAC_256,7202WLAN_CIPHER_SUITE_GCMP,7203WLAN_CIPHER_SUITE_GCMP_256,7204WLAN_CIPHER_SUITE_CCMP_256,7205};7206int ret;7207u32 ht_cap = 0;72087209ath12k_pdev_caps_update(ar);72107211SET_IEEE80211_PERM_ADDR(ar->hw, ar->mac_addr);72127213SET_IEEE80211_DEV(ar->hw, ab->dev);72147215ret = ath12k_mac_setup_channels_rates(ar,7216cap->supported_bands);7217if (ret)7218goto err;72197220ath12k_mac_setup_ht_vht_cap(ar, cap, &ht_cap);7221ath12k_mac_setup_sband_iftype_data(ar, cap);72227223ret = ath12k_mac_setup_iface_combinations(ar);7224if (ret) {7225ath12k_err(ar->ab, "failed to setup interface combinations: %d\n", ret);7226goto err_free_channels;7227}72287229ar->hw->wiphy->available_antennas_rx = cap->rx_chain_mask;7230ar->hw->wiphy->available_antennas_tx = cap->tx_chain_mask;72317232ar->hw->wiphy->interface_modes = ab->hw_params->interface_modes;72337234ieee80211_hw_set(ar->hw, SIGNAL_DBM);7235ieee80211_hw_set(ar->hw, SUPPORTS_PS);7236ieee80211_hw_set(ar->hw, SUPPORTS_DYNAMIC_PS);7237ieee80211_hw_set(ar->hw, MFP_CAPABLE);7238ieee80211_hw_set(ar->hw, REPORTS_TX_ACK_STATUS);7239ieee80211_hw_set(ar->hw, HAS_RATE_CONTROL);7240ieee80211_hw_set(ar->hw, AP_LINK_PS);7241ieee80211_hw_set(ar->hw, SPECTRUM_MGMT);7242ieee80211_hw_set(ar->hw, CONNECTION_MONITOR);7243ieee80211_hw_set(ar->hw, SUPPORTS_PER_STA_GTK);7244ieee80211_hw_set(ar->hw, CHANCTX_STA_CSA);7245ieee80211_hw_set(ar->hw, QUEUE_CONTROL);7246ieee80211_hw_set(ar->hw, SUPPORTS_TX_FRAG);7247ieee80211_hw_set(ar->hw, REPORTS_LOW_ACK);72487249if (ht_cap & WMI_HT_CAP_ENABLED) {7250ieee80211_hw_set(ar->hw, AMPDU_AGGREGATION);7251ieee80211_hw_set(ar->hw, TX_AMPDU_SETUP_IN_HW);7252ieee80211_hw_set(ar->hw, SUPPORTS_REORDERING_BUFFER);7253ieee80211_hw_set(ar->hw, SUPPORTS_AMSDU_IN_AMPDU);7254ieee80211_hw_set(ar->hw, USES_RSS);7255}72567257ar->hw->wiphy->features |= NL80211_FEATURE_STATIC_SMPS;7258ar->hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN;72597260/* TODO: Check if HT capability advertised from firmware is different7261* for each band for a dual band capable radio. It will be tricky to7262* handle it when the ht capability different for each band.7263*/7264if (ht_cap & WMI_HT_CAP_DYNAMIC_SMPS)7265ar->hw->wiphy->features |= NL80211_FEATURE_DYNAMIC_SMPS;72667267ar->hw->wiphy->max_scan_ssids = WLAN_SCAN_PARAMS_MAX_SSID;7268ar->hw->wiphy->max_scan_ie_len = WLAN_SCAN_PARAMS_MAX_IE_LEN;72697270ar->hw->max_listen_interval = ATH12K_MAX_HW_LISTEN_INTERVAL;72717272ar->hw->wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;7273ar->hw->wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;7274ar->hw->wiphy->max_remain_on_channel_duration = 5000;72757276ar->hw->wiphy->flags |= WIPHY_FLAG_AP_UAPSD;7277ar->hw->wiphy->features |= NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE |7278NL80211_FEATURE_AP_SCAN;72797280ar->max_num_stations = TARGET_NUM_STATIONS;7281ar->max_num_peers = TARGET_NUM_PEERS_PDEV;72827283ar->hw->wiphy->max_ap_assoc_sta = ar->max_num_stations;72847285ar->hw->queues = ATH12K_HW_MAX_QUEUES;7286ar->hw->wiphy->tx_queue_len = ATH12K_QUEUE_LEN;7287ar->hw->offchannel_tx_hw_queue = ATH12K_HW_MAX_QUEUES - 1;7288ar->hw->max_rx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF_HE;72897290ar->hw->vif_data_size = sizeof(struct ath12k_vif);7291ar->hw->sta_data_size = sizeof(struct ath12k_sta);72927293wiphy_ext_feature_set(ar->hw->wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST);7294wiphy_ext_feature_set(ar->hw->wiphy, NL80211_EXT_FEATURE_STA_TX_PWR);72957296ar->hw->wiphy->cipher_suites = cipher_suites;7297ar->hw->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);72987299ar->hw->wiphy->iftype_ext_capab = ath12k_iftypes_ext_capa;7300ar->hw->wiphy->num_iftype_ext_capab =7301ARRAY_SIZE(ath12k_iftypes_ext_capa);73027303if (ar->supports_6ghz) {7304wiphy_ext_feature_set(ar->hw->wiphy,7305NL80211_EXT_FEATURE_FILS_DISCOVERY);7306wiphy_ext_feature_set(ar->hw->wiphy,7307NL80211_EXT_FEATURE_UNSOL_BCAST_PROBE_RESP);7308}73097310wiphy_ext_feature_set(ar->hw->wiphy, NL80211_EXT_FEATURE_PUNCT);73117312ath12k_reg_init(ar);73137314if (!test_bit(ATH12K_FLAG_RAW_MODE, &ab->dev_flags)) {7315ar->hw->netdev_features = NETIF_F_HW_CSUM;7316ieee80211_hw_set(ar->hw, SW_CRYPTO_CONTROL);7317ieee80211_hw_set(ar->hw, SUPPORT_FAST_XMIT);7318}73197320ret = ieee80211_register_hw(ar->hw);7321if (ret) {7322ath12k_err(ar->ab, "ieee80211 registration failed: %d\n", ret);7323goto err_free_if_combs;7324}73257326if (!ab->hw_params->supports_monitor)7327/* There's a race between calling ieee80211_register_hw()7328* and here where the monitor mode is enabled for a little7329* while. But that time is so short and in practise it make7330* a difference in real life.7331*/7332ar->hw->wiphy->interface_modes &= ~BIT(NL80211_IFTYPE_MONITOR);73337334/* Apply the regd received during initialization */7335ret = ath12k_regd_update(ar, true);7336if (ret) {7337ath12k_err(ar->ab, "ath12k regd update failed: %d\n", ret);7338goto err_unregister_hw;7339}73407341return 0;73427343err_unregister_hw:7344ieee80211_unregister_hw(ar->hw);73457346err_free_if_combs:7347kfree(ar->hw->wiphy->iface_combinations[0].limits);7348kfree(ar->hw->wiphy->iface_combinations);73497350err_free_channels:7351kfree(ar->mac.sbands[NL80211_BAND_2GHZ].channels);7352kfree(ar->mac.sbands[NL80211_BAND_5GHZ].channels);7353kfree(ar->mac.sbands[NL80211_BAND_6GHZ].channels);73547355err:7356SET_IEEE80211_DEV(ar->hw, NULL);7357return ret;7358}73597360int ath12k_mac_register(struct ath12k_base *ab)7361{7362struct ath12k *ar;7363struct ath12k_pdev *pdev;7364int i;7365int ret;73667367if (test_bit(ATH12K_FLAG_REGISTERED, &ab->dev_flags))7368return 0;73697370for (i = 0; i < ab->num_radios; i++) {7371pdev = &ab->pdevs[i];7372ar = pdev->ar;7373if (ab->pdevs_macaddr_valid) {7374ether_addr_copy(ar->mac_addr, pdev->mac_addr);7375} else {7376ether_addr_copy(ar->mac_addr, ab->mac_addr);7377ar->mac_addr[4] += i;7378}73797380ret = __ath12k_mac_register(ar);7381if (ret)7382goto err_cleanup;73837384init_waitqueue_head(&ar->txmgmt_empty_waitq);7385idr_init(&ar->txmgmt_idr);7386spin_lock_init(&ar->txmgmt_idr_lock);7387}73887389/* Initialize channel counters frequency value in hertz */7390ab->cc_freq_hz = 320000;7391ab->free_vdev_map = (1LL << (ab->num_radios * TARGET_NUM_VDEVS)) - 1;73927393return 0;73947395err_cleanup:7396for (i = i - 1; i >= 0; i--) {7397pdev = &ab->pdevs[i];7398ar = pdev->ar;7399__ath12k_mac_unregister(ar);7400}74017402return ret;7403}74047405int ath12k_mac_allocate(struct ath12k_base *ab)7406{7407struct ieee80211_hw *hw;7408struct ath12k *ar;7409struct ath12k_pdev *pdev;7410int ret;7411int i;74127413if (test_bit(ATH12K_FLAG_REGISTERED, &ab->dev_flags))7414return 0;74157416for (i = 0; i < ab->num_radios; i++) {7417pdev = &ab->pdevs[i];7418hw = ieee80211_alloc_hw(sizeof(struct ath12k), &ath12k_ops);7419if (!hw) {7420ath12k_warn(ab, "failed to allocate mac80211 hw device\n");7421ret = -ENOMEM;7422goto err_free_mac;7423}74247425ar = hw->priv;7426ar->hw = hw;7427ar->ab = ab;7428ar->pdev = pdev;7429ar->pdev_idx = i;7430ar->lmac_id = ath12k_hw_get_mac_from_pdev_id(ab->hw_params, i);74317432ar->wmi = &ab->wmi_ab.wmi[i];7433/* FIXME: wmi[0] is already initialized during attach,7434* Should we do this again?7435*/7436ath12k_wmi_pdev_attach(ab, i);74377438ar->cfg_tx_chainmask = pdev->cap.tx_chain_mask;7439ar->cfg_rx_chainmask = pdev->cap.rx_chain_mask;7440ar->num_tx_chains = hweight32(pdev->cap.tx_chain_mask);7441ar->num_rx_chains = hweight32(pdev->cap.rx_chain_mask);74427443pdev->ar = ar;7444spin_lock_init(&ar->data_lock);7445INIT_LIST_HEAD(&ar->arvifs);7446INIT_LIST_HEAD(&ar->ppdu_stats_info);7447mutex_init(&ar->conf_mutex);7448init_completion(&ar->vdev_setup_done);7449init_completion(&ar->vdev_delete_done);7450init_completion(&ar->peer_assoc_done);7451init_completion(&ar->peer_delete_done);7452init_completion(&ar->install_key_done);7453init_completion(&ar->bss_survey_done);7454init_completion(&ar->scan.started);7455init_completion(&ar->scan.completed);74567457INIT_DELAYED_WORK(&ar->scan.timeout, ath12k_scan_timeout_work);7458INIT_WORK(&ar->regd_update_work, ath12k_regd_update_work);74597460INIT_WORK(&ar->wmi_mgmt_tx_work, ath12k_mgmt_over_wmi_tx_work);7461skb_queue_head_init(&ar->wmi_mgmt_tx_queue);7462clear_bit(ATH12K_FLAG_MONITOR_ENABLED, &ar->monitor_flags);7463}74647465return 0;74667467err_free_mac:7468ath12k_mac_destroy(ab);74697470return ret;7471}74727473void ath12k_mac_destroy(struct ath12k_base *ab)7474{7475struct ath12k *ar;7476struct ath12k_pdev *pdev;7477int i;74787479for (i = 0; i < ab->num_radios; i++) {7480pdev = &ab->pdevs[i];7481ar = pdev->ar;7482if (!ar)7483continue;74847485ieee80211_free_hw(ar->hw);7486pdev->ar = NULL;7487}7488}748974907491