Commit 4606a26c authored by Felix Fietkau's avatar Felix Fietkau

mt76: mt76x02: fix ED/CCA enabling/disabling

ED/CCA needs to be disable before stopping the MAC to avoid hangs from tx
being blocked. It must only be enabled again after the MAC has been started
again.
In many places this wasn't done properly, so fix this by always clearing
the relevant ED/CCA bits in mt76x2_mac_stop and set it up again after
channel change or calibration is done
Signed-off-by: default avatarFelix Fietkau <nbd@nbd.name>
parent 72e5d479
...@@ -187,6 +187,8 @@ void mt76x0_mac_stop(struct mt76x02_dev *dev) ...@@ -187,6 +187,8 @@ void mt76x0_mac_stop(struct mt76x02_dev *dev)
{ {
int i = 200, ok = 0; int i = 200, ok = 0;
mt76_clear(dev, MT_TXOP_CTRL_CFG, MT_TXOP_ED_CCA_EN);
/* Page count on TxQ */ /* Page count on TxQ */
while (i-- && ((mt76_rr(dev, 0x0438) & 0xffffffff) || while (i-- && ((mt76_rr(dev, 0x0438) & 0xffffffff) ||
(mt76_rr(dev, 0x0a30) & 0x000000ff) || (mt76_rr(dev, 0x0a30) & 0x000000ff) ||
......
...@@ -34,6 +34,8 @@ mt76x0_set_channel(struct mt76x02_dev *dev, struct cfg80211_chan_def *chandef) ...@@ -34,6 +34,8 @@ mt76x0_set_channel(struct mt76x02_dev *dev, struct cfg80211_chan_def *chandef)
mt76_rr(dev, MT_CH_IDLE); mt76_rr(dev, MT_CH_IDLE);
mt76_rr(dev, MT_CH_BUSY); mt76_rr(dev, MT_CH_BUSY);
mt76x02_edcca_init(dev, true);
if (mt76_is_mmio(dev)) { if (mt76_is_mmio(dev)) {
mt76x02_dfs_init_params(dev); mt76x02_dfs_init_params(dev);
tasklet_enable(&dev->pre_tbtt_tasklet); tasklet_enable(&dev->pre_tbtt_tasklet);
......
...@@ -1007,17 +1007,13 @@ int mt76x0_phy_set_channel(struct mt76x02_dev *dev, ...@@ -1007,17 +1007,13 @@ int mt76x0_phy_set_channel(struct mt76x02_dev *dev,
/* enable vco */ /* enable vco */
mt76x0_rf_set(dev, MT_RF(0, 4), BIT(7)); mt76x0_rf_set(dev, MT_RF(0, 4), BIT(7));
if (scan) { if (scan)
mt76x02_edcca_init(dev, false);
return 0; return 0;
}
mt76x02_init_agc_gain(dev); mt76x02_init_agc_gain(dev);
mt76x0_phy_calibrate(dev, false); mt76x0_phy_calibrate(dev, false);
mt76x0_phy_set_txpower(dev); mt76x0_phy_set_txpower(dev);
mt76x02_edcca_init(dev, true);
ieee80211_queue_delayed_work(dev->mt76.hw, &dev->cal_work, ieee80211_queue_delayed_work(dev->mt76.hw, &dev->cal_work,
MT_CALIBRATE_INTERVAL); MT_CALIBRATE_INTERVAL);
......
...@@ -23,6 +23,9 @@ void mt76x2_mac_stop(struct mt76x02_dev *dev, bool force) ...@@ -23,6 +23,9 @@ void mt76x2_mac_stop(struct mt76x02_dev *dev, bool force)
u32 rts_cfg; u32 rts_cfg;
int i; int i;
mt76_clear(dev, MT_TXOP_CTRL_CFG, MT_TXOP_ED_CCA_EN);
mt76_clear(dev, MT_TXOP_HLDR_ET, MT_TXOP_HLDR_TX40M_BLK_EN);
mt76_wr(dev, MT_MAC_SYS_CTRL, 0); mt76_wr(dev, MT_MAC_SYS_CTRL, 0);
rts_cfg = mt76_rr(dev, MT_TX_RTS_CFG); rts_cfg = mt76_rr(dev, MT_TX_RTS_CFG);
......
...@@ -74,6 +74,7 @@ mt76x2_phy_channel_calibrate(struct mt76x02_dev *dev, bool mac_stopped) ...@@ -74,6 +74,7 @@ mt76x2_phy_channel_calibrate(struct mt76x02_dev *dev, bool mac_stopped)
mt76x2_mac_resume(dev); mt76x2_mac_resume(dev);
mt76x2_apply_gain_adj(dev); mt76x2_apply_gain_adj(dev);
mt76x02_edcca_init(dev, true);
dev->cal.channel_cal_done = true; dev->cal.channel_cal_done = true;
} }
...@@ -240,10 +241,8 @@ int mt76x2_phy_set_channel(struct mt76x02_dev *dev, ...@@ -240,10 +241,8 @@ int mt76x2_phy_set_channel(struct mt76x02_dev *dev,
mt76_wr(dev, MT_BBP(AGC, 2), 0x00007070); mt76_wr(dev, MT_BBP(AGC, 2), 0x00007070);
mt76_wr(dev, MT_TXOP_CTRL_CFG, 0x04101B3F); mt76_wr(dev, MT_TXOP_CTRL_CFG, 0x04101B3F);
if (scan) { if (scan)
mt76x02_edcca_init(dev, false);
return 0; return 0;
}
mt76x2_phy_channel_calibrate(dev, true); mt76x2_phy_channel_calibrate(dev, true);
mt76x02_init_agc_gain(dev); mt76x02_init_agc_gain(dev);
...@@ -256,8 +255,6 @@ int mt76x2_phy_set_channel(struct mt76x02_dev *dev, ...@@ -256,8 +255,6 @@ int mt76x2_phy_set_channel(struct mt76x02_dev *dev,
0x38); 0x38);
} }
mt76x02_edcca_init(dev, true);
ieee80211_queue_delayed_work(mt76_hw(dev), &dev->cal_work, ieee80211_queue_delayed_work(mt76_hw(dev), &dev->cal_work,
MT_CALIBRATE_INTERVAL); MT_CALIBRATE_INTERVAL);
......
...@@ -143,8 +143,8 @@ int mt76x2u_mac_stop(struct mt76x02_dev *dev) ...@@ -143,8 +143,8 @@ int mt76x2u_mac_stop(struct mt76x02_dev *dev)
rts_cfg = mt76_rr(dev, MT_TX_RTS_CFG); rts_cfg = mt76_rr(dev, MT_TX_RTS_CFG);
mt76_wr(dev, MT_TX_RTS_CFG, rts_cfg & ~MT_TX_RTS_CFG_RETRY_LIMIT); mt76_wr(dev, MT_TX_RTS_CFG, rts_cfg & ~MT_TX_RTS_CFG_RETRY_LIMIT);
mt76_clear(dev, MT_TXOP_CTRL_CFG, BIT(20)); mt76_clear(dev, MT_TXOP_CTRL_CFG, MT_TXOP_ED_CCA_EN);
mt76_clear(dev, MT_TXOP_HLDR_ET, BIT(1)); mt76_clear(dev, MT_TXOP_HLDR_ET, MT_TXOP_HLDR_TX40M_BLK_EN);
/* wait tx dma to stop */ /* wait tx dma to stop */
for (i = 0; i < 2000; i++) { for (i = 0; i < 2000; i++) {
...@@ -217,6 +217,4 @@ void mt76x2u_mac_resume(struct mt76x02_dev *dev) ...@@ -217,6 +217,4 @@ void mt76x2u_mac_resume(struct mt76x02_dev *dev)
mt76_wr(dev, MT_MAC_SYS_CTRL, mt76_wr(dev, MT_MAC_SYS_CTRL,
MT_MAC_SYS_CTRL_ENABLE_TX | MT_MAC_SYS_CTRL_ENABLE_TX |
MT_MAC_SYS_CTRL_ENABLE_RX); MT_MAC_SYS_CTRL_ENABLE_RX);
mt76_set(dev, MT_TXOP_CTRL_CFG, BIT(20));
mt76_set(dev, MT_TXOP_HLDR_ET, BIT(1));
} }
...@@ -57,13 +57,12 @@ mt76x2u_set_channel(struct mt76x02_dev *dev, ...@@ -57,13 +57,12 @@ mt76x2u_set_channel(struct mt76x02_dev *dev,
mt76_set_channel(&dev->mt76); mt76_set_channel(&dev->mt76);
mt76_clear(dev, MT_TXOP_CTRL_CFG, BIT(20));
mt76_clear(dev, MT_TXOP_HLDR_ET, BIT(1));
mt76x2_mac_stop(dev, false); mt76x2_mac_stop(dev, false);
err = mt76x2u_phy_set_channel(dev, chandef); err = mt76x2u_phy_set_channel(dev, chandef);
mt76x2u_mac_resume(dev); mt76x2u_mac_resume(dev);
mt76x02_edcca_init(dev, true);
clear_bit(MT76_RESET, &dev->mt76.state); clear_bit(MT76_RESET, &dev->mt76.state);
mt76_txq_schedule_all(&dev->mt76); mt76_txq_schedule_all(&dev->mt76);
......
...@@ -45,6 +45,7 @@ mt76x2u_phy_channel_calibrate(struct mt76x02_dev *dev, bool mac_stopped) ...@@ -45,6 +45,7 @@ mt76x2u_phy_channel_calibrate(struct mt76x02_dev *dev, bool mac_stopped)
if (!mac_stopped) if (!mac_stopped)
mt76x2u_mac_resume(dev); mt76x2u_mac_resume(dev);
mt76x2_apply_gain_adj(dev); mt76x2_apply_gain_adj(dev);
mt76x02_edcca_init(dev, true);
dev->cal.channel_cal_done = true; dev->cal.channel_cal_done = true;
} }
......
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