* [PATCH V13 0/9] wifi: ath12k: add MU-MIMO and 160 MHz bandwidth support
@ 2025-04-18 17:48 Pradeep Kumar Chitrapu
2025-04-18 17:48 ` [PATCH V13 1/9] wifi: ath12k: push HE MU-MIMO params to hardware Pradeep Kumar Chitrapu
` (10 more replies)
0 siblings, 11 replies; 21+ messages in thread
From: Pradeep Kumar Chitrapu @ 2025-04-18 17:48 UTC (permalink / raw)
To: ath12k; +Cc: linux-wireless, Pradeep Kumar Chitrapu
Add support for
1. enabling MU-MIMO in HE and EHT modes from hardware
2. setting fixed HE rate/GI/LTF
3. 160 MHz bandwidth in HE mode
4. extended NSS bandwidth support
Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.0.1-00029-QCAHKSWPL_SILICONZ-1
Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0.c5-00481-QCAHMTSWPL_V1.0_V2.0_SILICONZ-3
changes in v13:
- rebase
changes in v12:
- rebase
changes in v11:
patch 1/9:
- fix return values in ath12k_mac_set_he_txbf_conf() and
ath12k_mac_vif_recalc_sta_he_txbf()
patch 6/9:
- fix missing he_mcs initialization in ath12k_mac_init_arvif()
changes in v10:
patch 6/9:
- use ath12k_ahsta_to_sta()
- fix rcu_dereference warning in ath12k_mac_set_bitrate_mask_iter()
- change return type for ath12k_mac_validate_fixed_rate_settings()
- improve readability by adhering to nl80211 definitions of GI
NL80211_TXRATE_DEFAULT_GI. Introduce ath12k_mac_nlgi_to_wmigi()
for conversion.
patch 7/9:
- do not change default MODE_11AC_VHT160 in
ath12k_mac_get_phymode_vht() as it breaks clients which do not
set VHT_CAP_SUPP_CHAN_WIDTH_160MHZ.
patch 8/9:
- Use IEEE80211_VHT_CAP_EXT_NSS_BW_MASK along with
IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ for determining VHT160
phymode.
changes in v9: rebase on top of master branch with mlo changes
patch 1/9 and 2/9:
- fetch link_conf using ath12k_mac_get_link_bss_conf()
instead of arvif->vif->bss_conf before mlo
patch 6/9
- fetch mcs/nss values from sta->link[] instead of sta->deflink
- fix spelling of 'incompatibility'
patch 8/9
- replace sta->deflink.addr with arsta->addr in
ath12k_peer_assoc_h_vht
patch 9/9
- replace sta->deflink.rx_nss with link_sta->rx_nss
changes in v8:
- rebase and resolve KASAN warnings reported by Jeff in v7, in patch 6/9.
Pradeep Kumar Chitrapu (9):
wifi: ath12k: push HE MU-MIMO params to hardware
wifi: ath12k: push EHT MU-MIMO params to hardware
wifi: ath12k: move HE MCS mapper to a separate function
wifi: ath12k: generate rx and tx mcs maps for supported HE mcs
wifi: ath12k: fix TX and RX MCS rate configurations in HE mode
wifi: ath12k: add support for setting fixed HE rate/GI/LTF
wifi: ath12k: clean up 80P80 support
wifi: ath12k: add support for 160 MHz bandwidth
wifi: ath12k: add extended NSS bandwidth support for 160 MHz
drivers/net/wireless/ath/ath12k/core.h | 2 +
drivers/net/wireless/ath/ath12k/mac.c | 1141 ++++++++++++++++++++----
drivers/net/wireless/ath/ath12k/mac.h | 17 +
drivers/net/wireless/ath/ath12k/wmi.c | 13 +-
drivers/net/wireless/ath/ath12k/wmi.h | 107 ++-
5 files changed, 1058 insertions(+), 222 deletions(-)
base-commit: d33705bb41ff786b537f8ed50a187a474db111c1
--
2.34.1
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH V13 1/9] wifi: ath12k: push HE MU-MIMO params to hardware
2025-04-18 17:48 [PATCH V13 0/9] wifi: ath12k: add MU-MIMO and 160 MHz bandwidth support Pradeep Kumar Chitrapu
@ 2025-04-18 17:48 ` Pradeep Kumar Chitrapu
2025-04-18 17:48 ` [PATCH V13 2/9] wifi: ath12k: push EHT " Pradeep Kumar Chitrapu
` (9 subsequent siblings)
10 siblings, 0 replies; 21+ messages in thread
From: Pradeep Kumar Chitrapu @ 2025-04-18 17:48 UTC (permalink / raw)
To: ath12k; +Cc: linux-wireless, Pradeep Kumar Chitrapu, Muna Sinada, Jeff Johnson
Currently, only the HE IE in management frames is updated with
respect to MU-MIMO configurations, but this change is not
reflected in the hardware. Add support to propagate MU-MIMO
configurations to the hardware as well.
Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.0.1-00029-QCAHKSWPL_SILICONZ-1
Co-developed-by: Muna Sinada <quic_msinada@quicinc.com>
Signed-off-by: Muna Sinada <quic_msinada@quicinc.com>
Signed-off-by: Pradeep Kumar Chitrapu <quic_pradeepc@quicinc.com>
Acked-by: Jeff Johnson <quic_jjohnson@quicinc.com>
---
drivers/net/wireless/ath/ath12k/mac.c | 228 +++++++++++++++++---------
drivers/net/wireless/ath/ath12k/mac.h | 15 ++
drivers/net/wireless/ath/ath12k/wmi.h | 28 +---
3 files changed, 169 insertions(+), 102 deletions(-)
diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c
index d170bca72948..8d7c210bc160 100644
--- a/drivers/net/wireless/ath/ath12k/mac.c
+++ b/drivers/net/wireless/ath/ath12k/mac.c
@@ -3115,6 +3115,125 @@ static int ath12k_setup_peer_smps(struct ath12k *ar, struct ath12k_link_vif *arv
ath12k_smps_map[smps]);
}
+static int ath12k_mac_set_he_txbf_conf(struct ath12k_link_vif *arvif)
+{
+ struct ath12k_vif *ahvif = arvif->ahvif;
+ struct ath12k *ar = arvif->ar;
+ u32 param = WMI_VDEV_PARAM_SET_HEMU_MODE;
+ u32 value = 0;
+ int ret;
+ struct ieee80211_bss_conf *link_conf;
+
+ link_conf = ath12k_mac_get_link_bss_conf(arvif);
+ if (!link_conf) {
+ ath12k_warn(ar->ab, "unable to access bss link conf in txbf conf\n");
+ return -EINVAL;
+ }
+
+ if (!link_conf->he_support)
+ return 0;
+
+ if (link_conf->he_su_beamformer) {
+ value |= u32_encode_bits(HE_SU_BFER_ENABLE, HE_MODE_SU_TX_BFER);
+ if (link_conf->he_mu_beamformer &&
+ ahvif->vdev_type == WMI_VDEV_TYPE_AP)
+ value |= u32_encode_bits(HE_MU_BFER_ENABLE, HE_MODE_MU_TX_BFER);
+ }
+
+ if (ahvif->vif->type != NL80211_IFTYPE_MESH_POINT) {
+ value |= u32_encode_bits(HE_DL_MUOFDMA_ENABLE, HE_MODE_DL_OFDMA) |
+ u32_encode_bits(HE_UL_MUOFDMA_ENABLE, HE_MODE_UL_OFDMA);
+
+ if (link_conf->he_full_ul_mumimo)
+ value |= u32_encode_bits(HE_UL_MUMIMO_ENABLE, HE_MODE_UL_MUMIMO);
+
+ if (link_conf->he_su_beamformee)
+ value |= u32_encode_bits(HE_SU_BFEE_ENABLE, HE_MODE_SU_TX_BFEE);
+ }
+
+ ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id, param, value);
+ if (ret) {
+ ath12k_warn(ar->ab, "failed to set vdev %d HE MU mode: %d\n",
+ arvif->vdev_id, ret);
+ return ret;
+ }
+
+ param = WMI_VDEV_PARAM_SET_HE_SOUNDING_MODE;
+ value = u32_encode_bits(HE_VHT_SOUNDING_MODE_ENABLE, HE_VHT_SOUNDING_MODE) |
+ u32_encode_bits(HE_TRIG_NONTRIG_SOUNDING_MODE_ENABLE,
+ HE_TRIG_NONTRIG_SOUNDING_MODE);
+ ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
+ param, value);
+ if (ret) {
+ ath12k_warn(ar->ab, "failed to set vdev %d sounding mode: %d\n",
+ arvif->vdev_id, ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int ath12k_mac_vif_recalc_sta_he_txbf(struct ath12k *ar,
+ struct ath12k_link_vif *arvif,
+ struct ieee80211_sta_he_cap *he_cap,
+ int *hemode)
+{
+ struct ieee80211_vif *vif = arvif->ahvif->vif;
+ struct ieee80211_he_cap_elem he_cap_elem = {};
+ struct ieee80211_sta_he_cap *cap_band;
+ struct cfg80211_chan_def def;
+ u8 link_id = arvif->link_id;
+ struct ieee80211_bss_conf *link_conf;
+
+ link_conf = ath12k_mac_get_link_bss_conf(arvif);
+ if (!link_conf) {
+ ath12k_warn(ar->ab, "unable to access bss link conf in recalc txbf conf\n");
+ return -EINVAL;
+ }
+
+ if (!link_conf->he_support)
+ return 0;
+
+ if (vif->type != NL80211_IFTYPE_STATION)
+ return -EINVAL;
+
+ if (WARN_ON(ath12k_mac_vif_link_chan(vif, link_id, &def)))
+ return -EINVAL;
+
+ if (def.chan->band == NL80211_BAND_2GHZ)
+ cap_band = &ar->mac.iftype[NL80211_BAND_2GHZ][vif->type].he_cap;
+ else
+ cap_band = &ar->mac.iftype[NL80211_BAND_5GHZ][vif->type].he_cap;
+
+ memcpy(&he_cap_elem, &cap_band->he_cap_elem, sizeof(he_cap_elem));
+
+ *hemode = 0;
+ if (HECAP_PHY_SUBFME_GET(he_cap_elem.phy_cap_info)) {
+ if (HECAP_PHY_SUBFMR_GET(he_cap->he_cap_elem.phy_cap_info))
+ *hemode |= u32_encode_bits(HE_SU_BFEE_ENABLE, HE_MODE_SU_TX_BFEE);
+ if (HECAP_PHY_MUBFMR_GET(he_cap->he_cap_elem.phy_cap_info))
+ *hemode |= u32_encode_bits(HE_MU_BFEE_ENABLE, HE_MODE_MU_TX_BFEE);
+ }
+
+ if (vif->type != NL80211_IFTYPE_MESH_POINT) {
+ *hemode |= u32_encode_bits(HE_DL_MUOFDMA_ENABLE, HE_MODE_DL_OFDMA) |
+ u32_encode_bits(HE_UL_MUOFDMA_ENABLE, HE_MODE_UL_OFDMA);
+
+ if (HECAP_PHY_ULMUMIMO_GET(he_cap_elem.phy_cap_info))
+ if (HECAP_PHY_ULMUMIMO_GET(he_cap->he_cap_elem.phy_cap_info))
+ *hemode |= u32_encode_bits(HE_UL_MUMIMO_ENABLE,
+ HE_MODE_UL_MUMIMO);
+
+ if (u32_get_bits(*hemode, HE_MODE_MU_TX_BFEE))
+ *hemode |= u32_encode_bits(HE_SU_BFEE_ENABLE, HE_MODE_SU_TX_BFEE);
+
+ if (u32_get_bits(*hemode, HE_MODE_MU_TX_BFER))
+ *hemode |= u32_encode_bits(HE_SU_BFER_ENABLE, HE_MODE_SU_TX_BFER);
+ }
+
+ return 0;
+}
+
static u32 ath12k_mac_ieee80211_sta_bw_to_wmi(struct ath12k *ar,
struct ieee80211_link_sta *link_sta)
{
@@ -3160,6 +3279,7 @@ static void ath12k_bss_assoc(struct ath12k *ar,
struct ath12k_sta *ahsta;
struct ath12k_peer *peer;
bool is_auth = false;
+ u32 hemode = 0;
int ret;
lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
@@ -3203,8 +3323,26 @@ static void ath12k_bss_assoc(struct ath12k *ar,
ath12k_peer_assoc_prepare(ar, arvif, arsta, peer_arg, false);
+ /* link_sta->he_cap must be protected by rcu_read_lock */
+ ret = ath12k_mac_vif_recalc_sta_he_txbf(ar, arvif, &link_sta->he_cap, &hemode);
+ if (ret) {
+ ath12k_warn(ar->ab, "failed to recalc he txbf for vdev %i on bss %pM: %d\n",
+ arvif->vdev_id, bss_conf->bssid, ret);
+ rcu_read_unlock();
+ return;
+ }
+
rcu_read_unlock();
+ /* keep this before ath12k_wmi_send_peer_assoc_cmd() */
+ ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
+ WMI_VDEV_PARAM_SET_HEMU_MODE, hemode);
+ if (ret) {
+ ath12k_warn(ar->ab, "failed to submit vdev param txbf 0x%x: %d\n",
+ hemode, ret);
+ return;
+ }
+
ret = ath12k_wmi_send_peer_assoc_cmd(ar, peer_arg);
if (ret) {
ath12k_warn(ar->ab, "failed to run peer assoc for %pM vdev %i: %d\n",
@@ -3818,6 +3956,13 @@ static void ath12k_mac_bss_info_changed(struct ath12k *ar,
ether_addr_copy(arvif->bssid, info->bssid);
if (changed & BSS_CHANGED_BEACON_ENABLED) {
+ if (info->enable_beacon) {
+ ret = ath12k_mac_set_he_txbf_conf(arvif);
+ if (ret)
+ ath12k_warn(ar->ab,
+ "failed to set HE TXBF config for vdev: %d\n",
+ arvif->vdev_id);
+ }
ath12k_control_beaconing(arvif, info);
if (arvif->is_up && info->he_support &&
@@ -6759,11 +6904,14 @@ static void ath12k_mac_copy_he_cap(struct ath12k_band_cap *band_cap,
he_cap_elem->mac_cap_info[1] &=
IEEE80211_HE_MAC_CAP1_TF_MAC_PAD_DUR_MASK;
-
+ he_cap_elem->phy_cap_info[0] &=
+ IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G |
+ IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G |
+ IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G;
+ he_cap_elem->phy_cap_info[0] &=
+ ~IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G;
he_cap_elem->phy_cap_info[5] &=
~IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_MASK;
- he_cap_elem->phy_cap_info[5] &=
- ~IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ_MASK;
he_cap_elem->phy_cap_info[5] |= num_tx_chains - 1;
switch (iftype) {
@@ -8054,72 +8202,6 @@ static int ath12k_mac_setup_vdev_create_arg(struct ath12k_link_vif *arvif,
return 0;
}
-static u32
-ath12k_mac_prepare_he_mode(struct ath12k_pdev *pdev, u32 viftype)
-{
- struct ath12k_pdev_cap *pdev_cap = &pdev->cap;
- struct ath12k_band_cap *cap_band = NULL;
- u32 *hecap_phy_ptr = NULL;
- u32 hemode;
-
- if (pdev->cap.supported_bands & WMI_HOST_WLAN_2GHZ_CAP)
- cap_band = &pdev_cap->band[NL80211_BAND_2GHZ];
- else
- cap_band = &pdev_cap->band[NL80211_BAND_5GHZ];
-
- hecap_phy_ptr = &cap_band->he_cap_phy_info[0];
-
- hemode = u32_encode_bits(HE_SU_BFEE_ENABLE, HE_MODE_SU_TX_BFEE) |
- u32_encode_bits(HECAP_PHY_SUBFMR_GET(hecap_phy_ptr),
- HE_MODE_SU_TX_BFER) |
- u32_encode_bits(HECAP_PHY_ULMUMIMO_GET(hecap_phy_ptr),
- HE_MODE_UL_MUMIMO);
-
- /* TODO: WDS and other modes */
- if (viftype == NL80211_IFTYPE_AP) {
- hemode |= u32_encode_bits(HECAP_PHY_MUBFMR_GET(hecap_phy_ptr),
- HE_MODE_MU_TX_BFER) |
- u32_encode_bits(HE_DL_MUOFDMA_ENABLE, HE_MODE_DL_OFDMA) |
- u32_encode_bits(HE_UL_MUOFDMA_ENABLE, HE_MODE_UL_OFDMA);
- } else {
- hemode |= u32_encode_bits(HE_MU_BFEE_ENABLE, HE_MODE_MU_TX_BFEE);
- }
-
- return hemode;
-}
-
-static int ath12k_set_he_mu_sounding_mode(struct ath12k *ar,
- struct ath12k_link_vif *arvif)
-{
- u32 param_id, param_value;
- struct ath12k_base *ab = ar->ab;
- struct ath12k_vif *ahvif = arvif->ahvif;
- int ret;
-
- param_id = WMI_VDEV_PARAM_SET_HEMU_MODE;
- param_value = ath12k_mac_prepare_he_mode(ar->pdev, ahvif->vif->type);
- ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
- param_id, param_value);
- if (ret) {
- ath12k_warn(ab, "failed to set vdev %d HE MU mode: %d param_value %x\n",
- arvif->vdev_id, ret, param_value);
- return ret;
- }
- param_id = WMI_VDEV_PARAM_SET_HE_SOUNDING_MODE;
- param_value =
- u32_encode_bits(HE_VHT_SOUNDING_MODE_ENABLE, HE_VHT_SOUNDING_MODE) |
- u32_encode_bits(HE_TRIG_NONTRIG_SOUNDING_MODE_ENABLE,
- HE_TRIG_NONTRIG_SOUNDING_MODE);
- ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
- param_id, param_value);
- if (ret) {
- ath12k_warn(ab, "failed to set vdev %d HE MU mode: %d\n",
- arvif->vdev_id, ret);
- return ret;
- }
- return ret;
-}
-
static void ath12k_mac_update_vif_offload(struct ath12k_link_vif *arvif)
{
struct ath12k_vif *ahvif = arvif->ahvif;
@@ -9278,14 +9360,6 @@ ath12k_mac_vdev_start_restart(struct ath12k_link_vif *arvif,
spin_unlock_bh(&ab->base_lock);
/* TODO: Notify if secondary 80Mhz also needs radar detection */
- if (link_conf->he_support) {
- ret = ath12k_set_he_mu_sounding_mode(ar, arvif);
- if (ret) {
- ath12k_warn(ar->ab, "failed to set he mode vdev %i\n",
- arg.vdev_id);
- return ret;
- }
- }
}
arg.passive |= !!(chandef->chan->flags & IEEE80211_CHAN_NO_IR);
diff --git a/drivers/net/wireless/ath/ath12k/mac.h b/drivers/net/wireless/ath/ath12k/mac.h
index da37332352fe..3ddfa00a5a17 100644
--- a/drivers/net/wireless/ath/ath12k/mac.h
+++ b/drivers/net/wireless/ath/ath12k/mac.h
@@ -54,6 +54,21 @@ struct ath12k_generic_iter {
#define ATH12K_DEFAULT_SCAN_LINK IEEE80211_MLD_MAX_NUM_LINKS
#define ATH12K_NUM_MAX_LINKS (IEEE80211_MLD_MAX_NUM_LINKS + 1)
+#define HECAP_PHY_SUBFMR_GET(hecap_phy) \
+ u8_get_bits(hecap_phy[3], IEEE80211_HE_PHY_CAP3_SU_BEAMFORMER)
+
+#define HECAP_PHY_SUBFME_GET(hecap_phy) \
+ u8_get_bits(hecap_phy[4], IEEE80211_HE_PHY_CAP4_SU_BEAMFORMEE)
+
+#define HECAP_PHY_MUBFMR_GET(hecap_phy) \
+ u8_get_bits(hecap_phy[4], IEEE80211_HE_PHY_CAP4_MU_BEAMFORMER)
+
+#define HECAP_PHY_ULMUMIMO_GET(hecap_phy) \
+ u8_get_bits(hecap_phy[2], IEEE80211_HE_PHY_CAP2_UL_MU_FULL_MU_MIMO)
+
+#define HECAP_PHY_ULOFDMA_GET(hecap_phy) \
+ u8_get_bits(hecap_phy[2], IEEE80211_HE_PHY_CAP2_UL_MU_PARTIAL_MU_MIMO)
+
enum ath12k_supported_bw {
ATH12K_BW_20 = 0,
ATH12K_BW_40 = 1,
diff --git a/drivers/net/wireless/ath/ath12k/wmi.h b/drivers/net/wireless/ath/ath12k/wmi.h
index 80fdbc566518..804992bb055c 100644
--- a/drivers/net/wireless/ath/ath12k/wmi.h
+++ b/drivers/net/wireless/ath/ath12k/wmi.h
@@ -3096,31 +3096,6 @@ struct ath12k_wmi_rx_reorder_queue_remove_arg {
#define WMI_VDEV_PARAM_TXBF_SU_TX_BFER BIT(2)
#define WMI_VDEV_PARAM_TXBF_MU_TX_BFER BIT(3)
-#define HECAP_PHYDWORD_0 0
-#define HECAP_PHYDWORD_1 1
-#define HECAP_PHYDWORD_2 2
-
-#define HECAP_PHY_SU_BFER BIT(31)
-#define HECAP_PHY_SU_BFEE BIT(0)
-#define HECAP_PHY_MU_BFER BIT(1)
-#define HECAP_PHY_UL_MUMIMO BIT(22)
-#define HECAP_PHY_UL_MUOFDMA BIT(23)
-
-#define HECAP_PHY_SUBFMR_GET(hecap_phy) \
- u32_get_bits(hecap_phy[HECAP_PHYDWORD_0], HECAP_PHY_SU_BFER)
-
-#define HECAP_PHY_SUBFME_GET(hecap_phy) \
- u32_get_bits(hecap_phy[HECAP_PHYDWORD_1], HECAP_PHY_SU_BFEE)
-
-#define HECAP_PHY_MUBFMR_GET(hecap_phy) \
- u32_get_bits(hecap_phy[HECAP_PHYDWORD_1], HECAP_PHY_MU_BFER)
-
-#define HECAP_PHY_ULMUMIMO_GET(hecap_phy) \
- u32_get_bits(hecap_phy[HECAP_PHYDWORD_0], HECAP_PHY_UL_MUMIMO)
-
-#define HECAP_PHY_ULOFDMA_GET(hecap_phy) \
- u32_get_bits(hecap_phy[HECAP_PHYDWORD_0], HECAP_PHY_UL_MUOFDMA)
-
#define HE_MODE_SU_TX_BFEE BIT(0)
#define HE_MODE_SU_TX_BFER BIT(1)
#define HE_MODE_MU_TX_BFEE BIT(2)
@@ -3132,8 +3107,11 @@ struct ath12k_wmi_rx_reorder_queue_remove_arg {
#define HE_DL_MUOFDMA_ENABLE 1
#define HE_UL_MUOFDMA_ENABLE 1
#define HE_DL_MUMIMO_ENABLE 1
+#define HE_UL_MUMIMO_ENABLE 1
#define HE_MU_BFEE_ENABLE 1
#define HE_SU_BFEE_ENABLE 1
+#define HE_MU_BFER_ENABLE 1
+#define HE_SU_BFER_ENABLE 1
#define HE_VHT_SOUNDING_MODE_ENABLE 1
#define HE_SU_MU_SOUNDING_MODE_ENABLE 1
--
2.34.1
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH V13 2/9] wifi: ath12k: push EHT MU-MIMO params to hardware
2025-04-18 17:48 [PATCH V13 0/9] wifi: ath12k: add MU-MIMO and 160 MHz bandwidth support Pradeep Kumar Chitrapu
2025-04-18 17:48 ` [PATCH V13 1/9] wifi: ath12k: push HE MU-MIMO params to hardware Pradeep Kumar Chitrapu
@ 2025-04-18 17:48 ` Pradeep Kumar Chitrapu
2025-04-18 17:48 ` [PATCH V13 3/9] wifi: ath12k: move HE MCS mapper to a separate function Pradeep Kumar Chitrapu
` (8 subsequent siblings)
10 siblings, 0 replies; 21+ messages in thread
From: Pradeep Kumar Chitrapu @ 2025-04-18 17:48 UTC (permalink / raw)
To: ath12k; +Cc: linux-wireless, Pradeep Kumar Chitrapu, Muna Sinada, Jeff Johnson
Currently, only the EHT IE in management frames is updated with
respect to MU-MIMO configurations, but this change is not
reflected in the hardware. Add support to propagate MU-MIMO
configurations to the hardware as well for AP mode. Similar
support for STA mode will be added in future.
Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.0.1-00029-QCAHKSWPL_SILICONZ-1
Co-developed-by: Muna Sinada <quic_msinada@quicinc.com>
Signed-off-by: Muna Sinada <quic_msinada@quicinc.com>
Signed-off-by: Pradeep Kumar Chitrapu <quic_pradeepc@quicinc.com>
Acked-by: Jeff Johnson <quic_jjohnson@quicinc.com>
---
drivers/net/wireless/ath/ath12k/mac.c | 58 +++++++++++++++++++++++++++
drivers/net/wireless/ath/ath12k/wmi.h | 21 ++++++++++
2 files changed, 79 insertions(+)
diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c
index 8d7c210bc160..8ef52ba86056 100644
--- a/drivers/net/wireless/ath/ath12k/mac.c
+++ b/drivers/net/wireless/ath/ath12k/mac.c
@@ -3234,6 +3234,58 @@ static int ath12k_mac_vif_recalc_sta_he_txbf(struct ath12k *ar,
return 0;
}
+static int ath12k_mac_set_eht_txbf_conf(struct ath12k_link_vif *arvif)
+{
+ struct ath12k_vif *ahvif = arvif->ahvif;
+ struct ath12k *ar = arvif->ar;
+ u32 param = WMI_VDEV_PARAM_SET_EHT_MU_MODE;
+ u32 value = 0;
+ int ret;
+ struct ieee80211_bss_conf *link_conf;
+
+ link_conf = ath12k_mac_get_link_bss_conf(arvif);
+ if (!link_conf) {
+ ath12k_warn(ar->ab, "unable to access bss link conf in eht txbf conf\n");
+ return -ENOENT;
+ }
+
+ if (!link_conf->eht_support)
+ return 0;
+
+ if (link_conf->eht_su_beamformer) {
+ value |= u32_encode_bits(EHT_SU_BFER_ENABLE, EHT_MODE_SU_TX_BFER);
+ if (link_conf->eht_mu_beamformer &&
+ ahvif->vdev_type == WMI_VDEV_TYPE_AP)
+ value |= u32_encode_bits(EHT_MU_BFER_ENABLE,
+ EHT_MODE_MU_TX_BFER) |
+ u32_encode_bits(EHT_DL_MUOFDMA_ENABLE,
+ EHT_MODE_DL_OFDMA_MUMIMO) |
+ u32_encode_bits(EHT_UL_MUOFDMA_ENABLE,
+ EHT_MODE_UL_OFDMA_MUMIMO);
+ }
+
+ if (ahvif->vif->type != NL80211_IFTYPE_MESH_POINT) {
+ value |= u32_encode_bits(EHT_DL_MUOFDMA_ENABLE, EHT_MODE_DL_OFDMA) |
+ u32_encode_bits(EHT_UL_MUOFDMA_ENABLE, EHT_MODE_UL_OFDMA);
+
+ if (link_conf->eht_80mhz_full_bw_ul_mumimo)
+ value |= u32_encode_bits(EHT_UL_MUMIMO_ENABLE, EHT_MODE_MUMIMO);
+
+ if (link_conf->eht_su_beamformee)
+ value |= u32_encode_bits(EHT_SU_BFEE_ENABLE,
+ EHT_MODE_SU_TX_BFEE);
+ }
+
+ ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id, param, value);
+ if (ret) {
+ ath12k_warn(ar->ab, "failed to set vdev %d EHT MU mode: %d\n",
+ arvif->vdev_id, ret);
+ return ret;
+ }
+
+ return 0;
+}
+
static u32 ath12k_mac_ieee80211_sta_bw_to_wmi(struct ath12k *ar,
struct ieee80211_link_sta *link_sta)
{
@@ -3962,6 +4014,12 @@ static void ath12k_mac_bss_info_changed(struct ath12k *ar,
ath12k_warn(ar->ab,
"failed to set HE TXBF config for vdev: %d\n",
arvif->vdev_id);
+
+ ret = ath12k_mac_set_eht_txbf_conf(arvif);
+ if (ret)
+ ath12k_warn(ar->ab,
+ "failed to set EHT TXBF config for vdev: %d\n",
+ arvif->vdev_id);
}
ath12k_control_beaconing(arvif, info);
diff --git a/drivers/net/wireless/ath/ath12k/wmi.h b/drivers/net/wireless/ath/ath12k/wmi.h
index 804992bb055c..c661bfa79ea0 100644
--- a/drivers/net/wireless/ath/ath12k/wmi.h
+++ b/drivers/net/wireless/ath/ath12k/wmi.h
@@ -1159,6 +1159,7 @@ enum wmi_tlv_vdev_param {
WMI_VDEV_PARAM_BSS_COLOR,
WMI_VDEV_PARAM_SET_HEMU_MODE,
WMI_VDEV_PARAM_HEOPS_0_31 = 0x8003,
+ WMI_VDEV_PARAM_SET_EHT_MU_MODE = 0x8005,
};
enum wmi_tlv_peer_flags {
@@ -3113,6 +3114,26 @@ struct ath12k_wmi_rx_reorder_queue_remove_arg {
#define HE_MU_BFER_ENABLE 1
#define HE_SU_BFER_ENABLE 1
+#define EHT_MODE_SU_TX_BFEE BIT(0)
+#define EHT_MODE_SU_TX_BFER BIT(1)
+#define EHT_MODE_MU_TX_BFEE BIT(2)
+#define EHT_MODE_MU_TX_BFER BIT(3)
+#define EHT_MODE_DL_OFDMA BIT(4)
+#define EHT_MODE_UL_OFDMA BIT(5)
+#define EHT_MODE_MUMIMO BIT(6)
+#define EHT_MODE_DL_OFDMA_TXBF BIT(7)
+#define EHT_MODE_DL_OFDMA_MUMIMO BIT(8)
+#define EHT_MODE_UL_OFDMA_MUMIMO BIT(9)
+
+#define EHT_DL_MUOFDMA_ENABLE 1
+#define EHT_UL_MUOFDMA_ENABLE 1
+#define EHT_DL_MUMIMO_ENABLE 1
+#define EHT_UL_MUMIMO_ENABLE 1
+#define EHT_MU_BFEE_ENABLE 1
+#define EHT_SU_BFEE_ENABLE 1
+#define EHT_MU_BFER_ENABLE 1
+#define EHT_SU_BFER_ENABLE 1
+
#define HE_VHT_SOUNDING_MODE_ENABLE 1
#define HE_SU_MU_SOUNDING_MODE_ENABLE 1
#define HE_TRIG_NONTRIG_SOUNDING_MODE_ENABLE 1
--
2.34.1
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH V13 3/9] wifi: ath12k: move HE MCS mapper to a separate function
2025-04-18 17:48 [PATCH V13 0/9] wifi: ath12k: add MU-MIMO and 160 MHz bandwidth support Pradeep Kumar Chitrapu
2025-04-18 17:48 ` [PATCH V13 1/9] wifi: ath12k: push HE MU-MIMO params to hardware Pradeep Kumar Chitrapu
2025-04-18 17:48 ` [PATCH V13 2/9] wifi: ath12k: push EHT " Pradeep Kumar Chitrapu
@ 2025-04-18 17:48 ` Pradeep Kumar Chitrapu
2025-04-18 17:48 ` [PATCH V13 4/9] wifi: ath12k: generate rx and tx mcs maps for supported HE mcs Pradeep Kumar Chitrapu
` (7 subsequent siblings)
10 siblings, 0 replies; 21+ messages in thread
From: Pradeep Kumar Chitrapu @ 2025-04-18 17:48 UTC (permalink / raw)
To: ath12k; +Cc: linux-wireless, Pradeep Kumar Chitrapu, Muna Sinada, Jeff Johnson
Refactor the HE MCS mapper functionality in
ath12k_mac_copy_he_cap() into a new function.
This helps improve readability, extensibility and will be used
when adding support for 160 MHz bandwidth in subsequent patches.
Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.0.1-00029-QCAHKSWPL_SILICONZ-1
Co-developed-by: Muna Sinada <quic_msinada@quicinc.com>
Signed-off-by: Muna Sinada <quic_msinada@quicinc.com>
Signed-off-by: Pradeep Kumar Chitrapu <quic_pradeepc@quicinc.com>
Acked-by: Jeff Johnson <quic_jjohnson@quicinc.com>
---
drivers/net/wireless/ath/ath12k/mac.c | 22 ++++++++++++++--------
1 file changed, 14 insertions(+), 8 deletions(-)
diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c
index 8ef52ba86056..30c7d5770ef6 100644
--- a/drivers/net/wireless/ath/ath12k/mac.c
+++ b/drivers/net/wireless/ath/ath12k/mac.c
@@ -6947,12 +6947,24 @@ static __le16 ath12k_mac_setup_he_6ghz_cap(struct ath12k_pdev_cap *pcap,
return cpu_to_le16(bcap->he_6ghz_capa);
}
+static void ath12k_mac_set_hemcsmap(struct ath12k_band_cap *band_cap,
+ struct ieee80211_sta_he_cap *he_cap)
+{
+ struct ieee80211_he_mcs_nss_supp *mcs_nss = &he_cap->he_mcs_nss_supp;
+
+ mcs_nss->rx_mcs_80 = cpu_to_le16(band_cap->he_mcs & 0xffff);
+ mcs_nss->tx_mcs_80 = cpu_to_le16(band_cap->he_mcs & 0xffff);
+ mcs_nss->rx_mcs_160 = cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff);
+ mcs_nss->tx_mcs_160 = cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff);
+ mcs_nss->rx_mcs_80p80 = cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff);
+ mcs_nss->tx_mcs_80p80 = cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff);
+}
+
static void ath12k_mac_copy_he_cap(struct ath12k_band_cap *band_cap,
int iftype, u8 num_tx_chains,
struct ieee80211_sta_he_cap *he_cap)
{
struct ieee80211_he_cap_elem *he_cap_elem = &he_cap->he_cap_elem;
- struct ieee80211_he_mcs_nss_supp *mcs_nss = &he_cap->he_mcs_nss_supp;
he_cap->has_he = true;
memcpy(he_cap_elem->mac_cap_info, band_cap->he_cap_info,
@@ -6992,13 +7004,7 @@ static void ath12k_mac_copy_he_cap(struct ath12k_band_cap *band_cap,
break;
}
- mcs_nss->rx_mcs_80 = cpu_to_le16(band_cap->he_mcs & 0xffff);
- mcs_nss->tx_mcs_80 = cpu_to_le16(band_cap->he_mcs & 0xffff);
- mcs_nss->rx_mcs_160 = cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff);
- mcs_nss->tx_mcs_160 = cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff);
- mcs_nss->rx_mcs_80p80 = cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff);
- mcs_nss->tx_mcs_80p80 = cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff);
-
+ ath12k_mac_set_hemcsmap(band_cap, he_cap);
memset(he_cap->ppe_thres, 0, sizeof(he_cap->ppe_thres));
if (he_cap_elem->phy_cap_info[6] &
IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT)
--
2.34.1
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH V13 4/9] wifi: ath12k: generate rx and tx mcs maps for supported HE mcs
2025-04-18 17:48 [PATCH V13 0/9] wifi: ath12k: add MU-MIMO and 160 MHz bandwidth support Pradeep Kumar Chitrapu
` (2 preceding siblings ...)
2025-04-18 17:48 ` [PATCH V13 3/9] wifi: ath12k: move HE MCS mapper to a separate function Pradeep Kumar Chitrapu
@ 2025-04-18 17:48 ` Pradeep Kumar Chitrapu
2025-05-29 6:59 ` Uraj Sasan
2025-04-18 17:48 ` [PATCH V13 5/9] wifi: ath12k: fix TX and RX MCS rate configurations in HE mode Pradeep Kumar Chitrapu
` (6 subsequent siblings)
10 siblings, 1 reply; 21+ messages in thread
From: Pradeep Kumar Chitrapu @ 2025-04-18 17:48 UTC (permalink / raw)
To: ath12k; +Cc: linux-wireless, Pradeep Kumar Chitrapu, Muna Sinada, Jeff Johnson
Generate rx and tx mcs maps in ath12k_mac_set_hemcsmap() based
on number of supported tx/rx chains and set them in supported
mcs/nss for HE capabilities.
Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.0.1-00029-QCAHKSWPL_SILICONZ-1
Co-developed-by: Muna Sinada <quic_msinada@quicinc.com>
Signed-off-by: Muna Sinada <quic_msinada@quicinc.com>
Signed-off-by: Pradeep Kumar Chitrapu <quic_pradeepc@quicinc.com>
Acked-by: Jeff Johnson <quic_jjohnson@quicinc.com>
---
drivers/net/wireless/ath/ath12k/mac.c | 40 ++++++++++++++++++++-------
1 file changed, 30 insertions(+), 10 deletions(-)
diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c
index 30c7d5770ef6..178c89029922 100644
--- a/drivers/net/wireless/ath/ath12k/mac.c
+++ b/drivers/net/wireless/ath/ath12k/mac.c
@@ -6947,20 +6947,40 @@ static __le16 ath12k_mac_setup_he_6ghz_cap(struct ath12k_pdev_cap *pcap,
return cpu_to_le16(bcap->he_6ghz_capa);
}
-static void ath12k_mac_set_hemcsmap(struct ath12k_band_cap *band_cap,
+static void ath12k_mac_set_hemcsmap(struct ath12k *ar,
+ struct ath12k_pdev_cap *cap,
struct ieee80211_sta_he_cap *he_cap)
{
struct ieee80211_he_mcs_nss_supp *mcs_nss = &he_cap->he_mcs_nss_supp;
+ u16 txmcs_map, rxmcs_map;
+ u32 i;
+
+ rxmcs_map = 0;
+ txmcs_map = 0;
+ for (i = 0; i < 8; i++) {
+ if (i < ar->num_tx_chains &&
+ (ar->cfg_tx_chainmask >> cap->tx_chain_mask_shift) & BIT(i))
+ txmcs_map |= IEEE80211_HE_MCS_SUPPORT_0_11 << (i * 2);
+ else
+ txmcs_map |= IEEE80211_HE_MCS_NOT_SUPPORTED << (i * 2);
+
+ if (i < ar->num_rx_chains &&
+ (ar->cfg_rx_chainmask >> cap->tx_chain_mask_shift) & BIT(i))
+ rxmcs_map |= IEEE80211_HE_MCS_SUPPORT_0_11 << (i * 2);
+ else
+ rxmcs_map |= IEEE80211_HE_MCS_NOT_SUPPORTED << (i * 2);
+ }
- mcs_nss->rx_mcs_80 = cpu_to_le16(band_cap->he_mcs & 0xffff);
- mcs_nss->tx_mcs_80 = cpu_to_le16(band_cap->he_mcs & 0xffff);
- mcs_nss->rx_mcs_160 = cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff);
- mcs_nss->tx_mcs_160 = cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff);
- mcs_nss->rx_mcs_80p80 = cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff);
- mcs_nss->tx_mcs_80p80 = cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff);
+ mcs_nss->rx_mcs_80 = cpu_to_le16(rxmcs_map & 0xffff);
+ mcs_nss->tx_mcs_80 = cpu_to_le16(txmcs_map & 0xffff);
+ mcs_nss->rx_mcs_160 = cpu_to_le16(rxmcs_map & 0xffff);
+ mcs_nss->tx_mcs_160 = cpu_to_le16(txmcs_map & 0xffff);
+ mcs_nss->rx_mcs_80p80 = cpu_to_le16(rxmcs_map & 0xffff);
+ mcs_nss->tx_mcs_80p80 = cpu_to_le16(txmcs_map & 0xffff);
}
-static void ath12k_mac_copy_he_cap(struct ath12k_band_cap *band_cap,
+static void ath12k_mac_copy_he_cap(struct ath12k *ar,
+ struct ath12k_band_cap *band_cap,
int iftype, u8 num_tx_chains,
struct ieee80211_sta_he_cap *he_cap)
{
@@ -7004,7 +7024,7 @@ static void ath12k_mac_copy_he_cap(struct ath12k_band_cap *band_cap,
break;
}
- ath12k_mac_set_hemcsmap(band_cap, he_cap);
+ ath12k_mac_set_hemcsmap(ar, &ar->pdev->cap, he_cap);
memset(he_cap->ppe_thres, 0, sizeof(he_cap->ppe_thres));
if (he_cap_elem->phy_cap_info[6] &
IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT)
@@ -7194,7 +7214,7 @@ static int ath12k_mac_copy_sband_iftype_data(struct ath12k *ar,
data[idx].types_mask = BIT(i);
- ath12k_mac_copy_he_cap(band_cap, i, ar->num_tx_chains, he_cap);
+ ath12k_mac_copy_he_cap(ar, band_cap, i, ar->num_tx_chains, he_cap);
if (band == NL80211_BAND_6GHZ) {
data[idx].he_6ghz_capa.capa =
ath12k_mac_setup_he_6ghz_cap(cap, band_cap);
--
2.34.1
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH V13 5/9] wifi: ath12k: fix TX and RX MCS rate configurations in HE mode
2025-04-18 17:48 [PATCH V13 0/9] wifi: ath12k: add MU-MIMO and 160 MHz bandwidth support Pradeep Kumar Chitrapu
` (3 preceding siblings ...)
2025-04-18 17:48 ` [PATCH V13 4/9] wifi: ath12k: generate rx and tx mcs maps for supported HE mcs Pradeep Kumar Chitrapu
@ 2025-04-18 17:48 ` Pradeep Kumar Chitrapu
2025-04-18 17:48 ` [PATCH V13 6/9] wifi: ath12k: add support for setting fixed HE rate/GI/LTF Pradeep Kumar Chitrapu
` (5 subsequent siblings)
10 siblings, 0 replies; 21+ messages in thread
From: Pradeep Kumar Chitrapu @ 2025-04-18 17:48 UTC (permalink / raw)
To: ath12k; +Cc: linux-wireless, Pradeep Kumar Chitrapu, Jeff Johnson
Currently, the TX and RX MCS rate configurations per peer are
reversed when sent to the firmware. As a result, RX MCS rates
are configured for TX, and vice versa. This commit rectifies
the configuration to match what the firmware expects.
Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.0.1-00029-QCAHKSWPL_SILICONZ-1
Fixes: d889913205cf ("wifi: ath12k: driver for Qualcomm Wi-Fi 7 devices")
Signed-off-by: Pradeep Kumar Chitrapu <quic_pradeepc@quicinc.com>
Acked-by: Jeff Johnson <quic_jjohnson@quicinc.com>
---
drivers/net/wireless/ath/ath12k/wmi.c | 4 ++--
drivers/net/wireless/ath/ath12k/wmi.h | 2 ++
2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c
index ea303dca38b5..6002d4df536a 100644
--- a/drivers/net/wireless/ath/ath12k/wmi.c
+++ b/drivers/net/wireless/ath/ath12k/wmi.c
@@ -2327,8 +2327,8 @@ int ath12k_wmi_send_peer_assoc_cmd(struct ath12k *ar,
he_mcs->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_HE_RATE_SET,
sizeof(*he_mcs));
- he_mcs->rx_mcs_set = cpu_to_le32(arg->peer_he_rx_mcs_set[i]);
- he_mcs->tx_mcs_set = cpu_to_le32(arg->peer_he_tx_mcs_set[i]);
+ he_mcs->rx_mcs_set = cpu_to_le32(arg->peer_he_tx_mcs_set[i]);
+ he_mcs->tx_mcs_set = cpu_to_le32(arg->peer_he_rx_mcs_set[i]);
ptr += sizeof(*he_mcs);
}
diff --git a/drivers/net/wireless/ath/ath12k/wmi.h b/drivers/net/wireless/ath/ath12k/wmi.h
index c661bfa79ea0..d4d0aae70011 100644
--- a/drivers/net/wireless/ath/ath12k/wmi.h
+++ b/drivers/net/wireless/ath/ath12k/wmi.h
@@ -4118,7 +4118,9 @@ struct ath12k_wmi_vht_rate_set_params {
struct ath12k_wmi_he_rate_set_params {
__le32 tlv_header;
+ /* MCS at which the peer can receive */
__le32 rx_mcs_set;
+ /* MCS at which the peer can transmit */
__le32 tx_mcs_set;
} __packed;
--
2.34.1
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH V13 6/9] wifi: ath12k: add support for setting fixed HE rate/GI/LTF
2025-04-18 17:48 [PATCH V13 0/9] wifi: ath12k: add MU-MIMO and 160 MHz bandwidth support Pradeep Kumar Chitrapu
` (4 preceding siblings ...)
2025-04-18 17:48 ` [PATCH V13 5/9] wifi: ath12k: fix TX and RX MCS rate configurations in HE mode Pradeep Kumar Chitrapu
@ 2025-04-18 17:48 ` Pradeep Kumar Chitrapu
2025-05-14 14:54 ` Jeff Johnson
2025-04-18 17:48 ` [PATCH V13 7/9] wifi: ath12k: clean up 80P80 support Pradeep Kumar Chitrapu
` (4 subsequent siblings)
10 siblings, 1 reply; 21+ messages in thread
From: Pradeep Kumar Chitrapu @ 2025-04-18 17:48 UTC (permalink / raw)
To: ath12k; +Cc: linux-wireless, Pradeep Kumar Chitrapu, Muna Sinada
Add support to set fixed HE rate/GI/LTF values using nl80211.
Reuse parts of the existing code path already used for HT/VHT
to implement the new helpers symmetrically, similar to how
HT/VHT is handled.
Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.0.1-00029-QCAHKSWPL_SILICONZ-1
Co-developed-by: Muna Sinada <quic_msinada@quicinc.com>
Signed-off-by: Muna Sinada <quic_msinada@quicinc.com>
Signed-off-by: Pradeep Kumar Chitrapu <quic_pradeepc@quicinc.com>
---
drivers/net/wireless/ath/ath12k/mac.c | 648 +++++++++++++++++++++++---
drivers/net/wireless/ath/ath12k/wmi.h | 27 ++
2 files changed, 623 insertions(+), 52 deletions(-)
diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c
index 178c89029922..bfad7bd1a1d4 100644
--- a/drivers/net/wireless/ath/ath12k/mac.c
+++ b/drivers/net/wireless/ath/ath12k/mac.c
@@ -520,6 +520,18 @@ ath12k_mac_max_vht_nss(const u16 *vht_mcs_mask)
return 1;
}
+static u32
+ath12k_mac_max_he_nss(const u16 he_mcs_mask[NL80211_HE_NSS_MAX])
+{
+ int nss;
+
+ for (nss = NL80211_HE_NSS_MAX - 1; nss >= 0; nss--)
+ if (he_mcs_mask[nss])
+ return nss + 1;
+
+ return 1;
+}
+
static u8 ath12k_parse_mpdudensity(u8 mpdudensity)
{
/* From IEEE Std 802.11-2020 defined values for "Minimum MPDU Start Spacing":
@@ -2035,9 +2047,15 @@ static void ath12k_peer_assoc_h_ht(struct ath12k *ar,
arg->peer_rate_caps |= WMI_HOST_RC_CW40_FLAG;
}
- if (arvif->bitrate_mask.control[band].gi != NL80211_TXRATE_FORCE_LGI) {
- if (ht_cap->cap & (IEEE80211_HT_CAP_SGI_20 |
- IEEE80211_HT_CAP_SGI_40))
+ /* As firmware handles these two flags (IEEE80211_HT_CAP_SGI_20
+ * and IEEE80211_HT_CAP_SGI_40) for enabling SGI, reset both
+ * flags if guard interval is to force Long GI
+ */
+ if (arvif->bitrate_mask.control[band].gi == NL80211_TXRATE_FORCE_LGI) {
+ arg->peer_ht_caps &= ~(IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_SGI_40);
+ } else {
+ /* Enable SGI flag if either SGI_20 or SGI_40 is supported */
+ if (ht_cap->cap & (IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_SGI_40))
arg->peer_rate_caps |= WMI_HOST_RC_SGI_FLAG;
}
@@ -2160,11 +2178,12 @@ static void ath12k_peer_assoc_h_vht(struct ath12k *ar,
struct ieee80211_link_sta *link_sta;
struct cfg80211_chan_def def;
enum nl80211_band band;
- const u16 *vht_mcs_mask;
+ u16 *vht_mcs_mask;
u16 tx_mcs_map;
u8 ampdu_factor;
u8 max_nss, vht_mcs;
- int i;
+ int i, vht_nss, nss_idx;
+ bool user_rate_valid = true;
lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
@@ -2217,6 +2236,25 @@ static void ath12k_peer_assoc_h_vht(struct ath12k *ar,
if (link_sta->bandwidth == IEEE80211_STA_RX_BW_160)
arg->bw_160 = true;
+ vht_nss = ath12k_mac_max_vht_nss(vht_mcs_mask);
+
+ if (vht_nss > link_sta->rx_nss) {
+ user_rate_valid = false;
+ for (nss_idx = link_sta->rx_nss - 1; nss_idx >= 0; nss_idx--) {
+ if (vht_mcs_mask[nss_idx]) {
+ user_rate_valid = true;
+ break;
+ }
+ }
+ }
+
+ if (!user_rate_valid) {
+ ath12k_dbg(ar->ab, ATH12K_DBG_MAC,
+ "Setting vht range MCS value to peer supported nss:%d for peer %pM\n",
+ link_sta->rx_nss, arsta->addr);
+ vht_mcs_mask[link_sta->rx_nss - 1] = vht_mcs_mask[vht_nss - 1];
+ }
+
/* Calculate peer NSS capability from VHT capabilities if STA
* supports VHT.
*/
@@ -2256,6 +2294,72 @@ static void ath12k_peer_assoc_h_vht(struct ath12k *ar,
/* TODO: rxnss_override */
}
+static int ath12k_mac_get_max_he_mcs_map(u16 mcs_map, int nss)
+{
+ switch ((mcs_map >> (2 * nss)) & 0x3) {
+ case IEEE80211_HE_MCS_SUPPORT_0_7: return BIT(8) - 1;
+ case IEEE80211_HE_MCS_SUPPORT_0_9: return BIT(10) - 1;
+ case IEEE80211_HE_MCS_SUPPORT_0_11: return BIT(12) - 1;
+ }
+ return 0;
+}
+
+static u16 ath12k_peer_assoc_h_he_limit(u16 tx_mcs_set,
+ const u16 *he_mcs_limit)
+{
+ int idx_limit;
+ int nss;
+ u16 mcs_map;
+ u16 mcs;
+
+ for (nss = 0; nss < NL80211_HE_NSS_MAX; nss++) {
+ mcs_map = ath12k_mac_get_max_he_mcs_map(tx_mcs_set, nss) &
+ he_mcs_limit[nss];
+
+ if (mcs_map)
+ idx_limit = fls(mcs_map) - 1;
+ else
+ idx_limit = -1;
+
+ switch (idx_limit) {
+ case 0 ... 7:
+ mcs = IEEE80211_HE_MCS_SUPPORT_0_7;
+ break;
+ case 8:
+ case 9:
+ mcs = IEEE80211_HE_MCS_SUPPORT_0_9;
+ break;
+ case 10:
+ case 11:
+ mcs = IEEE80211_HE_MCS_SUPPORT_0_11;
+ break;
+ default:
+ WARN_ON(1);
+ fallthrough;
+ case -1:
+ mcs = IEEE80211_HE_MCS_NOT_SUPPORTED;
+ break;
+ }
+
+ tx_mcs_set &= ~(0x3 << (nss * 2));
+ tx_mcs_set |= mcs << (nss * 2);
+ }
+
+ return tx_mcs_set;
+}
+
+static bool
+ath12k_peer_assoc_h_he_masked(const u16 he_mcs_mask[NL80211_HE_NSS_MAX])
+{
+ int nss;
+
+ for (nss = 0; nss < NL80211_HE_NSS_MAX; nss++)
+ if (he_mcs_mask[nss])
+ return false;
+
+ return true;
+}
+
static void ath12k_peer_assoc_h_he(struct ath12k *ar,
struct ath12k_link_vif *arvif,
struct ath12k_link_sta *arsta,
@@ -2266,18 +2370,28 @@ static void ath12k_peer_assoc_h_he(struct ath12k *ar,
const struct ieee80211_sta_he_cap *he_cap;
struct ieee80211_bss_conf *link_conf;
struct ieee80211_link_sta *link_sta;
+ struct cfg80211_chan_def def;
int i;
u8 ampdu_factor, max_nss;
u8 rx_mcs_80 = IEEE80211_HE_MCS_NOT_SUPPORTED;
u8 rx_mcs_160 = IEEE80211_HE_MCS_NOT_SUPPORTED;
u16 mcs_160_map, mcs_80_map;
+ u8 link_id = arvif->link_id;
bool support_160;
- u16 v;
+ enum nl80211_band band;
+ u16 *he_mcs_mask;
+ u8 he_mcs;
+ u16 he_tx_mcs = 0, v = 0;
+ int he_nss, nss_idx;
+ bool user_rate_valid = true;
+
+ if (WARN_ON(ath12k_mac_vif_link_chan(vif, link_id, &def)))
+ return;
link_conf = ath12k_mac_get_link_bss_conf(arvif);
if (!link_conf) {
ath12k_warn(ar->ab, "unable to access bss link conf in peer assoc he for vif %pM link %u",
- vif->addr, arvif->link_id);
+ vif->addr, link_id);
return;
}
@@ -2292,6 +2406,12 @@ static void ath12k_peer_assoc_h_he(struct ath12k *ar,
if (!he_cap->has_he)
return;
+ band = def.chan->band;
+ he_mcs_mask = arvif->bitrate_mask.control[band].he_mcs;
+
+ if (ath12k_peer_assoc_h_he_masked(he_mcs_mask))
+ return;
+
arg->he_flag = true;
support_160 = !!(he_cap->he_cap_elem.phy_cap_info[0] &
@@ -2397,25 +2517,47 @@ static void ath12k_peer_assoc_h_he(struct ath12k *ar,
if (he_cap->he_cap_elem.mac_cap_info[0] & IEEE80211_HE_MAC_CAP0_TWT_REQ)
arg->twt_requester = true;
+ he_nss = ath12k_mac_max_he_nss(he_mcs_mask);
+
+ if (he_nss > link_sta->rx_nss) {
+ user_rate_valid = false;
+ for (nss_idx = link_sta->rx_nss - 1; nss_idx >= 0; nss_idx--) {
+ if (he_mcs_mask[nss_idx]) {
+ user_rate_valid = true;
+ break;
+ }
+ }
+ }
+
+ if (!user_rate_valid) {
+ ath12k_dbg(ar->ab, ATH12K_DBG_MAC,
+ "Setting he range MCS value to peer supported nss:%d for peer %pM\n",
+ link_sta->rx_nss, arsta->addr);
+ he_mcs_mask[link_sta->rx_nss - 1] = he_mcs_mask[he_nss - 1];
+ }
+
switch (link_sta->bandwidth) {
case IEEE80211_STA_RX_BW_160:
if (he_cap->he_cap_elem.phy_cap_info[0] &
IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G) {
- v = le16_to_cpu(he_cap->he_mcs_nss_supp.rx_mcs_80p80);
+ v = ath12k_peer_assoc_h_he_limit(v, he_mcs_mask);
arg->peer_he_rx_mcs_set[WMI_HECAP_TXRX_MCS_NSS_IDX_80_80] = v;
v = le16_to_cpu(he_cap->he_mcs_nss_supp.tx_mcs_80p80);
arg->peer_he_tx_mcs_set[WMI_HECAP_TXRX_MCS_NSS_IDX_80_80] = v;
arg->peer_he_mcs_count++;
+ he_tx_mcs = v;
}
v = le16_to_cpu(he_cap->he_mcs_nss_supp.rx_mcs_160);
arg->peer_he_rx_mcs_set[WMI_HECAP_TXRX_MCS_NSS_IDX_160] = v;
- v = le16_to_cpu(he_cap->he_mcs_nss_supp.tx_mcs_160);
+ v = ath12k_peer_assoc_h_he_limit(v, he_mcs_mask);
arg->peer_he_tx_mcs_set[WMI_HECAP_TXRX_MCS_NSS_IDX_160] = v;
arg->peer_he_mcs_count++;
+ if (!he_tx_mcs)
+ he_tx_mcs = v;
fallthrough;
default:
@@ -2423,11 +2565,34 @@ static void ath12k_peer_assoc_h_he(struct ath12k *ar,
arg->peer_he_rx_mcs_set[WMI_HECAP_TXRX_MCS_NSS_IDX_80] = v;
v = le16_to_cpu(he_cap->he_mcs_nss_supp.tx_mcs_80);
+ v = ath12k_peer_assoc_h_he_limit(v, he_mcs_mask);
arg->peer_he_tx_mcs_set[WMI_HECAP_TXRX_MCS_NSS_IDX_80] = v;
arg->peer_he_mcs_count++;
+ if (!he_tx_mcs)
+ he_tx_mcs = v;
break;
}
+
+ /* Calculate peer NSS capability from HE capabilities if STA
+ * supports HE.
+ */
+ for (i = 0, max_nss = 0, he_mcs = 0; i < NL80211_HE_NSS_MAX; i++) {
+ he_mcs = he_tx_mcs >> (2 * i) & 3;
+
+ /* In case of fixed rates, MCS Range in he_tx_mcs might have
+ * unsupported range, with he_mcs_mask set, so check either of them
+ * to find nss.
+ */
+ if (he_mcs != IEEE80211_HE_MCS_NOT_SUPPORTED ||
+ he_mcs_mask[i])
+ max_nss = i + 1;
+ }
+ arg->peer_nss = min(link_sta->rx_nss, max_nss);
+
+ ath12k_dbg(ar->ab, ATH12K_DBG_MAC,
+ "mac he peer %pM nss %d mcs cnt %d\n",
+ arsta->addr, arg->peer_nss, arg->peer_he_mcs_count);
}
static void ath12k_peer_assoc_h_he_6ghz(struct ath12k *ar,
@@ -2763,6 +2928,7 @@ static void ath12k_peer_assoc_h_phymode(struct ath12k *ar,
enum nl80211_band band;
const u8 *ht_mcs_mask;
const u16 *vht_mcs_mask;
+ const u16 *he_mcs_mask;
enum wmi_phy_mode phymode = MODE_UNKNOWN;
lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
@@ -2776,6 +2942,7 @@ static void ath12k_peer_assoc_h_phymode(struct ath12k *ar,
band = def.chan->band;
ht_mcs_mask = arvif->bitrate_mask.control[band].ht_mcs;
vht_mcs_mask = arvif->bitrate_mask.control[band].vht_mcs;
+ he_mcs_mask = arvif->bitrate_mask.control[band].he_mcs;
link_sta = ath12k_mac_get_link_sta(arsta);
if (!link_sta) {
@@ -2791,7 +2958,8 @@ static void ath12k_peer_assoc_h_phymode(struct ath12k *ar,
phymode = MODE_11BE_EHT40_2G;
else
phymode = MODE_11BE_EHT20_2G;
- } else if (link_sta->he_cap.has_he) {
+ } else if (link_sta->he_cap.has_he &&
+ !ath12k_peer_assoc_h_he_masked(he_mcs_mask)) {
if (link_sta->bandwidth == IEEE80211_STA_RX_BW_80)
phymode = MODE_11AX_HE80_2G;
else if (link_sta->bandwidth == IEEE80211_STA_RX_BW_40)
@@ -2821,7 +2989,8 @@ static void ath12k_peer_assoc_h_phymode(struct ath12k *ar,
/* Check EHT first */
if (link_sta->eht_cap.has_eht) {
phymode = ath12k_mac_get_phymode_eht(ar, link_sta);
- } else if (link_sta->he_cap.has_he) {
+ } else if (link_sta->he_cap.has_he &&
+ !ath12k_peer_assoc_h_he_masked(he_mcs_mask)) {
phymode = ath12k_mac_get_phymode_he(ar, link_sta);
} else if (link_sta->vht_cap.vht_supported &&
!ath12k_peer_assoc_h_vht_masked(vht_mcs_mask)) {
@@ -3596,10 +3765,13 @@ static void ath12k_mac_init_arvif(struct ath12k_vif *ahvif,
for (i = 0; i < ARRAY_SIZE(arvif->bitrate_mask.control); i++) {
arvif->bitrate_mask.control[i].legacy = 0xffffffff;
+ arvif->bitrate_mask.control[i].gi = NL80211_TXRATE_DEFAULT_GI;
memset(arvif->bitrate_mask.control[i].ht_mcs, 0xff,
sizeof(arvif->bitrate_mask.control[i].ht_mcs));
memset(arvif->bitrate_mask.control[i].vht_mcs, 0xff,
sizeof(arvif->bitrate_mask.control[i].vht_mcs));
+ memset(arvif->bitrate_mask.control[i].he_mcs, 0xff,
+ sizeof(arvif->bitrate_mask.control[i].he_mcs));
}
/* Handle MLO related assignments */
@@ -5260,6 +5432,20 @@ ath12k_mac_bitrate_mask_num_vht_rates(struct ath12k *ar,
return num_rates;
}
+static int
+ath12k_mac_bitrate_mask_num_he_rates(struct ath12k *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].he_mcs); i++)
+ num_rates += hweight16(mask->control[band].he_mcs[i]);
+
+ return num_rates;
+}
+
static int
ath12k_mac_set_peer_vht_fixed_rate(struct ath12k_link_vif *arvif,
struct ath12k_link_sta *arsta,
@@ -5306,6 +5492,60 @@ ath12k_mac_set_peer_vht_fixed_rate(struct ath12k_link_vif *arvif,
return ret;
}
+static int
+ath12k_mac_set_peer_he_fixed_rate(struct ath12k_link_vif *arvif,
+ struct ath12k_link_sta *arsta,
+ const struct cfg80211_bitrate_mask *mask,
+ enum nl80211_band band)
+{
+ struct ath12k *ar = arvif->ar;
+ u8 he_rate, nss;
+ u32 rate_code;
+ int ret, i;
+ struct ath12k_sta *ahsta = arsta->ahsta;
+ struct ieee80211_sta *sta;
+
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
+
+ sta = ath12k_ahsta_to_sta(ahsta);
+ nss = 0;
+
+ for (i = 0; i < ARRAY_SIZE(mask->control[band].he_mcs); i++) {
+ if (hweight16(mask->control[band].he_mcs[i]) == 1) {
+ nss = i + 1;
+ he_rate = ffs(mask->control[band].he_mcs[i]) - 1;
+ }
+ }
+
+ if (!nss) {
+ ath12k_warn(ar->ab, "No single HE Fixed rate found to set for %pM",
+ arsta->addr);
+ return -EINVAL;
+ }
+
+ /* Avoid updating invalid nss as fixed rate*/
+ if (nss > sta->deflink.rx_nss)
+ return -EINVAL;
+
+ ath12k_dbg(ar->ab, ATH12K_DBG_MAC,
+ "Setting Fixed HE Rate for peer %pM. Device will not switch to any other selected rates",
+ arsta->addr);
+
+ rate_code = ATH12K_HW_RATE_CODE(he_rate, nss - 1,
+ WMI_RATE_PREAMBLE_HE);
+
+ ret = ath12k_wmi_set_peer_param(ar, arsta->addr,
+ arvif->vdev_id,
+ WMI_PEER_PARAM_FIXED_RATE,
+ rate_code);
+ if (ret)
+ ath12k_warn(ar->ab,
+ "failed to update STA %pM Fixed Rate %d: %d\n",
+ arsta->addr, rate_code, ret);
+
+ return ret;
+}
+
static int ath12k_mac_station_assoc(struct ath12k *ar,
struct ath12k_link_vif *arvif,
struct ath12k_link_sta *arsta,
@@ -5318,7 +5558,7 @@ static int ath12k_mac_station_assoc(struct ath12k *ar,
struct cfg80211_chan_def def;
enum nl80211_band band;
struct cfg80211_bitrate_mask *mask;
- u8 num_vht_rates;
+ u8 num_vht_rates, num_he_rates;
u8 link_id = arvif->link_id;
lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
@@ -5358,9 +5598,10 @@ static int ath12k_mac_station_assoc(struct ath12k *ar,
}
num_vht_rates = ath12k_mac_bitrate_mask_num_vht_rates(ar, band, mask);
+ num_he_rates = ath12k_mac_bitrate_mask_num_he_rates(ar, band, mask);
- /* If single VHT rate is configured (by set_bitrate_mask()),
- * peer_assoc will disable VHT. This is now enabled by a peer specific
+ /* 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
* fixed param.
* Note that all other rates and NSS will be disabled for this peer.
*/
@@ -5376,8 +5617,9 @@ static int ath12k_mac_station_assoc(struct ath12k *ar,
spin_unlock_bh(&ar->data_lock);
if (link_sta->vht_cap.vht_supported && num_vht_rates == 1) {
- ret = ath12k_mac_set_peer_vht_fixed_rate(arvif, arsta, mask,
- band);
+ ret = ath12k_mac_set_peer_vht_fixed_rate(arvif, arsta, mask, band);
+ } else if (link_sta->he_cap.has_he && num_he_rates == 1) {
+ ret = ath12k_mac_set_peer_he_fixed_rate(arvif, arsta, mask, band);
if (ret)
return ret;
}
@@ -5441,8 +5683,9 @@ static void ath12k_sta_rc_update_wk(struct wiphy *wiphy, struct wiphy_work *wk)
enum nl80211_band band;
const u8 *ht_mcs_mask;
const u16 *vht_mcs_mask;
- u32 changed, bw, nss, smps, bw_prev;
- int err, num_vht_rates;
+ const u16 *he_mcs_mask;
+ u32 changed, bw, nss, mac_nss, smps, bw_prev;
+ int err, num_vht_rates, num_he_rates;
const struct cfg80211_bitrate_mask *mask;
enum wmi_phy_mode peer_phymode;
struct ath12k_link_sta *arsta;
@@ -5462,6 +5705,7 @@ static void ath12k_sta_rc_update_wk(struct wiphy *wiphy, struct wiphy_work *wk)
band = def.chan->band;
ht_mcs_mask = arvif->bitrate_mask.control[band].ht_mcs;
vht_mcs_mask = arvif->bitrate_mask.control[band].vht_mcs;
+ he_mcs_mask = arvif->bitrate_mask.control[band].he_mcs;
spin_lock_bh(&ar->data_lock);
@@ -5476,8 +5720,10 @@ static void ath12k_sta_rc_update_wk(struct wiphy *wiphy, struct wiphy_work *wk)
spin_unlock_bh(&ar->data_lock);
nss = max_t(u32, 1, nss);
- nss = min(nss, max(ath12k_mac_max_ht_nss(ht_mcs_mask),
- ath12k_mac_max_vht_nss(vht_mcs_mask)));
+ mac_nss = max3(ath12k_mac_max_ht_nss(ht_mcs_mask),
+ ath12k_mac_max_vht_nss(vht_mcs_mask),
+ ath12k_mac_max_he_nss(he_mcs_mask));
+ nss = min(nss, mac_nss);
struct ath12k_wmi_peer_assoc_arg *peer_arg __free(kfree) =
kzalloc(sizeof(*peer_arg), GFP_KERNEL);
@@ -5560,6 +5806,8 @@ static void ath12k_sta_rc_update_wk(struct wiphy *wiphy, struct wiphy_work *wk)
mask = &arvif->bitrate_mask;
num_vht_rates = ath12k_mac_bitrate_mask_num_vht_rates(ar, band,
mask);
+ num_he_rates = ath12k_mac_bitrate_mask_num_he_rates(ar, band,
+ mask);
/* Peer_assoc_prepare will reject vht rates in
* bitrate_mask if its not available in range format and
@@ -5582,11 +5830,24 @@ static void ath12k_sta_rc_update_wk(struct wiphy *wiphy, struct wiphy_work *wk)
if (link_sta->vht_cap.vht_supported && num_vht_rates == 1) {
ath12k_mac_set_peer_vht_fixed_rate(arvif, arsta, mask,
band);
+ } else if (link_sta->he_cap.has_he && num_he_rates == 1) {
+ ath12k_mac_set_peer_he_fixed_rate(arvif, arsta, mask, band);
} else {
- /* If the peer is non-VHT or no fixed VHT rate
+ /* If the peer is non-VHT/HE or no fixed VHT/HE rate
* is provided in the new bitrate mask we set the
- * other rates using peer_assoc command.
+ * other rates using peer_assoc command. Also clear
+ * the peer fixed rate settings as it has higher proprity
+ * than peer assoc
*/
+ err = ath12k_wmi_set_peer_param(ar, arsta->addr,
+ arvif->vdev_id,
+ WMI_PEER_PARAM_FIXED_RATE,
+ WMI_FIXED_RATE_NONE);
+ if (err)
+ ath12k_warn(ar->ab,
+ "failed to disable peer fixed rate for STA %pM ret %d\n",
+ arsta->addr, err);
+
ath12k_peer_assoc_prepare(ar, arvif, arsta,
peer_arg, true);
@@ -10204,19 +10465,40 @@ ath12k_mac_has_single_legacy_rate(struct ath12k *ar,
if (ath12k_mac_bitrate_mask_num_vht_rates(ar, band, mask))
return false;
+ if (ath12k_mac_bitrate_mask_num_he_rates(ar, band, mask))
+ return false;
+
return num_rates == 1;
}
+static __le16
+ath12k_mac_get_tx_mcs_map(const struct ieee80211_sta_he_cap *he_cap)
+{
+ if (he_cap->he_cap_elem.phy_cap_info[0] &
+ IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G)
+ return he_cap->he_mcs_nss_supp.tx_mcs_80p80;
+
+ if (he_cap->he_cap_elem.phy_cap_info[0] &
+ IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G)
+ return he_cap->he_mcs_nss_supp.tx_mcs_160;
+
+ return he_cap->he_mcs_nss_supp.tx_mcs_80;
+}
+
static bool
ath12k_mac_bitrate_mask_get_single_nss(struct ath12k *ar,
+ struct ieee80211_vif *vif,
enum nl80211_band band,
const struct cfg80211_bitrate_mask *mask,
int *nss)
{
struct ieee80211_supported_band *sband = &ar->mac.sbands[band];
u16 vht_mcs_map = le16_to_cpu(sband->vht_cap.vht_mcs.tx_mcs_map);
+ const struct ieee80211_sta_he_cap *he_cap;
+ u16 he_mcs_map = 0;
u8 ht_nss_mask = 0;
u8 vht_nss_mask = 0;
+ u8 he_nss_mask = 0;
int i;
/* No need to consider legacy here. Basic rates are always present
@@ -10243,7 +10525,24 @@ ath12k_mac_bitrate_mask_get_single_nss(struct ath12k *ar,
return false;
}
- if (ht_nss_mask != vht_nss_mask)
+ he_cap = ieee80211_get_he_iftype_cap_vif(sband, vif);
+ if (!he_cap)
+ return false;
+
+ he_mcs_map = le16_to_cpu(ath12k_mac_get_tx_mcs_map(he_cap));
+
+ for (i = 0; i < ARRAY_SIZE(mask->control[band].he_mcs); i++) {
+ if (mask->control[band].he_mcs[i] == 0)
+ continue;
+
+ if (mask->control[band].he_mcs[i] ==
+ ath12k_mac_get_max_he_mcs_map(he_mcs_map, i))
+ he_nss_mask |= BIT(i);
+ else
+ return false;
+ }
+
+ if (ht_nss_mask != vht_nss_mask || ht_nss_mask != he_nss_mask)
return false;
if (ht_nss_mask == 0)
@@ -10290,54 +10589,182 @@ ath12k_mac_get_single_legacy_rate(struct ath12k *ar,
return 0;
}
-static int ath12k_mac_set_fixed_rate_params(struct ath12k_link_vif *arvif,
- u32 rate, u8 nss, u8 sgi, u8 ldpc)
+static int
+ath12k_mac_set_fixed_rate_gi_ltf(struct ath12k_link_vif *arvif, u8 he_gi, u8 he_ltf)
{
struct ath12k *ar = arvif->ar;
- u32 vdev_param;
int ret;
lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
- ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac set fixed rate params vdev %i rate 0x%02x nss %u sgi %u\n",
- arvif->vdev_id, rate, nss, sgi);
+ /* 0.8 = 0, 1.6 = 2 and 3.2 = 3. */
+ if (he_gi && he_gi != 0xFF)
+ he_gi += 1;
- vdev_param = WMI_VDEV_PARAM_FIXED_RATE;
ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
- vdev_param, rate);
+ WMI_VDEV_PARAM_SGI, he_gi);
if (ret) {
- ath12k_warn(ar->ab, "failed to set fixed rate param 0x%02x: %d\n",
- rate, ret);
+ ath12k_warn(ar->ab, "failed to set HE GI:%d, error:%d\n",
+ he_gi, ret);
return ret;
}
+ /* start from 1 */
+ if (he_ltf != 0xFF)
+ he_ltf += 1;
- vdev_param = WMI_VDEV_PARAM_NSS;
ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
- vdev_param, nss);
+ WMI_VDEV_PARAM_HE_LTF, he_ltf);
if (ret) {
- ath12k_warn(ar->ab, "failed to set nss param %d: %d\n",
- nss, ret);
+ ath12k_warn(ar->ab, "failed to set HE LTF:%d, error:%d\n",
+ he_ltf, ret);
return ret;
}
+ return 0;
+}
+
+static int
+ath12k_mac_set_auto_rate_gi_ltf(struct ath12k_link_vif *arvif, u16 he_gi, u8 he_ltf)
+{
+ struct ath12k *ar = arvif->ar;
+ int ret;
+ u32 he_ar_gi_ltf;
+
+ if (he_gi != 0xFF) {
+ switch (he_gi) {
+ case NL80211_RATE_INFO_HE_GI_0_8:
+ he_gi = WMI_AUTORATE_800NS_GI;
+ break;
+ case NL80211_RATE_INFO_HE_GI_1_6:
+ he_gi = WMI_AUTORATE_1600NS_GI;
+ break;
+ case NL80211_RATE_INFO_HE_GI_3_2:
+ he_gi = WMI_AUTORATE_3200NS_GI;
+ break;
+ default:
+ ath12k_warn(ar->ab, "Invalid GI\n");
+ return -EINVAL;
+ }
+ }
+
+ if (he_ltf != 0xFF) {
+ switch (he_ltf) {
+ case NL80211_RATE_INFO_HE_1XLTF:
+ he_ltf = WMI_HE_AUTORATE_LTF_1X;
+ break;
+ case NL80211_RATE_INFO_HE_2XLTF:
+ he_ltf = WMI_HE_AUTORATE_LTF_2X;
+ break;
+ case NL80211_RATE_INFO_HE_4XLTF:
+ he_ltf = WMI_HE_AUTORATE_LTF_4X;
+ break;
+ default:
+ ath12k_warn(ar->ab, "Invalid LTF\n");
+ return -EINVAL;
+ }
+ }
+
+ he_ar_gi_ltf = he_gi | he_ltf;
- vdev_param = WMI_VDEV_PARAM_SGI;
ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
- vdev_param, sgi);
+ WMI_VDEV_PARAM_AUTORATE_MISC_CFG,
+ he_ar_gi_ltf);
if (ret) {
- ath12k_warn(ar->ab, "failed to set sgi param %d: %d\n",
- sgi, ret);
+ ath12k_warn(ar->ab,
+ "failed to set HE autorate GI:%u, LTF:%u params, error:%d\n",
+ he_gi, he_ltf, ret);
return ret;
}
- vdev_param = WMI_VDEV_PARAM_LDPC;
+ return 0;
+}
+
+static u32 ath12k_mac_nlgi_to_wmigi(enum nl80211_txrate_gi gi)
+{
+ switch (gi) {
+ case NL80211_TXRATE_DEFAULT_GI:
+ return WMI_GI_400_NS;
+ case NL80211_TXRATE_FORCE_LGI:
+ return WMI_GI_800_NS;
+ default:
+ return WMI_GI_400_NS;
+ }
+}
+
+static int ath12k_mac_set_rate_params(struct ath12k_link_vif *arvif,
+ u32 rate, u8 nss, u8 sgi, u8 ldpc,
+ u8 he_gi, u8 he_ltf, bool he_fixed_rate)
+{
+ struct ieee80211_bss_conf *link_conf;
+ struct ath12k *ar = arvif->ar;
+ u32 vdev_param;
+ u32 param_value;
+ int ret;
+ bool he_support;
+
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
+
+ link_conf = ath12k_mac_get_link_bss_conf(arvif);
+ if (!link_conf)
+ return -EINVAL;
+
+ he_support = link_conf->he_support;
+
+ ath12k_dbg(ar->ab, ATH12K_DBG_MAC,
+ "mac set rate params vdev %i rate 0x%02x nss 0x%02x sgi 0x%02x ldpc 0x%02x\n",
+ arvif->vdev_id, rate, nss, sgi, ldpc);
+
+ ath12k_dbg(ar->ab, ATH12K_DBG_MAC,
+ "he_gi 0x%02x he_ltf 0x%02x he_fixed_rate %d\n", he_gi,
+ he_ltf, he_fixed_rate);
+
+ if (!he_support) {
+ vdev_param = WMI_VDEV_PARAM_FIXED_RATE;
+ ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
+ vdev_param, rate);
+ if (ret) {
+ ath12k_warn(ar->ab, "failed to set fixed rate param 0x%02x: %d\n",
+ rate, ret);
+ return ret;
+ }
+ }
+
+ vdev_param = WMI_VDEV_PARAM_NSS;
+
ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
- vdev_param, ldpc);
+ vdev_param, nss);
+ if (ret) {
+ ath12k_warn(ar->ab, "failed to set nss param %d: %d\n",
+ nss, ret);
+ return ret;
+ }
+
+ ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
+ WMI_VDEV_PARAM_LDPC, ldpc);
if (ret) {
ath12k_warn(ar->ab, "failed to set ldpc param %d: %d\n",
ldpc, ret);
return ret;
}
+ if (he_support) {
+ if (he_fixed_rate)
+ ret = ath12k_mac_set_fixed_rate_gi_ltf(arvif, he_gi, he_ltf);
+ else
+ ret = ath12k_mac_set_auto_rate_gi_ltf(arvif, he_gi, he_ltf);
+ if (ret)
+ return ret;
+ } else {
+ vdev_param = WMI_VDEV_PARAM_SGI;
+ param_value = ath12k_mac_nlgi_to_wmigi(sgi);
+ ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
+ vdev_param, param_value);
+ if (ret) {
+ ath12k_warn(ar->ab, "failed to set sgi param %d: %d\n",
+ sgi, ret);
+ return ret;
+ }
+ }
+
return 0;
}
@@ -10366,6 +10793,31 @@ ath12k_mac_vht_mcs_range_present(struct ath12k *ar,
return true;
}
+static bool
+ath12k_mac_he_mcs_range_present(struct ath12k *ar,
+ enum nl80211_band band,
+ const struct cfg80211_bitrate_mask *mask)
+{
+ int i;
+ u16 he_mcs;
+
+ for (i = 0; i < NL80211_HE_NSS_MAX; i++) {
+ he_mcs = mask->control[band].he_mcs[i];
+
+ switch (he_mcs) {
+ case 0:
+ case BIT(8) - 1:
+ case BIT(10) - 1:
+ case BIT(12) - 1:
+ break;
+ default:
+ return false;
+ }
+ }
+
+ return true;
+}
+
static void ath12k_mac_set_bitrate_mask_iter(void *data,
struct ieee80211_sta *sta)
{
@@ -10374,7 +10826,10 @@ static void ath12k_mac_set_bitrate_mask_iter(void *data,
struct ath12k_link_sta *arsta;
struct ath12k *ar = arvif->ar;
- arsta = rcu_dereference(ahsta->link[arvif->link_id]);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
+
+ arsta = wiphy_dereference(ath12k_ar_to_hw(ar)->wiphy,
+ ahsta->link[arvif->link_id]);
if (!arsta || arsta->arvif != arvif)
return;
@@ -10412,6 +10867,61 @@ static void ath12k_mac_disable_peer_fixed_rate(void *data,
arsta->addr, ret);
}
+static bool
+ath12k_mac_validate_fixed_rate_settings(struct ath12k *ar, enum nl80211_band band,
+ const struct cfg80211_bitrate_mask *mask,
+ unsigned int link_id)
+{
+ bool he_fixed_rate = false, vht_fixed_rate = false;
+ const u16 *vht_mcs_mask, *he_mcs_mask;
+ struct ieee80211_link_sta *link_sta;
+ struct ath12k_peer *peer, *tmp;
+ u8 vht_nss, he_nss;
+ int ret = true;
+
+ vht_mcs_mask = mask->control[band].vht_mcs;
+ he_mcs_mask = mask->control[band].he_mcs;
+
+ if (ath12k_mac_bitrate_mask_num_vht_rates(ar, band, mask) == 1)
+ vht_fixed_rate = true;
+
+ if (ath12k_mac_bitrate_mask_num_he_rates(ar, band, mask) == 1)
+ he_fixed_rate = true;
+
+ if (!vht_fixed_rate && !he_fixed_rate)
+ return true;
+
+ vht_nss = ath12k_mac_max_vht_nss(vht_mcs_mask);
+ he_nss = ath12k_mac_max_he_nss(he_mcs_mask);
+
+ rcu_read_lock();
+ spin_lock_bh(&ar->ab->base_lock);
+ list_for_each_entry_safe(peer, tmp, &ar->ab->peers, list) {
+ if (peer->sta) {
+ link_sta = rcu_dereference(peer->sta->link[link_id]);
+ if (!link_sta) {
+ ret = false;
+ goto exit;
+ }
+
+ if (vht_fixed_rate && (!link_sta->vht_cap.vht_supported ||
+ link_sta->rx_nss < vht_nss)) {
+ ret = false;
+ goto exit;
+ }
+ if (he_fixed_rate && (!link_sta->he_cap.has_he ||
+ link_sta->rx_nss < he_nss)) {
+ ret = false;
+ goto exit;
+ }
+ }
+ }
+exit:
+ spin_unlock_bh(&ar->ab->base_lock);
+ rcu_read_unlock();
+ return ret;
+}
+
static int
ath12k_mac_op_set_bitrate_mask(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
@@ -10424,13 +10934,17 @@ ath12k_mac_op_set_bitrate_mask(struct ieee80211_hw *hw,
enum nl80211_band band;
const u8 *ht_mcs_mask;
const u16 *vht_mcs_mask;
+ const u16 *he_mcs_mask;
+ u8 he_ltf = 0;
+ u8 he_gi = 0;
u32 rate;
- u8 nss;
+ u8 nss, mac_nss;
u8 sgi;
u8 ldpc;
int single_nss;
int ret;
int num_rates;
+ bool he_fixed_rate = false;
lockdep_assert_wiphy(hw->wiphy);
@@ -10445,14 +10959,18 @@ ath12k_mac_op_set_bitrate_mask(struct ieee80211_hw *hw,
band = def.chan->band;
ht_mcs_mask = mask->control[band].ht_mcs;
vht_mcs_mask = mask->control[band].vht_mcs;
+ he_mcs_mask = mask->control[band].he_mcs;
ldpc = !!(ar->ht_cap_info & WMI_HT_CAP_LDPC);
sgi = mask->control[band].gi;
- if (sgi == NL80211_TXRATE_FORCE_LGI) {
+ if (sgi == NL80211_TXRATE_FORCE_SGI) {
ret = -EINVAL;
goto out;
}
+ he_gi = mask->control[band].he_gi;
+ he_ltf = mask->control[band].he_ltf;
+
/* mac80211 doesn't support sending a fixed HT/VHT MCS alone, rather it
* requires passing at least one of used basic rates along with them.
* Fixed rate setting across different preambles(legacy, HT, VHT) is
@@ -10469,18 +10987,31 @@ ath12k_mac_op_set_bitrate_mask(struct ieee80211_hw *hw,
arvif->vdev_id, ret);
goto out;
}
+
ieee80211_iterate_stations_mtx(hw,
ath12k_mac_disable_peer_fixed_rate,
arvif);
- } else if (ath12k_mac_bitrate_mask_get_single_nss(ar, band, mask,
+ } else if (ath12k_mac_bitrate_mask_get_single_nss(ar, vif, band, mask,
&single_nss)) {
rate = WMI_FIXED_RATE_NONE;
nss = single_nss;
+ arvif->bitrate_mask = *mask;
+
+ ieee80211_iterate_stations_atomic(hw,
+ ath12k_mac_set_bitrate_mask_iter,
+ arvif);
} else {
rate = WMI_FIXED_RATE_NONE;
- nss = min_t(u32, ar->num_tx_chains,
- max(ath12k_mac_max_ht_nss(ht_mcs_mask),
- ath12k_mac_max_vht_nss(vht_mcs_mask)));
+
+ if (!ath12k_mac_validate_fixed_rate_settings(ar, band,
+ mask, arvif->link_id))
+ ath12k_warn(ar->ab,
+ "failed to update fixed rate settings due to mcs/nss incompatibility\n");
+
+ mac_nss = max3(ath12k_mac_max_ht_nss(ht_mcs_mask),
+ ath12k_mac_max_vht_nss(vht_mcs_mask),
+ ath12k_mac_max_he_nss(he_mcs_mask));
+ nss = min_t(u32, ar->num_tx_chains, mac_nss);
/* If multiple rates across different preambles are given
* we can reconfigure this info with all peers using PEER_ASSOC
@@ -10512,9 +11043,21 @@ ath12k_mac_op_set_bitrate_mask(struct ieee80211_hw *hw,
*/
ath12k_warn(ar->ab,
"Setting more than one MCS Value in bitrate mask not supported\n");
- return -EINVAL;
+ ret = -EINVAL;
+ goto out;
}
+ num_rates = ath12k_mac_bitrate_mask_num_he_rates(ar, band, mask);
+ if (num_rates == 1)
+ he_fixed_rate = true;
+
+ if (!ath12k_mac_he_mcs_range_present(ar, band, mask) &&
+ num_rates > 1) {
+ ath12k_warn(ar->ab,
+ "Setting more than one HE MCS Value in bitrate mask not supported\n");
+ ret = -EINVAL;
+ goto out;
+ }
ieee80211_iterate_stations_mtx(hw,
ath12k_mac_disable_peer_fixed_rate,
arvif);
@@ -10525,9 +11068,10 @@ ath12k_mac_op_set_bitrate_mask(struct ieee80211_hw *hw,
arvif);
}
- ret = ath12k_mac_set_fixed_rate_params(arvif, rate, nss, sgi, ldpc);
+ ret = ath12k_mac_set_rate_params(arvif, rate, nss, sgi, ldpc, he_gi,
+ he_ltf, he_fixed_rate);
if (ret) {
- ath12k_warn(ar->ab, "failed to set fixed rate params on vdev %i: %d\n",
+ ath12k_warn(ar->ab, "failed to set rate params on vdev %i: %d\n",
arvif->vdev_id, ret);
}
diff --git a/drivers/net/wireless/ath/ath12k/wmi.h b/drivers/net/wireless/ath/ath12k/wmi.h
index d4d0aae70011..f63818d9df7e 100644
--- a/drivers/net/wireless/ath/ath12k/wmi.h
+++ b/drivers/net/wireless/ath/ath12k/wmi.h
@@ -221,6 +221,22 @@ enum WMI_HOST_WLAN_BAND {
WMI_HOST_WLAN_2GHZ_5GHZ_CAP = 3,
};
+/* Parameters used for WMI_VDEV_PARAM_AUTORATE_MISC_CFG command.
+ * Used only for HE auto rate mode.
+ */
+enum {
+ /* HE LTF related configuration */
+ WMI_HE_AUTORATE_LTF_1X = BIT(0),
+ WMI_HE_AUTORATE_LTF_2X = BIT(1),
+ WMI_HE_AUTORATE_LTF_4X = BIT(2),
+
+ /* HE GI related configuration */
+ WMI_AUTORATE_400NS_GI = BIT(8),
+ WMI_AUTORATE_800NS_GI = BIT(9),
+ WMI_AUTORATE_1600NS_GI = BIT(10),
+ WMI_AUTORATE_3200NS_GI = BIT(11),
+};
+
enum wmi_cmd_group {
/* 0 to 2 are reserved */
WMI_GRP_START = 0x3,
@@ -1152,7 +1168,9 @@ enum wmi_tlv_vdev_param {
WMI_VDEV_PARAM_HE_RANGE_EXT,
WMI_VDEV_PARAM_ENABLE_BCAST_PROBE_RESPONSE,
WMI_VDEV_PARAM_FILS_MAX_CHANNEL_GUARD_TIME,
+ WMI_VDEV_PARAM_HE_LTF = 0x74,
WMI_VDEV_PARAM_BA_MODE = 0x7e,
+ WMI_VDEV_PARAM_AUTORATE_MISC_CFG = 0x80,
WMI_VDEV_PARAM_SET_HE_SOUNDING_MODE = 0x87,
WMI_VDEV_PARAM_6GHZ_PARAMS = 0x99,
WMI_VDEV_PARAM_PROTOTYPE = 0x8000,
@@ -3596,6 +3614,15 @@ struct wmi_force_fw_hang_cmd {
__le32 delay_time_ms;
} __packed;
+/* Param values to be sent for WMI_VDEV_PARAM_SGI param_id
+ * which are used in 11n, 11ac systems
+ * @WMI_GI_800_NS - Always uses 0.8us (Long GI)
+ * @WMI_GI_400_NS - Firmware switches between 0.4us (Short GI)
+ * and 0.8us (Long GI) based on packet error rate.
+ */
+#define WMI_GI_800_NS 0
+#define WMI_GI_400_NS 1
+
struct wmi_vdev_set_param_cmd {
__le32 tlv_header;
__le32 vdev_id;
--
2.34.1
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH V13 7/9] wifi: ath12k: clean up 80P80 support
2025-04-18 17:48 [PATCH V13 0/9] wifi: ath12k: add MU-MIMO and 160 MHz bandwidth support Pradeep Kumar Chitrapu
` (5 preceding siblings ...)
2025-04-18 17:48 ` [PATCH V13 6/9] wifi: ath12k: add support for setting fixed HE rate/GI/LTF Pradeep Kumar Chitrapu
@ 2025-04-18 17:48 ` Pradeep Kumar Chitrapu
2025-04-18 17:48 ` [PATCH V13 8/9] wifi: ath12k: add support for 160 MHz bandwidth Pradeep Kumar Chitrapu
` (3 subsequent siblings)
10 siblings, 0 replies; 21+ messages in thread
From: Pradeep Kumar Chitrapu @ 2025-04-18 17:48 UTC (permalink / raw)
To: ath12k; +Cc: linux-wireless, Pradeep Kumar Chitrapu, Jeff Johnson
Clean up unused 80P80 references as hardware does not support
it. This is applicable to both QCN9274 and WCN7850.
Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.0.1-00029-QCAHKSWPL_SILICONZ-1
Signed-off-by: Pradeep Kumar Chitrapu <quic_pradeepc@quicinc.com>
Acked-by: Jeff Johnson <quic_jjohnson@quicinc.com>
---
drivers/net/wireless/ath/ath12k/mac.c | 48 ++++++---------------------
drivers/net/wireless/ath/ath12k/wmi.c | 2 --
drivers/net/wireless/ath/ath12k/wmi.h | 1 -
3 files changed, 10 insertions(+), 41 deletions(-)
diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c
index bfad7bd1a1d4..e7c15a3c4c80 100644
--- a/drivers/net/wireless/ath/ath12k/mac.c
+++ b/drivers/net/wireless/ath/ath12k/mac.c
@@ -209,7 +209,7 @@ ath12k_phymodes[NUM_NL80211_BANDS][ATH12K_CHAN_WIDTH_NUM] = {
[NL80211_CHAN_WIDTH_40] = MODE_11BE_EHT40,
[NL80211_CHAN_WIDTH_80] = MODE_11BE_EHT80,
[NL80211_CHAN_WIDTH_160] = MODE_11BE_EHT160,
- [NL80211_CHAN_WIDTH_80P80] = MODE_11BE_EHT80_80,
+ [NL80211_CHAN_WIDTH_80P80] = MODE_UNKNOWN,
[NL80211_CHAN_WIDTH_320] = MODE_11BE_EHT320,
},
[NL80211_BAND_6GHZ] = {
@@ -220,7 +220,7 @@ ath12k_phymodes[NUM_NL80211_BANDS][ATH12K_CHAN_WIDTH_NUM] = {
[NL80211_CHAN_WIDTH_40] = MODE_11BE_EHT40,
[NL80211_CHAN_WIDTH_80] = MODE_11BE_EHT80,
[NL80211_CHAN_WIDTH_160] = MODE_11BE_EHT160,
- [NL80211_CHAN_WIDTH_80P80] = MODE_11BE_EHT80_80,
+ [NL80211_CHAN_WIDTH_80P80] = MODE_UNKNOWN,
[NL80211_CHAN_WIDTH_320] = MODE_11BE_EHT320,
},
@@ -2538,17 +2538,6 @@ static void ath12k_peer_assoc_h_he(struct ath12k *ar,
switch (link_sta->bandwidth) {
case IEEE80211_STA_RX_BW_160:
- if (he_cap->he_cap_elem.phy_cap_info[0] &
- IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G) {
- v = ath12k_peer_assoc_h_he_limit(v, he_mcs_mask);
- arg->peer_he_rx_mcs_set[WMI_HECAP_TXRX_MCS_NSS_IDX_80_80] = v;
-
- v = le16_to_cpu(he_cap->he_mcs_nss_supp.tx_mcs_80p80);
- arg->peer_he_tx_mcs_set[WMI_HECAP_TXRX_MCS_NSS_IDX_80_80] = v;
-
- arg->peer_he_mcs_count++;
- he_tx_mcs = v;
- }
v = le16_to_cpu(he_cap->he_mcs_nss_supp.rx_mcs_160);
arg->peer_he_rx_mcs_set[WMI_HECAP_TXRX_MCS_NSS_IDX_160] = v;
@@ -2833,16 +2822,11 @@ static enum wmi_phy_mode ath12k_mac_get_phymode_vht(struct ath12k *ar,
struct ieee80211_link_sta *link_sta)
{
if (link_sta->bandwidth == IEEE80211_STA_RX_BW_160) {
- switch (link_sta->vht_cap.cap &
- IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK) {
- case IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ:
- return MODE_11AC_VHT160;
- case IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ:
- return MODE_11AC_VHT80_80;
- default:
- /* not sure if this is a valid case? */
+ if (link_sta->vht_cap.cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ)
return MODE_11AC_VHT160;
- }
+
+ /* not sure if this is a valid case? */
+ return MODE_11AC_VHT160;
}
if (link_sta->bandwidth == IEEE80211_STA_RX_BW_80)
@@ -2864,11 +2848,8 @@ static enum wmi_phy_mode ath12k_mac_get_phymode_he(struct ath12k *ar,
if (link_sta->he_cap.he_cap_elem.phy_cap_info[0] &
IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G)
return MODE_11AX_HE160;
- else if (link_sta->he_cap.he_cap_elem.phy_cap_info[0] &
- IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G)
- return MODE_11AX_HE80_80;
- /* not sure if this is a valid case? */
- return MODE_11AX_HE160;
+
+ return MODE_UNKNOWN;
}
if (link_sta->bandwidth == IEEE80211_STA_RX_BW_80)
@@ -2896,14 +2877,10 @@ static enum wmi_phy_mode ath12k_mac_get_phymode_eht(struct ath12k *ar,
IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G)
return MODE_11BE_EHT160;
- if (link_sta->he_cap.he_cap_elem.phy_cap_info[0] &
- IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G)
- return MODE_11BE_EHT80_80;
-
ath12k_warn(ar->ab, "invalid EHT PHY capability info for 160 Mhz: %d\n",
link_sta->he_cap.he_cap_elem.phy_cap_info[0]);
- return MODE_11BE_EHT160;
+ return MODE_UNKNOWN;
}
if (link_sta->bandwidth == IEEE80211_STA_RX_BW_80)
@@ -7236,8 +7213,6 @@ static void ath12k_mac_set_hemcsmap(struct ath12k *ar,
mcs_nss->tx_mcs_80 = cpu_to_le16(txmcs_map & 0xffff);
mcs_nss->rx_mcs_160 = cpu_to_le16(rxmcs_map & 0xffff);
mcs_nss->tx_mcs_160 = cpu_to_le16(txmcs_map & 0xffff);
- mcs_nss->rx_mcs_80p80 = cpu_to_le16(rxmcs_map & 0xffff);
- mcs_nss->tx_mcs_80p80 = cpu_to_le16(txmcs_map & 0xffff);
}
static void ath12k_mac_copy_he_cap(struct ath12k *ar,
@@ -7259,6 +7234,7 @@ static void ath12k_mac_copy_he_cap(struct ath12k *ar,
IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G |
IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G |
IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G;
+ /* 80PLUS80 is not supported */
he_cap_elem->phy_cap_info[0] &=
~IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G;
he_cap_elem->phy_cap_info[5] &=
@@ -10474,10 +10450,6 @@ ath12k_mac_has_single_legacy_rate(struct ath12k *ar,
static __le16
ath12k_mac_get_tx_mcs_map(const struct ieee80211_sta_he_cap *he_cap)
{
- if (he_cap->he_cap_elem.phy_cap_info[0] &
- IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G)
- return he_cap->he_mcs_nss_supp.tx_mcs_80p80;
-
if (he_cap->he_cap_elem.phy_cap_info[0] &
IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G)
return he_cap->he_mcs_nss_supp.tx_mcs_160;
diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c
index 6002d4df536a..a74a1549143b 100644
--- a/drivers/net/wireless/ath/ath12k/wmi.c
+++ b/drivers/net/wireless/ath/ath12k/wmi.c
@@ -1061,8 +1061,6 @@ static void ath12k_wmi_put_wmi_channel(struct ath12k_wmi_channel_params *chan,
chan->band_center_freq1 = cpu_to_le32(center_freq1 - 40);
chan->band_center_freq2 = cpu_to_le32(center_freq1);
- } else if (arg->mode == MODE_11BE_EHT80_80) {
- chan->band_center_freq2 = cpu_to_le32(arg->band_center_freq2);
} else {
chan->band_center_freq2 = 0;
}
diff --git a/drivers/net/wireless/ath/ath12k/wmi.h b/drivers/net/wireless/ath/ath12k/wmi.h
index f63818d9df7e..6747ca60b7fa 100644
--- a/drivers/net/wireless/ath/ath12k/wmi.h
+++ b/drivers/net/wireless/ath/ath12k/wmi.h
@@ -3763,7 +3763,6 @@ struct wmi_vdev_install_key_arg {
#define WMI_HOST_MAX_HE_RATE_SET 3
#define WMI_HECAP_TXRX_MCS_NSS_IDX_80 0
#define WMI_HECAP_TXRX_MCS_NSS_IDX_160 1
-#define WMI_HECAP_TXRX_MCS_NSS_IDX_80_80 2
#define ATH12K_WMI_MLO_MAX_PARTNER_LINKS \
(ATH12K_WMI_MLO_MAX_LINKS + ATH12K_MAX_NUM_BRIDGE_LINKS - 1)
--
2.34.1
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH V13 8/9] wifi: ath12k: add support for 160 MHz bandwidth
2025-04-18 17:48 [PATCH V13 0/9] wifi: ath12k: add MU-MIMO and 160 MHz bandwidth support Pradeep Kumar Chitrapu
` (6 preceding siblings ...)
2025-04-18 17:48 ` [PATCH V13 7/9] wifi: ath12k: clean up 80P80 support Pradeep Kumar Chitrapu
@ 2025-04-18 17:48 ` Pradeep Kumar Chitrapu
2025-05-19 15:11 ` Nicolas Escande
2025-04-18 17:48 ` [PATCH V13 9/9] wifi: ath12k: add extended NSS bandwidth support for 160 MHz Pradeep Kumar Chitrapu
` (2 subsequent siblings)
10 siblings, 1 reply; 21+ messages in thread
From: Pradeep Kumar Chitrapu @ 2025-04-18 17:48 UTC (permalink / raw)
To: ath12k; +Cc: linux-wireless, Pradeep Kumar Chitrapu, P Praneesh, Jeff Johnson
Add support to configure maximum NSS in 160 MHz bandwidth.
Firmware advertises support for handling NSS ratio information
as a part of service ready ext event using nss_ratio_enabled
flag. Save this information in ath12k_pdev_cap to calculate
NSS ratio.
Additionally, reorder the code by moving
ath12k_peer_assoc_h_phymode() before ath12k_peer_assoc_h_vht()
to ensure that arg->peer_phymode correctly reflects the bandwidth
in the max NSS calculation.
Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.0.1-00029-QCAHKSWPL_SILICONZ-1
Co-developed-by: P Praneesh <quic_ppranees@quicinc.com>
Signed-off-by: P Praneesh <quic_ppranees@quicinc.com>
Signed-off-by: Pradeep Kumar Chitrapu <quic_pradeepc@quicinc.com>
Acked-by: Jeff Johnson <quic_jjohnson@quicinc.com>
---
drivers/net/wireless/ath/ath12k/core.h | 2 +
drivers/net/wireless/ath/ath12k/mac.c | 88 ++++++++++++++++++++++----
drivers/net/wireless/ath/ath12k/mac.h | 2 +
drivers/net/wireless/ath/ath12k/wmi.c | 7 +-
drivers/net/wireless/ath/ath12k/wmi.h | 28 ++++++++
5 files changed, 114 insertions(+), 13 deletions(-)
diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h
index 4b8f434e3e9a..d2b79180a534 100644
--- a/drivers/net/wireless/ath/ath12k/core.h
+++ b/drivers/net/wireless/ath/ath12k/core.h
@@ -841,6 +841,8 @@ struct ath12k_pdev_cap {
struct ath12k_band_cap band[NUM_NL80211_BANDS];
u32 eml_cap;
u32 mld_cap;
+ bool nss_ratio_enabled;
+ u8 nss_ratio_info;
};
struct mlo_timestamp {
diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c
index e7c15a3c4c80..ecd47f15ef95 100644
--- a/drivers/net/wireless/ath/ath12k/mac.c
+++ b/drivers/net/wireless/ath/ath12k/mac.c
@@ -2167,6 +2167,34 @@ ath12k_peer_assoc_h_vht_limit(u16 tx_mcs_set,
return tx_mcs_set;
}
+static u8 ath12k_get_nss_160mhz(struct ath12k *ar,
+ u8 max_nss)
+{
+ u8 nss_ratio_info = ar->pdev->cap.nss_ratio_info;
+ u8 max_sup_nss = 0;
+
+ switch (nss_ratio_info) {
+ case WMI_NSS_RATIO_1BY2_NSS:
+ max_sup_nss = max_nss >> 1;
+ break;
+ case WMI_NSS_RATIO_3BY4_NSS:
+ ath12k_warn(ar->ab, "WMI_NSS_RATIO_3BY4_NSS not supported\n");
+ break;
+ case WMI_NSS_RATIO_1_NSS:
+ max_sup_nss = max_nss;
+ break;
+ case WMI_NSS_RATIO_2_NSS:
+ ath12k_warn(ar->ab, "WMI_NSS_RATIO_2_NSS not supported\n");
+ break;
+ default:
+ ath12k_warn(ar->ab, "invalid nss ratio received from fw: %d\n",
+ nss_ratio_info);
+ break;
+ }
+
+ return max_sup_nss;
+}
+
static void ath12k_peer_assoc_h_vht(struct ath12k *ar,
struct ath12k_link_vif *arvif,
struct ath12k_link_sta *arsta,
@@ -2184,6 +2212,7 @@ static void ath12k_peer_assoc_h_vht(struct ath12k *ar,
u8 max_nss, vht_mcs;
int i, vht_nss, nss_idx;
bool user_rate_valid = true;
+ u32 rx_nss, tx_nss, nss_160;
lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
@@ -2288,10 +2317,24 @@ static void ath12k_peer_assoc_h_vht(struct ath12k *ar,
/* TODO: Check */
arg->tx_max_mcs_nss = 0xFF;
- ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac vht peer %pM max_mpdu %d flags 0x%x\n",
- arsta->addr, arg->peer_max_mpdu, arg->peer_flags);
+ if (arg->peer_phymode == MODE_11AC_VHT160) {
+ tx_nss = ath12k_get_nss_160mhz(ar, max_nss);
+ rx_nss = min(arg->peer_nss, tx_nss);
+ arg->peer_bw_rxnss_override = ATH12K_BW_NSS_MAP_ENABLE;
+
+ if (!rx_nss) {
+ ath12k_warn(ar->ab, "invalid max_nss\n");
+ return;
+ }
+
+ nss_160 = u32_encode_bits(rx_nss - 1, ATH12K_PEER_RX_NSS_160MHZ);
+ arg->peer_bw_rxnss_override |= nss_160;
+ }
- /* TODO: rxnss_override */
+ ath12k_dbg(ar->ab, ATH12K_DBG_MAC,
+ "mac vht peer %pM max_mpdu %d flags 0x%x nss_override 0x%x\n",
+ arsta->addr, arg->peer_max_mpdu, arg->peer_flags,
+ arg->peer_bw_rxnss_override);
}
static int ath12k_mac_get_max_he_mcs_map(u16 mcs_map, int nss)
@@ -2384,6 +2427,7 @@ static void ath12k_peer_assoc_h_he(struct ath12k *ar,
u16 he_tx_mcs = 0, v = 0;
int he_nss, nss_idx;
bool user_rate_valid = true;
+ u32 rx_nss, tx_nss, nss_160;
if (WARN_ON(ath12k_mac_vif_link_chan(vif, link_id, &def)))
return;
@@ -2578,10 +2622,27 @@ static void ath12k_peer_assoc_h_he(struct ath12k *ar,
max_nss = i + 1;
}
arg->peer_nss = min(link_sta->rx_nss, max_nss);
+ max_nss = min(max_nss, ar->num_tx_chains);
+
+ if (arg->peer_phymode == MODE_11AX_HE160) {
+ tx_nss = ath12k_get_nss_160mhz(ar, max_nss);
+ rx_nss = min(arg->peer_nss, tx_nss);
+ arg->peer_bw_rxnss_override = ATH12K_BW_NSS_MAP_ENABLE;
+
+ if (!rx_nss) {
+ ath12k_warn(ar->ab, "invalid max_nss\n");
+ return;
+ }
+
+ nss_160 = u32_encode_bits(rx_nss - 1, ATH12K_PEER_RX_NSS_160MHZ);
+ arg->peer_bw_rxnss_override |= nss_160;
+ }
ath12k_dbg(ar->ab, ATH12K_DBG_MAC,
- "mac he peer %pM nss %d mcs cnt %d\n",
- arsta->addr, arg->peer_nss, arg->peer_he_mcs_count);
+ "mac he peer %pM nss %d mcs cnt %d nss_override 0x%x\n",
+ arsta->addr, arg->peer_nss,
+ arg->peer_he_mcs_count,
+ arg->peer_bw_rxnss_override);
}
static void ath12k_peer_assoc_h_he_6ghz(struct ath12k *ar,
@@ -2822,11 +2883,12 @@ static enum wmi_phy_mode ath12k_mac_get_phymode_vht(struct ath12k *ar,
struct ieee80211_link_sta *link_sta)
{
if (link_sta->bandwidth == IEEE80211_STA_RX_BW_160) {
- if (link_sta->vht_cap.cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ)
+ if (link_sta->vht_cap.cap & (IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ |
+ IEEE80211_VHT_CAP_EXT_NSS_BW_MASK))
return MODE_11AC_VHT160;
/* not sure if this is a valid case? */
- return MODE_11AC_VHT160;
+ return MODE_UNKNOWN;
}
if (link_sta->bandwidth == IEEE80211_STA_RX_BW_80)
@@ -6983,10 +7045,8 @@ ath12k_create_vht_cap(struct ath12k *ar, u32 rate_cap_tx_chainmask,
ath12k_set_vht_txbf_cap(ar, &vht_cap.cap);
- /* TODO: Enable back VHT160 mode once association issues are fixed */
- /* Disabling VHT160 and VHT80+80 modes */
- vht_cap.cap &= ~IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK;
- vht_cap.cap &= ~IEEE80211_VHT_CAP_SHORT_GI_160;
+ /* 80P80 is not supported */
+ vht_cap.cap &= ~IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
rxmcs_map = 0;
txmcs_map = 0;
@@ -11808,7 +11868,8 @@ ath12k_mac_setup_radio_iface_comb(struct ath12k *ar,
comb[0].radar_detect_widths = BIT(NL80211_CHAN_WIDTH_20_NOHT) |
BIT(NL80211_CHAN_WIDTH_20) |
BIT(NL80211_CHAN_WIDTH_40) |
- BIT(NL80211_CHAN_WIDTH_80);
+ BIT(NL80211_CHAN_WIDTH_80) |
+ BIT(NL80211_CHAN_WIDTH_160);
}
return 0;
@@ -12184,6 +12245,9 @@ static int ath12k_mac_hw_register(struct ath12k_hw *ah)
ieee80211_hw_set(hw, REPORTS_LOW_ACK);
ieee80211_hw_set(hw, NO_VIRTUAL_MONITOR);
+ if (cap->nss_ratio_enabled)
+ ieee80211_hw_set(hw, SUPPORTS_VHT_EXT_NSS_BW);
+
if ((ht_cap & WMI_HT_CAP_ENABLED) || is_6ghz) {
ieee80211_hw_set(hw, AMPDU_AGGREGATION);
ieee80211_hw_set(hw, TX_AMPDU_SETUP_IN_HW);
diff --git a/drivers/net/wireless/ath/ath12k/mac.h b/drivers/net/wireless/ath/ath12k/mac.h
index 3ddfa00a5a17..e625740e57f3 100644
--- a/drivers/net/wireless/ath/ath12k/mac.h
+++ b/drivers/net/wireless/ath/ath12k/mac.h
@@ -41,6 +41,8 @@ struct ath12k_generic_iter {
#define IEEE80211_DISABLE_VHT_MCS_SUPPORT_0_11 BIT(24)
#define ATH12K_CHAN_WIDTH_NUM 14
+#define ATH12K_BW_NSS_MAP_ENABLE BIT(31)
+#define ATH12K_PEER_RX_NSS_160MHZ GENMASK(2, 0)
#define ATH12K_TX_POWER_MAX_VAL 70
#define ATH12K_TX_POWER_MIN_VAL 0
diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c
index a74a1549143b..ee837a66f6ac 100644
--- a/drivers/net/wireless/ath/ath12k/wmi.c
+++ b/drivers/net/wireless/ath/ath12k/wmi.c
@@ -532,6 +532,10 @@ ath12k_pull_mac_phy_cap_svc_ready_ext(struct ath12k_wmi_pdev *wmi_handle,
pdev_cap->he_mcs = le32_to_cpu(mac_caps->he_supp_mcs_5g);
pdev_cap->tx_chain_mask = le32_to_cpu(mac_caps->tx_chain_mask_5g);
pdev_cap->rx_chain_mask = le32_to_cpu(mac_caps->rx_chain_mask_5g);
+ pdev_cap->nss_ratio_enabled =
+ WMI_NSS_RATIO_EN_DIS_GET(mac_caps->nss_ratio);
+ pdev_cap->nss_ratio_info =
+ WMI_NSS_RATIO_INFO_GET(mac_caps->nss_ratio);
} else {
return -EINVAL;
}
@@ -1054,7 +1058,8 @@ static void ath12k_wmi_put_wmi_channel(struct ath12k_wmi_channel_params *chan,
chan->band_center_freq2 = cpu_to_le32(center_freq1);
- } else if (arg->mode == MODE_11BE_EHT160) {
+ } else if (arg->mode == MODE_11BE_EHT160 ||
+ arg->mode == MODE_11AX_HE160) {
if (arg->freq > center_freq1)
chan->band_center_freq1 = cpu_to_le32(center_freq1 + 40);
else
diff --git a/drivers/net/wireless/ath/ath12k/wmi.h b/drivers/net/wireless/ath/ath12k/wmi.h
index 6747ca60b7fa..e53eb69285d0 100644
--- a/drivers/net/wireless/ath/ath12k/wmi.h
+++ b/drivers/net/wireless/ath/ath12k/wmi.h
@@ -2306,6 +2306,21 @@ enum wmi_direct_buffer_module {
WMI_DIRECT_BUF_MAX
};
+/**
+ * enum wmi_nss_ratio - NSS ratio received from FW during service ready ext event
+ * @WMI_NSS_RATIO_1BY2_NSS: Max nss of 160MHz is equals to half of the max nss of 80MHz
+ * @WMI_NSS_RATIO_3BY4_NSS: Max nss of 160MHz is equals to 3/4 of the max nss of 80MHz
+ * @WMI_NSS_RATIO_1_NSS: Max nss of 160MHz is equals to the max nss of 80MHz
+ * @WMI_NSS_RATIO_2_NSS: Max nss of 160MHz is equals to two times the max nss of 80MHz
+ */
+
+enum wmi_nss_ratio {
+ WMI_NSS_RATIO_1BY2_NSS,
+ WMI_NSS_RATIO_3BY4_NSS,
+ WMI_NSS_RATIO_1_NSS,
+ WMI_NSS_RATIO_2_NSS
+};
+
struct ath12k_wmi_pdev_band_arg {
u32 pdev_id;
u32 start_freq;
@@ -2623,6 +2638,12 @@ struct ath12k_wmi_hw_mode_cap_params {
} __packed;
#define WMI_MAX_HECAP_PHY_SIZE (3)
+#define WMI_NSS_RATIO_EN_DIS_BITPOS BIT(0)
+#define WMI_NSS_RATIO_EN_DIS_GET(_val) \
+ le32_get_bits(_val, WMI_NSS_RATIO_EN_DIS_BITPOS)
+#define WMI_NSS_RATIO_INFO_BITPOS GENMASK(4, 1)
+#define WMI_NSS_RATIO_INFO_GET(_val) \
+ le32_get_bits(_val, WMI_NSS_RATIO_INFO_BITPOS)
/* pdev_id is present in lower 16 bits of pdev_and_hw_link_ids in
* ath12k_wmi_mac_phy_caps_params & ath12k_wmi_caps_ext_params.
@@ -2664,6 +2685,13 @@ struct ath12k_wmi_mac_phy_caps_params {
__le32 he_cap_info_2g_ext;
__le32 he_cap_info_5g_ext;
__le32 he_cap_info_internal;
+ __le32 wireless_modes;
+ __le32 low_2ghz_chan_freq;
+ __le32 high_2ghz_chan_freq;
+ __le32 low_5ghz_chan_freq;
+ __le32 high_5ghz_chan_freq;
+ __le32 nss_ratio;
+
} __packed;
struct ath12k_wmi_hal_reg_caps_ext_params {
--
2.34.1
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH V13 9/9] wifi: ath12k: add extended NSS bandwidth support for 160 MHz
2025-04-18 17:48 [PATCH V13 0/9] wifi: ath12k: add MU-MIMO and 160 MHz bandwidth support Pradeep Kumar Chitrapu
` (7 preceding siblings ...)
2025-04-18 17:48 ` [PATCH V13 8/9] wifi: ath12k: add support for 160 MHz bandwidth Pradeep Kumar Chitrapu
@ 2025-04-18 17:48 ` Pradeep Kumar Chitrapu
2025-04-18 18:48 ` [PATCH V13 0/9] wifi: ath12k: add MU-MIMO and 160 MHz bandwidth support Jeff Johnson
2025-04-28 16:20 ` Vasanthakumar Thiagarajan
10 siblings, 0 replies; 21+ messages in thread
From: Pradeep Kumar Chitrapu @ 2025-04-18 17:48 UTC (permalink / raw)
To: ath12k; +Cc: linux-wireless, Pradeep Kumar Chitrapu, Jeff Johnson
Currently rx and tx MCS map for 160 MHz under HE capabilities
are not updating properly, when 160 MHz is configured with NSS
lesser than max NSS support. Fix this by utilizing
nss_ratio_enabled and nss_ratio_info fields sent by firmware
in service ready event.
However, if firmware advertises EXT NSS BW support in VHT caps
as 1(1x2) and when nss_ratio_info indicates 1:1, reset the EXT
NSS BW Support in VHT caps to 0 which indicates 1x1. This is
to avoid incorrectly choosing 1:2 NSS ratio when using the
default VHT caps advertised by firmware.
Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.0.1-00029-QCAHKSWPL_SILICONZ-1
Signed-off-by: Pradeep Kumar Chitrapu <quic_pradeepc@quicinc.com>
Acked-by: Jeff Johnson <quic_jjohnson@quicinc.com>
---
drivers/net/wireless/ath/ath12k/mac.c | 33 ++++++++++++++++++++++-----
1 file changed, 27 insertions(+), 6 deletions(-)
diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c
index ecd47f15ef95..89b49a26ece5 100644
--- a/drivers/net/wireless/ath/ath12k/mac.c
+++ b/drivers/net/wireless/ath/ath12k/mac.c
@@ -2625,8 +2625,10 @@ static void ath12k_peer_assoc_h_he(struct ath12k *ar,
max_nss = min(max_nss, ar->num_tx_chains);
if (arg->peer_phymode == MODE_11AX_HE160) {
- tx_nss = ath12k_get_nss_160mhz(ar, max_nss);
+ tx_nss = ath12k_get_nss_160mhz(ar, ar->num_tx_chains);
rx_nss = min(arg->peer_nss, tx_nss);
+
+ arg->peer_nss = min(link_sta->rx_nss, ar->num_rx_chains);
arg->peer_bw_rxnss_override = ATH12K_BW_NSS_MAP_ENABLE;
if (!rx_nss) {
@@ -7068,6 +7070,12 @@ ath12k_create_vht_cap(struct ath12k *ar, u32 rate_cap_tx_chainmask,
vht_cap.vht_mcs.rx_mcs_map = cpu_to_le16(rxmcs_map);
vht_cap.vht_mcs.tx_mcs_map = cpu_to_le16(txmcs_map);
+ /* Check if the HW supports 1:1 NSS ratio and reset
+ * EXT NSS BW Support field to 0 to indicate 1:1 ratio
+ */
+ if (ar->pdev->cap.nss_ratio_info == WMI_NSS_RATIO_1_NSS)
+ vht_cap.cap &= ~IEEE80211_VHT_CAP_EXT_NSS_BW_MASK;
+
return vht_cap;
}
@@ -7250,11 +7258,12 @@ static void ath12k_mac_set_hemcsmap(struct ath12k *ar,
struct ieee80211_sta_he_cap *he_cap)
{
struct ieee80211_he_mcs_nss_supp *mcs_nss = &he_cap->he_mcs_nss_supp;
- u16 txmcs_map, rxmcs_map;
+ u8 maxtxnss_160 = ath12k_get_nss_160mhz(ar, ar->num_tx_chains);
+ u8 maxrxnss_160 = ath12k_get_nss_160mhz(ar, ar->num_rx_chains);
+ u16 txmcs_map_160 = 0, rxmcs_map_160 = 0;
+ u16 txmcs_map = 0, rxmcs_map = 0;
u32 i;
- rxmcs_map = 0;
- txmcs_map = 0;
for (i = 0; i < 8; i++) {
if (i < ar->num_tx_chains &&
(ar->cfg_tx_chainmask >> cap->tx_chain_mask_shift) & BIT(i))
@@ -7267,12 +7276,24 @@ static void ath12k_mac_set_hemcsmap(struct ath12k *ar,
rxmcs_map |= IEEE80211_HE_MCS_SUPPORT_0_11 << (i * 2);
else
rxmcs_map |= IEEE80211_HE_MCS_NOT_SUPPORTED << (i * 2);
+
+ if (i < maxtxnss_160 &&
+ (ar->cfg_tx_chainmask >> cap->tx_chain_mask_shift) & BIT(i))
+ txmcs_map_160 |= IEEE80211_HE_MCS_SUPPORT_0_11 << (i * 2);
+ else
+ txmcs_map_160 |= IEEE80211_HE_MCS_NOT_SUPPORTED << (i * 2);
+
+ if (i < maxrxnss_160 &&
+ (ar->cfg_tx_chainmask >> cap->tx_chain_mask_shift) & BIT(i))
+ rxmcs_map_160 |= IEEE80211_HE_MCS_SUPPORT_0_11 << (i * 2);
+ else
+ rxmcs_map_160 |= IEEE80211_HE_MCS_NOT_SUPPORTED << (i * 2);
}
mcs_nss->rx_mcs_80 = cpu_to_le16(rxmcs_map & 0xffff);
mcs_nss->tx_mcs_80 = cpu_to_le16(txmcs_map & 0xffff);
- mcs_nss->rx_mcs_160 = cpu_to_le16(rxmcs_map & 0xffff);
- mcs_nss->tx_mcs_160 = cpu_to_le16(txmcs_map & 0xffff);
+ mcs_nss->rx_mcs_160 = cpu_to_le16(rxmcs_map_160 & 0xffff);
+ mcs_nss->tx_mcs_160 = cpu_to_le16(txmcs_map_160 & 0xffff);
}
static void ath12k_mac_copy_he_cap(struct ath12k *ar,
--
2.34.1
^ permalink raw reply related [flat|nested] 21+ messages in thread
* Re: [PATCH V13 0/9] wifi: ath12k: add MU-MIMO and 160 MHz bandwidth support
2025-04-18 17:48 [PATCH V13 0/9] wifi: ath12k: add MU-MIMO and 160 MHz bandwidth support Pradeep Kumar Chitrapu
` (8 preceding siblings ...)
2025-04-18 17:48 ` [PATCH V13 9/9] wifi: ath12k: add extended NSS bandwidth support for 160 MHz Pradeep Kumar Chitrapu
@ 2025-04-18 18:48 ` Jeff Johnson
2025-04-28 16:20 ` Vasanthakumar Thiagarajan
10 siblings, 0 replies; 21+ messages in thread
From: Jeff Johnson @ 2025-04-18 18:48 UTC (permalink / raw)
To: Pradeep Kumar Chitrapu, ath12k; +Cc: linux-wireless
Reminder: you should be adding a destination branch tag to the subject prefix,
i.e. [PATCH ath-next v13 0/9]
Don't resend for this, but keep this in mind for future patches.
/jeff
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH V13 0/9] wifi: ath12k: add MU-MIMO and 160 MHz bandwidth support
2025-04-18 17:48 [PATCH V13 0/9] wifi: ath12k: add MU-MIMO and 160 MHz bandwidth support Pradeep Kumar Chitrapu
` (9 preceding siblings ...)
2025-04-18 18:48 ` [PATCH V13 0/9] wifi: ath12k: add MU-MIMO and 160 MHz bandwidth support Jeff Johnson
@ 2025-04-28 16:20 ` Vasanthakumar Thiagarajan
10 siblings, 0 replies; 21+ messages in thread
From: Vasanthakumar Thiagarajan @ 2025-04-28 16:20 UTC (permalink / raw)
To: Pradeep Kumar Chitrapu, ath12k; +Cc: linux-wireless
On 4/18/2025 11:18 PM, Pradeep Kumar Chitrapu wrote:
> Add support for
> 1. enabling MU-MIMO in HE and EHT modes from hardware
> 2. setting fixed HE rate/GI/LTF
> 3. 160 MHz bandwidth in HE mode
> 4. extended NSS bandwidth support
>
> Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.0.1-00029-QCAHKSWPL_SILICONZ-1
> Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0.c5-00481-QCAHMTSWPL_V1.0_V2.0_SILICONZ-3
>
> changes in v13:
> - rebase
>
> changes in v12:
> - rebase
>
> changes in v11:
> patch 1/9:
> - fix return values in ath12k_mac_set_he_txbf_conf() and
> ath12k_mac_vif_recalc_sta_he_txbf()
> patch 6/9:
> - fix missing he_mcs initialization in ath12k_mac_init_arvif()
>
> changes in v10:
> patch 6/9:
> - use ath12k_ahsta_to_sta()
> - fix rcu_dereference warning in ath12k_mac_set_bitrate_mask_iter()
> - change return type for ath12k_mac_validate_fixed_rate_settings()
> - improve readability by adhering to nl80211 definitions of GI
> NL80211_TXRATE_DEFAULT_GI. Introduce ath12k_mac_nlgi_to_wmigi()
> for conversion.
> patch 7/9:
> - do not change default MODE_11AC_VHT160 in
> ath12k_mac_get_phymode_vht() as it breaks clients which do not
> set VHT_CAP_SUPP_CHAN_WIDTH_160MHZ.
> patch 8/9:
> - Use IEEE80211_VHT_CAP_EXT_NSS_BW_MASK along with
> IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ for determining VHT160
> phymode.
>
> changes in v9: rebase on top of master branch with mlo changes
> patch 1/9 and 2/9:
> - fetch link_conf using ath12k_mac_get_link_bss_conf()
> instead of arvif->vif->bss_conf before mlo
> patch 6/9
> - fetch mcs/nss values from sta->link[] instead of sta->deflink
> - fix spelling of 'incompatibility'
> patch 8/9
> - replace sta->deflink.addr with arsta->addr in
> ath12k_peer_assoc_h_vht
> patch 9/9
> - replace sta->deflink.rx_nss with link_sta->rx_nss
>
> changes in v8:
> - rebase and resolve KASAN warnings reported by Jeff in v7, in patch 6/9.
>
> Pradeep Kumar Chitrapu (9):
> wifi: ath12k: push HE MU-MIMO params to hardware
> wifi: ath12k: push EHT MU-MIMO params to hardware
> wifi: ath12k: move HE MCS mapper to a separate function
> wifi: ath12k: generate rx and tx mcs maps for supported HE mcs
> wifi: ath12k: fix TX and RX MCS rate configurations in HE mode
> wifi: ath12k: add support for setting fixed HE rate/GI/LTF
> wifi: ath12k: clean up 80P80 support
> wifi: ath12k: add support for 160 MHz bandwidth
> wifi: ath12k: add extended NSS bandwidth support for 160 MHz
>
> drivers/net/wireless/ath/ath12k/core.h | 2 +
> drivers/net/wireless/ath/ath12k/mac.c | 1141 ++++++++++++++++++++----
> drivers/net/wireless/ath/ath12k/mac.h | 17 +
> drivers/net/wireless/ath/ath12k/wmi.c | 13 +-
> drivers/net/wireless/ath/ath12k/wmi.h | 107 ++-
> 5 files changed, 1058 insertions(+), 222 deletions(-)
Reviewed-by: Vasanthakumar Thiagarajan <vasanthakumar.thiagarajan@oss.qualcomm.com>
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH V13 6/9] wifi: ath12k: add support for setting fixed HE rate/GI/LTF
2025-04-18 17:48 ` [PATCH V13 6/9] wifi: ath12k: add support for setting fixed HE rate/GI/LTF Pradeep Kumar Chitrapu
@ 2025-05-14 14:54 ` Jeff Johnson
2025-05-21 21:39 ` Pradeep Kumar Chitrapu
0 siblings, 1 reply; 21+ messages in thread
From: Jeff Johnson @ 2025-05-14 14:54 UTC (permalink / raw)
To: Pradeep Kumar Chitrapu, ath12k; +Cc: linux-wireless, Muna Sinada
On 4/18/2025 10:48 AM, Pradeep Kumar Chitrapu wrote:
> Add support to set fixed HE rate/GI/LTF values using nl80211.
> Reuse parts of the existing code path already used for HT/VHT
> to implement the new helpers symmetrically, similar to how
> HT/VHT is handled.
>
> Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.0.1-00029-QCAHKSWPL_SILICONZ-1
>
> Co-developed-by: Muna Sinada <quic_msinada@quicinc.com>
> Signed-off-by: Muna Sinada <quic_msinada@quicinc.com>
> Signed-off-by: Pradeep Kumar Chitrapu <quic_pradeepc@quicinc.com>
Internal testing revealed interop issues with this patch, so this series is
being dropped for now.
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH V13 8/9] wifi: ath12k: add support for 160 MHz bandwidth
2025-04-18 17:48 ` [PATCH V13 8/9] wifi: ath12k: add support for 160 MHz bandwidth Pradeep Kumar Chitrapu
@ 2025-05-19 15:11 ` Nicolas Escande
2025-05-21 21:38 ` Pradeep Kumar Chitrapu
0 siblings, 1 reply; 21+ messages in thread
From: Nicolas Escande @ 2025-05-19 15:11 UTC (permalink / raw)
To: Pradeep Kumar Chitrapu, ath12k; +Cc: linux-wireless, P Praneesh, Jeff Johnson
On Fri Apr 18, 2025 at 7:48 PM CEST, Pradeep Kumar Chitrapu wrote:
> Add support to configure maximum NSS in 160 MHz bandwidth.
> Firmware advertises support for handling NSS ratio information
> as a part of service ready ext event using nss_ratio_enabled
> flag. Save this information in ath12k_pdev_cap to calculate
> NSS ratio.
>
> Additionally, reorder the code by moving
> ath12k_peer_assoc_h_phymode() before ath12k_peer_assoc_h_vht()
> to ensure that arg->peer_phymode correctly reflects the bandwidth
> in the max NSS calculation.
>
> Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.0.1-00029-QCAHKSWPL_SILICONZ-1
>
> Co-developed-by: P Praneesh <quic_ppranees@quicinc.com>
> Signed-off-by: P Praneesh <quic_ppranees@quicinc.com>
> Signed-off-by: Pradeep Kumar Chitrapu <quic_pradeepc@quicinc.com>
> Acked-by: Jeff Johnson <quic_jjohnson@quicinc.com>
[...]
Hello,
With this patch set we sometimes see the following warning shortly followed by a
firmware crash on QCN9274 running WLAN.WBE.1.3.1-00218-QCAHKSWPL_SILICONZ-1
[ 242.416516] ------------[ cut here ]------------
[ 242.423608] WARNING: CPU: 2 PID: 1427 at drivers/net/wireless/ath/ath12k/mac.c:3224 ath12k_peer_assoc_h_phymode+0xd4/0x800 [ath12k]
[ 242.428475] Modules linked in: dvb_usb_af9035 dvb_usb_dib0700 dib0070 dib7000m dibx000_common at24 ath12k qmi_helpers nf_nat_sip nf_conntrack_sip dwc3_qcom nf_nat_pptp nf_conntrack_pptp ipq_lpass
[ 242.444176] CPU: 2 UID: 0 PID: 1427 Comm: memcheck-arm64- Not tainted 6.13.0-02013-gd424b7b9a373-dirty #140
[ 242.466407] Hardware name: XXX (DT)
[ 242.476124] pstate: 60000005 (nZCv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--)
[ 242.480639] pc : ath12k_peer_assoc_h_phymode+0xd4/0x800 [ath12k]
[ 242.487584] lr : ath12k_peer_assoc_h_phymode+0x540/0x800 [ath12k]
[ 242.493834] sp : ffffffc08588b4b0
[ 242.499820] x29: ffffffc08588b4b0 x28: 0000000000000008 x27: ffffff802781bb60
[ 242.503123] x26: ffffff802cfa9af0 x25: ffffff802781bb60 x24: ffffff8016f38be0
[ 242.510241] x23: ffffff802cfa9fb0 x22: ffffff802781bce0 x21: ffffff802d50dc00
[ 242.517360] x20: ffffff8016f38be0 x19: ffffff802781bce0 x18: ffffffffffffffff
[ 242.524477] x17: 30363120726f6620 x16: 6f666e6920797469 x15: 6c69626170616320
[ 242.531595] x14: 5948502054485620 x13: 0000000000000001 x12: 0000000000000060
[ 242.538714] x11: ffffffc08126c6b0 x10: 0000000000000274 x9 : ffffffc08010468c
[ 242.545832] x8 : 00000000ffffdfff x7 : 00000000ffffe000 x6 : 0000000000000001
[ 242.552949] x5 : 0000000000000000 x4 : 0000000000000000 x3 : 0000000000000000
[ 242.560067] x2 : ffffff80bff6de70 x1 : ffffff80bff640c8 x0 : 0000000000000021
[ 242.567186] Call trace:
[ 242.574299] ath12k_peer_assoc_h_phymode+0xd4/0x800 [ath12k] (P)
[ 242.576560] ath12k_peer_assoc_prepare+0x5d4/0x1608 [ath12k]
[ 242.582809] ath12k_mac_op_sta_state+0x1f4/0x1100 [ath12k]
[ 242.588451] drv_sta_state+0xa0/0x5e0
[ 242.593745] _sta_info_move_state+0x20c/0x4b8
[ 242.597477] sta_info_move_state+0x18/0x28
[ 242.601817] sta_apply_auth_flags.isra.0+0x190/0x1c0
[ 242.605812] sta_apply_parameters+0x240/0x5e0
[ 242.610933] ieee80211_change_station+0x164/0x200
[ 242.615187] nl80211_set_station+0x3bc/0x520
[ 242.619874] genl_family_rcv_msg_doit+0xbc/0x128
[ 242.624215] genl_rcv_msg+0x1c0/0x260
[ 242.628815] netlink_rcv_skb+0x40/0x100
[ 242.632373] genl_rcv+0x3c/0x60
[ 242.636018] netlink_unicast+0x2d8/0x338
[ 242.639144] netlink_sendmsg+0x158/0x398
[ 242.643311] ____sys_sendmsg+0x104/0x290
[ 242.647217] ___sys_sendmsg+0x70/0xa0
[ 242.651123] __sys_sendmsg+0x64/0xb0
[ 242.654682] __arm64_sys_sendmsg+0x28/0x38
[ 242.658329] do_el0_svc+0x70/0x100
[ 242.662234] el0_svc+0x18/0x60
[ 242.665619] el0t_64_sync_handler+0x104/0x130
[ 242.668659] el0t_64_sync+0x154/0x158
[ 242.673086] ---[ end trace 0000000000000000 ]---
It's probably there since v1 of thies series but I just finally got to the
bottom of this now and I've tracked it down to the following hunk:
> @@ -2822,11 +2883,12 @@ static enum wmi_phy_mode ath12k_mac_get_phymode_vht(struct ath12k *ar,
> struct ieee80211_link_sta *link_sta)
> {
> if (link_sta->bandwidth == IEEE80211_STA_RX_BW_160) {
> - if (link_sta->vht_cap.cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ)
> + if (link_sta->vht_cap.cap & (IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ |
> + IEEE80211_VHT_CAP_EXT_NSS_BW_MASK))
> return MODE_11AC_VHT160;
>
> /* not sure if this is a valid case? */
> - return MODE_11AC_VHT160;
> + return MODE_UNKNOWN;
> }
>
> if (link_sta->bandwidth == IEEE80211_STA_RX_BW_80)
Which led me to understand that a sta that supports both VHT 160 and 80+80 ie
IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ will end up with a phy mode
MODE_UNKNOWN send to the firmware. Which I guess is the reason of the crash.
I understand that VHT 80+80 is not supported by this chipset, but shouldn't we
just allow the sta to connect using VHT 160 right ? Something like this maybe ?
diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c
index 048d62a48c88..d3a87af076e7 100644
--- a/drivers/net/wireless/ath/ath12k/mac.c
+++ b/drivers/net/wireless/ath/ath12k/mac.c
@@ -3041,7 +3041,7 @@ static enum wmi_phy_mode ath12k_mac_get_phymode_vht(struct ath12k *ar,
struct ieee80211_link_sta *link_sta)
{
if (link_sta->bandwidth == IEEE80211_STA_RX_BW_160) {
- if (link_sta->vht_cap.cap & (IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ |
+ if (link_sta->vht_cap.cap & (IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK |
IEEE80211_VHT_CAP_EXT_NSS_BW_MASK))
return MODE_11AC_VHT160;
^ permalink raw reply related [flat|nested] 21+ messages in thread
* Re: [PATCH V13 8/9] wifi: ath12k: add support for 160 MHz bandwidth
2025-05-19 15:11 ` Nicolas Escande
@ 2025-05-21 21:38 ` Pradeep Kumar Chitrapu
2025-05-22 8:34 ` Nicolas Escande
0 siblings, 1 reply; 21+ messages in thread
From: Pradeep Kumar Chitrapu @ 2025-05-21 21:38 UTC (permalink / raw)
To: Nicolas Escande, ath12k; +Cc: linux-wireless, P Praneesh, Jeff Johnson
On 5/19/2025 8:11 AM, Nicolas Escande wrote:
> On Fri Apr 18, 2025 at 7:48 PM CEST, Pradeep Kumar Chitrapu wrote:
>> Add support to configure maximum NSS in 160 MHz bandwidth.
>> Firmware advertises support for handling NSS ratio information
>> as a part of service ready ext event using nss_ratio_enabled
>> flag. Save this information in ath12k_pdev_cap to calculate
>> NSS ratio.
>>
>> Additionally, reorder the code by moving
>> ath12k_peer_assoc_h_phymode() before ath12k_peer_assoc_h_vht()
>> to ensure that arg->peer_phymode correctly reflects the bandwidth
>> in the max NSS calculation.
>>
>> Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.0.1-00029-QCAHKSWPL_SILICONZ-1
>>
>> Co-developed-by: P Praneesh <quic_ppranees@quicinc.com>
>> Signed-off-by: P Praneesh <quic_ppranees@quicinc.com>
>> Signed-off-by: Pradeep Kumar Chitrapu <quic_pradeepc@quicinc.com>
>> Acked-by: Jeff Johnson <quic_jjohnson@quicinc.com>
> [...]
>
> Hello,
>
> With this patch set we sometimes see the following warning shortly followed by a
> firmware crash on QCN9274 running WLAN.WBE.1.3.1-00218-QCAHKSWPL_SILICONZ-1
>
> [ 242.416516] ------------[ cut here ]------------
> [ 242.423608] WARNING: CPU: 2 PID: 1427 at drivers/net/wireless/ath/ath12k/mac.c:3224 ath12k_peer_assoc_h_phymode+0xd4/0x800 [ath12k]
> [ 242.428475] Modules linked in: dvb_usb_af9035 dvb_usb_dib0700 dib0070 dib7000m dibx000_common at24 ath12k qmi_helpers nf_nat_sip nf_conntrack_sip dwc3_qcom nf_nat_pptp nf_conntrack_pptp ipq_lpass
> [ 242.444176] CPU: 2 UID: 0 PID: 1427 Comm: memcheck-arm64- Not tainted 6.13.0-02013-gd424b7b9a373-dirty #140
> [ 242.466407] Hardware name: XXX (DT)
> [ 242.476124] pstate: 60000005 (nZCv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--)
> [ 242.480639] pc : ath12k_peer_assoc_h_phymode+0xd4/0x800 [ath12k]
> [ 242.487584] lr : ath12k_peer_assoc_h_phymode+0x540/0x800 [ath12k]
> [ 242.493834] sp : ffffffc08588b4b0
> [ 242.499820] x29: ffffffc08588b4b0 x28: 0000000000000008 x27: ffffff802781bb60
> [ 242.503123] x26: ffffff802cfa9af0 x25: ffffff802781bb60 x24: ffffff8016f38be0
> [ 242.510241] x23: ffffff802cfa9fb0 x22: ffffff802781bce0 x21: ffffff802d50dc00
> [ 242.517360] x20: ffffff8016f38be0 x19: ffffff802781bce0 x18: ffffffffffffffff
> [ 242.524477] x17: 30363120726f6620 x16: 6f666e6920797469 x15: 6c69626170616320
> [ 242.531595] x14: 5948502054485620 x13: 0000000000000001 x12: 0000000000000060
> [ 242.538714] x11: ffffffc08126c6b0 x10: 0000000000000274 x9 : ffffffc08010468c
> [ 242.545832] x8 : 00000000ffffdfff x7 : 00000000ffffe000 x6 : 0000000000000001
> [ 242.552949] x5 : 0000000000000000 x4 : 0000000000000000 x3 : 0000000000000000
> [ 242.560067] x2 : ffffff80bff6de70 x1 : ffffff80bff640c8 x0 : 0000000000000021
> [ 242.567186] Call trace:
> [ 242.574299] ath12k_peer_assoc_h_phymode+0xd4/0x800 [ath12k] (P)
> [ 242.576560] ath12k_peer_assoc_prepare+0x5d4/0x1608 [ath12k]
> [ 242.582809] ath12k_mac_op_sta_state+0x1f4/0x1100 [ath12k]
> [ 242.588451] drv_sta_state+0xa0/0x5e0
> [ 242.593745] _sta_info_move_state+0x20c/0x4b8
> [ 242.597477] sta_info_move_state+0x18/0x28
> [ 242.601817] sta_apply_auth_flags.isra.0+0x190/0x1c0
> [ 242.605812] sta_apply_parameters+0x240/0x5e0
> [ 242.610933] ieee80211_change_station+0x164/0x200
> [ 242.615187] nl80211_set_station+0x3bc/0x520
> [ 242.619874] genl_family_rcv_msg_doit+0xbc/0x128
> [ 242.624215] genl_rcv_msg+0x1c0/0x260
> [ 242.628815] netlink_rcv_skb+0x40/0x100
> [ 242.632373] genl_rcv+0x3c/0x60
> [ 242.636018] netlink_unicast+0x2d8/0x338
> [ 242.639144] netlink_sendmsg+0x158/0x398
> [ 242.643311] ____sys_sendmsg+0x104/0x290
> [ 242.647217] ___sys_sendmsg+0x70/0xa0
> [ 242.651123] __sys_sendmsg+0x64/0xb0
> [ 242.654682] __arm64_sys_sendmsg+0x28/0x38
> [ 242.658329] do_el0_svc+0x70/0x100
> [ 242.662234] el0_svc+0x18/0x60
> [ 242.665619] el0t_64_sync_handler+0x104/0x130
> [ 242.668659] el0t_64_sync+0x154/0x158
> [ 242.673086] ---[ end trace 0000000000000000 ]---
>
> It's probably there since v1 of thies series but I just finally got to the
> bottom of this now and I've tracked it down to the following hunk:
>
>> @@ -2822,11 +2883,12 @@ static enum wmi_phy_mode ath12k_mac_get_phymode_vht(struct ath12k *ar,
>> struct ieee80211_link_sta *link_sta)
>> {
>> if (link_sta->bandwidth == IEEE80211_STA_RX_BW_160) {
>> - if (link_sta->vht_cap.cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ)
>> + if (link_sta->vht_cap.cap & (IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ |
>> + IEEE80211_VHT_CAP_EXT_NSS_BW_MASK))
>> return MODE_11AC_VHT160;
>>
>> /* not sure if this is a valid case? */
>> - return MODE_11AC_VHT160;
>> + return MODE_UNKNOWN;
>> }
>>
>> if (link_sta->bandwidth == IEEE80211_STA_RX_BW_80)
>
> Which led me to understand that a sta that supports both VHT 160 and 80+80 ie
> IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ will end up with a phy mode
> MODE_UNKNOWN send to the firmware. Which I guess is the reason of the crash.
>
> I understand that VHT 80+80 is not supported by this chipset, but shouldn't we
> just allow the sta to connect using VHT 160 right ? Something like this maybe ?
>
> diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c
> index 048d62a48c88..d3a87af076e7 100644
> --- a/drivers/net/wireless/ath/ath12k/mac.c
> +++ b/drivers/net/wireless/ath/ath12k/mac.c
> @@ -3041,7 +3041,7 @@ static enum wmi_phy_mode ath12k_mac_get_phymode_vht(struct ath12k *ar,
> struct ieee80211_link_sta *link_sta)
> {
> if (link_sta->bandwidth == IEEE80211_STA_RX_BW_160) {
> - if (link_sta->vht_cap.cap & (IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ |
> + if (link_sta->vht_cap.cap & (IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK |
> IEEE80211_VHT_CAP_EXT_NSS_BW_MASK))
> return MODE_11AC_VHT160;
Thanks Nicolas,
I believe IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ mean only
80PLUS80 not both 160 and 80PLUS80 and STA must set
IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ flags for indicating 160 MHz
support. Please correct me if my understanding is correct. However I
agree that we must allow STA to connect irrespective of which flag STA
sets as long as bandwidth is 160MHz. I see ath10k and ath11k also allows
this by setting default phymode of MODE_11AC_VHT160 for BW
==IEEE80211_STA_RX_BW_160 case.
I will make this change in next revision.
Thanks
Pradeep
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH V13 6/9] wifi: ath12k: add support for setting fixed HE rate/GI/LTF
2025-05-14 14:54 ` Jeff Johnson
@ 2025-05-21 21:39 ` Pradeep Kumar Chitrapu
0 siblings, 0 replies; 21+ messages in thread
From: Pradeep Kumar Chitrapu @ 2025-05-21 21:39 UTC (permalink / raw)
To: Jeff Johnson, ath12k; +Cc: linux-wireless, Muna Sinada
On 5/14/2025 7:54 AM, Jeff Johnson wrote:
> On 4/18/2025 10:48 AM, Pradeep Kumar Chitrapu wrote:
>> Add support to set fixed HE rate/GI/LTF values using nl80211.
>> Reuse parts of the existing code path already used for HT/VHT
>> to implement the new helpers symmetrically, similar to how
>> HT/VHT is handled.
>>
>> Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.0.1-00029-QCAHKSWPL_SILICONZ-1
>>
>> Co-developed-by: Muna Sinada <quic_msinada@quicinc.com>
>> Signed-off-by: Muna Sinada <quic_msinada@quicinc.com>
>> Signed-off-by: Pradeep Kumar Chitrapu <quic_pradeepc@quicinc.com>
>
> Internal testing revealed interop issues with this patch, so this series is
> being dropped for now.
Thanks Jeff. Will address it in next revision
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH V13 8/9] wifi: ath12k: add support for 160 MHz bandwidth
2025-05-21 21:38 ` Pradeep Kumar Chitrapu
@ 2025-05-22 8:34 ` Nicolas Escande
2025-05-28 18:16 ` Pradeep Kumar Chitrapu
0 siblings, 1 reply; 21+ messages in thread
From: Nicolas Escande @ 2025-05-22 8:34 UTC (permalink / raw)
To: Pradeep Kumar Chitrapu, ath12k; +Cc: linux-wireless, P Praneesh, Jeff Johnson
On Wed May 21, 2025 at 11:38 PM CEST, Pradeep Kumar Chitrapu wrote:
[...]
> Thanks Nicolas,
>
> I believe IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ mean only
> 80PLUS80 not both 160 and 80PLUS80 and STA must set
> IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ flags for indicating 160 MHz
> support. Please correct me if my understanding is correct. However I
> agree that we must allow STA to connect irrespective of which flag STA
> sets as long as bandwidth is 160MHz. I see ath10k and ath11k also allows
> this by setting default phymode of MODE_11AC_VHT160 for BW
> ==IEEE80211_STA_RX_BW_160 case.
> I will make this change in next revision.
> Thanks
> Pradeep
Hello Pradeep,
Well this is quite unclear for me maybe Johannes or someone more aware of the
evolutions of the standard could shime in.
From what I've gathered:
- the naming IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ implies both
which points it was the case when added
- and the original 802.11ac-2013 Table 8-183v states:
Set to 0 if the STA does not support either 160 or 80+80 MHz.
Set to 1 if the STA supports 160 MHz.
Set to 2 if the STA supports 160 MHz and 80+80 MHz.
The value 3 is reserved.
Things get complicated after:
- later versions like 802.11-2020 have deprecated value 2 in favor of the new
Extendeed NSS BW feature
- Table 9-272 still implies both 160 & 80+80
- Table 11-23 & Table 11-24 implies only 80+80 but both talk about the
'VHT Operation' Channel Width field and not the 'VHT Capabilities' Supported
Channel Width. And thoses had different values even in the first AC amendment
So it feels like when no Extended NSS BW Support is used (first gen AC devices),
IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ really means both 160 & 80+80
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH V13 8/9] wifi: ath12k: add support for 160 MHz bandwidth
2025-05-22 8:34 ` Nicolas Escande
@ 2025-05-28 18:16 ` Pradeep Kumar Chitrapu
2025-06-02 9:05 ` Nicolas Escande
0 siblings, 1 reply; 21+ messages in thread
From: Pradeep Kumar Chitrapu @ 2025-05-28 18:16 UTC (permalink / raw)
To: Nicolas Escande, ath12k; +Cc: linux-wireless, P Praneesh, Jeff Johnson
On 5/22/2025 1:34 AM, Nicolas Escande wrote:
> On Wed May 21, 2025 at 11:38 PM CEST, Pradeep Kumar Chitrapu wrote:
> [...]
>> Thanks Nicolas,
>>
>> I believe IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ mean only
>> 80PLUS80 not both 160 and 80PLUS80 and STA must set
>> IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ flags for indicating 160 MHz
>> support. Please correct me if my understanding is correct. However I
>> agree that we must allow STA to connect irrespective of which flag STA
>> sets as long as bandwidth is 160MHz. I see ath10k and ath11k also allows
>> this by setting default phymode of MODE_11AC_VHT160 for BW
>> ==IEEE80211_STA_RX_BW_160 case.
>> I will make this change in next revision.
>> Thanks
>> Pradeep
>
> Hello Pradeep,
>
> Well this is quite unclear for me maybe Johannes or someone more aware of the
> evolutions of the standard could shime in.
>
> From what I've gathered:
> - the naming IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ implies both
> which points it was the case when added
> - and the original 802.11ac-2013 Table 8-183v states:
> Set to 0 if the STA does not support either 160 or 80+80 MHz.
> Set to 1 if the STA supports 160 MHz.
> Set to 2 if the STA supports 160 MHz and 80+80 MHz.
> The value 3 is reserved.
>
> Things get complicated after:
> - later versions like 802.11-2020 have deprecated value 2 in favor of the new
> Extendeed NSS BW feature
> - Table 9-272 still implies both 160 & 80+80
> - Table 11-23 & Table 11-24 implies only 80+80 but both talk about the
> 'VHT Operation' Channel Width field and not the 'VHT Capabilities' Supported
> Channel Width. And thoses had different values even in the first AC amendment
>
> So it feels like when no Extended NSS BW Support is used (first gen AC devices),
> IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ really means both 160 & 80+80
Thanks Nicolas for detailed response.
Request you to kindly review V14 series and let me know if it works?
Thanks
Pradeep
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH V13 4/9] wifi: ath12k: generate rx and tx mcs maps for supported HE mcs
2025-04-18 17:48 ` [PATCH V13 4/9] wifi: ath12k: generate rx and tx mcs maps for supported HE mcs Pradeep Kumar Chitrapu
@ 2025-05-29 6:59 ` Uraj Sasan
2025-05-30 23:01 ` Pradeep Kumar Chitrapu
0 siblings, 1 reply; 21+ messages in thread
From: Uraj Sasan @ 2025-05-29 6:59 UTC (permalink / raw)
To: Pradeep Kumar Chitrapu, ath12k; +Cc: linux-wireless, Muna Sinada, Jeff Johnson
On 4/18/2025 11:18 PM, Pradeep Kumar Chitrapu wrote:
> Generate rx and tx mcs maps in ath12k_mac_set_hemcsmap() based
> on number of supported tx/rx chains and set them in supported
> mcs/nss for HE capabilities.
>
> Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.0.1-00029-QCAHKSWPL_SILICONZ-1
>
> Co-developed-by: Muna Sinada <quic_msinada@quicinc.com>
> Signed-off-by: Muna Sinada <quic_msinada@quicinc.com>
> Signed-off-by: Pradeep Kumar Chitrapu <quic_pradeepc@quicinc.com>
> Acked-by: Jeff Johnson <quic_jjohnson@quicinc.com>
> ---
> drivers/net/wireless/ath/ath12k/mac.c | 40 ++++++++++++++++++++-------
> 1 file changed, 30 insertions(+), 10 deletions(-)
>
> diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c
> index 30c7d5770ef6..178c89029922 100644
> --- a/drivers/net/wireless/ath/ath12k/mac.c
> +++ b/drivers/net/wireless/ath/ath12k/mac.c
> @@ -6947,20 +6947,40 @@ static __le16 ath12k_mac_setup_he_6ghz_cap(struct ath12k_pdev_cap *pcap,
> return cpu_to_le16(bcap->he_6ghz_capa);
> }
>
> -static void ath12k_mac_set_hemcsmap(struct ath12k_band_cap *band_cap,
> +static void ath12k_mac_set_hemcsmap(struct ath12k *ar,
> + struct ath12k_pdev_cap *cap,
> struct ieee80211_sta_he_cap *he_cap)
> {
> struct ieee80211_he_mcs_nss_supp *mcs_nss = &he_cap->he_mcs_nss_supp;
> + u16 txmcs_map, rxmcs_map;
> + u32 i;
> +
> + rxmcs_map = 0;
> + txmcs_map = 0;
> + for (i = 0; i < 8; i++) {
> + if (i < ar->num_tx_chains &&
> + (ar->cfg_tx_chainmask >> cap->tx_chain_mask_shift) & BIT(i))
> + txmcs_map |= IEEE80211_HE_MCS_SUPPORT_0_11 << (i * 2);
> + else
> + txmcs_map |= IEEE80211_HE_MCS_NOT_SUPPORTED << (i * 2);
> +
> + if (i < ar->num_rx_chains &&
> + (ar->cfg_rx_chainmask >> cap->tx_chain_mask_shift) & BIT(i))
I could see the changes are already in external review but wanted to post it internally,
Shouldn't this be cap->rx_chain_mask_shift ?
*"i < ar->num_tx_chains and i < ar->num_rx_chains "*, this is issue since the value of ar->num_tx_chains is not the max supported by the hw always,
but it gets updated later also via iw phy set antenna command and if user provides any value from 0-15 we will have
issue. E.g if the value are non continues 1's eg 4 , 5, 6 it will fail and set the VHT/HT/EHT caps to disabled state,
and only 1,3,7,15 would work correctly.
> + rxmcs_map |= IEEE80211_HE_MCS_SUPPORT_0_11 << (i * 2);
> + else
> + rxmcs_map |= IEEE80211_HE_MCS_NOT_SUPPORTED << (i * 2);
> + }
>
> - mcs_nss->rx_mcs_80 = cpu_to_le16(band_cap->he_mcs & 0xffff);
> - mcs_nss->tx_mcs_80 = cpu_to_le16(band_cap->he_mcs & 0xffff);
> - mcs_nss->rx_mcs_160 = cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff);
> - mcs_nss->tx_mcs_160 = cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff);
> - mcs_nss->rx_mcs_80p80 = cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff);
> - mcs_nss->tx_mcs_80p80 = cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff);
> + mcs_nss->rx_mcs_80 = cpu_to_le16(rxmcs_map & 0xffff);
> + mcs_nss->tx_mcs_80 = cpu_to_le16(txmcs_map & 0xffff);
> + mcs_nss->rx_mcs_160 = cpu_to_le16(rxmcs_map & 0xffff);
> + mcs_nss->tx_mcs_160 = cpu_to_le16(txmcs_map & 0xffff);
> + mcs_nss->rx_mcs_80p80 = cpu_to_le16(rxmcs_map & 0xffff);
> + mcs_nss->tx_mcs_80p80 = cpu_to_le16(txmcs_map & 0xffff);
> }
>
> -static void ath12k_mac_copy_he_cap(struct ath12k_band_cap *band_cap,
> +static void ath12k_mac_copy_he_cap(struct ath12k *ar,
> + struct ath12k_band_cap *band_cap,
> int iftype, u8 num_tx_chains,
> struct ieee80211_sta_he_cap *he_cap)
> {
> @@ -7004,7 +7024,7 @@ static void ath12k_mac_copy_he_cap(struct ath12k_band_cap *band_cap,
> break;
> }
>
> - ath12k_mac_set_hemcsmap(band_cap, he_cap);
> + ath12k_mac_set_hemcsmap(ar, &ar->pdev->cap, he_cap);
> memset(he_cap->ppe_thres, 0, sizeof(he_cap->ppe_thres));
> if (he_cap_elem->phy_cap_info[6] &
> IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT)
> @@ -7194,7 +7214,7 @@ static int ath12k_mac_copy_sband_iftype_data(struct ath12k *ar,
>
> data[idx].types_mask = BIT(i);
>
> - ath12k_mac_copy_he_cap(band_cap, i, ar->num_tx_chains, he_cap);
> + ath12k_mac_copy_he_cap(ar, band_cap, i, ar->num_tx_chains, he_cap);
> if (band == NL80211_BAND_6GHZ) {
> data[idx].he_6ghz_capa.capa =
> ath12k_mac_setup_he_6ghz_cap(cap, band_cap);
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH V13 4/9] wifi: ath12k: generate rx and tx mcs maps for supported HE mcs
2025-05-29 6:59 ` Uraj Sasan
@ 2025-05-30 23:01 ` Pradeep Kumar Chitrapu
0 siblings, 0 replies; 21+ messages in thread
From: Pradeep Kumar Chitrapu @ 2025-05-30 23:01 UTC (permalink / raw)
To: Uraj Sasan, ath12k; +Cc: linux-wireless, Muna Sinada, Jeff Johnson
On 5/28/2025 11:59 PM, Uraj Sasan wrote:
>
> On 4/18/2025 11:18 PM, Pradeep Kumar Chitrapu wrote:
>> Generate rx and tx mcs maps in ath12k_mac_set_hemcsmap() based
>> on number of supported tx/rx chains and set them in supported
>> mcs/nss for HE capabilities.
>>
>> Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.0.1-00029-QCAHKSWPL_SILICONZ-1
>>
>> Co-developed-by: Muna Sinada <quic_msinada@quicinc.com>
>> Signed-off-by: Muna Sinada <quic_msinada@quicinc.com>
>> Signed-off-by: Pradeep Kumar Chitrapu <quic_pradeepc@quicinc.com>
>> Acked-by: Jeff Johnson <quic_jjohnson@quicinc.com>
>> ---
>> drivers/net/wireless/ath/ath12k/mac.c | 40 ++++++++++++++++++++-------
>> 1 file changed, 30 insertions(+), 10 deletions(-)
>>
>> diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c
>> index 30c7d5770ef6..178c89029922 100644
>> --- a/drivers/net/wireless/ath/ath12k/mac.c
>> +++ b/drivers/net/wireless/ath/ath12k/mac.c
>> @@ -6947,20 +6947,40 @@ static __le16 ath12k_mac_setup_he_6ghz_cap(struct ath12k_pdev_cap *pcap,
>> return cpu_to_le16(bcap->he_6ghz_capa);
>> }
>>
>> -static void ath12k_mac_set_hemcsmap(struct ath12k_band_cap *band_cap,
>> +static void ath12k_mac_set_hemcsmap(struct ath12k *ar,
>> + struct ath12k_pdev_cap *cap,
>> struct ieee80211_sta_he_cap *he_cap)
>> {
>> struct ieee80211_he_mcs_nss_supp *mcs_nss = &he_cap->he_mcs_nss_supp;
>> + u16 txmcs_map, rxmcs_map;
>> + u32 i;
>> +
>> + rxmcs_map = 0;
>> + txmcs_map = 0;
>> + for (i = 0; i < 8; i++) {
>> + if (i < ar->num_tx_chains &&
>> + (ar->cfg_tx_chainmask >> cap->tx_chain_mask_shift) & BIT(i))
>> + txmcs_map |= IEEE80211_HE_MCS_SUPPORT_0_11 << (i * 2);
>> + else
>> + txmcs_map |= IEEE80211_HE_MCS_NOT_SUPPORTED << (i * 2);
>> +
>> + if (i < ar->num_rx_chains &&
>> + (ar->cfg_rx_chainmask >> cap->tx_chain_mask_shift) & BIT(i))
>
> I could see the changes are already in external review but wanted to post it internally,
>
> Shouldn't this be cap->rx_chain_mask_shift ?
Hi Uraj
I expect tx_chain_mask_shift and rx_chain_mask_shift must be same. Do
you see any specific issue with this? This will help me debug more.
>
> *"i < ar->num_tx_chains and i < ar->num_rx_chains "*, this is issue since the value of ar->num_tx_chains is not the max supported by the hw always,
> but it gets updated later also via iw phy set antenna command and if user provides any value from 0-15 we will have
> issue. E.g if the value are non continues 1's eg 4 , 5, 6 it will fail and set the VHT/HT/EHT caps to disabled state,
> and only 1,3,7,15 would work correctly.
I see that when userspace changes chainmask, __ath12k_set_antenna calls
ath12k_mac_setup_ht_vht_cap() to reconfigure caps. Please let me know if
you are seeing any specific issue, so that I can address it better..
Thanks
pradeep
>
>> + rxmcs_map |= IEEE80211_HE_MCS_SUPPORT_0_11 << (i * 2);
>> + else
>> + rxmcs_map |= IEEE80211_HE_MCS_NOT_SUPPORTED << (i * 2);
>> + }
>>
>> - mcs_nss->rx_mcs_80 = cpu_to_le16(band_cap->he_mcs & 0xffff);
>> - mcs_nss->tx_mcs_80 = cpu_to_le16(band_cap->he_mcs & 0xffff);
>> - mcs_nss->rx_mcs_160 = cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff);
>> - mcs_nss->tx_mcs_160 = cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff);
>> - mcs_nss->rx_mcs_80p80 = cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff);
>> - mcs_nss->tx_mcs_80p80 = cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff);
>> + mcs_nss->rx_mcs_80 = cpu_to_le16(rxmcs_map & 0xffff);
>> + mcs_nss->tx_mcs_80 = cpu_to_le16(txmcs_map & 0xffff);
>> + mcs_nss->rx_mcs_160 = cpu_to_le16(rxmcs_map & 0xffff);
>> + mcs_nss->tx_mcs_160 = cpu_to_le16(txmcs_map & 0xffff);
>> + mcs_nss->rx_mcs_80p80 = cpu_to_le16(rxmcs_map & 0xffff);
>> + mcs_nss->tx_mcs_80p80 = cpu_to_le16(txmcs_map & 0xffff);
>> }
>>
>> -static void ath12k_mac_copy_he_cap(struct ath12k_band_cap *band_cap,
>> +static void ath12k_mac_copy_he_cap(struct ath12k *ar,
>> + struct ath12k_band_cap *band_cap,
>> int iftype, u8 num_tx_chains,
>> struct ieee80211_sta_he_cap *he_cap)
>> {
>> @@ -7004,7 +7024,7 @@ static void ath12k_mac_copy_he_cap(struct ath12k_band_cap *band_cap,
>> break;
>> }
>>
>> - ath12k_mac_set_hemcsmap(band_cap, he_cap);
>> + ath12k_mac_set_hemcsmap(ar, &ar->pdev->cap, he_cap);
>> memset(he_cap->ppe_thres, 0, sizeof(he_cap->ppe_thres));
>> if (he_cap_elem->phy_cap_info[6] &
>> IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT)
>> @@ -7194,7 +7214,7 @@ static int ath12k_mac_copy_sband_iftype_data(struct ath12k *ar,
>>
>> data[idx].types_mask = BIT(i);
>>
>> - ath12k_mac_copy_he_cap(band_cap, i, ar->num_tx_chains, he_cap);
>> + ath12k_mac_copy_he_cap(ar, band_cap, i, ar->num_tx_chains, he_cap);
>> if (band == NL80211_BAND_6GHZ) {
>> data[idx].he_6ghz_capa.capa =
>> ath12k_mac_setup_he_6ghz_cap(cap, band_cap);
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH V13 8/9] wifi: ath12k: add support for 160 MHz bandwidth
2025-05-28 18:16 ` Pradeep Kumar Chitrapu
@ 2025-06-02 9:05 ` Nicolas Escande
0 siblings, 0 replies; 21+ messages in thread
From: Nicolas Escande @ 2025-06-02 9:05 UTC (permalink / raw)
To: Pradeep Kumar Chitrapu, ath12k; +Cc: linux-wireless, P Praneesh, Jeff Johnson
On Wed May 28, 2025 at 8:16 PM CEST, Pradeep Kumar Chitrapu wrote:
>
>
> On 5/22/2025 1:34 AM, Nicolas Escande wrote:
>> On Wed May 21, 2025 at 11:38 PM CEST, Pradeep Kumar Chitrapu wrote:
>> [...]
>>> Thanks Nicolas,
>>>
>>> I believe IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ mean only
>>> 80PLUS80 not both 160 and 80PLUS80 and STA must set
>>> IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ flags for indicating 160 MHz
>>> support. Please correct me if my understanding is correct. However I
>>> agree that we must allow STA to connect irrespective of which flag STA
>>> sets as long as bandwidth is 160MHz. I see ath10k and ath11k also allows
>>> this by setting default phymode of MODE_11AC_VHT160 for BW
>>> ==IEEE80211_STA_RX_BW_160 case.
>>> I will make this change in next revision.
>>> Thanks
>>> Pradeep
>>
>> Hello Pradeep,
>>
>> Well this is quite unclear for me maybe Johannes or someone more aware of the
>> evolutions of the standard could shime in.
>>
>> From what I've gathered:
>> - the naming IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ implies both
>> which points it was the case when added
>> - and the original 802.11ac-2013 Table 8-183v states:
>> Set to 0 if the STA does not support either 160 or 80+80 MHz.
>> Set to 1 if the STA supports 160 MHz.
>> Set to 2 if the STA supports 160 MHz and 80+80 MHz.
>> The value 3 is reserved.
>>
>> Things get complicated after:
>> - later versions like 802.11-2020 have deprecated value 2 in favor of the new
>> Extendeed NSS BW feature
>> - Table 9-272 still implies both 160 & 80+80
>> - Table 11-23 & Table 11-24 implies only 80+80 but both talk about the
>> 'VHT Operation' Channel Width field and not the 'VHT Capabilities' Supported
>> Channel Width. And thoses had different values even in the first AC amendment
>>
>> So it feels like when no Extended NSS BW Support is used (first gen AC devices),
>> IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ really means both 160 & 80+80
> Thanks Nicolas for detailed response.
> Request you to kindly review V14 series and let me know if it works?
>
> Thanks
> Pradeep
Hello Pradeep,
Yes your new version fixes the problem for me.
Thanks
^ permalink raw reply [flat|nested] 21+ messages in thread
end of thread, other threads:[~2025-06-02 9:05 UTC | newest]
Thread overview: 21+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-04-18 17:48 [PATCH V13 0/9] wifi: ath12k: add MU-MIMO and 160 MHz bandwidth support Pradeep Kumar Chitrapu
2025-04-18 17:48 ` [PATCH V13 1/9] wifi: ath12k: push HE MU-MIMO params to hardware Pradeep Kumar Chitrapu
2025-04-18 17:48 ` [PATCH V13 2/9] wifi: ath12k: push EHT " Pradeep Kumar Chitrapu
2025-04-18 17:48 ` [PATCH V13 3/9] wifi: ath12k: move HE MCS mapper to a separate function Pradeep Kumar Chitrapu
2025-04-18 17:48 ` [PATCH V13 4/9] wifi: ath12k: generate rx and tx mcs maps for supported HE mcs Pradeep Kumar Chitrapu
2025-05-29 6:59 ` Uraj Sasan
2025-05-30 23:01 ` Pradeep Kumar Chitrapu
2025-04-18 17:48 ` [PATCH V13 5/9] wifi: ath12k: fix TX and RX MCS rate configurations in HE mode Pradeep Kumar Chitrapu
2025-04-18 17:48 ` [PATCH V13 6/9] wifi: ath12k: add support for setting fixed HE rate/GI/LTF Pradeep Kumar Chitrapu
2025-05-14 14:54 ` Jeff Johnson
2025-05-21 21:39 ` Pradeep Kumar Chitrapu
2025-04-18 17:48 ` [PATCH V13 7/9] wifi: ath12k: clean up 80P80 support Pradeep Kumar Chitrapu
2025-04-18 17:48 ` [PATCH V13 8/9] wifi: ath12k: add support for 160 MHz bandwidth Pradeep Kumar Chitrapu
2025-05-19 15:11 ` Nicolas Escande
2025-05-21 21:38 ` Pradeep Kumar Chitrapu
2025-05-22 8:34 ` Nicolas Escande
2025-05-28 18:16 ` Pradeep Kumar Chitrapu
2025-06-02 9:05 ` Nicolas Escande
2025-04-18 17:48 ` [PATCH V13 9/9] wifi: ath12k: add extended NSS bandwidth support for 160 MHz Pradeep Kumar Chitrapu
2025-04-18 18:48 ` [PATCH V13 0/9] wifi: ath12k: add MU-MIMO and 160 MHz bandwidth support Jeff Johnson
2025-04-28 16:20 ` Vasanthakumar Thiagarajan
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).