mt76: mt7915: register per-phy HE capabilities for each interface
The capabilities for the HE interfaces are generated from the capabilities reported by the firmware. This should move to common file once we got other HE devices support. Signed-off-by: Ryder Lee <ryder.lee@mediatek.com> Signed-off-by: Felix Fietkau <nbd@nbd.name>
This commit is contained in:
Родитель
f1d962369d
Коммит
37f4ca907c
|
@ -239,6 +239,194 @@ mt7915_init_wiphy(struct ieee80211_hw *hw)
|
|||
hw->max_tx_fragments = 4;
|
||||
}
|
||||
|
||||
static void
|
||||
mt7915_gen_ppe_thresh(u8 *he_ppet)
|
||||
{
|
||||
int ru, nss, max_nss = 1, max_ru = 3;
|
||||
u8 bit = 7, ru_bit_mask = 0x7;
|
||||
u8 ppet16_ppet8_ru3_ru0[] = {0x1c, 0xc7, 0x71};
|
||||
|
||||
he_ppet[0] = max_nss & IEEE80211_PPE_THRES_NSS_MASK;
|
||||
he_ppet[0] |= (ru_bit_mask <<
|
||||
IEEE80211_PPE_THRES_RU_INDEX_BITMASK_POS) &
|
||||
IEEE80211_PPE_THRES_RU_INDEX_BITMASK_MASK;
|
||||
|
||||
for (nss = 0; nss <= max_nss; nss++) {
|
||||
for (ru = 0; ru < max_ru; ru++) {
|
||||
u8 val;
|
||||
int i;
|
||||
|
||||
if (!(ru_bit_mask & BIT(ru)))
|
||||
continue;
|
||||
|
||||
val = (ppet16_ppet8_ru3_ru0[nss] >> (ru * 6)) &
|
||||
0x3f;
|
||||
val = ((val >> 3) & 0x7) | ((val & 0x7) << 3);
|
||||
for (i = 5; i >= 0; i--) {
|
||||
he_ppet[bit / 8] |=
|
||||
((val >> i) & 0x1) << ((bit % 8));
|
||||
bit++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
mt7915_init_he_caps(struct mt7915_phy *phy, enum nl80211_band band,
|
||||
struct ieee80211_sband_iftype_data *data)
|
||||
{
|
||||
int i, idx = 0;
|
||||
int nss = hweight8(phy->chainmask);
|
||||
u16 mcs_map = 0;
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
if (i < nss)
|
||||
mcs_map |= (IEEE80211_HE_MCS_SUPPORT_0_11 << (i * 2));
|
||||
else
|
||||
mcs_map |= (IEEE80211_HE_MCS_NOT_SUPPORTED << (i * 2));
|
||||
}
|
||||
|
||||
for (i = 0; i < NUM_NL80211_IFTYPES; i++) {
|
||||
struct ieee80211_sta_he_cap *he_cap = &data[idx].he_cap;
|
||||
struct ieee80211_he_cap_elem *he_cap_elem =
|
||||
&he_cap->he_cap_elem;
|
||||
struct ieee80211_he_mcs_nss_supp *he_mcs =
|
||||
&he_cap->he_mcs_nss_supp;
|
||||
|
||||
switch (i) {
|
||||
case NL80211_IFTYPE_STATION:
|
||||
case NL80211_IFTYPE_AP:
|
||||
#ifdef CONFIG_MAC80211_MESH
|
||||
case NL80211_IFTYPE_MESH_POINT:
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
|
||||
data[idx].types_mask = BIT(i);
|
||||
he_cap->has_he = true;
|
||||
|
||||
he_cap_elem->mac_cap_info[0] =
|
||||
IEEE80211_HE_MAC_CAP0_HTC_HE;
|
||||
he_cap_elem->mac_cap_info[1] =
|
||||
IEEE80211_HE_MAC_CAP1_TF_MAC_PAD_DUR_0US |
|
||||
IEEE80211_HE_MAC_CAP1_MULTI_TID_AGG_RX_QOS_1;
|
||||
he_cap_elem->mac_cap_info[2] =
|
||||
IEEE80211_HE_MAC_CAP2_BSR;
|
||||
he_cap_elem->mac_cap_info[3] =
|
||||
IEEE80211_HE_MAC_CAP3_OMI_CONTROL |
|
||||
IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_RESERVED;
|
||||
he_cap_elem->mac_cap_info[4] =
|
||||
IEEE80211_HE_MAC_CAP4_AMDSU_IN_AMPDU;
|
||||
|
||||
if (band == NL80211_BAND_2GHZ)
|
||||
he_cap_elem->phy_cap_info[0] =
|
||||
IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G;
|
||||
else if (band == NL80211_BAND_5GHZ)
|
||||
he_cap_elem->phy_cap_info[0] =
|
||||
IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G |
|
||||
IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G |
|
||||
IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G;
|
||||
|
||||
he_cap_elem->phy_cap_info[1] =
|
||||
IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD;
|
||||
he_cap_elem->phy_cap_info[2] =
|
||||
IEEE80211_HE_PHY_CAP2_NDP_4x_LTF_AND_3_2US |
|
||||
IEEE80211_HE_PHY_CAP2_STBC_TX_UNDER_80MHZ |
|
||||
IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ;
|
||||
|
||||
/* TODO: TxBF & MU & MESH */
|
||||
|
||||
switch (i) {
|
||||
case NL80211_IFTYPE_AP:
|
||||
he_cap_elem->mac_cap_info[0] |=
|
||||
IEEE80211_HE_MAC_CAP0_TWT_RES;
|
||||
he_cap_elem->mac_cap_info[4] |=
|
||||
IEEE80211_HE_MAC_CAP4_BQR;
|
||||
he_cap_elem->phy_cap_info[3] |=
|
||||
IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_QPSK |
|
||||
IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_QPSK;
|
||||
he_cap_elem->phy_cap_info[6] |=
|
||||
IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT;
|
||||
he_cap_elem->phy_cap_info[9] |=
|
||||
IEEE80211_HE_PHY_CAP9_RX_1024_QAM_LESS_THAN_242_TONE_RU;
|
||||
break;
|
||||
case NL80211_IFTYPE_STATION:
|
||||
he_cap_elem->mac_cap_info[0] |=
|
||||
IEEE80211_HE_MAC_CAP0_TWT_REQ;
|
||||
he_cap_elem->mac_cap_info[3] |=
|
||||
IEEE80211_HE_MAC_CAP3_FLEX_TWT_SCHED;
|
||||
|
||||
if (band == NL80211_BAND_2GHZ)
|
||||
he_cap_elem->phy_cap_info[0] |=
|
||||
IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_RU_MAPPING_IN_2G;
|
||||
else if (band == NL80211_BAND_5GHZ)
|
||||
he_cap_elem->phy_cap_info[0] |=
|
||||
IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_RU_MAPPING_IN_5G;
|
||||
|
||||
he_cap_elem->phy_cap_info[1] |=
|
||||
IEEE80211_HE_PHY_CAP1_DEVICE_CLASS_A;
|
||||
he_cap_elem->phy_cap_info[8] |=
|
||||
IEEE80211_HE_PHY_CAP8_20MHZ_IN_40MHZ_HE_PPDU_IN_2G |
|
||||
IEEE80211_HE_PHY_CAP8_20MHZ_IN_160MHZ_HE_PPDU |
|
||||
IEEE80211_HE_PHY_CAP8_80MHZ_IN_160MHZ_HE_PPDU;
|
||||
he_cap_elem->phy_cap_info[9] |=
|
||||
IEEE80211_HE_PHY_CAP9_TX_1024_QAM_LESS_THAN_242_TONE_RU;
|
||||
break;
|
||||
#ifdef CONFIG_MAC80211_MESH
|
||||
case NL80211_IFTYPE_MESH_POINT:
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
||||
he_mcs->rx_mcs_80 = cpu_to_le16(mcs_map);
|
||||
he_mcs->tx_mcs_80 = cpu_to_le16(mcs_map);
|
||||
he_mcs->rx_mcs_160 = cpu_to_le16(mcs_map);
|
||||
he_mcs->tx_mcs_160 = cpu_to_le16(mcs_map);
|
||||
he_mcs->rx_mcs_80p80 = cpu_to_le16(mcs_map);
|
||||
he_mcs->tx_mcs_80p80 = cpu_to_le16(mcs_map);
|
||||
|
||||
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) {
|
||||
mt7915_gen_ppe_thresh(he_cap->ppe_thres);
|
||||
} else {
|
||||
he_cap_elem->phy_cap_info[9] |=
|
||||
IEEE80211_HE_PHY_CAP9_NOMIMAL_PKT_PADDING_16US;
|
||||
}
|
||||
idx++;
|
||||
}
|
||||
|
||||
return idx;
|
||||
}
|
||||
|
||||
void mt7915_set_stream_he_caps(struct mt7915_phy *phy)
|
||||
{
|
||||
struct ieee80211_sband_iftype_data *data;
|
||||
struct ieee80211_supported_band *band;
|
||||
struct mt76_dev *mdev = &phy->dev->mt76;
|
||||
int n;
|
||||
|
||||
if (mdev->cap.has_2ghz) {
|
||||
data = phy->iftype[NL80211_BAND_2GHZ];
|
||||
n = mt7915_init_he_caps(phy, NL80211_BAND_2GHZ, data);
|
||||
|
||||
band = &phy->mt76->sband_2g.sband;
|
||||
band->iftype_data = data;
|
||||
band->n_iftype_data = n;
|
||||
}
|
||||
|
||||
if (mdev->cap.has_5ghz) {
|
||||
data = phy->iftype[NL80211_BAND_5GHZ];
|
||||
n = mt7915_init_he_caps(phy, NL80211_BAND_5GHZ, data);
|
||||
|
||||
band = &phy->mt76->sband_5g.sband;
|
||||
band->iftype_data = data;
|
||||
band->n_iftype_data = n;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
mt7915_cap_dbdc_enable(struct mt7915_dev *dev)
|
||||
{
|
||||
|
@ -256,6 +444,7 @@ mt7915_cap_dbdc_enable(struct mt7915_dev *dev)
|
|||
dev->mphy.hw->wiphy->available_antennas_tx = dev->phy.chainmask;
|
||||
|
||||
mt76_set_stream_caps(&dev->mt76, true);
|
||||
mt7915_set_stream_he_caps(&dev->phy);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -271,6 +460,7 @@ mt7915_cap_dbdc_disable(struct mt7915_dev *dev)
|
|||
dev->mphy.hw->wiphy->available_antennas_tx = dev->chainmask;
|
||||
|
||||
mt76_set_stream_caps(&dev->mt76, true);
|
||||
mt7915_set_stream_he_caps(&dev->phy);
|
||||
}
|
||||
|
||||
int mt7915_register_ext_phy(struct mt7915_dev *dev)
|
||||
|
|
|
@ -691,6 +691,7 @@ mt7915_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant)
|
|||
phy->chainmask = tx_ant;
|
||||
|
||||
mt76_set_stream_caps(&dev->mt76, true);
|
||||
mt7915_set_stream_he_caps(phy);
|
||||
|
||||
mutex_unlock(&dev->mt76.mutex);
|
||||
|
||||
|
|
|
@ -137,11 +137,13 @@ mt7915_get_phy_mode(struct mt7915_dev *dev, struct ieee80211_vif *vif,
|
|||
{
|
||||
struct ieee80211_sta_ht_cap *ht_cap;
|
||||
struct ieee80211_sta_vht_cap *vht_cap;
|
||||
const struct ieee80211_sta_he_cap *he_cap;
|
||||
u8 mode = 0;
|
||||
|
||||
if (sta) {
|
||||
ht_cap = &sta->ht_cap;
|
||||
vht_cap = &sta->vht_cap;
|
||||
he_cap = &sta->he_cap;
|
||||
} else {
|
||||
struct ieee80211_supported_band *sband;
|
||||
|
||||
|
@ -152,6 +154,7 @@ mt7915_get_phy_mode(struct mt7915_dev *dev, struct ieee80211_vif *vif,
|
|||
|
||||
ht_cap = &sband->ht_cap;
|
||||
vht_cap = &sband->vht_cap;
|
||||
he_cap = ieee80211_get_he_iftype_cap(sband, vif->type);
|
||||
}
|
||||
|
||||
if (band == NL80211_BAND_2GHZ) {
|
||||
|
@ -159,6 +162,9 @@ mt7915_get_phy_mode(struct mt7915_dev *dev, struct ieee80211_vif *vif,
|
|||
|
||||
if (ht_cap->ht_supported)
|
||||
mode |= PHY_MODE_GN;
|
||||
|
||||
if (he_cap->has_he)
|
||||
mode |= PHY_MODE_AX_24G;
|
||||
} else if (band == NL80211_BAND_5GHZ) {
|
||||
mode |= PHY_MODE_A;
|
||||
|
||||
|
@ -167,6 +173,9 @@ mt7915_get_phy_mode(struct mt7915_dev *dev, struct ieee80211_vif *vif,
|
|||
|
||||
if (vht_cap->vht_supported)
|
||||
mode |= PHY_MODE_AC;
|
||||
|
||||
if (he_cap->has_he)
|
||||
mode |= PHY_MODE_AX_5G;
|
||||
}
|
||||
|
||||
return mode;
|
||||
|
|
|
@ -815,6 +815,9 @@ enum {
|
|||
#define PHY_MODE_GN BIT(3)
|
||||
#define PHY_MODE_AN BIT(4)
|
||||
#define PHY_MODE_AC BIT(5)
|
||||
#define PHY_MODE_AX_24G BIT(6)
|
||||
#define PHY_MODE_AX_5G BIT(7)
|
||||
#define PHY_MODE_AX_6G BIT(8)
|
||||
|
||||
#define MODE_CCK BIT(0)
|
||||
#define MODE_OFDM BIT(1)
|
||||
|
|
|
@ -122,6 +122,8 @@ struct mt7915_phy {
|
|||
struct mt76_phy *mt76;
|
||||
struct mt7915_dev *dev;
|
||||
|
||||
struct ieee80211_sband_iftype_data iftype[2][NUM_NL80211_IFTYPES];
|
||||
|
||||
u32 rxfilter;
|
||||
u32 vif_mask;
|
||||
u32 omac_mask;
|
||||
|
@ -443,6 +445,7 @@ void mt7915_txp_skb_unmap(struct mt76_dev *dev,
|
|||
struct mt76_txwi_cache *txwi);
|
||||
int mt76_dfs_start_rdd(struct mt7915_dev *dev, bool force);
|
||||
int mt7915_dfs_init_radar_detector(struct mt7915_phy *phy);
|
||||
void mt7915_set_stream_he_caps(struct mt7915_phy *phy);
|
||||
void mt7915_update_channel(struct mt76_dev *mdev);
|
||||
int mt7915_init_debugfs(struct mt7915_dev *dev);
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче