FAILED: patch "[PATCH] wifi: mt76: mt7615: avoid waiting for mac work under the mt76" failed to apply to 5.10-stable tree
Subsystems (3)
[email protected]
maintainerThe patch below does not apply to the 5.10-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-5.10.y
git checkout FETCH_HEAD
git cherry-pick -x bda8324270b1ac91bfba1df8928e0570e29759e8
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2026090448-broiling-unsworn-6960@gregkh' --subject-prefix 'PATCH 5.10.y' 'HEAD^..'
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From bda8324270b1ac91bfba1df8928e0570e29759e8 Mon Sep 17 00:00:00 2001
From: Runyu Xiao <[email protected]>
Date: Fri, 12 Jun 2026 12:13:31 +0800
Subject: [PATCH] wifi: mt76: mt7615: avoid waiting for mac work under the mt76
mutex
mt7615_suspend() acquired the mt76 mutex and then called cancel_delayed_work_sync() on mac_work. mt7615_mac_work() acquires the same mutex via mt7615_mutex_acquire() at the top of the worker, so if mac_work is already running and blocked on the mutex, the suspend path deadlocks waiting for the work it holds the mutex against.
Flush scan_work and mac_work before taking the mutex, matching the suspend paths in mt7921 and mt7925. scan_work only takes the mt76 spinlock, but moving it keeps the sequence consistent. This also keeps mac_work from running over an already suspended HIF, which the previous split (async cancel under the lock, sync cancel after release) would have allowed.
drivers/net/wireless/mediatek/mt76/mt7615/main.c +3 -2
@@ -1239,11 +1239,12 @@ static int mt7615_suspend(struct ieee80211_hw *hw,cancel_delayed_work_sync (&dev->pm.ps_work);mt76_connac_free_pending_tx_skbs (&dev->pm,NULL ); +cancel_delayed_work_sync (&phy->scan_work); +cancel_delayed_work_sync (&phy->mt76->mac_work); +mt7615_mutex_acquire (dev);clear_bit (MT76_STATE_RUNNING , &phy->mt76->state); -cancel_delayed_work_sync (&phy->scan_work); -cancel_delayed_work_sync (&phy->mt76->mac_work);set_bit (MT76_STATE_SUSPEND , &phy->mt76->state); ieee80211_iterate_active_interfaces(hw,
Sasha Levin
maintainerPATCH 1/3 mt76: rely on mt76_phy in mt76_init_sband_2g and mt76_init_sband_5g
From: Lorenzo Bianconi <[email protected]>
[ Upstream commit 77af762e42f1f959d8a70c17c24accc96d7ee18d ]
This is a preliminary patch to properly support mt7915 dbdc
Stable-dep-of: bda8324270b1 ("wifi: mt76: mt7615: avoid waiting for mac work under the mt76 mutex")
--- drivers/net/wireless/mediatek/mt76/mac80211.c | 33 +++++++++---------- 1 file changed, 16 insertions(+), 17 deletions(-)
drivers/net/wireless/mediatek/mt76/mac80211.c +16 -17
@@ -168,13 +168,14 @@ void mt76_set_stream_caps(struct mt76_phy *phy, bool vht)EXPORT_SYMBOL_GPL (mt76_set_stream_caps);static int -mt76_init_sband (struct mt76_dev *dev,struct mt76_sband *msband, +mt76_init_sband (struct mt76_phy *phy,struct mt76_sband *msband,const struct ieee80211_channel *chan,int n_chan,struct ieee80211_rate *rates,int n_rates,bool vht) {struct ieee80211_supported_band *sband = &msband->sband; -struct ieee80211_sta_ht_cap *ht_cap;struct ieee80211_sta_vht_cap *vht_cap; +struct ieee80211_sta_ht_cap *ht_cap; +struct mt76_dev *dev = phy->dev;void *chanlist;int size;
@@ -204,7 +205,7 @@ mt76_init_sband(struct mt76_dev *dev, struct mt76_sband *msband, ht_cap->mcs.tx_params =IEEE80211_HT_MCS_TX_DEFINED ; ht_cap->ampdu_factor =IEEE80211_HT_MAX_AMPDU_64K ; -mt76_init_stream_cap (&dev->phy, sband, vht); +mt76_init_stream_cap (phy, sband, vht);if (!vht)return 0 ;
@@ -222,27 +223,25 @@ mt76_init_sband(struct mt76_dev *dev, struct mt76_sband *msband, }static int -mt76_init_sband_2g (struct mt76_dev *dev,struct ieee80211_rate *rates, +mt76_init_sband_2g (struct mt76_phy *phy,struct ieee80211_rate *rates,int n_rates) { - dev->hw->wiphy->bands[NL80211_BAND_2GHZ ] = &dev->phy.sband_2g.sband; + phy->hw->wiphy->bands[NL80211_BAND_2GHZ ] = &phy->sband_2g.sband; -return mt76_init_sband (dev, &dev->phy.sband_2g, - mt76_channels_2ghz, -ARRAY_SIZE (mt76_channels_2ghz), - rates, n_rates, false); +return mt76_init_sband (phy, &phy->sband_2g, mt76_channels_2ghz, +ARRAY_SIZE (mt76_channels_2ghz), rates, + n_rates, false); }static int -mt76_init_sband_5g (struct mt76_dev *dev,struct ieee80211_rate *rates, +mt76_init_sband_5g (struct mt76_phy *phy,struct ieee80211_rate *rates,int n_rates,bool vht) { - dev->hw->wiphy->bands[NL80211_BAND_5GHZ ] = &dev->phy.sband_5g.sband; + phy->hw->wiphy->bands[NL80211_BAND_5GHZ ] = &phy->sband_5g.sband; -return mt76_init_sband (dev, &dev->phy.sband_5g, - mt76_channels_5ghz, -ARRAY_SIZE (mt76_channels_5ghz), - rates, n_rates, vht); +return mt76_init_sband (phy, &phy->sband_5g, mt76_channels_5ghz, +ARRAY_SIZE (mt76_channels_5ghz), rates, + n_rates, vht); } static void
@@ -464,13 +463,13 @@ int mt76_register_device(struct mt76_dev *dev, bool vht,mt76_phy_init (dev, hw);if (phy->cap.has_2ghz) { - ret =mt76_init_sband_2g (dev, rates, n_rates); + ret =mt76_init_sband_2g (phy, rates, n_rates);if (ret)return ret; }if (phy->cap.has_5ghz) { - ret =mt76_init_sband_5g (dev, rates +4 , n_rates -4 , vht); + ret =mt76_init_sband_5g (phy, rates +4 , n_rates -4 , vht);if (ret)return ret; }
Signature · 1 line
2.53.0
Sasha Levin
maintainerPATCH 2/3 mt76: move mac_work in mt76_core module
From: Lorenzo Bianconi <[email protected]>
[ Upstream commit a782f8bfdd46a6028dee41b99a990534737ad997 ]
Move mac_work delayed_work and mac_work_count in mt76_phy since it is used by all drivers. This is a preliminary patch to create a common mcu library used by mt7615 and mt7921 drivers
Stable adaptation: retain the 5.10 device-based testmode data and API, mt7603 tasklet_init callback, and unconditional mt7915 watchdog scheduling. Apply the external-PHY watchdog initialization change to the existing mt7915_register_ext_phy implementation at its stable-tree location. No functions or newer testmode/DBDC infrastructure are added.
This keeps the MAC work relocation needed by bda8324270b1 while preserving stable suspend helpers and beacon filtering. The target applies cleanly with a three-way application after this dependency.
Stable-dep-of: bda8324270b1 ("wifi: mt76: mt7615: avoid waiting for mac work under the mt76 mutex")
--- drivers/net/wireless/mediatek/mt76/mt76.h | 4 ++- .../net/wireless/mediatek/mt76/mt7603/init.c | 2 +- .../net/wireless/mediatek/mt76/mt7603/mac.c | 14 ++++----- .../net/wireless/mediatek/mt76/mt7603/main.c | 10 +++---- .../wireless/mediatek/mt76/mt7603/mt7603.h | 2 -- .../net/wireless/mediatek/mt76/mt7615/init.c | 4 +-- .../net/wireless/mediatek/mt76/mt7615/mac.c | 25 ++++++++-------- .../net/wireless/mediatek/mt76/mt7615/main.c | 13 +++++---- .../wireless/mediatek/mt76/mt7615/mt7615.h | 3 -- .../net/wireless/mediatek/mt76/mt7615/usb.c | 2 +- .../net/wireless/mediatek/mt76/mt76x0/pci.c | 4 +-- .../net/wireless/mediatek/mt76/mt76x0/usb.c | 4 +-- .../net/wireless/mediatek/mt76/mt76x02_mac.c | 4 +-- .../net/wireless/mediatek/mt76/mt76x02_util.c | 2 +- .../wireless/mediatek/mt76/mt76x2/pci_init.c | 2 +- .../wireless/mediatek/mt76/mt76x2/pci_main.c | 2 +- .../wireless/mediatek/mt76/mt76x2/usb_init.c | 2 +- .../wireless/mediatek/mt76/mt76x2/usb_main.c | 2 +- .../net/wireless/mediatek/mt76/mt7915/init.c | 4 +-- .../net/wireless/mediatek/mt76/mt7915/mac.c | 29 ++++++++++--------- .../net/wireless/mediatek/mt76/mt7915/main.c | 9 +++--- .../wireless/mediatek/mt76/mt7915/mt7915.h | 2 -- 22 files changed, 72 insertions(+), 73 deletions(-)
drivers/net/wireless/mediatek/mt76/mt76.h +3 -1
@@ -569,6 +569,9 @@ struct mt76_phy {int txpower_cur;u8 antenna_mask; + +struct delayed_work mac_work; +u8 mac_work_count; };struct mt76_dev {
@@ -609,7 +612,6 @@ struct mt76_dev {struct mt76_worker tx_worker;struct napi_struct tx_napi; -struct delayed_work mac_work;wait_queue_head_t tx_wait;struct sk_buff_head status_list;
drivers/net/wireless/mediatek/mt76/mt7603/init.c +1 -1
@@ -532,7 +532,7 @@ int mt7603_register_device(struct mt7603_dev *dev)spin_lock_init (&dev->sta_poll_lock);spin_lock_init (&dev->ps_lock); -INIT_DELAYED_WORK (&dev->mt76.mac_work, mt7603_mac_work); +INIT_DELAYED_WORK (&dev->mphy.mac_work, mt7603_mac_work);tasklet_init (&dev->mt76.pre_tbtt_tasklet, mt7603_pre_tbtt_tasklet, (unsigned long )dev);
drivers/net/wireless/mediatek/mt76/mt7603/mac.c +7 -7
@@ -1796,7 +1796,7 @@ mt7603_false_cca_check(struct mt7603_dev *dev)void mt7603_mac_work (struct work_struct *work) { struct mt7603_dev *dev = container_of(work, struct mt7603_dev, - mt76.mac_work.work); + mphy.mac_work.work);bool reset = false;int i, idx;
@@ -1804,7 +1804,7 @@ void mt7603_mac_work(struct work_struct *work)mutex_lock (&dev->mt76.mutex); - dev->mac_work_count++; + dev->mphy.mac_work_count++;mt76_update_survey (&dev->mt76);mt7603_edcca_check (dev);
@@ -1815,7 +1815,7 @@ void mt7603_mac_work(struct work_struct *work) dev->mt76.aggr_stats[idx++] += val >>16 ; } -if (dev->mac_work_count ==10 ) +if (dev->mphy.mac_work_count ==10 )mt7603_false_cca_check (dev); if (mt7603_watchdog_check(dev, &dev->rx_pse_check,
@@ -1846,17 +1846,17 @@ void mt7603_mac_work(struct work_struct *work) dev->rx_dma_idx = ~0 ;memset (dev->tx_dma_idx,0xff ,sizeof (dev->tx_dma_idx)); reset = true; - dev->mac_work_count =0 ; + dev->mphy.mac_work_count =0 ; } -if (dev->mac_work_count >=10 ) - dev->mac_work_count =0 ; +if (dev->mphy.mac_work_count >=10 ) + dev->mphy.mac_work_count =0 ;mutex_unlock (&dev->mt76.mutex);if (reset)mt7603_mac_watchdog_reset (dev); -ieee80211_queue_delayed_work (mt76_hw (dev), &dev->mt76.mac_work, +ieee80211_queue_delayed_work (mt76_hw (dev), &dev->mphy.mac_work,msecs_to_jiffies (MT7603_WATCHDOG_TIME )); }
drivers/net/wireless/mediatek/mt76/mt7603/main.c +5 -5
@@ -17,7 +17,7 @@ mt7603_start(struct ieee80211_hw *hw)mt7603_mac_start (dev); dev->mphy.survey_time =ktime_get_boottime ();set_bit (MT76_STATE_RUNNING , &dev->mphy.state); -mt7603_mac_work (&dev->mt76.mac_work.work); +mt7603_mac_work (&dev->mphy.mac_work.work);return 0 ; }
@@ -28,7 +28,7 @@ mt7603_stop(struct ieee80211_hw *hw)struct mt7603_dev *dev = hw->priv;clear_bit (MT76_STATE_RUNNING , &dev->mphy.state); -cancel_delayed_work_sync (&dev->mt76.mac_work); +cancel_delayed_work_sync (&dev->mphy.mac_work);mt7603_mac_stop (dev); }
@@ -137,7 +137,7 @@ mt7603_set_channel(struct mt7603_dev *dev, struct cfg80211_chan_def *def)u8 bw =MT_BW_20 ;bool failed = false; -cancel_delayed_work_sync (&dev->mt76.mac_work); +cancel_delayed_work_sync (&dev->mphy.mac_work);tasklet_disable (&dev->mt76.pre_tbtt_tasklet);mutex_lock (&dev->mt76.mutex);
@@ -178,7 +178,7 @@ mt7603_set_channel(struct mt7603_dev *dev, struct cfg80211_chan_def *def)mt76_txq_schedule_all (&dev->mphy); -ieee80211_queue_delayed_work (mt76_hw (dev), &dev->mt76.mac_work, +ieee80211_queue_delayed_work (mt76_hw (dev), &dev->mphy.mac_work,msecs_to_jiffies (MT7603_WATCHDOG_TIME ));/* reset channel stats */
@@ -200,7 +200,7 @@ mt7603_set_channel(struct mt7603_dev *dev, struct cfg80211_chan_def *def)tasklet_enable (&dev->mt76.pre_tbtt_tasklet);if (failed) -mt7603_mac_work (&dev->mt76.mac_work.work); +mt7603_mac_work (&dev->mphy.mac_work.work);return ret; }
drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h +0 -2
@@ -132,8 +132,6 @@ struct mt7603_dev {spinlock_t ps_lock; -u8 mac_work_count; -u8 mcu_running;u8 ed_monitor_enabled;
drivers/net/wireless/mediatek/mt76/mt7615/init.c +2 -2
@@ -408,7 +408,7 @@ int mt7615_register_ext_phy(struct mt7615_dev *dev) mphy->antenna_mask =BIT (hweight8 (phy->chainmask)) -1 ;mt7615_init_wiphy (mphy->hw); -INIT_DELAYED_WORK (&phy->mac_work, mt7615_mac_work); +INIT_DELAYED_WORK (&mphy->mac_work, mt7615_mac_work);INIT_DELAYED_WORK (&phy->scan_work, mt7615_scan_work);skb_queue_head_init (&phy->scan_event_list);
@@ -464,7 +464,7 @@ void mt7615_init_device(struct mt7615_dev *dev)init_completion (&dev->pm.wake_cmpl);spin_lock_init (&dev->pm.txq_lock);set_bit (MT76_STATE_PM , &dev->mphy.state); -INIT_DELAYED_WORK (&dev->phy.mac_work, mt7615_mac_work); +INIT_DELAYED_WORK (&dev->mphy.mac_work, mt7615_mac_work);INIT_DELAYED_WORK (&dev->phy.scan_work, mt7615_scan_work);skb_queue_head_init (&dev->phy.scan_event_list);INIT_LIST_HEAD (&dev->sta_poll_list);
drivers/net/wireless/mediatek/mt76/mt7615/mac.c +13 -12
@@ -2015,17 +2015,17 @@ int mt7615_pm_set_enable(struct mt7615_dev *dev, bool enable)void mt7615_mac_work (struct work_struct *work) {struct mt7615_phy *phy; -struct mt76_dev *mdev; +struct mt76_phy *mphy; - phy = (struct mt7615_phy *)container_of(work, struct mt7615_phy, - mac_work.work); - mdev = &phy->dev->mt76; + mphy = (struct mt76_phy *)container_of(work, struct mt76_phy, + mac_work.work); + phy = mphy->priv;mt7615_mutex_acquire (phy->dev);mt7615_update_survey (phy->dev); -if (++phy->mac_work_count ==5 ) { - phy->mac_work_count =0 ; +if (++mphy->mac_work_count ==5 ) { + mphy->mac_work_count =0 ;mt7615_mac_update_mib_stats (phy);mt7615_mac_scs_check (phy);
@@ -2033,8 +2033,8 @@ void mt7615_mac_work(struct work_struct *work)mt7615_mutex_release (phy->dev); -mt76_tx_status_check (mdev,NULL , false); -ieee80211_queue_delayed_work (phy->mt76->hw, &phy->mac_work, +mt76_tx_status_check (mphy->dev,NULL , false); +ieee80211_queue_delayed_work (mphy->hw, &mphy->mac_work,MT7615_WATCHDOG_TIME ); }
@@ -2137,11 +2137,11 @@ void mt7615_mac_reset_work(struct work_struct *work)set_bit (MT76_RESET , &dev->mphy.state);set_bit (MT76_MCU_RESET , &dev->mphy.state);wake_up (&dev->mt76.mcu.wait); -cancel_delayed_work_sync (&dev->phy.mac_work); +cancel_delayed_work_sync (&dev->mphy.mac_work);del_timer_sync (&dev->phy.roc_timer);cancel_work_sync (&dev->phy.roc_work);if (phy2) { -cancel_delayed_work_sync (&phy2->mac_work); +cancel_delayed_work_sync (&phy2->mt76->mac_work);del_timer_sync (&phy2->roc_timer);cancel_work_sync (&phy2->roc_work); }
@@ -2196,10 +2196,11 @@ void mt7615_mac_reset_work(struct work_struct *work)mt7615_mutex_release (dev); -ieee80211_queue_delayed_work (mt76_hw (dev), &dev->phy.mac_work, +ieee80211_queue_delayed_work (mt76_hw (dev), &dev->mphy.mac_work,MT7615_WATCHDOG_TIME );if (phy2) -ieee80211_queue_delayed_work (ext_phy->hw, &phy2->mac_work, +ieee80211_queue_delayed_work (ext_phy->hw, + &phy2->mt76->mac_work,MT7615_WATCHDOG_TIME ); }
drivers/net/wireless/mediatek/mt76/mt7615/main.c +7 -6
@@ -70,7 +70,7 @@ static int mt7615_start(struct ieee80211_hw *hw)set_bit (MT76_STATE_RUNNING , &phy->mt76->state); -ieee80211_queue_delayed_work (hw, &phy->mac_work, +ieee80211_queue_delayed_work (hw, &phy->mt76->mac_work,MT7615_WATCHDOG_TIME );if (!running)
@@ -86,7 +86,7 @@ static void mt7615_stop(struct ieee80211_hw *hw)struct mt7615_dev *dev =mt7615_hw_dev (hw);struct mt7615_phy *phy =mt7615_hw_phy (hw); -cancel_delayed_work_sync (&phy->mac_work); +cancel_delayed_work_sync (&phy->mt76->mac_work);del_timer_sync (&phy->roc_timer);cancel_work_sync (&phy->roc_work);
@@ -293,7 +293,7 @@ int mt7615_set_channel(struct mt7615_phy *phy)bool ext_phy = phy != &dev->phy;int ret; -cancel_delayed_work_sync (&phy->mac_work); +cancel_delayed_work_sync (&phy->mt76->mac_work);mt7615_mutex_acquire (dev);
@@ -328,7 +328,8 @@ int mt7615_set_channel(struct mt7615_phy *phy)mt76_txq_schedule_all (phy->mt76);if (!mt76_testmode_enabled (&dev->mt76)) -ieee80211_queue_delayed_work (phy->mt76->hw, &phy->mac_work, +ieee80211_queue_delayed_work (phy->mt76->hw, + &phy->mt76->mac_work,MT7615_WATCHDOG_TIME );return ret;
@@ -1146,7 +1147,7 @@ static int mt7615_suspend(struct ieee80211_hw *hw,clear_bit (MT76_STATE_RUNNING , &phy->mt76->state);cancel_delayed_work_sync (&phy->scan_work); -cancel_delayed_work_sync (&phy->mac_work); +cancel_delayed_work_sync (&phy->mt76->mac_work);mt76_set (dev,MT_WF_RFCR (ext_phy),MT_WF_RFCR_DROP_OTHER_BEACON );
@@ -1189,7 +1190,7 @@ static int mt7615_resume(struct ieee80211_hw *hw)IEEE80211_IFACE_ITER_RESUME_ALL , mt7615_mcu_set_suspend_iter, phy); -ieee80211_queue_delayed_work (hw, &phy->mac_work, +ieee80211_queue_delayed_work (hw, &phy->mt76->mac_work,MT7615_WATCHDOG_TIME );mt76_clear (dev,MT_WF_RFCR (ext_phy),MT_WF_RFCR_DROP_OTHER_BEACON );
drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h +0 -3
@@ -201,9 +201,6 @@ struct mt7615_phy {struct mib_stats mib; -struct delayed_work mac_work; -u8 mac_work_count; -struct sk_buff_head scan_event_list;struct delayed_work scan_work;
drivers/net/wireless/mediatek/mt76/mt7615/usb.c +1 -1
@@ -29,7 +29,7 @@ static void mt7663u_stop(struct ieee80211_hw *hw)del_timer_sync (&phy->roc_timer);cancel_work_sync (&phy->roc_work);cancel_delayed_work_sync (&phy->scan_work); -cancel_delayed_work_sync (&phy->mac_work); +cancel_delayed_work_sync (&phy->mt76->mac_work);mt76u_stop_tx (&dev->mt76); }
drivers/net/wireless/mediatek/mt76/mt76x0/pci.c +2 -2
@@ -16,7 +16,7 @@ static int mt76x0e_start(struct ieee80211_hw *hw)mt76x02_mac_start (dev);mt76x0_phy_calibrate (dev, true); -ieee80211_queue_delayed_work (dev->mt76.hw, &dev->mt76.mac_work, +ieee80211_queue_delayed_work (dev->mt76.hw, &dev->mphy.mac_work,MT_MAC_WORK_INTERVAL );ieee80211_queue_delayed_work (dev->mt76.hw, &dev->cal_work,MT_CALIBRATE_INTERVAL );
@@ -28,7 +28,7 @@ static int mt76x0e_start(struct ieee80211_hw *hw) static void mt76x0e_stop_hw(struct mt76x02_dev *dev) { cancel_delayed_work_sync(&dev->cal_work); - cancel_delayed_work_sync(&dev->mt76.mac_work); + cancel_delayed_work_sync(&dev->mphy.mac_work); clear_bit(MT76_RESTART, &dev->mphy.state); if (!mt76_poll(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_TX_DMA_BUSY,
drivers/net/wireless/mediatek/mt76/mt76x0/usb.c +2 -2
@@ -82,7 +82,7 @@ static void mt76x0u_stop(struct ieee80211_hw *hw)clear_bit (MT76_STATE_RUNNING , &dev->mphy.state);cancel_delayed_work_sync (&dev->cal_work); -cancel_delayed_work_sync (&dev->mt76.mac_work); +cancel_delayed_work_sync (&dev->mphy.mac_work);mt76u_stop_tx (&dev->mt76);mt76x02u_exit_beacon_config (dev);
@@ -108,7 +108,7 @@ static int mt76x0u_start(struct ieee80211_hw *hw)return ret;mt76x0_phy_calibrate (dev, true); -ieee80211_queue_delayed_work (dev->mt76.hw, &dev->mt76.mac_work, +ieee80211_queue_delayed_work (dev->mt76.hw, &dev->mphy.mac_work,MT_MAC_WORK_INTERVAL );ieee80211_queue_delayed_work (dev->mt76.hw, &dev->cal_work,MT_CALIBRATE_INTERVAL );
drivers/net/wireless/mediatek/mt76/mt76x02_mac.c +2 -2
@@ -1163,7 +1163,7 @@ static void mt76x02_edcca_check(struct mt76x02_dev *dev)void mt76x02_mac_work (struct work_struct *work) { struct mt76x02_dev *dev = container_of(work, struct mt76x02_dev, - mt76.mac_work.work); + mphy.mac_work.work);int i, idx;mutex_lock (&dev->mt76.mutex);
@@ -1186,7 +1186,7 @@ void mt76x02_mac_work(struct work_struct *work)mt76_tx_status_check (&dev->mt76,NULL , false); -ieee80211_queue_delayed_work (mt76_hw (dev), &dev->mt76.mac_work, +ieee80211_queue_delayed_work (mt76_hw (dev), &dev->mphy.mac_work,MT_MAC_WORK_INTERVAL ); }
drivers/net/wireless/mediatek/mt76/mt76x02_util.c +1 -1
@@ -149,7 +149,7 @@ void mt76x02_init_device(struct mt76x02_dev *dev)struct ieee80211_hw *hw =mt76_hw (dev);struct wiphy *wiphy = hw->wiphy; -INIT_DELAYED_WORK (&dev->mt76.mac_work, mt76x02_mac_work); +INIT_DELAYED_WORK (&dev->mphy.mac_work, mt76x02_mac_work); hw->queues =4 ; hw->max_rates =1 ;
drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c +1 -1
@@ -271,7 +271,7 @@ static int mt76x2_init_hardware(struct mt76x02_dev *dev)void mt76x2_stop_hardware (struct mt76x02_dev *dev) {cancel_delayed_work_sync (&dev->cal_work); -cancel_delayed_work_sync (&dev->mt76.mac_work); +cancel_delayed_work_sync (&dev->mphy.mac_work);cancel_delayed_work_sync (&dev->wdt_work);clear_bit (MT76_RESTART , &dev->mphy.state);mt76x02_mcu_set_radio_state (dev, false);
drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c +1 -1
@@ -14,7 +14,7 @@ mt76x2_start(struct ieee80211_hw *hw)mt76x02_mac_start (dev);mt76x2_phy_start (dev); -ieee80211_queue_delayed_work (mt76_hw (dev), &dev->mt76.mac_work, +ieee80211_queue_delayed_work (mt76_hw (dev), &dev->mphy.mac_work,MT_MAC_WORK_INTERVAL );ieee80211_queue_delayed_work (mt76_hw (dev), &dev->wdt_work,MT_WATCHDOG_TIME );
drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c +1 -1
@@ -247,7 +247,7 @@ int mt76x2u_register_device(struct mt76x02_dev *dev)void mt76x2u_stop_hw (struct mt76x02_dev *dev) {cancel_delayed_work_sync (&dev->cal_work); -cancel_delayed_work_sync (&dev->mt76.mac_work); +cancel_delayed_work_sync (&dev->mphy.mac_work);mt76x2u_mac_stop (dev); }
drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c +1 -1
@@ -15,7 +15,7 @@ static int mt76x2u_start(struct ieee80211_hw *hw)if (ret)return ret; -ieee80211_queue_delayed_work (mt76_hw (dev), &dev->mt76.mac_work, +ieee80211_queue_delayed_work (mt76_hw (dev), &dev->mphy.mac_work,MT_MAC_WORK_INTERVAL );set_bit (MT76_STATE_RUNNING , &dev->mphy.state);
drivers/net/wireless/mediatek/mt76/mt7915/init.c +2 -2
@@ -618,7 +618,7 @@ int mt7915_register_ext_phy(struct mt7915_dev *dev)mt7915_init_wiphy (mphy->hw);INIT_LIST_HEAD (&phy->stats_list); -INIT_DELAYED_WORK (&phy->mac_work, mt7915_mac_work); +INIT_DELAYED_WORK (&mphy->mac_work, mt7915_mac_work);/* * Make the secondary PHY MAC address local without overlapping with
@@ -660,7 +660,7 @@ int mt7915_register_device(struct mt7915_dev *dev) dev->mt76.phy.priv = &dev->phy;INIT_LIST_HEAD (&dev->phy.stats_list);INIT_WORK (&dev->rc_work, mt7915_mac_sta_rc_work); -INIT_DELAYED_WORK (&dev->phy.mac_work, mt7915_mac_work); +INIT_DELAYED_WORK (&dev->mphy.mac_work, mt7915_mac_work);INIT_LIST_HEAD (&dev->sta_rc_list);INIT_LIST_HEAD (&dev->sta_poll_list);spin_lock_init (&dev->sta_poll_lock);
drivers/net/wireless/mediatek/mt76/mt7915/mac.c +15 -14
@@ -1209,9 +1209,9 @@ void mt7915_mac_reset_work(struct work_struct *work)set_bit (MT76_RESET , &dev->mphy.state);set_bit (MT76_MCU_RESET , &dev->mphy.state);wake_up (&dev->mt76.mcu.wait); -cancel_delayed_work_sync (&dev->phy.mac_work); +cancel_delayed_work_sync (&dev->mphy.mac_work);if (phy2) -cancel_delayed_work_sync (&phy2->mac_work); +cancel_delayed_work_sync (&phy2->mt76->mac_work);/* lock/unlock all queues to ensure that no tx is pending */ mt76_txq_schedule_all (&dev->mphy);
@@ -1262,10 +1262,11 @@ void mt7915_mac_reset_work(struct work_struct *work)mt7915_update_beacons (dev); -ieee80211_queue_delayed_work (mt76_hw (dev), &dev->phy.mac_work, +ieee80211_queue_delayed_work (mt76_hw (dev), &dev->mphy.mac_work,MT7915_WATCHDOG_TIME );if (phy2) -ieee80211_queue_delayed_work (ext_phy->hw, &phy2->mac_work, +ieee80211_queue_delayed_work (ext_phy->hw, + &phy2->mt76->mac_work,MT7915_WATCHDOG_TIME ); }
@@ -1367,17 +1368,17 @@ void mt7915_mac_sta_rc_work(struct work_struct *work)void mt7915_mac_work (struct work_struct *work) {struct mt7915_phy *phy; -struct mt76_dev *mdev; +struct mt76_phy *mphy; - phy = (struct mt7915_phy *)container_of(work, struct mt7915_phy, - mac_work.work); - mdev = &phy->dev->mt76; + mphy = (struct mt76_phy *)container_of(work, struct mt76_phy, + mac_work.work); + phy = mphy->priv; -mutex_lock (&mdev->mutex); +mutex_lock (&mphy->dev->mutex); -mt76_update_survey (mdev); -if (++phy->mac_work_count ==5 ) { - phy->mac_work_count =0 ; +mt76_update_survey (mphy->dev); +if (++mphy->mac_work_count ==5 ) { + mphy->mac_work_count =0 ;mt7915_mac_update_mib_stats (phy); }
@@ -1387,9 +1388,9 @@ void mt7915_mac_work(struct work_struct *work)mt7915_mac_sta_stats_work (phy); }; -mutex_unlock (&mdev->mutex); +mutex_unlock (&mphy->dev->mutex); -ieee80211_queue_delayed_work (phy->mt76->hw, &phy->mac_work, +ieee80211_queue_delayed_work (mphy->hw, &mphy->mac_work,MT7915_WATCHDOG_TIME ); }
drivers/net/wireless/mediatek/mt76/mt7915/main.c +5 -4
@@ -47,7 +47,7 @@ static int mt7915_start(struct ieee80211_hw *hw)set_bit (MT76_STATE_RUNNING , &phy->mt76->state); -ieee80211_queue_delayed_work (hw, &phy->mac_work, +ieee80211_queue_delayed_work (hw, &phy->mt76->mac_work,MT7915_WATCHDOG_TIME );if (!running)
@@ -63,7 +63,7 @@ static void mt7915_stop(struct ieee80211_hw *hw)struct mt7915_dev *dev =mt7915_hw_dev (hw);struct mt7915_phy *phy =mt7915_hw_phy (hw); -cancel_delayed_work_sync (&phy->mac_work); +cancel_delayed_work_sync (&phy->mt76->mac_work);mutex_lock (&dev->mt76.mutex);
@@ -227,7 +227,7 @@ static int mt7915_set_channel(struct mt7915_phy *phy)struct mt7915_dev *dev = phy->dev;int ret; -cancel_delayed_work_sync (&phy->mac_work); +cancel_delayed_work_sync (&phy->mt76->mac_work);mutex_lock (&dev->mt76.mutex);set_bit (MT76_RESET , &phy->mt76->state);
@@ -251,7 +251,8 @@ static int mt7915_set_channel(struct mt7915_phy *phy)mutex_unlock (&dev->mt76.mutex);mt76_txq_schedule_all (phy->mt76); -ieee80211_queue_delayed_work (phy->mt76->hw, &phy->mac_work, +ieee80211_queue_delayed_work (phy->mt76->hw, + &phy->mt76->mac_work,MT7915_WATCHDOG_TIME );return ret;
drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h +0 -2
@@ -130,8 +130,6 @@ struct mt7915_phy {struct mib_stats mib;struct list_head stats_list; -struct delayed_work mac_work; -u8 mac_work_count;u8 sta_work_count; };
Signature · 1 line
2.53.0
Sasha Levin
maintainerPATCH 3/3 wifi: mt76: mt7615: avoid waiting for mac work under the mt76 mutex
In reply to Sasha LevinFrom: Runyu Xiao <[email protected]>
[ Upstream commit bda8324270b1ac91bfba1df8928e0570e29759e8 ]
mt7615_suspend() acquired the mt76 mutex and then called cancel_delayed_work_sync() on mac_work. mt7615_mac_work() acquires the same mutex via mt7615_mutex_acquire() at the top of the worker, so if mac_work is already running and blocked on the mutex, the suspend path deadlocks waiting for the work it holds the mutex against.
Flush scan_work and mac_work before taking the mutex, matching the suspend paths in mt7921 and mt7925. scan_work only takes the mt76 spinlock, but moving it keeps the sequence consistent. This also keeps mac_work from running over an already suspended HIF, which the previous split (async cancel under the lock, sync cancel after release) would have allowed.
--- drivers/net/wireless/mediatek/mt76/mt7615/main.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
drivers/net/wireless/mediatek/mt76/mt7615/main.c +3 -2
@@ -1143,11 +1143,12 @@ static int mt7615_suspend(struct ieee80211_hw *hw,cancel_delayed_work_sync (&dev->pm.ps_work);mt7615_free_pending_tx_skbs (dev,NULL ); +cancel_delayed_work_sync (&phy->scan_work); +cancel_delayed_work_sync (&phy->mt76->mac_work); +mt7615_mutex_acquire (dev);clear_bit (MT76_STATE_RUNNING , &phy->mt76->state); -cancel_delayed_work_sync (&phy->scan_work); -cancel_delayed_work_sync (&phy->mt76->mac_work);mt76_set (dev,MT_WF_RFCR (ext_phy),MT_WF_RFCR_DROP_OTHER_BEACON );
Signature · 1 line
2.53.0