[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <2026012028-barmaid-ouch-e53b@gregkh>
Date: Tue, 20 Jan 2026 08:04:42 +0100
From: Greg KH <gregkh@...uxfoundation.org>
To: Zac <zac@...bowling.com>
Cc: sean.wang@...nel.org, deren.wu@...iatek.com, kvalo@...nel.org,
linux-kernel@...r.kernel.org, linux-mediatek@...ts.infradead.org,
linux-wireless@...r.kernel.org, lorenzo@...nel.org, nbd@....name,
ryder.lee@...iatek.com, sean.wang@...iatek.com,
stable@...r.kernel.org, linux@...me.work, zbowling@...il.com
Subject: Re: [PATCH 02/11] wifi: mt76: mt792x: fix NULL pointer and firmware
reload issues
On Mon, Jan 19, 2026 at 10:28:45PM -0800, Zac wrote:
> From: Zac Bowling <zac@...bowling.com>
>
> This patch combines two fixes for the shared mt792x code used by both
> MT7921 and MT7925 drivers:
>
> 1. Fix NULL pointer dereference in TX path:
>
> Add NULL pointer checks in mt792x_tx() to prevent kernel crashes when
> transmitting packets during MLO link removal.
>
> The function calls mt792x_sta_to_link() which can return NULL if the
> link is being removed, but the return value was dereferenced without
> checking. Similarly, the RCU-protected link_conf and link_sta pointers
> were used without NULL validation.
>
> This race can occur when:
> - A packet is queued for transmission
> - Concurrently, the link is being removed (mt7925_mac_link_sta_remove)
> - mt792x_sta_to_link() returns NULL for the removed link
> - Kernel crashes on wcid = &mlink->wcid dereference
>
> Fix by checking mlink, conf, and link_sta before use, freeing the SKB
> and returning early if any pointer is NULL.
>
> 2. Fix firmware reload failure after previous load crash:
>
> If the firmware loading process crashes or is interrupted after
> acquiring the patch semaphore but before releasing it, subsequent
> firmware load attempts will fail with 'Failed to get patch semaphore'.
>
> Apply the same fix from MT7915 (commit 79dd14f): release the patch
> semaphore before starting firmware load and restart MCU firmware to
> ensure clean state.
>
> Fixes: c74df1c067f2 ("wifi: mt76: mt792x: introduce mt792x-lib module")
> Fixes: 583204ae70f9 ("wifi: mt76: mt792x: move mt7921_load_firmware in mt792x-lib module")
> Link: https://github.com/openwrt/mt76/commit/79dd14f2e8161b656341b6653261779199aedbe4
> Signed-off-by: Zac Bowling <zac@...bowling.com>
> ---
> .../net/wireless/mediatek/mt76/mt792x_core.c | 27 +++++++++++++++++--
> 1 file changed, 25 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/net/wireless/mediatek/mt76/mt792x_core.c b/drivers/net/wireless/mediatek/mt76/mt792x_core.c
> index f2ed16feb6c1..05598202b488 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt792x_core.c
> +++ b/drivers/net/wireless/mediatek/mt76/mt792x_core.c
> @@ -95,6 +95,8 @@ void mt792x_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control,
> IEEE80211_TX_CTRL_MLO_LINK);
> sta = (struct mt792x_sta *)control->sta->drv_priv;
> mlink = mt792x_sta_to_link(sta, link_id);
> + if (!mlink)
> + goto free_skb;
> wcid = &mlink->wcid;
> }
>
> @@ -113,9 +115,12 @@ void mt792x_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control,
> link_id = wcid->link_id;
> rcu_read_lock();
> conf = rcu_dereference(vif->link_conf[link_id]);
> - memcpy(hdr->addr2, conf->addr, ETH_ALEN);
> -
> link_sta = rcu_dereference(control->sta->link[link_id]);
> + if (!conf || !link_sta) {
> + rcu_read_unlock();
> + goto free_skb;
> + }
> + memcpy(hdr->addr2, conf->addr, ETH_ALEN);
> memcpy(hdr->addr1, link_sta->addr, ETH_ALEN);
>
> if (vif->type == NL80211_IFTYPE_STATION)
> @@ -136,6 +141,10 @@ void mt792x_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control,
> }
>
> mt76_connac_pm_queue_skb(hw, &dev->pm, wcid, skb);
> + return;
> +
> +free_skb:
> + ieee80211_free_txskb(hw, skb);
> }
> EXPORT_SYMBOL_GPL(mt792x_tx);
>
> @@ -927,6 +936,20 @@ int mt792x_load_firmware(struct mt792x_dev *dev)
> {
> int ret;
>
> + /* Release semaphore if taken by previous failed load attempt.
> + * This prevents "Failed to get patch semaphore" errors when
> + * recovering from firmware crashes or suspend/resume failures.
> + */
> + ret = mt76_connac_mcu_patch_sem_ctrl(&dev->mt76, false);
> + if (ret < 0)
> + dev_dbg(dev->mt76.dev, "Semaphore release returned %d (may be expected)\n", ret);
> +
> + /* Always restart MCU to ensure clean state before loading firmware */
> + mt76_connac_mcu_restart(&dev->mt76);
> +
> + /* Wait for MCU to be ready after restart */
> + msleep(100);
> +
> ret = mt76_connac2_load_patch(&dev->mt76, mt792x_patch_name(dev));
> if (ret)
> return ret;
> --
> 2.52.0
>
<formletter>
This is not the correct way to submit patches for inclusion in the
stable kernel tree. Please read:
https://www.kernel.org/doc/html/latest/process/stable-kernel-rules.html
for how to do this properly.
</formletter>
Powered by blists - more mailing lists