__mt76_set_channel() disables the TX worker, schedules pending TX queues, sets MT76_RESET, and waits for pending TX to drain before changing the PHY channel state and calling the driver set_channel() callback. The wait result is ignored. If TX does not drain within the timeout, the function still publishes the new channel state and asks the driver to switch channels while old-channel TX may remain pending. Return -ETIMEDOUT when the drain wait expires. Keep the survey update on the old channel, then clear MT76_RESET and re-enable the TX worker through the existing exit path. This is marked RFC because the existing channel switch path treats the TX drain wait as best-effort. Maintainer feedback is needed on whether a TX drain timeout should fail the channel switch for all mt76 devices or whether the current force-forward behavior is intentional. Signed-off-by: Pengpeng Hou --- drivers/net/wireless/mediatek/mt76/mac80211.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/mediatek/mt76/mac80211.c b/drivers/net/wireless/mediatek/mt76/mac80211.c index 13c4e8abe..37474d64c 100644 --- a/drivers/net/wireless/mediatek/mt76/mac80211.c +++ b/drivers/net/wireless/mediatek/mt76/mac80211.c @@ -1033,6 +1033,7 @@ int __mt76_set_channel(struct mt76_phy *phy, struct cfg80211_chan_def *chandef, bool offchannel) { struct mt76_dev *dev = phy->dev; + long time_left; int timeout = HZ / 5; int ret; @@ -1040,8 +1041,13 @@ int __mt76_set_channel(struct mt76_phy *phy, struct cfg80211_chan_def *chandef, mt76_txq_schedule_pending(phy); set_bit(MT76_RESET, &phy->state); - wait_event_timeout(dev->tx_wait, !mt76_has_tx_pending(phy), timeout); + time_left = wait_event_timeout(dev->tx_wait, !mt76_has_tx_pending(phy), + timeout); mt76_update_survey(phy); + if (!time_left) { + ret = -ETIMEDOUT; + goto out; + } if (phy->chandef.chan->center_freq != chandef->chan->center_freq || phy->chandef.width != chandef->width) @@ -1059,6 +1065,7 @@ int __mt76_set_channel(struct mt76_phy *phy, struct cfg80211_chan_def *chandef, ret = dev->drv->set_channel(phy); +out: clear_bit(MT76_RESET, &phy->state); mt76_worker_enable(&dev->tx_worker); mt76_worker_schedule(&dev->tx_worker); -- 2.50.1 (Apple Git-155)