| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Copyright 2004, Instant802 Networks, Inc. |
|---|
| 3 | 4 | * Copyright 2013-2014 Intel Mobile Communications GmbH |
|---|
| 4 | | - * |
|---|
| 5 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 6 | | - * it under the terms of the GNU General Public License version 2 as |
|---|
| 7 | | - * published by the Free Software Foundation. |
|---|
| 8 | 5 | */ |
|---|
| 9 | 6 | |
|---|
| 10 | 7 | #include <linux/netdevice.h> |
|---|
| .. | .. |
|---|
| 141 | 138 | return ieee80211_downgrade_queue(sdata, NULL, skb); |
|---|
| 142 | 139 | } |
|---|
| 143 | 140 | |
|---|
| 144 | | -/* Indicate which queue to use. */ |
|---|
| 145 | | -u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata, |
|---|
| 146 | | - struct sk_buff *skb) |
|---|
| 141 | +u16 __ieee80211_select_queue(struct ieee80211_sub_if_data *sdata, |
|---|
| 142 | + struct sta_info *sta, struct sk_buff *skb) |
|---|
| 147 | 143 | { |
|---|
| 148 | | - struct ieee80211_local *local = sdata->local; |
|---|
| 149 | | - struct sta_info *sta = NULL; |
|---|
| 150 | | - const u8 *ra = NULL; |
|---|
| 151 | | - bool qos = false; |
|---|
| 144 | + const struct ethhdr *eth = (void *)skb->data; |
|---|
| 152 | 145 | struct mac80211_qos_map *qos_map; |
|---|
| 153 | | - u16 ret; |
|---|
| 146 | + bool qos; |
|---|
| 154 | 147 | |
|---|
| 155 | | - if (local->hw.queues < IEEE80211_NUM_ACS || skb->len < 6) { |
|---|
| 156 | | - skb->priority = 0; /* required for correct WPA/11i MIC */ |
|---|
| 157 | | - return 0; |
|---|
| 158 | | - } |
|---|
| 159 | | - |
|---|
| 160 | | - rcu_read_lock(); |
|---|
| 161 | | - switch (sdata->vif.type) { |
|---|
| 162 | | - case NL80211_IFTYPE_AP_VLAN: |
|---|
| 163 | | - sta = rcu_dereference(sdata->u.vlan.sta); |
|---|
| 164 | | - if (sta) { |
|---|
| 165 | | - qos = sta->sta.wme; |
|---|
| 166 | | - break; |
|---|
| 167 | | - } |
|---|
| 168 | | - /* fall through */ |
|---|
| 169 | | - case NL80211_IFTYPE_AP: |
|---|
| 170 | | - ra = skb->data; |
|---|
| 171 | | - break; |
|---|
| 172 | | - case NL80211_IFTYPE_WDS: |
|---|
| 173 | | - ra = sdata->u.wds.remote_addr; |
|---|
| 174 | | - break; |
|---|
| 175 | | -#ifdef CONFIG_MAC80211_MESH |
|---|
| 176 | | - case NL80211_IFTYPE_MESH_POINT: |
|---|
| 148 | + /* all mesh/ocb stations are required to support WME */ |
|---|
| 149 | + if ((sdata->vif.type == NL80211_IFTYPE_MESH_POINT && |
|---|
| 150 | + !is_multicast_ether_addr(eth->h_dest)) || |
|---|
| 151 | + (sdata->vif.type == NL80211_IFTYPE_OCB && sta)) |
|---|
| 177 | 152 | qos = true; |
|---|
| 178 | | - break; |
|---|
| 179 | | -#endif |
|---|
| 180 | | - case NL80211_IFTYPE_STATION: |
|---|
| 181 | | - /* might be a TDLS station */ |
|---|
| 182 | | - sta = sta_info_get(sdata, skb->data); |
|---|
| 183 | | - if (sta) |
|---|
| 184 | | - qos = sta->sta.wme; |
|---|
| 185 | | - |
|---|
| 186 | | - ra = sdata->u.mgd.bssid; |
|---|
| 187 | | - break; |
|---|
| 188 | | - case NL80211_IFTYPE_ADHOC: |
|---|
| 189 | | - ra = skb->data; |
|---|
| 190 | | - break; |
|---|
| 191 | | - case NL80211_IFTYPE_OCB: |
|---|
| 192 | | - /* all stations are required to support WME */ |
|---|
| 193 | | - qos = true; |
|---|
| 194 | | - break; |
|---|
| 195 | | - default: |
|---|
| 196 | | - break; |
|---|
| 197 | | - } |
|---|
| 198 | | - |
|---|
| 199 | | - if (!sta && ra && !is_multicast_ether_addr(ra)) { |
|---|
| 200 | | - sta = sta_info_get(sdata, ra); |
|---|
| 201 | | - if (sta) |
|---|
| 202 | | - qos = sta->sta.wme; |
|---|
| 203 | | - } |
|---|
| 153 | + else if (sta) |
|---|
| 154 | + qos = sta->sta.wme; |
|---|
| 155 | + else |
|---|
| 156 | + qos = false; |
|---|
| 204 | 157 | |
|---|
| 205 | 158 | if (!qos) { |
|---|
| 206 | 159 | skb->priority = 0; /* required for correct WPA/11i MIC */ |
|---|
| 207 | | - ret = IEEE80211_AC_BE; |
|---|
| 208 | | - goto out; |
|---|
| 160 | + return IEEE80211_AC_BE; |
|---|
| 209 | 161 | } |
|---|
| 210 | 162 | |
|---|
| 211 | 163 | if (skb->protocol == sdata->control_port_protocol) { |
|---|
| .. | .. |
|---|
| 220 | 172 | &qos_map->qos_map : NULL); |
|---|
| 221 | 173 | |
|---|
| 222 | 174 | downgrade: |
|---|
| 223 | | - ret = ieee80211_downgrade_queue(sdata, sta, skb); |
|---|
| 224 | | - out: |
|---|
| 175 | + return ieee80211_downgrade_queue(sdata, sta, skb); |
|---|
| 176 | +} |
|---|
| 177 | + |
|---|
| 178 | + |
|---|
| 179 | +/* Indicate which queue to use. */ |
|---|
| 180 | +u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata, |
|---|
| 181 | + struct sk_buff *skb) |
|---|
| 182 | +{ |
|---|
| 183 | + struct ieee80211_local *local = sdata->local; |
|---|
| 184 | + struct sta_info *sta = NULL; |
|---|
| 185 | + const u8 *ra = NULL; |
|---|
| 186 | + u16 ret; |
|---|
| 187 | + |
|---|
| 188 | + /* when using iTXQ, we can do this later */ |
|---|
| 189 | + if (local->ops->wake_tx_queue) |
|---|
| 190 | + return 0; |
|---|
| 191 | + |
|---|
| 192 | + if (local->hw.queues < IEEE80211_NUM_ACS || skb->len < 6) { |
|---|
| 193 | + skb->priority = 0; /* required for correct WPA/11i MIC */ |
|---|
| 194 | + return 0; |
|---|
| 195 | + } |
|---|
| 196 | + |
|---|
| 197 | + rcu_read_lock(); |
|---|
| 198 | + switch (sdata->vif.type) { |
|---|
| 199 | + case NL80211_IFTYPE_AP_VLAN: |
|---|
| 200 | + sta = rcu_dereference(sdata->u.vlan.sta); |
|---|
| 201 | + if (sta) |
|---|
| 202 | + break; |
|---|
| 203 | + fallthrough; |
|---|
| 204 | + case NL80211_IFTYPE_AP: |
|---|
| 205 | + ra = skb->data; |
|---|
| 206 | + break; |
|---|
| 207 | + case NL80211_IFTYPE_WDS: |
|---|
| 208 | + ra = sdata->u.wds.remote_addr; |
|---|
| 209 | + break; |
|---|
| 210 | + case NL80211_IFTYPE_STATION: |
|---|
| 211 | + /* might be a TDLS station */ |
|---|
| 212 | + sta = sta_info_get(sdata, skb->data); |
|---|
| 213 | + if (sta) |
|---|
| 214 | + break; |
|---|
| 215 | + |
|---|
| 216 | + ra = sdata->u.mgd.bssid; |
|---|
| 217 | + break; |
|---|
| 218 | + case NL80211_IFTYPE_ADHOC: |
|---|
| 219 | + ra = skb->data; |
|---|
| 220 | + break; |
|---|
| 221 | + default: |
|---|
| 222 | + break; |
|---|
| 223 | + } |
|---|
| 224 | + |
|---|
| 225 | + if (!sta && ra && !is_multicast_ether_addr(ra)) |
|---|
| 226 | + sta = sta_info_get(sdata, ra); |
|---|
| 227 | + |
|---|
| 228 | + ret = __ieee80211_select_queue(sdata, sta, skb); |
|---|
| 229 | + |
|---|
| 225 | 230 | rcu_read_unlock(); |
|---|
| 226 | 231 | return ret; |
|---|
| 227 | 232 | } |
|---|