mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-10 11:40:19 -04:00
wifi: ath12k: push HE MU-MIMO params to hardware
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> Link: https://patch.msgid.link/20250701010408.1257201-2-quic_pradeepc@quicinc.com Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
This commit is contained in:
committed by
Jeff Johnson
parent
c256a94d1b
commit
5d6707e88e
@@ -3160,6 +3160,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)
|
||||
{
|
||||
@@ -3205,6 +3324,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);
|
||||
@@ -3248,8 +3368,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;
|
||||
}
|
||||
|
||||
peer_arg->is_assoc = true;
|
||||
ret = ath12k_wmi_send_peer_assoc_cmd(ar, peer_arg);
|
||||
if (ret) {
|
||||
@@ -3874,6 +4012,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 &&
|
||||
@@ -7349,11 +7494,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) {
|
||||
@@ -8672,72 +8820,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;
|
||||
@@ -9931,14 +10013,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);
|
||||
|
||||
@@ -59,6 +59,21 @@ struct ath12k_generic_iter {
|
||||
|
||||
#define ATH12K_NUM_MAX_ACTIVE_LINKS_PER_DEVICE 2
|
||||
|
||||
#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,
|
||||
|
||||
@@ -3136,31 +3136,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)
|
||||
@@ -3172,8 +3147,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
|
||||
|
||||
Reference in New Issue
Block a user