developer | 66bc8fb | 2024-05-06 17:14:15 +0800 | [diff] [blame^] | 1 | From de4d3e25a555dedd70793d0362b1e501ed1a77f1 Mon Sep 17 00:00:00 2001 |
| 2 | From: Benjamin Lin <benjamin-jw.lin@mediatek.com> |
| 3 | Date: Tue, 30 Apr 2024 10:28:29 +0800 |
| 4 | Subject: [PATCH] mac80211: mtk: fix inconsistent QoS mapping between AP and |
| 5 | AP_VLAN VIFs |
| 6 | |
| 7 | Fix inconsistent QoS mapping between AP and AP_VLAN IFs. |
| 8 | Specifically, when WDS AP IF is connected by a WDS STA, the QoS map of the AP_VLAN VIF is NULL. |
| 9 | So the QoS types of packets to the WDS STA will be determined using the default mapping rule. |
| 10 | However, SoftMAC driver uses the QoS map of the AP VIF, which may already be set. |
| 11 | Therefore, it is possible that the QoS mappings of SW and HW are inconsistent. |
| 12 | Thus, sync QoS map of AP VIF to that of AP_VLAN VIF. |
| 13 | |
| 14 | Signed-off-by: Benjamin Lin <benjamin-jw.lin@mediatek.com> |
| 15 | --- |
| 16 | net/mac80211/iface.c | 23 ++++++++++++++++++++++- |
| 17 | 1 file changed, 22 insertions(+), 1 deletion(-) |
| 18 | |
| 19 | diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c |
| 20 | index ef32d53..138ad79 100644 |
| 21 | --- a/net/mac80211/iface.c |
| 22 | +++ b/net/mac80211/iface.c |
| 23 | @@ -297,8 +297,29 @@ static int ieee80211_check_concurrent_iface(struct ieee80211_sub_if_data *sdata, |
| 24 | * can only add VLANs to enabled APs |
| 25 | */ |
| 26 | if (iftype == NL80211_IFTYPE_AP_VLAN && |
| 27 | - nsdata->vif.type == NL80211_IFTYPE_AP) |
| 28 | + nsdata->vif.type == NL80211_IFTYPE_AP) { |
| 29 | + struct mac80211_qos_map *old_qos_map, *new_qos_map = NULL; |
| 30 | + |
| 31 | sdata->bss = &nsdata->u.ap; |
| 32 | + |
| 33 | + rcu_read_lock(); |
| 34 | + old_qos_map = rcu_dereference(nsdata->qos_map); |
| 35 | + if (old_qos_map) { |
| 36 | + new_qos_map = kzalloc(sizeof(*new_qos_map), GFP_KERNEL); |
| 37 | + if (!new_qos_map) { |
| 38 | + rcu_read_unlock(); |
| 39 | + return -ENOMEM; |
| 40 | + } |
| 41 | + memcpy(&new_qos_map->qos_map, &old_qos_map->qos_map, |
| 42 | + sizeof(new_qos_map->qos_map)); |
| 43 | + } |
| 44 | + rcu_read_unlock(); |
| 45 | + |
| 46 | + old_qos_map = sdata_dereference(sdata->qos_map, sdata); |
| 47 | + rcu_assign_pointer(sdata->qos_map, new_qos_map); |
| 48 | + if (old_qos_map) |
| 49 | + kfree_rcu(old_qos_map, rcu_head); |
| 50 | + } |
| 51 | } |
| 52 | } |
| 53 | |
| 54 | -- |
| 55 | 2.18.0 |
| 56 | |