fix qdisc ordering
[openwrt.git] / openwrt / target / linux / linux-2.4 / patches / 002-wl_fix.patch
1 diff -Nur linux-2.4.30/include/linux/netdevice.h linux-2.4.30-wl-fix/include/linux/netdevice.h
2 --- linux-2.4.30/include/linux/netdevice.h      2004-11-17 12:54:22.000000000 +0100
3 +++ linux-2.4.30-wl-fix/include/linux/netdevice.h       2005-05-09 16:31:08.000000000 +0200
4 @@ -297,7 +297,7 @@
5          * See <net/iw_handler.h> for details. Jean II */
6         struct iw_handler_def * wireless_handlers;
7  
8 -       struct ethtool_ops *ethtool_ops;
9 +
10  
11         /*
12          * This marks the end of the "visible" part of the structure. All
13 @@ -352,8 +355,8 @@
14  
15         struct Qdisc            *qdisc;
16         struct Qdisc            *qdisc_sleeping;
17 +       struct Qdisc            *qdisc_list;
18         struct Qdisc            *qdisc_ingress;
19 -       struct list_head        qdisc_list;
20         unsigned long           tx_queue_len;   /* Max frames per queue allowed */
21  
22         /* hard_start_xmit synchronizer */
23         struct Qdisc            *qdisc;
24         struct Qdisc            *qdisc_sleeping;
25         struct Qdisc            *qdisc_ingress;
26 +       /*
27 +        * this is needed for the wlan driver binary blob from linksys
28 +        */
29 +#ifdef CONFIG_BCM4710
30 +       struct Qdisc            *qdisc_list;
31 +#else
32         struct list_head        qdisc_list;
33 +#endif
34         unsigned long           tx_queue_len;   /* Max frames per queue allowed */
35  
36         /* hard_start_xmit synchronizer */
37 @@ -453,6 +460,7 @@
38         /* this will get initialized at each interface type init routine */
39         struct divert_blk       *divert;
40  #endif /* CONFIG_NET_DIVERT */
41 +       struct ethtool_ops *ethtool_ops;
42  };
43  
44  /* 2.6 compatibility */
45 diff -Nur linux-2.4.30/include/linux/skbuff.h linux-2.4.30-wl-fix/include/linux/skbuff.h
46 --- linux-2.4.30/include/linux/skbuff.h 2005-04-04 03:42:20.000000000 +0200
47 +++ linux-2.4.30-wl-fix/include/linux/skbuff.h  2005-05-08 00:50:55.000000000 +0200
48 @@ -135,10 +135,6 @@
49         struct sock     *sk;                    /* Socket we are owned by                       */
50         struct timeval  stamp;                  /* Time we arrived                              */
51         struct net_device       *dev;           /* Device we arrived on/are leaving by          */
52 -       struct net_device       *real_dev;      /* For support of point to point protocols 
53 -                                                  (e.g. 802.3ad) over bonding, we must save the
54 -                                                  physical device that got the packet before
55 -                                                  replacing skb->dev with the virtual device.  */
56  
57         /* Transport layer header */
58         union
59 @@ -219,6 +215,10 @@
60  #ifdef CONFIG_NET_SCHED
61         __u32           tc_index;               /* traffic control index */
62  #endif
63 +       struct net_device       *real_dev;      /* For support of point to point protocols 
64 +                                                  (e.g. 802.3ad) over bonding, we must save the
65 +                                                  physical device that got the packet before
66 +                                                  replacing skb->dev with the virtual device.  */
67  };
68  
69  #ifdef __KERNEL__
70 diff -Nur linux-2.4.30/include/net/pkt_sched.h linux-2.4.30-wl-fix/include/net/pkt_sched.h
71 --- linux-2.4.30/include/net/pkt_sched.h        2004-11-17 12:54:22.000000000 +0100
72 +++ linux-2.4.30-wl-fix/include/net/pkt_sched.h 2005-05-08 01:05:48.000000000 +0200
73 @@ -59,8 +59,11 @@
74         int                     (*enqueue)(struct sk_buff *, struct Qdisc *);
75         struct sk_buff *        (*dequeue)(struct Qdisc *);
76         int                     (*requeue)(struct sk_buff *, struct Qdisc *);
77 -       unsigned int            (*drop)(struct Qdisc *);
78 -
79 +#ifdef CONFIG_BCM4710
80 +       int                     (*drop)(struct Qdisc *);
81 +#else
82 +       unsigned int            (*drop)(struct Qdisc *);
83 +#endif
84         int                     (*init)(struct Qdisc *, struct rtattr *arg);
85         void                    (*reset)(struct Qdisc *);
86         void                    (*destroy)(struct Qdisc *);
87 @@ -80,12 +83,19 @@
88  #define TCQ_F_THROTTLED        2
89  #define TCQ_F_INGRESS  4
90         struct Qdisc_ops        *ops;
91 +#ifdef CONFIG_BCM4710
92 +       struct Qdisc            *next;
93 +#endif
94         u32                     handle;
95 -       u32                     parent;
96 +#ifndef CONFIG_BCM4710
97 +       u32                     parent;
98 +#endif
99         atomic_t                refcnt;
100         struct sk_buff_head     q;
101         struct net_device       *dev;
102 -       struct list_head        list;
103 +#ifndef CONFIG_BCM4710
104 +       struct list_head        list;
105 +#endif
106  
107         struct tc_stats         stats;
108         int                     (*reshape_fail)(struct sk_buff *skb, struct Qdisc *q);
109 diff -Nur linux-2.4.30/net/core/dev.c linux-2.4.30-wl-fix/net/core/dev.c
110 --- linux-2.4.30/net/core/dev.c 2005-04-04 03:42:20.000000000 +0200
111 +++ linux-2.4.30-wl-fix/net/core/dev.c  2005-05-08 00:51:08.000000000 +0200
112 @@ -2311,6 +2311,7 @@
113                         }
114                         return ret;
115  
116 +#ifndef CONFIG_BCM4710
117                 case SIOCETHTOOL:
118                         dev_load(ifr.ifr_name);
119                         rtnl_lock();
120 @@ -2324,6 +2325,7 @@
121                                         ret = -EFAULT;
122                         }
123                         return ret;
124 +#endif
125  
126                 /*
127                  *      These ioctl calls:
128 diff -Nur linux-2.4.30/net/core/Makefile linux-2.4.30-wl-fix/net/core/Makefile
129 --- linux-2.4.30/net/core/Makefile      2004-11-17 12:54:22.000000000 +0100
130 +++ linux-2.4.30-wl-fix/net/core/Makefile       2005-05-08 00:51:02.000000000 +0200
131 @@ -9,7 +9,11 @@
132  
133  O_TARGET := core.o
134  
135 +ifeq ($(CONFIG_BCM4710),y)
136 +export-objs := netfilter.o profile.o neighbour.o
137 +else
138  export-objs := netfilter.o profile.o ethtool.o neighbour.o
139 +endif
140  
141  obj-y := sock.o skbuff.o iovec.o datagram.o scm.o
142  
143 @@ -21,8 +25,13 @@
144  
145  obj-$(CONFIG_FILTER) += filter.o
146  
147 +ifeq ($(CONFIG_BCM4710),y)
148 +obj-$(CONFIG_NET) +=   dev.o dev_mcast.o dst.o neighbour.o \
149 +                       rtnetlink.o utils.o
150 +else
151  obj-$(CONFIG_NET) +=   dev.o ethtool.o dev_mcast.o dst.o neighbour.o \
152                         rtnetlink.o utils.o
153 +endif
154  
155  obj-$(CONFIG_NETFILTER) += netfilter.o
156  obj-$(CONFIG_NET_DIVERT) += dv.o
157 diff -Nur linux-2.4.30/net/sched/sch_api.c linux-2.4.30-wl-fix/net/sched/sch_api.c
158 --- linux-2.4.30/net/sched/sch_api.c    2004-11-17 12:54:22.000000000 +0100
159 +++ linux-2.4.30-wl-fix/net/sched/sch_api.c     2005-05-08 00:51:14.000000000 +0200
160 @@ -194,11 +194,12 @@
161  {
162         struct Qdisc *q;
163  
164 -       list_for_each_entry(q, &dev->qdisc_list, list) {
165 +        for (q = dev->qdisc_list; q; q = q->next) {
166                 if (q->handle == handle)
167                         return q;
168         }
169         return NULL;
170 +
171  }
172  
173  struct Qdisc *qdisc_leaf(struct Qdisc *p, u32 classid)
174 @@ -371,8 +372,6 @@
175                         unsigned long cl = cops->get(parent, classid);
176                         if (cl) {
177                                 err = cops->graft(parent, cl, new, old);
178 -                               if (new)
179 -                                       new->parent = classid;
180                                 cops->put(parent, cl);
181                         }
182                 }
183 @@ -427,7 +426,6 @@
184  
185         memset(sch, 0, size);
186  
187 -       INIT_LIST_HEAD(&sch->list);
188         skb_queue_head_init(&sch->q);
189  
190         if (handle == TC_H_INGRESS)
191 @@ -453,7 +451,8 @@
192  
193         if (!ops->init || (err = ops->init(sch, tca[TCA_OPTIONS-1])) == 0) {
194                 write_lock(&qdisc_tree_lock);
195 -               list_add_tail(&sch->list, &dev->qdisc_list);
196 +               sch->next = dev->qdisc_list;
197 +               dev->qdisc_list = sch;
198                 write_unlock(&qdisc_tree_lock);
199  #ifdef CONFIG_NET_ESTIMATOR
200                 if (tca[TCA_RATE-1])
201 @@ -808,19 +807,16 @@
202                 if (idx > s_idx)
203                         s_q_idx = 0;
204                 read_lock(&qdisc_tree_lock);
205 -               q_idx = 0;
206 -               list_for_each_entry(q, &dev->qdisc_list, list) {
207 -                       if (q_idx < s_q_idx) {
208 -                               q_idx++;
209 -                               continue;
210 -                       }
211 -                       if (tc_fill_qdisc(skb, q, q->parent, NETLINK_CB(cb->skb).pid,
212 -                                         cb->nlh->nlmsg_seq, NLM_F_MULTI, RTM_NEWQDISC) <= 0) {
213 -                               read_unlock(&qdisc_tree_lock);
214 -                               goto done;
215 -                       }
216 -                       q_idx++;
217 -               }
218 +                for (q = dev->qdisc_list, q_idx = 0; q;
219 +                     q = q->next, q_idx++) {
220 +                        if (q_idx < s_q_idx)
221 +                                continue;
222 +                        if (tc_fill_qdisc(skb, q, 0, NETLINK_CB(cb->skb).pid,
223 +                                          cb->nlh->nlmsg_seq, NLM_F_MULTI, RTM_NEWQDISC) <= 0) {
224 +                                read_unlock(&qdisc_tree_lock);
225 +                                goto done;
226 +                        }
227 +                }
228                 read_unlock(&qdisc_tree_lock);
229         }
230  
231 @@ -1033,27 +1029,24 @@
232         t = 0;
233  
234         read_lock(&qdisc_tree_lock);
235 -       list_for_each_entry(q, &dev->qdisc_list, list) {
236 -               if (t < s_t || !q->ops->cl_ops ||
237 -                   (tcm->tcm_parent &&
238 -                    TC_H_MAJ(tcm->tcm_parent) != q->handle)) {
239 -                       t++;
240 -                       continue;
241 -               }
242 -               if (t > s_t)
243 -                       memset(&cb->args[1], 0, sizeof(cb->args)-sizeof(cb->args[0]));
244 -               arg.w.fn = qdisc_class_dump;
245 -               arg.skb = skb;
246 -               arg.cb = cb;
247 -               arg.w.stop  = 0;
248 -               arg.w.skip = cb->args[1];
249 -               arg.w.count = 0;
250 -               q->ops->cl_ops->walk(q, &arg.w);
251 -               cb->args[1] = arg.w.count;
252 -               if (arg.w.stop)
253 -                       break;
254 -               t++;
255 -       }
256 +        for (q=dev->qdisc_list, t=0; q; q = q->next, t++) {
257 +                if (t < s_t) continue;
258 +                if (!q->ops->cl_ops) continue;
259 +                if (tcm->tcm_parent && TC_H_MAJ(tcm->tcm_parent) != q->handle)
260 +                        continue;
261 +                if (t > s_t)
262 +                        memset(&cb->args[1], 0, sizeof(cb->args)-sizeof(cb->args[0]));
263 +                arg.w.fn = qdisc_class_dump;
264 +                arg.skb = skb;
265 +                arg.cb = cb;
266 +                arg.w.stop  = 0;
267 +                arg.w.skip = cb->args[1];
268 +                arg.w.count = 0;
269 +                q->ops->cl_ops->walk(q, &arg.w);
270 +                cb->args[1] = arg.w.count;
271 +                if (arg.w.stop)
272 +                        break;
273 +        }
274         read_unlock(&qdisc_tree_lock);
275  
276         cb->args[0] = t;
277 diff -Nur linux-2.4.30/net/sched/sch_generic.c linux-2.4.30-wl-fix/net/sched/sch_generic.c
278 --- linux-2.4.30/net/sched/sch_generic.c        2004-11-17 12:54:22.000000000 +0100
279 +++ linux-2.4.30-wl-fix/net/sched/sch_generic.c 2005-05-08 00:51:20.000000000 +0200
280 @@ -392,7 +392,6 @@
281                 return NULL;
282         memset(sch, 0, size);
283  
284 -       INIT_LIST_HEAD(&sch->list);
285         skb_queue_head_init(&sch->q);
286         sch->ops = ops;
287         sch->enqueue = ops->enqueue;
288 @@ -422,11 +421,22 @@
289  void qdisc_destroy(struct Qdisc *qdisc)
290  {
291         struct Qdisc_ops *ops = qdisc->ops;
292 +       struct net_device *dev;
293  
294         if (qdisc->flags&TCQ_F_BUILTIN ||
295             !atomic_dec_and_test(&qdisc->refcnt))
296                 return;
297 -       list_del(&qdisc->list);
298 +
299 +       dev = qdisc->dev;
300 +       if (dev) {
301 +               struct Qdisc *q, **qp;
302 +               for (qp = &qdisc->dev->qdisc_list; (q=*qp) != NULL; qp = &q->next) {
303 +                       if (q == qdisc) {
304 +                               *qp = q->next;
305 +                               break;
306 +                       }
307 +               }
308 +       }
309  #ifdef CONFIG_NET_ESTIMATOR
310         qdisc_kill_estimator(&qdisc->stats);
311  #endif
312 @@ -455,9 +465,9 @@
313                                 return;
314                         }
315                         write_lock(&qdisc_tree_lock);
316 -                       list_add_tail(&qdisc->list, &dev->qdisc_list);
317 +                       qdisc->next = dev->qdisc_list;
318 +                       dev->qdisc_list = qdisc;
319                         write_unlock(&qdisc_tree_lock);
320 -
321                 } else {
322                         qdisc =  &noqueue_qdisc;
323                 }
324 @@ -501,7 +511,7 @@
325         dev->qdisc = &noop_qdisc;
326         spin_unlock_bh(&dev->queue_lock);
327         dev->qdisc_sleeping = &noop_qdisc;
328 -       INIT_LIST_HEAD(&dev->qdisc_list);
329 +       dev->qdisc_list = NULL;
330         write_unlock(&qdisc_tree_lock);
331  
332         dev_watchdog_init(dev);
333 @@ -523,7 +533,7 @@
334                 qdisc_destroy(qdisc);
335          }
336  #endif
337 -       BUG_TRAP(list_empty(&dev->qdisc_list));
338 +       BUG_TRAP(dev->qdisc_list == NULL);
339         BUG_TRAP(!timer_pending(&dev->watchdog_timer));
340         spin_unlock_bh(&dev->queue_lock);
341         write_unlock(&qdisc_tree_lock);
342 diff -urN linux.old/net/core/dev.c linux.dev/net/core/dev.c
343 --- linux.old/net/core/dev.c    2005-05-28 17:42:07.000000000 +0200
344 +++ linux.dev/net/core/dev.c    2005-05-28 20:38:06.000000000 +0200
345 @@ -2223,6 +2223,7 @@
346                             cmd == SIOCGMIIPHY ||
347                             cmd == SIOCGMIIREG ||
348                             cmd == SIOCSMIIREG ||
349 +                           cmd == SIOCETHTOOL ||
350                             cmd == SIOCWANDEV) {
351                                 if (dev->do_ioctl) {
352                                         if (!netif_device_present(dev))
353 @@ -2405,6 +2406,7 @@
354                  
355                 default:
356                         if (cmd == SIOCWANDEV ||
357 +                           (cmd == SIOCETHTOOL) ||
358                             (cmd >= SIOCDEVPRIVATE &&
359                              cmd <= SIOCDEVPRIVATE + 15)) {
360                                 dev_load(ifr.ifr_name);