~ubuntu-branches/ubuntu/hardy/linux-backports-modules-2.6.24/hardy-security

« back to all changes in this revision

Viewing changes to updates/wireless/iwlwifi/mac80211/compatible/net/mac80211/wme.c

  • Committer: Bazaar Package Importer
  • Author(s): , Ben Collins
  • Date: 2008-04-02 06:59:04 UTC
  • Revision ID: james.westby@ubuntu.com-20080402065904-e5knh2gn2hms3xbb
Tags: 2.6.24-14.11
[Ben Collins]

* iwlwifi: Update to iwlwifi-1.2.25 and mac80211-10.0.4
  - LP: #200950
* ubuntu: Slight cleanups to module hiearchy and Makefiles
* mac80211: Enable LED triggers
* iwlwifi: Add LED trigger support (rx and tx only)
  - LP: #176090

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright 2004, Instant802 Networks, Inc.
 
3
 *
 
4
 * This program is free software; you can redistribute it and/or modify
 
5
 * it under the terms of the GNU General Public License version 2 as
 
6
 * published by the Free Software Foundation.
 
7
 */
 
8
 
 
9
#include <linux/netdevice.h>
 
10
#include <linux/skbuff.h>
 
11
#include <linux/module.h>
 
12
#include <linux/if_arp.h>
 
13
#include <linux/types.h>
 
14
#include <net/ip.h>
 
15
#include <net/pkt_sched.h>
 
16
 
 
17
#include <net/mac80211.h>
 
18
#include "ieee80211_i.h"
 
19
#include "wme.h"
 
20
 
 
21
static inline int WLAN_FC_IS_QOS_DATA(u16 fc)
 
22
{
 
23
        return (fc & 0x8C) == 0x88;
 
24
}
 
25
 
 
26
 
 
27
ieee80211_txrx_result
 
28
ieee80211_rx_h_parse_qos(struct ieee80211_txrx_data *rx)
 
29
{
 
30
        u8 *data = rx->skb->data;
 
31
        int tid;
 
32
        unsigned int is_agg_frame = 0;
 
33
 
 
34
        /* does the frame have a qos control field? */
 
35
        if (WLAN_FC_IS_QOS_DATA(rx->fc)) {
 
36
                u8 *qc = data + iwlwifi_ieee80211_get_hdrlen(rx->fc) - QOS_CONTROL_LEN;
 
37
 
 
38
                /* frame has qos control */
 
39
                rx->u.rx.qos_control = le16_to_cpu(*((__le16*)qc));
 
40
                tid = rx->u.rx.qos_control & QOS_CONTROL_TID_MASK;
 
41
                if (rx->u.rx.qos_control &
 
42
                    IEEE80211_QOS_CONTROL_A_MSDU_PRESENT)
 
43
                        is_agg_frame = 1;
 
44
        } else {
 
45
                if (unlikely((rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT)) {
 
46
                        /* Separate TID for management frames */
 
47
                        tid = NUM_RX_DATA_QUEUES - 1;
 
48
                } else {
 
49
                        /* no qos control present */
 
50
                        tid = 0; /* 802.1d - Best Effort */
 
51
                }
 
52
                rx->u.rx.qos_control = 0;
 
53
        }
 
54
#ifdef CONFIG_MAC80211_DEBUG_COUNTERS
 
55
        I802_DEBUG_INC(rx->local->wme_rx_queue[tid]);
 
56
        if (rx->sta) {
 
57
                I802_DEBUG_INC(rx->sta->wme_rx_queue[tid]);
 
58
        }
 
59
#endif /* CONFIG_MAC80211_DEBUG_COUNTERS */
 
60
 
 
61
        rx->u.rx.queue = tid;
 
62
        rx->u.rx.is_agg_frame = is_agg_frame;
 
63
        /* Set skb->priority to 1d tag if highest order bit of TID is not set.
 
64
         * For now, set skb->priority to 0 for other cases. */
 
65
        rx->skb->priority = (tid > 7) ? 0 : tid;
 
66
 
 
67
        return TXRX_CONTINUE;
 
68
}
 
69
 
 
70
 
 
71
ieee80211_txrx_result
 
72
ieee80211_rx_h_remove_qos_control(struct ieee80211_txrx_data *rx)
 
73
{
 
74
        u16 fc = rx->fc;
 
75
        u8 *data = rx->skb->data;
 
76
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) data;
 
77
 
 
78
        if (!WLAN_FC_IS_QOS_DATA(fc))
 
79
                return TXRX_CONTINUE;
 
80
 
 
81
        /* remove the qos control field, update frame type and meta-data */
 
82
        memmove(data + 2, data, iwlwifi_ieee80211_get_hdrlen(fc) - 2);
 
83
        hdr = (struct ieee80211_hdr *) skb_pull(rx->skb, 2);
 
84
        /* change frame type to non QOS */
 
85
        rx->fc = fc &= ~IEEE80211_STYPE_QOS_DATA;
 
86
        hdr->frame_control = cpu_to_le16(fc);
 
87
 
 
88
        return TXRX_CONTINUE;
 
89
}
 
