summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBen Greear <greearb@candelatech.com>2020-09-22 12:19:56 -0700
committerJohannes Berg <johannes.berg@intel.com>2020-09-28 15:05:53 +0200
commit265a0708339daeb71848169f52b91066cc2984fd (patch)
tree7a7e2cb7037d3058f0cadceaf9041871c37ef2bb
parent6c8b6e4a5f745ec49286ac0a3f1d591a34818f82 (diff)
downloadlinux-265a0708339daeb71848169f52b91066cc2984fd.tar.bz2
mac80211: Support not iterating over not-sdata-in-driver ifaces
Allow drivers to request that interface-iterator does NOT iterate over interfaces that are not sdata-in-driver. This will allow us to fix crashes in ath10k (and possibly other drivers). To summarize Johannes' explanation: Consider add interface wlan0 add interface wlan1 iterate active interfaces -> wlan0 wlan1 add interface wlan2 iterate active interfaces -> wlan0 wlan1 wlan2 If you apply this scenario to a restart, which ought to be functionally equivalent to the normal startup, just compressed in time, you're basically saying that today you get add interface wlan0 add interface wlan1 iterate active interfaces -> wlan0 wlan1 wlan2 << problem here add interface wlan2 iterate active interfaces -> wlan0 wlan1 wlan2 which yeah, totally seems wrong. But fixing that to be add interface wlan0 add interface wlan1 iterate active interfaces -> <nothing> add interface wlan2 iterate active interfaces -> <nothing> (or maybe -> wlan0 wlan1 wlan2 if the reconfig already completed) This is also at least somewhat wrong, but better to not iterate over something that exists in the driver than iterate over something that does not. Originally the first issue was causing crashes in testing with lots of station vdevs on an ath10k radio, combined with firmware crashing. I ran with a similar patch for years with no obvious bad results, including significant testing with ath9k and ath10k. Signed-off-by: Ben Greear <greearb@candelatech.com> Link: https://lore.kernel.org/r/20200922191957.25257-1-greearb@candelatech.com Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-rw-r--r--include/net/mac80211.h4
-rw-r--r--net/mac80211/util.c3
2 files changed, 7 insertions, 0 deletions
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 72bc877d2c22..4747d446179a 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -5407,11 +5407,15 @@ void ieee80211_sched_scan_stopped(struct ieee80211_hw *hw);
* @IEEE80211_IFACE_ITER_RESUME_ALL: During resume, iterate over all
* interfaces, even if they haven't been re-added to the driver yet.
* @IEEE80211_IFACE_ITER_ACTIVE: Iterate only active interfaces (netdev is up).
+ * @IEEE80211_IFACE_SKIP_SDATA_NOT_IN_DRIVER: Skip any interfaces where SDATA
+ * is not in the driver. This may fix crashes during firmware recovery
+ * for instance.
*/
enum ieee80211_interface_iteration_flags {
IEEE80211_IFACE_ITER_NORMAL = 0,
IEEE80211_IFACE_ITER_RESUME_ALL = BIT(0),
IEEE80211_IFACE_ITER_ACTIVE = BIT(1),
+ IEEE80211_IFACE_SKIP_SDATA_NOT_IN_DRIVER = BIT(2),
};
/**
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 99d584fe49e8..49342060490f 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -785,6 +785,9 @@ static void __iterate_interfaces(struct ieee80211_local *local,
if (!(iter_flags & IEEE80211_IFACE_ITER_RESUME_ALL) &&
active_only && !(sdata->flags & IEEE80211_SDATA_IN_DRIVER))
continue;
+ if ((iter_flags & IEEE80211_IFACE_SKIP_SDATA_NOT_IN_DRIVER) &&
+ !(sdata->flags & IEEE80211_SDATA_IN_DRIVER))
+ continue;
if (ieee80211_sdata_running(sdata) || !active_only)
iterator(data, sdata->vif.addr,
&sdata->vif);