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:
Kalle Valo
2023-05-17 17:59:59 +03:00
23 changed files with 546 additions and 153 deletions
+3
View File
@@ -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);
+3
View File
@@ -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];
+2 -2
View File
@@ -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) &&
+4 -2
View File
@@ -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. */
+6 -28
View File
@@ -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);
-2
View File
@@ -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);
+3
View File
@@ -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,
+1
View File
@@ -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
+367 -52
View File
@@ -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,
&params->mbssid_flags,
&params->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)) {
+22 -28
View File
@@ -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",
+40 -8
View File
@@ -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);
+1
View File
@@ -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);
+1
View File
@@ -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
+13 -6
View File
@@ -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;
+6
View File
@@ -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),
},
};
+2
View File
@@ -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 {
+37 -12
View File
@@ -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);
}
+4 -2
View File
@@ -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?
+1
View File
@@ -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,
};
+7 -1
View File
@@ -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;
}
+1 -1
View File
@@ -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;
+18 -9
View File
@@ -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);
+4
View File
@@ -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);