90
 
 
91
 
 
92
#ifdef CONFIG_NET_SCHED
 
93
/* maximum number of hardware queues we support. */
 
94
#define TC_80211_MAX_QUEUES 16
 
95
 
 
96
struct ieee80211_sched_data
 
97
{
 
98
        struct tcf_proto *filter_list;
 
99
        struct Qdisc *queues[TC_80211_MAX_QUEUES];
 
100
        struct sk_buff_head requeued[TC_80211_MAX_QUEUES];
 
101
        unsigned long qdisc_pool;
 
102
};
 
103
 
 
104
 
 
105
/* given a data frame determine the 802.1p/1d tag to use */
 
106
static inline unsigned classify_1d(struct sk_buff *skb, struct Qdisc *qd)
 
107
{
 
108
        struct iphdr *ip;
 
109
        int dscp;
 
110
        int offset;
 
111
 
 
112
        struct ieee80211_sched_data *q = qdisc_priv(qd);
 
113
        struct tcf_result res = { -1, 0 };
 
114
 
 
115
        /* if there is a user set filter list, call out to that */
 
116
        if (q->filter_list) {
 
117
                tc_classify(skb, q->filter_list, &res);
 
118
                if (res.class != -1)
 
119
                        return res.class;
 
120
        }
 
121
 
 
122
        /* skb->priority values from 256->263 are magic values to
 
123
         * directly indicate a specific 802.1d priority.
 
124
         * This is used to allow 802.1d priority to be passed directly in
 
125
         * from VLAN tags, etc. */
 
126
        if (skb->priority >= 256 && skb->priority <= 263)
 
127
                return skb->priority - 256;
 
128
 
 
129
        /* check there is a valid IP header present */
 
130
        offset = iwlwifi_iwlwifi_ieee80211_get_hdrlen_from_skb(skb) + 8 /* LLC + proto */;
 
131
        if (skb->protocol != __constant_htons(ETH_P_IP) ||
 
132
            skb->len < offset + sizeof(*ip))
 
133
                return 0;
 
134
 
 
135
        ip = (struct iphdr *) (skb->data + offset);
 
136
 
 
137
        dscp = ip->tos & 0xfc;
 
138
        if (dscp & 0x1c)
 
139
                return 0;
 
140
        return dscp >> 5;
 
141
}
 
142
 
 
143
 
 
144
static inline int wme_downgrade_ac(struct sk_buff *skb)
 
145
{
 
146
        switch (skb->priority) {
 
147
        case 6:
 
148
        case 7:
 
149
                skb->priority = 5; /* VO -> VI */
 
150
                return 0;
 
151
        case 4:
 
152
        case 5:
 
153
                skb->priority = 3; /* VI -> BE */
 
154
                return 0;
 
155
        case 0:
 
156
        case 3:
 
157
                skb->priority = 2; /* BE -> BK */
 
158
                return 0;
 
159
        default:
 
160
                return -1;
 
161
        }
 
162
}
 
163
 
 
164
 
 
165
/* positive return value indicates which queue to use
 
166
 * negative return value indicates to drop the frame */
 
167
static inline int classify80211(struct sk_buff *skb, struct Qdisc *qd)
 
