Merge ath-next from git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git
ath.git patches for v6.5. Major changes: ath11k * Multiple Basic Service Set Identifier (MBSSID) and Enhanced MBSSID Advertisement (EMA) support in AP mode
This commit is contained in:
@@ -3643,6 +3643,9 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev,
|
||||
mutex_init(&ar->dump_mutex);
|
||||
spin_lock_init(&ar->data_lock);
|
||||
|
||||
for (int ac = 0; ac < IEEE80211_NUM_ACS; ac++)
|
||||
spin_lock_init(&ar->queue_lock[ac]);
|
||||
|
||||
INIT_LIST_HEAD(&ar->peers);
|
||||
init_waitqueue_head(&ar->peer_mapping_wq);
|
||||
init_waitqueue_head(&ar->htt.empty_tx_wq);
|
||||
|
||||
@@ -1170,6 +1170,9 @@ struct ath10k {
|
||||
/* protects shared structure data */
|
||||
spinlock_t data_lock;
|
||||
|
||||
/* serialize wake_tx_queue calls per ac */
|
||||
spinlock_t queue_lock[IEEE80211_NUM_ACS];
|
||||
|
||||
struct list_head arvifs;
|
||||
struct list_head peers;
|
||||
struct ath10k_peer *peer_map[ATH10K_MAX_NUM_PEER_IDS];
|
||||
|
||||
@@ -293,8 +293,8 @@ void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb)
|
||||
goto free;
|
||||
}
|
||||
|
||||
num_peers = ath10k_wmi_fw_stats_num_peers(&ar->debug.fw_stats.peers);
|
||||
num_vdevs = ath10k_wmi_fw_stats_num_vdevs(&ar->debug.fw_stats.vdevs);
|
||||
num_peers = list_count_nodes(&ar->debug.fw_stats.peers);
|
||||
num_vdevs = list_count_nodes(&ar->debug.fw_stats.vdevs);
|
||||
is_start = (list_empty(&ar->debug.fw_stats.pdevs) &&
|
||||
!list_empty(&stats.pdevs));
|
||||
is_end = (!list_empty(&ar->debug.fw_stats.pdevs) &&
|
||||
|
||||
@@ -4732,13 +4732,14 @@ static void ath10k_mac_op_wake_tx_queue(struct ieee80211_hw *hw,
|
||||
{
|
||||
struct ath10k *ar = hw->priv;
|
||||
int ret;
|
||||
u8 ac;
|
||||
u8 ac = txq->ac;
|
||||
|
||||
ath10k_htt_tx_txq_update(hw, txq);
|
||||
if (ar->htt.tx_q_state.mode != HTT_TX_MODE_SWITCH_PUSH)
|
||||
return;
|
||||
|
||||
ac = txq->ac;
|
||||
spin_lock_bh(&ar->queue_lock[ac]);
|
||||
|
||||
ieee80211_txq_schedule_start(hw, ac);
|
||||
txq = ieee80211_next_txq(hw, ac);
|
||||
if (!txq)
|
||||
@@ -4753,6 +4754,7 @@ static void ath10k_mac_op_wake_tx_queue(struct ieee80211_hw *hw,
|
||||
ath10k_htt_tx_txq_update(hw, txq);
|
||||
out:
|
||||
ieee80211_txq_schedule_end(hw, ac);
|
||||
spin_unlock_bh(&ar->queue_lock[ac]);
|
||||
}
|
||||
|
||||
/* Must not be called with conf_mutex held as workers can use that also. */
|
||||
|
||||
@@ -8164,28 +8164,6 @@ ath10k_wmi_10_2_4_op_gen_pdev_get_tpc_config(struct ath10k *ar, u32 param)
|
||||
return skb;
|
||||
}
|
||||
|
||||
size_t ath10k_wmi_fw_stats_num_peers(struct list_head *head)
|
||||
{
|
||||
struct ath10k_fw_stats_peer *i;
|
||||
size_t num = 0;
|
||||
|
||||
list_for_each_entry(i, head, list)
|
||||
++num;
|
||||
|
||||
return num;
|
||||
}
|
||||
|
||||
size_t ath10k_wmi_fw_stats_num_vdevs(struct list_head *head)
|
||||
{
|
||||
struct ath10k_fw_stats_vdev *i;
|
||||
size_t num = 0;
|
||||
|
||||
list_for_each_entry(i, head, list)
|
||||
++num;
|
||||
|
||||
return num;
|
||||
}
|
||||
|
||||
static void
|
||||
ath10k_wmi_fw_pdev_base_stats_fill(const struct ath10k_fw_stats_pdev *pdev,
|
||||
char *buf, u32 *length)
|
||||
@@ -8462,8 +8440,8 @@ void ath10k_wmi_main_op_fw_stats_fill(struct ath10k *ar,
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
num_peers = ath10k_wmi_fw_stats_num_peers(&fw_stats->peers);
|
||||
num_vdevs = ath10k_wmi_fw_stats_num_vdevs(&fw_stats->vdevs);
|
||||
num_peers = list_count_nodes(&fw_stats->peers);
|
||||
num_vdevs = list_count_nodes(&fw_stats->vdevs);
|
||||
|
||||
ath10k_wmi_fw_pdev_base_stats_fill(pdev, buf, &len);
|
||||
ath10k_wmi_fw_pdev_tx_stats_fill(pdev, buf, &len);
|
||||
@@ -8520,8 +8498,8 @@ void ath10k_wmi_10x_op_fw_stats_fill(struct ath10k *ar,
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
num_peers = ath10k_wmi_fw_stats_num_peers(&fw_stats->peers);
|
||||
num_vdevs = ath10k_wmi_fw_stats_num_vdevs(&fw_stats->vdevs);
|
||||
num_peers = list_count_nodes(&fw_stats->peers);
|
||||
num_vdevs = list_count_nodes(&fw_stats->vdevs);
|
||||
|
||||
ath10k_wmi_fw_pdev_base_stats_fill(pdev, buf, &len);
|
||||
ath10k_wmi_fw_pdev_extra_stats_fill(pdev, buf, &len);
|
||||
@@ -8668,8 +8646,8 @@ void ath10k_wmi_10_4_op_fw_stats_fill(struct ath10k *ar,
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
num_peers = ath10k_wmi_fw_stats_num_peers(&fw_stats->peers);
|
||||
num_vdevs = ath10k_wmi_fw_stats_num_vdevs(&fw_stats->vdevs);
|
||||
num_peers = list_count_nodes(&fw_stats->peers);
|
||||
num_vdevs = list_count_nodes(&fw_stats->vdevs);
|
||||
|
||||
ath10k_wmi_fw_pdev_base_stats_fill(pdev, buf, &len);
|
||||
ath10k_wmi_fw_pdev_extra_stats_fill(pdev, buf, &len);
|
||||
|
||||
@@ -7502,8 +7502,6 @@ void ath10k_wmi_main_op_fw_stats_fill(struct ath10k *ar,
|
||||
void ath10k_wmi_10x_op_fw_stats_fill(struct ath10k *ar,
|
||||
struct ath10k_fw_stats *fw_stats,
|
||||
char *buf);
|
||||
size_t ath10k_wmi_fw_stats_num_peers(struct list_head *head);
|
||||
size_t ath10k_wmi_fw_stats_num_vdevs(struct list_head *head);
|
||||
void ath10k_wmi_10_4_op_fw_stats_fill(struct ath10k *ar,
|
||||
struct ath10k_fw_stats *fw_stats,
|
||||
char *buf);
|
||||
|
||||
@@ -202,6 +202,9 @@ static void ath11k_init_wmi_config_ipq8074(struct ath11k_base *ab,
|
||||
config->twt_ap_sta_count = 1000;
|
||||
config->flag1 |= WMI_RSRC_CFG_FLAG1_BSS_CHANNEL_INFO_64;
|
||||
config->flag1 |= WMI_RSRC_CFG_FLAG1_ACK_RSSI;
|
||||
config->ema_max_vap_cnt = ab->num_radios;
|
||||
config->ema_max_profile_period = TARGET_EMA_MAX_PROFILE_PERIOD;
|
||||
config->beacon_tx_offload_max_vdev += config->ema_max_vap_cnt;
|
||||
}
|
||||
|
||||
static int ath11k_hw_mac_id_to_pdev_id_ipq8074(struct ath11k_hw_params *hw,
|
||||
|
||||
@@ -64,6 +64,7 @@
|
||||
#define TARGET_NUM_WDS_ENTRIES 32
|
||||
#define TARGET_DMA_BURST_SIZE 1
|
||||
#define TARGET_RX_BATCHMODE 1
|
||||
#define TARGET_EMA_MAX_PROFILE_PERIOD 8
|
||||
|
||||
#define ATH11K_HW_MAX_QUEUES 4
|
||||
#define ATH11K_QUEUE_LEN 4096
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// SPDX-License-Identifier: BSD-3-Clause-Clear
|
||||
/*
|
||||
* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <net/mac80211.h>
|
||||
@@ -433,7 +433,7 @@ u8 ath11k_mac_bitrate_to_idx(const struct ieee80211_supported_band *sband,
|
||||
}
|
||||
|
||||
static u32
|
||||
ath11k_mac_max_ht_nss(const u8 ht_mcs_mask[IEEE80211_HT_MCS_MASK_LEN])
|
||||
ath11k_mac_max_ht_nss(const u8 *ht_mcs_mask)
|
||||
{
|
||||
int nss;
|
||||
|
||||
@@ -445,7 +445,7 @@ ath11k_mac_max_ht_nss(const u8 ht_mcs_mask[IEEE80211_HT_MCS_MASK_LEN])
|
||||
}
|
||||
|
||||
static u32
|
||||
ath11k_mac_max_vht_nss(const u16 vht_mcs_mask[NL80211_VHT_NSS_MAX])
|
||||
ath11k_mac_max_vht_nss(const u16 *vht_mcs_mask)
|
||||
{
|
||||
int nss;
|
||||
|
||||
@@ -457,7 +457,7 @@ ath11k_mac_max_vht_nss(const u16 vht_mcs_mask[NL80211_VHT_NSS_MAX])
|
||||
}
|
||||
|
||||
static u32
|
||||
ath11k_mac_max_he_nss(const u16 he_mcs_mask[NL80211_HE_NSS_MAX])
|
||||
ath11k_mac_max_he_nss(const u16 *he_mcs_mask)
|
||||
{
|
||||
int nss;
|
||||
|
||||
@@ -964,7 +964,7 @@ static int ath11k_mac_monitor_vdev_start(struct ath11k *ar, int vdev_id,
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = ath11k_wmi_vdev_up(ar, vdev_id, 0, ar->mac_addr);
|
||||
ret = ath11k_wmi_vdev_up(ar, vdev_id, 0, ar->mac_addr, NULL, 0, 0);
|
||||
if (ret) {
|
||||
ath11k_warn(ar->ab, "failed to put up monitor vdev %i: %d\n",
|
||||
vdev_id, ret);
|
||||
@@ -1351,28 +1351,92 @@ err_mon_del:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ath11k_mac_setup_bcn_tmpl(struct ath11k_vif *arvif)
|
||||
static void ath11k_mac_setup_nontx_vif_rsnie(struct ath11k_vif *arvif,
|
||||
bool tx_arvif_rsnie_present,
|
||||
const u8 *profile, u8 profile_len)
|
||||
{
|
||||
struct ath11k *ar = arvif->ar;
|
||||
struct ath11k_base *ab = ar->ab;
|
||||
struct ieee80211_hw *hw = ar->hw;
|
||||
struct ieee80211_vif *vif = arvif->vif;
|
||||
struct ieee80211_mutable_offsets offs = {};
|
||||
struct sk_buff *bcn;
|
||||
struct ieee80211_mgmt *mgmt;
|
||||
u8 *ies;
|
||||
int ret;
|
||||
if (cfg80211_find_ie(WLAN_EID_RSN, profile, profile_len)) {
|
||||
arvif->rsnie_present = true;
|
||||
} else if (tx_arvif_rsnie_present) {
|
||||
int i;
|
||||
u8 nie_len;
|
||||
const u8 *nie = cfg80211_find_ext_ie(WLAN_EID_EXT_NON_INHERITANCE,
|
||||
profile, profile_len);
|
||||
if (!nie)
|
||||
return;
|
||||
|
||||
if (arvif->vdev_type != WMI_VDEV_TYPE_AP)
|
||||
return 0;
|
||||
|
||||
bcn = ieee80211_beacon_get_template(hw, vif, &offs, 0);
|
||||
if (!bcn) {
|
||||
ath11k_warn(ab, "failed to get beacon template from mac80211\n");
|
||||
return -EPERM;
|
||||
nie_len = nie[1];
|
||||
nie += 2;
|
||||
for (i = 0; i < nie_len; i++) {
|
||||
if (nie[i] == WLAN_EID_RSN) {
|
||||
arvif->rsnie_present = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool ath11k_mac_set_nontx_vif_params(struct ath11k_vif *tx_arvif,
|
||||
struct ath11k_vif *arvif,
|
||||
struct sk_buff *bcn)
|
||||
{
|
||||
struct ieee80211_mgmt *mgmt;
|
||||
const u8 *ies, *profile, *next_profile;
|
||||
int ies_len;
|
||||
|
||||
ies = bcn->data + ieee80211_get_hdrlen_from_skb(bcn);
|
||||
mgmt = (struct ieee80211_mgmt *)bcn->data;
|
||||
ies += sizeof(mgmt->u.beacon);
|
||||
ies_len = skb_tail_pointer(bcn) - ies;
|
||||
|
||||
ies = cfg80211_find_ie(WLAN_EID_MULTIPLE_BSSID, ies, ies_len);
|
||||
arvif->rsnie_present = tx_arvif->rsnie_present;
|
||||
|
||||
while (ies) {
|
||||
u8 mbssid_len;
|
||||
|
||||
ies_len -= (2 + ies[1]);
|
||||
mbssid_len = ies[1] - 1;
|
||||
profile = &ies[3];
|
||||
|
||||
while (mbssid_len) {
|
||||
u8 profile_len;
|
||||
|
||||
profile_len = profile[1];
|
||||
next_profile = profile + (2 + profile_len);
|
||||
mbssid_len -= (2 + profile_len);
|
||||
|
||||
profile += 2;
|
||||
profile_len -= (2 + profile[1]);
|
||||
profile += (2 + profile[1]); /* nontx capabilities */
|
||||
profile_len -= (2 + profile[1]);
|
||||
profile += (2 + profile[1]); /* SSID */
|
||||
if (profile[2] == arvif->vif->bss_conf.bssid_index) {
|
||||
profile_len -= 5;
|
||||
profile = profile + 5;
|
||||
ath11k_mac_setup_nontx_vif_rsnie(arvif,
|
||||
tx_arvif->rsnie_present,
|
||||
profile,
|
||||
profile_len);
|
||||
return true;
|
||||
}
|
||||
profile = next_profile;
|
||||
}
|
||||
ies = cfg80211_find_ie(WLAN_EID_MULTIPLE_BSSID, profile,
|
||||
ies_len);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void ath11k_mac_set_vif_params(struct ath11k_vif *arvif,
|
||||
struct sk_buff *bcn)
|
||||
{
|
||||
struct ieee80211_mgmt *mgmt;
|
||||
u8 *ies;
|
||||
|
||||
ies = bcn->data + ieee80211_get_hdrlen_from_skb(bcn);
|
||||
mgmt = (struct ieee80211_mgmt *)bcn->data;
|
||||
ies += sizeof(mgmt->u.beacon);
|
||||
|
||||
if (cfg80211_find_ie(WLAN_EID_RSN, ies, (skb_tail_pointer(bcn) - ies)))
|
||||
@@ -1386,9 +1450,95 @@ static int ath11k_mac_setup_bcn_tmpl(struct ath11k_vif *arvif)
|
||||
arvif->wpaie_present = true;
|
||||
else
|
||||
arvif->wpaie_present = false;
|
||||
}
|
||||
|
||||
ret = ath11k_wmi_bcn_tmpl(ar, arvif->vdev_id, &offs, bcn);
|
||||
static int ath11k_mac_setup_bcn_tmpl_ema(struct ath11k_vif *arvif)
|
||||
{
|
||||
struct ath11k_vif *tx_arvif;
|
||||
struct ieee80211_ema_beacons *beacons;
|
||||
int ret = 0;
|
||||
bool nontx_vif_params_set = false;
|
||||
u32 params = 0;
|
||||
u8 i = 0;
|
||||
|
||||
tx_arvif = (void *)arvif->vif->mbssid_tx_vif->drv_priv;
|
||||
|
||||
beacons = ieee80211_beacon_get_template_ema_list(tx_arvif->ar->hw,
|
||||
tx_arvif->vif, 0);
|
||||
if (!beacons || !beacons->cnt) {
|
||||
ath11k_warn(arvif->ar->ab,
|
||||
"failed to get ema beacon templates from mac80211\n");
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
if (tx_arvif == arvif)
|
||||
ath11k_mac_set_vif_params(tx_arvif, beacons->bcn[0].skb);
|
||||
else
|
||||
arvif->wpaie_present = tx_arvif->wpaie_present;
|
||||
|
||||
for (i = 0; i < beacons->cnt; i++) {
|
||||
if (tx_arvif != arvif && !nontx_vif_params_set)
|
||||
nontx_vif_params_set =
|
||||
ath11k_mac_set_nontx_vif_params(tx_arvif, arvif,
|
||||
beacons->bcn[i].skb);
|
||||
|
||||
params = beacons->cnt;
|
||||
params |= (i << WMI_EMA_TMPL_IDX_SHIFT);
|
||||
params |= ((!i ? 1 : 0) << WMI_EMA_FIRST_TMPL_SHIFT);
|
||||
params |= ((i + 1 == beacons->cnt ? 1 : 0) << WMI_EMA_LAST_TMPL_SHIFT);
|
||||
|
||||
ret = ath11k_wmi_bcn_tmpl(tx_arvif->ar, tx_arvif->vdev_id,
|
||||
&beacons->bcn[i].offs,
|
||||
beacons->bcn[i].skb, params);
|
||||
if (ret) {
|
||||
ath11k_warn(tx_arvif->ar->ab,
|
||||
"failed to set ema beacon template id %i error %d\n",
|
||||
i, ret);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ieee80211_beacon_free_ema_list(beacons);
|
||||
|
||||
if (tx_arvif != arvif && !nontx_vif_params_set)
|
||||
return -EINVAL; /* Profile not found in the beacons */
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ath11k_mac_setup_bcn_tmpl_mbssid(struct ath11k_vif *arvif)
|
||||
{
|
||||
struct ath11k *ar = arvif->ar;
|
||||
struct ath11k_base *ab = ar->ab;
|
||||
struct ath11k_vif *tx_arvif = arvif;
|
||||
struct ieee80211_hw *hw = ar->hw;
|
||||
struct ieee80211_vif *vif = arvif->vif;
|
||||
struct ieee80211_mutable_offsets offs = {};
|
||||
struct sk_buff *bcn;
|
||||
int ret;
|
||||
|
||||
if (arvif->vif->mbssid_tx_vif) {
|
||||
tx_arvif = (void *)arvif->vif->mbssid_tx_vif->drv_priv;
|
||||
if (tx_arvif != arvif) {
|
||||
ar = tx_arvif->ar;
|
||||
ab = ar->ab;
|
||||
hw = ar->hw;
|
||||
vif = tx_arvif->vif;
|
||||
}
|
||||
}
|
||||
|
||||
bcn = ieee80211_beacon_get_template(hw, vif, &offs, 0);
|
||||
if (!bcn) {
|
||||
ath11k_warn(ab, "failed to get beacon template from mac80211\n");
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
if (tx_arvif == arvif)
|
||||
ath11k_mac_set_vif_params(tx_arvif, bcn);
|
||||
else if (!ath11k_mac_set_nontx_vif_params(tx_arvif, arvif, bcn))
|
||||
return -EINVAL;
|
||||
|
||||
ret = ath11k_wmi_bcn_tmpl(ar, arvif->vdev_id, &offs, bcn, 0);
|
||||
kfree_skb(bcn);
|
||||
|
||||
if (ret)
|
||||
@@ -1398,6 +1548,26 @@ static int ath11k_mac_setup_bcn_tmpl(struct ath11k_vif *arvif)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ath11k_mac_setup_bcn_tmpl(struct ath11k_vif *arvif)
|
||||
{
|
||||
struct ieee80211_vif *vif = arvif->vif;
|
||||
|
||||
if (arvif->vdev_type != WMI_VDEV_TYPE_AP)
|
||||
return 0;
|
||||
|
||||
/* Target does not expect beacon templates for the already up
|
||||
* non-transmitting interfaces, and results in a crash if sent.
|
||||
*/
|
||||
if (vif->mbssid_tx_vif &&
|
||||
arvif != (void *)vif->mbssid_tx_vif->drv_priv && arvif->is_up)
|
||||
return 0;
|
||||
|
||||
if (vif->bss_conf.ema_ap && vif->mbssid_tx_vif)
|
||||
return ath11k_mac_setup_bcn_tmpl_ema(arvif);
|
||||
|
||||
return ath11k_mac_setup_bcn_tmpl_mbssid(arvif);
|
||||
}
|
||||
|
||||
void ath11k_mac_bcn_tx_event(struct ath11k_vif *arvif)
|
||||
{
|
||||
struct ieee80211_vif *vif = arvif->vif;
|
||||
@@ -1423,6 +1593,7 @@ static void ath11k_control_beaconing(struct ath11k_vif *arvif,
|
||||
struct ieee80211_bss_conf *info)
|
||||
{
|
||||
struct ath11k *ar = arvif->ar;
|
||||
struct ath11k_vif *tx_arvif = NULL;
|
||||
int ret = 0;
|
||||
|
||||
lockdep_assert_held(&arvif->ar->conf_mutex);
|
||||
@@ -1451,8 +1622,14 @@ static void ath11k_control_beaconing(struct ath11k_vif *arvif,
|
||||
|
||||
ether_addr_copy(arvif->bssid, info->bssid);
|
||||
|
||||
if (arvif->vif->mbssid_tx_vif)
|
||||
tx_arvif = (struct ath11k_vif *)arvif->vif->mbssid_tx_vif->drv_priv;
|
||||
|
||||
ret = ath11k_wmi_vdev_up(arvif->ar, arvif->vdev_id, arvif->aid,
|
||||
arvif->bssid);
|
||||
arvif->bssid,
|
||||
tx_arvif ? tx_arvif->bssid : NULL,
|
||||
info->bssid_index,
|
||||
1 << info->bssid_indicator);
|
||||
if (ret) {
|
||||
ath11k_warn(ar->ab, "failed to bring up vdev %d: %i\n",
|
||||
arvif->vdev_id, ret);
|
||||
@@ -1658,7 +1835,7 @@ static void ath11k_peer_assoc_h_rates(struct ath11k *ar,
|
||||
}
|
||||
|
||||
static bool
|
||||
ath11k_peer_assoc_h_ht_masked(const u8 ht_mcs_mask[IEEE80211_HT_MCS_MASK_LEN])
|
||||
ath11k_peer_assoc_h_ht_masked(const u8 *ht_mcs_mask)
|
||||
{
|
||||
int nss;
|
||||
|
||||
@@ -1670,7 +1847,7 @@ ath11k_peer_assoc_h_ht_masked(const u8 ht_mcs_mask[IEEE80211_HT_MCS_MASK_LEN])
|
||||
}
|
||||
|
||||
static bool
|
||||
ath11k_peer_assoc_h_vht_masked(const u16 vht_mcs_mask[])
|
||||
ath11k_peer_assoc_h_vht_masked(const u16 *vht_mcs_mask)
|
||||
{
|
||||
int nss;
|
||||
|
||||
@@ -2065,7 +2242,7 @@ static u16 ath11k_peer_assoc_h_he_limit(u16 tx_mcs_set,
|
||||
}
|
||||
|
||||
static bool
|
||||
ath11k_peer_assoc_h_he_masked(const u16 he_mcs_mask[NL80211_HE_NSS_MAX])
|
||||
ath11k_peer_assoc_h_he_masked(const u16 *he_mcs_mask)
|
||||
{
|
||||
int nss;
|
||||
|
||||
@@ -2879,7 +3056,8 @@ static void ath11k_bss_assoc(struct ieee80211_hw *hw,
|
||||
arvif->aid = vif->cfg.aid;
|
||||
ether_addr_copy(arvif->bssid, bss_conf->bssid);
|
||||
|
||||
ret = ath11k_wmi_vdev_up(ar, arvif->vdev_id, arvif->aid, arvif->bssid);
|
||||
ret = ath11k_wmi_vdev_up(ar, arvif->vdev_id, arvif->aid, arvif->bssid,
|
||||
NULL, 0, 0);
|
||||
if (ret) {
|
||||
ath11k_warn(ar->ab, "failed to set vdev %d up: %d\n",
|
||||
arvif->vdev_id, ret);
|
||||
@@ -4159,6 +4337,20 @@ exit:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
ath11k_mac_bitrate_mask_num_ht_rates(struct ath11k *ar,
|
||||
enum nl80211_band band,
|
||||
const struct cfg80211_bitrate_mask *mask)
|
||||
{
|
||||
int num_rates = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(mask->control[band].ht_mcs); i++)
|
||||
num_rates += hweight8(mask->control[band].ht_mcs[i]);
|
||||
|
||||
return num_rates;
|
||||
}
|
||||
|
||||
static int
|
||||
ath11k_mac_bitrate_mask_num_vht_rates(struct ath11k *ar,
|
||||
enum nl80211_band band,
|
||||
@@ -4288,6 +4480,54 @@ ath11k_mac_set_peer_he_fixed_rate(struct ath11k_vif *arvif,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
ath11k_mac_set_peer_ht_fixed_rate(struct ath11k_vif *arvif,
|
||||
struct ieee80211_sta *sta,
|
||||
const struct cfg80211_bitrate_mask *mask,
|
||||
enum nl80211_band band)
|
||||
{
|
||||
struct ath11k *ar = arvif->ar;
|
||||
u8 ht_rate, nss = 0;
|
||||
u32 rate_code;
|
||||
int ret, i;
|
||||
|
||||
lockdep_assert_held(&ar->conf_mutex);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(mask->control[band].ht_mcs); i++) {
|
||||
if (hweight8(mask->control[band].ht_mcs[i]) == 1) {
|
||||
nss = i + 1;
|
||||
ht_rate = ffs(mask->control[band].ht_mcs[i]) - 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!nss) {
|
||||
ath11k_warn(ar->ab, "No single HT Fixed rate found to set for %pM",
|
||||
sta->addr);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Avoid updating invalid nss as fixed rate*/
|
||||
if (nss > sta->deflink.rx_nss)
|
||||
return -EINVAL;
|
||||
|
||||
ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
|
||||
"Setting Fixed HT Rate for peer %pM. Device will not switch to any other selected rates",
|
||||
sta->addr);
|
||||
|
||||
rate_code = ATH11K_HW_RATE_CODE(ht_rate, nss - 1,
|
||||
WMI_RATE_PREAMBLE_HT);
|
||||
ret = ath11k_wmi_set_peer_param(ar, sta->addr,
|
||||
arvif->vdev_id,
|
||||
WMI_PEER_PARAM_FIXED_RATE,
|
||||
rate_code);
|
||||
if (ret)
|
||||
ath11k_warn(ar->ab,
|
||||
"failed to update STA %pM HT Fixed Rate %d: %d\n",
|
||||
sta->addr, rate_code, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ath11k_station_assoc(struct ath11k *ar,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta,
|
||||
@@ -4299,7 +4539,7 @@ static int ath11k_station_assoc(struct ath11k *ar,
|
||||
struct cfg80211_chan_def def;
|
||||
enum nl80211_band band;
|
||||
struct cfg80211_bitrate_mask *mask;
|
||||
u8 num_vht_rates, num_he_rates;
|
||||
u8 num_ht_rates, num_vht_rates, num_he_rates;
|
||||
|
||||
lockdep_assert_held(&ar->conf_mutex);
|
||||
|
||||
@@ -4327,6 +4567,7 @@ static int ath11k_station_assoc(struct ath11k *ar,
|
||||
|
||||
num_vht_rates = ath11k_mac_bitrate_mask_num_vht_rates(ar, band, mask);
|
||||
num_he_rates = ath11k_mac_bitrate_mask_num_he_rates(ar, band, mask);
|
||||
num_ht_rates = ath11k_mac_bitrate_mask_num_ht_rates(ar, band, mask);
|
||||
|
||||
/* If single VHT/HE rate is configured (by set_bitrate_mask()),
|
||||
* peer_assoc will disable VHT/HE. This is now enabled by a peer specific
|
||||
@@ -4343,6 +4584,11 @@ static int ath11k_station_assoc(struct ath11k *ar,
|
||||
band);
|
||||
if (ret)
|
||||
return ret;
|
||||
} else if (sta->deflink.ht_cap.ht_supported && num_ht_rates == 1) {
|
||||
ret = ath11k_mac_set_peer_ht_fixed_rate(arvif, sta, mask,
|
||||
band);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Re-assoc is run only to update supported rates for given station. It
|
||||
@@ -4416,7 +4662,7 @@ static void ath11k_sta_rc_update_wk(struct work_struct *wk)
|
||||
const u16 *vht_mcs_mask;
|
||||
const u16 *he_mcs_mask;
|
||||
u32 changed, bw, nss, smps, bw_prev;
|
||||
int err, num_vht_rates, num_he_rates;
|
||||
int err, num_ht_rates, num_vht_rates, num_he_rates;
|
||||
const struct cfg80211_bitrate_mask *mask;
|
||||
struct peer_assoc_params peer_arg;
|
||||
enum wmi_phy_mode peer_phymode;
|
||||
@@ -4532,6 +4778,8 @@ static void ath11k_sta_rc_update_wk(struct work_struct *wk)
|
||||
|
||||
if (changed & IEEE80211_RC_SUPP_RATES_CHANGED) {
|
||||
mask = &arvif->bitrate_mask;
|
||||
num_ht_rates = ath11k_mac_bitrate_mask_num_ht_rates(ar, band,
|
||||
mask);
|
||||
num_vht_rates = ath11k_mac_bitrate_mask_num_vht_rates(ar, band,
|
||||
mask);
|
||||
num_he_rates = ath11k_mac_bitrate_mask_num_he_rates(ar, band,
|
||||
@@ -4554,6 +4802,9 @@ static void ath11k_sta_rc_update_wk(struct work_struct *wk)
|
||||
} else if (sta->deflink.he_cap.has_he && num_he_rates == 1) {
|
||||
ath11k_mac_set_peer_he_fixed_rate(arvif, sta, mask,
|
||||
band);
|
||||
} else if (sta->deflink.ht_cap.ht_supported && num_ht_rates == 1) {
|
||||
ath11k_mac_set_peer_ht_fixed_rate(arvif, sta, mask,
|
||||
band);
|
||||
} else {
|
||||
/* If the peer is non-VHT/HE or no fixed VHT/HE rate
|
||||
* is provided in the new bitrate mask we set the
|
||||
@@ -6181,17 +6432,62 @@ static void ath11k_mac_op_stop(struct ieee80211_hw *hw)
|
||||
atomic_set(&ar->num_pending_mgmt_tx, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
ath11k_mac_setup_vdev_create_params(struct ath11k_vif *arvif,
|
||||
struct vdev_create_params *params)
|
||||
static int ath11k_mac_setup_vdev_params_mbssid(struct ath11k_vif *arvif,
|
||||
u32 *flags, u32 *tx_vdev_id)
|
||||
{
|
||||
struct ath11k *ar = arvif->ar;
|
||||
struct ath11k_vif *tx_arvif;
|
||||
struct ieee80211_vif *tx_vif;
|
||||
|
||||
*tx_vdev_id = 0;
|
||||
tx_vif = arvif->vif->mbssid_tx_vif;
|
||||
if (!tx_vif) {
|
||||
*flags = WMI_HOST_VDEV_FLAGS_NON_MBSSID_AP;
|
||||
return 0;
|
||||
}
|
||||
|
||||
tx_arvif = (void *)tx_vif->drv_priv;
|
||||
|
||||
if (arvif->vif->bss_conf.nontransmitted) {
|
||||
if (ar->hw->wiphy != ieee80211_vif_to_wdev(tx_vif)->wiphy)
|
||||
return -EINVAL;
|
||||
|
||||
*flags = WMI_HOST_VDEV_FLAGS_NON_TRANSMIT_AP;
|
||||
*tx_vdev_id = ath11k_vif_to_arvif(tx_vif)->vdev_id;
|
||||
} else if (tx_arvif == arvif) {
|
||||
*flags = WMI_HOST_VDEV_FLAGS_TRANSMIT_AP;
|
||||
} else {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (arvif->vif->bss_conf.ema_ap)
|
||||
*flags |= WMI_HOST_VDEV_FLAGS_EMA_MODE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ath11k_mac_setup_vdev_create_params(struct ath11k_vif *arvif,
|
||||
struct vdev_create_params *params)
|
||||
{
|
||||
struct ath11k *ar = arvif->ar;
|
||||
struct ath11k_pdev *pdev = ar->pdev;
|
||||
int ret;
|
||||
|
||||
params->if_id = arvif->vdev_id;
|
||||
params->type = arvif->vdev_type;
|
||||
params->subtype = arvif->vdev_subtype;
|
||||
params->pdev_id = pdev->pdev_id;
|
||||
params->mbssid_flags = 0;
|
||||
params->mbssid_tx_vdev_id = 0;
|
||||
|
||||
if (!test_bit(WMI_TLV_SERVICE_MBSS_PARAM_IN_VDEV_START_SUPPORT,
|
||||
ar->ab->wmi_ab.svc_map)) {
|
||||
ret = ath11k_mac_setup_vdev_params_mbssid(arvif,
|
||||
¶ms->mbssid_flags,
|
||||
¶ms->mbssid_tx_vdev_id);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (pdev->cap.supported_bands & WMI_HOST_WLAN_2G_CAP) {
|
||||
params->chains[NL80211_BAND_2GHZ].tx = ar->num_tx_chains;
|
||||
@@ -6206,6 +6502,7 @@ ath11k_mac_setup_vdev_create_params(struct ath11k_vif *arvif,
|
||||
params->chains[NL80211_BAND_6GHZ].tx = ar->num_tx_chains;
|
||||
params->chains[NL80211_BAND_6GHZ].rx = ar->num_rx_chains;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ath11k_mac_op_update_vif_offload(struct ieee80211_hw *hw,
|
||||
@@ -6500,7 +6797,12 @@ static int ath11k_mac_op_add_interface(struct ieee80211_hw *hw,
|
||||
for (i = 0; i < ARRAY_SIZE(vif->hw_queue); i++)
|
||||
vif->hw_queue[i] = i % (ATH11K_HW_MAX_QUEUES - 1);
|
||||
|
||||
ath11k_mac_setup_vdev_create_params(arvif, &vdev_param);
|
||||
ret = ath11k_mac_setup_vdev_create_params(arvif, &vdev_param);
|
||||
if (ret) {
|
||||
ath11k_warn(ab, "failed to create vdev parameters %d: %d\n",
|
||||
arvif->vdev_id, ret);
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = ath11k_wmi_vdev_create(ar, vif->addr, &vdev_param);
|
||||
if (ret) {
|
||||
@@ -6905,6 +7207,17 @@ ath11k_mac_vdev_start_restart(struct ath11k_vif *arvif,
|
||||
arg.pref_tx_streams = ar->num_tx_chains;
|
||||
arg.pref_rx_streams = ar->num_rx_chains;
|
||||
|
||||
arg.mbssid_flags = 0;
|
||||
arg.mbssid_tx_vdev_id = 0;
|
||||
if (test_bit(WMI_TLV_SERVICE_MBSS_PARAM_IN_VDEV_START_SUPPORT,
|
||||
ar->ab->wmi_ab.svc_map)) {
|
||||
ret = ath11k_mac_setup_vdev_params_mbssid(arvif,
|
||||
&arg.mbssid_flags,
|
||||
&arg.mbssid_tx_vdev_id);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (arvif->vdev_type == WMI_VDEV_TYPE_AP) {
|
||||
arg.ssid = arvif->u.ap.ssid;
|
||||
arg.ssid_len = arvif->u.ap.ssid_len;
|
||||
@@ -7071,7 +7384,8 @@ ath11k_mac_update_vif_chan(struct ath11k *ar,
|
||||
int n_vifs)
|
||||
{
|
||||
struct ath11k_base *ab = ar->ab;
|
||||
struct ath11k_vif *arvif;
|
||||
struct ath11k_vif *arvif, *tx_arvif = NULL;
|
||||
struct ieee80211_vif *mbssid_tx_vif;
|
||||
int ret;
|
||||
int i;
|
||||
bool monitor_vif = false;
|
||||
@@ -7125,8 +7439,15 @@ ath11k_mac_update_vif_chan(struct ath11k *ar,
|
||||
ath11k_warn(ab, "failed to update bcn tmpl during csa: %d\n",
|
||||
ret);
|
||||
|
||||
mbssid_tx_vif = arvif->vif->mbssid_tx_vif;
|
||||
if (mbssid_tx_vif)
|
||||
tx_arvif = (struct ath11k_vif *)mbssid_tx_vif->drv_priv;
|
||||
|
||||
ret = ath11k_wmi_vdev_up(arvif->ar, arvif->vdev_id, arvif->aid,
|
||||
arvif->bssid);
|
||||
arvif->bssid,
|
||||
tx_arvif ? tx_arvif->bssid : NULL,
|
||||
arvif->vif->bss_conf.bssid_index,
|
||||
1 << arvif->vif->bss_conf.bssid_indicator);
|
||||
if (ret) {
|
||||
ath11k_warn(ab, "failed to bring vdev up %d: %d\n",
|
||||
arvif->vdev_id, ret);
|
||||
@@ -7244,7 +7565,8 @@ static int ath11k_start_vdev_delay(struct ieee80211_hw *hw,
|
||||
}
|
||||
|
||||
if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR) {
|
||||
ret = ath11k_wmi_vdev_up(ar, arvif->vdev_id, 0, ar->mac_addr);
|
||||
ret = ath11k_wmi_vdev_up(ar, arvif->vdev_id, 0, ar->mac_addr,
|
||||
NULL, 0, 0);
|
||||
if (ret) {
|
||||
ath11k_warn(ab, "failed put monitor up: %d\n", ret);
|
||||
return ret;
|
||||
@@ -7542,20 +7864,6 @@ static void ath11k_mac_op_flush(struct ieee80211_hw *hw, struct ieee80211_vif *v
|
||||
ath11k_mac_flush_tx_complete(ar);
|
||||
}
|
||||
|
||||
static int
|
||||
ath11k_mac_bitrate_mask_num_ht_rates(struct ath11k *ar,
|
||||
enum nl80211_band band,
|
||||
const struct cfg80211_bitrate_mask *mask)
|
||||
{
|
||||
int num_rates = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(mask->control[band].ht_mcs); i++)
|
||||
num_rates += hweight16(mask->control[band].ht_mcs[i]);
|
||||
|
||||
return num_rates;
|
||||
}
|
||||
|
||||
static bool
|
||||
ath11k_mac_has_single_legacy_rate(struct ath11k *ar,
|
||||
enum nl80211_band band,
|
||||
@@ -8892,7 +9200,7 @@ static int ath11k_mac_setup_channels_rates(struct ath11k *ar,
|
||||
}
|
||||
|
||||
if (supported_bands & WMI_HOST_WLAN_5G_CAP) {
|
||||
if (reg_cap->high_5ghz_chan >= ATH11K_MAX_6G_FREQ) {
|
||||
if (reg_cap->high_5ghz_chan >= ATH11K_MIN_6G_FREQ) {
|
||||
channels = kmemdup(ath11k_6ghz_channels,
|
||||
sizeof(ath11k_6ghz_channels), GFP_KERNEL);
|
||||
if (!channels) {
|
||||
@@ -9001,19 +9309,23 @@ static int ath11k_mac_setup_iface_combinations(struct ath11k *ar)
|
||||
|
||||
static const u8 ath11k_if_types_ext_capa[] = {
|
||||
[0] = WLAN_EXT_CAPA1_EXT_CHANNEL_SWITCHING,
|
||||
[2] = WLAN_EXT_CAPA3_MULTI_BSSID_SUPPORT,
|
||||
[7] = WLAN_EXT_CAPA8_OPMODE_NOTIF,
|
||||
};
|
||||
|
||||
static const u8 ath11k_if_types_ext_capa_sta[] = {
|
||||
[0] = WLAN_EXT_CAPA1_EXT_CHANNEL_SWITCHING,
|
||||
[2] = WLAN_EXT_CAPA3_MULTI_BSSID_SUPPORT,
|
||||
[7] = WLAN_EXT_CAPA8_OPMODE_NOTIF,
|
||||
[9] = WLAN_EXT_CAPA10_TWT_REQUESTER_SUPPORT,
|
||||
};
|
||||
|
||||
static const u8 ath11k_if_types_ext_capa_ap[] = {
|
||||
[0] = WLAN_EXT_CAPA1_EXT_CHANNEL_SWITCHING,
|
||||
[2] = WLAN_EXT_CAPA3_MULTI_BSSID_SUPPORT,
|
||||
[7] = WLAN_EXT_CAPA8_OPMODE_NOTIF,
|
||||
[9] = WLAN_EXT_CAPA10_TWT_RESPONDER_SUPPORT,
|
||||
[10] = WLAN_EXT_CAPA11_EMA_SUPPORT,
|
||||
};
|
||||
|
||||
static const struct wiphy_iftype_ext_capab ath11k_iftypes_ext_capa[] = {
|
||||
@@ -9251,6 +9563,9 @@ static int __ath11k_mac_register(struct ath11k *ar)
|
||||
wiphy_ext_feature_set(ar->hw->wiphy,
|
||||
NL80211_EXT_FEATURE_ENABLE_FTM_RESPONDER);
|
||||
|
||||
ar->hw->wiphy->mbssid_max_interfaces = TARGET_NUM_VDEVS(ab);
|
||||
ar->hw->wiphy->ema_max_profile_periodicity = TARGET_EMA_MAX_PROFILE_PERIOD;
|
||||
|
||||
ath11k_reg_init(ar);
|
||||
|
||||
if (!test_bit(ATH11K_FLAG_RAW_MODE, &ab->dev_flags)) {
|
||||
|
||||
@@ -724,6 +724,9 @@ int ath11k_wmi_vdev_create(struct ath11k *ar, u8 *macaddr,
|
||||
cmd->vdev_subtype = param->subtype;
|
||||
cmd->num_cfg_txrx_streams = WMI_NUM_SUPPORTED_BAND_MAX;
|
||||
cmd->pdev_id = param->pdev_id;
|
||||
cmd->mbssid_flags = param->mbssid_flags;
|
||||
cmd->mbssid_tx_vdev_id = param->mbssid_tx_vdev_id;
|
||||
|
||||
ether_addr_copy(cmd->vdev_macaddr.addr, macaddr);
|
||||
|
||||
ptr = skb->data + sizeof(*cmd);
|
||||
@@ -941,6 +944,8 @@ int ath11k_wmi_vdev_start(struct ath11k *ar, struct wmi_vdev_start_req_arg *arg,
|
||||
cmd->cac_duration_ms = arg->cac_duration_ms;
|
||||
cmd->regdomain = arg->regdomain;
|
||||
cmd->he_ops = arg->he_ops;
|
||||
cmd->mbssid_flags = arg->mbssid_flags;
|
||||
cmd->mbssid_tx_vdev_id = arg->mbssid_tx_vdev_id;
|
||||
|
||||
if (!restart) {
|
||||
if (arg->ssid) {
|
||||
@@ -996,7 +1001,8 @@ int ath11k_wmi_vdev_start(struct ath11k *ar, struct wmi_vdev_start_req_arg *arg,
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ath11k_wmi_vdev_up(struct ath11k *ar, u32 vdev_id, u32 aid, const u8 *bssid)
|
||||
int ath11k_wmi_vdev_up(struct ath11k *ar, u32 vdev_id, u32 aid, const u8 *bssid,
|
||||
u8 *tx_bssid, u32 nontx_profile_idx, u32 nontx_profile_cnt)
|
||||
{
|
||||
struct ath11k_pdev_wmi *wmi = ar->wmi;
|
||||
struct wmi_vdev_up_cmd *cmd;
|
||||
@@ -1020,14 +1026,19 @@ int ath11k_wmi_vdev_up(struct ath11k *ar, u32 vdev_id, u32 aid, const u8 *bssid)
|
||||
|
||||
ether_addr_copy(cmd->vdev_bssid.addr, bssid);
|
||||
|
||||
cmd->nontx_profile_idx = nontx_profile_idx;
|
||||
cmd->nontx_profile_cnt = nontx_profile_cnt;
|
||||
if (tx_bssid)
|
||||
ether_addr_copy(cmd->tx_vdev_bssid.addr, tx_bssid);
|
||||
|
||||
if (arvif && arvif->vif->type == NL80211_IFTYPE_STATION) {
|
||||
bss_conf = &arvif->vif->bss_conf;
|
||||
|
||||
if (bss_conf->nontransmitted) {
|
||||
ether_addr_copy(cmd->trans_bssid.addr,
|
||||
ether_addr_copy(cmd->tx_vdev_bssid.addr,
|
||||
bss_conf->transmitter_bssid);
|
||||
cmd->profile_idx = bss_conf->bssid_index;
|
||||
cmd->profile_num = bss_conf->bssid_indicator;
|
||||
cmd->nontx_profile_idx = bss_conf->bssid_index;
|
||||
cmd->nontx_profile_cnt = bss_conf->bssid_indicator;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1688,7 +1699,7 @@ int ath11k_wmi_send_bcn_offload_control_cmd(struct ath11k *ar,
|
||||
|
||||
int ath11k_wmi_bcn_tmpl(struct ath11k *ar, u32 vdev_id,
|
||||
struct ieee80211_mutable_offsets *offs,
|
||||
struct sk_buff *bcn)
|
||||
struct sk_buff *bcn, u32 ema_params)
|
||||
{
|
||||
struct ath11k_pdev_wmi *wmi = ar->wmi;
|
||||
struct wmi_bcn_tmpl_cmd *cmd;
|
||||
@@ -1726,6 +1737,8 @@ int ath11k_wmi_bcn_tmpl(struct ath11k *ar, u32 vdev_id,
|
||||
}
|
||||
|
||||
cmd->buf_len = bcn->len;
|
||||
cmd->mbssid_ie_offset = offs->mbssid_off;
|
||||
cmd->ema_params = ema_params;
|
||||
|
||||
ptr = skb->data + sizeof(*cmd);
|
||||
|
||||
@@ -3987,6 +4000,9 @@ ath11k_wmi_copy_resource_config(struct wmi_resource_config *wmi_cfg,
|
||||
~(1 << WMI_CFG_HOST_SERVICE_FLAG_REG_CC_EXT);
|
||||
wmi_cfg->host_service_flags |= (tg_cfg->is_reg_cc_ext_event_supported <<
|
||||
WMI_CFG_HOST_SERVICE_FLAG_REG_CC_EXT);
|
||||
wmi_cfg->flags2 = WMI_RSRC_CFG_FLAG2_CALC_NEXT_DTIM_COUNT_SET;
|
||||
wmi_cfg->ema_max_vap_cnt = tg_cfg->ema_max_vap_cnt;
|
||||
wmi_cfg->ema_max_profile_period = tg_cfg->ema_max_profile_period;
|
||||
}
|
||||
|
||||
static int ath11k_init_cmd_send(struct ath11k_pdev_wmi *wmi,
|
||||
@@ -6548,28 +6564,6 @@ int ath11k_wmi_pull_fw_stats(struct ath11k_base *ab, struct sk_buff *skb,
|
||||
&parse);
|
||||
}
|
||||
|
||||
size_t ath11k_wmi_fw_stats_num_vdevs(struct list_head *head)
|
||||
{
|
||||
struct ath11k_fw_stats_vdev *i;
|
||||
size_t num = 0;
|
||||
|
||||
list_for_each_entry(i, head, list)
|
||||
++num;
|
||||
|
||||
return num;
|
||||
}
|
||||
|
||||
static size_t ath11k_wmi_fw_stats_num_bcn(struct list_head *head)
|
||||
{
|
||||
struct ath11k_fw_stats_bcn *i;
|
||||
size_t num = 0;
|
||||
|
||||
list_for_each_entry(i, head, list)
|
||||
++num;
|
||||
|
||||
return num;
|
||||
}
|
||||
|
||||
static void
|
||||
ath11k_wmi_fw_pdev_base_stats_fill(const struct ath11k_fw_stats_pdev *pdev,
|
||||
char *buf, u32 *length)
|
||||
@@ -6880,7 +6874,7 @@ void ath11k_wmi_fw_stats_fill(struct ath11k *ar,
|
||||
}
|
||||
|
||||
if (stats_id == WMI_REQUEST_BCN_STAT) {
|
||||
num_bcn = ath11k_wmi_fw_stats_num_bcn(&fw_stats->bcn);
|
||||
num_bcn = list_count_nodes(&fw_stats->bcn);
|
||||
|
||||
len += scnprintf(buf + len, buf_len - len, "\n");
|
||||
len += scnprintf(buf + len, buf_len - len, "%30s (%zu)\n",
|
||||
|
||||
@@ -137,6 +137,14 @@ enum {
|
||||
WMI_AUTORATE_3200NS_GI = BIT(11),
|
||||
};
|
||||
|
||||
enum {
|
||||
WMI_HOST_VDEV_FLAGS_NON_MBSSID_AP = 0x00000001,
|
||||
WMI_HOST_VDEV_FLAGS_TRANSMIT_AP = 0x00000002,
|
||||
WMI_HOST_VDEV_FLAGS_NON_TRANSMIT_AP = 0x00000004,
|
||||
WMI_HOST_VDEV_FLAGS_EMA_MODE = 0x00000008,
|
||||
WMI_HOST_VDEV_FLAGS_SCAN_MODE_VAP = 0x00000010,
|
||||
};
|
||||
|
||||
/*
|
||||
* wmi command groups.
|
||||
*/
|
||||
@@ -2096,6 +2104,7 @@ enum wmi_tlv_service {
|
||||
WMI_TLV_SERVICE_EXT2_MSG = 220,
|
||||
WMI_TLV_SERVICE_PEER_POWER_SAVE_DURATION_SUPPORT = 246,
|
||||
WMI_TLV_SERVICE_SRG_SRP_SPATIAL_REUSE_SUPPORT = 249,
|
||||
WMI_TLV_SERVICE_MBSS_PARAM_IN_VDEV_START_SUPPORT = 253,
|
||||
WMI_TLV_SERVICE_PASSIVE_SCAN_START_TIME_ENHANCE = 263,
|
||||
|
||||
/* The second 128 bits */
|
||||
@@ -2317,6 +2326,7 @@ struct wmi_init_cmd {
|
||||
} __packed;
|
||||
|
||||
#define WMI_RSRC_CFG_FLAG1_BSS_CHANNEL_INFO_64 BIT(5)
|
||||
#define WMI_RSRC_CFG_FLAG2_CALC_NEXT_DTIM_COUNT_SET BIT(9)
|
||||
#define WMI_RSRC_CFG_FLAG1_ACK_RSSI BIT(18)
|
||||
|
||||
#define WMI_CFG_HOST_SERVICE_FLAG_REG_CC_EXT 4
|
||||
@@ -2389,6 +2399,9 @@ struct wmi_resource_config {
|
||||
u32 msdu_flow_override_config1;
|
||||
u32 flags2;
|
||||
u32 host_service_flags;
|
||||
u32 max_rnr_neighbours;
|
||||
u32 ema_max_vap_cnt;
|
||||
u32 ema_max_profile_period;
|
||||
} __packed;
|
||||
|
||||
struct wmi_service_ready_event {
|
||||
@@ -2579,6 +2592,8 @@ struct vdev_create_params {
|
||||
u8 rx;
|
||||
} chains[NUM_NL80211_BANDS];
|
||||
u32 pdev_id;
|
||||
u32 mbssid_flags;
|
||||
u32 mbssid_tx_vdev_id;
|
||||
};
|
||||
|
||||
struct wmi_vdev_create_cmd {
|
||||
@@ -2589,6 +2604,8 @@ struct wmi_vdev_create_cmd {
|
||||
struct wmi_mac_addr vdev_macaddr;
|
||||
u32 num_cfg_txrx_streams;
|
||||
u32 pdev_id;
|
||||
u32 mbssid_flags;
|
||||
u32 mbssid_tx_vdev_id;
|
||||
} __packed;
|
||||
|
||||
struct wmi_vdev_txrx_streams {
|
||||
@@ -2608,9 +2625,9 @@ struct wmi_vdev_up_cmd {
|
||||
u32 vdev_id;
|
||||
u32 vdev_assoc_id;
|
||||
struct wmi_mac_addr vdev_bssid;
|
||||
struct wmi_mac_addr trans_bssid;
|
||||
u32 profile_idx;
|
||||
u32 profile_num;
|
||||
struct wmi_mac_addr tx_vdev_bssid;
|
||||
u32 nontx_profile_idx;
|
||||
u32 nontx_profile_cnt;
|
||||
} __packed;
|
||||
|
||||
struct wmi_vdev_stop_cmd {
|
||||
@@ -2652,6 +2669,9 @@ struct wmi_vdev_start_request_cmd {
|
||||
u32 he_ops;
|
||||
u32 cac_duration_ms;
|
||||
u32 regdomain;
|
||||
u32 min_data_rate;
|
||||
u32 mbssid_flags;
|
||||
u32 mbssid_tx_vdev_id;
|
||||
} __packed;
|
||||
|
||||
#define MGMT_TX_DL_FRM_LEN 64
|
||||
@@ -2821,6 +2841,9 @@ struct wmi_vdev_start_req_arg {
|
||||
u32 pref_rx_streams;
|
||||
u32 pref_tx_streams;
|
||||
u32 num_noa_descriptors;
|
||||
u32 min_data_rate;
|
||||
u32 mbssid_flags;
|
||||
u32 mbssid_tx_vdev_id;
|
||||
};
|
||||
|
||||
struct peer_create_params {
|
||||
@@ -3543,6 +3566,10 @@ struct wmi_get_pdev_temperature_cmd {
|
||||
|
||||
#define WMI_BEACON_TX_BUFFER_SIZE 512
|
||||
|
||||
#define WMI_EMA_TMPL_IDX_SHIFT 8
|
||||
#define WMI_EMA_FIRST_TMPL_SHIFT 16
|
||||
#define WMI_EMA_LAST_TMPL_SHIFT 24
|
||||
|
||||
struct wmi_bcn_tmpl_cmd {
|
||||
u32 tlv_header;
|
||||
u32 vdev_id;
|
||||
@@ -3553,6 +3580,11 @@ struct wmi_bcn_tmpl_cmd {
|
||||
u32 csa_event_bitmap;
|
||||
u32 mbssid_ie_offset;
|
||||
u32 esp_ie_offset;
|
||||
u32 csc_switch_count_offset;
|
||||
u32 csc_event_bitmap;
|
||||
u32 mu_edca_ie_offset;
|
||||
u32 feature_enable_bitmap;
|
||||
u32 ema_params;
|
||||
} __packed;
|
||||
|
||||
struct wmi_key_seq_counter {
|
||||
@@ -5646,6 +5678,8 @@ struct target_resource_config {
|
||||
u32 twt_ap_pdev_count;
|
||||
u32 twt_ap_sta_count;
|
||||
u8 is_reg_cc_ext_event_supported;
|
||||
u32 ema_max_vap_cnt;
|
||||
u32 ema_max_profile_period;
|
||||
};
|
||||
|
||||
enum wmi_debug_log_param {
|
||||
@@ -6273,10 +6307,11 @@ int ath11k_wmi_mgmt_send(struct ath11k *ar, u32 vdev_id, u32 buf_id,
|
||||
struct sk_buff *frame);
|
||||
int ath11k_wmi_bcn_tmpl(struct ath11k *ar, u32 vdev_id,
|
||||
struct ieee80211_mutable_offsets *offs,
|
||||
struct sk_buff *bcn);
|
||||
struct sk_buff *bcn, u32 ema_param);
|
||||
int ath11k_wmi_vdev_down(struct ath11k *ar, u8 vdev_id);
|
||||
int ath11k_wmi_vdev_up(struct ath11k *ar, u32 vdev_id, u32 aid,
|
||||
const u8 *bssid);
|
||||
const u8 *bssid, u8 *tx_bssid, u32 nontx_profile_idx,
|
||||
u32 nontx_profile_cnt);
|
||||
int ath11k_wmi_vdev_stop(struct ath11k *ar, u8 vdev_id);
|
||||
int ath11k_wmi_vdev_start(struct ath11k *ar, struct wmi_vdev_start_req_arg *arg,
|
||||
bool restart);
|
||||
@@ -6372,9 +6407,6 @@ int ath11k_wmi_send_pdev_set_regdomain(struct ath11k *ar,
|
||||
struct pdev_set_regdomain_params *param);
|
||||
int ath11k_wmi_pull_fw_stats(struct ath11k_base *ab, struct sk_buff *skb,
|
||||
struct ath11k_fw_stats *stats);
|
||||
size_t ath11k_wmi_fw_stats_num_peers(struct list_head *head);
|
||||
size_t ath11k_wmi_fw_stats_num_peers_extd(struct list_head *head);
|
||||
size_t ath11k_wmi_fw_stats_num_vdevs(struct list_head *head);
|
||||
void ath11k_wmi_fw_stats_fill(struct ath11k *ar,
|
||||
struct ath11k_fw_stats *fw_stats, u32 stats_id,
|
||||
char *buf);
|
||||
|
||||
@@ -706,6 +706,7 @@ static void ath12k_core_pre_reconfigure_recovery(struct ath12k_base *ab)
|
||||
idr_for_each(&ar->txmgmt_idr,
|
||||
ath12k_mac_tx_mgmt_pending_free, ar);
|
||||
idr_destroy(&ar->txmgmt_idr);
|
||||
wake_up(&ar->txmgmt_empty_waitq);
|
||||
}
|
||||
|
||||
wake_up(&ab->wmi_ab.tx_credits_wq);
|
||||
|
||||
@@ -533,6 +533,7 @@ struct ath12k {
|
||||
/* protects txmgmt_idr data */
|
||||
spinlock_t txmgmt_idr_lock;
|
||||
atomic_t num_pending_mgmt_tx;
|
||||
wait_queue_head_t txmgmt_empty_waitq;
|
||||
|
||||
/* cycle count is reported twice for each visited channel during scan.
|
||||
* access protected by data_lock
|
||||
|
||||
@@ -978,7 +978,19 @@ int ath12k_dp_rx_peer_tid_setup(struct ath12k *ar, const u8 *peer_mac, int vdev_
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
if (!ab->hw_params->reoq_lut_support) {
|
||||
ret = ath12k_wmi_peer_rx_reorder_queue_setup(ar, vdev_id,
|
||||
peer_mac,
|
||||
paddr, tid, 1,
|
||||
ba_win_sz);
|
||||
if (ret) {
|
||||
ath12k_warn(ab, "failed to setup peer rx reorder queuefor tid %d: %d\n",
|
||||
tid, ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
rx_tid->tid = tid;
|
||||
@@ -1362,11 +1374,6 @@ ath12k_update_per_peer_tx_stats(struct ath12k *ar,
|
||||
* Firmware rate's control to be skipped for this?
|
||||
*/
|
||||
|
||||
if (flags == WMI_RATE_PREAMBLE_HE && mcs > 11) {
|
||||
ath12k_warn(ab, "Invalid HE mcs %d peer stats", mcs);
|
||||
return;
|
||||
}
|
||||
|
||||
if (flags == WMI_RATE_PREAMBLE_HE && mcs > ATH12K_HE_MCS_MAX) {
|
||||
ath12k_warn(ab, "Invalid HE mcs %d peer stats", mcs);
|
||||
return;
|
||||
|
||||
@@ -906,6 +906,7 @@ static const struct ath12k_hw_params ath12k_hw_params[] = {
|
||||
|
||||
.hal_ops = &hal_qcn9274_ops,
|
||||
|
||||
.qmi_cnss_feature_bitmap = BIT(CNSS_QDSS_CFG_MISS_V01),
|
||||
},
|
||||
{
|
||||
.name = "wcn7850 hw2.0",
|
||||
@@ -960,6 +961,9 @@ static const struct ath12k_hw_params ath12k_hw_params[] = {
|
||||
.wmi_init = ath12k_wmi_init_wcn7850,
|
||||
|
||||
.hal_ops = &hal_wcn7850_ops,
|
||||
|
||||
.qmi_cnss_feature_bitmap = BIT(CNSS_QDSS_CFG_MISS_V01) |
|
||||
BIT(CNSS_PCIE_PERST_NO_PULL_V01),
|
||||
},
|
||||
{
|
||||
.name = "qcn9274 hw2.0",
|
||||
@@ -1013,6 +1017,8 @@ static const struct ath12k_hw_params ath12k_hw_params[] = {
|
||||
.wmi_init = ath12k_wmi_init_qcn9274,
|
||||
|
||||
.hal_ops = &hal_qcn9274_ops,
|
||||
|
||||
.qmi_cnss_feature_bitmap = BIT(CNSS_QDSS_CFG_MISS_V01),
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -184,6 +184,8 @@ struct ath12k_hw_params {
|
||||
struct ath12k_wmi_resource_config_arg *config);
|
||||
|
||||
const struct hal_ops *hal_ops;
|
||||
|
||||
u64 qmi_cnss_feature_bitmap;
|
||||
};
|
||||
|
||||
struct ath12k_hw_ops {
|
||||
|
||||
@@ -381,7 +381,7 @@ u8 ath12k_mac_bitrate_to_idx(const struct ieee80211_supported_band *sband,
|
||||
}
|
||||
|
||||
static u32
|
||||
ath12k_mac_max_ht_nss(const u8 ht_mcs_mask[IEEE80211_HT_MCS_MASK_LEN])
|
||||
ath12k_mac_max_ht_nss(const u8 *ht_mcs_mask)
|
||||
{
|
||||
int nss;
|
||||
|
||||
@@ -393,7 +393,7 @@ ath12k_mac_max_ht_nss(const u8 ht_mcs_mask[IEEE80211_HT_MCS_MASK_LEN])
|
||||
}
|
||||
|
||||
static u32
|
||||
ath12k_mac_max_vht_nss(const u16 vht_mcs_mask[NL80211_VHT_NSS_MAX])
|
||||
ath12k_mac_max_vht_nss(const u16 *vht_mcs_mask)
|
||||
{
|
||||
int nss;
|
||||
|
||||
@@ -771,6 +771,9 @@ static int ath12k_mac_vdev_setup_sync(struct ath12k *ar)
|
||||
if (test_bit(ATH12K_FLAG_CRASH_FLUSH, &ar->ab->dev_flags))
|
||||
return -ESHUTDOWN;
|
||||
|
||||
ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "vdev setup timeout %d\n",
|
||||
ATH12K_VDEV_SETUP_TIMEOUT_HZ);
|
||||
|
||||
if (!wait_for_completion_timeout(&ar->vdev_setup_done,
|
||||
ATH12K_VDEV_SETUP_TIMEOUT_HZ))
|
||||
return -ETIMEDOUT;
|
||||
@@ -1303,7 +1306,7 @@ static void ath12k_peer_assoc_h_rates(struct ath12k *ar,
|
||||
}
|
||||
|
||||
static bool
|
||||
ath12k_peer_assoc_h_ht_masked(const u8 ht_mcs_mask[IEEE80211_HT_MCS_MASK_LEN])
|
||||
ath12k_peer_assoc_h_ht_masked(const u8 *ht_mcs_mask)
|
||||
{
|
||||
int nss;
|
||||
|
||||
@@ -1315,7 +1318,7 @@ ath12k_peer_assoc_h_ht_masked(const u8 ht_mcs_mask[IEEE80211_HT_MCS_MASK_LEN])
|
||||
}
|
||||
|
||||
static bool
|
||||
ath12k_peer_assoc_h_vht_masked(const u16 vht_mcs_mask[NL80211_VHT_NSS_MAX])
|
||||
ath12k_peer_assoc_h_vht_masked(const u16 *vht_mcs_mask)
|
||||
{
|
||||
int nss;
|
||||
|
||||
@@ -4375,6 +4378,21 @@ static int __ath12k_set_antenna(struct ath12k *ar, u32 tx_ant, u32 rx_ant)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ath12k_mgmt_over_wmi_tx_drop(struct ath12k *ar, struct sk_buff *skb)
|
||||
{
|
||||
int num_mgmt;
|
||||
|
||||
ieee80211_free_txskb(ar->hw, skb);
|
||||
|
||||
num_mgmt = atomic_dec_if_positive(&ar->num_pending_mgmt_tx);
|
||||
|
||||
if (num_mgmt < 0)
|
||||
WARN_ON_ONCE(1);
|
||||
|
||||
if (!num_mgmt)
|
||||
wake_up(&ar->txmgmt_empty_waitq);
|
||||
}
|
||||
|
||||
int ath12k_mac_tx_mgmt_pending_free(int buf_id, void *skb, void *ctx)
|
||||
{
|
||||
struct sk_buff *msdu = skb;
|
||||
@@ -4391,7 +4409,7 @@ int ath12k_mac_tx_mgmt_pending_free(int buf_id, void *skb, void *ctx)
|
||||
info = IEEE80211_SKB_CB(msdu);
|
||||
memset(&info->status, 0, sizeof(info->status));
|
||||
|
||||
ieee80211_free_txskb(ar->hw, msdu);
|
||||
ath12k_mgmt_over_wmi_tx_drop(ar, skb);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -4475,7 +4493,7 @@ static void ath12k_mgmt_over_wmi_tx_purge(struct ath12k *ar)
|
||||
struct sk_buff *skb;
|
||||
|
||||
while ((skb = skb_dequeue(&ar->wmi_mgmt_tx_queue)) != NULL)
|
||||
ieee80211_free_txskb(ar->hw, skb);
|
||||
ath12k_mgmt_over_wmi_tx_drop(ar, skb);
|
||||
}
|
||||
|
||||
static void ath12k_mgmt_over_wmi_tx_work(struct work_struct *work)
|
||||
@@ -4490,7 +4508,7 @@ static void ath12k_mgmt_over_wmi_tx_work(struct work_struct *work)
|
||||
skb_cb = ATH12K_SKB_CB(skb);
|
||||
if (!skb_cb->vif) {
|
||||
ath12k_warn(ar->ab, "no vif found for mgmt frame\n");
|
||||
ieee80211_free_txskb(ar->hw, skb);
|
||||
ath12k_mgmt_over_wmi_tx_drop(ar, skb);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -4501,16 +4519,14 @@ static void ath12k_mgmt_over_wmi_tx_work(struct work_struct *work)
|
||||
if (ret) {
|
||||
ath12k_warn(ar->ab, "failed to tx mgmt frame, vdev_id %d :%d\n",
|
||||
arvif->vdev_id, ret);
|
||||
ieee80211_free_txskb(ar->hw, skb);
|
||||
} else {
|
||||
atomic_inc(&ar->num_pending_mgmt_tx);
|
||||
ath12k_mgmt_over_wmi_tx_drop(ar, skb);
|
||||
}
|
||||
} else {
|
||||
ath12k_warn(ar->ab,
|
||||
"dropping mgmt frame for vdev %d, is_started %d\n",
|
||||
arvif->vdev_id,
|
||||
arvif->is_started);
|
||||
ieee80211_free_txskb(ar->hw, skb);
|
||||
ath12k_mgmt_over_wmi_tx_drop(ar, skb);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4535,12 +4551,13 @@ static int ath12k_mac_mgmt_tx(struct ath12k *ar, struct sk_buff *skb,
|
||||
return -ENOSPC;
|
||||
}
|
||||
|
||||
if (skb_queue_len(q) == ATH12K_TX_MGMT_NUM_PENDING_MAX) {
|
||||
if (skb_queue_len_lockless(q) >= ATH12K_TX_MGMT_NUM_PENDING_MAX) {
|
||||
ath12k_warn(ar->ab, "mgmt tx queue is full\n");
|
||||
return -ENOSPC;
|
||||
}
|
||||
|
||||
skb_queue_tail(q, skb);
|
||||
atomic_inc(&ar->num_pending_mgmt_tx);
|
||||
ieee80211_queue_work(ar->hw, &ar->wmi_mgmt_tx_work);
|
||||
|
||||
return 0;
|
||||
@@ -6014,6 +6031,13 @@ static void ath12k_mac_op_flush(struct ieee80211_hw *hw, struct ieee80211_vif *v
|
||||
ATH12K_FLUSH_TIMEOUT);
|
||||
if (time_left == 0)
|
||||
ath12k_warn(ar->ab, "failed to flush transmit queue %ld\n", time_left);
|
||||
|
||||
time_left = wait_event_timeout(ar->txmgmt_empty_waitq,
|
||||
(atomic_read(&ar->num_pending_mgmt_tx) == 0),
|
||||
ATH12K_FLUSH_TIMEOUT);
|
||||
if (time_left == 0)
|
||||
ath12k_warn(ar->ab, "failed to flush mgmt transmit queue %ld\n",
|
||||
time_left);
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -6991,6 +7015,7 @@ int ath12k_mac_register(struct ath12k_base *ab)
|
||||
if (ret)
|
||||
goto err_cleanup;
|
||||
|
||||
init_waitqueue_head(&ar->txmgmt_empty_waitq);
|
||||
idr_init(&ar->txmgmt_idr);
|
||||
spin_lock_init(&ar->txmgmt_idr_lock);
|
||||
}
|
||||
|
||||
@@ -1942,8 +1942,10 @@ static int ath12k_qmi_host_cap_send(struct ath12k_base *ab)
|
||||
req.cal_done_valid = 1;
|
||||
req.cal_done = ab->qmi.cal_done;
|
||||
|
||||
req.feature_list_valid = 1;
|
||||
req.feature_list = BIT(CNSS_QDSS_CFG_MISS_V01);
|
||||
if (ab->hw_params->qmi_cnss_feature_bitmap) {
|
||||
req.feature_list_valid = 1;
|
||||
req.feature_list = ab->hw_params->qmi_cnss_feature_bitmap;
|
||||
}
|
||||
|
||||
/* BRINGUP: here we are piggybacking a lot of stuff using
|
||||
* internal_sleep_clock, should it be split?
|
||||
|
||||
@@ -189,6 +189,7 @@ struct wlfw_host_mlo_chip_info_s_v01 {
|
||||
enum ath12k_qmi_cnss_feature {
|
||||
CNSS_FEATURE_MIN_ENUM_VAL_V01 = INT_MIN,
|
||||
CNSS_QDSS_CFG_MISS_V01 = 3,
|
||||
CNSS_PCIE_PERST_NO_PULL_V01 = 4,
|
||||
CNSS_MAX_FEATURE_V01 = 64,
|
||||
CNSS_FEATURE_MAX_ENUM_VAL_V01 = INT_MAX,
|
||||
};
|
||||
|
||||
@@ -4640,6 +4640,7 @@ static int wmi_process_mgmt_tx_comp(struct ath12k *ar, u32 desc_id,
|
||||
struct sk_buff *msdu;
|
||||
struct ieee80211_tx_info *info;
|
||||
struct ath12k_skb_cb *skb_cb;
|
||||
int num_mgmt;
|
||||
|
||||
spin_lock_bh(&ar->txmgmt_idr_lock);
|
||||
msdu = idr_find(&ar->txmgmt_idr, desc_id);
|
||||
@@ -4663,10 +4664,15 @@ static int wmi_process_mgmt_tx_comp(struct ath12k *ar, u32 desc_id,
|
||||
|
||||
ieee80211_tx_status_irqsafe(ar->hw, msdu);
|
||||
|
||||
num_mgmt = atomic_dec_if_positive(&ar->num_pending_mgmt_tx);
|
||||
|
||||
/* WARN when we received this event without doing any mgmt tx */
|
||||
if (atomic_dec_if_positive(&ar->num_pending_mgmt_tx) < 0)
|
||||
if (num_mgmt < 0)
|
||||
WARN_ON_ONCE(1);
|
||||
|
||||
if (!num_mgmt)
|
||||
wake_up(&ar->txmgmt_empty_waitq);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -2682,7 +2682,7 @@ struct ath12k_wmi_ssid_params {
|
||||
u8 ssid[ATH12K_WMI_SSID_LEN];
|
||||
} __packed;
|
||||
|
||||
#define ATH12K_VDEV_SETUP_TIMEOUT_HZ (1 * HZ)
|
||||
#define ATH12K_VDEV_SETUP_TIMEOUT_HZ (5 * HZ)
|
||||
|
||||
struct wmi_vdev_start_request_cmd {
|
||||
__le32 tlv_header;
|
||||
|
||||
@@ -1099,17 +1099,22 @@ static bool ath9k_hw_verify_hang(struct ath_hw *ah, unsigned int queue)
|
||||
{
|
||||
u32 dma_dbg_chain, dma_dbg_complete;
|
||||
u8 dcu_chain_state, dcu_complete_state;
|
||||
unsigned int dbg_reg, reg_offset;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NUM_STATUS_READS; i++) {
|
||||
if (queue < 6)
|
||||
dma_dbg_chain = REG_READ(ah, AR_DMADBG_4);
|
||||
else
|
||||
dma_dbg_chain = REG_READ(ah, AR_DMADBG_5);
|
||||
if (queue < 6) {
|
||||
dbg_reg = AR_DMADBG_4;
|
||||
reg_offset = queue * 5;
|
||||
} else {
|
||||
dbg_reg = AR_DMADBG_5;
|
||||
reg_offset = (queue - 6) * 5;
|
||||
}
|
||||
|
||||
for (i = 0; i < NUM_STATUS_READS; i++) {
|
||||
dma_dbg_chain = REG_READ(ah, dbg_reg);
|
||||
dma_dbg_complete = REG_READ(ah, AR_DMADBG_6);
|
||||
|
||||
dcu_chain_state = (dma_dbg_chain >> (5 * queue)) & 0x1f;
|
||||
dcu_chain_state = (dma_dbg_chain >> reg_offset) & 0x1f;
|
||||
dcu_complete_state = dma_dbg_complete & 0x3;
|
||||
|
||||
if ((dcu_chain_state != 0x6) || (dcu_complete_state != 0x1))
|
||||
@@ -1128,6 +1133,7 @@ static bool ar9003_hw_detect_mac_hang(struct ath_hw *ah)
|
||||
u8 dcu_chain_state, dcu_complete_state;
|
||||
bool dcu_wait_frdone = false;
|
||||
unsigned long chk_dcu = 0;
|
||||
unsigned int reg_offset;
|
||||
unsigned int i = 0;
|
||||
|
||||
dma_dbg_4 = REG_READ(ah, AR_DMADBG_4);
|
||||
@@ -1139,12 +1145,15 @@ static bool ar9003_hw_detect_mac_hang(struct ath_hw *ah)
|
||||
goto exit;
|
||||
|
||||
for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
|
||||
if (i < 6)
|
||||
if (i < 6) {
|
||||
chk_dbg = dma_dbg_4;
|
||||
else
|
||||
reg_offset = i * 5;
|
||||
} else {
|
||||
chk_dbg = dma_dbg_5;
|
||||
reg_offset = (i - 6) * 5;
|
||||
}
|
||||
|
||||
dcu_chain_state = (chk_dbg >> (5 * i)) & 0x1f;
|
||||
dcu_chain_state = (chk_dbg >> reg_offset) & 0x1f;
|
||||
if (dcu_chain_state == 0x6) {
|
||||
dcu_wait_frdone = true;
|
||||
chk_dcu |= BIT(i);
|
||||
|
||||
@@ -221,6 +221,10 @@ static void ath9k_wmi_ctrl_rx(void *priv, struct sk_buff *skb,
|
||||
if (unlikely(wmi->stopped))
|
||||
goto free_skb;
|
||||
|
||||
/* Validate the obtained SKB. */
|
||||
if (unlikely(skb->len < sizeof(struct wmi_cmd_hdr)))
|
||||
goto free_skb;
|
||||
|
||||
hdr = (struct wmi_cmd_hdr *) skb->data;
|
||||
cmd_id = be16_to_cpu(hdr->command_id);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user