aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/wme.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/wme.c')
-rw-r--r--net/mac80211/wme.c139
1 files changed, 129 insertions, 10 deletions
diff --git a/net/mac80211/wme.c b/net/mac80211/wme.c
index 4e236599dd31..4e94e4026e78 100644
--- a/net/mac80211/wme.c
+++ b/net/mac80211/wme.c
@@ -19,10 +19,13 @@
19#include "wme.h" 19#include "wme.h"
20 20
21/* maximum number of hardware queues we support. */ 21/* maximum number of hardware queues we support. */
22#define TC_80211_MAX_QUEUES 8 22#define TC_80211_MAX_QUEUES 16
23
24const int ieee802_1d_to_ac[8] = { 2, 3, 3, 2, 1, 1, 0, 0 };
23 25
24struct ieee80211_sched_data 26struct ieee80211_sched_data
25{ 27{
28 unsigned long qdisc_pool[BITS_TO_LONGS(TC_80211_MAX_QUEUES)];
26 struct tcf_proto *filter_list; 29 struct tcf_proto *filter_list;
27 struct Qdisc *queues[TC_80211_MAX_QUEUES]; 30 struct Qdisc *queues[TC_80211_MAX_QUEUES];
28 struct sk_buff_head requeued[TC_80211_MAX_QUEUES]; 31 struct sk_buff_head requeued[TC_80211_MAX_QUEUES];
@@ -98,7 +101,6 @@ static inline int classify80211(struct sk_buff *skb, struct Qdisc *qd)
98 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; 101 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
99 unsigned short fc = le16_to_cpu(hdr->frame_control); 102 unsigned short fc = le16_to_cpu(hdr->frame_control);
100 int qos; 103 int qos;
101 const int ieee802_1d_to_ac[8] = { 2, 3, 3, 2, 1, 1, 0, 0 };
102 104
103 /* see if frame is data or non data frame */ 105 /* see if frame is data or non data frame */
104 if (unlikely((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA)) { 106 if (unlikely((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA)) {
@@ -146,9 +148,26 @@ static int wme_qdiscop_enqueue(struct sk_buff *skb, struct Qdisc* qd)
146 unsigned short fc = le16_to_cpu(hdr->frame_control); 148 unsigned short fc = le16_to_cpu(hdr->frame_control);
147 struct Qdisc *qdisc; 149 struct Qdisc *qdisc;
148 int err, queue; 150 int err, queue;
151 struct sta_info *sta;
152 u8 tid;
149 153
150 if (pkt_data->flags & IEEE80211_TXPD_REQUEUE) { 154 if (pkt_data->flags & IEEE80211_TXPD_REQUEUE) {
151 skb_queue_tail(&q->requeued[pkt_data->queue], skb); 155 queue = pkt_data->queue;
156 rcu_read_lock();
157 sta = sta_info_get(local, hdr->addr1);
158 tid = skb->priority & QOS_CONTROL_TAG1D_MASK;
159 if (sta) {
160 int ampdu_queue = sta->tid_to_tx_q[tid];
161 if ((ampdu_queue < local->hw.queues) &&
162 test_bit(ampdu_queue, q->qdisc_pool)) {
163 queue = ampdu_queue;
164 pkt_data->flags |= IEEE80211_TXPD_AMPDU;
165 } else {
166 pkt_data->flags &= ~IEEE80211_TXPD_AMPDU;
167 }
168 }
169 rcu_read_unlock();
170 skb_queue_tail(&q->requeued[queue], skb);
152 qd->q.qlen++; 171 qd->q.qlen++;
153 return 0; 172 return 0;
154 } 173 }
@@ -159,14 +178,31 @@ static int wme_qdiscop_enqueue(struct sk_buff *skb, struct Qdisc* qd)
159 */ 178 */
160 if (WLAN_FC_IS_QOS_DATA(fc)) { 179 if (WLAN_FC_IS_QOS_DATA(fc)) {
161 u8 *p = skb->data + ieee80211_get_hdrlen(fc) - 2; 180 u8 *p = skb->data + ieee80211_get_hdrlen(fc) - 2;
162 u8 qos_hdr = skb->priority & QOS_CONTROL_TAG1D_MASK; 181 u8 ack_policy = 0;
182 tid = skb->priority & QOS_CONTROL_TAG1D_MASK;
163 if (local->wifi_wme_noack_test) 183 if (local->wifi_wme_noack_test)
164 qos_hdr |= QOS_CONTROL_ACK_POLICY_NOACK << 184 ack_policy |= QOS_CONTROL_ACK_POLICY_NOACK <<
165 QOS_CONTROL_ACK_POLICY_SHIFT; 185 QOS_CONTROL_ACK_POLICY_SHIFT;
166 /* qos header is 2 bytes, second reserved */ 186 /* qos header is 2 bytes, second reserved */
167 *p = qos_hdr; 187 *p = ack_policy | tid;
168 p++; 188 p++;
169 *p = 0; 189 *p = 0;
190
191 rcu_read_lock();
192
193 sta = sta_info_get(local, hdr->addr1);
194 if (sta) {
195 int ampdu_queue = sta->tid_to_tx_q[tid];
196 if ((ampdu_queue < local->hw.queues) &&
197 test_bit(ampdu_queue, q->qdisc_pool)) {
198 queue = ampdu_queue;
199 pkt_data->flags |= IEEE80211_TXPD_AMPDU;
200 } else {
201 pkt_data->flags &= ~IEEE80211_TXPD_AMPDU;
202 }
203 }
204
205 rcu_read_unlock();
170 } 206 }
171 207
172 if (unlikely(queue >= local->hw.queues)) { 208 if (unlikely(queue >= local->hw.queues)) {
@@ -184,6 +220,7 @@ static int wme_qdiscop_enqueue(struct sk_buff *skb, struct Qdisc* qd)
184 kfree_skb(skb); 220 kfree_skb(skb);
185 err = NET_XMIT_DROP; 221 err = NET_XMIT_DROP;
186 } else { 222 } else {
223 tid = skb->priority & QOS_CONTROL_TAG1D_MASK;
187 pkt_data->queue = (unsigned int) queue; 224 pkt_data->queue = (unsigned int) queue;
188 qdisc = q->queues[queue]; 225 qdisc = q->queues[queue];
189 err = qdisc->enqueue(skb, qdisc); 226 err = qdisc->enqueue(skb, qdisc);
@@ -235,10 +272,11 @@ static struct sk_buff *wme_qdiscop_dequeue(struct Qdisc* qd)
235 /* check all the h/w queues in numeric/priority order */ 272 /* check all the h/w queues in numeric/priority order */
236 for (queue = 0; queue < hw->queues; queue++) { 273 for (queue = 0; queue < hw->queues; queue++) {
237 /* see if there is room in this hardware queue */ 274 /* see if there is room in this hardware queue */
238 if (test_bit(IEEE80211_LINK_STATE_XOFF, 275 if ((test_bit(IEEE80211_LINK_STATE_XOFF,
239 &local->state[queue]) || 276 &local->state[queue])) ||
240 test_bit(IEEE80211_LINK_STATE_PENDING, 277 (test_bit(IEEE80211_LINK_STATE_PENDING,
241 &local->state[queue])) 278 &local->state[queue])) ||
279 (!test_bit(queue, q->qdisc_pool)))
242 continue; 280 continue;
243 281
244 /* there is space - try and get a frame */ 282 /* there is space - try and get a frame */
@@ -360,6 +398,10 @@ static int wme_qdiscop_init(struct Qdisc *qd, struct nlattr *opt)
360 } 398 }
361 } 399 }
362 400
401 /* reserve all legacy QoS queues */
402 for (i = 0; i < min(IEEE80211_TX_QUEUE_DATA4, queues); i++)
403 set_bit(i, q->qdisc_pool);
404
363 return err; 405 return err;
364} 406}
365 407
@@ -605,3 +647,80 @@ void ieee80211_wme_unregister(void)
605{ 647{
606 unregister_qdisc(&wme_qdisc_ops); 648 unregister_qdisc(&wme_qdisc_ops);
607} 649}
650
651int ieee80211_ht_agg_queue_add(struct ieee80211_local *local,
652 struct sta_info *sta, u16 tid)
653{
654 int i;
655 struct ieee80211_sched_data *q =
656 qdisc_priv(local->mdev->qdisc_sleeping);
657 DECLARE_MAC_BUF(mac);
658
659 /* prepare the filter and save it for the SW queue
660 * matching the recieved HW queue */
661
662 /* try to get a Qdisc from the pool */
663 for (i = IEEE80211_TX_QUEUE_BEACON; i < local->hw.queues; i++)
664 if (!test_and_set_bit(i, q->qdisc_pool)) {
665 ieee80211_stop_queue(local_to_hw(local), i);
666 sta->tid_to_tx_q[tid] = i;
667
668 /* IF there are already pending packets
669 * on this tid first we need to drain them
670 * on the previous queue
671 * since HT is strict in order */
672#ifdef CONFIG_MAC80211_HT_DEBUG
673 if (net_ratelimit())
674 printk(KERN_DEBUG "allocated aggregation queue"
675 " %d tid %d addr %s pool=0x%lX",
676 i, tid, print_mac(mac, sta->addr),
677 q->qdisc_pool[0]);
678#endif /* CONFIG_MAC80211_HT_DEBUG */
679 return 0;
680 }
681
682 return -EAGAIN;
683}
684
685/**
686 * the caller needs to hold local->mdev->queue_lock
687 */
688void ieee80211_ht_agg_queue_remove(struct ieee80211_local *local,
689 struct sta_info *sta, u16 tid,
690 u8 requeue)
691{
692 struct ieee80211_sched_data *q =
693 qdisc_priv(local->mdev->qdisc_sleeping);
694 int agg_queue = sta->tid_to_tx_q[tid];
695
696 /* return the qdisc to the pool */
697 clear_bit(agg_queue, q->qdisc_pool);
698 sta->tid_to_tx_q[tid] = local->hw.queues;
699
700 if (requeue)
701 ieee80211_requeue(local, agg_queue);
702 else
703 q->queues[agg_queue]->ops->reset(q->queues[agg_queue]);
704}
705
706void ieee80211_requeue(struct ieee80211_local *local, int queue)
707{
708 struct Qdisc *root_qd = local->mdev->qdisc_sleeping;
709 struct ieee80211_sched_data *q = qdisc_priv(root_qd);
710 struct Qdisc *qdisc = q->queues[queue];
711 struct sk_buff *skb = NULL;
712 u32 len = qdisc->q.qlen;
713
714 if (!qdisc || !qdisc->dequeue)
715 return;
716
717 printk(KERN_DEBUG "requeue: qlen = %d\n", qdisc->q.qlen);
718 for (len = qdisc->q.qlen; len > 0; len--) {
719 skb = qdisc->dequeue(qdisc);
720 root_qd->q.qlen--;
721 /* packet will be classified again and */
722 /* skb->packet_data->queue will be overridden if needed */
723 if (skb)
724 wme_qdiscop_enqueue(skb, root_qd);
725 }
726}