aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/tx.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/tx.c')
-rw-r--r--net/mac80211/tx.c91
1 files changed, 91 insertions, 0 deletions
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 2dd89670e1cd..0cb41d1a1f20 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -3107,6 +3107,97 @@ ieee80211_get_buffered_bc(struct ieee80211_hw *hw,
3107} 3107}
3108EXPORT_SYMBOL(ieee80211_get_buffered_bc); 3108EXPORT_SYMBOL(ieee80211_get_buffered_bc);
3109 3109
3110int ieee80211_reserve_tid(struct ieee80211_sta *pubsta, u8 tid)
3111{
3112 struct sta_info *sta = container_of(pubsta, struct sta_info, sta);
3113 struct ieee80211_sub_if_data *sdata = sta->sdata;
3114 struct ieee80211_local *local = sdata->local;
3115 int ret;
3116 u32 queues;
3117
3118 lockdep_assert_held(&local->sta_mtx);
3119
3120 /* only some cases are supported right now */
3121 switch (sdata->vif.type) {
3122 case NL80211_IFTYPE_STATION:
3123 case NL80211_IFTYPE_AP:
3124 case NL80211_IFTYPE_AP_VLAN:
3125 break;
3126 default:
3127 WARN_ON(1);
3128 return -EINVAL;
3129 }
3130
3131 if (WARN_ON(tid >= IEEE80211_NUM_UPS))
3132 return -EINVAL;
3133
3134 if (sta->reserved_tid == tid) {
3135 ret = 0;
3136 goto out;
3137 }
3138
3139 if (sta->reserved_tid != IEEE80211_TID_UNRESERVED) {
3140 sdata_err(sdata, "TID reservation already active\n");
3141 ret = -EALREADY;
3142 goto out;
3143 }
3144
3145 ieee80211_stop_vif_queues(sdata->local, sdata,
3146 IEEE80211_QUEUE_STOP_REASON_RESERVE_TID);
3147
3148 synchronize_net();
3149
3150 /* Tear down BA sessions so we stop aggregating on this TID */
3151 if (local->hw.flags & IEEE80211_HW_AMPDU_AGGREGATION) {
3152 set_sta_flag(sta, WLAN_STA_BLOCK_BA);
3153 __ieee80211_stop_tx_ba_session(sta, tid,
3154 AGG_STOP_LOCAL_REQUEST);
3155 }
3156
3157 queues = BIT(sdata->vif.hw_queue[ieee802_1d_to_ac[tid]]);
3158 __ieee80211_flush_queues(local, sdata, queues);
3159
3160 sta->reserved_tid = tid;
3161
3162 ieee80211_wake_vif_queues(local, sdata,
3163 IEEE80211_QUEUE_STOP_REASON_RESERVE_TID);
3164
3165 if (local->hw.flags & IEEE80211_HW_AMPDU_AGGREGATION)
3166 clear_sta_flag(sta, WLAN_STA_BLOCK_BA);
3167
3168 ret = 0;
3169 out:
3170 return ret;
3171}
3172EXPORT_SYMBOL(ieee80211_reserve_tid);
3173
3174void ieee80211_unreserve_tid(struct ieee80211_sta *pubsta, u8 tid)
3175{
3176 struct sta_info *sta = container_of(pubsta, struct sta_info, sta);
3177 struct ieee80211_sub_if_data *sdata = sta->sdata;
3178
3179 lockdep_assert_held(&sdata->local->sta_mtx);
3180
3181 /* only some cases are supported right now */
3182 switch (sdata->vif.type) {
3183 case NL80211_IFTYPE_STATION:
3184 case NL80211_IFTYPE_AP:
3185 case NL80211_IFTYPE_AP_VLAN:
3186 break;
3187 default:
3188 WARN_ON(1);
3189 return;
3190 }
3191
3192 if (tid != sta->reserved_tid) {
3193 sdata_err(sdata, "TID to unreserve (%d) isn't reserved\n", tid);
3194 return;
3195 }
3196
3197 sta->reserved_tid = IEEE80211_TID_UNRESERVED;
3198}
3199EXPORT_SYMBOL(ieee80211_unreserve_tid);
3200
3110void __ieee80211_tx_skb_tid_band(struct ieee80211_sub_if_data *sdata, 3201void __ieee80211_tx_skb_tid_band(struct ieee80211_sub_if_data *sdata,
3111 struct sk_buff *skb, int tid, 3202 struct sk_buff *skb, int tid,
3112 enum ieee80211_band band) 3203 enum ieee80211_band band)