diff -Nur linux-2.4.30/include/linux/netdevice.h linux-2.4.30-wl-fix/include/linux/netdevice.h --- linux-2.4.30/include/linux/netdevice.h 2004-11-17 12:54:22.000000000 +0100 +++ linux-2.4.30-wl-fix/include/linux/netdevice.h 2005-05-09 16:31:08.000000000 +0200 @@ -297,7 +297,7 @@ * See for details. Jean II */ struct iw_handler_def * wireless_handlers; - struct ethtool_ops *ethtool_ops; + /* * This marks the end of the "visible" part of the structure. All @@ -352,8 +355,8 @@ struct Qdisc *qdisc; struct Qdisc *qdisc_sleeping; + struct Qdisc *qdisc_list; struct Qdisc *qdisc_ingress; - struct list_head qdisc_list; unsigned long tx_queue_len; /* Max frames per queue allowed */ /* hard_start_xmit synchronizer */ @@ -453,6 +460,7 @@ /* this will get initialized at each interface type init routine */ struct divert_blk *divert; #endif /* CONFIG_NET_DIVERT */ + struct ethtool_ops *ethtool_ops; }; /* 2.6 compatibility */ diff -Nur linux-2.4.30/include/linux/skbuff.h linux-2.4.30-wl-fix/include/linux/skbuff.h --- linux-2.4.30/include/linux/skbuff.h 2005-04-04 03:42:20.000000000 +0200 +++ linux-2.4.30-wl-fix/include/linux/skbuff.h 2005-05-08 00:50:55.000000000 +0200 @@ -135,10 +135,6 @@ struct sock *sk; /* Socket we are owned by */ struct timeval stamp; /* Time we arrived */ struct net_device *dev; /* Device we arrived on/are leaving by */ - struct net_device *real_dev; /* For support of point to point protocols - (e.g. 802.3ad) over bonding, we must save the - physical device that got the packet before - replacing skb->dev with the virtual device. */ /* Transport layer header */ union @@ -219,6 +215,10 @@ #ifdef CONFIG_NET_SCHED __u32 tc_index; /* traffic control index */ #endif + struct net_device *real_dev; /* For support of point to point protocols + (e.g. 802.3ad) over bonding, we must save the + physical device that got the packet before + replacing skb->dev with the virtual device. */ }; #ifdef __KERNEL__ diff -Nur linux-2.4.30/include/net/pkt_sched.h linux-2.4.30-wl-fix/include/net/pkt_sched.h --- linux-2.4.30/include/net/pkt_sched.h 2004-11-17 12:54:22.000000000 +0100 +++ linux-2.4.30-wl-fix/include/net/pkt_sched.h 2005-05-08 01:05:48.000000000 +0200 @@ -59,8 +59,11 @@ int (*enqueue)(struct sk_buff *, struct Qdisc *); struct sk_buff * (*dequeue)(struct Qdisc *); int (*requeue)(struct sk_buff *, struct Qdisc *); - unsigned int (*drop)(struct Qdisc *); - +#ifdef CONFIG_BCM4710 + int (*drop)(struct Qdisc *); +#else + unsigned int (*drop)(struct Qdisc *); +#endif int (*init)(struct Qdisc *, struct rtattr *arg); void (*reset)(struct Qdisc *); void (*destroy)(struct Qdisc *); @@ -80,12 +83,19 @@ #define TCQ_F_THROTTLED 2 #define TCQ_F_INGRESS 4 struct Qdisc_ops *ops; +#ifdef CONFIG_BCM4710 + struct Qdisc *next; +#endif u32 handle; - u32 parent; +#ifndef CONFIG_BCM4710 + u32 parent; +#endif atomic_t refcnt; struct sk_buff_head q; struct net_device *dev; - struct list_head list; +#ifndef CONFIG_BCM4710 + struct list_head list; +#endif struct tc_stats stats; int (*reshape_fail)(struct sk_buff *skb, struct Qdisc *q); diff -Nur linux-2.4.30/net/core/dev.c linux-2.4.30-wl-fix/net/core/dev.c --- linux-2.4.30/net/core/dev.c 2005-04-04 03:42:20.000000000 +0200 +++ linux-2.4.30-wl-fix/net/core/dev.c 2005-05-08 00:51:08.000000000 +0200 @@ -2311,6 +2311,7 @@ } return ret; +#ifndef CONFIG_BCM4710 case SIOCETHTOOL: dev_load(ifr.ifr_name); rtnl_lock(); @@ -2324,6 +2325,7 @@ ret = -EFAULT; } return ret; +#endif /* * These ioctl calls: diff -Nur linux-2.4.30/net/core/Makefile linux-2.4.30-wl-fix/net/core/Makefile --- linux-2.4.30/net/core/Makefile 2004-11-17 12:54:22.000000000 +0100 +++ linux-2.4.30-wl-fix/net/core/Makefile 2005-05-08 00:51:02.000000000 +0200 @@ -9,7 +9,11 @@ O_TARGET := core.o +ifeq ($(CONFIG_BCM4710),y) +export-objs := netfilter.o profile.o neighbour.o +else export-objs := netfilter.o profile.o ethtool.o neighbour.o +endif obj-y := sock.o skbuff.o iovec.o datagram.o scm.o @@ -21,8 +25,13 @@ obj-$(CONFIG_FILTER) += filter.o +ifeq ($(CONFIG_BCM4710),y) +obj-$(CONFIG_NET) += dev.o dev_mcast.o dst.o neighbour.o \ + rtnetlink.o utils.o +else obj-$(CONFIG_NET) += dev.o ethtool.o dev_mcast.o dst.o neighbour.o \ rtnetlink.o utils.o +endif obj-$(CONFIG_NETFILTER) += netfilter.o obj-$(CONFIG_NET_DIVERT) += dv.o diff -Nur linux-2.4.30/net/sched/sch_api.c linux-2.4.30-wl-fix/net/sched/sch_api.c --- linux-2.4.30/net/sched/sch_api.c 2004-11-17 12:54:22.000000000 +0100 +++ linux-2.4.30-wl-fix/net/sched/sch_api.c 2005-05-08 00:51:14.000000000 +0200 @@ -194,11 +194,12 @@ { struct Qdisc *q; - list_for_each_entry(q, &dev->qdisc_list, list) { + for (q = dev->qdisc_list; q; q = q->next) { if (q->handle == handle) return q; } return NULL; + } struct Qdisc *qdisc_leaf(struct Qdisc *p, u32 classid) @@ -371,8 +372,6 @@ unsigned long cl = cops->get(parent, classid); if (cl) { err = cops->graft(parent, cl, new, old); - if (new) - new->parent = classid; cops->put(parent, cl); } } @@ -427,7 +426,6 @@ memset(sch, 0, size); - INIT_LIST_HEAD(&sch->list); skb_queue_head_init(&sch->q); if (handle == TC_H_INGRESS) @@ -453,7 +451,8 @@ if (!ops->init || (err = ops->init(sch, tca[TCA_OPTIONS-1])) == 0) { write_lock(&qdisc_tree_lock); - list_add_tail(&sch->list, &dev->qdisc_list); + sch->next = dev->qdisc_list; + dev->qdisc_list = sch; write_unlock(&qdisc_tree_lock); #ifdef CONFIG_NET_ESTIMATOR if (tca[TCA_RATE-1]) @@ -808,19 +807,16 @@ if (idx > s_idx) s_q_idx = 0; read_lock(&qdisc_tree_lock); - q_idx = 0; - list_for_each_entry(q, &dev->qdisc_list, list) { - if (q_idx < s_q_idx) { - q_idx++; - continue; - } - if (tc_fill_qdisc(skb, q, q->parent, NETLINK_CB(cb->skb).pid, - cb->nlh->nlmsg_seq, NLM_F_MULTI, RTM_NEWQDISC) <= 0) { - read_unlock(&qdisc_tree_lock); - goto done; - } - q_idx++; - } + for (q = dev->qdisc_list, q_idx = 0; q; + q = q->next, q_idx++) { + if (q_idx < s_q_idx) + continue; + if (tc_fill_qdisc(skb, q, 0, NETLINK_CB(cb->skb).pid, + cb->nlh->nlmsg_seq, NLM_F_MULTI, RTM_NEWQDISC) <= 0) { + read_unlock(&qdisc_tree_lock); + goto done; + } + } read_unlock(&qdisc_tree_lock); } @@ -1033,27 +1029,24 @@ t = 0; read_lock(&qdisc_tree_lock); - list_for_each_entry(q, &dev->qdisc_list, list) { - if (t < s_t || !q->ops->cl_ops || - (tcm->tcm_parent && - TC_H_MAJ(tcm->tcm_parent) != q->handle)) { - t++; - continue; - } - if (t > s_t) - memset(&cb->args[1], 0, sizeof(cb->args)-sizeof(cb->args[0])); - arg.w.fn = qdisc_class_dump; - arg.skb = skb; - arg.cb = cb; - arg.w.stop = 0; - arg.w.skip = cb->args[1]; - arg.w.count = 0; - q->ops->cl_ops->walk(q, &arg.w); - cb->args[1] = arg.w.count; - if (arg.w.stop) - break; - t++; - } + for (q=dev->qdisc_list, t=0; q; q = q->next, t++) { + if (t < s_t) continue; + if (!q->ops->cl_ops) continue; + if (tcm->tcm_parent && TC_H_MAJ(tcm->tcm_parent) != q->handle) + continue; + if (t > s_t) + memset(&cb->args[1], 0, sizeof(cb->args)-sizeof(cb->args[0])); + arg.w.fn = qdisc_class_dump; + arg.skb = skb; + arg.cb = cb; + arg.w.stop = 0; + arg.w.skip = cb->args[1]; + arg.w.count = 0; + q->ops->cl_ops->walk(q, &arg.w); + cb->args[1] = arg.w.count; + if (arg.w.stop) + break; + } read_unlock(&qdisc_tree_lock); cb->args[0] = t; diff -Nur linux-2.4.30/net/sched/sch_generic.c linux-2.4.30-wl-fix/net/sched/sch_generic.c --- linux-2.4.30/net/sched/sch_generic.c 2004-11-17 12:54:22.000000000 +0100 +++ linux-2.4.30-wl-fix/net/sched/sch_generic.c 2005-05-08 00:51:20.000000000 +0200 @@ -392,7 +392,6 @@ return NULL; memset(sch, 0, size); - INIT_LIST_HEAD(&sch->list); skb_queue_head_init(&sch->q); sch->ops = ops; sch->enqueue = ops->enqueue; @@ -422,11 +421,22 @@ void qdisc_destroy(struct Qdisc *qdisc) { struct Qdisc_ops *ops = qdisc->ops; + struct net_device *dev; if (qdisc->flags&TCQ_F_BUILTIN || !atomic_dec_and_test(&qdisc->refcnt)) return; - list_del(&qdisc->list); + + dev = qdisc->dev; + if (dev) { + struct Qdisc *q, **qp; + for (qp = &qdisc->dev->qdisc_list; (q=*qp) != NULL; qp = &q->next) { + if (q == qdisc) { + *qp = q->next; + break; + } + } + } #ifdef CONFIG_NET_ESTIMATOR qdisc_kill_estimator(&qdisc->stats); #endif @@ -455,9 +465,9 @@ return; } write_lock(&qdisc_tree_lock); - list_add_tail(&qdisc->list, &dev->qdisc_list); + qdisc->next = dev->qdisc_list; + dev->qdisc_list = qdisc; write_unlock(&qdisc_tree_lock); - } else { qdisc = &noqueue_qdisc; } @@ -501,7 +511,7 @@ dev->qdisc = &noop_qdisc; spin_unlock_bh(&dev->queue_lock); dev->qdisc_sleeping = &noop_qdisc; - INIT_LIST_HEAD(&dev->qdisc_list); + dev->qdisc_list = NULL; write_unlock(&qdisc_tree_lock); dev_watchdog_init(dev); @@ -523,7 +533,7 @@ qdisc_destroy(qdisc); } #endif - BUG_TRAP(list_empty(&dev->qdisc_list)); + BUG_TRAP(dev->qdisc_list == NULL); BUG_TRAP(!timer_pending(&dev->watchdog_timer)); spin_unlock_bh(&dev->queue_lock); write_unlock(&qdisc_tree_lock); diff -urN linux.old/net/core/dev.c linux.dev/net/core/dev.c --- linux.old/net/core/dev.c 2005-05-28 17:42:07.000000000 +0200 +++ linux.dev/net/core/dev.c 2005-05-28 20:38:06.000000000 +0200 @@ -2223,6 +2223,7 @@ cmd == SIOCGMIIPHY || cmd == SIOCGMIIREG || cmd == SIOCSMIIREG || + cmd == SIOCETHTOOL || cmd == SIOCWANDEV) { if (dev->do_ioctl) { if (!netif_device_present(dev)) @@ -2405,6 +2406,7 @@ default: if (cmd == SIOCWANDEV || + (cmd == SIOCETHTOOL) || (cmd >= SIOCDEVPRIVATE && cmd <= SIOCDEVPRIVATE + 15)) { dev_load(ifr.ifr_name);