mirror of
https://github.com/Telecominfraproject/wlan-ap.git
synced 2025-12-20 10:51:27 +00:00
398 lines
13 KiB
Diff
398 lines
13 KiB
Diff
From 8cdb5b7216f6b7f022fb64d37db9e7dcd0e8dbcf Mon Sep 17 00:00:00 2001
|
|
From: P Praneesh <ppranees@codeaurora.org>
|
|
Date: Tue, 11 Aug 2020 21:36:57 +0530
|
|
Subject: [PATCH] ath11k: Add native 160MHz support for qcn9000
|
|
|
|
nss_ratio_enabled flag is added to indicate firmware
|
|
supports sending NSS ratio information from firmware
|
|
as a part of service ready ext event. Extract this
|
|
NSS ratio info from service ready ext event and
|
|
save this information in ath11k_pdev_cap to calculate
|
|
NSS ratio.
|
|
|
|
Current firmware configurations support two types
|
|
of NSS ratio which is WMI_NSS_RATIO_1_NSS for qcn9000
|
|
and WMI_NSS_RATIO_1BY2_NSS for ipq8074. Based on this
|
|
two configuration, max supported NSS getting calculated.
|
|
|
|
Tested on: QCN9000
|
|
|
|
Signed-off-by: P Praneesh <ppranees@codeaurora.org>
|
|
---
|
|
drivers/net/wireless/ath/ath11k/core.h | 2 +
|
|
drivers/net/wireless/ath/ath11k/mac.c | 75 +++++++++++++++++++++++++---------
|
|
drivers/net/wireless/ath/ath11k/mac.h | 3 ++
|
|
drivers/net/wireless/ath/ath11k/wmi.c | 18 ++++++--
|
|
drivers/net/wireless/ath/ath11k/wmi.h | 30 ++++++++++++++
|
|
5 files changed, 106 insertions(+), 22 deletions(-)
|
|
|
|
--- a/drivers/net/wireless/ath/ath11k/core.h
|
|
+++ b/drivers/net/wireless/ath/ath11k/core.h
|
|
@@ -697,6 +697,8 @@ struct ath11k_pdev_cap {
|
|
u32 tx_chain_mask_shift;
|
|
u32 rx_chain_mask_shift;
|
|
struct ath11k_band_cap band[NUM_NL80211_BANDS];
|
|
+ bool nss_ratio_enabled;
|
|
+ u8 nss_ratio_info;
|
|
};
|
|
|
|
struct ath11k_pdev {
|
|
--- a/drivers/net/wireless/ath/ath11k/mac.c
|
|
+++ b/drivers/net/wireless/ath/ath11k/mac.c
|
|
@@ -1474,6 +1474,33 @@ ath11k_peer_assoc_h_vht_limit(u16 tx_mcs
|
|
return tx_mcs_set;
|
|
}
|
|
|
|
+static u8 ath11k_get_nss_160MHz(struct ath11k *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:
|
|
+ ath11k_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:
|
|
+ ath11k_warn(ar->ab, "WMI_NSS_RATIO_2_NSS not supported\n");
|
|
+ break;
|
|
+ default:
|
|
+ ath11k_warn(ar->ab, "invalid nss ratio received from fw\n");
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ return max_sup_nss;
|
|
+}
|
|
+
|
|
static void ath11k_peer_assoc_h_vht(struct ath11k *ar,
|
|
struct ieee80211_vif *vif,
|
|
struct ieee80211_sta *sta,
|
|
@@ -1489,6 +1516,7 @@ static void ath11k_peer_assoc_h_vht(stru
|
|
int i;
|
|
bool user_rate_valid = true;
|
|
int vht_nss, nss_idx;
|
|
+ u32 rx_nss_160, tx_nss_160;
|
|
|
|
if (WARN_ON(ath11k_mac_vif_chan(vif, &def)))
|
|
return;
|
|
@@ -1580,10 +1608,32 @@ static void ath11k_peer_assoc_h_vht(stru
|
|
/* TODO: Check */
|
|
arg->tx_max_mcs_nss = 0xFF;
|
|
|
|
- ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac vht peer %pM max_mpdu %d flags 0x%x\n",
|
|
- sta->addr, arg->peer_max_mpdu, arg->peer_flags);
|
|
+ if (arg->peer_phymode == MODE_11AC_VHT160 ||
|
|
+ arg->peer_phymode == MODE_11AC_VHT80_80) {
|
|
+ tx_nss_160 = ath11k_get_nss_160MHz(ar, max_nss);
|
|
+ rx_nss_160 = min(arg->peer_nss, tx_nss_160);
|
|
+
|
|
+ if (rx_nss_160) {
|
|
+ arg->peer_bw_rxnss_override =
|
|
+ ATH11K_BW_NSS_FWCONF_MAP_ENABLE;
|
|
+
|
|
+ if (arg->peer_phymode == MODE_11AC_VHT160)
|
|
+ arg->peer_bw_rxnss_override |=
|
|
+ FIELD_PREP(ATH11K_PEER_RX_NSS_160MHZ,
|
|
+ rx_nss_160 - 1);
|
|
+ else
|
|
+ arg->peer_bw_rxnss_override |=
|
|
+ FIELD_PREP(ATH11K_PEER_RX_NSS_80_80MHZ,
|
|
+ rx_nss_160 - 1);
|
|
+ } else {
|
|
+ ath11k_warn(ar->ab, "invalid max_nss\n");
|
|
+ }
|
|
+ }
|
|
|
|
- /* TODO: rxnss_override */
|
|
+ ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
|
|
+ "mac vht peer %pM max_mpdu %d flags 0x%x peer_bw_rxnss_override 0x%x\n",
|
|
+ sta->addr, arg->peer_max_mpdu, arg->peer_flags,
|
|
+ arg->peer_bw_rxnss_override);
|
|
}
|
|
|
|
static int ath11k_mac_get_max_he_mcs_map(u16 mcs_map, int nss)
|
|
@@ -1675,6 +1725,7 @@ static void ath11k_peer_assoc_h_he(struc
|
|
__le16 he_tx_mcs = 0, v = 0;
|
|
bool user_rate_valid = true;
|
|
int he_nss, nss_idx;
|
|
+ u32 rx_nss_160, tx_nss_160;
|
|
int i;
|
|
|
|
if (WARN_ON(ath11k_mac_vif_chan(vif, &def)))
|
|
@@ -1842,9 +1893,35 @@ static void ath11k_peer_assoc_h_he(struc
|
|
}
|
|
arg->peer_nss = min(sta->rx_nss, max_nss);
|
|
|
|
+ if (arg->peer_phymode == MODE_11AX_HE160 ||
|
|
+ arg->peer_phymode == MODE_11AX_HE80_80) {
|
|
+ tx_nss_160 = ath11k_get_nss_160MHz(ar, ar->num_tx_chains);
|
|
+ rx_nss_160 = min(arg->peer_nss, tx_nss_160);
|
|
+
|
|
+ arg->peer_nss = min(sta->rx_nss, ar->num_rx_chains);
|
|
+
|
|
+ if (rx_nss_160) {
|
|
+ arg->peer_bw_rxnss_override =
|
|
+ ATH11K_BW_NSS_FWCONF_MAP_ENABLE;
|
|
+
|
|
+ if (arg->peer_phymode == MODE_11AX_HE160)
|
|
+ arg->peer_bw_rxnss_override |=
|
|
+ FIELD_PREP(ATH11K_PEER_RX_NSS_160MHZ,
|
|
+ rx_nss_160 - 1);
|
|
+ else
|
|
+ arg->peer_bw_rxnss_override |=
|
|
+ FIELD_PREP(ATH11K_PEER_RX_NSS_80_80MHZ,
|
|
+ rx_nss_160 - 1);
|
|
+ } else {
|
|
+ ath11k_warn(ar->ab, "invalid max_nss\n");
|
|
+ }
|
|
+ }
|
|
+
|
|
ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
|
|
- "mac he peer %pM nss %d mcs cnt %d\n",
|
|
- sta->addr, arg->peer_nss, arg->peer_he_mcs_count);
|
|
+ "mac he peer %pM nss %d mcs cnt %d peer_bw_rxnss_override 0x%x\n",
|
|
+ sta->addr, arg->peer_nss,
|
|
+ arg->peer_he_mcs_count,
|
|
+ arg->peer_bw_rxnss_override);
|
|
}
|
|
|
|
static void ath11k_peer_assoc_h_smps(struct ieee80211_sta *sta,
|
|
@@ -2132,11 +2209,11 @@ static void ath11k_peer_assoc_prepare(st
|
|
ath11k_peer_assoc_h_basic(ar, vif, sta, arg);
|
|
ath11k_peer_assoc_h_crypto(ar, vif, sta, arg);
|
|
ath11k_peer_assoc_h_rates(ar, vif, sta, arg);
|
|
+ ath11k_peer_assoc_h_phymode(ar, vif, sta, arg);
|
|
ath11k_peer_assoc_h_ht(ar, vif, sta, arg);
|
|
ath11k_peer_assoc_h_vht(ar, vif, sta, arg);
|
|
ath11k_peer_assoc_h_he(ar, vif, sta, arg);
|
|
ath11k_peer_assoc_h_qos(ar, vif, sta, arg);
|
|
- ath11k_peer_assoc_h_phymode(ar, vif, sta, arg);
|
|
ath11k_peer_assoc_h_smps(sta, arg);
|
|
|
|
/* TODO: amsdu_disable req? */
|
|
@@ -4582,11 +4659,6 @@ ath11k_create_vht_cap(struct ath11k *ar,
|
|
|
|
ath11k_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;
|
|
-
|
|
rxmcs_map = 0;
|
|
txmcs_map = 0;
|
|
for (i = 0; i < 8; i++) {
|
|
@@ -4607,6 +4679,12 @@ ath11k_create_vht_cap(struct ath11k *ar,
|
|
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;
|
|
}
|
|
|
|
@@ -4788,11 +4866,12 @@ static void ath11k_mac_set_hemcsmap(stru
|
|
struct ath11k_pdev_cap *cap,
|
|
struct ieee80211_sta_he_cap * he_cap)
|
|
{
|
|
- u16 txmcs_map, rxmcs_map;
|
|
+ u16 txmcs_map = 0, rxmcs_map = 0;
|
|
+ u16 txmcs_map_160 = 0, rxmcs_map_160 = 0;
|
|
u32 i = 0;
|
|
+ u8 maxtxnss_160 = ath11k_get_nss_160MHz(ar, ar->num_tx_chains);
|
|
+ u8 maxrxnss_160 = ath11k_get_nss_160MHz(ar, ar->num_rx_chains);
|
|
|
|
- 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))
|
|
@@ -4805,19 +4884,31 @@ static void ath11k_mac_set_hemcsmap(stru
|
|
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);
|
|
}
|
|
he_cap->he_mcs_nss_supp.rx_mcs_80 =
|
|
cpu_to_le16(rxmcs_map & 0xffff);
|
|
he_cap->he_mcs_nss_supp.tx_mcs_80 =
|
|
cpu_to_le16(txmcs_map & 0xffff);
|
|
he_cap->he_mcs_nss_supp.rx_mcs_160 =
|
|
- cpu_to_le16(rxmcs_map & 0xffff);
|
|
+ cpu_to_le16(rxmcs_map_160 & 0xffff);
|
|
he_cap->he_mcs_nss_supp.tx_mcs_160 =
|
|
- cpu_to_le16(txmcs_map & 0xffff);
|
|
+ cpu_to_le16(txmcs_map_160 & 0xffff);
|
|
he_cap->he_mcs_nss_supp.rx_mcs_80p80 =
|
|
- cpu_to_le16(rxmcs_map & 0xffff);
|
|
+ cpu_to_le16(rxmcs_map_160 & 0xffff);
|
|
he_cap->he_mcs_nss_supp.tx_mcs_80p80 =
|
|
- cpu_to_le16(txmcs_map & 0xffff);
|
|
+ cpu_to_le16(txmcs_map_160 & 0xffff);
|
|
}
|
|
|
|
static int ath11k_mac_copy_he_cap(struct ath11k *ar,
|
|
@@ -4852,10 +4943,6 @@ static int ath11k_mac_copy_he_cap(struct
|
|
|
|
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_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;
|
|
@@ -7648,7 +7735,9 @@ static int ath11k_mac_setup_iface_combin
|
|
combinations[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);
|
|
+ ddBIT(NL80211_CHAN_WIDTH_80) |
|
|
+ BIT(NL80211_CHAN_WIDTH_80P80) |
|
|
+ BIT(NL80211_CHAN_WIDTH_160);
|
|
|
|
ar->hw->wiphy->iface_combinations = combinations;
|
|
ar->hw->wiphy->n_iface_combinations = 1;
|
|
@@ -7855,6 +7944,14 @@ static int __ath11k_mac_register(struct
|
|
ieee80211_hw_set(ar->hw, USES_RSS);
|
|
}
|
|
|
|
+ /* If supported number of NSS is less than the maximum
|
|
+ * NSS of device, then SUPPORTS_VHT_EXT_NSS_BW capablity
|
|
+ * needs to adevertise to upper layer
|
|
+ */
|
|
+ if(cap->nss_ratio_enabled)
|
|
+ ieee80211_hw_set(ar->hw, SUPPORTS_VHT_EXT_NSS_BW);
|
|
+
|
|
+
|
|
ar->hw->wiphy->features |= NL80211_FEATURE_STATIC_SMPS;
|
|
ar->hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
|
|
|
|
--- a/drivers/net/wireless/ath/ath11k/mac.h
|
|
+++ b/drivers/net/wireless/ath/ath11k/mac.h
|
|
@@ -115,6 +115,9 @@ struct ath11k_generic_iter {
|
|
#define WMI_MAX_SPATIAL_STREAM 3
|
|
|
|
#define ATH11K_CHAN_WIDTH_NUM 8
|
|
+#define ATH11K_BW_NSS_FWCONF_MAP_ENABLE BIT(31)
|
|
+#define ATH11K_PEER_RX_NSS_160MHZ GENMASK(2, 0)
|
|
+#define ATH11K_PEER_RX_NSS_80_80MHZ GENMASK(5, 3)
|
|
|
|
#define ATH11K_OBSS_PD_MAX_THRESHOLD -82
|
|
#define ATH11K_OBSS_PD_NON_SRG_MAX_THRESHOLD -62
|
|
--- a/drivers/net/wireless/ath/ath11k/wmi.c
|
|
+++ b/drivers/net/wireless/ath/ath11k/wmi.c
|
|
@@ -390,6 +390,10 @@ ath11k_pull_mac_phy_cap_svc_ready_ext(st
|
|
pdev_cap->he_mcs = mac_phy_caps->he_supp_mcs_5g;
|
|
pdev_cap->tx_chain_mask = mac_phy_caps->tx_chain_mask_5g;
|
|
pdev_cap->rx_chain_mask = mac_phy_caps->rx_chain_mask_5g;
|
|
+ pdev_cap->nss_ratio_enabled =
|
|
+ WMI_NSS_RATIO_ENABLE_DISABLE_GET(mac_phy_caps->nss_ratio);
|
|
+ pdev_cap->nss_ratio_info =
|
|
+ WMI_NSS_RATIO_INFO_GET(mac_phy_caps->nss_ratio);
|
|
} else {
|
|
return -EINVAL;
|
|
}
|
|
@@ -813,14 +817,23 @@ int ath11k_wmi_vdev_down(struct ath11k *
|
|
static void ath11k_wmi_put_wmi_channel(struct wmi_channel *chan,
|
|
struct wmi_vdev_start_req_arg *arg)
|
|
{
|
|
+ u32 center_freq1 = arg->channel.band_center_freq1;
|
|
+
|
|
memset(chan, 0, sizeof(*chan));
|
|
|
|
chan->mhz = arg->channel.freq;
|
|
chan->band_center_freq1 = arg->channel.band_center_freq1;
|
|
- if (arg->channel.mode == MODE_11AC_VHT80_80)
|
|
+
|
|
+ if (arg->channel.mode == MODE_11AX_HE160) {
|
|
+ if (arg->channel.freq > arg->channel.band_center_freq1)
|
|
+ chan->band_center_freq1 = center_freq1 + 40;
|
|
+ else
|
|
+ chan->band_center_freq1 = center_freq1 - 40;
|
|
+
|
|
+ chan->band_center_freq2 = arg->channel.band_center_freq1;
|
|
+ } else if ((arg->channel.mode == MODE_11AC_VHT80_80) ||
|
|
+ (arg->channel.mode == MODE_11AX_HE80_80))
|
|
chan->band_center_freq2 = arg->channel.band_center_freq2;
|
|
- else
|
|
- chan->band_center_freq2 = 0;
|
|
|
|
chan->info |= FIELD_PREP(WMI_CHAN_INFO_MODE, arg->channel.mode);
|
|
if (arg->channel.passive)
|
|
--- a/drivers/net/wireless/ath/ath11k/wmi.h
|
|
+++ b/drivers/net/wireless/ath/ath11k/wmi.h
|
|
@@ -2163,6 +2163,24 @@ 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 = 0x0,
|
|
+ WMI_NSS_RATIO_3BY4_NSS = 0x1,
|
|
+ WMI_NSS_RATIO_1_NSS = 0x2,
|
|
+ WMI_NSS_RATIO_2_NSS = 0x3,
|
|
+};
|
|
+
|
|
struct wmi_host_pdev_band_to_mac {
|
|
u32 pdev_id;
|
|
u32 start_freq;
|
|
@@ -2408,6 +2426,12 @@ struct wmi_hw_mode_capabilities {
|
|
} __packed;
|
|
|
|
#define WMI_MAX_HECAP_PHY_SIZE (3)
|
|
+#define WMI_NSS_RATIO_ENABLE_DISABLE_BITPOS BIT(0)
|
|
+#define WMI_NSS_RATIO_ENABLE_DISABLE_GET(_val) \
|
|
+ FIELD_GET(WMI_NSS_RATIO_ENABLE_DISABLE_BITPOS, _val)
|
|
+#define WMI_NSS_RATIO_INFO_BITPOS GENMASK(4,1)
|
|
+#define WMI_NSS_RATIO_INFO_GET(_val) \
|
|
+ FIELD_GET(WMI_NSS_RATIO_INFO_BITPOS, _val)
|
|
|
|
struct wmi_mac_phy_capabilities {
|
|
u32 hw_mode_id;
|
|
@@ -2441,6 +2465,12 @@ struct wmi_mac_phy_capabilities {
|
|
u32 he_cap_info_2g_ext;
|
|
u32 he_cap_info_5g_ext;
|
|
u32 he_cap_info_internal;
|
|
+ u32 wireless_modes;
|
|
+ u32 low_2ghz_chan_freq;
|
|
+ u32 high_2ghz_chan_freq;
|
|
+ u32 low_5ghz_chan_freq;
|
|
+ u32 high_5ghz_chan_freq;
|
|
+ u32 nss_ratio;
|
|
} __packed;
|
|
|
|
struct wmi_hal_reg_capabilities_ext {
|