| From ee0db868ee4d88493dfdc82f59e3b4e449ddddd5 Mon Sep 17 00:00:00 2001 |
| From: Oldřich Jedlička <oldium.pro@gmail.com> |
| Date: Sat, 4 Nov 2023 15:13:33 +0100 |
| Subject: wifi: mac80211: do not pass AP_VLAN vif pointer to drivers during |
| flush |
| MIME-Version: 1.0 |
| Content-Type: text/plain; charset=UTF-8 |
| Content-Transfer-Encoding: 8bit |
| |
| [ Upstream commit 3e3a2b645c043f7e3e488d5011478cefb69bbe8b ] |
| |
| This fixes WARN_ONs when using AP_VLANs after station removal. The flush |
| call passed AP_VLAN vif to driver, but because these vifs are virtual and |
| not registered with drivers, we need to translate to the correct AP vif |
| first. |
| |
| Closes: https://github.com/openwrt/openwrt/issues/12420 |
| Fixes: 0b75a1b1e42e ("wifi: mac80211: flush queues on STA removal") |
| Fixes: d00800a289c9 ("wifi: mac80211: add flush_sta method") |
| Tested-by: Konstantin Demin <rockdrilla@gmail.com> |
| Tested-by: Koen Vandeputte <koen.vandeputte@citymesh.com> |
| Signed-off-by: Oldřich Jedlička <oldium.pro@gmail.com> |
| Link: https://lore.kernel.org/r/20231104141333.3710-1-oldium.pro@gmail.com |
| Signed-off-by: Johannes Berg <johannes.berg@intel.com> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| net/mac80211/driver-ops.h | 9 +++++++-- |
| 1 file changed, 7 insertions(+), 2 deletions(-) |
| |
| --- a/net/mac80211/driver-ops.h |
| +++ b/net/mac80211/driver-ops.h |
| @@ -23,7 +23,7 @@ |
| static inline struct ieee80211_sub_if_data * |
| get_bss_sdata(struct ieee80211_sub_if_data *sdata) |
| { |
| - if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) |
| + if (sdata && sdata->vif.type == NL80211_IFTYPE_AP_VLAN) |
| sdata = container_of(sdata->bss, struct ieee80211_sub_if_data, |
| u.ap); |
| |
| @@ -638,10 +638,13 @@ static inline void drv_flush(struct ieee |
| struct ieee80211_sub_if_data *sdata, |
| u32 queues, bool drop) |
| { |
| - struct ieee80211_vif *vif = sdata ? &sdata->vif : NULL; |
| + struct ieee80211_vif *vif; |
| |
| might_sleep(); |
| |
| + sdata = get_bss_sdata(sdata); |
| + vif = sdata ? &sdata->vif : NULL; |
| + |
| if (sdata && !check_sdata_in_driver(sdata)) |
| return; |
| |
| @@ -657,6 +660,8 @@ static inline void drv_flush_sta(struct |
| { |
| might_sleep(); |
| |
| + sdata = get_bss_sdata(sdata); |
| + |
| if (sdata && !check_sdata_in_driver(sdata)) |
| return; |
| |