mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-10 10:20:17 -04:00
wifi: ath12k: add support for 160 MHz bandwidth
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> Link: https://patch.msgid.link/20250701010408.1257201-9-quic_pradeepc@quicinc.com Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
This commit is contained in:
committed by
Jeff Johnson
parent
dd25a004fb
commit
18ab9d038f
@@ -894,6 +894,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 {
|
||||
|
||||
@@ -2203,6 +2203,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,
|
||||
@@ -2220,6 +2248,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);
|
||||
|
||||
@@ -2324,10 +2353,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;
|
||||
|
||||
/* TODO: rxnss_override */
|
||||
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 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)
|
||||
@@ -2420,6 +2463,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;
|
||||
@@ -2617,9 +2661,25 @@ static void ath12k_peer_assoc_h_he(struct ath12k *ar,
|
||||
max_nss = min(max_nss, ar->num_tx_chains);
|
||||
arg->peer_nss = min(link_sta->rx_nss, max_nss);
|
||||
|
||||
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,
|
||||
@@ -2860,10 +2920,13 @@ 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? */
|
||||
/* Allow STA to connect even if it does not explicitly advertise 160 MHz
|
||||
* support
|
||||
*/
|
||||
return MODE_11AC_VHT160;
|
||||
}
|
||||
|
||||
@@ -7575,10 +7638,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;
|
||||
@@ -12974,7 +13035,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;
|
||||
@@ -13356,6 +13418,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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -537,6 +537,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;
|
||||
}
|
||||
@@ -1059,7 +1063,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
|
||||
|
||||
@@ -2333,6 +2333,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;
|
||||
@@ -2652,6 +2667,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.
|
||||
|
||||
Reference in New Issue
Block a user