summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2024-03-11 12:28:15 +0100
committeriwlwifi publisher <>2024-04-17 13:35:30 +0000
commitd812b888da464f49b4ceadbccf0d298f7efe4922 (patch)
tree948bcfca64eb2f0cdf92574b3daae8a043f1c49c
parentcb9f67d71ad77ace6f175931f0426c873db1e6cf (diff)
downloadbackport-iwlwifi-d812b888da464f49b4ceadbccf0d298f7efe4922.tar.gz
[BUGFIX] wifi: mac80211: don't enter idle during link switch
When doing link switch with a disjoint set of links before and after the switch, we end up removing all channel contexts, adding new ones later. This looks like 'idle' to the code now, and we enter idle which also includes flushing queues. But we can't actually flush since we don't have a link active (bound to a channel context), and entering idle just to leave it again is also wrong. Fix this by passing through an indication that we shouldn't do any idle checks in this case. type=bugfix fixes=unknown ticket=jira:WIFI-394211 Change-Id: If4a522a9dd3133b91983854b909a4de13aa635da Signed-off-by: Johannes Berg <johannes.berg@intel.com> Reviewed-on: https://gerritwcs.ir.intel.com/c/iwlwifi-stack-dev/+/98541 automatic-review: iil_jenkins iil_jenkins <EC.GER.UNIX.IIL.JENKINS@INTEL.COM> tested: iil_jenkins iil_jenkins <EC.GER.UNIX.IIL.JENKINS@INTEL.COM> Tested-by: iil_jenkins iil_jenkins <EC.GER.UNIX.IIL.JENKINS@INTEL.COM> Reviewed-by: Miriam Rachel Korenblit <miriam.rachel.korenblit@intel.com> (cherry picked from commit 058c30f1131e35607277dc2561a66eb4ee3590a3) Reviewed-on: https://gerritwcs.ir.intel.com/c/iwlwifi-stack-dev/+/98264 Reviewed-by: Golan Ben Ami <golan.ben.ami@intel.com> PerCI-Ready: Golan Ben Ami <golan.ben.ami@intel.com> x-iwlwifi-stack-dev: 4f70dc32c2a2f96cb53f44cd683dd7b061f0fbbd
-rw-r--r--net/mac80211/chan.c34
-rw-r--r--net/mac80211/ieee80211_i.h2
-rw-r--r--net/mac80211/link.c2
-rw-r--r--versions3
4 files changed, 24 insertions, 17 deletions
diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c
index 80e4b97841..5a7fb0e4f8 100644
--- a/net/mac80211/chan.c
+++ b/net/mac80211/chan.c
@@ -695,26 +695,29 @@ ieee80211_new_chanctx(struct ieee80211_local *local,
}
static void ieee80211_del_chanctx(struct ieee80211_local *local,
- struct ieee80211_chanctx *ctx)
+ struct ieee80211_chanctx *ctx,
+ bool skip_idle_recalc)
{
lockdep_assert_wiphy(local->hw.wiphy);
drv_remove_chanctx(local, ctx);
- ieee80211_recalc_idle(local);
+ if (!skip_idle_recalc)
+ ieee80211_recalc_idle(local);
ieee80211_remove_wbrf(local, &ctx->conf.def);
}
static void ieee80211_free_chanctx(struct ieee80211_local *local,
- struct ieee80211_chanctx *ctx)
+ struct ieee80211_chanctx *ctx,
+ bool skip_idle_recalc)
{
lockdep_assert_wiphy(local->hw.wiphy);
WARN_ON_ONCE(ieee80211_chanctx_refcount(local, ctx) != 0);
list_del_rcu(&ctx->list);
- ieee80211_del_chanctx(local, ctx);
+ ieee80211_del_chanctx(local, ctx, skip_idle_recalc);
kfree_rcu(ctx, rcu_head);
}
@@ -1002,7 +1005,7 @@ int ieee80211_link_unreserve_chanctx(struct ieee80211_link_data *link)
list_del_rcu(&ctx->list);
kfree_rcu(ctx, rcu_head);
} else {
- ieee80211_free_chanctx(sdata->local, ctx);
+ ieee80211_free_chanctx(sdata->local, ctx, false);
}
}
@@ -1218,7 +1221,7 @@ ieee80211_link_use_reserved_reassign(struct ieee80211_link_data *link)
CHANCTX_SWMODE_REASSIGN_VIF);
if (err) {
if (ieee80211_chanctx_refcount(local, new_ctx) == 0)
- ieee80211_free_chanctx(local, new_ctx);
+ ieee80211_free_chanctx(local, new_ctx, false);
goto out;
}
@@ -1232,7 +1235,7 @@ ieee80211_link_use_reserved_reassign(struct ieee80211_link_data *link)
ieee80211_check_fast_xmit_iface(sdata);
if (ieee80211_chanctx_refcount(local, old_ctx) == 0)
- ieee80211_free_chanctx(local, old_ctx);
+ ieee80211_free_chanctx(local, old_ctx, false);
ieee80211_recalc_chanctx_min_def(local, new_ctx, NULL);
ieee80211_recalc_smps_chanctx(local, new_ctx);
@@ -1286,7 +1289,7 @@ ieee80211_link_use_reserved_assign(struct ieee80211_link_data *link)
err = ieee80211_assign_link_chanctx(link, new_ctx);
if (err) {
if (ieee80211_chanctx_refcount(local, new_ctx) == 0)
- ieee80211_free_chanctx(local, new_ctx);
+ ieee80211_free_chanctx(local, new_ctx, false);
goto out;
}
@@ -1383,7 +1386,7 @@ static int ieee80211_chsw_switch_ctxs(struct ieee80211_local *local)
if (!list_empty(&ctx->replace_ctx->assigned_links))
continue;
- ieee80211_del_chanctx(local, ctx->replace_ctx);
+ ieee80211_del_chanctx(local, ctx->replace_ctx, false);
err = ieee80211_add_chanctx(local, ctx);
if (err)
goto err;
@@ -1400,7 +1403,7 @@ err:
if (!list_empty(&ctx->replace_ctx->assigned_links))
continue;
- ieee80211_del_chanctx(local, ctx);
+ ieee80211_del_chanctx(local, ctx, false);
WARN_ON(ieee80211_add_chanctx(local, ctx->replace_ctx));
}
@@ -1652,7 +1655,8 @@ err:
return err;
}
-static void __ieee80211_link_release_channel(struct ieee80211_link_data *link)
+void __ieee80211_link_release_channel(struct ieee80211_link_data *link,
+ bool skip_idle_recalc)
{
struct ieee80211_sub_if_data *sdata = link->sdata;
struct ieee80211_bss_conf *link_conf = link->conf;
@@ -1680,7 +1684,7 @@ static void __ieee80211_link_release_channel(struct ieee80211_link_data *link)
ieee80211_assign_link_chanctx(link, NULL);
if (ieee80211_chanctx_refcount(local, ctx) == 0)
- ieee80211_free_chanctx(local, ctx);
+ ieee80211_free_chanctx(local, ctx, skip_idle_recalc);
link->radar_required = false;
@@ -1721,7 +1725,7 @@ int ieee80211_link_use_channel(struct ieee80211_link_data *link,
if (ret < 0)
goto out;
- __ieee80211_link_release_channel(link);
+ __ieee80211_link_release_channel(link, false);
ctx = ieee80211_find_chanctx(local, chanreq, mode);
if (!ctx)
@@ -1737,7 +1741,7 @@ int ieee80211_link_use_channel(struct ieee80211_link_data *link,
if (ret) {
/* if assign fails refcount stays the same */
if (ieee80211_chanctx_refcount(local, ctx) == 0)
- ieee80211_free_chanctx(local, ctx);
+ ieee80211_free_chanctx(local, ctx, false);
goto out;
}
@@ -1930,7 +1934,7 @@ void ieee80211_link_release_channel(struct ieee80211_link_data *link)
lockdep_assert_wiphy(sdata->local->hw.wiphy);
if (rcu_access_pointer(link->conf->chanctx_conf))
- __ieee80211_link_release_channel(link);
+ __ieee80211_link_release_channel(link, false);
}
void ieee80211_link_vlan_copy_chanctx(struct ieee80211_link_data *link)
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index ab1c669f39..55d124a7b0 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -2574,6 +2574,8 @@ int __must_check
ieee80211_link_change_chanreq(struct ieee80211_link_data *link,
const struct ieee80211_chan_req *req,
u64 *changed);
+void __ieee80211_link_release_channel(struct ieee80211_link_data *link,
+ bool skip_idle_recalc);
void ieee80211_link_release_channel(struct ieee80211_link_data *link);
void ieee80211_link_vlan_copy_chanctx(struct ieee80211_link_data *link);
void ieee80211_link_copy_chanctx_to_vlans(struct ieee80211_link_data *link,
diff --git a/net/mac80211/link.c b/net/mac80211/link.c
index 73b3b0309a..75527e75b8 100644
--- a/net/mac80211/link.c
+++ b/net/mac80211/link.c
@@ -358,7 +358,7 @@ static int _ieee80211_set_active_links(struct ieee80211_sub_if_data *sdata,
ieee80211_teardown_tdls_peers(link);
- ieee80211_link_release_channel(link);
+ __ieee80211_link_release_channel(link, true);
/*
* If CSA is (still) active while the link is deactivated,
diff --git a/versions b/versions
index 39aa972e7f..7fb7cf9997 100644
--- a/versions
+++ b/versions
@@ -2,4 +2,5 @@ BACKPORTS_VERSION="(see git)"
BACKPORTED_KERNEL_VERSION="(see git)"
BACKPORTED_KERNEL_NAME="iwlwifi"
BACKPORTS_BUILD_TSTAMP=__DATE__ \" \" __TIME__
-BACKPORTS_GIT_TRACKED="iwlwifi-stack-public:master:12010:72bcec7b"
+BACKPORTS_GIT_TRACKED="iwlwifi-stack-public:release/core87:12011:4f70dc32"
+BACKPORTS_BRANCH_TSTAMP="Apr 17 2024 13:11:40"