diff options
author | Linus Torvalds <torvalds@woody.osdl.org> | 2006-12-09 12:38:59 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.osdl.org> | 2006-12-09 12:38:59 -0500 |
commit | 99b48cff405333afe26ac603b37639c410a48e5d (patch) | |
tree | 31b427930317b1596ca6070585f66a108b722580 | |
parent | 200d018eff4be3a1fb9823441cfcebb7de86a677 (diff) | |
parent | d3dcc077bf88806201093f86325ec656e4dbfbce (diff) |
Merge master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
* master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6:
[NETLINK]: Put {IFA,IFLA}_{RTA,PAYLOAD} macros back for userspace.
[NET_SCHED] sch_htb: turn intermediate classes into leaves
[NET_SCHED] sch_cbq: deactivating when grafting, purging etc.
[XFRM]: Fix XFRMGRP_REPORT to use correct multicast group.
[NET]: Force a cache line split in hh_cache in SMP.
[NETPOLL]: make arp replies through netpoll use mac address of sender
[NETLINK]: Restore API compatibility of address and neighbour bits
[AX.25]: Fix default address and broadcast address initialization.
[AX.25]: Constify ax25 utility functions
[BNX2]: Add an error check.
[NET]: Convert hh_lock to seqlock.
-rw-r--r-- | drivers/net/bnx2.c | 2 | ||||
-rw-r--r-- | drivers/net/hamradio/6pack.c | 9 | ||||
-rw-r--r-- | drivers/net/hamradio/baycom_epp.c | 10 | ||||
-rw-r--r-- | drivers/net/hamradio/bpqether.c | 9 | ||||
-rw-r--r-- | drivers/net/hamradio/dmascc.c | 10 | ||||
-rw-r--r-- | drivers/net/hamradio/hdlcdrv.c | 16 | ||||
-rw-r--r-- | drivers/net/hamradio/mkiss.c | 9 | ||||
-rw-r--r-- | drivers/net/hamradio/scc.c | 9 | ||||
-rw-r--r-- | drivers/net/hamradio/yam.c | 9 | ||||
-rw-r--r-- | include/linux/if_addr.h | 6 | ||||
-rw-r--r-- | include/linux/if_link.h | 6 | ||||
-rw-r--r-- | include/linux/netdevice.h | 11 | ||||
-rw-r--r-- | include/linux/rtnetlink.h | 2 | ||||
-rw-r--r-- | include/linux/xfrm.h | 2 | ||||
-rw-r--r-- | include/net/ax25.h | 20 | ||||
-rw-r--r-- | include/net/neighbour.h | 18 | ||||
-rw-r--r-- | net/ax25/ax25_addr.c | 34 | ||||
-rw-r--r-- | net/core/neighbour.c | 11 | ||||
-rw-r--r-- | net/core/netpoll.c | 14 | ||||
-rw-r--r-- | net/ipv4/ip_output.c | 14 | ||||
-rw-r--r-- | net/ipv6/ip6_output.c | 17 | ||||
-rw-r--r-- | net/sched/sch_cbq.c | 21 | ||||
-rw-r--r-- | net/sched/sch_htb.c | 51 |
23 files changed, 184 insertions, 126 deletions
diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index 5bacb7587df4..7d824cf8ee2d 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c | |||
@@ -2510,7 +2510,7 @@ bnx2_init_cpus(struct bnx2 *bp) | |||
2510 | if (CHIP_NUM(bp) == CHIP_NUM_5709) { | 2510 | if (CHIP_NUM(bp) == CHIP_NUM_5709) { |
2511 | fw = &bnx2_cp_fw_09; | 2511 | fw = &bnx2_cp_fw_09; |
2512 | 2512 | ||
2513 | load_cpu_fw(bp, &cpu_reg, fw); | 2513 | rc = load_cpu_fw(bp, &cpu_reg, fw); |
2514 | if (rc) | 2514 | if (rc) |
2515 | goto init_cpu_err; | 2515 | goto init_cpu_err; |
2516 | } | 2516 | } |
diff --git a/drivers/net/hamradio/6pack.c b/drivers/net/hamradio/6pack.c index 92420f007b97..760d04a671f9 100644 --- a/drivers/net/hamradio/6pack.c +++ b/drivers/net/hamradio/6pack.c | |||
@@ -325,11 +325,6 @@ static int sp_rebuild_header(struct sk_buff *skb) | |||
325 | 325 | ||
326 | static void sp_setup(struct net_device *dev) | 326 | static void sp_setup(struct net_device *dev) |
327 | { | 327 | { |
328 | static char ax25_bcast[AX25_ADDR_LEN] = | ||
329 | {'Q'<<1,'S'<<1,'T'<<1,' '<<1,' '<<1,' '<<1,'0'<<1}; | ||
330 | static char ax25_test[AX25_ADDR_LEN] = | ||
331 | {'L'<<1,'I'<<1,'N'<<1,'U'<<1,'X'<<1,' '<<1,'1'<<1}; | ||
332 | |||
333 | /* Finish setting up the DEVICE info. */ | 328 | /* Finish setting up the DEVICE info. */ |
334 | dev->mtu = SIXP_MTU; | 329 | dev->mtu = SIXP_MTU; |
335 | dev->hard_start_xmit = sp_xmit; | 330 | dev->hard_start_xmit = sp_xmit; |
@@ -347,8 +342,8 @@ static void sp_setup(struct net_device *dev) | |||
347 | dev->tx_timeout = NULL; | 342 | dev->tx_timeout = NULL; |
348 | 343 | ||
349 | /* Only activated in AX.25 mode */ | 344 | /* Only activated in AX.25 mode */ |
350 | memcpy(dev->broadcast, ax25_bcast, AX25_ADDR_LEN); | 345 | memcpy(dev->broadcast, &ax25_bcast, AX25_ADDR_LEN); |
351 | memcpy(dev->dev_addr, ax25_test, AX25_ADDR_LEN); | 346 | memcpy(dev->dev_addr, &ax25_defaddr, AX25_ADDR_LEN); |
352 | 347 | ||
353 | SET_MODULE_OWNER(dev); | 348 | SET_MODULE_OWNER(dev); |
354 | 349 | ||
diff --git a/drivers/net/hamradio/baycom_epp.c b/drivers/net/hamradio/baycom_epp.c index 3c33d6f6a6a6..8a83db0fb3b7 100644 --- a/drivers/net/hamradio/baycom_epp.c +++ b/drivers/net/hamradio/baycom_epp.c | |||
@@ -1141,12 +1141,6 @@ static int baycom_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) | |||
1141 | */ | 1141 | */ |
1142 | static void baycom_probe(struct net_device *dev) | 1142 | static void baycom_probe(struct net_device *dev) |
1143 | { | 1143 | { |
1144 | static char ax25_bcast[AX25_ADDR_LEN] = { | ||
1145 | 'Q' << 1, 'S' << 1, 'T' << 1, ' ' << 1, ' ' << 1, ' ' << 1, '0' << 1 | ||
1146 | }; | ||
1147 | static char ax25_nocall[AX25_ADDR_LEN] = { | ||
1148 | 'L' << 1, 'I' << 1, 'N' << 1, 'U' << 1, 'X' << 1, ' ' << 1, '1' << 1 | ||
1149 | }; | ||
1150 | const struct hdlcdrv_channel_params dflt_ch_params = { | 1144 | const struct hdlcdrv_channel_params dflt_ch_params = { |
1151 | 20, 2, 10, 40, 0 | 1145 | 20, 2, 10, 40, 0 |
1152 | }; | 1146 | }; |
@@ -1182,8 +1176,8 @@ static void baycom_probe(struct net_device *dev) | |||
1182 | dev->hard_header_len = AX25_MAX_HEADER_LEN + AX25_BPQ_HEADER_LEN; | 1176 | dev->hard_header_len = AX25_MAX_HEADER_LEN + AX25_BPQ_HEADER_LEN; |
1183 | dev->mtu = AX25_DEF_PACLEN; /* eth_mtu is the default */ | 1177 | dev->mtu = AX25_DEF_PACLEN; /* eth_mtu is the default */ |
1184 | dev->addr_len = AX25_ADDR_LEN; /* sizeof an ax.25 address */ | 1178 | dev->addr_len = AX25_ADDR_LEN; /* sizeof an ax.25 address */ |
1185 | memcpy(dev->broadcast, ax25_bcast, AX25_ADDR_LEN); | 1179 | memcpy(dev->broadcast, &ax25_bcast, AX25_ADDR_LEN); |
1186 | memcpy(dev->dev_addr, ax25_nocall, AX25_ADDR_LEN); | 1180 | memcpy(dev->dev_addr, &ax25_nocall, AX25_ADDR_LEN); |
1187 | dev->tx_queue_len = 16; | 1181 | dev->tx_queue_len = 16; |
1188 | 1182 | ||
1189 | /* New style flags */ | 1183 | /* New style flags */ |
diff --git a/drivers/net/hamradio/bpqether.c b/drivers/net/hamradio/bpqether.c index 889f338132fa..5b788d84011f 100644 --- a/drivers/net/hamradio/bpqether.c +++ b/drivers/net/hamradio/bpqether.c | |||
@@ -88,11 +88,6 @@ | |||
88 | 88 | ||
89 | static char banner[] __initdata = KERN_INFO "AX.25: bpqether driver version 004\n"; | 89 | static char banner[] __initdata = KERN_INFO "AX.25: bpqether driver version 004\n"; |
90 | 90 | ||
91 | static unsigned char ax25_bcast[AX25_ADDR_LEN] = | ||
92 | {'Q' << 1, 'S' << 1, 'T' << 1, ' ' << 1, ' ' << 1, ' ' << 1, '0' << 1}; | ||
93 | static unsigned char ax25_defaddr[AX25_ADDR_LEN] = | ||
94 | {'L' << 1, 'I' << 1, 'N' << 1, 'U' << 1, 'X' << 1, ' ' << 1, '1' << 1}; | ||
95 | |||
96 | static char bcast_addr[6]={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; | 91 | static char bcast_addr[6]={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; |
97 | 92 | ||
98 | static char bpq_eth_addr[6]; | 93 | static char bpq_eth_addr[6]; |
@@ -487,8 +482,8 @@ static void bpq_setup(struct net_device *dev) | |||
487 | dev->do_ioctl = bpq_ioctl; | 482 | dev->do_ioctl = bpq_ioctl; |
488 | dev->destructor = free_netdev; | 483 | dev->destructor = free_netdev; |
489 | 484 | ||
490 | memcpy(dev->broadcast, ax25_bcast, AX25_ADDR_LEN); | 485 | memcpy(dev->broadcast, &ax25_bcast, AX25_ADDR_LEN); |
491 | memcpy(dev->dev_addr, ax25_defaddr, AX25_ADDR_LEN); | 486 | memcpy(dev->dev_addr, &ax25_defaddr, AX25_ADDR_LEN); |
492 | 487 | ||
493 | dev->flags = 0; | 488 | dev->flags = 0; |
494 | 489 | ||
diff --git a/drivers/net/hamradio/dmascc.c b/drivers/net/hamradio/dmascc.c index e6e721aff6f6..0fbb414b5a4d 100644 --- a/drivers/net/hamradio/dmascc.c +++ b/drivers/net/hamradio/dmascc.c | |||
@@ -264,12 +264,6 @@ static int io[MAX_NUM_DEVS] __initdata = { 0, }; | |||
264 | 264 | ||
265 | /* Beware! hw[] is also used in cleanup_module(). */ | 265 | /* Beware! hw[] is also used in cleanup_module(). */ |
266 | static struct scc_hardware hw[NUM_TYPES] __initdata_or_module = HARDWARE; | 266 | static struct scc_hardware hw[NUM_TYPES] __initdata_or_module = HARDWARE; |
267 | static char ax25_broadcast[7] __initdata = | ||
268 | { 'Q' << 1, 'S' << 1, 'T' << 1, ' ' << 1, ' ' << 1, ' ' << 1, | ||
269 | '0' << 1 }; | ||
270 | static char ax25_test[7] __initdata = | ||
271 | { 'L' << 1, 'I' << 1, 'N' << 1, 'U' << 1, 'X' << 1, ' ' << 1, | ||
272 | '1' << 1 }; | ||
273 | 267 | ||
274 | 268 | ||
275 | /* Global variables */ | 269 | /* Global variables */ |
@@ -443,8 +437,8 @@ static void __init dev_setup(struct net_device *dev) | |||
443 | dev->mtu = 1500; | 437 | dev->mtu = 1500; |
444 | dev->addr_len = AX25_ADDR_LEN; | 438 | dev->addr_len = AX25_ADDR_LEN; |
445 | dev->tx_queue_len = 64; | 439 | dev->tx_queue_len = 64; |
446 | memcpy(dev->broadcast, ax25_broadcast, AX25_ADDR_LEN); | 440 | memcpy(dev->broadcast, &ax25_bcast, AX25_ADDR_LEN); |
447 | memcpy(dev->dev_addr, ax25_test, AX25_ADDR_LEN); | 441 | memcpy(dev->dev_addr, &ax25_defaddr, AX25_ADDR_LEN); |
448 | } | 442 | } |
449 | 443 | ||
450 | static int __init setup_adapter(int card_base, int type, int n) | 444 | static int __init setup_adapter(int card_base, int type, int n) |
diff --git a/drivers/net/hamradio/hdlcdrv.c b/drivers/net/hamradio/hdlcdrv.c index dacc7687b97f..452873e7c68f 100644 --- a/drivers/net/hamradio/hdlcdrv.c +++ b/drivers/net/hamradio/hdlcdrv.c | |||
@@ -63,18 +63,6 @@ | |||
63 | 63 | ||
64 | /* --------------------------------------------------------------------- */ | 64 | /* --------------------------------------------------------------------- */ |
65 | 65 | ||
66 | /* | ||
67 | * The name of the card. Is used for messages and in the requests for | ||
68 | * io regions, irqs and dma channels | ||
69 | */ | ||
70 | |||
71 | static char ax25_bcast[AX25_ADDR_LEN] = | ||
72 | {'Q' << 1, 'S' << 1, 'T' << 1, ' ' << 1, ' ' << 1, ' ' << 1, '0' << 1}; | ||
73 | static char ax25_nocall[AX25_ADDR_LEN] = | ||
74 | {'L' << 1, 'I' << 1, 'N' << 1, 'U' << 1, 'X' << 1, ' ' << 1, '1' << 1}; | ||
75 | |||
76 | /* --------------------------------------------------------------------- */ | ||
77 | |||
78 | #define KISS_VERBOSE | 66 | #define KISS_VERBOSE |
79 | 67 | ||
80 | /* --------------------------------------------------------------------- */ | 68 | /* --------------------------------------------------------------------- */ |
@@ -709,8 +697,8 @@ static void hdlcdrv_setup(struct net_device *dev) | |||
709 | dev->hard_header_len = AX25_MAX_HEADER_LEN + AX25_BPQ_HEADER_LEN; | 697 | dev->hard_header_len = AX25_MAX_HEADER_LEN + AX25_BPQ_HEADER_LEN; |
710 | dev->mtu = AX25_DEF_PACLEN; /* eth_mtu is the default */ | 698 | dev->mtu = AX25_DEF_PACLEN; /* eth_mtu is the default */ |
711 | dev->addr_len = AX25_ADDR_LEN; /* sizeof an ax.25 address */ | 699 | dev->addr_len = AX25_ADDR_LEN; /* sizeof an ax.25 address */ |
712 | memcpy(dev->broadcast, ax25_bcast, AX25_ADDR_LEN); | 700 | memcpy(dev->broadcast, &ax25_bcast, AX25_ADDR_LEN); |
713 | memcpy(dev->dev_addr, ax25_nocall, AX25_ADDR_LEN); | 701 | memcpy(dev->dev_addr, &ax25_defaddr, AX25_ADDR_LEN); |
714 | dev->tx_queue_len = 16; | 702 | dev->tx_queue_len = 16; |
715 | } | 703 | } |
716 | 704 | ||
diff --git a/drivers/net/hamradio/mkiss.c b/drivers/net/hamradio/mkiss.c index d8715b200c17..d08fbc396648 100644 --- a/drivers/net/hamradio/mkiss.c +++ b/drivers/net/hamradio/mkiss.c | |||
@@ -672,11 +672,6 @@ static struct net_device_stats *ax_get_stats(struct net_device *dev) | |||
672 | 672 | ||
673 | static void ax_setup(struct net_device *dev) | 673 | static void ax_setup(struct net_device *dev) |
674 | { | 674 | { |
675 | static char ax25_bcast[AX25_ADDR_LEN] = | ||
676 | {'Q'<<1,'S'<<1,'T'<<1,' '<<1,' '<<1,' '<<1,'0'<<1}; | ||
677 | static char ax25_test[AX25_ADDR_LEN] = | ||
678 | {'L'<<1,'I'<<1,'N'<<1,'U'<<1,'X'<<1,' '<<1,'1'<<1}; | ||
679 | |||
680 | /* Finish setting up the DEVICE info. */ | 675 | /* Finish setting up the DEVICE info. */ |
681 | dev->mtu = AX_MTU; | 676 | dev->mtu = AX_MTU; |
682 | dev->hard_start_xmit = ax_xmit; | 677 | dev->hard_start_xmit = ax_xmit; |
@@ -691,8 +686,8 @@ static void ax_setup(struct net_device *dev) | |||
691 | dev->hard_header = ax_header; | 686 | dev->hard_header = ax_header; |
692 | dev->rebuild_header = ax_rebuild_header; | 687 | dev->rebuild_header = ax_rebuild_header; |
693 | 688 | ||
694 | memcpy(dev->broadcast, ax25_bcast, AX25_ADDR_LEN); | 689 | memcpy(dev->broadcast, &ax25_bcast, AX25_ADDR_LEN); |
695 | memcpy(dev->dev_addr, ax25_test, AX25_ADDR_LEN); | 690 | memcpy(dev->dev_addr, &ax25_defaddr, AX25_ADDR_LEN); |
696 | 691 | ||
697 | dev->flags = IFF_BROADCAST | IFF_MULTICAST; | 692 | dev->flags = IFF_BROADCAST | IFF_MULTICAST; |
698 | } | 693 | } |
diff --git a/drivers/net/hamradio/scc.c b/drivers/net/hamradio/scc.c index ec9b6d9b6f05..2ce047e9d262 100644 --- a/drivers/net/hamradio/scc.c +++ b/drivers/net/hamradio/scc.c | |||
@@ -1540,11 +1540,6 @@ static int scc_net_alloc(const char *name, struct scc_channel *scc) | |||
1540 | /* * Network driver methods * */ | 1540 | /* * Network driver methods * */ |
1541 | /* ******************************************************************** */ | 1541 | /* ******************************************************************** */ |
1542 | 1542 | ||
1543 | static unsigned char ax25_bcast[AX25_ADDR_LEN] = | ||
1544 | {'Q' << 1, 'S' << 1, 'T' << 1, ' ' << 1, ' ' << 1, ' ' << 1, '0' << 1}; | ||
1545 | static unsigned char ax25_nocall[AX25_ADDR_LEN] = | ||
1546 | {'L' << 1, 'I' << 1, 'N' << 1, 'U' << 1, 'X' << 1, ' ' << 1, '1' << 1}; | ||
1547 | |||
1548 | /* ----> Initialize device <----- */ | 1543 | /* ----> Initialize device <----- */ |
1549 | 1544 | ||
1550 | static void scc_net_setup(struct net_device *dev) | 1545 | static void scc_net_setup(struct net_device *dev) |
@@ -1562,8 +1557,8 @@ static void scc_net_setup(struct net_device *dev) | |||
1562 | dev->do_ioctl = scc_net_ioctl; | 1557 | dev->do_ioctl = scc_net_ioctl; |
1563 | dev->tx_timeout = NULL; | 1558 | dev->tx_timeout = NULL; |
1564 | 1559 | ||
1565 | memcpy(dev->broadcast, ax25_bcast, AX25_ADDR_LEN); | 1560 | memcpy(dev->broadcast, &ax25_bcast, AX25_ADDR_LEN); |
1566 | memcpy(dev->dev_addr, ax25_nocall, AX25_ADDR_LEN); | 1561 | memcpy(dev->dev_addr, &ax25_defaddr, AX25_ADDR_LEN); |
1567 | 1562 | ||
1568 | dev->flags = 0; | 1563 | dev->flags = 0; |
1569 | 1564 | ||
diff --git a/drivers/net/hamradio/yam.c b/drivers/net/hamradio/yam.c index 3c4455bd466d..6d74f08720d5 100644 --- a/drivers/net/hamradio/yam.c +++ b/drivers/net/hamradio/yam.c | |||
@@ -156,11 +156,6 @@ static struct net_device *yam_devs[NR_PORTS]; | |||
156 | 156 | ||
157 | static struct yam_mcs *yam_data; | 157 | static struct yam_mcs *yam_data; |
158 | 158 | ||
159 | static char ax25_bcast[7] = | ||
160 | {'Q' << 1, 'S' << 1, 'T' << 1, ' ' << 1, ' ' << 1, ' ' << 1, '0' << 1}; | ||
161 | static char ax25_test[7] = | ||
162 | {'L' << 1, 'I' << 1, 'N' << 1, 'U' << 1, 'X' << 1, ' ' << 1, '1' << 1}; | ||
163 | |||
164 | static DEFINE_TIMER(yam_timer, NULL, 0, 0); | 159 | static DEFINE_TIMER(yam_timer, NULL, 0, 0); |
165 | 160 | ||
166 | /* --------------------------------------------------------------------- */ | 161 | /* --------------------------------------------------------------------- */ |
@@ -1115,8 +1110,8 @@ static void yam_setup(struct net_device *dev) | |||
1115 | dev->hard_header_len = AX25_MAX_HEADER_LEN; | 1110 | dev->hard_header_len = AX25_MAX_HEADER_LEN; |
1116 | dev->mtu = AX25_MTU; | 1111 | dev->mtu = AX25_MTU; |
1117 | dev->addr_len = AX25_ADDR_LEN; | 1112 | dev->addr_len = AX25_ADDR_LEN; |
1118 | memcpy(dev->broadcast, ax25_bcast, AX25_ADDR_LEN); | 1113 | memcpy(dev->broadcast, &ax25_bcast, AX25_ADDR_LEN); |
1119 | memcpy(dev->dev_addr, ax25_test, AX25_ADDR_LEN); | 1114 | memcpy(dev->dev_addr, &ax25_defaddr, AX25_ADDR_LEN); |
1120 | } | 1115 | } |
1121 | 1116 | ||
1122 | static int __init yam_init_driver(void) | 1117 | static int __init yam_init_driver(void) |
diff --git a/include/linux/if_addr.h b/include/linux/if_addr.h index dbe8f6120a40..d557e4ce9b6b 100644 --- a/include/linux/if_addr.h +++ b/include/linux/if_addr.h | |||
@@ -52,4 +52,10 @@ struct ifa_cacheinfo | |||
52 | __u32 tstamp; /* updated timestamp, hundredths of seconds */ | 52 | __u32 tstamp; /* updated timestamp, hundredths of seconds */ |
53 | }; | 53 | }; |
54 | 54 | ||
55 | /* backwards compatibility for userspace */ | ||
56 | #ifndef __KERNEL__ | ||
57 | #define IFA_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ifaddrmsg)))) | ||
58 | #define IFA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ifaddrmsg)) | ||
59 | #endif | ||
60 | |||
55 | #endif | 61 | #endif |
diff --git a/include/linux/if_link.h b/include/linux/if_link.h index e963a077e6f5..35ed3b5467f3 100644 --- a/include/linux/if_link.h +++ b/include/linux/if_link.h | |||
@@ -82,6 +82,12 @@ enum | |||
82 | 82 | ||
83 | #define IFLA_MAX (__IFLA_MAX - 1) | 83 | #define IFLA_MAX (__IFLA_MAX - 1) |
84 | 84 | ||
85 | /* backwards compatibility for userspace */ | ||
86 | #ifndef __KERNEL__ | ||
87 | #define IFLA_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ifinfomsg)))) | ||
88 | #define IFLA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ifinfomsg)) | ||
89 | #endif | ||
90 | |||
85 | /* ifi_flags. | 91 | /* ifi_flags. |
86 | 92 | ||
87 | IFF_* flags. | 93 | IFF_* flags. |
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index c57088f575a3..6be767c76b37 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h | |||
@@ -193,13 +193,20 @@ struct hh_cache | |||
193 | { | 193 | { |
194 | struct hh_cache *hh_next; /* Next entry */ | 194 | struct hh_cache *hh_next; /* Next entry */ |
195 | atomic_t hh_refcnt; /* number of users */ | 195 | atomic_t hh_refcnt; /* number of users */ |
196 | __be16 hh_type; /* protocol identifier, f.e ETH_P_IP | 196 | /* |
197 | * We want hh_output, hh_len, hh_lock and hh_data be a in a separate | ||
198 | * cache line on SMP. | ||
199 | * They are mostly read, but hh_refcnt may be changed quite frequently, | ||
200 | * incurring cache line ping pongs. | ||
201 | */ | ||
202 | __be16 hh_type ____cacheline_aligned_in_smp; | ||
203 | /* protocol identifier, f.e ETH_P_IP | ||
197 | * NOTE: For VLANs, this will be the | 204 | * NOTE: For VLANs, this will be the |
198 | * encapuslated type. --BLG | 205 | * encapuslated type. --BLG |
199 | */ | 206 | */ |
200 | u16 hh_len; /* length of header */ | 207 | u16 hh_len; /* length of header */ |
201 | int (*hh_output)(struct sk_buff *skb); | 208 | int (*hh_output)(struct sk_buff *skb); |
202 | rwlock_t hh_lock; | 209 | seqlock_t hh_lock; |
203 | 210 | ||
204 | /* cached hardware header; allow for machine alignment needs. */ | 211 | /* cached hardware header; allow for machine alignment needs. */ |
205 | #define HH_DATA_MOD 16 | 212 | #define HH_DATA_MOD 16 |
diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h index 493297acdae8..4a629ea70cc4 100644 --- a/include/linux/rtnetlink.h +++ b/include/linux/rtnetlink.h | |||
@@ -3,6 +3,8 @@ | |||
3 | 3 | ||
4 | #include <linux/netlink.h> | 4 | #include <linux/netlink.h> |
5 | #include <linux/if_link.h> | 5 | #include <linux/if_link.h> |
6 | #include <linux/if_addr.h> | ||
7 | #include <linux/neighbour.h> | ||
6 | 8 | ||
7 | /**** | 9 | /**** |
8 | * Routing/neighbour discovery messages. | 10 | * Routing/neighbour discovery messages. |
diff --git a/include/linux/xfrm.h b/include/linux/xfrm.h index 088ba8113f7e..9529ea1ae392 100644 --- a/include/linux/xfrm.h +++ b/include/linux/xfrm.h | |||
@@ -357,7 +357,7 @@ struct xfrm_user_report { | |||
357 | #define XFRMGRP_EXPIRE 2 | 357 | #define XFRMGRP_EXPIRE 2 |
358 | #define XFRMGRP_SA 4 | 358 | #define XFRMGRP_SA 4 |
359 | #define XFRMGRP_POLICY 8 | 359 | #define XFRMGRP_POLICY 8 |
360 | #define XFRMGRP_REPORT 0x10 | 360 | #define XFRMGRP_REPORT 0x20 |
361 | #endif | 361 | #endif |
362 | 362 | ||
363 | enum xfrm_nlgroups { | 363 | enum xfrm_nlgroups { |
diff --git a/include/net/ax25.h b/include/net/ax25.h index 69374cd1a857..e1d116f11923 100644 --- a/include/net/ax25.h +++ b/include/net/ax25.h | |||
@@ -282,15 +282,17 @@ extern void ax25_fillin_cb(ax25_cb *, ax25_dev *); | |||
282 | extern struct sock *ax25_make_new(struct sock *, struct ax25_dev *); | 282 | extern struct sock *ax25_make_new(struct sock *, struct ax25_dev *); |
283 | 283 | ||
284 | /* ax25_addr.c */ | 284 | /* ax25_addr.c */ |
285 | extern ax25_address null_ax25_address; | 285 | extern const ax25_address ax25_bcast; |
286 | extern char *ax2asc(char *buf, ax25_address *); | 286 | extern const ax25_address ax25_defaddr; |
287 | extern void asc2ax(ax25_address *addr, char *callsign); | 287 | extern const ax25_address null_ax25_address; |
288 | extern int ax25cmp(ax25_address *, ax25_address *); | 288 | extern int ax25cmp(const ax25_address *, const ax25_address *); |
289 | extern int ax25digicmp(ax25_digi *, ax25_digi *); | 289 | extern int ax25digicmp(const ax25_digi *, const ax25_digi *); |
290 | extern unsigned char *ax25_addr_parse(unsigned char *, int, ax25_address *, ax25_address *, ax25_digi *, int *, int *); | 290 | extern const unsigned char *ax25_addr_parse(const unsigned char *, int, |
291 | extern int ax25_addr_build(unsigned char *, ax25_address *, ax25_address *, ax25_digi *, int, int); | 291 | ax25_address *, ax25_address *, ax25_digi *, int *, int *); |
292 | extern int ax25_addr_size(ax25_digi *); | 292 | extern int ax25_addr_build(unsigned char *, const ax25_address *, |
293 | extern void ax25_digi_invert(ax25_digi *, ax25_digi *); | 293 | const ax25_address *, const ax25_digi *, int, int); |
294 | extern int ax25_addr_size(const ax25_digi *); | ||
295 | extern void ax25_digi_invert(const ax25_digi *, ax25_digi *); | ||
294 | 296 | ||
295 | /* ax25_dev.c */ | 297 | /* ax25_dev.c */ |
296 | extern ax25_dev *ax25_dev_list; | 298 | extern ax25_dev *ax25_dev_list; |
diff --git a/include/net/neighbour.h b/include/net/neighbour.h index 23967031ddb7..3725b93c52f3 100644 --- a/include/net/neighbour.h +++ b/include/net/neighbour.h | |||
@@ -309,6 +309,24 @@ static inline int neigh_event_send(struct neighbour *neigh, struct sk_buff *skb) | |||
309 | return 0; | 309 | return 0; |
310 | } | 310 | } |
311 | 311 | ||
312 | static inline int neigh_hh_output(struct hh_cache *hh, struct sk_buff *skb) | ||
313 | { | ||
314 | unsigned seq; | ||
315 | int hh_len; | ||
316 | |||
317 | do { | ||
318 | int hh_alen; | ||
319 | |||
320 | seq = read_seqbegin(&hh->hh_lock); | ||
321 | hh_len = hh->hh_len; | ||
322 | hh_alen = HH_DATA_ALIGN(hh_len); | ||
323 | memcpy(skb->data - hh_alen, hh->hh_data, hh_alen); | ||
324 | } while (read_seqretry(&hh->hh_lock, seq)); | ||
325 | |||
326 | skb_push(skb, hh_len); | ||
327 | return hh->hh_output(skb); | ||
328 | } | ||
329 | |||
312 | static inline struct neighbour * | 330 | static inline struct neighbour * |
313 | __neigh_lookup(struct neigh_table *tbl, const void *pkey, struct net_device *dev, int creat) | 331 | __neigh_lookup(struct neigh_table *tbl, const void *pkey, struct net_device *dev, int creat) |
314 | { | 332 | { |
diff --git a/net/ax25/ax25_addr.c b/net/ax25/ax25_addr.c index 5f0896ad0042..21a0616152fc 100644 --- a/net/ax25/ax25_addr.c +++ b/net/ax25/ax25_addr.c | |||
@@ -29,17 +29,26 @@ | |||
29 | #include <linux/interrupt.h> | 29 | #include <linux/interrupt.h> |
30 | 30 | ||
31 | /* | 31 | /* |
32 | * The null address is defined as a callsign of all spaces with an | 32 | * The default broadcast address of an interface is QST-0; the default address |
33 | * SSID of zero. | 33 | * is LINUX-1. The null address is defined as a callsign of all spaces with |
34 | * an SSID of zero. | ||
34 | */ | 35 | */ |
35 | ax25_address null_ax25_address = {{0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00}}; | ||
36 | 36 | ||
37 | const ax25_address ax25_bcast = | ||
38 | {{'Q' << 1, 'S' << 1, 'T' << 1, ' ' << 1, ' ' << 1, ' ' << 1, 0 << 1}}; | ||
39 | const ax25_address ax25_defaddr = | ||
40 | {{'L' << 1, 'I' << 1, 'N' << 1, 'U' << 1, 'X' << 1, ' ' << 1, 1 << 1}}; | ||
41 | const ax25_address null_ax25_address = | ||
42 | {{' ' << 1, ' ' << 1, ' ' << 1, ' ' << 1, ' ' << 1, ' ' << 1, 0 << 1}}; | ||
43 | |||
44 | EXPORT_SYMBOL_GPL(ax25_bcast); | ||
45 | EXPORT_SYMBOL_GPL(ax25_defaddr); | ||
37 | EXPORT_SYMBOL(null_ax25_address); | 46 | EXPORT_SYMBOL(null_ax25_address); |
38 | 47 | ||
39 | /* | 48 | /* |
40 | * ax25 -> ascii conversion | 49 | * ax25 -> ascii conversion |
41 | */ | 50 | */ |
42 | char *ax2asc(char *buf, ax25_address *a) | 51 | char *ax2asc(char *buf, const ax25_address *a) |
43 | { | 52 | { |
44 | char c, *s; | 53 | char c, *s; |
45 | int n; | 54 | int n; |
@@ -72,7 +81,7 @@ EXPORT_SYMBOL(ax2asc); | |||
72 | /* | 81 | /* |
73 | * ascii -> ax25 conversion | 82 | * ascii -> ax25 conversion |
74 | */ | 83 | */ |
75 | void asc2ax(ax25_address *addr, char *callsign) | 84 | void asc2ax(ax25_address *addr, const char *callsign) |
76 | { | 85 | { |
77 | char *s; | 86 | char *s; |
78 | int n; | 87 | int n; |
@@ -107,7 +116,7 @@ EXPORT_SYMBOL(asc2ax); | |||
107 | /* | 116 | /* |
108 | * Compare two ax.25 addresses | 117 | * Compare two ax.25 addresses |
109 | */ | 118 | */ |
110 | int ax25cmp(ax25_address *a, ax25_address *b) | 119 | int ax25cmp(const ax25_address *a, const ax25_address *b) |
111 | { | 120 | { |
112 | int ct = 0; | 121 | int ct = 0; |
113 | 122 | ||
@@ -128,7 +137,7 @@ EXPORT_SYMBOL(ax25cmp); | |||
128 | /* | 137 | /* |
129 | * Compare two AX.25 digipeater paths. | 138 | * Compare two AX.25 digipeater paths. |
130 | */ | 139 | */ |
131 | int ax25digicmp(ax25_digi *digi1, ax25_digi *digi2) | 140 | int ax25digicmp(const ax25_digi *digi1, const ax25_digi *digi2) |
132 | { | 141 | { |
133 | int i; | 142 | int i; |
134 | 143 | ||
@@ -149,7 +158,9 @@ int ax25digicmp(ax25_digi *digi1, ax25_digi *digi2) | |||
149 | * Given an AX.25 address pull of to, from, digi list, command/response and the start of data | 158 | * Given an AX.25 address pull of to, from, digi list, command/response and the start of data |
150 | * | 159 | * |
151 | */ | 160 | */ |
152 | unsigned char *ax25_addr_parse(unsigned char *buf, int len, ax25_address *src, ax25_address *dest, ax25_digi *digi, int *flags, int *dama) | 161 | const unsigned char *ax25_addr_parse(const unsigned char *buf, int len, |
162 | ax25_address *src, ax25_address *dest, ax25_digi *digi, int *flags, | ||
163 | int *dama) | ||
153 | { | 164 | { |
154 | int d = 0; | 165 | int d = 0; |
155 | 166 | ||
@@ -204,7 +215,8 @@ unsigned char *ax25_addr_parse(unsigned char *buf, int len, ax25_address *src, a | |||
204 | /* | 215 | /* |
205 | * Assemble an AX.25 header from the bits | 216 | * Assemble an AX.25 header from the bits |
206 | */ | 217 | */ |
207 | int ax25_addr_build(unsigned char *buf, ax25_address *src, ax25_address *dest, ax25_digi *d, int flag, int modulus) | 218 | int ax25_addr_build(unsigned char *buf, const ax25_address *src, |
219 | const ax25_address *dest, const ax25_digi *d, int flag, int modulus) | ||
208 | { | 220 | { |
209 | int len = 0; | 221 | int len = 0; |
210 | int ct = 0; | 222 | int ct = 0; |
@@ -261,7 +273,7 @@ int ax25_addr_build(unsigned char *buf, ax25_address *src, ax25_address *dest, a | |||
261 | return len; | 273 | return len; |
262 | } | 274 | } |
263 | 275 | ||
264 | int ax25_addr_size(ax25_digi *dp) | 276 | int ax25_addr_size(const ax25_digi *dp) |
265 | { | 277 | { |
266 | if (dp == NULL) | 278 | if (dp == NULL) |
267 | return 2 * AX25_ADDR_LEN; | 279 | return 2 * AX25_ADDR_LEN; |
@@ -272,7 +284,7 @@ int ax25_addr_size(ax25_digi *dp) | |||
272 | /* | 284 | /* |
273 | * Reverse Digipeat List. May not pass both parameters as same struct | 285 | * Reverse Digipeat List. May not pass both parameters as same struct |
274 | */ | 286 | */ |
275 | void ax25_digi_invert(ax25_digi *in, ax25_digi *out) | 287 | void ax25_digi_invert(const ax25_digi *in, ax25_digi *out) |
276 | { | 288 | { |
277 | int ct; | 289 | int ct; |
278 | 290 | ||
diff --git a/net/core/neighbour.c b/net/core/neighbour.c index 0ab1987b9348..e7300b6b4079 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c | |||
@@ -577,9 +577,10 @@ void neigh_destroy(struct neighbour *neigh) | |||
577 | while ((hh = neigh->hh) != NULL) { | 577 | while ((hh = neigh->hh) != NULL) { |
578 | neigh->hh = hh->hh_next; | 578 | neigh->hh = hh->hh_next; |
579 | hh->hh_next = NULL; | 579 | hh->hh_next = NULL; |
580 | write_lock_bh(&hh->hh_lock); | 580 | |
581 | write_seqlock_bh(&hh->hh_lock); | ||
581 | hh->hh_output = neigh_blackhole; | 582 | hh->hh_output = neigh_blackhole; |
582 | write_unlock_bh(&hh->hh_lock); | 583 | write_sequnlock_bh(&hh->hh_lock); |
583 | if (atomic_dec_and_test(&hh->hh_refcnt)) | 584 | if (atomic_dec_and_test(&hh->hh_refcnt)) |
584 | kfree(hh); | 585 | kfree(hh); |
585 | } | 586 | } |
@@ -897,9 +898,9 @@ static void neigh_update_hhs(struct neighbour *neigh) | |||
897 | 898 | ||
898 | if (update) { | 899 | if (update) { |
899 | for (hh = neigh->hh; hh; hh = hh->hh_next) { | 900 | for (hh = neigh->hh; hh; hh = hh->hh_next) { |
900 | write_lock_bh(&hh->hh_lock); | 901 | write_seqlock_bh(&hh->hh_lock); |
901 | update(hh, neigh->dev, neigh->ha); | 902 | update(hh, neigh->dev, neigh->ha); |
902 | write_unlock_bh(&hh->hh_lock); | 903 | write_sequnlock_bh(&hh->hh_lock); |
903 | } | 904 | } |
904 | } | 905 | } |
905 | } | 906 | } |
@@ -1089,7 +1090,7 @@ static void neigh_hh_init(struct neighbour *n, struct dst_entry *dst, | |||
1089 | break; | 1090 | break; |
1090 | 1091 | ||
1091 | if (!hh && (hh = kzalloc(sizeof(*hh), GFP_ATOMIC)) != NULL) { | 1092 | if (!hh && (hh = kzalloc(sizeof(*hh), GFP_ATOMIC)) != NULL) { |
1092 | rwlock_init(&hh->hh_lock); | 1093 | seqlock_init(&hh->hh_lock); |
1093 | hh->hh_type = protocol; | 1094 | hh->hh_type = protocol; |
1094 | atomic_set(&hh->hh_refcnt, 0); | 1095 | atomic_set(&hh->hh_refcnt, 0); |
1095 | hh->hh_next = NULL; | 1096 | hh->hh_next = NULL; |
diff --git a/net/core/netpoll.c b/net/core/netpoll.c index b3c559b9ac35..8a271285f2f3 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c | |||
@@ -330,6 +330,7 @@ static void arp_reply(struct sk_buff *skb) | |||
330 | unsigned char *arp_ptr; | 330 | unsigned char *arp_ptr; |
331 | int size, type = ARPOP_REPLY, ptype = ETH_P_ARP; | 331 | int size, type = ARPOP_REPLY, ptype = ETH_P_ARP; |
332 | __be32 sip, tip; | 332 | __be32 sip, tip; |
333 | unsigned char *sha; | ||
333 | struct sk_buff *send_skb; | 334 | struct sk_buff *send_skb; |
334 | struct netpoll *np = NULL; | 335 | struct netpoll *np = NULL; |
335 | 336 | ||
@@ -356,9 +357,14 @@ static void arp_reply(struct sk_buff *skb) | |||
356 | arp->ar_op != htons(ARPOP_REQUEST)) | 357 | arp->ar_op != htons(ARPOP_REQUEST)) |
357 | return; | 358 | return; |
358 | 359 | ||
359 | arp_ptr = (unsigned char *)(arp+1) + skb->dev->addr_len; | 360 | arp_ptr = (unsigned char *)(arp+1); |
361 | /* save the location of the src hw addr */ | ||
362 | sha = arp_ptr; | ||
363 | arp_ptr += skb->dev->addr_len; | ||
360 | memcpy(&sip, arp_ptr, 4); | 364 | memcpy(&sip, arp_ptr, 4); |
361 | arp_ptr += 4 + skb->dev->addr_len; | 365 | arp_ptr += 4; |
366 | /* if we actually cared about dst hw addr, it would get copied here */ | ||
367 | arp_ptr += skb->dev->addr_len; | ||
362 | memcpy(&tip, arp_ptr, 4); | 368 | memcpy(&tip, arp_ptr, 4); |
363 | 369 | ||
364 | /* Should we ignore arp? */ | 370 | /* Should we ignore arp? */ |
@@ -381,7 +387,7 @@ static void arp_reply(struct sk_buff *skb) | |||
381 | 387 | ||
382 | if (np->dev->hard_header && | 388 | if (np->dev->hard_header && |
383 | np->dev->hard_header(send_skb, skb->dev, ptype, | 389 | np->dev->hard_header(send_skb, skb->dev, ptype, |
384 | np->remote_mac, np->local_mac, | 390 | sha, np->local_mac, |
385 | send_skb->len) < 0) { | 391 | send_skb->len) < 0) { |
386 | kfree_skb(send_skb); | 392 | kfree_skb(send_skb); |
387 | return; | 393 | return; |
@@ -405,7 +411,7 @@ static void arp_reply(struct sk_buff *skb) | |||
405 | arp_ptr += np->dev->addr_len; | 411 | arp_ptr += np->dev->addr_len; |
406 | memcpy(arp_ptr, &tip, 4); | 412 | memcpy(arp_ptr, &tip, 4); |
407 | arp_ptr += 4; | 413 | arp_ptr += 4; |
408 | memcpy(arp_ptr, np->remote_mac, np->dev->addr_len); | 414 | memcpy(arp_ptr, sha, np->dev->addr_len); |
409 | arp_ptr += np->dev->addr_len; | 415 | arp_ptr += np->dev->addr_len; |
410 | memcpy(arp_ptr, &sip, 4); | 416 | memcpy(arp_ptr, &sip, 4); |
411 | 417 | ||
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index a35209d517ad..f071f84808fa 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c | |||
@@ -164,7 +164,6 @@ EXPORT_SYMBOL_GPL(ip_build_and_send_pkt); | |||
164 | static inline int ip_finish_output2(struct sk_buff *skb) | 164 | static inline int ip_finish_output2(struct sk_buff *skb) |
165 | { | 165 | { |
166 | struct dst_entry *dst = skb->dst; | 166 | struct dst_entry *dst = skb->dst; |
167 | struct hh_cache *hh = dst->hh; | ||
168 | struct net_device *dev = dst->dev; | 167 | struct net_device *dev = dst->dev; |
169 | int hh_len = LL_RESERVED_SPACE(dev); | 168 | int hh_len = LL_RESERVED_SPACE(dev); |
170 | 169 | ||
@@ -183,16 +182,9 @@ static inline int ip_finish_output2(struct sk_buff *skb) | |||
183 | skb = skb2; | 182 | skb = skb2; |
184 | } | 183 | } |
185 | 184 | ||
186 | if (hh) { | 185 | if (dst->hh) |
187 | int hh_alen; | 186 | return neigh_hh_output(dst->hh, skb); |
188 | 187 | else if (dst->neighbour) | |
189 | read_lock_bh(&hh->hh_lock); | ||
190 | hh_alen = HH_DATA_ALIGN(hh->hh_len); | ||
191 | memcpy(skb->data - hh_alen, hh->hh_data, hh_alen); | ||
192 | read_unlock_bh(&hh->hh_lock); | ||
193 | skb_push(skb, hh->hh_len); | ||
194 | return hh->hh_output(skb); | ||
195 | } else if (dst->neighbour) | ||
196 | return dst->neighbour->output(skb); | 188 | return dst->neighbour->output(skb); |
197 | 189 | ||
198 | if (net_ratelimit()) | 190 | if (net_ratelimit()) |
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index e9212c7ff5cf..7b7bd44fbf47 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c | |||
@@ -72,20 +72,11 @@ static __inline__ void ipv6_select_ident(struct sk_buff *skb, struct frag_hdr *f | |||
72 | 72 | ||
73 | static inline int ip6_output_finish(struct sk_buff *skb) | 73 | static inline int ip6_output_finish(struct sk_buff *skb) |
74 | { | 74 | { |
75 | |||
76 | struct dst_entry *dst = skb->dst; | 75 | struct dst_entry *dst = skb->dst; |
77 | struct hh_cache *hh = dst->hh; | 76 | |
78 | 77 | if (dst->hh) | |
79 | if (hh) { | 78 | return neigh_hh_output(dst->hh, skb); |
80 | int hh_alen; | 79 | else if (dst->neighbour) |
81 | |||
82 | read_lock_bh(&hh->hh_lock); | ||
83 | hh_alen = HH_DATA_ALIGN(hh->hh_len); | ||
84 | memcpy(skb->data - hh_alen, hh->hh_data, hh_alen); | ||
85 | read_unlock_bh(&hh->hh_lock); | ||
86 | skb_push(skb, hh->hh_len); | ||
87 | return hh->hh_output(skb); | ||
88 | } else if (dst->neighbour) | ||
89 | return dst->neighbour->output(skb); | 80 | return dst->neighbour->output(skb); |
90 | 81 | ||
91 | IP6_INC_STATS_BH(ip6_dst_idev(dst), IPSTATS_MIB_OUTNOROUTES); | 82 | IP6_INC_STATS_BH(ip6_dst_idev(dst), IPSTATS_MIB_OUTNOROUTES); |
diff --git a/net/sched/sch_cbq.c b/net/sched/sch_cbq.c index ba82dfab6043..f79a4f3d0a95 100644 --- a/net/sched/sch_cbq.c +++ b/net/sched/sch_cbq.c | |||
@@ -371,8 +371,6 @@ static void cbq_deactivate_class(struct cbq_class *this) | |||
371 | return; | 371 | return; |
372 | } | 372 | } |
373 | } | 373 | } |
374 | |||
375 | cl = cl_prev->next_alive; | ||
376 | return; | 374 | return; |
377 | } | 375 | } |
378 | } while ((cl_prev = cl) != q->active[prio]); | 376 | } while ((cl_prev = cl) != q->active[prio]); |
@@ -1258,6 +1256,8 @@ static unsigned int cbq_drop(struct Qdisc* sch) | |||
1258 | do { | 1256 | do { |
1259 | if (cl->q->ops->drop && (len = cl->q->ops->drop(cl->q))) { | 1257 | if (cl->q->ops->drop && (len = cl->q->ops->drop(cl->q))) { |
1260 | sch->q.qlen--; | 1258 | sch->q.qlen--; |
1259 | if (!cl->q->q.qlen) | ||
1260 | cbq_deactivate_class(cl); | ||
1261 | return len; | 1261 | return len; |
1262 | } | 1262 | } |
1263 | } while ((cl = cl->next_alive) != cl_head); | 1263 | } while ((cl = cl->next_alive) != cl_head); |
@@ -1685,8 +1685,7 @@ static int cbq_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new, | |||
1685 | #endif | 1685 | #endif |
1686 | } | 1686 | } |
1687 | sch_tree_lock(sch); | 1687 | sch_tree_lock(sch); |
1688 | *old = cl->q; | 1688 | *old = xchg(&cl->q, new); |
1689 | cl->q = new; | ||
1690 | qdisc_tree_decrease_qlen(*old, (*old)->q.qlen); | 1689 | qdisc_tree_decrease_qlen(*old, (*old)->q.qlen); |
1691 | qdisc_reset(*old); | 1690 | qdisc_reset(*old); |
1692 | sch_tree_unlock(sch); | 1691 | sch_tree_unlock(sch); |
@@ -1704,6 +1703,14 @@ cbq_leaf(struct Qdisc *sch, unsigned long arg) | |||
1704 | return cl ? cl->q : NULL; | 1703 | return cl ? cl->q : NULL; |
1705 | } | 1704 | } |
1706 | 1705 | ||
1706 | static void cbq_qlen_notify(struct Qdisc *sch, unsigned long arg) | ||
1707 | { | ||
1708 | struct cbq_class *cl = (struct cbq_class *)arg; | ||
1709 | |||
1710 | if (cl->q->q.qlen == 0) | ||
1711 | cbq_deactivate_class(cl); | ||
1712 | } | ||
1713 | |||
1707 | static unsigned long cbq_get(struct Qdisc *sch, u32 classid) | 1714 | static unsigned long cbq_get(struct Qdisc *sch, u32 classid) |
1708 | { | 1715 | { |
1709 | struct cbq_sched_data *q = qdisc_priv(sch); | 1716 | struct cbq_sched_data *q = qdisc_priv(sch); |
@@ -1988,12 +1995,17 @@ static int cbq_delete(struct Qdisc *sch, unsigned long arg) | |||
1988 | { | 1995 | { |
1989 | struct cbq_sched_data *q = qdisc_priv(sch); | 1996 | struct cbq_sched_data *q = qdisc_priv(sch); |
1990 | struct cbq_class *cl = (struct cbq_class*)arg; | 1997 | struct cbq_class *cl = (struct cbq_class*)arg; |
1998 | unsigned int qlen; | ||
1991 | 1999 | ||
1992 | if (cl->filters || cl->children || cl == &q->link) | 2000 | if (cl->filters || cl->children || cl == &q->link) |
1993 | return -EBUSY; | 2001 | return -EBUSY; |
1994 | 2002 | ||
1995 | sch_tree_lock(sch); | 2003 | sch_tree_lock(sch); |
1996 | 2004 | ||
2005 | qlen = cl->q->q.qlen; | ||
2006 | qdisc_reset(cl->q); | ||
2007 | qdisc_tree_decrease_qlen(cl->q, qlen); | ||
2008 | |||
1997 | if (cl->next_alive) | 2009 | if (cl->next_alive) |
1998 | cbq_deactivate_class(cl); | 2010 | cbq_deactivate_class(cl); |
1999 | 2011 | ||
@@ -2084,6 +2096,7 @@ static void cbq_walk(struct Qdisc *sch, struct qdisc_walker *arg) | |||
2084 | static struct Qdisc_class_ops cbq_class_ops = { | 2096 | static struct Qdisc_class_ops cbq_class_ops = { |
2085 | .graft = cbq_graft, | 2097 | .graft = cbq_graft, |
2086 | .leaf = cbq_leaf, | 2098 | .leaf = cbq_leaf, |
2099 | .qlen_notify = cbq_qlen_notify, | ||
2087 | .get = cbq_get, | 2100 | .get = cbq_get, |
2088 | .put = cbq_put, | 2101 | .put = cbq_put, |
2089 | .change = cbq_change_class, | 2102 | .change = cbq_change_class, |
diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c index 215e68c2b615..15f23c5511a8 100644 --- a/net/sched/sch_htb.c +++ b/net/sched/sch_htb.c | |||
@@ -147,6 +147,10 @@ struct htb_class { | |||
147 | psched_tdiff_t mbuffer; /* max wait time */ | 147 | psched_tdiff_t mbuffer; /* max wait time */ |
148 | long tokens, ctokens; /* current number of tokens */ | 148 | long tokens, ctokens; /* current number of tokens */ |
149 | psched_time_t t_c; /* checkpoint time */ | 149 | psched_time_t t_c; /* checkpoint time */ |
150 | |||
151 | int prio; /* For parent to leaf return possible here */ | ||
152 | int quantum; /* we do backup. Finally full replacement */ | ||
153 | /* of un.leaf originals should be done. */ | ||
150 | }; | 154 | }; |
151 | 155 | ||
152 | /* TODO: maybe compute rate when size is too large .. or drop ? */ | 156 | /* TODO: maybe compute rate when size is too large .. or drop ? */ |
@@ -1271,6 +1275,38 @@ static void htb_destroy_filters(struct tcf_proto **fl) | |||
1271 | } | 1275 | } |
1272 | } | 1276 | } |
1273 | 1277 | ||
1278 | static inline int htb_parent_last_child(struct htb_class *cl) | ||
1279 | { | ||
1280 | if (!cl->parent) | ||
1281 | /* the root class */ | ||
1282 | return 0; | ||
1283 | |||
1284 | if (!(cl->parent->children.next == &cl->sibling && | ||
1285 | cl->parent->children.prev == &cl->sibling)) | ||
1286 | /* not the last child */ | ||
1287 | return 0; | ||
1288 | |||
1289 | return 1; | ||
1290 | } | ||
1291 | |||
1292 | static void htb_parent_to_leaf(struct htb_class *cl, struct Qdisc *new_q) | ||
1293 | { | ||
1294 | struct htb_class *parent = cl->parent; | ||
1295 | |||
1296 | BUG_TRAP(!cl->level && cl->un.leaf.q && !cl->prio_activity); | ||
1297 | |||
1298 | parent->level = 0; | ||
1299 | memset(&parent->un.inner, 0, sizeof(parent->un.inner)); | ||
1300 | INIT_LIST_HEAD(&parent->un.leaf.drop_list); | ||
1301 | parent->un.leaf.q = new_q ? new_q : &noop_qdisc; | ||
1302 | parent->un.leaf.quantum = parent->quantum; | ||
1303 | parent->un.leaf.prio = parent->prio; | ||
1304 | parent->tokens = parent->buffer; | ||
1305 | parent->ctokens = parent->cbuffer; | ||
1306 | PSCHED_GET_TIME(parent->t_c); | ||
1307 | parent->cmode = HTB_CAN_SEND; | ||
1308 | } | ||
1309 | |||
1274 | static void htb_destroy_class(struct Qdisc *sch, struct htb_class *cl) | 1310 | static void htb_destroy_class(struct Qdisc *sch, struct htb_class *cl) |
1275 | { | 1311 | { |
1276 | struct htb_sched *q = qdisc_priv(sch); | 1312 | struct htb_sched *q = qdisc_priv(sch); |
@@ -1328,6 +1364,8 @@ static int htb_delete(struct Qdisc *sch, unsigned long arg) | |||
1328 | struct htb_sched *q = qdisc_priv(sch); | 1364 | struct htb_sched *q = qdisc_priv(sch); |
1329 | struct htb_class *cl = (struct htb_class *)arg; | 1365 | struct htb_class *cl = (struct htb_class *)arg; |
1330 | unsigned int qlen; | 1366 | unsigned int qlen; |
1367 | struct Qdisc *new_q = NULL; | ||
1368 | int last_child = 0; | ||
1331 | 1369 | ||
1332 | // TODO: why don't allow to delete subtree ? references ? does | 1370 | // TODO: why don't allow to delete subtree ? references ? does |
1333 | // tc subsys quarantee us that in htb_destroy it holds no class | 1371 | // tc subsys quarantee us that in htb_destroy it holds no class |
@@ -1335,6 +1373,12 @@ static int htb_delete(struct Qdisc *sch, unsigned long arg) | |||
1335 | if (!list_empty(&cl->children) || cl->filter_cnt) | 1373 | if (!list_empty(&cl->children) || cl->filter_cnt) |
1336 | return -EBUSY; | 1374 | return -EBUSY; |
1337 | 1375 | ||
1376 | if (!cl->level && htb_parent_last_child(cl)) { | ||
1377 | new_q = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops, | ||
1378 | cl->parent->classid); | ||
1379 | last_child = 1; | ||
1380 | } | ||
1381 | |||
1338 | sch_tree_lock(sch); | 1382 | sch_tree_lock(sch); |
1339 | 1383 | ||
1340 | /* delete from hash and active; remainder in destroy_class */ | 1384 | /* delete from hash and active; remainder in destroy_class */ |
@@ -1349,6 +1393,9 @@ static int htb_delete(struct Qdisc *sch, unsigned long arg) | |||
1349 | if (cl->prio_activity) | 1393 | if (cl->prio_activity) |
1350 | htb_deactivate(q, cl); | 1394 | htb_deactivate(q, cl); |
1351 | 1395 | ||
1396 | if (last_child) | ||
1397 | htb_parent_to_leaf(cl, new_q); | ||
1398 | |||
1352 | if (--cl->refcnt == 0) | 1399 | if (--cl->refcnt == 0) |
1353 | htb_destroy_class(sch, cl); | 1400 | htb_destroy_class(sch, cl); |
1354 | 1401 | ||
@@ -1483,6 +1530,10 @@ static int htb_change_class(struct Qdisc *sch, u32 classid, | |||
1483 | cl->un.leaf.quantum = hopt->quantum; | 1530 | cl->un.leaf.quantum = hopt->quantum; |
1484 | if ((cl->un.leaf.prio = hopt->prio) >= TC_HTB_NUMPRIO) | 1531 | if ((cl->un.leaf.prio = hopt->prio) >= TC_HTB_NUMPRIO) |
1485 | cl->un.leaf.prio = TC_HTB_NUMPRIO - 1; | 1532 | cl->un.leaf.prio = TC_HTB_NUMPRIO - 1; |
1533 | |||
1534 | /* backup for htb_parent_to_leaf */ | ||
1535 | cl->quantum = cl->un.leaf.quantum; | ||
1536 | cl->prio = cl->un.leaf.prio; | ||
1486 | } | 1537 | } |
1487 | 1538 | ||
1488 | cl->buffer = hopt->buffer; | 1539 | cl->buffer = hopt->buffer; |