From nobody Sun Feb 8 12:36:46 2026 Received: from mail-pg1-f172.google.com (mail-pg1-f172.google.com [209.85.215.172]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9636D30FC3C for ; Fri, 2 Jan 2026 20:05:26 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.215.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1767384328; cv=none; b=T1kFPLgIj/4bLOW22zc4pvVLg5wGh8OfFl99oSLF4QY9bdurU8N40Fqxbevlz1pU6AbdF2eLiC6TDggnp55DBtWULCSs/0qs63sXmSqt55duwdm4Lqn9sJZ6BFQbFCi/Az3tvRPGLGewMxPLro8wHb84Vs7nfJXNM6fq0xr67fg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1767384328; c=relaxed/simple; bh=yjtYcRRkKQqQtoPpO8wa+reKIsluW1SFisMiniS49Js=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=XjztI6x7XUsrzwIVQD3ImGt7XEmwbNH7B1E25HZR0pnkm+m+FJeC9b0aPDgzrbcCgN4GWheJ9UxalUADWbJriNB1GDWL3+kW2ZsNRxej26yfEYMXtEi8e66A3qwwiygCLtOgABfk3ONH+13mF+mVfpN1QvURlyZyGfbtaZQZq5g= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=OXk+FhmA; arc=none smtp.client-ip=209.85.215.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="OXk+FhmA" Received: by mail-pg1-f172.google.com with SMTP id 41be03b00d2f7-b553412a19bso11654639a12.1 for ; Fri, 02 Jan 2026 12:05:26 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1767384326; x=1767989126; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=Ncj038f085969Nim0LRgx0ReaJFA7+G2XHIbBniHkeA=; b=OXk+FhmA4uZtkWXjS6DoBViAoRGtlvmmipgNj6PnDecoT0jFp6VDlYj5c5G8TXNiLM CwjL+XuqV4o/dyKefHiK5Q2ZZymwWccWp9mfRPUdoF44S/IEh+fFv0kdSi7g48SEdPhE fabNo/4qa3pBdFkhFGWAKsENyj+NKoLXllUOPds2sva0//EdDIHXhhZmKlH46wP/o7Bg q/lTs5ofoqNzVIFTxrnf9zqToXra3rto00adxR3YevEJJlIiDP7j/qaO8pG/RFnn0TJT evI4cvM3MTe9egm64AXYK8UmgleTlj7d6sxZhk89fYYt2++suWIQCQECwKyOTwSha1uC g5GA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1767384326; x=1767989126; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=Ncj038f085969Nim0LRgx0ReaJFA7+G2XHIbBniHkeA=; b=r/vXaYoBbQLyuZQFWp2gVkGzXxlm8wLbKkAr+DRVaYe5NPCpgV/ve/eY8Y2mw5KqWx JgBrkjKOXpSEXe1dB//kn4vLq8LWBW/S38i0iIb4c05r0bd94nX8pjHjeMv+/x7Z3O+5 UI5B3Ujjtn1lh2aFMx/0rW7NVSSZFeEb+Jv0aLg24drM+dKJLshyHyWXQN6m8IqKrdZP 9yrMzMwU9PvBDlx1If6fiq7QcoQOnPMs8FSnY1jmYZlss/dy87/AwVzAtkbWWdVHrLhg baK+UjmNxDN3Fn9MipeMXVI/spyeccaC0iaVJQA0Ixgpj4tFwckTog1Lf3vJqWCM4EXs 6CiQ== X-Forwarded-Encrypted: i=1; AJvYcCXFV52i9erQ0GO6foeqLCRJpM8O9cWmAgurzOhxM1E1wD9QSnlkxual0U1pueOIvcHBDkgAv+sJD8BcDc0=@vger.kernel.org X-Gm-Message-State: AOJu0YyF6Bvh7qt43ZzsdBabCdZU14Nn4idLzVrTjZdsUznuj43l090t LV8jrxW38jkmphR6YXM0z9JT5riLk66AWGS7FUQ73K8oGRwCBg9jfdD+ X-Gm-Gg: AY/fxX6iIUN3JF90MkBerY0WwnpnNEu0XFWSF31CaI3/nPneEw3BXG0nqRIS+0K9Dk+ k0vLnM9j5Erxy3tU3Bcs5Cdx37DNoztArP//Mjcx2W3EJ7rRwklvEcK/aEPP6oNG/UHJP3O7fvr DRur4fKb5GDC2J6bsUUbsVyHVTiLJhJw91NTa8wj8yJU/HEXexa/48MXI6kZLV945K5X7wTWaOZ 2t9M6oIAdyFIVEsSHY26nX/thjFUVNP1ABll5ucSDCX/PN9PAjS2ItmK3jYgqTosgXiwd3LPPhw 6ZzmvhMy2owqqBjDuQfOyhMHcf3KKHsmK1GJq2wiES/F+rS4Z7Rg0ossFK9h+iod/WOgvsgMxF7 YjGUaATeUj6BN5QSeD5x5WcasCtifCKLj+U5XmTMrRwWECR3AkZtQ8EJvy7ImGIH0GMXiJyApUM UTfFllqW9oEutmiIe9VR+FxPpuYn/UpOA/R6mduhhuCzQ9U0y9U9Hr/9ihckIpgoo= X-Google-Smtp-Source: AGHT+IEJMTl9orAyZvANwo9RkNPL17koGUPtHZ7Z0I9llFHsfMfuhxzZ4nXZhxh8hKJD/wdxKzAyLA== X-Received: by 2002:a05:7301:100f:b0:2b0:4e86:8163 with SMTP id 5a478bee46e88-2b05ec02fffmr39900309eec.13.1767384325632; Fri, 02 Jan 2026 12:05:25 -0800 (PST) Received: from zubuntu.bengal-mercat.ts.net ([2001:5a8:60d:bc9:9ebf:dff:fe00:f8f2]) by smtp.gmail.com with ESMTPSA id 5a478bee46e88-2b140c42e38sm1983337eec.34.2026.01.02.12.05.24 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 02 Jan 2026 12:05:25 -0800 (PST) From: Zac Bowling To: zbowling@gmail.com Cc: deren.wu@mediatek.com, kvalo@kernel.org, linux-kernel@vger.kernel.org, linux-mediatek@lists.infradead.org, linux-wireless@vger.kernel.org, lorenzo@kernel.org, nbd@nbd.name, ryder.lee@mediatek.com, sean.wang@mediatek.com Subject: [PATCH] wifi: mt76: mt7925: comprehensive stability fixes Date: Fri, 2 Jan 2026 12:05:24 -0800 Message-ID: <20260102200524.290779-1-zbowling@gmail.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260102200315.290015-1-zbowling@gmail.com> References: <20260102200315.290015-1-zbowling@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Zac Bowling This unified patch combines all MT7925 driver fixes for kernel stability: 1. NULL pointer dereference fixes in vif iteration, TX path, and MCU functi= ons 2. Missing mutex protection in reset, ROC, PM, and resume paths 3. Error handling for MCU commands (AMPDU, BSS info, key setup) 4. lockdep assertions for debugging 5. MLO (Multi-Link Operation) improvements for roaming and AP mode 6. Firmware reload recovery after crashes These fixes address kernel panics and system hangs that occur during: - WiFi network switching and BSSID roaming - Suspend/resume cycles - MLO link state transitions - Firmware recovery after crashes Tested on Framework Desktop (AMD Ryzen AI Max 300) with MT7925 (RZ717). Individual patches and detailed analysis available at: https://github.com/zbowling/mt7925 Signed-off-by: Zac Bowling --- diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/init.c b/drivers/net= /wireless/mediatek/mt76/mt7925/init.c index d7d5afe365ed..f800112ccaf7 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7925/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7925/init.c @@ -162,10 +162,17 @@ void mt7925_regd_update(struct mt792x_dev *dev) if (!dev->regd_change) return; =20 - mt7925_mcu_set_clc(dev, mdev->alpha2, dev->country_ie_env); + if (mt7925_mcu_set_clc(dev, mdev->alpha2, dev->country_ie_env) < 0) + dev_warn(dev->mt76.dev, "Failed to set CLC\n"); + mt7925_regd_channel_update(wiphy, dev); - mt7925_mcu_set_channel_domain(hw->priv); - mt7925_set_tx_sar_pwr(hw, NULL); + + if (mt7925_mcu_set_channel_domain(hw->priv) < 0) + dev_warn(dev->mt76.dev, "Failed to set channel domain\n"); + + if (mt7925_set_tx_sar_pwr(hw, NULL) < 0) + dev_warn(dev->mt76.dev, "Failed to set TX SAR power\n"); + dev->regd_change =3D false; } EXPORT_SYMBOL_GPL(mt7925_regd_update); diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/mac.c b/drivers/net/= wireless/mediatek/mt76/mt7925/mac.c index 1e44e96f034e..a4109dc72163 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7925/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7925/mac.c @@ -1270,6 +1270,12 @@ mt7925_vif_connect_iter(void *priv, u8 *mac, bss_conf =3D mt792x_vif_to_bss_conf(vif, i); mconf =3D mt792x_vif_to_link(mvif, i); =20 + /* Skip links that don't have bss_conf set up yet in mac80211. + * This can happen during HW reset when link state is inconsistent. + */ + if (!bss_conf) + continue; + mt76_connac_mcu_uni_add_dev(&dev->mphy, bss_conf, &mconf->mt76, &mvif->sta.deflink.wcid, true); mt7925_mcu_set_tx(dev, bss_conf); @@ -1324,9 +1330,11 @@ void mt7925_mac_reset_work(struct work_struct *work) dev->hw_full_reset =3D false; pm->suspended =3D false; ieee80211_wake_queues(hw); + mt792x_mutex_acquire(dev); ieee80211_iterate_active_interfaces(hw, IEEE80211_IFACE_ITER_RESUME_ALL, mt7925_vif_connect_iter, NULL); + mt792x_mutex_release(dev); mt76_connac_power_save_sched(&dev->mt76.phy, pm); =20 mt792x_mutex_acquire(dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/main.c b/drivers/net= /wireless/mediatek/mt76/mt7925/main.c index ac3d485a2f78..b6e3002faf41 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7925/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7925/main.c @@ -596,6 +596,17 @@ static int mt7925_set_link_key(struct ieee80211_hw *hw= , enum set_key_cmd cmd, link_sta =3D sta ? mt792x_sta_to_link_sta(vif, sta, link_id) : NULL; mconf =3D mt792x_vif_to_link(mvif, link_id); mlink =3D mt792x_sta_to_link(msta, link_id); + + if (!link_conf || !mconf || !mlink) { + /* During MLO roaming, link state may be torn down before + * mac80211 requests key removal. If removing a key and + * the link is already gone, consider it successfully removed. + */ + if (cmd !=3D SET_KEY) + return 0; + return -EINVAL; + } + wcid =3D &mlink->wcid; wcid_keyidx =3D &wcid->hw_key_idx; =20 @@ -625,8 +636,10 @@ static int mt7925_set_link_key(struct ieee80211_hw *hw= , enum set_key_cmd cmd, struct mt792x_phy *phy =3D mt792x_hw_phy(hw); =20 mconf->mt76.cipher =3D mt7925_mcu_get_cipher(key->cipher); - mt7925_mcu_add_bss_info(phy, mconf->mt76.ctx, link_conf, - link_sta, true); + err =3D mt7925_mcu_add_bss_info(phy, mconf->mt76.ctx, link_conf, + link_sta, true); + if (err) + goto out; } =20 if (cmd =3D=3D SET_KEY) @@ -743,9 +756,11 @@ void mt7925_set_runtime_pm(struct mt792x_dev *dev) bool monitor =3D !!(hw->conf.flags & IEEE80211_CONF_MONITOR); =20 pm->enable =3D pm->enable_user && !monitor; + mt792x_mutex_acquire(dev); ieee80211_iterate_active_interfaces(hw, IEEE80211_IFACE_ITER_RESUME_ALL, mt7925_pm_interface_iter, dev); + mt792x_mutex_release(dev); pm->ds_enable =3D pm->ds_enable_user && !monitor; mt7925_mcu_set_deep_sleep(dev, pm->ds_enable); } @@ -848,12 +863,17 @@ static int mt7925_mac_link_sta_add(struct mt76_dev *m= dev, =20 msta =3D (struct mt792x_sta *)link_sta->sta->drv_priv; mlink =3D mt792x_sta_to_link(msta, link_id); + if (!mlink) + return -EINVAL; =20 idx =3D mt76_wcid_alloc(dev->mt76.wcid_mask, MT792x_WTBL_STA - 1); if (idx < 0) return -ENOSPC; =20 mconf =3D mt792x_vif_to_link(mvif, link_id); + if (!mconf) + return -EINVAL; + mt76_wcid_init(&mlink->wcid, 0); mlink->wcid.sta =3D 1; mlink->wcid.idx =3D idx; @@ -879,15 +899,20 @@ static int mt7925_mac_link_sta_add(struct mt76_dev *m= dev, MT_WTBL_UPDATE_ADM_COUNT_CLEAR); =20 link_conf =3D mt792x_vif_to_bss_conf(vif, link_id); + if (!link_conf) + return -EINVAL; =20 /* should update bss info before STA add */ if (vif->type =3D=3D NL80211_IFTYPE_STATION && !link_sta->sta->tdls) { if (ieee80211_vif_is_mld(vif)) - mt7925_mcu_add_bss_info(&dev->phy, mconf->mt76.ctx, - link_conf, link_sta, link_sta !=3D mlink->pri_link); + ret =3D mt7925_mcu_add_bss_info(&dev->phy, mconf->mt76.ctx, + link_conf, link_sta, + link_sta !=3D mlink->pri_link); else - mt7925_mcu_add_bss_info(&dev->phy, mconf->mt76.ctx, - link_conf, link_sta, false); + ret =3D mt7925_mcu_add_bss_info(&dev->phy, mconf->mt76.ctx, + link_conf, link_sta, false); + if (ret) + return ret; } =20 if (ieee80211_vif_is_mld(vif) && @@ -985,18 +1010,29 @@ mt7925_mac_set_links(struct mt76_dev *mdev, struct i= eee80211_vif *vif) { struct mt792x_dev *dev =3D container_of(mdev, struct mt792x_dev, mt76); struct mt792x_vif *mvif =3D (struct mt792x_vif *)vif->drv_priv; - struct ieee80211_bss_conf *link_conf =3D - mt792x_vif_to_bss_conf(vif, mvif->deflink_id); - struct cfg80211_chan_def *chandef =3D &link_conf->chanreq.oper; - enum nl80211_band band =3D chandef->chan->band, secondary_band; + struct ieee80211_bss_conf *link_conf; + struct cfg80211_chan_def *chandef; + enum nl80211_band band, secondary_band; + u16 sel_links; + u8 secondary_link_id; + + link_conf =3D mt792x_vif_to_bss_conf(vif, mvif->deflink_id); + if (!link_conf) + return; + + chandef =3D &link_conf->chanreq.oper; + band =3D chandef->chan->band; =20 - u16 sel_links =3D mt76_select_links(vif, 2); - u8 secondary_link_id =3D __ffs(~BIT(mvif->deflink_id) & sel_links); + sel_links =3D mt76_select_links(vif, 2); + secondary_link_id =3D __ffs(~BIT(mvif->deflink_id) & sel_links); =20 if (!ieee80211_vif_is_mld(vif) || hweight16(sel_links) < 2) return; =20 link_conf =3D mt792x_vif_to_bss_conf(vif, secondary_link_id); + if (!link_conf) + return; + secondary_band =3D link_conf->chanreq.oper.chan->band; =20 if (band =3D=3D NL80211_BAND_2GHZ || @@ -1024,6 +1060,8 @@ static void mt7925_mac_link_sta_assoc(struct mt76_dev= *mdev, =20 msta =3D (struct mt792x_sta *)link_sta->sta->drv_priv; mlink =3D mt792x_sta_to_link(msta, link_sta->link_id); + if (!mlink) + return; =20 mt792x_mutex_acquire(dev); =20 @@ -1033,12 +1071,13 @@ static void mt7925_mac_link_sta_assoc(struct mt76_d= ev *mdev, link_conf =3D mt792x_vif_to_bss_conf(vif, vif->bss_conf.link_id); } =20 - if (vif->type =3D=3D NL80211_IFTYPE_STATION && !link_sta->sta->tdls) { + if (link_conf && vif->type =3D=3D NL80211_IFTYPE_STATION && !link_sta->st= a->tdls) { struct mt792x_bss_conf *mconf; =20 mconf =3D mt792x_link_conf_to_mconf(link_conf); - mt7925_mcu_add_bss_info(&dev->phy, mconf->mt76.ctx, - link_conf, link_sta, true); + if (mconf) + mt7925_mcu_add_bss_info(&dev->phy, mconf->mt76.ctx, + link_conf, link_sta, true); } =20 ewma_avg_signal_init(&mlink->avg_ack_signal); @@ -1085,6 +1124,8 @@ static void mt7925_mac_link_sta_remove(struct mt76_de= v *mdev, =20 msta =3D (struct mt792x_sta *)link_sta->sta->drv_priv; mlink =3D mt792x_sta_to_link(msta, link_id); + if (!mlink) + return; =20 mt7925_roc_abort_sync(dev); =20 @@ -1098,10 +1139,12 @@ static void mt7925_mac_link_sta_remove(struct mt76_= dev *mdev, =20 link_conf =3D mt792x_vif_to_bss_conf(vif, link_id); =20 - if (vif->type =3D=3D NL80211_IFTYPE_STATION && !link_sta->sta->tdls) { + if (link_conf && vif->type =3D=3D NL80211_IFTYPE_STATION && !link_sta->st= a->tdls) { struct mt792x_bss_conf *mconf; =20 mconf =3D mt792x_link_conf_to_mconf(link_conf); + if (!mconf) + goto out; =20 if (ieee80211_vif_is_mld(vif)) mt792x_mac_link_bss_remove(dev, mconf, mlink); @@ -1109,6 +1152,7 @@ static void mt7925_mac_link_sta_remove(struct mt76_de= v *mdev, mt7925_mcu_add_bss_info(&dev->phy, mconf->mt76.ctx, link_conf, link_sta, false); } +out: =20 spin_lock_bh(&mdev->sta_poll_lock); if (!list_empty(&mlink->wcid.poll_list)) @@ -1247,22 +1291,22 @@ mt7925_ampdu_action(struct ieee80211_hw *hw, struct= ieee80211_vif *vif, case IEEE80211_AMPDU_RX_START: mt76_rx_aggr_start(&dev->mt76, &msta->deflink.wcid, tid, ssn, params->buf_size); - mt7925_mcu_uni_rx_ba(dev, params, true); + ret =3D mt7925_mcu_uni_rx_ba(dev, params, true); break; case IEEE80211_AMPDU_RX_STOP: mt76_rx_aggr_stop(&dev->mt76, &msta->deflink.wcid, tid); - mt7925_mcu_uni_rx_ba(dev, params, false); + ret =3D mt7925_mcu_uni_rx_ba(dev, params, false); break; case IEEE80211_AMPDU_TX_OPERATIONAL: mtxq->aggr =3D true; mtxq->send_bar =3D false; - mt7925_mcu_uni_tx_ba(dev, params, true); + ret =3D mt7925_mcu_uni_tx_ba(dev, params, true); break; case IEEE80211_AMPDU_TX_STOP_FLUSH: case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT: mtxq->aggr =3D false; clear_bit(tid, &msta->deflink.wcid.ampdu_state); - mt7925_mcu_uni_tx_ba(dev, params, false); + ret =3D mt7925_mcu_uni_tx_ba(dev, params, false); break; case IEEE80211_AMPDU_TX_START: set_bit(tid, &msta->deflink.wcid.ampdu_state); @@ -1271,8 +1315,9 @@ mt7925_ampdu_action(struct ieee80211_hw *hw, struct i= eee80211_vif *vif, case IEEE80211_AMPDU_TX_STOP_CONT: mtxq->aggr =3D false; clear_bit(tid, &msta->deflink.wcid.ampdu_state); - mt7925_mcu_uni_tx_ba(dev, params, false); - ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); + ret =3D mt7925_mcu_uni_tx_ba(dev, params, false); + if (!ret) + ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); break; } mt792x_mutex_release(dev); @@ -1293,12 +1338,12 @@ mt7925_mlo_pm_iter(void *priv, u8 *mac, struct ieee= 80211_vif *vif) if (mvif->mlo_pm_state !=3D MT792x_MLO_CHANGED_PS) return; =20 - mt792x_mutex_acquire(dev); for_each_set_bit(i, &valid, IEEE80211_MLD_MAX_NUM_LINKS) { bss_conf =3D mt792x_vif_to_bss_conf(vif, i); + if (!bss_conf) + continue; mt7925_mcu_uni_bss_ps(dev, bss_conf); } - mt792x_mutex_release(dev); } =20 void mt7925_mlo_pm_work(struct work_struct *work) @@ -1307,9 +1352,11 @@ void mt7925_mlo_pm_work(struct work_struct *work) mlo_pm_work.work); struct ieee80211_hw *hw =3D mt76_hw(dev); =20 + mt792x_mutex_acquire(dev); ieee80211_iterate_active_interfaces(hw, IEEE80211_IFACE_ITER_RESUME_ALL, mt7925_mlo_pm_iter, dev); + mt792x_mutex_release(dev); } =20 static bool is_valid_alpha2(const char *alpha2) @@ -1645,6 +1692,8 @@ static void mt7925_ipv6_addr_change(struct ieee80211_= hw *hw, =20 for_each_set_bit(i, &valid, IEEE80211_MLD_MAX_NUM_LINKS) { bss_conf =3D mt792x_vif_to_bss_conf(vif, i); + if (!bss_conf) + continue; __mt7925_ipv6_addr_change(hw, bss_conf, idev); } } @@ -1706,6 +1755,9 @@ mt7925_conf_tx(struct ieee80211_hw *hw, struct ieee80= 211_vif *vif, [IEEE80211_AC_BK] =3D 1, }; =20 + if (!mconf) + return -EINVAL; + /* firmware uses access class index */ mconf->queue_params[mq_to_aci[queue]] =3D *params; =20 @@ -1876,6 +1928,8 @@ static void mt7925_vif_cfg_changed(struct ieee80211_h= w *hw, if (changed & BSS_CHANGED_ARP_FILTER) { for_each_set_bit(i, &valid, IEEE80211_MLD_MAX_NUM_LINKS) { bss_conf =3D mt792x_vif_to_bss_conf(vif, i); + if (!bss_conf) + continue; mt7925_mcu_update_arp_filter(&dev->mt76, bss_conf); } } @@ -1891,6 +1945,8 @@ static void mt7925_vif_cfg_changed(struct ieee80211_h= w *hw, } else if (mvif->mlo_pm_state =3D=3D MT792x_MLO_CHANGED_PS) { for_each_set_bit(i, &valid, IEEE80211_MLD_MAX_NUM_LINKS) { bss_conf =3D mt792x_vif_to_bss_conf(vif, i); + if (!bss_conf) + continue; mt7925_mcu_uni_bss_ps(dev, bss_conf); } } @@ -1912,7 +1968,12 @@ static void mt7925_link_info_changed(struct ieee8021= 1_hw *hw, struct ieee80211_bss_conf *link_conf; =20 mconf =3D mt792x_vif_to_link(mvif, info->link_id); + if (!mconf) + return; + link_conf =3D mt792x_vif_to_bss_conf(vif, mconf->link_id); + if (!link_conf) + return; =20 mt792x_mutex_acquire(dev); =20 @@ -2033,6 +2094,11 @@ mt7925_change_vif_links(struct ieee80211_hw *hw, str= uct ieee80211_vif *vif, mlink =3D mlinks[link_id]; link_conf =3D mt792x_vif_to_bss_conf(vif, link_id); =20 + if (!link_conf) { + err =3D -EINVAL; + goto free; + } + rcu_assign_pointer(mvif->link_conf[link_id], mconf); rcu_assign_pointer(mvif->sta.link[link_id], mlink); =20 @@ -2113,9 +2179,14 @@ static int mt7925_assign_vif_chanctx(struct ieee8021= 1_hw *hw, =20 if (ieee80211_vif_is_mld(vif)) { mconf =3D mt792x_vif_to_link(mvif, link_conf->link_id); + if (!mconf) { + mutex_unlock(&dev->mt76.mutex); + return -EINVAL; + } + pri_link_conf =3D mt792x_vif_to_bss_conf(vif, mvif->deflink_id); =20 - if (vif->type =3D=3D NL80211_IFTYPE_STATION && + if (pri_link_conf && vif->type =3D=3D NL80211_IFTYPE_STATION && mconf =3D=3D &mvif->bss_conf) mt7925_mcu_add_bss_info(&dev->phy, NULL, pri_link_conf, NULL, true); @@ -2144,6 +2215,10 @@ static void mt7925_unassign_vif_chanctx(struct ieee8= 0211_hw *hw, =20 if (ieee80211_vif_is_mld(vif)) { mconf =3D mt792x_vif_to_link(mvif, link_conf->link_id); + if (!mconf) { + mutex_unlock(&dev->mt76.mutex); + return; + } =20 if (vif->type =3D=3D NL80211_IFTYPE_STATION && mconf =3D=3D &mvif->bss_conf) diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c b/drivers/net/= wireless/mediatek/mt76/mt7925/mcu.c index 8eda407e4135..cf38e36790e7 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c @@ -1722,6 +1722,10 @@ mt7925_mcu_sta_phy_tlv(struct sk_buff *skb, =20 link_conf =3D mt792x_vif_to_bss_conf(vif, link_sta->link_id); mconf =3D mt792x_vif_to_link(mvif, link_sta->link_id); + + if (!link_conf || !mconf) + return; + chandef =3D mconf->mt76.ctx ? &mconf->mt76.ctx->def : &link_conf->chanreq.oper; =20 @@ -1800,6 +1804,10 @@ mt7925_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, =20 link_conf =3D mt792x_vif_to_bss_conf(vif, link_sta->link_id); mconf =3D mt792x_vif_to_link(mvif, link_sta->link_id); + + if (!link_conf || !mconf) + return; + chandef =3D mconf->mt76.ctx ? &mconf->mt76.ctx->def : &link_conf->chanreq.oper; band =3D chandef->chan->band; diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/pci.c b/drivers/net/= wireless/mediatek/mt76/mt7925/pci.c index 8eb1fe1082d1..b6c90c5f7e91 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7925/pci.c +++ b/drivers/net/wireless/mediatek/mt76/mt7925/pci.c @@ -454,7 +454,9 @@ static int mt7925_pci_suspend(struct device *device) cancel_delayed_work_sync(&pm->ps_work); cancel_work_sync(&pm->wake_work); =20 + mt792x_mutex_acquire(dev); mt7925_roc_abort_sync(dev); + mt792x_mutex_release(dev); =20 err =3D mt792x_mcu_drv_pmctrl(dev); if (err < 0) @@ -581,10 +583,12 @@ static int _mt7925_pci_resume(struct device *device, = bool restore) } =20 /* restore previous ds setting */ + mt792x_mutex_acquire(dev); if (!pm->ds_enable) mt7925_mcu_set_deep_sleep(dev, false); =20 mt7925_regd_update(dev); + mt792x_mutex_release(dev); failed: pm->suspended =3D false; =20 diff --git a/drivers/net/wireless/mediatek/mt76/mt792x_core.c b/drivers/net= /wireless/mediatek/mt76/mt792x_core.c index 9cad572c34a3..0170a23b0529 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 =3D (struct mt792x_sta *)control->sta->drv_priv; mlink =3D mt792x_sta_to_link(sta, link_id); + if (!mlink) + goto free_skb; wcid =3D &mlink->wcid; } =20 @@ -113,9 +115,12 @@ void mt792x_tx(struct ieee80211_hw *hw, struct ieee802= 11_tx_control *control, link_id =3D wcid->link_id; rcu_read_lock(); conf =3D rcu_dereference(vif->link_conf[link_id]); - memcpy(hdr->addr2, conf->addr, ETH_ALEN); - link_sta =3D 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); =20 if (vif->type =3D=3D NL80211_IFTYPE_STATION) @@ -136,6 +141,10 @@ void mt792x_tx(struct ieee80211_hw *hw, struct ieee802= 11_tx_control *control, } =20 mt76_connac_pm_queue_skb(hw, &dev->pm, wcid, skb); + return; + +free_skb: + ieee80211_free_txskb(hw, skb); } EXPORT_SYMBOL_GPL(mt792x_tx);