developer | 7b18d4c | 2021-12-09 15:24:27 +0800 | [diff] [blame] | 1 | diff --git a/package/kernel/mt76/patches/1005-mt76-zero-wait-dfs.patch b/package/kernel/mt76/patches/1005-mt76-zero-wait-dfs.patch |
| 2 | new file mode 100644 |
| 3 | index 0000000..68883e4 |
| 4 | --- /dev/null |
| 5 | +++ b/package/kernel/mt76/patches/1005-mt76-zero-wait-dfs.patch |
| 6 | @@ -0,0 +1,369 @@ |
| 7 | +diff --git a/mt7915/debugfs.c b/mt7915/debugfs.c |
| 8 | +index 3a0ec43..2ce6973 100644 |
| 9 | +--- a/mt7915/debugfs.c |
| 10 | ++++ b/mt7915/debugfs.c |
| 11 | +@@ -75,12 +75,62 @@ mt7915_radar_trigger(void *data, u64 val) |
| 12 | + { |
| 13 | + struct mt7915_dev *dev = data; |
| 14 | + |
| 15 | +- return mt7915_mcu_rdd_cmd(dev, RDD_RADAR_EMULATE, 1, 0, 0); |
| 16 | ++ if (val > MT_RX_SEL2) |
| 17 | ++ return -EINVAL; |
| 18 | ++ |
| 19 | ++ return mt7915_mcu_rdd_cmd(dev, RDD_RADAR_EMULATE, val, 0, 0); |
| 20 | + } |
| 21 | + |
| 22 | + DEFINE_DEBUGFS_ATTRIBUTE(fops_radar_trigger, NULL, |
| 23 | + mt7915_radar_trigger, "%lld\n"); |
| 24 | + |
| 25 | ++static int |
| 26 | ++mt7915_rdd_monitor(struct seq_file *s, void *data) |
| 27 | ++{ |
| 28 | ++ struct mt7915_dev *dev = dev_get_drvdata(s->private); |
| 29 | ++ struct cfg80211_chan_def *chandef = &dev->rdd2_chandef; |
| 30 | ++ const char *bw; |
| 31 | ++ int ret = 0; |
| 32 | ++ |
| 33 | ++ mutex_lock(&dev->mt76.mutex); |
| 34 | ++ |
| 35 | ++ if (!cfg80211_chandef_valid(chandef)) { |
| 36 | ++ ret = -EINVAL; |
| 37 | ++ goto out; |
| 38 | ++ } |
| 39 | ++ |
| 40 | ++ if (!dev->rdd2_phy) { |
| 41 | ++ seq_printf(s, "not running\n"); |
| 42 | ++ goto out; |
| 43 | ++ } |
| 44 | ++ |
| 45 | ++ switch (chandef->width) { |
| 46 | ++ case NL80211_CHAN_WIDTH_40: |
| 47 | ++ bw = "40"; |
| 48 | ++ break; |
| 49 | ++ case NL80211_CHAN_WIDTH_80: |
| 50 | ++ bw = "80"; |
| 51 | ++ break; |
| 52 | ++ case NL80211_CHAN_WIDTH_160: |
| 53 | ++ bw = "160"; |
| 54 | ++ break; |
| 55 | ++ case NL80211_CHAN_WIDTH_80P80: |
| 56 | ++ bw = "80P80"; |
| 57 | ++ break; |
| 58 | ++ default: |
| 59 | ++ bw = "20"; |
| 60 | ++ break; |
| 61 | ++ } |
| 62 | ++ |
| 63 | ++ seq_printf(s, "channel %d (%d MHz) width %s MHz center1: %d MHz\n", |
| 64 | ++ chandef->chan->hw_value, chandef->chan->center_freq, |
| 65 | ++ bw, chandef->center_freq1); |
| 66 | ++out: |
| 67 | ++ mutex_unlock(&dev->mt76.mutex); |
| 68 | ++ |
| 69 | ++ return ret; |
| 70 | ++} |
| 71 | ++ |
| 72 | + static int |
| 73 | + mt7915_fw_debug_wm_set(void *data, u64 val) |
| 74 | + { |
| 75 | +@@ -552,6 +602,8 @@ int mt7915_init_debugfs(struct mt7915_phy *phy) |
| 76 | + &dev->hw_pattern); |
| 77 | + debugfs_create_file("radar_trigger", 0200, dir, dev, |
| 78 | + &fops_radar_trigger); |
| 79 | ++ debugfs_create_devm_seqfile(dev->mt76.dev, "rdd_monitor", dir, |
| 80 | ++ mt7915_rdd_monitor); |
| 81 | + } |
| 82 | + |
| 83 | + #ifdef MTK_DEBUG |
| 84 | +diff --git a/mt7915/init.c b/mt7915/init.c |
| 85 | +index e32cefc..6767702 100644 |
| 86 | +--- a/mt7915/init.c |
| 87 | ++++ b/mt7915/init.c |
| 88 | +@@ -294,6 +294,9 @@ mt7915_regd_notifier(struct wiphy *wiphy, |
| 89 | + memcpy(dev->mt76.alpha2, request->alpha2, sizeof(dev->mt76.alpha2)); |
| 90 | + dev->mt76.region = request->dfs_region; |
| 91 | + |
| 92 | ++ if (dev->mt76.region == NL80211_DFS_UNSET) |
| 93 | ++ mt7915_mcu_rdd_offchan_enable(phy, NULL); |
| 94 | ++ |
| 95 | + mt7915_init_txpower(dev, &mphy->sband_2g.sband); |
| 96 | + mt7915_init_txpower(dev, &mphy->sband_5g.sband); |
| 97 | + |
| 98 | +@@ -307,6 +310,7 @@ static void |
| 99 | + mt7915_init_wiphy(struct ieee80211_hw *hw) |
| 100 | + { |
| 101 | + struct mt7915_phy *phy = mt7915_hw_phy(hw); |
| 102 | ++ struct mt76_dev *mdev = &phy->dev->mt76; |
| 103 | + struct wiphy *wiphy = hw->wiphy; |
| 104 | + |
| 105 | + hw->queues = 4; |
| 106 | +@@ -334,6 +338,12 @@ mt7915_init_wiphy(struct ieee80211_hw *hw) |
| 107 | + wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_VHT); |
| 108 | + wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_HE); |
| 109 | + |
| 110 | ++ if (!mdev->dev->of_node || |
| 111 | ++ !of_property_read_bool(mdev->dev->of_node, |
| 112 | ++ "mediatek,disable-radar-offchan")) |
| 113 | ++ wiphy_ext_feature_set(wiphy, |
| 114 | ++ NL80211_EXT_FEATURE_RADAR_OFFCHAN); |
| 115 | ++ |
| 116 | + ieee80211_hw_set(hw, HAS_RATE_CONTROL); |
| 117 | + ieee80211_hw_set(hw, SUPPORTS_TX_ENCAP_OFFLOAD); |
| 118 | + ieee80211_hw_set(hw, SUPPORTS_RX_DECAP_OFFLOAD); |
| 119 | +diff --git a/mt7915/main.c b/mt7915/main.c |
| 120 | +index 31efe2c..c9dba1f 100644 |
| 121 | +--- a/mt7915/main.c |
| 122 | ++++ b/mt7915/main.c |
| 123 | +@@ -1312,6 +1312,55 @@ mt7915_twt_teardown_request(struct ieee80211_hw *hw, |
| 124 | + mutex_unlock(&dev->mt76.mutex); |
| 125 | + } |
| 126 | + |
| 127 | ++static int |
| 128 | ++mt7915_set_radar_offchan(struct ieee80211_hw *hw, |
| 129 | ++ struct cfg80211_chan_def *chandef) |
| 130 | ++{ |
| 131 | ++ struct mt7915_phy *phy = mt7915_hw_phy(hw); |
| 132 | ++ struct mt7915_dev *dev = phy->dev; |
| 133 | ++ int ret = -EINVAL; |
| 134 | ++ bool running; |
| 135 | ++ |
| 136 | ++ mutex_lock(&dev->mt76.mutex); |
| 137 | ++ |
| 138 | ++ if (dev->mt76.region == NL80211_DFS_UNSET) |
| 139 | ++ goto out; |
| 140 | ++ |
| 141 | ++ if (dev->rdd2_phy && dev->rdd2_phy != phy) { |
| 142 | ++ /* rdd2 is already locked */ |
| 143 | ++ ret = -EBUSY; |
| 144 | ++ goto out; |
| 145 | ++ } |
| 146 | ++ |
| 147 | ++ /* rdd2 already configured on a radar channel */ |
| 148 | ++ running = dev->rdd2_phy && |
| 149 | ++ cfg80211_chandef_valid(&dev->rdd2_chandef) && |
| 150 | ++ !!(dev->rdd2_chandef.chan->flags & IEEE80211_CHAN_RADAR); |
| 151 | ++ |
| 152 | ++ if (!chandef || running || |
| 153 | ++ !(chandef->chan->flags & IEEE80211_CHAN_RADAR)) { |
| 154 | ++ ret = mt7915_mcu_rdd_offchan_enable(phy, NULL); |
| 155 | ++ if (ret) |
| 156 | ++ goto out; |
| 157 | ++ |
| 158 | ++ if (!running) |
| 159 | ++ goto update_phy; |
| 160 | ++ } |
| 161 | ++ |
| 162 | ++ ret = mt7915_mcu_rdd_offchan_enable(phy, chandef); |
| 163 | ++ if (ret) |
| 164 | ++ goto out; |
| 165 | ++ |
| 166 | ++update_phy: |
| 167 | ++ dev->rdd2_phy = chandef ? phy : NULL; |
| 168 | ++ if (chandef) |
| 169 | ++ dev->rdd2_chandef = *chandef; |
| 170 | ++out: |
| 171 | ++ mutex_unlock(&dev->mt76.mutex); |
| 172 | ++ |
| 173 | ++ return ret; |
| 174 | ++} |
| 175 | ++ |
| 176 | + const struct ieee80211_ops mt7915_ops = { |
| 177 | + .tx = mt7915_tx, |
| 178 | + .start = mt7915_start, |
| 179 | +@@ -1357,4 +1406,5 @@ const struct ieee80211_ops mt7915_ops = { |
| 180 | + #ifdef CONFIG_MAC80211_DEBUGFS |
| 181 | + .sta_add_debugfs = mt7915_sta_add_debugfs, |
| 182 | + #endif |
| 183 | ++ .set_radar_offchan = mt7915_set_radar_offchan, |
| 184 | + }; |
| 185 | +diff --git a/mt7915/mcu.c b/mt7915/mcu.c |
| 186 | +index a5fb821..b361f68 100644 |
| 187 | +--- a/mt7915/mcu.c |
| 188 | ++++ b/mt7915/mcu.c |
| 189 | +@@ -487,7 +487,12 @@ mt7915_mcu_rx_radar_detected(struct mt7915_dev *dev, struct sk_buff *skb) |
| 190 | + if (r->band_idx && dev->mt76.phy2) |
| 191 | + mphy = dev->mt76.phy2; |
| 192 | + |
| 193 | +- ieee80211_radar_detected(mphy->hw); |
| 194 | ++ if (r->band_idx == MT_RX_SEL2) |
| 195 | ++ cfg80211_offchan_radar_event(mphy->hw->wiphy, |
| 196 | ++ &dev->rdd2_chandef, |
| 197 | ++ GFP_ATOMIC); |
| 198 | ++ else |
| 199 | ++ ieee80211_radar_detected(mphy->hw); |
| 200 | + dev->hw_pattern++; |
| 201 | + } |
| 202 | + |
| 203 | +@@ -3409,6 +3414,97 @@ int mt7915_mcu_set_radar_th(struct mt7915_dev *dev, int index, |
| 204 | + sizeof(req), true); |
| 205 | + } |
| 206 | + |
| 207 | ++static int |
| 208 | ++mt7915_mcu_offchan_chain_ctrl(struct mt7915_phy *phy, |
| 209 | ++ struct cfg80211_chan_def *chandef, |
| 210 | ++ int cmd) |
| 211 | ++{ |
| 212 | ++ struct mt7915_dev *dev = phy->dev; |
| 213 | ++ struct mt76_phy *mphy = phy->mt76; |
| 214 | ++ struct ieee80211_channel *chan = mphy->chandef.chan; |
| 215 | ++ int freq = mphy->chandef.center_freq1; |
| 216 | ++ struct mt7915_mcu_offchan_chain_ctrl req = { |
| 217 | ++ .monitor_scan_type = 2, /* simple rx */ |
| 218 | ++ }; |
| 219 | ++ |
| 220 | ++ if (!chandef && cmd != CH_SWITCH_BACKGROUND_SCAN_STOP) |
| 221 | ++ return -EINVAL; |
| 222 | ++ |
| 223 | ++ if (!cfg80211_chandef_valid(&mphy->chandef)) |
| 224 | ++ return -EINVAL; |
| 225 | ++ |
| 226 | ++ switch (cmd) { |
| 227 | ++ case CH_SWITCH_BACKGROUND_SCAN_START: { |
| 228 | ++ req.chan = chan->hw_value; |
| 229 | ++ req.central_chan = ieee80211_frequency_to_channel(freq); |
| 230 | ++ req.bw = mt7915_mcu_chan_bw(&mphy->chandef); |
| 231 | ++ req.monitor_chan = chandef->chan->hw_value; |
| 232 | ++ req.monitor_central_chan = |
| 233 | ++ ieee80211_frequency_to_channel(chandef->center_freq1); |
| 234 | ++ req.monitor_bw = mt7915_mcu_chan_bw(chandef); |
| 235 | ++ req.band_idx = phy != &dev->phy; |
| 236 | ++ req.scan_mode = 1; |
| 237 | ++ break; |
| 238 | ++ } |
| 239 | ++ case CH_SWITCH_BACKGROUND_SCAN_RUNNING: |
| 240 | ++ req.monitor_chan = chandef->chan->hw_value; |
| 241 | ++ req.monitor_central_chan = |
| 242 | ++ ieee80211_frequency_to_channel(chandef->center_freq1); |
| 243 | ++ req.band_idx = phy != &dev->phy; |
| 244 | ++ req.scan_mode = 2; |
| 245 | ++ break; |
| 246 | ++ case CH_SWITCH_BACKGROUND_SCAN_STOP: |
| 247 | ++ req.chan = chan->hw_value; |
| 248 | ++ req.central_chan = ieee80211_frequency_to_channel(freq); |
| 249 | ++ req.bw = mt7915_mcu_chan_bw(&mphy->chandef); |
| 250 | ++ req.tx_stream = hweight8(mphy->antenna_mask); |
| 251 | ++ req.rx_stream = mphy->antenna_mask; |
| 252 | ++ break; |
| 253 | ++ default: |
| 254 | ++ return -EINVAL; |
| 255 | ++ } |
| 256 | ++ req.band = chandef ? chandef->chan->band == NL80211_BAND_5GHZ : 1; |
| 257 | ++ |
| 258 | ++ return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(OFFCH_SCAN_CTRL), |
| 259 | ++ &req, sizeof(req), false); |
| 260 | ++} |
| 261 | ++ |
| 262 | ++int mt7915_mcu_rdd_offchan_enable(struct mt7915_phy *phy, |
| 263 | ++ struct cfg80211_chan_def *chandef) |
| 264 | ++{ |
| 265 | ++ struct mt7915_dev *dev = phy->dev; |
| 266 | ++ int err, region; |
| 267 | ++ |
| 268 | ++ if (!chandef) { /* disable offchain */ |
| 269 | ++ err = mt7915_mcu_rdd_cmd(dev, RDD_STOP, MT_RX_SEL2, 0, 0); |
| 270 | ++ if (err) |
| 271 | ++ return err; |
| 272 | ++ |
| 273 | ++ return mt7915_mcu_offchan_chain_ctrl(phy, NULL, |
| 274 | ++ CH_SWITCH_BACKGROUND_SCAN_STOP); |
| 275 | ++ } |
| 276 | ++ |
| 277 | ++ err = mt7915_mcu_offchan_chain_ctrl(phy, chandef, |
| 278 | ++ CH_SWITCH_BACKGROUND_SCAN_START); |
| 279 | ++ if (err) |
| 280 | ++ return err; |
| 281 | ++ |
| 282 | ++ switch (dev->mt76.region) { |
| 283 | ++ case NL80211_DFS_ETSI: |
| 284 | ++ region = 0; |
| 285 | ++ break; |
| 286 | ++ case NL80211_DFS_JP: |
| 287 | ++ region = 2; |
| 288 | ++ break; |
| 289 | ++ case NL80211_DFS_FCC: |
| 290 | ++ default: |
| 291 | ++ region = 1; |
| 292 | ++ break; |
| 293 | ++ } |
| 294 | ++ |
| 295 | ++ return mt7915_mcu_rdd_cmd(dev, RDD_START, MT_RX_SEL2, 0, region); |
| 296 | ++} |
| 297 | ++ |
| 298 | + int mt7915_mcu_set_chan_info(struct mt7915_phy *phy, int cmd) |
| 299 | + { |
| 300 | + struct mt7915_dev *dev = phy->dev; |
| 301 | +diff --git a/mt7915/mcu.h b/mt7915/mcu.h |
| 302 | +index 2f856ae..64bea9a 100644 |
| 303 | +--- a/mt7915/mcu.h |
| 304 | ++++ b/mt7915/mcu.h |
| 305 | +@@ -153,6 +153,29 @@ struct mt7915_mcu_rdd_report { |
| 306 | + } hw_pulse[32]; |
| 307 | + } __packed; |
| 308 | + |
| 309 | ++struct mt7915_mcu_offchan_chain_ctrl { |
| 310 | ++ u8 chan; /* primary channel */ |
| 311 | ++ u8 central_chan; /* central channel */ |
| 312 | ++ u8 bw; |
| 313 | ++ u8 tx_stream; |
| 314 | ++ u8 rx_stream; |
| 315 | ++ |
| 316 | ++ u8 monitor_chan; /* monitor channel */ |
| 317 | ++ u8 monitor_central_chan;/* monitor central channel */ |
| 318 | ++ u8 monitor_bw; |
| 319 | ++ u8 monitor_tx_stream; |
| 320 | ++ u8 monitor_rx_stream; |
| 321 | ++ |
| 322 | ++ u8 scan_mode; /* 0: ScanStop |
| 323 | ++ * 1: ScanStart |
| 324 | ++ * 2: ScanRunning |
| 325 | ++ */ |
| 326 | ++ u8 band_idx; /* DBDC */ |
| 327 | ++ u8 monitor_scan_type; |
| 328 | ++ u8 band; /* 0: 2.4GHz, 1: 5GHz */ |
| 329 | ++ u8 rsv[2]; |
| 330 | ++} __packed; |
| 331 | ++ |
| 332 | + struct mt7915_mcu_eeprom { |
| 333 | + u8 buffer_mode; |
| 334 | + u8 format; |
| 335 | +@@ -286,6 +309,7 @@ enum { |
| 336 | + MCU_EXT_CMD_SCS_CTRL = 0x82, |
| 337 | + MCU_EXT_CMD_TWT_AGRT_UPDATE = 0x94, |
| 338 | + MCU_EXT_CMD_FW_DBG_CTRL = 0x95, |
| 339 | ++ MCU_EXT_CMD_OFFCH_SCAN_CTRL = 0x9a, |
| 340 | + MCU_EXT_CMD_SET_RDD_TH = 0x9d, |
| 341 | + MCU_EXT_CMD_MURU_CTRL = 0x9f, |
| 342 | + MCU_EXT_CMD_SET_SPR = 0xa8, |
| 343 | +diff --git a/mt7915/mt7915.h b/mt7915/mt7915.h |
| 344 | +index 27dcd3f..f3449eb 100644 |
| 345 | +--- a/mt7915/mt7915.h |
| 346 | ++++ b/mt7915/mt7915.h |
| 347 | +@@ -298,6 +298,10 @@ struct mt7915_dev { |
| 348 | + struct tasklet_struct irq_tasklet; |
| 349 | + struct mt7915_phy phy; |
| 350 | + |
| 351 | ++ /* monitor rx chain configured channel */ |
| 352 | ++ struct cfg80211_chan_def rdd2_chandef; |
| 353 | ++ struct mt7915_phy *rdd2_phy; |
| 354 | ++ |
| 355 | + u16 chainmask; |
| 356 | + u32 hif_idx; |
| 357 | + |
| 358 | +@@ -379,6 +383,7 @@ enum { |
| 359 | + enum { |
| 360 | + MT_RX_SEL0, |
| 361 | + MT_RX_SEL1, |
| 362 | ++ MT_RX_SEL2, /* monitor chain */ |
| 363 | + }; |
| 364 | + |
| 365 | + enum mt7915_rdd_cmd { |
| 366 | +@@ -516,6 +521,8 @@ int mt7915_mcu_get_rx_rate(struct mt7915_phy *phy, struct ieee80211_vif *vif, |
| 367 | + struct ieee80211_sta *sta, struct rate_info *rate); |
| 368 | + int mt7915_mcu_rdd_cmd(struct mt7915_dev *dev, enum mt7915_rdd_cmd cmd, |
| 369 | + u8 index, u8 rx_sel, u8 val); |
| 370 | ++int mt7915_mcu_rdd_offchan_enable(struct mt7915_phy *phy, |
| 371 | ++ struct cfg80211_chan_def *chandef); |
| 372 | + int mt7915_mcu_wa_cmd(struct mt7915_dev *dev, int cmd, u32 a1, u32 a2, u32 a3); |
| 373 | + int mt7915_mcu_fw_log_2_host(struct mt7915_dev *dev, u8 type, u8 ctrl); |
| 374 | + int mt7915_mcu_fw_dbg_ctrl(struct mt7915_dev *dev, u32 module, u8 level); |
| 375 | + |