Commit 37f4ca90 authored by Ryder Lee's avatar Ryder Lee Committed by Felix Fietkau

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: default avatarRyder Lee <ryder.lee@mediatek.com>
Signed-off-by: default avatarFelix Fietkau <nbd@nbd.name>
parent f1d96236
...@@ -239,6 +239,194 @@ mt7915_init_wiphy(struct ieee80211_hw *hw) ...@@ -239,6 +239,194 @@ mt7915_init_wiphy(struct ieee80211_hw *hw)
hw->max_tx_fragments = 4; 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 static void
mt7915_cap_dbdc_enable(struct mt7915_dev *dev) mt7915_cap_dbdc_enable(struct mt7915_dev *dev)
{ {
...@@ -256,6 +444,7 @@ 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; dev->mphy.hw->wiphy->available_antennas_tx = dev->phy.chainmask;
mt76_set_stream_caps(&dev->mt76, true); mt76_set_stream_caps(&dev->mt76, true);
mt7915_set_stream_he_caps(&dev->phy);
} }
static void static void
...@@ -271,6 +460,7 @@ mt7915_cap_dbdc_disable(struct mt7915_dev *dev) ...@@ -271,6 +460,7 @@ mt7915_cap_dbdc_disable(struct mt7915_dev *dev)
dev->mphy.hw->wiphy->available_antennas_tx = dev->chainmask; dev->mphy.hw->wiphy->available_antennas_tx = dev->chainmask;
mt76_set_stream_caps(&dev->mt76, true); mt76_set_stream_caps(&dev->mt76, true);
mt7915_set_stream_he_caps(&dev->phy);
} }
int mt7915_register_ext_phy(struct mt7915_dev *dev) 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) ...@@ -691,6 +691,7 @@ mt7915_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant)
phy->chainmask = tx_ant; phy->chainmask = tx_ant;
mt76_set_stream_caps(&dev->mt76, true); mt76_set_stream_caps(&dev->mt76, true);
mt7915_set_stream_he_caps(phy);
mutex_unlock(&dev->mt76.mutex); mutex_unlock(&dev->mt76.mutex);
......
...@@ -137,11 +137,13 @@ mt7915_get_phy_mode(struct mt7915_dev *dev, struct ieee80211_vif *vif, ...@@ -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_ht_cap *ht_cap;
struct ieee80211_sta_vht_cap *vht_cap; struct ieee80211_sta_vht_cap *vht_cap;
const struct ieee80211_sta_he_cap *he_cap;
u8 mode = 0; u8 mode = 0;
if (sta) { if (sta) {
ht_cap = &sta->ht_cap; ht_cap = &sta->ht_cap;
vht_cap = &sta->vht_cap; vht_cap = &sta->vht_cap;
he_cap = &sta->he_cap;
} else { } else {
struct ieee80211_supported_band *sband; struct ieee80211_supported_band *sband;
...@@ -152,6 +154,7 @@ mt7915_get_phy_mode(struct mt7915_dev *dev, struct ieee80211_vif *vif, ...@@ -152,6 +154,7 @@ mt7915_get_phy_mode(struct mt7915_dev *dev, struct ieee80211_vif *vif,
ht_cap = &sband->ht_cap; ht_cap = &sband->ht_cap;
vht_cap = &sband->vht_cap; vht_cap = &sband->vht_cap;
he_cap = ieee80211_get_he_iftype_cap(sband, vif->type);
} }
if (band == NL80211_BAND_2GHZ) { if (band == NL80211_BAND_2GHZ) {
...@@ -159,6 +162,9 @@ mt7915_get_phy_mode(struct mt7915_dev *dev, struct ieee80211_vif *vif, ...@@ -159,6 +162,9 @@ mt7915_get_phy_mode(struct mt7915_dev *dev, struct ieee80211_vif *vif,
if (ht_cap->ht_supported) if (ht_cap->ht_supported)
mode |= PHY_MODE_GN; mode |= PHY_MODE_GN;
if (he_cap->has_he)
mode |= PHY_MODE_AX_24G;
} else if (band == NL80211_BAND_5GHZ) { } else if (band == NL80211_BAND_5GHZ) {
mode |= PHY_MODE_A; mode |= PHY_MODE_A;
...@@ -167,6 +173,9 @@ mt7915_get_phy_mode(struct mt7915_dev *dev, struct ieee80211_vif *vif, ...@@ -167,6 +173,9 @@ mt7915_get_phy_mode(struct mt7915_dev *dev, struct ieee80211_vif *vif,
if (vht_cap->vht_supported) if (vht_cap->vht_supported)
mode |= PHY_MODE_AC; mode |= PHY_MODE_AC;
if (he_cap->has_he)
mode |= PHY_MODE_AX_5G;
} }
return mode; return mode;
......
...@@ -815,6 +815,9 @@ enum { ...@@ -815,6 +815,9 @@ enum {
#define PHY_MODE_GN BIT(3) #define PHY_MODE_GN BIT(3)
#define PHY_MODE_AN BIT(4) #define PHY_MODE_AN BIT(4)
#define PHY_MODE_AC BIT(5) #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_CCK BIT(0)
#define MODE_OFDM BIT(1) #define MODE_OFDM BIT(1)
......
...@@ -122,6 +122,8 @@ struct mt7915_phy { ...@@ -122,6 +122,8 @@ struct mt7915_phy {
struct mt76_phy *mt76; struct mt76_phy *mt76;
struct mt7915_dev *dev; struct mt7915_dev *dev;
struct ieee80211_sband_iftype_data iftype[2][NUM_NL80211_IFTYPES];
u32 rxfilter; u32 rxfilter;
u32 vif_mask; u32 vif_mask;
u32 omac_mask; u32 omac_mask;
...@@ -443,6 +445,7 @@ void mt7915_txp_skb_unmap(struct mt76_dev *dev, ...@@ -443,6 +445,7 @@ void mt7915_txp_skb_unmap(struct mt76_dev *dev,
struct mt76_txwi_cache *txwi); struct mt76_txwi_cache *txwi);
int mt76_dfs_start_rdd(struct mt7915_dev *dev, bool force); int mt76_dfs_start_rdd(struct mt7915_dev *dev, bool force);
int mt7915_dfs_init_radar_detector(struct mt7915_phy *phy); 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); void mt7915_update_channel(struct mt76_dev *mdev);
int mt7915_init_debugfs(struct mt7915_dev *dev); int mt7915_init_debugfs(struct mt7915_dev *dev);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment