Commit cf00259c authored by Leon Yen's avatar Leon Yen Committed by Zhengchao Shao
Browse files

wifi: mt76: mt7921s: fix potential hung tasks during chip recovery

stable inclusion
from stable-v6.6.36
commit 85edd783f4539a994d66c4c014d5858f490b7a02
category: bugfix
bugzilla: https://gitee.com/src-openeuler/kernel/issues/IACR0E
CVE: CVE-2024-40977

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=85edd783f4539a994d66c4c014d5858f490b7a02



---------------------------

[ Upstream commit ecf0b2b8a37c8464186620bef37812a117ff6366 ]

During chip recovery (e.g. chip reset), there is a possible situation that
kernel worker reset_work is holding the lock and waiting for kernel thread
stat_worker to be parked, while stat_worker is waiting for the release of
the same lock.
It causes a deadlock resulting in the dumping of hung tasks messages and
possible rebooting of the device.

This patch prevents the execution of stat_worker during the chip recovery.

Signed-off-by: default avatarLeon Yen <leon.yen@mediatek.com>
Signed-off-by: default avatarMing Yen Hsieh <MingYen.Hsieh@mediatek.com>
Signed-off-by: default avatarFelix Fietkau <nbd@nbd.name>
Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
Signed-off-by: default avatarZhengchao Shao <shaozhengchao@huawei.com>
parent 17af64c8
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -663,6 +663,7 @@ void mt7921_mac_reset_work(struct work_struct *work)
	int i, ret;

	dev_dbg(dev->mt76.dev, "chip reset\n");
	set_bit(MT76_RESET, &dev->mphy.state);
	dev->hw_full_reset = true;
	ieee80211_stop_queues(hw);

@@ -691,6 +692,7 @@ void mt7921_mac_reset_work(struct work_struct *work)
	}

	dev->hw_full_reset = false;
	clear_bit(MT76_RESET, &dev->mphy.state);
	pm->suspended = false;
	ieee80211_wake_queues(hw);
	ieee80211_iterate_active_interfaces(hw,
+0 −2
Original line number Diff line number Diff line
@@ -64,7 +64,6 @@ int mt7921e_mac_reset(struct mt792x_dev *dev)
	mt76_wr(dev, dev->irq_map->host_irq_enable, 0);
	mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0x0);

	set_bit(MT76_RESET, &dev->mphy.state);
	set_bit(MT76_MCU_RESET, &dev->mphy.state);
	wake_up(&dev->mt76.mcu.wait);
	skb_queue_purge(&dev->mt76.mcu.res_q);
@@ -115,7 +114,6 @@ int mt7921e_mac_reset(struct mt792x_dev *dev)

	err = __mt7921_start(&dev->phy);
out:
	clear_bit(MT76_RESET, &dev->mphy.state);

	local_bh_disable();
	napi_enable(&dev->mt76.tx_napi);
+0 −2
Original line number Diff line number Diff line
@@ -98,7 +98,6 @@ int mt7921s_mac_reset(struct mt792x_dev *dev)
	mt76_connac_free_pending_tx_skbs(&dev->pm, NULL);
	mt76_txq_schedule_all(&dev->mphy);
	mt76_worker_disable(&dev->mt76.tx_worker);
	set_bit(MT76_RESET, &dev->mphy.state);
	set_bit(MT76_MCU_RESET, &dev->mphy.state);
	wake_up(&dev->mt76.mcu.wait);
	skb_queue_purge(&dev->mt76.mcu.res_q);
@@ -135,7 +134,6 @@ int mt7921s_mac_reset(struct mt792x_dev *dev)

	err = __mt7921_start(&dev->phy);
out:
	clear_bit(MT76_RESET, &dev->mphy.state);

	mt76_worker_enable(&dev->mt76.tx_worker);

+2 −1
Original line number Diff line number Diff line
@@ -499,7 +499,8 @@ static void mt76s_tx_status_data(struct mt76_worker *worker)
	dev = container_of(sdio, struct mt76_dev, sdio);

	while (true) {
		if (test_bit(MT76_REMOVED, &dev->phy.state))
		if (test_bit(MT76_RESET, &dev->phy.state) ||
		    test_bit(MT76_REMOVED, &dev->phy.state))
			break;

		if (!dev->drv->tx_status_data(dev, &update))