168
{
 
169
        struct ieee80211_local *local = wdev_priv(qd->dev->ieee80211_ptr);
 
170
        struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(qd->dev);
 
171
        struct ieee80211_if_sta *ifsta = &sdata->u.sta;
 
172
        struct ieee80211_tx_packet_data *pkt_data =
 
173
                (struct ieee80211_tx_packet_data *) skb->cb;
 
174
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
 
175
        unsigned short fc = le16_to_cpu(hdr->frame_control);
 
176
        int qos, tsid, dir;
 
177
        const int ieee802_1d_to_ac[8] = { 2, 3, 3, 2, 1, 1, 0, 0 };
 
178
 
 
179
        /* see if frame is data or non data frame */
 
180
        if (unlikely((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA)) {
 
181
                /* management frames go on AC_VO queue, but are sent
 
182
                * without QoS control fields */
 
183
                return IEEE80211_TX_QUEUE_DATA0;
 
184
        }
 
185
 
 
186
        if (unlikely(pkt_data->mgmt_iface)) {
 
187
                /* Data frames from hostapd (mainly, EAPOL) use AC_VO
 
188
                * and they will include QoS control fields if
 
189
                * the target STA is using WME. */
 
190
                skb->priority = 7;
 
191
                return ieee802_1d_to_ac[skb->priority];
 
192
        }
 
193
 
 
194
        /* is this a QoS frame? */
 
195
        qos = fc & IEEE80211_STYPE_QOS_DATA;
 
196
 
 
197
        if (!qos) {
 
198
                skb->priority = 0; /* required for correct WPA/11i MIC */
 
199
                return ieee802_1d_to_ac[skb->priority];
 
200
        }
 
201
 
 
202
        /* use the data classifier to determine what 802.1d tag the
 
203
         * data frame has */
 
204
        skb->priority = classify_1d(skb, qd);
 
205
        tsid = 8 + skb->priority;
 
206
 
 
207
        /* FIXME: only uplink needs to be checked for Tx */
 
208
        dir = STA_TS_UPLINK;
 
209
 
 
210
        if ((sdata->type == IEEE80211_IF_TYPE_STA) &&
 
211
            (local->wmm_acm & BIT(skb->priority))) {
 
212
                switch (ifsta->ts_data[tsid][dir].status) {
 
213
                case TS_STATUS_ACTIVE:
 
214
                        /* if TS Management is enabled, update used_time */
 
215
                        ifsta->ts_data[tsid][dir].used_time_usec +=
 
216
                                ifsta->MPDUExchangeTime;
 
217
                        break;
 
218
                case TS_STATUS_THROTTLING:
 
219
                        /* if admitted time is used up, refuse to send more */
 
220
                        if (net_ratelimit())
 
221
                                printk(KERN_DEBUG "QoS packet throttling\n");
 
222
                        break;
 
223
                default:
 
224
                        break;
 
225
                }
 
226
        }
 
227
 
 
228
        /* in case we are a client verify acm is not set for this ac */
 
229
        while ((local->wmm_acm & BIT(skb->priority)) &&
 
230
               !((sdata->type == IEEE80211_IF_TYPE_STA) &&
 
231
                 (ifsta->ts_data[skb->priority + EDCA_TSID_MIN][dir].status
 
232
                        == TS_STATUS_ACTIVE))) {
 
233
                if (wme_downgrade_ac(skb)) {
 
234
                        /* No AC with lower priority has acm=0, drop packet. */
 
235
                        return -1;
 
236
                }
 
237
        }
 
238
 
 
239
        /* look up which queue to use for frames with this 1d tag */
 
240
        return ieee802_1d_to_ac[skb->priority];
 
241
}
 
242
 
 
243
 
 
244
static int wme_qdiscop_enqueue(struct sk_buff *skb, struct Qdisc* qd)
 
245
{
 
246
        struct ieee80211_local *local = wdev_priv(qd->dev->ieee80211_ptr);
 
247
        struct ieee80211_sched_data *q = qdisc_priv(qd);
 
248
        struct ieee80211_tx_packet_data *pkt_data =
 
249
                (struct ieee80211_tx_packet_data *) skb->cb;
 
250
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
 
251
        unsigned short fc = le16_to_cpu(hdr->frame_control);
 
252
        struct Qdisc *qdisc;
 
253
        int err, queue;
 
254
 
 
255
        if (pkt_data->requeue) {
 
256
                skb_queue_tail(&q->requeued[pkt_data->queue], skb);
 
257
                qd->q.qlen++;
 
258
                return 0;
 
259
        }
 
260
 
 
261
        queue = classify80211(skb, qd);
 
262
 
 
263
        /* now we know the 1d priority, fill in the QoS header if there is one
 
264
         */
 
265
        if (WLAN_FC_IS_QOS_DATA(fc)) {
 
266
                struct sta_info *sta;
 
267
                u8 *p = skb->data + iwlwifi_ieee80211_get_hdrlen(fc) - 2;
 
268
                u8 tid = skb->priority & QOS_CONTROL_TAG1D_MASK;
 
269
                u8 ack_policy = 0;
 
270
                if (local->wifi_wme_noack_test)
 
271
                        ack_policy |= QOS_CONTROL_ACK_POLICY_NOACK <<
 
272
                                        QOS_CONTROL_ACK_POLICY_SHIFT;
 
273
                /* qos header is 2 bytes, second reserved */
 
274
                *p = ack_policy|tid;
 
275
                p++;
 
276
                *p = 0;
 
277
 
 
278
                sta = iwlwifi_sta_info_get(local, hdr->addr1);
 
279
                if (sta) {
 
280
                        int ht_queue = sta->tx_queue_id[tid];
 
281
                        if ((ht_queue < local->hw.queues) &&
 
282
                                test_bit(ht_queue, &q->qdisc_pool)) {
 
283
                                queue = ht_queue;
 
284
                                pkt_data->ht_queue = 1;
 
285
                        }
 
286
                        printk(KERN_DEBUG "wme:%s ht_queue=%d,queue=%d pool=0x%lX qdisc=%p\n",
 
287
                                 __func__,ht_queue,queue,q->qdisc_pool,q);
 
288
 
 
289
                        iwlwifi_sta_info_put(sta);
 
290
                }
 
291
 
 
292
 
 
293
        }
 
294
 
 
295
        if (unlikely(queue >= local->hw.queues)) {
 
296
#if 0
 
297
                if (net_ratelimit()) {
 
298
                        printk(KERN_DEBUG "%s - queue=%d (hw does not "
 
299
                               "support) -> %d\n",
 
300
                               __func__, queue, local->hw.queues - 1);
 
301
                }
 
302
#endif
 
303
                queue = local->hw.queues - 1;
 
304
        }
 
305
 
 
306
        if (unlikely(queue < 0)) {
 
307
                        kfree_skb(skb);
 
308
                        err = NET_XMIT_DROP;
 
309
        } else {
 
310
 
 
311
                pkt_data->queue = (unsigned int) queue;
 
312
                qdisc = q->queues[queue];
 
313
                err = qdisc->enqueue(skb, qdisc);
 
314
                if (err == NET_XMIT_SUCCESS) {
 
315
                        qd->q.qlen++;
 
316
                        qd->bstats.bytes += skb->len;
 
317
                        qd->bstats.packets++;
 
318
                        return NET_XMIT_SUCCESS;
 
319
                }
 
320
        }
 
321
        qd->qstats.drops++;
 
322
        return err;
 
323
}
 
324
 
 
325
 
 
326
/* TODO: clean up the cases where master_hard_start_xmit
 
327
 * returns non 0 - it shouldn't ever do that. Once done we
 
328
 * can remove this function */
 
329
static int wme_qdiscop_requeue(struct sk_buff *skb, struct Qdisc* qd)
 
330
{
 
331
        struct ieee80211_sched_data *q = qdisc_priv(qd);
 
332
        struct ieee80211_tx_packet_data *pkt_data =
 
333
                (struct ieee80211_tx_packet_data *) skb->cb;
 
334
        struct Qdisc *qdisc;
 
335
        int err;
 
336
 
 
337
        /* we recorded which queue to use earlier! */
 
338
        qdisc = q->queues[pkt_data->queue];
 
339
 
 
340
        if ((err = qdisc->ops->requeue(skb, qdisc)) == 0) {
 
341
                qd->q.qlen++;
 
342
                return 0;
 
343
        }
 
344
        qd->qstats.drops++;
 
345
        return err;
 
346
}
 
347
 
 
348
 
 
349
static struct sk_buff *wme_qdiscop_dequeue(struct Qdisc* qd)
 
350
{
 
351
        struct ieee80211_sched_data *q = qdisc_priv(qd);
 
352
        struct net_device *dev = qd->dev;
 
353
        struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
 
354
        struct ieee80211_hw *hw = &local->hw;
 
355
        struct sk_buff *skb;
 
356
        struct Qdisc *qdisc;
 
357
        int queue;
 
358
 
 
359
        /* check all the h/w queues in numeric/priority order */
 
360
        for (queue = 0; queue < hw->queues; queue++) {
 
361
                /* see if there is room in this hardware queue */
 
362
                if ((test_bit(IEEE80211_LINK_STATE_XOFF,&local->state[queue])) ||
 
363
                    (test_bit(IEEE80211_LINK_STATE_PENDING,&local->state[queue])) ||
 
364
                         (!test_bit(queue,&q->qdisc_pool)))
 
365
                        continue;
 
366
 
 
367
                /* there is space - try and get a frame */
 
368
                skb = skb_dequeue(&q->requeued[queue]);
 
369
                if (skb) {
 
370
                        qd->q.qlen--;
 
371
                        return skb;
 
372
                }
 
373
 
 
374
                qdisc = q->queues[queue];
 
375
                skb = qdisc->dequeue(qdisc);
 
376
                if (skb) {
 
377
                        qd->q.qlen--;
 
378
                        return skb;
 
379
                }
 
380
        }
 
381
        /* returning a NULL here when all the h/w queues are full means we
 
382
         * never need to call netif_stop_queue in the driver */
 
383
        return NULL;
 
384
}
 
385
 
 
386
 
 
387
static void wme_qdiscop_reset(struct Qdisc* qd)
 
388
{
 
389
        struct ieee80211_sched_data *q = qdisc_priv(qd);
 
390
        struct ieee80211_local *local = wdev_priv(qd->dev->ieee80211_ptr);
 
391
        struct ieee80211_hw *hw = &local->hw;
 
392
        int queue;
 
393
 
 
394
        /* QUESTION: should we have some hardware flush functionality here? */
 
395
 
 
396
        for (queue = 0; queue < hw->queues; queue++) {
 
397
                skb_queue_purge(&q->requeued[queue]);
 
398
                qdisc_reset(q->queues[queue]);
 
399
        }
 
400
        qd->q.qlen = 0;
 
401
}
 
402
 
 
403
 
 
404
static void wme_qdiscop_destroy(struct Qdisc* qd)
 
405
{
 
406
        struct ieee80211_sched_data *q = qdisc_priv(qd);
 
407
        struct ieee80211_local *local = wdev_priv(qd->dev->ieee80211_ptr);
 
408
        struct ieee80211_hw *hw = &local->hw;
 
409
        int queue;
 
410
 
 
411
        tcf_destroy_chain(q->filter_list);
 
412
        q->filter_list = NULL;
 
413
 
 
414
        for (queue=0; queue < hw->queues; queue++) {
 
415
                skb_queue_purge(&q->requeued[queue]);
 
416
                qdisc_destroy(q->queues[queue]);
 
417
                q->queues[queue] = &noop_qdisc;
 
418
        }
 
419
}
 
420
 
 
421
 
 
422
/* called whenever parameters are updated on existing qdisc */
 
423
static int wme_qdiscop_tune(struct Qdisc *qd, struct rtattr *opt)
 
424
{
 
425
/*      struct ieee80211_sched_data *q = qdisc_priv(qd);
 
426
*/
 
427
        /* check our options block is the right size */
 
428
        /* copy any options to our local structure */
 
429
/*      Ignore options block for now - always use static mapping
 
430
        struct tc_ieee80211_qopt *qopt = RTA_DATA(opt);
 
431
 
 
432
        if (opt->rta_len < RTA_LENGTH(sizeof(*qopt)))
 
433
                return -EINVAL;
 
434
        memcpy(q->tag2queue, qopt->tag2queue, sizeof(qopt->tag2queue));
 
435
*/
 
436
        return 0;
 
437
}
 
438
 
 
439
 
 
440
/* called during initial creation of qdisc on device */
 
441
static int wme_qdiscop_init(struct Qdisc *qd, struct rtattr *opt)
 
442
{
 
443
        struct ieee80211_sched_data *q = qdisc_priv(qd);
 
444
        struct net_device *dev = qd->dev;
 
445
        struct ieee80211_local *local;
 
446
        int queues;
 
447
        int err = 0, i;
 
448
 
 
449
        /* check that device is a mac80211 device */
 
450
        if (!dev->ieee80211_ptr ||
 
451
            dev->ieee80211_ptr->wiphy->privid != mac80211_wiphy_privid)
 
452
                return -EINVAL;
 
453
 
 
454
        /* check this device is an ieee80211 master type device */
 
455
        if (dev->type != ARPHRD_IEEE80211)
 
456
                return -EINVAL;
 
457
 
 
458
        /* check that there is no qdisc currently attached to device
 
459
         * this ensures that we will be the root qdisc. (I can't find a better
 
460
         * way to test this explicitly) */
 
461
        if (dev->qdisc_sleeping != &noop_qdisc)
 
462
                return -EINVAL;
 
463
 
 
464
        if (qd->flags & TCQ_F_INGRESS)
 
465
                return -EINVAL;
 
466
 
 
467
        local = wdev_priv(dev->ieee80211_ptr);
 
468
        queues = local->hw.queues;
 
469
 
 
470
        /* if options were passed in, set them */
 
471
        if (opt) {
 
472
                err = wme_qdiscop_tune(qd, opt);
 
473
        }
 
474
 
 
475
        /* create child queues */
 
476
        for (i = 0; i < queues; i++) {
 
477
                skb_queue_head_init(&q->requeued[i]);
 
478
                q->queues[i] = qdisc_create_dflt(qd->dev, &pfifo_qdisc_ops,
 
479
                                                 qd->handle);
 
480
                if (q->queues[i] == 0) {
 
481
                        q->queues[i] = &noop_qdisc;
 
482
                        printk(KERN_ERR "%s child qdisc %i creation failed", dev->name, i);
 
483
                }
 
484
        }
 
485
 
 
486
        for (i = 0; i < 4; i++)
 
487
                set_bit(i,&q->qdisc_pool);
 
488
 
 
489
 
 
490
        return err;
 
491
}
 
492
 
 
493
static int wme_qdiscop_dump(struct Qdisc *qd, struct sk_buff *skb)
 
494
{
 
495
/*      struct ieee80211_sched_data *q = qdisc_priv(qd);
 
496
        unsigned char *p = skb->tail;
 
497
        struct tc_ieee80211_qopt opt;
 
498
 
 
499
        memcpy(&opt.tag2queue, q->tag2queue, TC_80211_MAX_TAG + 1);
 
500
        RTA_PUT(skb, TCA_OPTIONS, sizeof(opt), &opt);
 
501
*/      return skb->len;
 
502
/*
 
503
rtattr_failure:
 
504
        skb_trim(skb, p - skb->data);*/
 
505
        return -1;
 
506
}
 
507
 
 
508
 
 
509
static int wme_classop_graft(struct Qdisc *qd, unsigned long arg,
 
510
                             struct Qdisc *new, struct Qdisc **old)
 
511
{
 
512
        struct ieee80211_sched_data *q = qdisc_priv(qd);
 
513
        struct ieee80211_local *local = wdev_priv(qd->dev->ieee80211_ptr);
 
514
        struct ieee80211_hw *hw = &local->hw;
 
515
        unsigned long queue = arg - 1;
 
516
 
 
517
        if (queue >= hw->queues)
 
518
                return -EINVAL;
 
519
 
 
520
        if (!new)
 
521
                new = &noop_qdisc;
 
522
 
 
523
        sch_tree_lock(qd);
 
524
        *old = q->queues[queue];
 
525
        q->queues[queue] = new;
 
526
        qdisc_reset(*old);
 
527
        sch_tree_unlock(qd);
 
528
 
 
529
        return 0;
 
530
}
 
531
 
 
532
 
 
533
static struct Qdisc *
 
534
wme_classop_leaf(struct Qdisc *qd, unsigned long arg)
 
535
{
 
536
        struct ieee80211_sched_data *q = qdisc_priv(qd);
 
537
        struct ieee80211_local *local = wdev_priv(qd->dev->ieee80211_ptr);
 
538
        struct ieee80211_hw *hw = &local->hw;
 
539
        unsigned long queue = arg - 1;
 
540
 
 
541
        if (queue >= hw->queues)
 
542
                return NULL;
 
543
 
 
544
        return q->queues[queue];
 
545
}
 
546
 
 
547
 
 
548
static unsigned long wme_classop_get(struct Qdisc *qd, u32 classid)
 
549
{
 
550
        struct ieee80211_local *local = wdev_priv(qd->dev->ieee80211_ptr);
 
551
        struct ieee80211_hw *hw = &local->hw;
 
552
        unsigned long queue = TC_H_MIN(classid);
 
553
 
 
554
        if (queue - 1 >= hw->queues)
 
555
                return 0;
 
556
 
 
557
        return queue;
 
558
}
 
559
 
 
560
 
 
561
static unsigned long wme_classop_bind(struct Qdisc *qd, unsigned long parent,
 
562
                                      u32 classid)
 
563
{
 
564
        return wme_classop_get(qd, classid);
 
565
}
 
566
 
 
567
 
 
568
static void wme_classop_put(struct Qdisc *q, unsigned long cl)
 
569
{
 
570
}
 
571
 
 
572
 
 
573
static int wme_classop_change(struct Qdisc *qd, u32 handle, u32 parent,
 
574
                              struct rtattr **tca, unsigned long *arg)
 
575
{
 
576
        unsigned long cl = *arg;
 
577
        struct ieee80211_local *local = wdev_priv(qd->dev->ieee80211_ptr);
 
578
        struct ieee80211_hw *hw = &local->hw;
 
579
 
 
580
        if (cl - 1 > hw->queues)
 
581
                return -ENOENT;
 
582
 
 
583
        /* TODO: put code to program hardware queue parameters here,
 
584
         * to allow programming from tc command line */
 
585
 
 
586
        return 0;
 
587
}
 
588
 
 
589
 
 
590
/* we don't support deleting hardware queues
 
591
 * when we add WMM-SA support - TSPECs may be deleted here */
 
592
static int wme_classop_delete(struct Qdisc *qd, unsigned long cl)
 
593
{
 
594
        struct ieee80211_local *local = wdev_priv(qd->dev->ieee80211_ptr);
 
595
        struct ieee80211_hw *hw = &local->hw;
 
596
 
 
597
        if (cl - 1 > hw->queues)
 
598
                return -ENOENT;
 
599
        return 0;
 
600
}
 
601
 
 
602
 
 
603
static int wme_classop_dump_class(struct Qdisc *qd, unsigned long cl,
 
604
                                  struct sk_buff *skb, struct tcmsg *tcm)
 
605
{
 
606
        struct ieee80211_sched_data *q = qdisc_priv(qd);
 
607
        struct ieee80211_local *local = wdev_priv(qd->dev->ieee80211_ptr);
 
608
        struct ieee80211_hw *hw = &local->hw;
 
609
 
 
610
        if (cl - 1 > hw->queues)
 
611
                return -ENOENT;
 
612
        tcm->tcm_handle = TC_H_MIN(cl);
 
613
        tcm->tcm_parent = qd->handle;
 
614
        tcm->tcm_info = q->queues[cl-1]->handle; /* do we need this? */
 
615
        return 0;
 
616
}
 
617
 
 
618
 
 
619
static void wme_classop_walk(struct Qdisc *qd, struct qdisc_walker *arg)
 
620
{
 
621
        struct ieee80211_local *local = wdev_priv(qd->dev->ieee80211_ptr);
 
622
        struct ieee80211_hw *hw = &local->hw;
 
623
        int queue;
 
624
 
 
625
        if (arg->stop)
 
626
                return;
 
627
 
 
628
        for (queue = 0; queue < hw->queues; queue++) {
 
629
                if (arg->count < arg->skip) {
 
630
                        arg->count++;
 
631
                        continue;
 
632
                }
 
633
                /* we should return classids for our internal queues here
 
634
                 * as well as the external ones */
 
635
                if (arg->fn(qd, queue+1, arg) < 0) {
 
636
                        arg->stop = 1;
 
637
                        break;
 
638
                }
 
639
                arg->count++;
 
640
        }
 
641
}
 
642
 
 
643
 
 
644
static struct tcf_proto ** wme_classop_find_tcf(struct Qdisc *qd,
 
645
                                                unsigned long cl)
 
646
{
 
647
        struct ieee80211_sched_data *q = qdisc_priv(qd);
 
648
 
 
649
        if (cl)
 
650
                return NULL;
 
651
 
 
652
        return &q->filter_list;
 
653
}
 
654
 
 
655
 
 
656
/* this qdisc is classful (i.e. has classes, some of which may have leaf qdiscs attached)
 
657
 * - these are the operations on the classes */
 
658
static struct Qdisc_class_ops class_ops =
 
659
{
 
660
        .graft = wme_classop_graft,
 
661
        .leaf = wme_classop_leaf,
 
662
 
 
663
        .get = wme_classop_get,
 
664
        .put = wme_classop_put,
 
665
        .change = wme_classop_change,
 
666
        .delete = wme_classop_delete,
 
667
        .walk = wme_classop_walk,
 
668
 
 
669
        .tcf_chain = wme_classop_find_tcf,
 
670
        .bind_tcf = wme_classop_bind,
 
671
        .unbind_tcf = wme_classop_put,
 
672
 
 
673
        .dump = wme_classop_dump_class,
 
674
};
 
675
 
 
676
 
 
677
/* queueing discipline operations */
 
678
static struct Qdisc_ops wme_qdisc_ops =
 
679
{
 
680
        .next = NULL,
 
681
        .cl_ops = &class_ops,
 
682
        .id = "ieee80211",
 
683
        .priv_size = sizeof(struct ieee80211_sched_data),
 
684
 
 
685
        .enqueue = wme_qdiscop_enqueue,
 
686
        .dequeue = wme_qdiscop_dequeue,
 
687
        .requeue = wme_qdiscop_requeue,
 
688
        .drop = NULL, /* drop not needed since we are always the root qdisc */
 
689
 
 
690
        .init = wme_qdiscop_init,
 
691
        .reset = wme_qdiscop_reset,
 
692
        .destroy = wme_qdiscop_destroy,
 
693
        .change = wme_qdiscop_tune,
 
694
 
 
695
        .dump = wme_qdiscop_dump,
 
696
};
 
697
 
 
698
 
 
699
void ieee80211_install_qdisc(struct net_device *dev)
 
700
{
 
701
        struct Qdisc *qdisc;
 
702
 
 
703
        qdisc = qdisc_create_dflt(dev, &wme_qdisc_ops, TC_H_ROOT);
 
704
        if (!qdisc) {
 
705
                printk(KERN_ERR "%s: qdisc installation failed\n", dev->name);
 
706
                return;
 
707
        }
 
708
 
 
709
        /* same handle as would be allocated by qdisc_alloc_handle() */
 
710
        qdisc->handle = 0x80010000;
 
711
 
 
712
        qdisc_lock_tree(dev);
 
713
        list_add_tail(&qdisc->list, &dev->qdisc_list);
 
714
        dev->qdisc_sleeping = qdisc;
 
715
        qdisc_unlock_tree(dev);
 
716
}
 
717
 
 
718
 
 
719
int ieee80211_qdisc_installed(struct net_device *dev)
 
720
{
 
721
        return dev->qdisc_sleeping->ops == &wme_qdisc_ops;
 
722
}
 
723
 
 
724
 
 
725
int ieee80211_wme_register(void)
 
726
{
 
727
        return register_qdisc(&wme_qdisc_ops);
 
728
}
 
729
 
 
730
 
 
731
void ieee80211_wme_unregister(void)
 
732
{
 
733
        unregister_qdisc(&wme_qdisc_ops);
 
734
}
 
735
#endif /* CONFIG_NET_SCHED */
 
736
 
 
737
int ieee80211_ht_agg_queue_add(struct ieee80211_local *local, struct sta_info *sta, u16 tid)
 
738
{
 
739
#ifdef CONFIG_NET_SCHED
 
740
        int i;
 
741
        struct ieee80211_sched_data *q = qdisc_priv(local->mdev->qdisc_sleeping);
 
742
 
 
743
        /* prepare the filter and save it for the SW queue
 
744
        * matching the recieved HW queue
 
745
        * (TODO - policy should be replaced for AP)*/
 
746
 
 
747
        /* try to get a Qdisc from a pool */
 
748
        /* FIXME: use test and set command */
 
749
        for (i=7; i < local->hw.queues; i++)
 
750
                if (!test_and_set_bit(i, &q->qdisc_pool)) {
 
751
                        sta->tx_queue_id[tid] = i;
 
752
 
 
753
                        /* IF there are already pending packets
 
754
                         * on this tid first we need to drain them
 
755
                         * on the previous queue
 
756
                         * since HT is strict in order */
 
757
#ifdef CONFIG_MAC80211_DEBUG
 
758
                        printk(KERN_ERR "mac80211:wme allocated ht agg queue %d"
 
759
                                "for tid=%d and sta " MAC_FMT "pool=0x%lX qdisc=%p\n",
 
760
                                i,tid,MAC_ARG(sta->addr),q->qdisc_pool,q);
 
761
#endif /* CONFIG_MAC80211_DEBUG */
 
762
                        return 0;
 
763
                }
 
764
 
 
765
#endif /* CONFIG_NET_SCHED */
 
766
        return -EAGAIN;
 
767
}
 
768
 
 
769
int ieee80211_ht_agg_queue_remove(struct ieee80211_local *local, struct sta_info *sta, u16 tid)
 
770
{
 
771
#ifdef CONFIG_NET_SCHED
 
772
        int i;
 
773
        struct ieee80211_sched_data *q = qdisc_priv(local->mdev->qdisc_sleeping);
 
774
 
 
775
        /* return the qdisc to the pool */
 
776
        i = sta->tx_queue_id[tid];
 
777
        clear_bit(i, &q->qdisc_pool);
 
778
        sta->tx_queue_id[tid] = local->hw.queues;
 
779
 
 
780
#endif /* CONFIG_NET_SCHED */
 
781
        return 0;
 
782
}
 
783