| From 04a4a2672095e1b0162153655874ba194370ffc2 Mon Sep 17 00:00:00 2001 |
| From: StanleyYP Wang <StanleyYP.Wang@mediatek.com> |
| Date: Mon, 3 Jun 2024 16:40:38 +0800 |
| Subject: [PATCH 132/223] mtk: mt76: mt7996: update testmode bf support |
| |
| Fix bssid & omac idx to band idx when testmode is enabled |
| |
| Add support for per-packet bw & primary channel selection index configuration |
| This is used for ibf calibaration of group 9 ~ 13 in Kite |
| |
| Change-Id: Ib993f75d331b1fa22b7c07197321f91c8dae46ec |
| Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com> |
| --- |
| mt76.h | 3 +++ |
| mt7996/main.c | 29 +++++++++++++++------- |
| mt7996/testmode.c | 63 ++++++++++++++++++++++++++++++++--------------- |
| testmode.c | 15 ++++++++--- |
| testmode.h | 6 +++++ |
| tools/fields.c | 16 ++++++++++-- |
| 6 files changed, 98 insertions(+), 34 deletions(-) |
| |
| diff --git a/mt76.h b/mt76.h |
| index bc263bd4..526b6298 100644 |
| --- a/mt76.h |
| +++ b/mt76.h |
| @@ -796,6 +796,9 @@ struct mt76_testmode_data { |
| bool ibf; |
| bool ebf; |
| |
| + u8 tx_pkt_bw; |
| + u8 tx_pri_sel; |
| + |
| u32 freq_offset; |
| |
| u8 tx_power[4]; |
| diff --git a/mt7996/main.c b/mt7996/main.c |
| index 485c87f9..f67e1b5d 100644 |
| --- a/mt7996/main.c |
| +++ b/mt7996/main.c |
| @@ -349,16 +349,27 @@ static int mt7996_add_bss_conf(struct mt7996_phy *phy, |
| mconf = &mvif->deflink; |
| } |
| |
| - mconf->mt76.idx = __ffs64(~dev->mt76.vif_mask); |
| - if (mconf->mt76.idx >= mt7996_max_interface_num(dev)) { |
| - ret = -ENOSPC; |
| - goto error; |
| - } |
| + if (!dev->testmode_enable) { |
| + mconf->mt76.idx = __ffs64(~dev->mt76.vif_mask); |
| + if (mconf->mt76.idx >= mt7996_max_interface_num(dev)) { |
| + ret = -ENOSPC; |
| + goto error; |
| + } |
| |
| - idx = get_omac_idx(vif->type, phy->omac_mask); |
| - if (idx < 0) { |
| - ret = -ENOSPC; |
| - goto error; |
| + idx = get_omac_idx(vif->type, phy->omac_mask); |
| + if (idx < 0) { |
| + ret = -ENOSPC; |
| + goto error; |
| + } |
| + } else { |
| + /* bss idx & omac idx should be set to band idx for ibf cal */ |
| + if (dev->mt76.vif_mask & BIT_ULL(band_idx) || |
| + phy->omac_mask & BIT_ULL(band_idx)) { |
| + ret = -ENOSPC; |
| + goto error; |
| + } |
| + mconf->mt76.idx = band_idx; |
| + idx = band_idx; |
| } |
| |
| mconf->own_mld_id = get_own_mld_idx(dev->mld_id_mask, false); |
| diff --git a/mt7996/testmode.c b/mt7996/testmode.c |
| index c68619cb..240227a9 100644 |
| --- a/mt7996/testmode.c |
| +++ b/mt7996/testmode.c |
| @@ -241,8 +241,10 @@ mt7996_tm_init(struct mt7996_phy *phy, bool en) |
| |
| mt7996_tm_rf_switch_mode(dev, rf_test_mode); |
| |
| - mt7996_mcu_add_bss_info(phy, &phy->monitor_vif->bss_conf, &mvif->deflink, &mvif->sta.deflink, en); |
| - mt7996_mcu_add_sta(dev, &phy->monitor_vif->bss_conf, &mvif->deflink, NULL, &mvif->sta.deflink, en, false); |
| + mt7996_mcu_add_bss_info(phy, &phy->monitor_vif->bss_conf, |
| + &mvif->deflink, &mvif->sta.deflink, en); |
| + mt7996_mcu_add_sta(dev, &phy->monitor_vif->bss_conf, &mvif->deflink, |
| + NULL, &mvif->sta.deflink, en, false); |
| |
| mt7996_tm_set(dev, SET_ID(BAND_IDX), phy->mt76->band_idx); |
| |
| @@ -258,9 +260,11 @@ mt7996_tm_update_channel(struct mt7996_phy *phy) |
| { |
| #define CHAN_FREQ_BW_80P80_TAG (SET_ID(CHAN_FREQ) | BIT(16)) |
| struct mt7996_dev *dev = phy->dev; |
| + struct mt76_testmode_data *td = &phy->mt76->test; |
| struct cfg80211_chan_def *chandef = &phy->mt76->chandef; |
| struct ieee80211_channel *chan = chandef->chan; |
| - u8 width = chandef->width; |
| + u8 dbw, width = chandef->width, pri_sel = 0; |
| + int width_mhz; |
| static const u8 ch_band[] = { |
| [NL80211_BAND_2GHZ] = 0, |
| [NL80211_BAND_5GHZ] = 1, |
| @@ -280,18 +284,37 @@ mt7996_tm_update_channel(struct mt7996_phy *phy) |
| mt7996_tm_set(dev, CHAN_FREQ_BW_80P80_TAG, chandef->center_freq2 * 1000); |
| } |
| |
| - /* TODO: define per-packet bw */ |
| - /* per-packet bw */ |
| - mt7996_tm_set(dev, SET_ID(DBW), mt7996_tm_bw_mapping(width, BW_MAP_NL_TO_FW)); |
| + width_mhz = mt7996_tm_bw_mapping(width, BW_MAP_NL_TO_MHZ); |
| + |
| + /* data (per-packet) bw */ |
| + dbw = width; |
| + if (mt76_testmode_param_present(td, MT76_TM_ATTR_TX_PKT_BW)) { |
| + int pkt_bw_mhz = mt7996_tm_bw_mapping(td->tx_pkt_bw, BW_MAP_NL_TO_MHZ); |
| + |
| + if (pkt_bw_mhz > width_mhz) { |
| + dev_info(dev->mt76.dev, |
| + "per-packet bw cannot exceed system bw, use %d MHz instead\n", |
| + width_mhz); |
| + td->tx_pkt_bw = width; |
| + } |
| + dbw = td->tx_pkt_bw; |
| + } |
| + mt7996_tm_set(dev, SET_ID(DBW), mt7996_tm_bw_mapping(dbw, BW_MAP_NL_TO_FW)); |
| |
| /* control channel selection index */ |
| - mt7996_tm_set(dev, SET_ID(PRIMARY_CH), 0); |
| + if (mt76_testmode_param_present(td, MT76_TM_ATTR_TX_PRI_SEL)) { |
| + if (td->tx_pri_sel > width_mhz / 20 - 1) { |
| + dev_info(dev->mt76.dev, |
| + "Invalid primary channel selection index, use 0 instead\n"); |
| + td->tx_pri_sel = 0; |
| + } |
| + pri_sel = td->tx_pri_sel; |
| + } |
| + mt7996_tm_set(dev, SET_ID(PRIMARY_CH), pri_sel); |
| mt7996_tm_set(dev, SET_ID(BAND), ch_band[chan->band]); |
| |
| /* trigger switch channel calibration */ |
| mt7996_tm_set(dev, SET_ID(CHAN_FREQ), chandef->center_freq1 * 1000); |
| - |
| - // TODO: update power limit table |
| } |
| |
| static void |
| @@ -1185,14 +1208,9 @@ mt7996_tm_txbf_init(struct mt7996_phy *phy, u16 *val) |
| mt7996_tm_set_mac_addr(dev, td->addr[1], SET_ID(SA)); |
| mt7996_tm_set_mac_addr(dev, td->addr[2], SET_ID(BSSID)); |
| |
| - /* bss idx & omac idx should be set to band idx for ibf cal */ |
| - mvif->deflink.mt76.idx = band_idx; |
| - dev->mt76.vif_mask |= BIT_ULL(mvif->deflink.mt76.idx); |
| - mvif->deflink.mt76.omac_idx = band_idx; |
| - phy->omac_mask |= BIT_ULL(mvif->deflink.mt76.omac_idx); |
| - |
| mt7996_mcu_add_dev_info(phy, &phy->monitor_vif->bss_conf, &mvif->deflink, true); |
| - mt7996_mcu_add_bss_info(phy, &phy->monitor_vif->bss_conf, &mvif->deflink, &mvif->sta.deflink, true); |
| + mt7996_mcu_add_bss_info(phy, &phy->monitor_vif->bss_conf, |
| + &mvif->deflink, &mvif->sta.deflink, true); |
| |
| if (td->ibf) { |
| if (td->is_txbf_dut) { |
| @@ -1367,7 +1385,8 @@ mt7996_tm_add_txbf_sta(struct mt7996_phy *phy, u8 pfmu_idx, u8 nr, u8 nc, bool e |
| .tx_mode = mt7996_tm_rate_mapping(td->tx_rate_mode, RATE_MODE_TO_PHY), |
| }, |
| }; |
| - u8 ndp_rate, ndpa_rate, rept_poll_rate, bf_bw; |
| + u8 ndp_rate, ndpa_rate, rept_poll_rate; |
| + u8 bf_bw = phy->mt76->chandef.width; |
| |
| if ((td->tx_rate_mode == MT76_TM_TX_MODE_HE_SU || |
| td->tx_rate_mode == MT76_TM_TX_MODE_EHT_SU) && !td->ibf) { |
| @@ -1397,11 +1416,12 @@ mt7996_tm_add_txbf_sta(struct mt7996_phy *phy, u8 pfmu_idx, u8 nr, u8 nc, bool e |
| } |
| } |
| |
| - bf_bw = mt7996_tm_bw_mapping(phy->mt76->chandef.width, BW_MAP_NL_TO_BF); |
| req.bf.ndp_rate = ndp_rate; |
| req.bf.ndpa_rate = ndpa_rate; |
| req.bf.rept_poll_rate = rept_poll_rate; |
| - req.bf.bw = bf_bw; |
| + if (mt76_testmode_param_present(td, MT76_TM_ATTR_TX_PKT_BW)) |
| + bf_bw = td->tx_pkt_bw; |
| + req.bf.bw = mt7996_tm_bw_mapping(bf_bw, BW_MAP_NL_TO_BF); |
| req.bf.tx_mode = (td->tx_rate_mode == MT76_TM_TX_MODE_EHT_SU) ? 0xf : req.bf.tx_mode; |
| |
| if (ebf) { |
| @@ -1428,6 +1448,7 @@ mt7996_tm_txbf_profile_update(struct mt7996_phy *phy, u16 *val, bool ebf) |
| struct mt7996_dev *dev = phy->dev; |
| struct mt7996_pfmu_tag *tag = dev->test.txbf_pfmu_tag; |
| u8 rate, pfmu_idx = val[0], nc = val[2], nr; |
| + u8 dbw = phy->mt76->chandef.width; |
| int ret; |
| bool is_atenl = val[5]; |
| |
| @@ -1446,7 +1467,9 @@ mt7996_tm_txbf_profile_update(struct mt7996_phy *phy, u16 *val, bool ebf) |
| tag->t1.nr = nr; |
| tag->t1.nc = nc; |
| tag->t1.invalid_prof = true; |
| - tag->t1.data_bw = mt7996_tm_bw_mapping(phy->mt76->chandef.width, BW_MAP_NL_TO_BF); |
| + if (mt76_testmode_param_present(td, MT76_TM_ATTR_TX_PKT_BW)) |
| + dbw = td->tx_pkt_bw; |
| + tag->t1.data_bw = mt7996_tm_bw_mapping(dbw, BW_MAP_NL_TO_BF); |
| tag->t2.se_idx = td->tx_spe_idx; |
| |
| if (ebf) { |
| diff --git a/testmode.c b/testmode.c |
| index a1744755..2834400f 100644 |
| --- a/testmode.c |
| +++ b/testmode.c |
| @@ -25,6 +25,8 @@ const struct nla_policy mt76_tm_policy[NUM_MT76_TM_ATTRS] = { |
| [MT76_TM_ATTR_TX_DUTY_CYCLE] = { .type = NLA_U8 }, |
| [MT76_TM_ATTR_TX_IPG] = { .type = NLA_U32 }, |
| [MT76_TM_ATTR_TX_TIME] = { .type = NLA_U32 }, |
| + [MT76_TM_ATTR_TX_PKT_BW] = { .type = NLA_U8 }, |
| + [MT76_TM_ATTR_TX_PRI_SEL] = { .type = NLA_U8 }, |
| [MT76_TM_ATTR_FREQ_OFFSET] = { .type = NLA_U32 }, |
| [MT76_TM_ATTR_DRV_DATA] = { .type = NLA_NESTED }, |
| [MT76_TM_ATTR_OFF_CH_SCAN_CH] = { .type = NLA_U8 }, |
| @@ -567,12 +569,15 @@ int mt76_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif, |
| &td->tx_duty_cycle, 0, 99) || |
| mt76_tm_get_u8(tb[MT76_TM_ATTR_TX_POWER_CONTROL], |
| &td->tx_power_control, 0, 1) || |
| + mt76_tm_get_u8(tb[MT76_TM_ATTR_TX_PKT_BW], &td->tx_pkt_bw, |
| + NL80211_CHAN_WIDTH_20_NOHT, NL80211_CHAN_WIDTH_320) || |
| + mt76_tm_get_u8(tb[MT76_TM_ATTR_TX_PRI_SEL], &td->tx_pri_sel, 0, 15) || |
| mt76_tm_get_u8(tb[MT76_TM_ATTR_AID], &td->aid, 0, 16) || |
| mt76_tm_get_u8(tb[MT76_TM_ATTR_OFF_CH_SCAN_CH], &td->offchan_ch, 36, 196) || |
| mt76_tm_get_u8(tb[MT76_TM_ATTR_OFF_CH_SCAN_CENTER_CH], &td->offchan_center_ch, |
| 36, 196) || |
| - mt76_tm_get_u8(tb[MT76_TM_ATTR_OFF_CH_SCAN_BW], |
| - &td->offchan_bw, NL80211_CHAN_WIDTH_20_NOHT, NL80211_CHAN_WIDTH_160) || |
| + mt76_tm_get_u8(tb[MT76_TM_ATTR_OFF_CH_SCAN_BW], &td->offchan_bw, |
| + NL80211_CHAN_WIDTH_20_NOHT, NL80211_CHAN_WIDTH_160) || |
| mt76_tm_get_u8(tb[MT76_TM_ATTR_IPI_THRESHOLD], &td->ipi_threshold, 0, 10) || |
| mt76_tm_get_u8(tb[MT76_TM_ATTR_IPI_RESET], &td->ipi_reset, 0, 1)) |
| goto out; |
| @@ -616,7 +621,7 @@ int mt76_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif, |
| |
| err = mt76_tm_get_u8(cur, &td->tx_power[idx++], 0, 63); |
| if (err) |
| - return err; |
| + goto out; |
| } |
| } |
| |
| @@ -823,6 +828,10 @@ int mt76_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *msg, |
| nla_put_u32(msg, MT76_TM_ATTR_TX_TIME, td->tx_time)) || |
| (mt76_testmode_param_present(td, MT76_TM_ATTR_TX_POWER_CONTROL) && |
| nla_put_u8(msg, MT76_TM_ATTR_TX_POWER_CONTROL, td->tx_power_control)) || |
| + (mt76_testmode_param_present(td, MT76_TM_ATTR_TX_PKT_BW) && |
| + nla_put_u8(msg, MT76_TM_ATTR_TX_PKT_BW, td->tx_pkt_bw)) || |
| + (mt76_testmode_param_present(td, MT76_TM_ATTR_TX_PRI_SEL) && |
| + nla_put_u8(msg, MT76_TM_ATTR_TX_PRI_SEL, td->tx_pri_sel)) || |
| (mt76_testmode_param_present(td, MT76_TM_ATTR_FREQ_OFFSET) && |
| nla_put_u32(msg, MT76_TM_ATTR_FREQ_OFFSET, td->freq_offset))) |
| goto out; |
| diff --git a/testmode.h b/testmode.h |
| index 794a74f9..44f9984c 100644 |
| --- a/testmode.h |
| +++ b/testmode.h |
| @@ -37,6 +37,9 @@ |
| * @MT76_TM_ATTR_TX_POWER_CONTROL: enable tx power control (u8) |
| * @MT76_TM_ATTR_TX_POWER: per-antenna tx power array (nested, u8 attrs) |
| * |
| + * @MT76_TM_ATTR_TX_PKT_BW: per-packet data bandwidth (u8) |
| + * @MT76_TM_ATTR_TX_PRI_SEL: primary channel selection index (u8) |
| + * |
| * @MT76_TM_ATTR_FREQ_OFFSET: RF frequency offset (u32) |
| * |
| * @MT76_TM_ATTR_STATS: statistics (nested, see &enum mt76_testmode_stats_attr) |
| @@ -104,6 +107,9 @@ enum mt76_testmode_attr { |
| MT76_TM_ATTR_TX_POWER_CONTROL, |
| MT76_TM_ATTR_TX_POWER, |
| |
| + MT76_TM_ATTR_TX_PKT_BW, |
| + MT76_TM_ATTR_TX_PRI_SEL, |
| + |
| MT76_TM_ATTR_FREQ_OFFSET, |
| |
| MT76_TM_ATTR_STATS, |
| diff --git a/tools/fields.c b/tools/fields.c |
| index f793d1a5..8b372602 100644 |
| --- a/tools/fields.c |
| +++ b/tools/fields.c |
| @@ -35,13 +35,21 @@ static const char * const testmode_tx_mode[] = { |
| [MT76_TM_TX_MODE_EHT_MU] = "eht_mu", |
| }; |
| |
| -static const char * const testmode_offchan_bw[] = { |
| +static const char * const testmode_bw[] = { |
| [NL80211_CHAN_WIDTH_20_NOHT] = "NOHT", |
| [NL80211_CHAN_WIDTH_20] = "20", |
| [NL80211_CHAN_WIDTH_40] = "40", |
| [NL80211_CHAN_WIDTH_80] = "80", |
| [NL80211_CHAN_WIDTH_80P80] = "80p80", |
| [NL80211_CHAN_WIDTH_160] = "160", |
| + [NL80211_CHAN_WIDTH_5] = "5", |
| + [NL80211_CHAN_WIDTH_10] = "10", |
| + [NL80211_CHAN_WIDTH_1] = "1", |
| + [NL80211_CHAN_WIDTH_2] = "2", |
| + [NL80211_CHAN_WIDTH_4] = "4", |
| + [NL80211_CHAN_WIDTH_8] = "8", |
| + [NL80211_CHAN_WIDTH_16] = "16", |
| + [NL80211_CHAN_WIDTH_320] = "320", |
| }; |
| |
| static const char * const testmode_txbf_act[] = { |
| @@ -430,6 +438,8 @@ static const struct tm_field testdata_fields[NUM_MT76_TM_ATTRS] = { |
| FIELD(u8, TX_POWER_CONTROL, "tx_power_control"), |
| FIELD_ARRAY(u8, TX_POWER, "tx_power"), |
| FIELD(u8, TX_ANTENNA, "tx_antenna"), |
| + FIELD_ENUM(TX_PKT_BW, "tx_pkt_bw", testmode_bw), |
| + FIELD(u8, TX_PRI_SEL, "tx_pri_sel"), |
| FIELD(u32, FREQ_OFFSET, "freq_offset"), |
| FIELD(u8, AID, "aid"), |
| FIELD(u8, RU_ALLOC, "ru_alloc"), |
| @@ -438,7 +448,7 @@ static const struct tm_field testdata_fields[NUM_MT76_TM_ATTRS] = { |
| FIELD_ARRAY(u16_hex, TXBF_PARAM, "txbf_param"), |
| FIELD(u8, OFF_CH_SCAN_CH, "offchan_ch"), |
| FIELD(u8, OFF_CH_SCAN_CENTER_CH, "offchan_center_ch"), |
| - FIELD_ENUM(OFF_CH_SCAN_BW, "offchan_bw", testmode_offchan_bw), |
| + FIELD_ENUM(OFF_CH_SCAN_BW, "offchan_bw", testmode_bw), |
| FIELD(u8, IPI_THRESHOLD, "ipi_threshold"), |
| FIELD(u32, IPI_PERIOD, "ipi_period"), |
| FIELD(u8, IPI_RESET, "ipi_reset"), |
| @@ -469,6 +479,8 @@ static struct nla_policy testdata_policy[NUM_MT76_TM_ATTRS] = { |
| [MT76_TM_ATTR_TX_POWER_CONTROL] = { .type = NLA_U8 }, |
| [MT76_TM_ATTR_TX_ANTENNA] = { .type = NLA_U8 }, |
| [MT76_TM_ATTR_TX_SPE_IDX] = { .type = NLA_U8 }, |
| + [MT76_TM_ATTR_TX_PKT_BW] = { .type = NLA_U8 }, |
| + [MT76_TM_ATTR_TX_PRI_SEL] = { .type = NLA_U8 }, |
| [MT76_TM_ATTR_FREQ_OFFSET] = { .type = NLA_U32 }, |
| [MT76_TM_ATTR_AID] = { .type = NLA_U8 }, |
| [MT76_TM_ATTR_RU_ALLOC] = { .type = NLA_U8 }, |
| -- |
| 2.45.2 |
| |