diff options
Diffstat (limited to 'net/mac80211/wme.c')
-rw-r--r-- | net/mac80211/wme.c | 33 |
1 files changed, 24 insertions, 9 deletions
diff --git a/net/mac80211/wme.c b/net/mac80211/wme.c index 3b873989992c..fdf52db95b33 100644 --- a/net/mac80211/wme.c +++ b/net/mac80211/wme.c | |||
@@ -54,10 +54,18 @@ static int wme_downgrade_ac(struct sk_buff *skb) | |||
54 | } | 54 | } |
55 | 55 | ||
56 | static u16 ieee80211_downgrade_queue(struct ieee80211_sub_if_data *sdata, | 56 | static u16 ieee80211_downgrade_queue(struct ieee80211_sub_if_data *sdata, |
57 | struct sk_buff *skb) | 57 | struct sta_info *sta, struct sk_buff *skb) |
58 | { | 58 | { |
59 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | ||
60 | |||
59 | /* in case we are a client verify acm is not set for this ac */ | 61 | /* in case we are a client verify acm is not set for this ac */ |
60 | while (unlikely(sdata->wmm_acm & BIT(skb->priority))) { | 62 | while (sdata->wmm_acm & BIT(skb->priority)) { |
63 | int ac = ieee802_1d_to_ac[skb->priority]; | ||
64 | |||
65 | if (ifmgd->tx_tspec[ac].admitted_time && | ||
66 | skb->priority == ifmgd->tx_tspec[ac].up) | ||
67 | return ac; | ||
68 | |||
61 | if (wme_downgrade_ac(skb)) { | 69 | if (wme_downgrade_ac(skb)) { |
62 | /* | 70 | /* |
63 | * This should not really happen. The AP has marked all | 71 | * This should not really happen. The AP has marked all |
@@ -96,7 +104,7 @@ u16 ieee80211_select_queue_80211(struct ieee80211_sub_if_data *sdata, | |||
96 | p = ieee80211_get_qos_ctl(hdr); | 104 | p = ieee80211_get_qos_ctl(hdr); |
97 | skb->priority = *p & IEEE80211_QOS_CTL_TAG1D_MASK; | 105 | skb->priority = *p & IEEE80211_QOS_CTL_TAG1D_MASK; |
98 | 106 | ||
99 | return ieee80211_downgrade_queue(sdata, skb); | 107 | return ieee80211_downgrade_queue(sdata, NULL, skb); |
100 | } | 108 | } |
101 | 109 | ||
102 | /* Indicate which queue to use. */ | 110 | /* Indicate which queue to use. */ |
@@ -108,6 +116,7 @@ u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata, | |||
108 | const u8 *ra = NULL; | 116 | const u8 *ra = NULL; |
109 | bool qos = false; | 117 | bool qos = false; |
110 | struct mac80211_qos_map *qos_map; | 118 | struct mac80211_qos_map *qos_map; |
119 | u16 ret; | ||
111 | 120 | ||
112 | if (local->hw.queues < IEEE80211_NUM_ACS || skb->len < 6) { | 121 | if (local->hw.queues < IEEE80211_NUM_ACS || skb->len < 6) { |
113 | skb->priority = 0; /* required for correct WPA/11i MIC */ | 122 | skb->priority = 0; /* required for correct WPA/11i MIC */ |
@@ -139,6 +148,10 @@ u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata, | |||
139 | case NL80211_IFTYPE_ADHOC: | 148 | case NL80211_IFTYPE_ADHOC: |
140 | ra = skb->data; | 149 | ra = skb->data; |
141 | break; | 150 | break; |
151 | case NL80211_IFTYPE_OCB: | ||
152 | /* all stations are required to support WME */ | ||
153 | qos = true; | ||
154 | break; | ||
142 | default: | 155 | default: |
143 | break; | 156 | break; |
144 | } | 157 | } |
@@ -148,27 +161,29 @@ u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata, | |||
148 | if (sta) | 161 | if (sta) |
149 | qos = sta->sta.wme; | 162 | qos = sta->sta.wme; |
150 | } | 163 | } |
151 | rcu_read_unlock(); | ||
152 | 164 | ||
153 | if (!qos) { | 165 | if (!qos) { |
154 | skb->priority = 0; /* required for correct WPA/11i MIC */ | 166 | skb->priority = 0; /* required for correct WPA/11i MIC */ |
155 | return IEEE80211_AC_BE; | 167 | ret = IEEE80211_AC_BE; |
168 | goto out; | ||
156 | } | 169 | } |
157 | 170 | ||
158 | if (skb->protocol == sdata->control_port_protocol) { | 171 | if (skb->protocol == sdata->control_port_protocol) { |
159 | skb->priority = 7; | 172 | skb->priority = 7; |
160 | return ieee80211_downgrade_queue(sdata, skb); | 173 | goto downgrade; |
161 | } | 174 | } |
162 | 175 | ||
163 | /* use the data classifier to determine what 802.1d tag the | 176 | /* use the data classifier to determine what 802.1d tag the |
164 | * data frame has */ | 177 | * data frame has */ |
165 | rcu_read_lock(); | ||
166 | qos_map = rcu_dereference(sdata->qos_map); | 178 | qos_map = rcu_dereference(sdata->qos_map); |
167 | skb->priority = cfg80211_classify8021d(skb, qos_map ? | 179 | skb->priority = cfg80211_classify8021d(skb, qos_map ? |
168 | &qos_map->qos_map : NULL); | 180 | &qos_map->qos_map : NULL); |
169 | rcu_read_unlock(); | ||
170 | 181 | ||
171 | return ieee80211_downgrade_queue(sdata, skb); | 182 | downgrade: |
183 | ret = ieee80211_downgrade_queue(sdata, sta, skb); | ||
184 | out: | ||
185 | rcu_read_unlock(); | ||
186 | return ret; | ||
172 | } | 187 | } |
173 | 188 | ||
174 | /** | 189 | /** |