FAILED: patch "[PATCH] wifi: mac80211: keep paired old chanctx alive" failed to apply to 6.6-stable tree
Subsystems (2)
[email protected]
maintainerThe patch below does not apply to the 6.6-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-6.6.y
git checkout FETCH_HEAD
git cherry-pick -x 3412e9a800786d1dec4a58367db1cba275e7ef11
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2026100550-agreeing-enamel-9da2@gregkh' --subject-prefix 'PATCH 6.6.y' 'HEAD^..'
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 3412e9a800786d1dec4a58367db1cba275e7ef11 Mon Sep 17 00:00:00 2001
From: Zhiling Zou <[email protected]>
Date: Mon, 3 Aug 2026 12:35:10 +0800
Subject: [PATCH] wifi: mac80211: keep paired old chanctx alive
An in-place replacement keeps reciprocal replace_ctx pointers between the old WILL_BE_REPLACED chanctx and the new REPLACES_OTHER chanctx. However, the early free paths only consider assigned and reserved link users when deciding whether to free the old chanctx.
That lets the old chanctx be freed too early while the replacement partner still points back to it, either when the last assigned link is released or when that link successfully reassigns to another existing context. Later unreserve and switch-finalization paths can then follow a stale replace_ctx pointer.
Keep a paired old chanctx alive until the replacement pair has been torn down. Apply the same check to both __ieee80211_link_release_channel() and ieee80211_link_use_reserved_reassign(). If the replacement is later abandoned, ieee80211_link_unreserve_chanctx() already tears down the pairing before freeing the old chanctx once no users remain.
net/mac80211/chan.c +18 -2
@@ -231,6 +231,13 @@ int ieee80211_chanctx_refcount(struct ieee80211_local *local,return num; } +static bool +ieee80211_chanctx_has_replace_partner (struct ieee80211_chanctx *ctx) +{ +return ctx->replace_state ==IEEE80211_CHANCTX_WILL_BE_REPLACED && + ctx->replace_ctx; +} +static int ieee80211_num_chanctx (struct ieee80211_local *local,int radio_idx) {struct ieee80211_chanctx *ctx;
@@ -1405,6 +1412,7 @@ void ieee80211_link_unreserve_chanctx(struct ieee80211_link_data *link) {struct ieee80211_sub_if_data *sdata = link->sdata;struct ieee80211_chanctx *ctx = link->reserved_chanctx; +struct ieee80211_chanctx *old_ctx =NULL ;lockdep_assert_wiphy (sdata->local->hw.wiphy);
@@ -1418,6 +1426,7 @@ void ieee80211_link_unreserve_chanctx(struct ieee80211_link_data *link)if (WARN_ON (!ctx->replace_ctx))return ; + old_ctx = ctx->replace_ctx;WARN_ON (ctx->replace_ctx->replace_state !=IEEE80211_CHANCTX_WILL_BE_REPLACED );WARN_ON (ctx->replace_ctx->replace_ctx != ctx);
@@ -1428,6 +1437,11 @@ void ieee80211_link_unreserve_chanctx(struct ieee80211_link_data *link)list_del_rcu (&ctx->list);kfree_rcu (ctx, rcu_head); + +if (ieee80211_chanctx_refcount (sdata->local, + old_ctx) ==0 ) +ieee80211_free_chanctx (sdata->local, old_ctx, + false); }else {ieee80211_free_chanctx (sdata->local, ctx, false); }
@@ -1707,7 +1721,8 @@ ieee80211_link_use_reserved_reassign(struct ieee80211_link_data *link)ieee80211_check_fast_xmit_iface (sdata); -if (ieee80211_chanctx_refcount (local, old_ctx) ==0 ) +if (ieee80211_chanctx_refcount (local, old_ctx) ==0 && + !ieee80211_chanctx_has_replace_partner (old_ctx))ieee80211_free_chanctx (local, old_ctx, false);ieee80211_recalc_chanctx_min_def (local, new_ctx);
@@ -2192,7 +2207,8 @@ void __ieee80211_link_release_channel(struct ieee80211_link_data *link, }ieee80211_assign_link_chanctx (link,NULL , false); -if (ieee80211_chanctx_refcount (local, ctx) ==0 ) +if (ieee80211_chanctx_refcount (local, ctx) ==0 && + !ieee80211_chanctx_has_replace_partner (ctx))ieee80211_free_chanctx (local, ctx, skip_idle_recalc); link->radar_required = false;
Sasha Levin
maintainerPATCH 1/1 wifi: mac80211: keep paired old chanctx alive
From: Zhiling Zou <[email protected]>
[ Upstream commit 3412e9a800786d1dec4a58367db1cba275e7ef11 ]
An in-place replacement keeps reciprocal replace_ctx pointers between the old WILL_BE_REPLACED chanctx and the new REPLACES_OTHER chanctx. However, the early free paths only consider assigned and reserved link users when deciding whether to free the old chanctx.
That lets the old chanctx be freed too early while the replacement partner still points back to it, either when the last assigned link is released or when that link successfully reassigns to another existing context. Later unreserve and switch-finalization paths can then follow a stale replace_ctx pointer.
Keep a paired old chanctx alive until the replacement pair has been torn down. Apply the same check to both __ieee80211_link_release_channel() and ieee80211_link_use_reserved_reassign(). If the replacement is later abandoned, ieee80211_link_unreserve_chanctx() already tears down the pairing before freeing the old chanctx once no users remain.
--- net/mac80211/chan.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-)
net/mac80211/chan.c +12 -2
@@ -1067,6 +1067,7 @@ int ieee80211_link_unreserve_chanctx(struct ieee80211_link_data *link) {struct ieee80211_sub_if_data *sdata = link->sdata;struct ieee80211_chanctx *ctx = link->reserved_chanctx; +struct ieee80211_chanctx *old_ctx =NULL ;lockdep_assert_held (&sdata->local->chanctx_mtx);
@@ -1081,6 +1082,7 @@ int ieee80211_link_unreserve_chanctx(struct ieee80211_link_data *link)if (WARN_ON (!ctx->replace_ctx))return -EINVAL ; + old_ctx = ctx->replace_ctx;WARN_ON (ctx->replace_ctx->replace_state !=IEEE80211_CHANCTX_WILL_BE_REPLACED );WARN_ON (ctx->replace_ctx->replace_ctx != ctx);
@@ -1091,6 +1093,10 @@ int ieee80211_link_unreserve_chanctx(struct ieee80211_link_data *link)list_del_rcu (&ctx->list);kfree_rcu (ctx, rcu_head); + +if (ieee80211_chanctx_refcount (sdata->local, + old_ctx) ==0 ) +ieee80211_free_chanctx (sdata->local, old_ctx); }else {ieee80211_free_chanctx (sdata->local, ctx); }
@@ -1322,7 +1328,9 @@ ieee80211_link_use_reserved_reassign(struct ieee80211_link_data *link)ieee80211_check_fast_xmit_iface (sdata); -if (ieee80211_chanctx_refcount (local, old_ctx) ==0 ) +if (ieee80211_chanctx_refcount (local, old_ctx) ==0 && + !(old_ctx->replace_state ==IEEE80211_CHANCTX_WILL_BE_REPLACED && + old_ctx->replace_ctx))ieee80211_free_chanctx (local, old_ctx);ieee80211_recalc_chanctx_min_def (local, new_ctx,NULL );
@@ -1802,7 +1810,9 @@ static void __ieee80211_link_release_channel(struct ieee80211_link_data *link) }ieee80211_assign_link_chanctx (link,NULL ); -if (ieee80211_chanctx_refcount (local, ctx) ==0 ) +if (ieee80211_chanctx_refcount (local, ctx) ==0 && + !(ctx->replace_state ==IEEE80211_CHANCTX_WILL_BE_REPLACED && + ctx->replace_ctx))ieee80211_free_chanctx (local, ctx); link->radar_required = false;
Signature · 1 line
2.53.0