2022-11-10 15:43:04

by Nicolas Cavallari

[permalink] [raw]
Subject: mt76: Fix mt7915 DBDC

The 5ghz phy capabilities were mostly broken when testing with a
mini-pcie mt7915 DBDC from AsiaRF.

I do not know about all the mt7915 variants, so I can't be sure that
this series does not break other models.

These patches are based on the mt76 tree.




2022-11-10 15:43:08

by Nicolas Cavallari

[permalink] [raw]
Subject: [PATCH 2/4] wifi: mt76: mt7915: Fix chainmask calculation on mt7915 DBDC

mt7915 does not have a per-band number of chains unlike the other chips,
it only has a total number of chains. Yet the current code would
consider the total number as a per-band number.

For example, it would report that a 2x2 + 2x2 DBDC card have 4 chains on
each band and set chainmask to 0b1111 for the first interface and
0b11110000 for the second.

Fixes: 99ad32a4ca3a ("mt76: mt7915: add support for MT7986")
Signed-off-by: Nicolas Cavallari <[email protected]>
---
drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c | 1 +
1 file changed, 1 insertion(+)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c
index 83bced0c0785..8bb971018a1e 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c
@@ -194,6 +194,7 @@ void mt7915_eeprom_parse_hw_cap(struct mt7915_dev *dev,
nss = path;
if (dev->dbdc_support) {
if (is_mt7915(&dev->mt76)) {
+ path = path / 2;
nss = FIELD_GET(MT_EE_WIFI_CONF3_TX_PATH_B0,
eeprom[MT_EE_WIFI_CONF + 3]);
if (phy->band_idx)
--
2.38.1


2022-11-10 15:43:17

by Nicolas Cavallari

[permalink] [raw]
Subject: [PATCH 3/4] wifi: mt76: mt7915: Fix VHT beamforming capabilities with DBDC

Do not hardcode beamformee 4 space-time streams support, because
DBDC can only support up to 2.

Fixes: 00b2e16e0063 ("mt76: mt7915: add TxBF capabilities")
Signed-off-by: Nicolas Cavallari <[email protected]>
---
drivers/net/wireless/mediatek/mt76/mt7915/init.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/init.c b/drivers/net/wireless/mediatek/mt76/mt7915/init.c
index 324db5291c85..f2707115b5f3 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/init.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/init.c
@@ -711,7 +711,8 @@ void mt7915_set_stream_vht_txbf_caps(struct mt7915_phy *phy)

*cap |= IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE |
IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE |
- (3 << IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT);
+ FIELD_PREP(IEEE80211_VHT_CAP_BEAMFORMEE_STS_MASK,
+ sts - 1);

*cap &= ~(IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK |
IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE |
--
2.38.1


2022-11-10 15:50:56

by Nicolas Cavallari

[permalink] [raw]
Subject: [PATCH 1/4] wifi: mt76: mt7915: fix antenna selection with bad eeprom.

If the nss value is zero in the eeprom, set it to the max.
This eeprom fragment from a mt7915 DBDC shows the problem:

00000190: 24 24 08 00 28 00 00 15 00 00 00 00 00 00 00 00

Fixes: 51a87540232c ("wifi: mt76: mt7915: rework eeprom tx paths and streams init")
Signed-off-by: Nicolas Cavallari <[email protected]>
---
drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c | 2 ++
1 file changed, 2 insertions(+)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c
index e2482c65d639..83bced0c0785 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c
@@ -208,6 +208,8 @@ void mt7915_eeprom_parse_hw_cap(struct mt7915_dev *dev,
nss_max = 2;
}

+ if (!nss)
+ nss = nss_max;
nss = min_t(u8, min_t(u8, nss_max, nss), path);

mphy->chainmask = BIT(path) - 1;
--
2.38.1


2022-11-10 15:50:56

by Nicolas Cavallari

[permalink] [raw]
Subject: [PATCH 4/4] wifi: mt76: mt7915: don't claim 160MHz support with mt7915 DBDC

The hardware simply does not support this in DBDC mode. Remove it from
the HE capabilities.

Signed-off-by: Nicolas Cavallari <[email protected]>
---
.../net/wireless/mediatek/mt76/mt7915/init.c | 47 ++++++++++++-------
1 file changed, 31 insertions(+), 16 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/init.c b/drivers/net/wireless/mediatek/mt76/mt7915/init.c
index f2707115b5f3..e257b031400f 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/init.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/init.c
@@ -737,8 +737,12 @@ mt7915_set_stream_he_txbf_caps(struct mt7915_phy *phy,
u8 c, sts_160 = sts;

/* Can do 1/2 of STS in 160Mhz mode for mt7915 */
- if (is_mt7915(&dev->mt76) && !dev->dbdc_support)
- sts_160 /= 2;
+ if (is_mt7915(&dev->mt76)) {
+ if (!dev->dbdc_support)
+ sts_160 /= 2;
+ else
+ sts_160 = 0;
+ }

#ifdef CONFIG_MAC80211_MESH
if (vif == NL80211_IFTYPE_MESH_POINT)
@@ -748,8 +752,9 @@ mt7915_set_stream_he_txbf_caps(struct mt7915_phy *phy,
elem->phy_cap_info[3] &= ~IEEE80211_HE_PHY_CAP3_SU_BEAMFORMER;
elem->phy_cap_info[4] &= ~IEEE80211_HE_PHY_CAP4_MU_BEAMFORMER;

- c = IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_MASK |
- IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ_MASK;
+ c = IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_MASK;
+ if (sts_160)
+ c |= IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ_MASK;
elem->phy_cap_info[5] &= ~c;

c = IEEE80211_HE_PHY_CAP6_TRIG_SU_BEAMFORMING_FB |
@@ -765,8 +770,9 @@ mt7915_set_stream_he_txbf_caps(struct mt7915_phy *phy,
elem->phy_cap_info[2] |= c;

c = IEEE80211_HE_PHY_CAP4_SU_BEAMFORMEE |
- IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_UNDER_80MHZ_4 |
- IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_ABOVE_80MHZ_4;
+ IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_UNDER_80MHZ_4;
+ if (sts_160)
+ c |= IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_ABOVE_80MHZ_4;
elem->phy_cap_info[4] |= c;

/* do not support NG16 due to spec D4.0 changes subcarrier idx */
@@ -791,12 +797,13 @@ mt7915_set_stream_he_txbf_caps(struct mt7915_phy *phy,
elem->phy_cap_info[4] |= IEEE80211_HE_PHY_CAP4_MU_BEAMFORMER;

/* num_snd_dim
- * for mt7915, max supported sts is 2 for bw > 80MHz
+ * for mt7915, max supported sts is 2 for bw > 80MHz and 0 if dbdc
*/
c = FIELD_PREP(IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_MASK,
- sts - 1) |
- FIELD_PREP(IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ_MASK,
- sts_160 - 1);
+ sts - 1);
+ if (sts_160)
+ c |= FIELD_PREP(IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ_MASK,
+ sts_160 - 1);
elem->phy_cap_info[5] |= c;

c = IEEE80211_HE_PHY_CAP6_TRIG_SU_BEAMFORMING_FB |
@@ -841,11 +848,14 @@ mt7915_init_he_caps(struct mt7915_phy *phy, enum nl80211_band band,
u16 mcs_map_160 = 0;
u8 nss_160;

- /* Can do 1/2 of NSS streams in 160Mhz mode for mt7915 */
- if (is_mt7915(&dev->mt76) && !dev->dbdc_support)
+ if (!is_mt7915(&dev->mt76))
+ nss_160 = nss;
+ else if (!dev->dbdc_support)
+ /* Can do 1/2 of NSS streams in 160Mhz mode for mt7915 */
nss_160 = nss / 2;
else
- nss_160 = nss;
+ /* Can't do 160MHz with mt7915 dbdc */
+ nss_160 = 0;

for (i = 0; i < 8; i++) {
if (i < nss)
@@ -891,11 +901,14 @@ mt7915_init_he_caps(struct mt7915_phy *phy, enum nl80211_band band,
if (band == NL80211_BAND_2GHZ)
he_cap_elem->phy_cap_info[0] =
IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G;
- else
+ else if (nss_160)
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;
+ else
+ he_cap_elem->phy_cap_info[0] =
+ IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G;

he_cap_elem->phy_cap_info[1] =
IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD;
@@ -949,9 +962,11 @@ mt7915_init_he_caps(struct mt7915_phy *phy, enum nl80211_band band,
IEEE80211_HE_PHY_CAP7_HE_SU_MU_PPDU_4XLTF_AND_08_US_GI;
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 |
IEEE80211_HE_PHY_CAP8_DCM_MAX_RU_484;
+ if (nss_160)
+ he_cap_elem->phy_cap_info[8] |=
+ 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_LONGER_THAN_16_SIGB_OFDM_SYM |
IEEE80211_HE_PHY_CAP9_NON_TRIGGERED_CQI_FEEDBACK |
--
2.38.1


2022-11-12 18:46:09

by Felix Fietkau

[permalink] [raw]
Subject: Re: [PATCH 2/4] wifi: mt76: mt7915: Fix chainmask calculation on mt7915 DBDC

On 10.11.22 16:39, Nicolas Cavallari wrote:
> mt7915 does not have a per-band number of chains unlike the other chips,
> it only has a total number of chains. Yet the current code would
> consider the total number as a per-band number.
>
> For example, it would report that a 2x2 + 2x2 DBDC card have 4 chains on
> each band and set chainmask to 0b1111 for the first interface and
> 0b11110000 for the second.
>
> Fixes: 99ad32a4ca3a ("mt76: mt7915: add support for MT7986")
> Signed-off-by: Nicolas Cavallari <[email protected]>
> ---
> drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c
> index 83bced0c0785..8bb971018a1e 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c
> +++ b/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c
> @@ -194,6 +194,7 @@ void mt7915_eeprom_parse_hw_cap(struct mt7915_dev *dev,
> nss = path;
> if (dev->dbdc_support) {
> if (is_mt7915(&dev->mt76)) {
> + path = path / 2;
> nss = FIELD_GET(MT_EE_WIFI_CONF3_TX_PATH_B0,
> eeprom[MT_EE_WIFI_CONF + 3]);
> if (phy->band_idx)
This was causing a regression on properly calibrated DBDC cards, where
the 'path' variable contains the per-band path, not the total path.
I've folded in the following change to fix your commit:

--- a/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c
@@ -194,7 +194,7 @@ void mt7915_eeprom_parse_hw_cap(struct mt7915_dev *dev,
nss = path;
if (dev->dbdc_support) {
if (is_mt7915(&dev->mt76)) {
- path = path / 2;
+ path = min_t(u8, path, 2);
nss = FIELD_GET(MT_EE_WIFI_CONF3_TX_PATH_B0,
eeprom[MT_EE_WIFI_CONF + 3]);
if (phy->band_idx)


2022-11-14 10:15:53

by Nicolas Cavallari

[permalink] [raw]
Subject: Re: [PATCH 2/4] wifi: mt76: mt7915: Fix chainmask calculation on mt7915 DBDC

On 12/11/2022 19:17, Felix Fietkau wrote:
> On 10.11.22 16:39, Nicolas Cavallari wrote:
>> mt7915 does not have a per-band number of chains unlike the other chips,
>> it only has a total number of chains. Yet the current code would
>> consider the total number as a per-band number.
>>
>> For example, it would report that a 2x2 + 2x2 DBDC card have 4 chains on
>> each band and set chainmask to 0b1111 for the first interface and
>> 0b11110000 for the second.
>>
>> Fixes: 99ad32a4ca3a ("mt76: mt7915: add support for MT7986")
>> Signed-off-by: Nicolas Cavallari <[email protected]>
>> ---
>> drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c | 1 +
>> 1 file changed, 1 insertion(+)
>>
>> diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c
>> index 83bced0c0785..8bb971018a1e 100644
>> --- a/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c
>> +++ b/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c
>> @@ -194,6 +194,7 @@ void mt7915_eeprom_parse_hw_cap(struct mt7915_dev *dev,
>> nss = path;
>> if (dev->dbdc_support) {
>> if (is_mt7915(&dev->mt76)) {
>> + path = path / 2;
>> nss = FIELD_GET(MT_EE_WIFI_CONF3_TX_PATH_B0,
>> eeprom[MT_EE_WIFI_CONF + 3]);
>> if (phy->band_idx)
> This was causing a regression on properly calibrated DBDC cards, where
> the 'path' variable contains the per-band path, not the total path.
> I've folded in the following change to fix your commit:
>
> [...]

Maybe the commit message need to be changed too, because it contains my wrong
interpretation of the eeprom field...