developer | 42c7a43 | 2024-07-12 14:39:29 +0800 | [diff] [blame^] | 1 | From d1999bcb10d6f3b0d97bad2ba47ea3bae1b38a52 Mon Sep 17 00:00:00 2001 |
developer | b403ad0 | 2022-11-08 10:16:29 +0800 | [diff] [blame] | 2 | From: StanleyYP Wang <StanleyYP.Wang@mediatek.com> |
| 3 | Date: Thu, 27 Oct 2022 17:42:07 +0800 |
developer | 42c7a43 | 2024-07-12 14:39:29 +0800 | [diff] [blame^] | 4 | Subject: [PATCH] wifi: mt76: testmode: add ZWDFS test mode support |
developer | b403ad0 | 2022-11-08 10:16:29 +0800 | [diff] [blame] | 5 | |
developer | b403ad0 | 2022-11-08 10:16:29 +0800 | [diff] [blame] | 6 | Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com> |
| 7 | --- |
developer | 047bc18 | 2022-11-16 12:20:48 +0800 | [diff] [blame] | 8 | mt76.h | 9 ++ |
developer | b403ad0 | 2022-11-08 10:16:29 +0800 | [diff] [blame] | 9 | mt76_connac_mcu.h | 2 + |
developer | 692ed9b | 2023-06-19 12:03:50 +0800 | [diff] [blame] | 10 | mt7915/mcu.c | 66 +++++++++++ |
| 11 | mt7915/mcu.h | 46 ++++++++ |
developer | b403ad0 | 2022-11-08 10:16:29 +0800 | [diff] [blame] | 12 | mt7915/mt7915.h | 4 + |
developer | 047bc18 | 2022-11-16 12:20:48 +0800 | [diff] [blame] | 13 | mt7915/regs.h | 2 + |
developer | 692ed9b | 2023-06-19 12:03:50 +0800 | [diff] [blame] | 14 | mt7915/testmode.c | 288 ++++++++++++++++++++++++++++++++++++++++++++++ |
| 15 | testmode.c | 25 +++- |
| 16 | testmode.h | 45 ++++++++ |
| 17 | tools/fields.c | 22 ++++ |
| 18 | 10 files changed, 508 insertions(+), 1 deletion(-) |
developer | b403ad0 | 2022-11-08 10:16:29 +0800 | [diff] [blame] | 19 | |
| 20 | diff --git a/mt76.h b/mt76.h |
developer | 42c7a43 | 2024-07-12 14:39:29 +0800 | [diff] [blame^] | 21 | index 5dfae96..65ec039 100644 |
developer | b403ad0 | 2022-11-08 10:16:29 +0800 | [diff] [blame] | 22 | --- a/mt76.h |
| 23 | +++ b/mt76.h |
developer | a46f613 | 2024-03-26 14:09:54 +0800 | [diff] [blame] | 24 | @@ -793,6 +793,15 @@ struct mt76_testmode_data { |
developer | b403ad0 | 2022-11-08 10:16:29 +0800 | [diff] [blame] | 25 | u64 fcs_error[__MT_RXQ_MAX]; |
| 26 | u64 len_mismatch; |
| 27 | } rx_stats; |
| 28 | + |
| 29 | + u8 offchan_ch; |
| 30 | + u8 offchan_center_ch; |
| 31 | + u8 offchan_bw; |
| 32 | + |
| 33 | + u8 ipi_threshold; |
| 34 | + u32 ipi_period; |
| 35 | + u8 ipi_antenna_idx; |
developer | 047bc18 | 2022-11-16 12:20:48 +0800 | [diff] [blame] | 36 | + u8 ipi_reset; |
developer | b403ad0 | 2022-11-08 10:16:29 +0800 | [diff] [blame] | 37 | }; |
| 38 | |
| 39 | struct mt76_vif { |
| 40 | diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h |
developer | 42c7a43 | 2024-07-12 14:39:29 +0800 | [diff] [blame^] | 41 | index 6060eec..09d41b5 100644 |
developer | b403ad0 | 2022-11-08 10:16:29 +0800 | [diff] [blame] | 42 | --- a/mt76_connac_mcu.h |
| 43 | +++ b/mt76_connac_mcu.h |
developer | 42c7a43 | 2024-07-12 14:39:29 +0800 | [diff] [blame^] | 44 | @@ -1243,6 +1243,7 @@ enum { |
developer | b403ad0 | 2022-11-08 10:16:29 +0800 | [diff] [blame] | 45 | MCU_EXT_CMD_OFFCH_SCAN_CTRL = 0x9a, |
| 46 | MCU_EXT_CMD_SET_RDD_TH = 0x9d, |
| 47 | MCU_EXT_CMD_MURU_CTRL = 0x9f, |
| 48 | + MCU_EXT_CMD_IPI_HIST_CTRL = 0xa3, |
| 49 | MCU_EXT_CMD_RX_STAT = 0xa4, |
| 50 | MCU_EXT_CMD_SET_SPR = 0xa8, |
| 51 | MCU_EXT_CMD_GROUP_PRE_CAL_INFO = 0xab, |
developer | 42c7a43 | 2024-07-12 14:39:29 +0800 | [diff] [blame^] | 52 | @@ -1254,6 +1255,7 @@ enum { |
developer | dad89a3 | 2024-04-29 14:17:17 +0800 | [diff] [blame] | 53 | MCU_EXT_CMD_SET_QOS_MAP = 0xb4, |
developer | b403ad0 | 2022-11-08 10:16:29 +0800 | [diff] [blame] | 54 | MCU_EXT_CMD_CERT_CFG = 0xb7, |
| 55 | MCU_EXT_CMD_CSI_CTRL = 0xc2, |
| 56 | + MCU_EXT_CMD_IPI_HIST_SCAN = 0xc5, |
| 57 | }; |
| 58 | |
| 59 | enum { |
| 60 | diff --git a/mt7915/mcu.c b/mt7915/mcu.c |
developer | 42c7a43 | 2024-07-12 14:39:29 +0800 | [diff] [blame^] | 61 | index 17a23e3..3ba91a6 100644 |
developer | b403ad0 | 2022-11-08 10:16:29 +0800 | [diff] [blame] | 62 | --- a/mt7915/mcu.c |
| 63 | +++ b/mt7915/mcu.c |
developer | 753619c | 2024-02-22 13:42:45 +0800 | [diff] [blame] | 64 | @@ -2759,6 +2759,7 @@ mt7915_mcu_background_chain_ctrl(struct mt7915_phy *phy, |
developer | b403ad0 | 2022-11-08 10:16:29 +0800 | [diff] [blame] | 65 | req.monitor_chan = chandef->chan->hw_value; |
| 66 | req.monitor_central_chan = |
| 67 | ieee80211_frequency_to_channel(chandef->center_freq1); |
| 68 | + req.monitor_bw = mt76_connac_chan_bw(chandef); |
developer | 17bb0a8 | 2022-12-13 15:52:04 +0800 | [diff] [blame] | 69 | req.band_idx = phy->mt76->band_idx; |
developer | b403ad0 | 2022-11-08 10:16:29 +0800 | [diff] [blame] | 70 | req.scan_mode = 2; |
| 71 | break; |
developer | 42c7a43 | 2024-07-12 14:39:29 +0800 | [diff] [blame^] | 72 | @@ -4954,3 +4955,68 @@ int mt7915_mcu_set_amsdu_algo(struct mt7915_dev *dev, u16 wcid, u8 enable) |
| 73 | return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(MEC_CTRL), &req, sizeof(req), true); |
developer | b403ad0 | 2022-11-08 10:16:29 +0800 | [diff] [blame] | 74 | } |
| 75 | #endif |
developer | 42c7a43 | 2024-07-12 14:39:29 +0800 | [diff] [blame^] | 76 | + |
developer | b403ad0 | 2022-11-08 10:16:29 +0800 | [diff] [blame] | 77 | +int mt7915_mcu_ipi_hist_ctrl(struct mt7915_phy *phy, void *data, u8 cmd, bool wait_resp) |
| 78 | +{ |
| 79 | + struct mt7915_dev *dev = phy->dev; |
| 80 | + struct sk_buff *skb; |
| 81 | + int ret; |
| 82 | + struct { |
| 83 | + u8 ipi_hist_idx; |
| 84 | + u8 band_idx; |
| 85 | + u8 set_val; |
| 86 | + u8 rsv; |
| 87 | + int idle_power_th; |
| 88 | + u32 idle_power_max_cnt; |
| 89 | + u32 idle_power_duration; |
| 90 | + u32 idle_power_cmd_type; |
| 91 | + } __packed req = { |
| 92 | + .ipi_hist_idx = cmd, |
developer | 17bb0a8 | 2022-12-13 15:52:04 +0800 | [diff] [blame] | 93 | + .band_idx = phy->mt76->band_idx, |
developer | b403ad0 | 2022-11-08 10:16:29 +0800 | [diff] [blame] | 94 | + }; |
| 95 | + |
developer | 047bc18 | 2022-11-16 12:20:48 +0800 | [diff] [blame] | 96 | + if (!wait_resp) |
| 97 | + return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(IPI_HIST_CTRL), |
| 98 | + &req, sizeof(req), true); |
| 99 | + |
| 100 | + ret = mt76_mcu_send_and_get_msg(&dev->mt76, MCU_EXT_QUERY(IPI_HIST_CTRL), |
developer | b403ad0 | 2022-11-08 10:16:29 +0800 | [diff] [blame] | 101 | + &req, sizeof(req), wait_resp, &skb); |
developer | 047bc18 | 2022-11-16 12:20:48 +0800 | [diff] [blame] | 102 | + |
developer | b403ad0 | 2022-11-08 10:16:29 +0800 | [diff] [blame] | 103 | + if (ret) |
| 104 | + return ret; |
| 105 | + |
developer | b403ad0 | 2022-11-08 10:16:29 +0800 | [diff] [blame] | 106 | + memcpy(data, skb->data, sizeof(struct mt7915_mcu_rdd_ipi_ctrl)); |
| 107 | + dev_kfree_skb(skb); |
| 108 | + |
| 109 | + return 0; |
| 110 | +} |
| 111 | + |
| 112 | +int mt7915_mcu_ipi_hist_scan(struct mt7915_phy *phy, void *data, u8 mode, bool wait_resp) |
| 113 | +{ |
| 114 | + struct mt7915_dev *dev = phy->dev; |
| 115 | + struct sk_buff *skb; |
| 116 | + int ret; |
| 117 | + struct rdd_ipi_hist_scan { |
| 118 | + u8 mode; |
| 119 | + u8 pd_setting; |
| 120 | + u8 band_idx; |
| 121 | + u8 rsv; |
| 122 | + } __packed req = { |
| 123 | + .mode = mode, |
| 124 | + .pd_setting = 1, |
developer | 17bb0a8 | 2022-12-13 15:52:04 +0800 | [diff] [blame] | 125 | + .band_idx = phy->mt76->band_idx, |
developer | b403ad0 | 2022-11-08 10:16:29 +0800 | [diff] [blame] | 126 | + }; |
| 127 | + |
| 128 | + ret = mt76_mcu_send_and_get_msg(&dev->mt76, MCU_EXT_CMD(IPI_HIST_SCAN), |
| 129 | + &req, sizeof(req), wait_resp, &skb); |
| 130 | + if (ret) |
| 131 | + return ret; |
| 132 | + |
| 133 | + if (!wait_resp) |
| 134 | + return 0; |
| 135 | + |
| 136 | + memcpy(data, skb->data, sizeof(struct mt7915_mcu_rdd_ipi_scan)); |
| 137 | + dev_kfree_skb(skb); |
| 138 | + |
| 139 | + return 0; |
| 140 | +} |
| 141 | diff --git a/mt7915/mcu.h b/mt7915/mcu.h |
developer | dc9eeae | 2024-04-08 14:36:46 +0800 | [diff] [blame] | 142 | index c791c7f..066246b 100644 |
developer | b403ad0 | 2022-11-08 10:16:29 +0800 | [diff] [blame] | 143 | --- a/mt7915/mcu.h |
| 144 | +++ b/mt7915/mcu.h |
developer | 753619c | 2024-02-22 13:42:45 +0800 | [diff] [blame] | 145 | @@ -698,6 +698,52 @@ enum CSI_CHAIN_TYPE { |
developer | b403ad0 | 2022-11-08 10:16:29 +0800 | [diff] [blame] | 146 | }; |
| 147 | #endif |
| 148 | |
| 149 | +enum { |
| 150 | + RDD_SET_IPI_CR_INIT, /* CR initialization */ |
| 151 | + RDD_SET_IPI_HIST_RESET, /* Reset IPI histogram counter */ |
| 152 | + RDD_SET_IDLE_POWER, /* Idle power info */ |
| 153 | + RDD_SET_IPI_HIST_NUM |
| 154 | +}; |
| 155 | + |
| 156 | +enum { |
| 157 | + RDD_IPI_HIST_0, /* IPI count for power <= -92 (dBm) */ |
| 158 | + RDD_IPI_HIST_1, /* IPI count for -92 < power <= -89 (dBm) */ |
| 159 | + RDD_IPI_HIST_2, /* IPI count for -89 < power <= -86 (dBm) */ |
| 160 | + RDD_IPI_HIST_3, /* IPI count for -86 < power <= -83 (dBm) */ |
| 161 | + RDD_IPI_HIST_4, /* IPI count for -83 < power <= -80 (dBm) */ |
| 162 | + RDD_IPI_HIST_5, /* IPI count for -80 < power <= -75 (dBm) */ |
| 163 | + RDD_IPI_HIST_6, /* IPI count for -75 < power <= -70 (dBm) */ |
| 164 | + RDD_IPI_HIST_7, /* IPI count for -70 < power <= -65 (dBm) */ |
| 165 | + RDD_IPI_HIST_8, /* IPI count for -65 < power <= -60 (dBm) */ |
| 166 | + RDD_IPI_HIST_9, /* IPI count for -60 < power <= -55 (dBm) */ |
| 167 | + RDD_IPI_HIST_10, /* IPI count for -55 < power (dBm) */ |
| 168 | + RDD_IPI_FREE_RUN_CNT, /* IPI count for counter++ per 8 us */ |
| 169 | + RDD_IPI_HIST_ALL_CNT, /* Get all IPI */ |
| 170 | + RDD_IPI_HIST_0_TO_10_CNT, /* Get IPI histogram 0 to 10 */ |
| 171 | + RDD_IPI_HIST_2_TO_10_CNT, /* Get IPI histogram 2 to 10 */ |
| 172 | + RDD_TX_ASSERT_TIME, /* Get band 1 TX assert time */ |
| 173 | + RDD_IPI_HIST_NUM |
| 174 | +}; |
| 175 | + |
| 176 | +#define RDM_NF_MAX_WF_IDX 8 |
| 177 | +#define POWER_INDICATE_HIST_MAX RDD_IPI_FREE_RUN_CNT |
| 178 | +#define IPI_HIST_TYPE_NUM (POWER_INDICATE_HIST_MAX + 1) |
| 179 | + |
| 180 | +struct mt7915_mcu_rdd_ipi_ctrl { |
| 181 | + u8 ipi_hist_idx; |
| 182 | + u8 band_idx; |
| 183 | + u8 rsv[2]; |
| 184 | + u32 ipi_hist_val[IPI_HIST_TYPE_NUM]; |
| 185 | + u32 tx_assert_time; /* unit: us */ |
| 186 | +} __packed; |
| 187 | + |
| 188 | +struct mt7915_mcu_rdd_ipi_scan { |
| 189 | + u32 ipi_hist_val[RDM_NF_MAX_WF_IDX][POWER_INDICATE_HIST_MAX]; |
| 190 | + u8 band_idx; |
| 191 | + u8 rsv[2]; |
| 192 | + u8 tx_assert_time; /* unit: us */ |
| 193 | +} __packed; |
| 194 | + |
| 195 | /* MURU */ |
| 196 | #define OFDMA_DL BIT(0) |
| 197 | #define OFDMA_UL BIT(1) |
| 198 | diff --git a/mt7915/mt7915.h b/mt7915/mt7915.h |
developer | 42c7a43 | 2024-07-12 14:39:29 +0800 | [diff] [blame^] | 199 | index ca385b6..00f5544 100644 |
developer | b403ad0 | 2022-11-08 10:16:29 +0800 | [diff] [blame] | 200 | --- a/mt7915/mt7915.h |
| 201 | +++ b/mt7915/mt7915.h |
developer | 42c7a43 | 2024-07-12 14:39:29 +0800 | [diff] [blame^] | 202 | @@ -306,6 +306,7 @@ struct mt7915_phy { |
developer | b403ad0 | 2022-11-08 10:16:29 +0800 | [diff] [blame] | 203 | |
developer | 47efbdb | 2023-06-29 20:33:22 +0800 | [diff] [blame] | 204 | struct mt76_mib_stats mib; |
developer | b403ad0 | 2022-11-08 10:16:29 +0800 | [diff] [blame] | 205 | struct mt76_channel_state state_ts; |
| 206 | + struct delayed_work ipi_work; |
| 207 | |
developer | 8effbd3 | 2023-04-17 15:57:28 +0800 | [diff] [blame] | 208 | u8 stats_work_count; |
| 209 | struct list_head stats_list; |
developer | 42c7a43 | 2024-07-12 14:39:29 +0800 | [diff] [blame^] | 210 | @@ -786,6 +787,9 @@ int mt7915_vendor_amnt_sta_remove(struct mt7915_phy *phy, |
developer | b403ad0 | 2022-11-08 10:16:29 +0800 | [diff] [blame] | 211 | struct ieee80211_sta *sta); |
| 212 | #endif |
| 213 | |
| 214 | +int mt7915_mcu_ipi_hist_ctrl(struct mt7915_phy *phy, void *data, u8 cmd, bool wait_resp); |
| 215 | +int mt7915_mcu_ipi_hist_scan(struct mt7915_phy *phy, void *data, u8 mode, bool wait_resp); |
| 216 | + |
| 217 | #ifdef MTK_DEBUG |
| 218 | int mt7915_mtk_init_debugfs(struct mt7915_phy *phy, struct dentry *dir); |
| 219 | int mt7915_dbg_mcu_wa_cmd(struct mt7915_dev *dev, int cmd, u32 a1, u32 a2, u32 a3, bool wait_resp); |
developer | 047bc18 | 2022-11-16 12:20:48 +0800 | [diff] [blame] | 220 | diff --git a/mt7915/regs.h b/mt7915/regs.h |
developer | dc9eeae | 2024-04-08 14:36:46 +0800 | [diff] [blame] | 221 | index 1236da9..7e9b76b 100644 |
developer | 047bc18 | 2022-11-16 12:20:48 +0800 | [diff] [blame] | 222 | --- a/mt7915/regs.h |
| 223 | +++ b/mt7915/regs.h |
developer | a46f613 | 2024-03-26 14:09:54 +0800 | [diff] [blame] | 224 | @@ -1211,6 +1211,8 @@ enum offs_rev { |
developer | 047bc18 | 2022-11-16 12:20:48 +0800 | [diff] [blame] | 225 | #define MT_WF_IRPI_NSS(phy, nss) MT_WF_IRPI(0x6000 + ((phy) << 20) + ((nss) << 16)) |
| 226 | #define MT_WF_IRPI_NSS_MT7916(phy, nss) MT_WF_IRPI(0x1000 + ((phy) << 20) + ((nss) << 16)) |
| 227 | |
| 228 | +#define MT_WF_IPI_RESET 0x831a3008 |
| 229 | + |
| 230 | /* PHY */ |
| 231 | #define MT_WF_PHY_BASE 0x83080000 |
| 232 | #define MT_WF_PHY(ofs) (MT_WF_PHY_BASE + (ofs)) |
developer | b403ad0 | 2022-11-08 10:16:29 +0800 | [diff] [blame] | 233 | diff --git a/mt7915/testmode.c b/mt7915/testmode.c |
developer | dc9eeae | 2024-04-08 14:36:46 +0800 | [diff] [blame] | 234 | index 453319e..caa3590 100644 |
developer | b403ad0 | 2022-11-08 10:16:29 +0800 | [diff] [blame] | 235 | --- a/mt7915/testmode.c |
| 236 | +++ b/mt7915/testmode.c |
developer | 1a17367 | 2023-12-21 14:49:33 +0800 | [diff] [blame] | 237 | @@ -14,6 +14,12 @@ enum { |
developer | b403ad0 | 2022-11-08 10:16:29 +0800 | [diff] [blame] | 238 | TM_CHANGED_AID, |
| 239 | TM_CHANGED_CFG, |
| 240 | TM_CHANGED_TXBF_ACT, |
| 241 | + TM_CHANGED_OFF_CHAN_CH, |
| 242 | + TM_CHANGED_OFF_CHAN_CENTER_CH, |
| 243 | + TM_CHANGED_OFF_CHAN_BW, |
| 244 | + TM_CHANGED_IPI_THRESHOLD, |
| 245 | + TM_CHANGED_IPI_PERIOD, |
developer | 047bc18 | 2022-11-16 12:20:48 +0800 | [diff] [blame] | 246 | + TM_CHANGED_IPI_RESET, |
developer | b403ad0 | 2022-11-08 10:16:29 +0800 | [diff] [blame] | 247 | |
| 248 | /* must be last */ |
| 249 | NUM_TM_CHANGED |
developer | 1a17367 | 2023-12-21 14:49:33 +0800 | [diff] [blame] | 250 | @@ -26,6 +32,12 @@ static const u8 tm_change_map[] = { |
developer | b403ad0 | 2022-11-08 10:16:29 +0800 | [diff] [blame] | 251 | [TM_CHANGED_AID] = MT76_TM_ATTR_AID, |
| 252 | [TM_CHANGED_CFG] = MT76_TM_ATTR_CFG, |
| 253 | [TM_CHANGED_TXBF_ACT] = MT76_TM_ATTR_TXBF_ACT, |
| 254 | + [TM_CHANGED_OFF_CHAN_CH] = MT76_TM_ATTR_OFF_CH_SCAN_CH, |
| 255 | + [TM_CHANGED_OFF_CHAN_CENTER_CH] = MT76_TM_ATTR_OFF_CH_SCAN_CENTER_CH, |
| 256 | + [TM_CHANGED_OFF_CHAN_BW] = MT76_TM_ATTR_OFF_CH_SCAN_BW, |
| 257 | + [TM_CHANGED_IPI_THRESHOLD] = MT76_TM_ATTR_IPI_THRESHOLD, |
| 258 | + [TM_CHANGED_IPI_PERIOD] = MT76_TM_ATTR_IPI_PERIOD, |
developer | 047bc18 | 2022-11-16 12:20:48 +0800 | [diff] [blame] | 259 | + [TM_CHANGED_IPI_RESET] = MT76_TM_ATTR_IPI_RESET, |
developer | b403ad0 | 2022-11-08 10:16:29 +0800 | [diff] [blame] | 260 | }; |
| 261 | |
| 262 | struct reg_band { |
developer | 1a17367 | 2023-12-21 14:49:33 +0800 | [diff] [blame] | 263 | @@ -984,6 +996,272 @@ mt7915_tm_set_txbf(struct mt7915_phy *phy) |
developer | b403ad0 | 2022-11-08 10:16:29 +0800 | [diff] [blame] | 264 | return 0; |
| 265 | } |
| 266 | |
developer | 692ed9b | 2023-06-19 12:03:50 +0800 | [diff] [blame] | 267 | +static u8 |
| 268 | +mt7915_tm_get_center_chan(struct mt7915_phy *phy, struct cfg80211_chan_def *chandef, |
| 269 | + int width_mhz) |
| 270 | +{ |
| 271 | + struct mt76_phy *mphy = phy->mt76; |
| 272 | + const struct ieee80211_channel *chan = mphy->sband_5g.sband.channels; |
| 273 | + u32 bitmap, i, offset, size = 32; |
| 274 | + u16 first_control = 0, control_chan = chandef->chan->hw_value; |
| 275 | + static const u32 width_to_bitmap[] = { |
| 276 | + [NL80211_CHAN_WIDTH_20_NOHT] = 0x0, |
| 277 | + [NL80211_CHAN_WIDTH_20] = 0x0, |
| 278 | + [NL80211_CHAN_WIDTH_40] = 0x55554055, |
| 279 | + [NL80211_CHAN_WIDTH_80] = 0x44444011, |
| 280 | + [NL80211_CHAN_WIDTH_80P80] = 0x0, |
| 281 | + [NL80211_CHAN_WIDTH_160] = 0x04004001, |
| 282 | + }; |
| 283 | + |
| 284 | + bitmap = width_to_bitmap[chandef->width]; |
| 285 | + if (!bitmap) |
| 286 | + return control_chan; |
| 287 | + |
| 288 | + offset = width_mhz / 10 - 2; |
| 289 | + for (i = 0; i < size; i++) { |
| 290 | + if (!((1 << i) & bitmap)) |
| 291 | + continue; |
| 292 | + |
| 293 | + if (control_chan >= chan[i].hw_value) |
| 294 | + first_control = chan[i].hw_value; |
| 295 | + else |
| 296 | + break; |
| 297 | + } |
| 298 | + |
| 299 | + if (chandef->width == NL80211_CHAN_WIDTH_40 && |
| 300 | + control_chan >= chan[size].hw_value) |
| 301 | + return chan[size].hw_value + offset; |
| 302 | + else if (first_control == 0) |
| 303 | + return control_chan; |
| 304 | + |
| 305 | + return first_control + offset; |
| 306 | +} |
| 307 | + |
developer | b403ad0 | 2022-11-08 10:16:29 +0800 | [diff] [blame] | 308 | +static int |
developer | 692ed9b | 2023-06-19 12:03:50 +0800 | [diff] [blame] | 309 | +mt7915_tm_set_offchan(struct mt7915_phy *phy, bool no_center) |
developer | b403ad0 | 2022-11-08 10:16:29 +0800 | [diff] [blame] | 310 | +{ |
| 311 | + struct mt76_phy *mphy = phy->mt76; |
| 312 | + struct mt7915_dev *dev = phy->dev; |
| 313 | + struct ieee80211_hw *hw = mphy->hw; |
| 314 | + struct mt76_testmode_data *td = &phy->mt76->test; |
| 315 | + struct cfg80211_chan_def chandef = {}; |
| 316 | + struct ieee80211_channel *chan; |
| 317 | + int ret, freq = ieee80211_channel_to_frequency(td->offchan_ch, NL80211_BAND_5GHZ); |
| 318 | + int width_mhz; |
| 319 | + const int bw_to_mhz[] = { |
| 320 | + [NL80211_CHAN_WIDTH_20_NOHT] = 20, |
| 321 | + [NL80211_CHAN_WIDTH_20] = 20, |
| 322 | + [NL80211_CHAN_WIDTH_40] = 40, |
| 323 | + [NL80211_CHAN_WIDTH_80] = 80, |
| 324 | + [NL80211_CHAN_WIDTH_80P80] = 80, |
| 325 | + [NL80211_CHAN_WIDTH_160] = 160, |
| 326 | + }; |
| 327 | + |
developer | 047bc18 | 2022-11-16 12:20:48 +0800 | [diff] [blame] | 328 | + if (!mphy->cap.has_5ghz || !freq) { |
developer | b403ad0 | 2022-11-08 10:16:29 +0800 | [diff] [blame] | 329 | + ret = -EINVAL; |
| 330 | + dev_info(dev->mt76.dev, "Failed to set offchan (invalid band or channel)!\n"); |
| 331 | + goto out; |
| 332 | + } |
| 333 | + |
| 334 | + chandef.width = td->offchan_bw; |
| 335 | + width_mhz = bw_to_mhz[chandef.width]; |
developer | b403ad0 | 2022-11-08 10:16:29 +0800 | [diff] [blame] | 336 | + chan = ieee80211_get_channel(hw->wiphy, freq); |
developer | 692ed9b | 2023-06-19 12:03:50 +0800 | [diff] [blame] | 337 | + if (!chan) { |
| 338 | + ret = -EINVAL; |
| 339 | + dev_info(dev->mt76.dev, "Failed to set offchan (invalid control channel)!\n"); |
| 340 | + goto out; |
| 341 | + } |
developer | b403ad0 | 2022-11-08 10:16:29 +0800 | [diff] [blame] | 342 | + chandef.chan = chan; |
| 343 | + |
developer | 692ed9b | 2023-06-19 12:03:50 +0800 | [diff] [blame] | 344 | + if (no_center) |
| 345 | + td->offchan_center_ch = mt7915_tm_get_center_chan(phy, &chandef, width_mhz); |
| 346 | + chandef.center_freq1 = ieee80211_channel_to_frequency(td->offchan_center_ch, |
| 347 | + NL80211_BAND_5GHZ); |
| 348 | + if (!cfg80211_chandef_valid(&chandef)) { |
| 349 | + ret = -EINVAL; |
| 350 | + dev_info(dev->mt76.dev, "Failed to set offchan, chandef is invalid!\n"); |
| 351 | + goto out; |
| 352 | + } |
| 353 | + |
developer | b403ad0 | 2022-11-08 10:16:29 +0800 | [diff] [blame] | 354 | + memset(&dev->rdd2_chandef, 0, sizeof(struct cfg80211_chan_def)); |
| 355 | + |
| 356 | + ret = mt7915_mcu_rdd_background_enable(phy, &chandef); |
| 357 | + |
| 358 | + if (ret) |
| 359 | + goto out; |
| 360 | + |
| 361 | + dev->rdd2_phy = phy; |
| 362 | + dev->rdd2_chandef = chandef; |
| 363 | + |
| 364 | + return ret; |
| 365 | + |
| 366 | +out: |
| 367 | + td->offchan_ch = 0; |
developer | 692ed9b | 2023-06-19 12:03:50 +0800 | [diff] [blame] | 368 | + td->offchan_center_ch = 0; |
developer | b403ad0 | 2022-11-08 10:16:29 +0800 | [diff] [blame] | 369 | + td->offchan_bw = 0; |
| 370 | + |
| 371 | + return ret; |
| 372 | +} |
| 373 | + |
| 374 | +static void |
| 375 | +mt7915_tm_dump_ipi(struct mt7915_phy *phy, void *data, u8 antenna_num, |
| 376 | + u8 start_antenna_idx, bool is_scan) |
| 377 | +{ |
| 378 | +#define PRECISION 100 |
| 379 | + struct mt7915_dev *dev = phy->dev; |
| 380 | + struct mt76_testmode_data *td = &phy->mt76->test; |
| 381 | + struct mt7915_mcu_rdd_ipi_scan *scan_data; |
| 382 | + struct mt7915_mcu_rdd_ipi_ctrl *ctrl_data; |
| 383 | + u32 ipi_idx, ipi_free_count, ipi_percentage, ipi_hist_count_th, ipi_hist_total_count; |
| 384 | + u32 self_idle_ratio, ipi_idle_ratio, channel_load, tx_assert_time; |
| 385 | + u8 i, antenna_idx = start_antenna_idx; |
| 386 | + u32 *ipi_hist_data; |
| 387 | + const char *power_lower_bound, *power_upper_bound; |
| 388 | + static const char * const ipi_idx_to_power_bound[] = { |
| 389 | + [RDD_IPI_HIST_0] = "-92", |
| 390 | + [RDD_IPI_HIST_1] = "-89", |
| 391 | + [RDD_IPI_HIST_2] = "-86", |
| 392 | + [RDD_IPI_HIST_3] = "-83", |
| 393 | + [RDD_IPI_HIST_4] = "-80", |
| 394 | + [RDD_IPI_HIST_5] = "-75", |
| 395 | + [RDD_IPI_HIST_6] = "-70", |
| 396 | + [RDD_IPI_HIST_7] = "-65", |
| 397 | + [RDD_IPI_HIST_8] = "-60", |
| 398 | + [RDD_IPI_HIST_9] = "-55", |
| 399 | + [RDD_IPI_HIST_10] = "inf", |
| 400 | + }; |
| 401 | + |
| 402 | + if (is_scan) { |
| 403 | + scan_data = (struct mt7915_mcu_rdd_ipi_scan *)data; |
| 404 | + tx_assert_time = scan_data->tx_assert_time; |
| 405 | + } else { |
| 406 | + ctrl_data = (struct mt7915_mcu_rdd_ipi_ctrl *)data; |
| 407 | + tx_assert_time = ctrl_data->tx_assert_time; |
| 408 | + } |
| 409 | + |
| 410 | + for (i = 0; i < antenna_num; i++) { |
| 411 | + ipi_free_count = 0; |
| 412 | + ipi_hist_count_th = 0; |
| 413 | + ipi_hist_total_count = 0; |
| 414 | + ipi_hist_data = is_scan ? scan_data->ipi_hist_val[antenna_idx] : |
| 415 | + ctrl_data->ipi_hist_val; |
| 416 | + |
| 417 | + dev_info(dev->mt76.dev, "Antenna index: %d\n", antenna_idx); |
| 418 | + for (ipi_idx = 0; ipi_idx < POWER_INDICATE_HIST_MAX; ipi_idx++) { |
| 419 | + power_lower_bound = ipi_idx ? ipi_idx_to_power_bound[ipi_idx - 1] : |
| 420 | + "-inf"; |
| 421 | + power_upper_bound = ipi_idx_to_power_bound[ipi_idx]; |
| 422 | + |
| 423 | + dev_info(dev->mt76.dev, |
| 424 | + "IPI %d (power range: (%s, %s] dBm): ipi count = %d\n", |
| 425 | + ipi_idx, power_lower_bound, |
| 426 | + power_upper_bound, ipi_hist_data[ipi_idx]); |
| 427 | + |
| 428 | + if (td->ipi_threshold <= ipi_idx && ipi_idx <= RDD_IPI_HIST_10) |
| 429 | + ipi_hist_count_th += ipi_hist_data[ipi_idx]; |
| 430 | + |
| 431 | + ipi_hist_total_count += ipi_hist_data[ipi_idx]; |
| 432 | + } |
| 433 | + ipi_free_count = is_scan ? ipi_hist_total_count : |
| 434 | + ipi_hist_data[RDD_IPI_FREE_RUN_CNT]; |
| 435 | + |
| 436 | + dev_info(dev->mt76.dev, |
| 437 | + "IPI threshold %d: ipi_hist_count_th = %d, ipi_free_count = %d\n", |
| 438 | + td->ipi_threshold, ipi_hist_count_th, ipi_free_count); |
| 439 | + dev_info(dev->mt76.dev, "TX assert time = %d [ms]\n", |
| 440 | + tx_assert_time / 1000); |
| 441 | + |
| 442 | + // Calculate channel load = (self idle ratio - idle ratio) / self idle ratio |
| 443 | + if (ipi_hist_count_th >= UINT_MAX / (100 * PRECISION)) |
| 444 | + ipi_percentage = 100 * PRECISION * |
| 445 | + (ipi_hist_count_th / (100 * PRECISION)) / |
| 446 | + (ipi_free_count / (100 * PRECISION)); |
| 447 | + else |
| 448 | + ipi_percentage = PRECISION * 100 * ipi_hist_count_th / ipi_free_count; |
| 449 | + |
| 450 | + ipi_idle_ratio = ((100 * PRECISION) - ipi_percentage) / PRECISION; |
| 451 | + |
| 452 | + self_idle_ratio = PRECISION * 100 * |
| 453 | + (td->ipi_period - (tx_assert_time / 1000)) / |
| 454 | + td->ipi_period / PRECISION; |
| 455 | + |
| 456 | + if (self_idle_ratio < ipi_idle_ratio) |
| 457 | + channel_load = 0; |
| 458 | + else |
| 459 | + channel_load = self_idle_ratio - ipi_idle_ratio; |
| 460 | + |
| 461 | + if (self_idle_ratio <= td->ipi_threshold) { |
| 462 | + dev_info(dev->mt76.dev, |
| 463 | + "band[%d]: self idle ratio = %d%%, idle ratio = %d%%\n", |
developer | 17bb0a8 | 2022-12-13 15:52:04 +0800 | [diff] [blame] | 464 | + phy->mt76->band_idx, self_idle_ratio, ipi_idle_ratio); |
developer | b403ad0 | 2022-11-08 10:16:29 +0800 | [diff] [blame] | 465 | + return; |
| 466 | + } |
| 467 | + |
| 468 | + channel_load = (100 * channel_load) / self_idle_ratio; |
| 469 | + dev_info(dev->mt76.dev, |
| 470 | + "band[%d]: chan load = %d%%, self idle ratio = %d%%, idle ratio = %d%%\n", |
developer | 17bb0a8 | 2022-12-13 15:52:04 +0800 | [diff] [blame] | 471 | + phy->mt76->band_idx, channel_load, self_idle_ratio, ipi_idle_ratio); |
developer | b403ad0 | 2022-11-08 10:16:29 +0800 | [diff] [blame] | 472 | + antenna_idx++; |
| 473 | + } |
| 474 | +} |
| 475 | + |
| 476 | +static void |
| 477 | +mt7915_tm_ipi_work(struct work_struct *work) |
| 478 | +{ |
| 479 | + struct mt7915_phy *phy = container_of(work, struct mt7915_phy, ipi_work.work); |
| 480 | + struct mt7915_dev *dev = phy->dev; |
| 481 | + struct mt76_testmode_data *td = &phy->mt76->test; |
| 482 | + u8 start_antenna_idx = 0, antenna_num = 1; |
| 483 | + |
| 484 | + if (!is_mt7915(&dev->mt76)) { |
| 485 | + struct mt7915_mcu_rdd_ipi_scan data; |
| 486 | + |
developer | 17bb0a8 | 2022-12-13 15:52:04 +0800 | [diff] [blame] | 487 | + if (phy->mt76->band_idx) |
developer | b403ad0 | 2022-11-08 10:16:29 +0800 | [diff] [blame] | 488 | + start_antenna_idx = 4; |
| 489 | + |
| 490 | + /* Use all antenna */ |
| 491 | + if (td->ipi_antenna_idx == MT76_TM_IPI_ANTENNA_ALL) |
| 492 | + antenna_num = 4; |
| 493 | + else |
| 494 | + start_antenna_idx += td->ipi_antenna_idx; |
| 495 | + |
| 496 | + mt7915_mcu_ipi_hist_scan(phy, &data, 0, true); |
| 497 | + mt7915_tm_dump_ipi(phy, &data, antenna_num, start_antenna_idx, true); |
| 498 | + } else { |
| 499 | + struct mt7915_mcu_rdd_ipi_ctrl data; |
| 500 | + |
developer | 047bc18 | 2022-11-16 12:20:48 +0800 | [diff] [blame] | 501 | + start_antenna_idx = 4; |
developer | b403ad0 | 2022-11-08 10:16:29 +0800 | [diff] [blame] | 502 | + mt7915_mcu_ipi_hist_ctrl(phy, &data, RDD_IPI_HIST_ALL_CNT, true); |
| 503 | + mt7915_tm_dump_ipi(phy, &data, antenna_num, start_antenna_idx, false); |
| 504 | + } |
| 505 | +} |
| 506 | + |
developer | 047bc18 | 2022-11-16 12:20:48 +0800 | [diff] [blame] | 507 | +static inline void |
| 508 | +mt7915_tm_reset_ipi(struct mt7915_phy *phy) |
| 509 | +{ |
| 510 | +#define IPI_RESET_BIT BIT(2) |
| 511 | + struct mt7915_dev *dev = phy->dev; |
| 512 | + |
| 513 | + if (is_mt7915(&dev->mt76)) |
| 514 | + mt7915_mcu_ipi_hist_ctrl(phy, NULL, RDD_SET_IPI_HIST_RESET, false); |
| 515 | + else |
| 516 | + mt76_set(dev, MT_WF_IPI_RESET, IPI_RESET_BIT); |
| 517 | +} |
| 518 | + |
developer | b403ad0 | 2022-11-08 10:16:29 +0800 | [diff] [blame] | 519 | +static int |
| 520 | +mt7915_tm_set_ipi(struct mt7915_phy *phy) |
| 521 | +{ |
| 522 | + struct mt76_testmode_data *td = &phy->mt76->test; |
| 523 | + |
developer | 047bc18 | 2022-11-16 12:20:48 +0800 | [diff] [blame] | 524 | + mt7915_tm_reset_ipi(phy); |
| 525 | + |
developer | b403ad0 | 2022-11-08 10:16:29 +0800 | [diff] [blame] | 526 | + cancel_delayed_work(&phy->ipi_work); |
| 527 | + ieee80211_queue_delayed_work(phy->mt76->hw, &phy->ipi_work, |
| 528 | + msecs_to_jiffies(td->ipi_period)); |
| 529 | + |
| 530 | + return 0; |
| 531 | +} |
| 532 | + |
| 533 | static int |
| 534 | mt7915_tm_set_wmm_qid(struct mt7915_phy *phy, u8 qid, u8 aifs, u8 cw_min, |
| 535 | u16 cw_max, u16 txop, u8 tx_cmd) |
developer | 1a17367 | 2023-12-21 14:49:33 +0800 | [diff] [blame] | 536 | @@ -1273,6 +1551,8 @@ mt7915_tm_init(struct mt7915_phy *phy, bool en) |
developer | b403ad0 | 2022-11-08 10:16:29 +0800 | [diff] [blame] | 537 | phy->mt76->test.tx_mpdu_len = 0; |
| 538 | phy->test.bf_en = 0; |
| 539 | mt7915_tm_set_entry(phy); |
| 540 | + } else { |
| 541 | + INIT_DELAYED_WORK(&phy->ipi_work, mt7915_tm_ipi_work); |
| 542 | } |
| 543 | } |
| 544 | |
developer | 1a17367 | 2023-12-21 14:49:33 +0800 | [diff] [blame] | 545 | @@ -2038,6 +2318,14 @@ mt7915_tm_update_params(struct mt7915_phy *phy, u32 changed) |
developer | b403ad0 | 2022-11-08 10:16:29 +0800 | [diff] [blame] | 546 | mt7915_tm_set_cfg(phy); |
| 547 | if (changed & BIT(TM_CHANGED_TXBF_ACT)) |
| 548 | mt7915_tm_set_txbf(phy); |
| 549 | + if ((changed & BIT(TM_CHANGED_OFF_CHAN_CH)) && |
| 550 | + (changed & BIT(TM_CHANGED_OFF_CHAN_BW))) |
developer | 692ed9b | 2023-06-19 12:03:50 +0800 | [diff] [blame] | 551 | + mt7915_tm_set_offchan(phy, !(changed & BIT(TM_CHANGED_OFF_CHAN_CENTER_CH))); |
developer | b403ad0 | 2022-11-08 10:16:29 +0800 | [diff] [blame] | 552 | + if ((changed & BIT(TM_CHANGED_IPI_THRESHOLD)) && |
| 553 | + (changed & BIT(TM_CHANGED_IPI_PERIOD))) |
| 554 | + mt7915_tm_set_ipi(phy); |
developer | 047bc18 | 2022-11-16 12:20:48 +0800 | [diff] [blame] | 555 | + if (changed & BIT(TM_CHANGED_IPI_RESET)) |
| 556 | + mt7915_tm_reset_ipi(phy); |
developer | b403ad0 | 2022-11-08 10:16:29 +0800 | [diff] [blame] | 557 | } |
| 558 | |
| 559 | static int |
| 560 | diff --git a/testmode.c b/testmode.c |
developer | 42c7a43 | 2024-07-12 14:39:29 +0800 | [diff] [blame^] | 561 | index 06b10a3..d8fc5d6 100644 |
developer | b403ad0 | 2022-11-08 10:16:29 +0800 | [diff] [blame] | 562 | --- a/testmode.c |
| 563 | +++ b/testmode.c |
developer | 1a17367 | 2023-12-21 14:49:33 +0800 | [diff] [blame] | 564 | @@ -26,6 +26,13 @@ const struct nla_policy mt76_tm_policy[NUM_MT76_TM_ATTRS] = { |
developer | b403ad0 | 2022-11-08 10:16:29 +0800 | [diff] [blame] | 565 | [MT76_TM_ATTR_TX_TIME] = { .type = NLA_U32 }, |
| 566 | [MT76_TM_ATTR_FREQ_OFFSET] = { .type = NLA_U32 }, |
| 567 | [MT76_TM_ATTR_DRV_DATA] = { .type = NLA_NESTED }, |
| 568 | + [MT76_TM_ATTR_OFF_CH_SCAN_CH] = { .type = NLA_U8 }, |
| 569 | + [MT76_TM_ATTR_OFF_CH_SCAN_CENTER_CH] = { .type = NLA_U8 }, |
| 570 | + [MT76_TM_ATTR_OFF_CH_SCAN_PATH] = { .type = NLA_U8 }, |
| 571 | + [MT76_TM_ATTR_IPI_THRESHOLD] = { .type = NLA_U8 }, |
| 572 | + [MT76_TM_ATTR_IPI_PERIOD] = { .type = NLA_U32 }, |
| 573 | + [MT76_TM_ATTR_IPI_ANTENNA_INDEX] = { .type = NLA_U8 }, |
developer | 047bc18 | 2022-11-16 12:20:48 +0800 | [diff] [blame] | 574 | + [MT76_TM_ATTR_IPI_RESET] = { .type = NLA_U8 }, |
developer | b403ad0 | 2022-11-08 10:16:29 +0800 | [diff] [blame] | 575 | }; |
| 576 | EXPORT_SYMBOL_GPL(mt76_tm_policy); |
| 577 | |
developer | 1a17367 | 2023-12-21 14:49:33 +0800 | [diff] [blame] | 578 | @@ -407,6 +414,7 @@ mt76_testmode_init_defaults(struct mt76_phy *phy) |
developer | b403ad0 | 2022-11-08 10:16:29 +0800 | [diff] [blame] | 579 | td->tx_count = 1; |
| 580 | td->tx_rate_mode = MT76_TM_TX_MODE_OFDM; |
| 581 | td->tx_rate_nss = 1; |
| 582 | + td->ipi_antenna_idx = MT76_TM_IPI_ANTENNA_ALL; |
| 583 | |
| 584 | memcpy(td->addr[0], phy->macaddr, ETH_ALEN); |
| 585 | memcpy(td->addr[1], phy->macaddr, ETH_ALEN); |
developer | 1a17367 | 2023-12-21 14:49:33 +0800 | [diff] [blame] | 586 | @@ -615,6 +623,9 @@ int mt76_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif, |
developer | b403ad0 | 2022-11-08 10:16:29 +0800 | [diff] [blame] | 587 | if (tb[MT76_TM_ATTR_TX_RATE_IDX]) |
| 588 | td->tx_rate_idx = nla_get_u8(tb[MT76_TM_ATTR_TX_RATE_IDX]); |
| 589 | |
| 590 | + if (tb[MT76_TM_ATTR_IPI_PERIOD]) |
| 591 | + td->ipi_period = nla_get_u32(tb[MT76_TM_ATTR_IPI_PERIOD]); |
| 592 | + |
| 593 | if (mt76_tm_get_u8(tb[MT76_TM_ATTR_TX_RATE_MODE], &td->tx_rate_mode, |
| 594 | 0, MT76_TM_TX_MODE_MAX) || |
| 595 | mt76_tm_get_u8(tb[MT76_TM_ATTR_TX_RATE_NSS], &td->tx_rate_nss, |
developer | 1a17367 | 2023-12-21 14:49:33 +0800 | [diff] [blame] | 596 | @@ -631,7 +642,16 @@ int mt76_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif, |
developer | b403ad0 | 2022-11-08 10:16:29 +0800 | [diff] [blame] | 597 | &td->tx_power_control, 0, 1) || |
| 598 | mt76_tm_get_u8(tb[MT76_TM_ATTR_AID], &td->aid, 0, 16) || |
| 599 | mt76_tm_get_u8(tb[MT76_TM_ATTR_RU_ALLOC], &td->ru_alloc, 0, 0xff) || |
| 600 | - mt76_tm_get_u8(tb[MT76_TM_ATTR_RU_IDX], &td->ru_idx, 0, 68)) |
| 601 | + mt76_tm_get_u8(tb[MT76_TM_ATTR_RU_IDX], &td->ru_idx, 0, 68) || |
| 602 | + mt76_tm_get_u8(tb[MT76_TM_ATTR_OFF_CH_SCAN_CH], &td->offchan_ch, 36, 196) || |
| 603 | + mt76_tm_get_u8(tb[MT76_TM_ATTR_OFF_CH_SCAN_CENTER_CH], &td->offchan_center_ch, |
| 604 | + 36, 196) || |
| 605 | + mt76_tm_get_u8(tb[MT76_TM_ATTR_OFF_CH_SCAN_BW], |
| 606 | + &td->offchan_bw, NL80211_CHAN_WIDTH_20_NOHT, NL80211_CHAN_WIDTH_160) || |
| 607 | + mt76_tm_get_u8(tb[MT76_TM_ATTR_IPI_THRESHOLD], &td->ipi_threshold, 0, 10) || |
| 608 | + mt76_tm_get_u8(tb[MT76_TM_ATTR_IPI_ANTENNA_INDEX], &td->ipi_antenna_idx, |
developer | 047bc18 | 2022-11-16 12:20:48 +0800 | [diff] [blame] | 609 | + MT76_TM_IPI_ANTENNA_0, MT76_TM_IPI_ANTENNA_ALL) || |
| 610 | + mt76_tm_get_u8(tb[MT76_TM_ATTR_IPI_RESET], &td->ipi_reset, 0, 1)) |
developer | b403ad0 | 2022-11-08 10:16:29 +0800 | [diff] [blame] | 611 | goto out; |
| 612 | |
| 613 | if (tb[MT76_TM_ATTR_TX_LENGTH]) { |
developer | 42c7a43 | 2024-07-12 14:39:29 +0800 | [diff] [blame^] | 614 | @@ -868,6 +888,9 @@ int mt76_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *msg, |
developer | b403ad0 | 2022-11-08 10:16:29 +0800 | [diff] [blame] | 615 | nla_put_u8(msg, MT76_TM_ATTR_TX_RATE_MODE, td->tx_rate_mode) || |
| 616 | nla_put_u8(msg, MT76_TM_ATTR_TX_RATE_SGI, td->tx_rate_sgi) || |
| 617 | nla_put_u8(msg, MT76_TM_ATTR_TX_RATE_STBC, td->tx_rate_stbc) || |
| 618 | + nla_put_u8(msg, MT76_TM_ATTR_OFF_CH_SCAN_CH, td->offchan_ch) || |
| 619 | + nla_put_u8(msg, MT76_TM_ATTR_OFF_CH_SCAN_CENTER_CH, td->offchan_center_ch) || |
| 620 | + nla_put_u8(msg, MT76_TM_ATTR_OFF_CH_SCAN_BW, td->offchan_bw) || |
| 621 | (mt76_testmode_param_present(td, MT76_TM_ATTR_TX_LTF) && |
| 622 | nla_put_u8(msg, MT76_TM_ATTR_TX_LTF, td->tx_ltf)) || |
| 623 | (mt76_testmode_param_present(td, MT76_TM_ATTR_TX_ANTENNA) && |
| 624 | diff --git a/testmode.h b/testmode.h |
developer | dc9eeae | 2024-04-08 14:36:46 +0800 | [diff] [blame] | 625 | index 1d7aef8..b39cf51 100644 |
developer | b403ad0 | 2022-11-08 10:16:29 +0800 | [diff] [blame] | 626 | --- a/testmode.h |
| 627 | +++ b/testmode.h |
developer | 1a17367 | 2023-12-21 14:49:33 +0800 | [diff] [blame] | 628 | @@ -64,6 +64,20 @@ |
developer | 692ed9b | 2023-06-19 12:03:50 +0800 | [diff] [blame] | 629 | * (nested, u8 attrs) |
developer | b403ad0 | 2022-11-08 10:16:29 +0800 | [diff] [blame] | 630 | * |
| 631 | * @MT76_TM_ATTR_CFG: config testmode rf feature (nested, see &mt76_testmode_cfg) |
| 632 | + * @MT76_TM_ATTR_TXBF_ACT: txbf setting actions (u8) |
| 633 | + * @MT76_TM_ATTR_TXBF_PARAM: txbf parameters (nested) |
| 634 | + * |
| 635 | + * @MT76_TM_ATTR_OFF_CH_SCAN_CH: config the channel of background chain (ZWDFS) (u8) |
| 636 | + * @MT76_TM_ATTR_OFF_CH_SCAN_CENTER_CH: config the center channel of background chain (ZWDFS) (u8) |
| 637 | + * @MT76_TM_ATTR_OFF_CH_SCAN_BW: config the bandwidth of background chain (ZWDFS) (u8) |
| 638 | + * @MT76_TM_ATTR_OFF_CH_SCAN_PATH: config the tx path of background chain (ZWDFS) (u8) |
| 639 | + * |
| 640 | + * @MT76_TM_ATTR_IPI_THRESHOLD: config the IPI index you want to read (u8) |
| 641 | + * @MT76_TM_ATTR_IPI_PERIOD: config the time period for reading |
| 642 | + * the histogram of specific IPI index (u8) |
| 643 | + * @MT76_TM_ATTR_IPI_ANTENNA_INDEX: config the antenna index for reading |
| 644 | + * the histogram of specific IPI index (u8) |
developer | 047bc18 | 2022-11-16 12:20:48 +0800 | [diff] [blame] | 645 | + * @MT76_TM_ATTR_IPI_RESET: Reset the IPI counter |
developer | b403ad0 | 2022-11-08 10:16:29 +0800 | [diff] [blame] | 646 | * |
| 647 | */ |
| 648 | enum mt76_testmode_attr { |
developer | 1a17367 | 2023-12-21 14:49:33 +0800 | [diff] [blame] | 649 | @@ -118,6 +132,16 @@ enum mt76_testmode_attr { |
developer | b403ad0 | 2022-11-08 10:16:29 +0800 | [diff] [blame] | 650 | MT76_TM_ATTR_TXBF_ACT, |
| 651 | MT76_TM_ATTR_TXBF_PARAM, |
| 652 | |
| 653 | + MT76_TM_ATTR_OFF_CH_SCAN_CH, |
| 654 | + MT76_TM_ATTR_OFF_CH_SCAN_CENTER_CH, |
| 655 | + MT76_TM_ATTR_OFF_CH_SCAN_BW, |
| 656 | + MT76_TM_ATTR_OFF_CH_SCAN_PATH, |
| 657 | + |
| 658 | + MT76_TM_ATTR_IPI_THRESHOLD, |
| 659 | + MT76_TM_ATTR_IPI_PERIOD, |
| 660 | + MT76_TM_ATTR_IPI_ANTENNA_INDEX, |
developer | 047bc18 | 2022-11-16 12:20:48 +0800 | [diff] [blame] | 661 | + MT76_TM_ATTR_IPI_RESET, |
developer | b403ad0 | 2022-11-08 10:16:29 +0800 | [diff] [blame] | 662 | + |
| 663 | /* keep last */ |
| 664 | NUM_MT76_TM_ATTRS, |
| 665 | MT76_TM_ATTR_MAX = NUM_MT76_TM_ATTRS - 1, |
developer | 1a17367 | 2023-12-21 14:49:33 +0800 | [diff] [blame] | 666 | @@ -296,4 +320,25 @@ enum mt76_testmode_txbf_act { |
developer | b403ad0 | 2022-11-08 10:16:29 +0800 | [diff] [blame] | 667 | MT76_TM_TXBF_ACT_MAX = NUM_MT76_TM_TXBF_ACT - 1, |
| 668 | }; |
| 669 | |
| 670 | +/** |
| 671 | + * enum mt76_testmode_ipi_antenna - specify antenna index for ipi count |
| 672 | + * |
| 673 | + * @MT76_TM_IPI_ANTENNA_0: use antenna 0 |
| 674 | + * @MT76_TM_IPI_ANTENNA_1: use antenna 1 |
| 675 | + * @MT76_TM_IPI_ANTENNA_2: use antenna 2 |
| 676 | + * @MT76_TM_IPI_ANTENNA_3: use antenna 3 |
| 677 | + * @MT76_TM_IPI_ANTENNA_ALL: use all antenna |
| 678 | + */ |
| 679 | +enum mt76_testmode_ipi_antenna { |
| 680 | + MT76_TM_IPI_ANTENNA_0, |
| 681 | + MT76_TM_IPI_ANTENNA_1, |
| 682 | + MT76_TM_IPI_ANTENNA_2, |
| 683 | + MT76_TM_IPI_ANTENNA_3, |
| 684 | + MT76_TM_IPI_ANTENNA_ALL, |
| 685 | + |
| 686 | + /* keep last */ |
| 687 | + NUM_MT76_TM_IPI_ANTENNA, |
| 688 | + MT76_TM_IPI_ANTENNA_MAX = NUM_MT76_TM_IPI_ANTENNA - 1, |
| 689 | +}; |
| 690 | + |
| 691 | #endif |
| 692 | diff --git a/tools/fields.c b/tools/fields.c |
developer | dc9eeae | 2024-04-08 14:36:46 +0800 | [diff] [blame] | 693 | index b0ee84d..e2cf4b9 100644 |
developer | b403ad0 | 2022-11-08 10:16:29 +0800 | [diff] [blame] | 694 | --- a/tools/fields.c |
| 695 | +++ b/tools/fields.c |
| 696 | @@ -46,6 +46,14 @@ static const char * const testmode_txbf_act[] = { |
| 697 | [MT76_TM_TXBF_ACT_E2P_UPDATE] = "e2p_update", |
| 698 | }; |
| 699 | |
| 700 | +static const char * const testmode_offchan_bw[] = { |
| 701 | + [NL80211_CHAN_WIDTH_20_NOHT] = "NOHT", |
| 702 | + [NL80211_CHAN_WIDTH_20] = "20", |
| 703 | + [NL80211_CHAN_WIDTH_40] = "40", |
| 704 | + [NL80211_CHAN_WIDTH_80] = "80", |
| 705 | + [NL80211_CHAN_WIDTH_160] = "160", |
| 706 | +}; |
| 707 | + |
| 708 | static void print_enum(const struct tm_field *field, struct nlattr *attr) |
| 709 | { |
| 710 | unsigned int i = nla_get_u8(attr); |
developer | 1a17367 | 2023-12-21 14:49:33 +0800 | [diff] [blame] | 711 | @@ -414,6 +422,13 @@ static const struct tm_field testdata_fields[NUM_MT76_TM_ATTRS] = { |
developer | b403ad0 | 2022-11-08 10:16:29 +0800 | [diff] [blame] | 712 | FIELD(u8, RU_IDX, "ru_idx"), |
| 713 | FIELD_ENUM(TXBF_ACT, "txbf_act", testmode_txbf_act), |
| 714 | FIELD_ARRAY(u16_hex, TXBF_PARAM, "txbf_param"), |
| 715 | + FIELD(u8, OFF_CH_SCAN_CH, "offchan_ch"), |
| 716 | + FIELD(u8, OFF_CH_SCAN_CENTER_CH, "offchan_center_ch"), |
| 717 | + FIELD_ENUM(OFF_CH_SCAN_BW, "offchan_bw", testmode_offchan_bw), |
| 718 | + FIELD(u8, IPI_THRESHOLD, "ipi_threshold"), |
| 719 | + FIELD(u32, IPI_PERIOD, "ipi_period"), |
| 720 | + FIELD(u8, IPI_ANTENNA_INDEX, "ipi_antenna_idx"), |
developer | 047bc18 | 2022-11-16 12:20:48 +0800 | [diff] [blame] | 721 | + FIELD(u8, IPI_RESET, "ipi_reset"), |
developer | b403ad0 | 2022-11-08 10:16:29 +0800 | [diff] [blame] | 722 | FIELD_MAC(MAC_ADDRS, "mac_addrs"), |
| 723 | FIELD_NESTED_RO(STATS, stats, "", |
| 724 | .print_extra = print_extra_stats), |
developer | 1a17367 | 2023-12-21 14:49:33 +0800 | [diff] [blame] | 725 | @@ -446,6 +461,13 @@ static struct nla_policy testdata_policy[NUM_MT76_TM_ATTRS] = { |
developer | b403ad0 | 2022-11-08 10:16:29 +0800 | [diff] [blame] | 726 | [MT76_TM_ATTR_RU_IDX] = { .type = NLA_U8 }, |
| 727 | [MT76_TM_ATTR_STATS] = { .type = NLA_NESTED }, |
| 728 | [MT76_TM_ATTR_TXBF_ACT] = { .type = NLA_U8 }, |
| 729 | + [MT76_TM_ATTR_OFF_CH_SCAN_CH] = { .type = NLA_U8 }, |
| 730 | + [MT76_TM_ATTR_OFF_CH_SCAN_CENTER_CH] = { .type = NLA_U8 }, |
| 731 | + [MT76_TM_ATTR_OFF_CH_SCAN_BW] = { .type = NLA_U8 }, |
| 732 | + [MT76_TM_ATTR_IPI_THRESHOLD] = { .type = NLA_U8 }, |
| 733 | + [MT76_TM_ATTR_IPI_PERIOD] = { .type = NLA_U32 }, |
| 734 | + [MT76_TM_ATTR_IPI_ANTENNA_INDEX] = { .type = NLA_U8 }, |
developer | 047bc18 | 2022-11-16 12:20:48 +0800 | [diff] [blame] | 735 | + [MT76_TM_ATTR_IPI_RESET] = { .type = NLA_U8 }, |
developer | b403ad0 | 2022-11-08 10:16:29 +0800 | [diff] [blame] | 736 | }; |
| 737 | |
| 738 | const struct tm_field msg_field = { |
| 739 | -- |
developer | bd9fa1e | 2023-10-16 11:04:00 +0800 | [diff] [blame] | 740 | 2.18.0 |
developer | b403ad0 | 2022-11-08 10:16:29 +0800 | [diff] [blame] | 741 | |