* Re: [RFT] fib_trie: cleanup
From: David Miller @ 2007-07-26 8:49 UTC (permalink / raw)
To: shemminger; +Cc: bunk, Robert.Olsson, akpm, paulmck, mingo, josh, netdev
In-Reply-To: <20070726094648.3b7301ae@oldman>
From: Stephen Hemminger <shemminger@linux-foundation.org>
Date: Thu, 26 Jul 2007 09:46:48 +0100
> Try this out:
> * replace macro's with inlines
> * get rid of places doing multiple evaluations of NODE_PARENT
No objections from me.
Robert?
^ permalink raw reply
* Re: 2.6.20->2.6.21 - networking dies after random time
From: Jarek Poplawski @ 2007-07-26 8:55 UTC (permalink / raw)
To: Ingo Molnar
Cc: Thomas Gleixner, Marcin ??lusarz, Linus Torvalds,
Jean-Baptiste Vignaud, linux-kernel, shemminger, linux-net,
netdev, Andrew Morton, Alan Cox
In-Reply-To: <20070726083120.GA26910@elte.hu>
On Thu, Jul 26, 2007 at 10:31:20AM +0200, Ingo Molnar wrote:
...
> yeah. The patch below enables sw-resend on x86, to test the theory
> whether the APIC-driven hardware-vector-resend code has some problem.
I think Marcin is using x86_64 (Athlon 64) yet.
Jarek P.
^ permalink raw reply
* [IPVS]: Use skb_forward_csum
From: Herbert Xu @ 2007-07-26 8:59 UTC (permalink / raw)
To: David S. Miller, netdev; +Cc: Simon Horman
Hi Dave:
Found this while looking at 8797. Although it's not clear
that this is the cause yet (it could only happen if a
seemingly remote TCP stream is DNATed to a local address),
we need this patch anyway to avoid clobbering incoming
traffic with CHECKSUM_PARTIAL in its ip_summed field.
[IPVS]: Use skb_forward_csum
As a path that forwards packets, IPVS should be using
skb_forward_csum instead of directly setting ip_summed
to CHECKSUM_NONE.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Cheers,
--
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
--
diff --git a/net/ipv4/ipvs/ip_vs_xmit.c b/net/ipv4/ipvs/ip_vs_xmit.c
index 900ce29..666e080 100644
--- a/net/ipv4/ipvs/ip_vs_xmit.c
+++ b/net/ipv4/ipvs/ip_vs_xmit.c
@@ -128,7 +128,7 @@ ip_vs_dst_reset(struct ip_vs_dest *dest)
#define IP_VS_XMIT(skb, rt) \
do { \
(skb)->ipvs_property = 1; \
- (skb)->ip_summed = CHECKSUM_NONE; \
+ skb_forward_csum(skb); \
NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, (skb), NULL, \
(rt)->u.dst.dev, dst_output); \
} while (0)
^ permalink raw reply related
* Re: [RFT] fib_trie: cleanup
From: Andrew Morton @ 2007-07-26 9:04 UTC (permalink / raw)
To: Stephen Hemminger
Cc: Adrian Bunk, Robert Olsson, Paul E. McKenney, Ingo Molnar,
Josh Triplett, netdev
In-Reply-To: <20070726094648.3b7301ae@oldman>
On Thu, 26 Jul 2007 09:46:48 +0100 Stephen Hemminger <shemminger@linux-foundation.org> wrote:
> Try this out:
> * replace macro's with inlines
> * get rid of places doing multiple evaluations of NODE_PARENT
And it fixes the rcu abuse which resulted in
http://lkml.org/lkml/2007/7/25/319. Which I assume is what inspired the
effort.
your typecasting style is inconsistent:
> + return rcu_dereference((struct tnode *) (node->parent & ~NODE_TYPE_MASK));
space
> + (unsigned long)ptr | NODE_TYPE(node));
no space
> + while (tn != NULL && (tp = node_parent((struct node *)tn)) != NULL) {
no space
> + tp = node_parent((struct node *) tn);
space
> + node_set_parent((struct node *)l, tp);
no space
> + node_set_parent((struct node *)tn, tp);
no space
> + struct tnode *parent = node_parent((struct node *) pn);
space
etc.
"no space" seems to be more usual, by about a 50.1:49.9 ratio. It is
a lot more common in net/:
box:/usr/src/25> grep '[(]unsigned long[)] ' net/*/*.c | wc -l
91
box:/usr/src/25> grep '[(]unsigned long[)][^ ]' net/*/*.c | wc -l
242
^ permalink raw reply
* [0/6] Allow registration/change name notifications to fail
From: Herbert Xu @ 2007-07-26 9:07 UTC (permalink / raw)
To: David S. Miller, netdev; +Cc: Patrick McHardy, Herbert Xu
Hi Dave:
This series of patches adds support to let netdev registration
and change name events to fail. Failures of the former kind
prevents the device from registered while the latter attempts
to roll back the change (which unfortunately can also fail).
If the failure occurs while a netdev is being registered,
then the registration as a whole will fail. If it occurs
when a protocol is being registered, then that protocol
will fail to register instead.
Having this allows us to flag allocations failures in a
meaningful way rather than letting the next action that
requires what is allocated to flag the failure.
In particular, this allows the reporting of failures to
allocate the IPv4/IPv6 device objects.
Cheers,
--
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
^ permalink raw reply
* [PATCH 1/6] [NET]: Call uninit if necessary in register_netdevice
From: Herbert Xu @ 2007-07-26 9:09 UTC (permalink / raw)
To: David S. Miller, netdev, Patrick McHardy, Herbert Xu
In-Reply-To: <20070726090725.GA510@gondor.apana.org.au>
[NET]: Call uninit if necessary in register_netdevice
This patch makes register_netdevice call dev->uninit if the regsitration
fails after dev->init has completed successfully. Very few drivers use
the init/uninit calls but at least one (drivers/net/wan/sealevel.c) may
leak without this change.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
---
net/core/dev.c | 11 ++++++++---
1 files changed, 8 insertions(+), 3 deletions(-)
diff --git a/net/core/dev.c b/net/core/dev.c
index ee40355..a284c9b 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -3333,7 +3333,7 @@ int register_netdevice(struct net_device *dev)
if (!dev_valid_name(dev->name)) {
ret = -EINVAL;
- goto out;
+ goto err_uninit;
}
dev->ifindex = dev_new_index();
@@ -3347,7 +3347,7 @@ int register_netdevice(struct net_device *dev)
= hlist_entry(p, struct net_device, name_hlist);
if (!strncmp(d->name, dev->name, IFNAMSIZ)) {
ret = -EEXIST;
- goto out;
+ goto err_uninit;
}
}
@@ -3407,7 +3407,7 @@ int register_netdevice(struct net_device *dev)
ret = netdev_register_sysfs(dev);
if (ret)
- goto out;
+ goto err_uninit;
dev->reg_state = NETREG_REGISTERED;
/*
@@ -3432,6 +3432,11 @@ int register_netdevice(struct net_device *dev)
out:
return ret;
+
+err_uninit:
+ if (dev->uninit)
+ dev->uninit(dev);
+ goto out;
}
/**
^ permalink raw reply related
* [PATCH 2/6] [NET]: Take dev_base_lock when moving device name hash list entry
From: Herbert Xu @ 2007-07-26 9:09 UTC (permalink / raw)
To: David S. Miller, netdev, Patrick McHardy, Herbert Xu
In-Reply-To: <20070726090725.GA510@gondor.apana.org.au>
[NET]: Take dev_base_lock when moving device name hash list entry
When we added name-based hashing the dev_base_lock was designated as the
lock to take when changing the name hash list. Unfortunately, because
it was a preexisting lock that just happened to be taken in the right
spots we neglected to take it in dev_change_name.
The race can affect calles of __dev_get_by_name that do so without taking
the RTNL. They may end up walking down the wrong hash chain and end up
missing the device that they're looking for.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
---
net/core/dev.c | 4 ++++
1 files changed, 4 insertions(+)
diff --git a/net/core/dev.c b/net/core/dev.c
index a284c9b..0a35c15 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -839,8 +839,12 @@ int dev_change_name(struct net_device *dev, char *newname)
strlcpy(dev->name, newname, IFNAMSIZ);
device_rename(&dev->dev, dev->name);
+
+ write_lock_bh(&dev_base_lock);
hlist_del(&dev->name_hlist);
hlist_add_head(&dev->name_hlist, dev_name_hash(dev->name));
+ write_unlock_bh(&dev_base_lock);
+
raw_notifier_call_chain(&netdev_chain, NETDEV_CHANGENAME, dev);
return err;
^ permalink raw reply related
* [PATCH 3/6] [NET] loopback: Panic if registration fails
From: Herbert Xu @ 2007-07-26 9:09 UTC (permalink / raw)
To: David S. Miller, netdev, Patrick McHardy, Herbert Xu
In-Reply-To: <20070726090725.GA510@gondor.apana.org.au>
[NET] loopback: Panic if registration fails
Because IPv4 and IPv6 both depend on the presence of the loopback device
to function, failure in registration the loopback device should be fatal.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
---
drivers/net/loopback.c | 7 ++++++-
1 files changed, 6 insertions(+), 1 deletion(-)
diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c
index 6ba6ed2..5106c23 100644
--- a/drivers/net/loopback.c
+++ b/drivers/net/loopback.c
@@ -229,7 +229,12 @@ struct net_device loopback_dev = {
/* Setup and register the loopback device. */
static int __init loopback_init(void)
{
- return register_netdev(&loopback_dev);
+ int err = register_netdev(&loopback_dev);
+
+ if (err)
+ panic("loopback: Failed to register netdevice: %d\n", err);
+
+ return err;
};
module_init(loopback_init);
^ permalink raw reply related
* [PATCH 4/6] [NET]: Allow netdev REGISTER/CHANGENAME events to fail
From: Herbert Xu @ 2007-07-26 9:09 UTC (permalink / raw)
To: David S. Miller, netdev, Patrick McHardy, Herbert Xu
In-Reply-To: <20070726090725.GA510@gondor.apana.org.au>
[NET]: Allow netdev REGISTER/CHANGENAME events to fail
This patch adds code to allow errors to be passed up from event
handlers of NETDEV_REGISTER and NETDEV_CHANGENAME. It also adds
the notifier_from_errno/notifier_to_errnor helpers to pass the
errno value up to the notifier caller.
If an error is detected when a device is registered, it causes
that operation to fail. A NETDEV_UNREGISTER will be sent to
all event handlers.
Similarly if NETDEV_CHANGENAME fails the original name is restored
and a new NETDEV_CHANGENAME event is sent.
As such all event handlers must be idempotent with respect to
these events.
When an event handler is registered NETDEV_REGISTER events are
sent for all devices currently registered. Should any of them
fail, we will send NETDEV_GOING_DOWN/NETDEV_DOWN/NETDEV_UNREGISTER
events to that handler for the devices which have already been
registered with it. The handler registration itself will fail.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
---
include/linux/notifier.h | 13 +++++++++
net/core/dev.c | 62 +++++++++++++++++++++++++++++++++++++++--------
2 files changed, 65 insertions(+), 10 deletions(-)
diff --git a/include/linux/notifier.h b/include/linux/notifier.h
index be3f2bb..fad7ff1 100644
--- a/include/linux/notifier.h
+++ b/include/linux/notifier.h
@@ -157,6 +157,19 @@ extern int __srcu_notifier_call_chain(struct srcu_notifier_head *nh,
*/
#define NOTIFY_STOP (NOTIFY_OK|NOTIFY_STOP_MASK)
+/* Encapsulate (negative) errno value (in particular, NOTIFY_BAD <=> EPERM). */
+static inline int notifier_from_errno(int err)
+{
+ return NOTIFY_STOP_MASK | (NOTIFY_OK - err);
+}
+
+/* Restore (negative) errno value from notify return value. */
+static inline int notifier_to_errno(int ret)
+{
+ ret &= ~NOTIFY_STOP_MASK;
+ return ret > NOTIFY_OK ? NOTIFY_OK - ret : 0;
+}
+
/*
* Declared notifiers so far. I can imagine quite a few more chains
* over time (eg laptop power reset chains, reboot chain (to clean
diff --git a/net/core/dev.c b/net/core/dev.c
index 0a35c15..d94b178 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -817,7 +817,9 @@ int dev_alloc_name(struct net_device *dev, const char *name)
*/
int dev_change_name(struct net_device *dev, char *newname)
{
+ char oldname[IFNAMSIZ];
int err = 0;
+ int ret;
ASSERT_RTNL();
@@ -827,6 +829,8 @@ int dev_change_name(struct net_device *dev, char *newname)
if (!dev_valid_name(newname))
return -EINVAL;
+ memcpy(oldname, dev->name, IFNAMSIZ);
+
if (strchr(newname, '%')) {
err = dev_alloc_name(dev, newname);
if (err < 0)
@@ -838,6 +842,7 @@ int dev_change_name(struct net_device *dev, char *newname)
else
strlcpy(dev->name, newname, IFNAMSIZ);
+rollback:
device_rename(&dev->dev, dev->name);
write_lock_bh(&dev_base_lock);
@@ -845,7 +850,20 @@ int dev_change_name(struct net_device *dev, char *newname)
hlist_add_head(&dev->name_hlist, dev_name_hash(dev->name));
write_unlock_bh(&dev_base_lock);
- raw_notifier_call_chain(&netdev_chain, NETDEV_CHANGENAME, dev);
+ ret = raw_notifier_call_chain(&netdev_chain, NETDEV_CHANGENAME, dev);
+ ret = notifier_to_errno(ret);
+
+ if (ret) {
+ if (err) {
+ printk(KERN_ERR
+ "%s: name change rollback failed: %d.\n",
+ dev->name, ret);
+ } else {
+ err = ret;
+ memcpy(dev->name, oldname, IFNAMSIZ);
+ goto rollback;
+ }
+ }
return err;
}
@@ -1058,20 +1076,43 @@ int dev_close(struct net_device *dev)
int register_netdevice_notifier(struct notifier_block *nb)
{
struct net_device *dev;
+ struct net_device *last;
int err;
rtnl_lock();
err = raw_notifier_chain_register(&netdev_chain, nb);
- if (!err) {
- for_each_netdev(dev) {
- nb->notifier_call(nb, NETDEV_REGISTER, dev);
+ if (err)
+ goto unlock;
- if (dev->flags & IFF_UP)
- nb->notifier_call(nb, NETDEV_UP, dev);
- }
+ for_each_netdev(dev) {
+ err = nb->notifier_call(nb, NETDEV_REGISTER, dev);
+ err = notifier_to_errno(err);
+ if (err)
+ goto rollback;
+
+ if (!(dev->flags & IFF_UP))
+ continue;
+
+ nb->notifier_call(nb, NETDEV_UP, dev);
}
+
+unlock:
rtnl_unlock();
return err;
+
+rollback:
+ last = dev;
+ for_each_netdev(dev) {
+ if (dev == last)
+ break;
+
+ if (dev->flags & IFF_UP) {
+ nb->notifier_call(nb, NETDEV_GOING_DOWN, dev);
+ nb->notifier_call(nb, NETDEV_DOWN, dev);
+ }
+ nb->notifier_call(nb, NETDEV_UNREGISTER, dev);
+ }
+ goto unlock;
}
/**
@@ -3430,9 +3471,10 @@ int register_netdevice(struct net_device *dev)
write_unlock_bh(&dev_base_lock);
/* Notify protocols, that a new device appeared. */
- raw_notifier_call_chain(&netdev_chain, NETDEV_REGISTER, dev);
-
- ret = 0;
+ ret = raw_notifier_call_chain(&netdev_chain, NETDEV_REGISTER, dev);
+ ret = notifier_to_errno(ret);
+ if (ret)
+ unregister_netdevice(dev);
out:
return ret;
^ permalink raw reply related
* [PATCH 5/6] [IPV4/IPV6]: Fail registration if inet device construction fails
From: Herbert Xu @ 2007-07-26 9:09 UTC (permalink / raw)
To: David S. Miller, netdev, Patrick McHardy, Herbert Xu
In-Reply-To: <20070726090725.GA510@gondor.apana.org.au>
[IPV4/IPV6]: Fail registration if inet device construction fails
Now that netdev notifications can fail, we can use this to signal
errors during registration for IPv4/IPv6. In particular, if we
fail to allocate memory for the inet device, we can fail the netdev
registration.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
---
net/ipv4/devinet.c | 5 ++---
net/ipv6/addrconf.c | 8 +++++---
2 files changed, 7 insertions(+), 6 deletions(-)
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index abf6352..5b77bda 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -1056,10 +1056,9 @@ static int inetdev_event(struct notifier_block *this, unsigned long event,
if (!in_dev) {
if (event == NETDEV_REGISTER) {
in_dev = inetdev_init(dev);
+ if (!in_dev)
+ return notifier_from_errno(-ENOMEM);
if (dev == &loopback_dev) {
- if (!in_dev)
- panic("devinet: "
- "Failed to create loopback\n");
IN_DEV_CONF_SET(in_dev, NOXFRM, 1);
IN_DEV_CONF_SET(in_dev, NOPOLICY, 1);
}
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 0601292..91ef3be 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -2256,14 +2256,14 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event,
struct net_device *dev = (struct net_device *) data;
struct inet6_dev *idev = __in6_dev_get(dev);
int run_pending = 0;
+ int err;
switch(event) {
case NETDEV_REGISTER:
if (!idev && dev->mtu >= IPV6_MIN_MTU) {
idev = ipv6_add_dev(dev);
if (!idev)
- printk(KERN_WARNING "IPv6: add_dev failed for %s\n",
- dev->name);
+ return notifier_from_errno(-ENOMEM);
}
break;
case NETDEV_UP:
@@ -2373,7 +2373,9 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event,
NULL);
addrconf_sysctl_register(idev, &idev->cnf);
#endif
- snmp6_register_dev(idev);
+ err = snmp6_register_dev(idev);
+ if (err)
+ return notifier_from_errno(err);
}
break;
}
^ permalink raw reply related
* [PATCH 6/6] [IPV6]: Remove circular dependency on if_inet6.h
From: Herbert Xu @ 2007-07-26 9:09 UTC (permalink / raw)
To: David S. Miller, netdev, Patrick McHardy, Herbert Xu
In-Reply-To: <20070726090725.GA510@gondor.apana.org.au>
[IPV6]: Remove circular dependency on if_inet6.h
net/if_inet6.h includes linux/ipv6.h which also tries to include
net/if_inet6.h. Since the latter only needs it for forward
declarations, we can fix this by adding the declarations.
A number of files are implicitly including net/if_inet6.h through
linux/ipv6.h. They also use net/ipv6.h so this patch includes
net/if_inet6.h there.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
---
include/linux/ipv6.h | 5 ++++-
include/net/ipv6.h | 1 +
2 files changed, 5 insertions(+), 1 deletion(-)
diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h
index 97983dc..4ca60c3 100644
--- a/include/linux/ipv6.h
+++ b/include/linux/ipv6.h
@@ -219,7 +219,6 @@ enum {
#include <linux/tcp.h>
#include <linux/udp.h>
-#include <net/if_inet6.h> /* struct ipv6_mc_socklist */
#include <net/inet_sock.h>
static inline struct ipv6hdr *ipv6_hdr(const struct sk_buff *skb)
@@ -273,6 +272,10 @@ struct tcp6_request_sock {
struct inet6_request_sock tcp6rsk_inet6;
};
+struct ipv6_mc_socklist;
+struct ipv6_ac_socklist;
+struct ipv6_fl_socklist;
+
/**
* struct ipv6_pinfo - ipv6 private area
*
diff --git a/include/net/ipv6.h b/include/net/ipv6.h
index 46b9dce..9059e0e 100644
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -17,6 +17,7 @@
#include <linux/ipv6.h>
#include <linux/hardirq.h>
+#include <net/if_inet6.h>
#include <net/ndisc.h>
#include <net/flow.h>
#include <net/snmp.h>
^ permalink raw reply related
* Re: 2.6.20->2.6.21 - networking dies after random time
From: Jarek Poplawski @ 2007-07-26 9:11 UTC (permalink / raw)
To: Thomas Gleixner
Cc: Marcin Ślusarz, Ingo Molnar, Linus Torvalds,
Jean-Baptiste Vignaud, linux-kernel, shemminger, linux-net,
netdev, Andrew Morton, Alan Cox
In-Reply-To: <1185437431.3227.21.camel@chaos>
On Thu, Jul 26, 2007 at 10:10:31AM +0200, Thomas Gleixner wrote:
> On Thu, 2007-07-26 at 10:13 +0200, Jarek Poplawski wrote:
...
> > PS: Now, it seems to me Thomas could be the nearest. BTW, could somebody
> > give me some tip, how these re-triggered interrupts are skipped on dev's
> > reset before enable_irq?
>
> I think the correct solution is really not to resend level type
> interrupts. If the interrupt line is still active, then the interrupt
> comes up by itself. I'm cooking a patch for that.
>
> The other question is:
>
> Is the driver confused by the resent irq or is the chip-set unhappy
> about the resend ?
>
> We could figure the latter out by activating the software based resend
> method.
Probably I miss something, but isn't there any problem with level type,
when APIC re-triggers an interrupt, which is not acked by driver nor
card (after some hw reset/clear)?
Jarek P.
^ permalink raw reply
* Re: 2.6.20->2.6.21 - networking dies after random time
From: Ingo Molnar @ 2007-07-26 9:12 UTC (permalink / raw)
To: Jarek Poplawski
Cc: Thomas Gleixner, Marcin ??lusarz, Linus Torvalds,
Jean-Baptiste Vignaud, linux-kernel, shemminger, linux-net,
netdev, Andrew Morton, Alan Cox
In-Reply-To: <20070726085523.GA3423@ff.dom.local>
* Jarek Poplawski <jarkao2@o2.pl> wrote:
> On Thu, Jul 26, 2007 at 10:31:20AM +0200, Ingo Molnar wrote:
> ...
> > yeah. The patch below enables sw-resend on x86, to test the theory
> > whether the APIC-driven hardware-vector-resend code has some problem.
>
> I think Marcin is using x86_64 (Athlon 64) yet.
yeah - i meant to cover both arches but forgot about x86_64 - updated
patch attached below.
Ingo
----------------->
Subject: x86: activate HARDIRQS_SW_RESEND
From: Ingo Molnar <mingo@elte.hu>
activate the software-triggered IRQ-resend logic.
it appears some chipsets/cpus do not handle local-APIC driven IRQ
resends all that well, so always use the soft mechanism to trigger
the execution of pending interrupts.
Signed-off-by: Ingo Molnar <mingo@elte.hu>
---
arch/i386/Kconfig | 4 ++++
arch/x86_64/Kconfig | 4 ++++
kernel/irq/manage.c | 8 ++++++++
3 files changed, 16 insertions(+)
Index: linux-rt-rebase.q/arch/i386/Kconfig
===================================================================
--- linux-rt-rebase.q.orig/arch/i386/Kconfig
+++ linux-rt-rebase.q/arch/i386/Kconfig
@@ -1284,6 +1284,10 @@ config GENERIC_PENDING_IRQ
depends on GENERIC_HARDIRQS && SMP
default y
+config HARDIRQS_SW_RESEND
+ bool
+ default y
+
config X86_SMP
bool
depends on SMP && !X86_VOYAGER
Index: linux-rt-rebase.q/arch/x86_64/Kconfig
===================================================================
--- linux-rt-rebase.q.orig/arch/x86_64/Kconfig
+++ linux-rt-rebase.q/arch/x86_64/Kconfig
@@ -721,6 +721,10 @@ config GENERIC_PENDING_IRQ
depends on GENERIC_HARDIRQS && SMP
default y
+config HARDIRQS_SW_RESEND
+ bool
+ default y
+
menu "Power management options"
source kernel/power/Kconfig
Index: linux-rt-rebase.q/kernel/irq/manage.c
===================================================================
--- linux-rt-rebase.q.orig/kernel/irq/manage.c
+++ linux-rt-rebase.q/kernel/irq/manage.c
@@ -175,6 +175,14 @@ void enable_irq(unsigned int irq)
desc->depth--;
}
spin_unlock_irqrestore(&desc->lock, flags);
+#ifdef CONFIG_HARDIRQS_SW_RESEND
+ /*
+ * Do a bh disable/enable pair to trigger any pending
+ * irq resend logic:
+ */
+ local_bh_disable();
+ local_bh_enable();
+#endif
}
EXPORT_SYMBOL(enable_irq);
^ permalink raw reply
* Re: [RFT] fib_trie: cleanup
From: Stephen Hemminger @ 2007-07-26 9:15 UTC (permalink / raw)
To: Andrew Morton
Cc: Adrian Bunk, Robert Olsson, Paul E. McKenney, Ingo Molnar,
Josh Triplett, netdev
In-Reply-To: <20070726020431.1e693866.akpm@linux-foundation.org>
On Thu, 26 Jul 2007 02:04:31 -0700
Andrew Morton <akpm@linux-foundation.org> wrote:
> On Thu, 26 Jul 2007 09:46:48 +0100 Stephen Hemminger <shemminger@linux-foundation.org> wrote:
>
> > Try this out:
> > * replace macro's with inlines
> > * get rid of places doing multiple evaluations of NODE_PARENT
>
> And it fixes the rcu abuse which resulted in
> http://lkml.org/lkml/2007/7/25/319. Which I assume is what inspired the
> effort.
>
>
> your typecasting style is inconsistent:
>
> > + return rcu_dereference((struct tnode *) (node->parent & ~NODE_TYPE_MASK));
>
> space
I have a couple of followon cleanup patches, one of them is whitespace demunging
^ permalink raw reply
* Re: [DRIVER SUBMISSION] DRBD wants to go mainline
From: Evgeniy Polyakov @ 2007-07-26 9:17 UTC (permalink / raw)
To: Kyle Moffett
Cc: david, Satyam Sharma, Lars Ellenberg, Jens Axboe, Andrew Morton,
LKML Kernel, netdev
In-Reply-To: <B3CFC70C-ADBC-406A-A2C8-908530FED007@mac.com>
Hi Kyle.
On Wed, Jul 25, 2007 at 11:43:38PM -0400, Kyle Moffett (mrlinuxman@mac.com) wrote:
> If you made all your sockets and inter-thread pipes nonblocking then
> in userspace you would just epoll_wait() on the sockets and pipes and
> be easily able to react to any IO from anywhere.
>
> In kernel space there are similar nonblocking interfaces, although it
> would probably be easier just to use a couple threads.
There are no such interfaces in kernel - one must create own state
machine on top of ->poll() callback, or use sys_poll()/epoll, but likely
it is not what one wants for high-performance in-kernel event processing
engine. Having two threads does not solve the problem - eventually one
needs to send a header before receiving data. So, the solution would
either to use always-blocking mode like in NBD, or create own state
machine using ->poll() callbacks.
> Cheers,
> Kyle Moffett
--
Evgeniy Polyakov
^ permalink raw reply
* inconsistency in dev->hard_header() arguments?
From: kalash nainwal @ 2007-07-26 9:55 UTC (permalink / raw)
To: netdev; +Cc: linux-kernel
The function is called like this- dev->hard_header(skb, dev, ptype,
dest_hw, src_hw, skb->len); where "skb->protocol" is same as "ptype",
but the former is expected to be in network byte order before calling
hard_header, while latter in host byte order (eth_header internally
does its own conversion of ptype). Is this deliberate? or a bug?
We've a driver, which sends pkt over ethernet. Here's the sample send routine-
my_eth_send(struct sk_buff * mp, struct net_device *dev, int linkno)
{
<snip>
mp->protocol = link->ln_sap;
mp->nh.raw = mp->data;
dev->hard_header(mp, mp->dev, ntohs(link->ln_sap),
dest_node->n_linkinfo[linkno].n_addr,
src_node->n_linkinfo[linkno].n_addr,
mp->len);
dev_queue_xmit(mp);
}
We store the type field (i.e., link->ln_sap) in our driver in network
byte order only (as skb->protocol is expected to be in network byte
order), but as eth_header internally does the conversion again, we've
to un-convert it (for every outgoing pkt!!) unnecessarily. We can get
away with this by using two different variables for ptype- one in n/w
order, other in host order; but unless there's some hidden magic
behind the current behavior, I'd like to send a patch to fix this in
kernel. Or if you think it would touch too many files, might break too
many things...we can let it be.
Regards,
-Kalash
^ permalink raw reply
* Re: [0/6] Allow registration/change name notifications to fail
From: Stephen Hemminger @ 2007-07-26 10:37 UTC (permalink / raw)
To: Herbert Xu; +Cc: David S. Miller, netdev, Patrick McHardy, Herbert Xu
In-Reply-To: <20070726090725.GA510@gondor.apana.org.au>
On Thu, 26 Jul 2007 17:07:25 +0800
Herbert Xu <herbert@gondor.apana.org.au> wrote:
> Hi Dave:
>
> This series of patches adds support to let netdev registration
> and change name events to fail. Failures of the former kind
> prevents the device from registered while the latter attempts
> to roll back the change (which unfortunately can also fail).
>
> If the failure occurs while a netdev is being registered,
> then the registration as a whole will fail. If it occurs
> when a protocol is being registered, then that protocol
> will fail to register instead.
>
> Having this allows us to flag allocations failures in a
> meaningful way rather than letting the next action that
> requires what is allocated to flag the failure.
>
> In particular, this allows the reporting of failures to
> allocate the IPv4/IPv6 device objects.
>
> Cheers,
Thanks for looking at this, are there bugs this fixes so it should
go to stable?
^ permalink raw reply
* [RFT] fib_trie: macro cleanup
From: Stephen Hemminger @ 2007-07-26 10:43 UTC (permalink / raw)
To: David S. Miller
Cc: Adrian Bunk, Robert Olsson, Andrew Morton, Paul E. McKenney,
Ingo Molnar, Josh Triplett, netdev
In-Reply-To: <20070726094648.3b7301ae@oldman>
This patch converts the messy macro for MASK_PFX to inline function
and expands TKEY_GET_MASK in the one place it is used.
--- a/net/ipv4/fib_trie.c 2007-07-26 09:26:19.000000000 +0100
+++ b/net/ipv4/fib_trie.c 2007-07-26 10:17:21.000000000 +0100
@@ -85,8 +85,6 @@
#define MAX_STAT_DEPTH 32
#define KEYLENGTH (8*sizeof(t_key))
-#define MASK_PFX(k, l) (((l)==0)?0:(k >> (KEYLENGTH-l)) << (KEYLENGTH-l))
-#define TKEY_GET_MASK(offset, bits) (((bits)==0)?0:((t_key)(-1) << (KEYLENGTH - bits) >> offset))
typedef unsigned int t_key;
@@ -192,6 +190,11 @@ static inline int tnode_child_length(con
return 1 << tn->bits;
}
+static inline t_key mask_pfx(t_key k, unsigned short l)
+{
+ return (l == 0) ? 0 : k >> (KEYLENGTH-l) << (KEYLENGTH-l);
+}
+
static inline t_key tkey_extract_bits(t_key a, int offset, int bits)
{
if (offset < KEYLENGTH)
@@ -676,7 +679,7 @@ static struct tnode *inflate(struct trie
inode->pos == oldtnode->pos + oldtnode->bits &&
inode->bits > 1) {
struct tnode *left, *right;
- t_key m = TKEY_GET_MASK(inode->pos, 1);
+ t_key m = ~0U << (KEYLENGTH - 1) >> inode->pos;
left = tnode_new(inode->key&(~m), inode->pos + 1,
inode->bits - 1);
@@ -1364,7 +1367,8 @@ fn_trie_lookup(struct fib_table *tb, con
bits = pn->bits;
if (!chopped_off)
- cindex = tkey_extract_bits(MASK_PFX(key, current_prefix_length), pos, bits);
+ cindex = tkey_extract_bits(mask_pfx(key, current_prefix_length),
+ pos, bits);
n = tnode_get_child(pn, cindex);
@@ -1450,8 +1454,8 @@ fn_trie_lookup(struct fib_table *tb, con
* to find a matching prefix.
*/
- node_prefix = MASK_PFX(cn->key, cn->pos);
- key_prefix = MASK_PFX(key, cn->pos);
+ node_prefix = mask_pfx(cn->key, cn->pos);
+ key_prefix = mask_pfx(key, cn->pos);
pref_mismatch = key_prefix^node_prefix;
mp = 0;
@@ -2327,7 +2331,7 @@ static int fib_trie_seq_show(struct seq_
if (IS_TNODE(n)) {
struct tnode *tn = (struct tnode *) n;
- __be32 prf = htonl(MASK_PFX(tn->key, tn->pos));
+ __be32 prf = htonl(mask_pfx(tn->key, tn->pos));
seq_indent(seq, iter->depth-1);
seq_printf(seq, " +-- %d.%d.%d.%d/%d %d %d %d\n",
^ permalink raw reply
* [RFC] fib_trie: whitespace cleanup
From: Stephen Hemminger @ 2007-07-26 10:49 UTC (permalink / raw)
To: Andrew Morton
Cc: Adrian Bunk, Robert Olsson, Paul E. McKenney, Ingo Molnar,
Josh Triplett, netdev
In-Reply-To: <20070726020431.1e693866.akpm@linux-foundation.org>
Whitespace cleanup run code through lindent then cleanup results.
Applys after other two patches.
--- a/net/ipv4/fib_trie.c 2007-07-26 10:17:21.000000000 +0100
+++ b/net/ipv4/fib_trie.c 2007-07-26 11:47:52.000000000 +0100
@@ -156,7 +156,8 @@ struct trie {
};
static void put_child(struct trie *t, struct tnode *tn, int i, struct node *n);
-static void tnode_put_child_reorg(struct tnode *tn, int i, struct node *n, int wasfull);
+static void tnode_put_child_reorg(struct tnode *tn, int i, struct node *n,
+ int wasfull);
static struct node *resize(struct trie *t, struct tnode *tn);
static struct tnode *inflate(struct trie *t, struct tnode *tn);
static struct tnode *halve(struct trie *t, struct tnode *tn);
@@ -167,13 +168,12 @@ static struct trie *trie_local = NULL, *
static inline struct tnode *node_parent(struct node *node)
{
- return rcu_dereference((struct tnode *) (node->parent & ~NODE_TYPE_MASK));
+ return rcu_dereference((struct tnode *)(node->parent & ~NODE_TYPE_MASK));
}
static inline void node_set_parent(struct node *node, struct tnode *ptr)
{
- rcu_assign_pointer(node->parent,
- (unsigned long)ptr | NODE_TYPE(node));
+ rcu_assign_pointer(node->parent, (unsigned long)ptr | NODE_TYPE(node));
}
/* rcu_read_lock needs to be hold by caller from readside */
@@ -192,13 +192,13 @@ static inline int tnode_child_length(con
static inline t_key mask_pfx(t_key k, unsigned short l)
{
- return (l == 0) ? 0 : k >> (KEYLENGTH-l) << (KEYLENGTH-l);
+ return (l == 0) ? 0 : k >> (KEYLENGTH - l) << (KEYLENGTH - l);
}
static inline t_key tkey_extract_bits(t_key a, int offset, int bits)
{
if (offset < KEYLENGTH)
- return ((t_key)(a << offset)) >> (KEYLENGTH - bits);
+ return ((t_key) (a << offset)) >> (KEYLENGTH - bits);
else
return 0;
}
@@ -223,7 +223,7 @@ static inline int tkey_mismatch(t_key a,
if (!diff)
return 0;
- while ((diff << i) >> (KEYLENGTH-1) == 0)
+ while ((diff << i) >> (KEYLENGTH - 1) == 0)
i++;
return i;
}
@@ -285,7 +285,6 @@ static inline int tkey_mismatch(t_key a,
The bits from (n->pos) to (n->pos + n->bits - 1) - "C" - are the index into
n's child array, and will of course be different for each child.
-
The rest of the bits, from (n->pos + n->bits) onward, are completely unknown
at this point.
@@ -293,7 +292,7 @@ static inline int tkey_mismatch(t_key a,
static inline void check_tnode(const struct tnode *tn)
{
- WARN_ON(tn && tn->pos+tn->bits > 32);
+ WARN_ON(tn && tn->pos + tn->bits > 32);
}
static int halve_threshold = 25;
@@ -301,7 +300,6 @@ static int inflate_threshold = 50;
static int halve_threshold_root = 8;
static int inflate_threshold_root = 15;
-
static void __alias_free_mem(struct rcu_head *head)
{
struct fib_alias *fa = container_of(head, struct fib_alias, rcu);
@@ -335,7 +333,7 @@ static struct tnode *tnode_alloc(unsigne
if (size <= PAGE_SIZE)
return kcalloc(size, 1, GFP_KERNEL);
- pages = alloc_pages(GFP_KERNEL|__GFP_ZERO, get_order(size));
+ pages = alloc_pages(GFP_KERNEL | __GFP_ZERO, get_order(size));
if (!pages)
return NULL;
@@ -346,7 +344,7 @@ static void __tnode_free_rcu(struct rcu_
{
struct tnode *tn = container_of(head, struct tnode, rcu);
unsigned int size = sizeof(struct tnode) +
- (1 << tn->bits) * sizeof(struct node *);
+ (1 << tn->bits) * sizeof(struct node *);
if (size <= PAGE_SIZE)
kfree(tn);
@@ -357,7 +355,7 @@ static void __tnode_free_rcu(struct rcu_
static inline void tnode_free(struct tnode *tn)
{
if (IS_LEAF(tn)) {
- struct leaf *l = (struct leaf *) tn;
+ struct leaf *l = (struct leaf *)tn;
call_rcu_bh(&l->rcu, __leaf_free_rcu);
} else
call_rcu(&tn->rcu, __tnode_free_rcu);
@@ -365,7 +363,7 @@ static inline void tnode_free(struct tno
static struct leaf *leaf_new(void)
{
- struct leaf *l = kmalloc(sizeof(struct leaf), GFP_KERNEL);
+ struct leaf *l = kmalloc(sizeof(struct leaf), GFP_KERNEL);
if (l) {
l->parent = T_LEAF;
INIT_HLIST_HEAD(&l->list);
@@ -375,7 +373,7 @@ static struct leaf *leaf_new(void)
static struct leaf_info *leaf_info_new(int plen)
{
- struct leaf_info *li = kmalloc(sizeof(struct leaf_info), GFP_KERNEL);
+ struct leaf_info *li = kmalloc(sizeof(struct leaf_info), GFP_KERNEL);
if (li) {
li->plen = plen;
INIT_LIST_HEAD(&li->falh);
@@ -383,9 +381,9 @@ static struct leaf_info *leaf_info_new(i
return li;
}
-static struct tnode* tnode_new(t_key key, int pos, int bits)
+static struct tnode *tnode_new(t_key key, int pos, int bits)
{
- int nchildren = 1<<bits;
+ int nchildren = 1 << bits;
int sz = sizeof(struct tnode) + nchildren * sizeof(struct node *);
struct tnode *tn = tnode_alloc(sz);
@@ -396,11 +394,11 @@ static struct tnode* tnode_new(t_key key
tn->bits = bits;
tn->key = key;
tn->full_children = 0;
- tn->empty_children = 1<<bits;
+ tn->empty_children = 1 << bits;
}
- pr_debug("AT %p s=%u %u\n", tn, (unsigned int) sizeof(struct tnode),
- (unsigned int) (sizeof(struct node) * 1<<bits));
+ pr_debug("AT %p s=%u %u\n", tn, (unsigned int)sizeof(struct tnode),
+ (unsigned int)(sizeof(struct node) * 1 << bits));
return tn;
}
@@ -414,10 +412,11 @@ static inline int tnode_full(const struc
if (n == NULL || IS_LEAF(n))
return 0;
- return ((struct tnode *) n)->pos == tn->pos + tn->bits;
+ return ((struct tnode *)n)->pos == tn->pos + tn->bits;
}
-static inline void put_child(struct trie *t, struct tnode *tn, int i, struct node *n)
+static inline void put_child(struct trie *t, struct tnode *tn, int i,
+ struct node *n)
{
tnode_put_child_reorg(tn, i, n, -1);
}
@@ -427,13 +426,13 @@ static inline void put_child(struct trie
* Update the value of full_children and empty_children.
*/
-static void tnode_put_child_reorg(struct tnode *tn, int i, struct node *n, int wasfull)
+static void tnode_put_child_reorg(struct tnode *tn, int i, struct node *n,
+ int wasfull)
{
struct node *chi = tn->child[i];
int isfull;
- BUG_ON(i >= 1<<tn->bits);
-
+ BUG_ON(i >= 1 << tn->bits);
/* update emptyChildren */
if (n == NULL && chi != NULL)
@@ -566,9 +565,10 @@ static struct node *resize(struct trie *
err = 0;
max_resize = 10;
- while ((tn->full_children > 0 && max_resize-- &&
- 50 * (tn->full_children + tnode_child_length(tn) - tn->empty_children) >=
- inflate_threshold_use * tnode_child_length(tn))) {
+ while ((tn->full_children > 0 && max_resize-- &&
+ 50 * (tn->full_children + tnode_child_length(tn) -
+ tn->empty_children) >=
+ inflate_threshold_use * tnode_child_length(tn))) {
old_tn = tn;
tn = inflate(t, tn);
@@ -583,10 +583,12 @@ static struct node *resize(struct trie *
if (max_resize < 0) {
if (!tn->parent)
- printk(KERN_WARNING "Fix inflate_threshold_root. Now=%d size=%d bits\n",
+ printk(KERN_WARNING
+ "Fix inflate_threshold_root. Now=%d size=%d bits\n",
inflate_threshold_root, tn->bits);
else
- printk(KERN_WARNING "Fix inflate_threshold. Now=%d size=%d bits\n",
+ printk(KERN_WARNING
+ "Fix inflate_threshold. Now=%d size=%d bits\n",
inflate_threshold, tn->bits);
}
@@ -597,7 +599,6 @@ static struct node *resize(struct trie *
* node is above threshold.
*/
-
/* Keep root node larger */
if (!tn->parent)
@@ -607,7 +608,7 @@ static struct node *resize(struct trie *
err = 0;
max_resize = 10;
- while (tn->bits > 1 && max_resize-- &&
+ while (tn->bits > 1 && max_resize-- &&
100 * (tnode_child_length(tn) - tn->empty_children) <
halve_threshold_use * tnode_child_length(tn)) {
@@ -624,10 +625,12 @@ static struct node *resize(struct trie *
if (max_resize < 0) {
if (!tn->parent)
- printk(KERN_WARNING "Fix halve_threshold_root. Now=%d size=%d bits\n",
+ printk(KERN_WARNING
+ "Fix halve_threshold_root. Now=%d size=%d bits\n",
halve_threshold_root, tn->bits);
else
- printk(KERN_WARNING "Fix halve_threshold. Now=%d size=%d bits\n",
+ printk(KERN_WARNING
+ "Fix halve_threshold. Now=%d size=%d bits\n",
halve_threshold, tn->bits);
}
@@ -647,7 +650,7 @@ static struct node *resize(struct trie *
return n;
}
- return (struct node *) tn;
+ return (struct node *)tn;
}
static struct tnode *inflate(struct trie *t, struct tnode *tn)
@@ -672,7 +675,8 @@ static struct tnode *inflate(struct trie
*/
for (i = 0; i < olen; i++) {
- struct tnode *inode = (struct tnode *) tnode_get_child(oldtnode, i);
+ struct tnode *inode =
+ (struct tnode *)tnode_get_child(oldtnode, i);
if (inode &&
IS_TNODE(inode) &&
@@ -681,12 +685,12 @@ static struct tnode *inflate(struct trie
struct tnode *left, *right;
t_key m = ~0U << (KEYLENGTH - 1) >> inode->pos;
- left = tnode_new(inode->key&(~m), inode->pos + 1,
+ left = tnode_new(inode->key & (~m), inode->pos + 1,
inode->bits - 1);
if (!left)
goto nomem;
- right = tnode_new(inode->key|m, inode->pos + 1,
+ right = tnode_new(inode->key | m, inode->pos + 1,
inode->bits - 1);
if (!right) {
@@ -694,8 +698,8 @@ static struct tnode *inflate(struct trie
goto nomem;
}
- put_child(t, tn, 2*i, (struct node *) left);
- put_child(t, tn, 2*i+1, (struct node *) right);
+ put_child(t, tn, 2 * i, (struct node *)left);
+ put_child(t, tn, 2 * i + 1, (struct node *)right);
}
}
@@ -710,22 +714,22 @@ static struct tnode *inflate(struct trie
/* A leaf or an internal node with skipped bits */
- if (IS_LEAF(node) || ((struct tnode *) node)->pos >
- tn->pos + tn->bits - 1) {
- if (tkey_extract_bits(node->key, oldtnode->pos + oldtnode->bits,
- 1) == 0)
- put_child(t, tn, 2*i, node);
+ if (IS_LEAF(node) || ((struct tnode *)node)->pos >
+ tn->pos + tn->bits - 1) {
+ if (!tkey_extract_bits(node->key,
+ oldtnode->pos + oldtnode->bits, 1))
+ put_child(t, tn, 2 * i, node);
else
- put_child(t, tn, 2*i+1, node);
+ put_child(t, tn, 2 * i + 1, node);
continue;
}
/* An internal node with two children */
- inode = (struct tnode *) node;
+ inode = (struct tnode *)node;
if (inode->bits == 1) {
- put_child(t, tn, 2*i, inode->child[0]);
- put_child(t, tn, 2*i+1, inode->child[1]);
+ put_child(t, tn, 2 * i, inode->child[0]);
+ put_child(t, tn, 2 * i + 1, inode->child[1]);
tnode_free(inode);
continue;
@@ -754,13 +758,13 @@ static struct tnode *inflate(struct trie
* bit to zero.
*/
- left = (struct tnode *) tnode_get_child(tn, 2*i);
- put_child(t, tn, 2*i, NULL);
+ left = (struct tnode *)tnode_get_child(tn, 2 * i);
+ put_child(t, tn, 2 * i, NULL);
BUG_ON(!left);
- right = (struct tnode *) tnode_get_child(tn, 2*i+1);
- put_child(t, tn, 2*i+1, NULL);
+ right = (struct tnode *)tnode_get_child(tn, 2 * i + 1);
+ put_child(t, tn, 2 * i + 1, NULL);
BUG_ON(!right);
@@ -769,8 +773,8 @@ static struct tnode *inflate(struct trie
put_child(t, left, j, inode->child[j]);
put_child(t, right, j, inode->child[j + size]);
}
- put_child(t, tn, 2*i, resize(t, left));
- put_child(t, tn, 2*i+1, resize(t, right));
+ put_child(t, tn, 2 * i, resize(t, left));
+ put_child(t, tn, 2 * i + 1, resize(t, right));
tnode_free(inode);
}
@@ -814,7 +818,7 @@ static struct tnode *halve(struct trie *
for (i = 0; i < olen; i += 2) {
left = tnode_get_child(oldtnode, i);
- right = tnode_get_child(oldtnode, i+1);
+ right = tnode_get_child(oldtnode, i + 1);
/* Two nonempty children */
if (left && right) {
@@ -825,7 +829,7 @@ static struct tnode *halve(struct trie *
if (!newn)
goto nomem;
- put_child(t, tn, i/2, (struct node *)newn);
+ put_child(t, tn, i / 2, (struct node *)newn);
}
}
@@ -834,27 +838,27 @@ static struct tnode *halve(struct trie *
struct tnode *newBinNode;
left = tnode_get_child(oldtnode, i);
- right = tnode_get_child(oldtnode, i+1);
+ right = tnode_get_child(oldtnode, i + 1);
/* At least one of the children is empty */
if (left == NULL) {
- if (right == NULL) /* Both are empty */
+ if (right == NULL) /* Both are empty */
continue;
- put_child(t, tn, i/2, right);
+ put_child(t, tn, i / 2, right);
continue;
}
if (right == NULL) {
- put_child(t, tn, i/2, left);
+ put_child(t, tn, i / 2, left);
continue;
}
/* Two nonempty children */
- newBinNode = (struct tnode *) tnode_get_child(tn, i/2);
- put_child(t, tn, i/2, NULL);
+ newBinNode = (struct tnode *)tnode_get_child(tn, i / 2);
+ put_child(t, tn, i / 2, NULL);
put_child(t, newBinNode, 0, left);
put_child(t, newBinNode, 1, right);
- put_child(t, tn, i/2, resize(t, newBinNode));
+ put_child(t, tn, i / 2, resize(t, newBinNode));
}
tnode_free(oldtnode);
return tn;
@@ -896,13 +900,13 @@ static struct leaf_info *find_leaf_info(
struct leaf_info *li;
hlist_for_each_entry_rcu(li, node, head, hlist)
- if (li->plen == plen)
- return li;
+ if (li->plen == plen)
+ return li;
return NULL;
}
-static inline struct list_head * get_fa_head(struct leaf *l, int plen)
+static inline struct list_head *get_fa_head(struct leaf *l, int plen)
{
struct leaf_info *li = find_leaf_info(l, plen);
@@ -935,8 +939,7 @@ static void insert_leaf_info(struct hlis
/* rcu_read_lock needs to be hold by caller from readside */
-static struct leaf *
-fib_find_node(struct trie *t, u32 key)
+static struct leaf *fib_find_node(struct trie *t, u32 key)
{
int pos;
struct tnode *tn;
@@ -945,14 +948,16 @@ fib_find_node(struct trie *t, u32 key)
pos = 0;
n = rcu_dereference(t->trie);
- while (n != NULL && NODE_TYPE(n) == T_TNODE) {
- tn = (struct tnode *) n;
+ while (n != NULL && NODE_TYPE(n) == T_TNODE) {
+ tn = (struct tnode *)n;
check_tnode(tn);
- if (tkey_sub_equals(tn->key, pos, tn->pos-pos, key)) {
+ if (tkey_sub_equals(tn->key, pos, tn->pos - pos, key)) {
pos = tn->pos + tn->bits;
- n = tnode_get_child(tn, tkey_extract_bits(key, tn->pos, tn->bits));
+ n = tnode_get_child(tn,
+ tkey_extract_bits(key, tn->pos,
+ tn->bits));
} else
break;
}
@@ -973,10 +978,11 @@ static struct node *trie_rebalance(struc
while (tn != NULL && (tp = node_parent((struct node *)tn)) != NULL) {
cindex = tkey_extract_bits(key, tp->pos, tp->bits);
wasfull = tnode_full(tp, tnode_get_child(tp, cindex));
- tn = (struct tnode *) resize (t, (struct tnode *)tn);
- tnode_put_child_reorg((struct tnode *)tp, cindex,(struct node*)tn, wasfull);
+ tn = (struct tnode *)resize(t, (struct tnode *)tn);
+ tnode_put_child_reorg((struct tnode *)tp, cindex,
+ (struct node *)tn, wasfull);
- tp = node_parent((struct node *) tn);
+ tp = node_parent((struct node *)tn);
if (!tp)
break;
tn = tp;
@@ -984,15 +990,15 @@ static struct node *trie_rebalance(struc
/* Handle last (top) tnode */
if (IS_TNODE(tn))
- tn = (struct tnode*) resize(t, (struct tnode *)tn);
+ tn = (struct tnode *)resize(t, (struct tnode *)tn);
- return (struct node*) tn;
+ return (struct node *)tn;
}
/* only used from updater-side */
-static struct list_head *
-fib_insert_node(struct trie *t, int *err, u32 key, int plen)
+static struct list_head *fib_insert_node(struct trie *t, int *err, u32 key,
+ int plen)
{
int pos, newpos;
struct tnode *tp = NULL, *tn = NULL;
@@ -1024,15 +1030,17 @@ fib_insert_node(struct trie *t, int *err
* If it doesn't, we need to replace it with a T_TNODE.
*/
- while (n != NULL && NODE_TYPE(n) == T_TNODE) {
- tn = (struct tnode *) n;
+ while (n != NULL && NODE_TYPE(n) == T_TNODE) {
+ tn = (struct tnode *)n;
check_tnode(tn);
- if (tkey_sub_equals(tn->key, pos, tn->pos-pos, key)) {
+ if (tkey_sub_equals(tn->key, pos, tn->pos - pos, key)) {
tp = tn;
pos = tn->pos + tn->bits;
- n = tnode_get_child(tn, tkey_extract_bits(key, tn->pos, tn->bits));
+ n = tnode_get_child(tn,
+ tkey_extract_bits(key, tn->pos,
+ tn->bits));
BUG_ON(n && node_parent(n) != tn);
} else
@@ -1050,7 +1058,7 @@ fib_insert_node(struct trie *t, int *err
/* Case 1: n is a leaf. Compare prefixes */
if (n != NULL && IS_LEAF(n) && tkey_equals(key, n->key)) {
- struct leaf *l = (struct leaf *) n;
+ struct leaf *l = (struct leaf *)n;
li = leaf_info_new(plen);
@@ -1075,7 +1083,7 @@ fib_insert_node(struct trie *t, int *err
li = leaf_info_new(plen);
if (!li) {
- tnode_free((struct tnode *) l);
+ tnode_free((struct tnode *)l);
*err = -ENOMEM;
goto err;
}
@@ -1098,7 +1106,7 @@ fib_insert_node(struct trie *t, int *err
*/
if (tp)
- pos = tp->pos+tp->bits;
+ pos = tp->pos + tp->bits;
else
pos = 0;
@@ -1107,12 +1115,12 @@ fib_insert_node(struct trie *t, int *err
tn = tnode_new(n->key, newpos, 1);
} else {
newpos = 0;
- tn = tnode_new(key, newpos, 1); /* First tnode */
+ tn = tnode_new(key, newpos, 1); /* First tnode */
}
if (!tn) {
free_leaf_info(li);
- tnode_free((struct tnode *) l);
+ tnode_free((struct tnode *)l);
*err = -ENOMEM;
goto err;
}
@@ -1121,20 +1129,22 @@ fib_insert_node(struct trie *t, int *err
missbit = tkey_extract_bits(key, newpos, 1);
put_child(t, tn, missbit, (struct node *)l);
- put_child(t, tn, 1-missbit, n);
+ put_child(t, tn, 1 - missbit, n);
if (tp) {
cindex = tkey_extract_bits(key, tp->pos, tp->bits);
- put_child(t, (struct tnode *)tp, cindex, (struct node *)tn);
+ put_child(t, (struct tnode *)tp, cindex,
+ (struct node *)tn);
} else {
- rcu_assign_pointer(t->trie, (struct node *)tn); /* First tnode */
+ rcu_assign_pointer(t->trie, (struct node *)tn); /* First tnode */
tp = tn;
}
}
if (tp && tp->pos + tp->bits > 32)
- printk(KERN_WARNING "fib_trie tp=%p pos=%d, bits=%d, key=%0x plen=%d\n",
- tp, tp->pos, tp->bits, key, plen);
+ printk(KERN_WARNING
+ "fib_trie tp=%p pos=%d, bits=%d, key=%0x plen=%d\n", tp,
+ tp->pos, tp->bits, key, plen);
/* Rebalance the trie */
@@ -1150,7 +1160,7 @@ err:
*/
static int fn_trie_insert(struct fib_table *tb, struct fib_config *cfg)
{
- struct trie *t = (struct trie *) tb->tb_data;
+ struct trie *t = (struct trie *)tb->tb_data;
struct fib_alias *fa, *new_fa;
struct list_head *fa_head = NULL;
struct fib_info *fi;
@@ -1230,7 +1240,7 @@ static int fn_trie_insert(struct fib_tab
if (state & FA_S_ACCESSED)
rt_cache_flush(-1);
rtmsg_fib(RTM_NEWROUTE, htonl(key), new_fa, plen,
- tb->tb_id, &cfg->fc_nlinfo, NLM_F_REPLACE);
+ tb->tb_id, &cfg->fc_nlinfo, NLM_F_REPLACE);
goto succeeded;
}
@@ -1278,8 +1288,7 @@ static int fn_trie_insert(struct fib_tab
goto out_free_new_fa;
}
- list_add_tail_rcu(&new_fa->fa_list,
- (fa ? &fa->fa_list : fa_head));
+ list_add_tail_rcu(&new_fa->fa_list, (fa ? &fa->fa_list : fa_head));
rt_cache_flush(-1);
rtmsg_fib(RTM_NEWROUTE, htonl(key), new_fa, plen, tb->tb_id,
@@ -1295,7 +1304,6 @@ err:
return err;
}
-
/* should be called with rcu_read_lock */
static inline int check_leaf(struct trie *t, struct leaf *l,
t_key key, int *plen, const struct flowi *flp,
@@ -1313,7 +1321,9 @@ static inline int check_leaf(struct trie
if (l->key != (key & ntohl(mask)))
continue;
- if ((err = fib_semantic_match(&li->falh, flp, res, htonl(l->key), mask, i)) <= 0) {
+ err = fib_semantic_match(&li->falh, flp, res, htonl(l->key),
+ mask, i);
+ if (err <= 0) {
*plen = i;
#ifdef CONFIG_IP_FIB_TRIE_STATS
t->stats.semantic_match_passed++;
@@ -1328,9 +1338,10 @@ static inline int check_leaf(struct trie
}
static int
-fn_trie_lookup(struct fib_table *tb, const struct flowi *flp, struct fib_result *res)
+fn_trie_lookup(struct fib_table *tb, const struct flowi *flp,
+ struct fib_result *res)
{
- struct trie *t = (struct trie *) tb->tb_data;
+ struct trie *t = (struct trie *)tb->tb_data;
int plen, ret = 0;
struct node *n;
struct tnode *pn;
@@ -1355,11 +1366,12 @@ fn_trie_lookup(struct fib_table *tb, con
/* Just a leaf? */
if (IS_LEAF(n)) {
- if ((ret = check_leaf(t, (struct leaf *)n, key, &plen, flp, res)) <= 0)
+ ret = check_leaf(t, (struct leaf *)n, key, &plen, flp, res);
+ if (ret <= 0)
goto found;
goto failed;
}
- pn = (struct tnode *) n;
+ pn = (struct tnode *)n;
chopped_off = 0;
while (pn) {
@@ -1367,7 +1379,7 @@ fn_trie_lookup(struct fib_table *tb, con
bits = pn->bits;
if (!chopped_off)
- cindex = tkey_extract_bits(mask_pfx(key, current_prefix_length),
+ cindex = tkey_extract_bits(mask_pfx (key, current_prefix_length),
pos, bits);
n = tnode_get_child(pn, cindex);
@@ -1380,12 +1392,12 @@ fn_trie_lookup(struct fib_table *tb, con
}
if (IS_LEAF(n)) {
- if ((ret = check_leaf(t, (struct leaf *)n, key, &plen, flp, res)) <= 0)
+ ret = check_leaf(t, (struct leaf *)n, key, &plen, flp, res);
+ if (ret <= 0)
goto found;
else
goto backtrace;
}
-
#define HL_OPTIMIZE
#ifdef HL_OPTIMIZE
cn = (struct tnode *)n;
@@ -1418,10 +1430,10 @@ fn_trie_lookup(struct fib_table *tb, con
/* NOTA BENE: CHECKING ONLY SKIPPED BITS FOR THE NEW NODE HERE */
- if (current_prefix_length < pos+bits) {
+ if (current_prefix_length < pos + bits) {
if (tkey_extract_bits(cn->key, current_prefix_length,
- cn->pos - current_prefix_length) != 0 ||
- !(cn->child[0]))
+ cn->pos - current_prefix_length) != 0
+ || !(cn->child[0]))
goto backtrace;
}
@@ -1456,19 +1468,19 @@ fn_trie_lookup(struct fib_table *tb, con
node_prefix = mask_pfx(cn->key, cn->pos);
key_prefix = mask_pfx(key, cn->pos);
- pref_mismatch = key_prefix^node_prefix;
+ pref_mismatch = key_prefix ^ node_prefix;
mp = 0;
/* In short: If skipped bits in this node do not match the search
* key, enter the "prefix matching" state.directly.
*/
if (pref_mismatch) {
- while (!(pref_mismatch & (1<<(KEYLENGTH-1)))) {
+ while (!(pref_mismatch & (1 << (KEYLENGTH - 1)))) {
mp++;
- pref_mismatch = pref_mismatch <<1;
+ pref_mismatch = pref_mismatch << 1;
}
- key_prefix = tkey_extract_bits(cn->key, mp, cn->pos-mp);
+ key_prefix = tkey_extract_bits(cn->key, mp, cn->pos - mp);
if (key_prefix != 0)
goto backtrace;
@@ -1476,7 +1488,7 @@ fn_trie_lookup(struct fib_table *tb, con
current_prefix_length = mp;
}
#endif
- pn = (struct tnode *)n; /* Descend */
+ pn = (struct tnode *)n; /* Descend */
chopped_off = 0;
continue;
@@ -1484,12 +1496,14 @@ backtrace:
chopped_off++;
/* As zero don't change the child key (cindex) */
- while ((chopped_off <= pn->bits) && !(cindex & (1<<(chopped_off-1))))
+ while (chopped_off <= pn->bits
+ && !(cindex & (1 << (chopped_off - 1))))
chopped_off++;
/* Decrease current_... with bits chopped off */
if (current_prefix_length > pn->pos + pn->bits - chopped_off)
- current_prefix_length = pn->pos + pn->bits - chopped_off;
+ current_prefix_length =
+ pn->pos + pn->bits - chopped_off;
/*
* Either we do the actual chop off according or if we have
@@ -1497,14 +1511,15 @@ backtrace:
*/
if (chopped_off <= pn->bits) {
- cindex &= ~(1 << (chopped_off-1));
+ cindex &= ~(1 << (chopped_off - 1));
} else {
- struct tnode *parent = node_parent((struct node *) pn);
+ struct tnode *parent = node_parent((struct node *)pn);
if (!parent)
goto failed;
/* Get Child's index */
- cindex = tkey_extract_bits(pn->key, parent->pos, parent->bits);
+ cindex = tkey_extract_bits(pn->key,
+ parent->pos, parent->bits);
pn = parent;
chopped_off = 0;
@@ -1537,13 +1552,13 @@ static int trie_leaf_remove(struct trie
*/
while (n != NULL && IS_TNODE(n)) {
- struct tnode *tn = (struct tnode *) n;
+ struct tnode *tn = (struct tnode *)n;
check_tnode(tn);
- n = tnode_get_child(tn ,tkey_extract_bits(key, tn->pos, tn->bits));
+ n = tnode_get_child(tn, tkey_extract_bits(key, tn->pos, tn->bits));
BUG_ON(n && node_parent(n) != tn);
}
- l = (struct leaf *) n;
+ l = (struct leaf *)n;
if (!n || !tkey_equals(l->key, key))
return 0;
@@ -1557,7 +1572,7 @@ static int trie_leaf_remove(struct trie
t->size--;
tp = node_parent(n);
- tnode_free((struct tnode *) n);
+ tnode_free((struct tnode *)n);
if (tp) {
cindex = tkey_extract_bits(key, tp->pos, tp->bits);
@@ -1574,7 +1589,7 @@ static int trie_leaf_remove(struct trie
*/
static int fn_trie_delete(struct fib_table *tb, struct fib_config *cfg)
{
- struct trie *t = (struct trie *) tb->tb_data;
+ struct trie *t = (struct trie *)tb->tb_data;
u32 key, mask;
int plen = cfg->fc_dst_len;
u8 tos = cfg->fc_tos;
@@ -1694,7 +1709,7 @@ static int trie_flush_leaf(struct trie *
static struct leaf *nextleaf(struct trie *t, struct leaf *thisleaf)
{
- struct node *c = (struct node *) thisleaf;
+ struct node *c = (struct node *)thisleaf;
struct tnode *p;
int idx;
struct node *trie = rcu_dereference(t->trie);
@@ -1703,10 +1718,10 @@ static struct leaf *nextleaf(struct trie
if (trie == NULL)
return NULL;
- if (IS_LEAF(trie)) /* trie w. just a leaf */
- return (struct leaf *) trie;
+ if (IS_LEAF(trie)) /* trie w. just a leaf */
+ return (struct leaf *)trie;
- p = (struct tnode*) trie; /* Start */
+ p = (struct tnode *)trie; /* Start */
} else
p = node_parent(c);
@@ -1720,7 +1735,7 @@ static struct leaf *nextleaf(struct trie
pos = 0;
last = 1 << p->bits;
- for (idx = pos; idx < last ; idx++) {
+ for (idx = pos; idx < last; idx++) {
c = rcu_dereference(p->child[idx]);
if (!c)
@@ -1728,26 +1743,28 @@ static struct leaf *nextleaf(struct trie
/* Decend if tnode */
while (IS_TNODE(c)) {
- p = (struct tnode *) c;
+ p = (struct tnode *)c;
idx = 0;
/* Rightmost non-NULL branch */
if (p && IS_TNODE(p))
while (!(c = rcu_dereference(p->child[idx]))
- && idx < (1<<p->bits)) idx++;
+ && idx < (1 << p->bits))
+ idx++;
/* Done with this tnode? */
if (idx >= (1 << p->bits) || !c)
goto up;
}
- return (struct leaf *) c;
+ return (struct leaf *)c;
}
up:
/* No more children go up one step */
- c = (struct node *) p;
+ c = (struct node *)p;
p = node_parent(c);
}
- return NULL; /* Ready. Root of trie */
+
+ return NULL; /* Ready. Root of trie */
}
/*
@@ -1755,7 +1772,7 @@ up:
*/
static int fn_trie_flush(struct fib_table *tb)
{
- struct trie *t = (struct trie *) tb->tb_data;
+ struct trie *t = (struct trie *)tb->tb_data;
struct leaf *ll = NULL, *l = NULL;
int found = 0, h;
@@ -1779,9 +1796,10 @@ static int fn_trie_flush(struct fib_tabl
static int trie_last_dflt = -1;
static void
-fn_trie_select_default(struct fib_table *tb, const struct flowi *flp, struct fib_result *res)
+fn_trie_select_default(struct fib_table *tb, const struct flowi *flp,
+ struct fib_result *res)
{
- struct trie *t = (struct trie *) tb->tb_data;
+ struct trie *t = (struct trie *)tb->tb_data;
int order, last_idx;
struct fib_info *fi = NULL;
struct fib_info *last_resort;
@@ -1809,8 +1827,7 @@ fn_trie_select_default(struct fib_table
list_for_each_entry_rcu(fa, fa_head, fa_list) {
struct fib_info *next_fi = fa->fa_info;
- if (fa->fa_scope != res->scope ||
- fa->fa_type != RTN_UNICAST)
+ if (fa->fa_scope != res->scope || fa->fa_type != RTN_UNICAST)
continue;
if (next_fi->fib_priority > res->fi->fib_priority)
@@ -1856,12 +1873,13 @@ fn_trie_select_default(struct fib_table
atomic_inc(&last_resort->fib_clntref);
}
trie_last_dflt = last_idx;
- out:;
+out:
rcu_read_unlock();
}
-static int fn_trie_dump_fa(t_key key, int plen, struct list_head *fah, struct fib_table *tb,
- struct sk_buff *skb, struct netlink_callback *cb)
+static int fn_trie_dump_fa(t_key key, int plen, struct list_head *fah,
+ struct fib_table *tb, struct sk_buff *skb,
+ struct netlink_callback *cb)
{
int i, s_i;
struct fib_alias *fa;
@@ -1886,10 +1904,7 @@ static int fn_trie_dump_fa(t_key key, in
tb->tb_id,
fa->fa_type,
fa->fa_scope,
- xkey,
- plen,
- fa->fa_tos,
- fa->fa_info, 0) < 0) {
+ xkey, plen, fa->fa_tos, fa->fa_info, 0) < 0) {
cb->args[4] = i;
return -1;
}
@@ -1899,8 +1914,8 @@ static int fn_trie_dump_fa(t_key key, in
return skb->len;
}
-static int fn_trie_dump_plen(struct trie *t, int plen, struct fib_table *tb, struct sk_buff *skb,
- struct netlink_callback *cb)
+static int fn_trie_dump_plen(struct trie *t, int plen, struct fib_table *tb,
+ struct sk_buff *skb, struct netlink_callback *cb)
{
int h, s_h;
struct list_head *fa_head;
@@ -1913,7 +1928,7 @@ static int fn_trie_dump_plen(struct trie
continue;
if (h > s_h)
memset(&cb->args[4], 0,
- sizeof(cb->args) - 4*sizeof(cb->args[0]));
+ sizeof(cb->args) - 4 * sizeof(cb->args[0]));
fa_head = get_fa_head(l, plen);
@@ -1923,7 +1938,7 @@ static int fn_trie_dump_plen(struct trie
if (list_empty(fa_head))
continue;
- if (fn_trie_dump_fa(l->key, plen, fa_head, tb, skb, cb)<0) {
+ if (fn_trie_dump_fa(l->key, plen, fa_head, tb, skb, cb) < 0) {
cb->args[3] = h;
return -1;
}
@@ -1932,10 +1947,11 @@ static int fn_trie_dump_plen(struct trie
return skb->len;
}
-static int fn_trie_dump(struct fib_table *tb, struct sk_buff *skb, struct netlink_callback *cb)
+static int fn_trie_dump(struct fib_table *tb, struct sk_buff *skb,
+ struct netlink_callback *cb)
{
int m, s_m;
- struct trie *t = (struct trie *) tb->tb_data;
+ struct trie *t = (struct trie *)tb->tb_data;
s_m = cb->args[2];
@@ -1945,9 +1961,9 @@ static int fn_trie_dump(struct fib_table
continue;
if (m > s_m)
memset(&cb->args[3], 0,
- sizeof(cb->args) - 3*sizeof(cb->args[0]));
+ sizeof(cb->args) - 3 * sizeof(cb->args[0]));
- if (fn_trie_dump_plen(t, 32-m, tb, skb, cb)<0) {
+ if (fn_trie_dump_plen(t, 32 - m, tb, skb, cb) < 0) {
cb->args[2] = m;
goto out;
}
@@ -1963,9 +1979,9 @@ out:
/* Fix more generic FIB names for init later */
#ifdef CONFIG_IP_MULTIPLE_TABLES
-struct fib_table * fib_hash_init(u32 id)
+struct fib_table *fib_hash_init(u32 id)
#else
-struct fib_table * __init fib_hash_init(u32 id)
+struct fib_table *__init fib_hash_init(u32 id)
#endif
{
struct fib_table *tb;
@@ -1974,8 +1990,7 @@ struct fib_table * __init fib_hash_init(
if (fn_alias_kmem == NULL)
fn_alias_kmem = kmem_cache_create("ip_fib_alias",
sizeof(struct fib_alias),
- 0, SLAB_HWCACHE_ALIGN,
- NULL);
+ 0, SLAB_HWCACHE_ALIGN, NULL);
tb = kmalloc(sizeof(struct fib_table) + sizeof(struct trie),
GFP_KERNEL);
@@ -1991,7 +2006,7 @@ struct fib_table * __init fib_hash_init(
tb->tb_dump = fn_trie_dump;
memset(tb->tb_data, 0, sizeof(struct trie));
- t = (struct trie *) tb->tb_data;
+ t = (struct trie *)tb->tb_data;
trie_init(t);
@@ -2001,7 +2016,8 @@ struct fib_table * __init fib_hash_init(
trie_main = t;
if (id == RT_TABLE_LOCAL)
- printk(KERN_INFO "IPv4 FIB: Using LC-trie version %s\n", VERSION);
+ printk(KERN_INFO "IPv4 FIB: Using LC-trie version %s\n",
+ VERSION);
return tb;
}
@@ -2028,7 +2044,7 @@ static struct node *fib_trie_get_next(st
pr_debug("get_next iter={node=%p index=%d depth=%d}\n",
iter->tnode, iter->index, iter->depth);
rescan:
- while (cindex < (1<<tn->bits)) {
+ while (cindex < (1 << tn->bits)) {
struct node *n = tnode_get_child(tn, cindex);
if (n) {
@@ -2037,7 +2053,7 @@ rescan:
iter->index = cindex + 1;
} else {
/* push down one level */
- iter->tnode = (struct tnode *) n;
+ iter->tnode = (struct tnode *)n;
iter->index = 0;
++iter->depth;
}
@@ -2050,7 +2066,7 @@ rescan:
/* Current node exhausted, pop back up */
p = node_parent((struct node *)tn);
if (p) {
- cindex = tkey_extract_bits(tn->key, p->pos, p->bits)+1;
+ cindex = tkey_extract_bits(tn->key, p->pos, p->bits) + 1;
tn = p;
--iter->depth;
goto rescan;
@@ -2063,7 +2079,7 @@ rescan:
static struct node *fib_trie_get_first(struct fib_trie_iter *iter,
struct trie *t)
{
- struct node *n ;
+ struct node *n;
if (!t)
return NULL;
@@ -2075,13 +2091,13 @@ static struct node *fib_trie_get_first(s
if (n) {
if (IS_TNODE(n)) {
- iter->tnode = (struct tnode *) n;
+ iter->tnode = (struct tnode *)n;
iter->trie = t;
iter->index = 0;
iter->depth = 1;
} else {
iter->tnode = NULL;
- iter->trie = t;
+ iter->trie = t;
iter->index = 0;
iter->depth = 0;
}
@@ -2098,22 +2114,21 @@ static void trie_collect_stats(struct tr
memset(s, 0, sizeof(*s));
rcu_read_lock();
- for (n = fib_trie_get_first(&iter, t); n;
- n = fib_trie_get_next(&iter)) {
+ for (n = fib_trie_get_first(&iter, t); n; n = fib_trie_get_next(&iter)) {
if (IS_LEAF(n)) {
s->leaves++;
s->totdepth += iter.depth;
if (iter.depth > s->maxdepth)
s->maxdepth = iter.depth;
} else {
- const struct tnode *tn = (const struct tnode *) n;
+ const struct tnode *tn = (const struct tnode *)n;
int i;
s->tnodes++;
if (tn->bits < MAX_STAT_DEPTH)
s->nodesizes[tn->bits]++;
- for (i = 0; i < (1<<tn->bits); i++)
+ for (i = 0; i < (1 << tn->bits); i++)
if (!tn->child[i])
s->nullpointers++;
}
@@ -2129,11 +2144,12 @@ static void trie_show_stats(struct seq_f
unsigned i, max, pointers, bytes, avdepth;
if (stat->leaves)
- avdepth = stat->totdepth*100 / stat->leaves;
+ avdepth = stat->totdepth * 100 / stat->leaves;
else
avdepth = 0;
- seq_printf(seq, "\tAver depth: %d.%02d\n", avdepth / 100, avdepth % 100 );
+ seq_printf(seq, "\tAver depth: %d.%02d\n", avdepth / 100,
+ avdepth % 100);
seq_printf(seq, "\tMax depth: %u\n", stat->maxdepth);
seq_printf(seq, "\tLeaves: %u\n", stat->leaves);
@@ -2143,14 +2159,14 @@ static void trie_show_stats(struct seq_f
bytes += sizeof(struct tnode) * stat->tnodes;
max = MAX_STAT_DEPTH;
- while (max > 0 && stat->nodesizes[max-1] == 0)
+ while (max > 0 && stat->nodesizes[max - 1] == 0)
max--;
pointers = 0;
for (i = 1; i <= max; i++)
if (stat->nodesizes[i] != 0) {
- seq_printf(seq, " %d: %d", i, stat->nodesizes[i]);
- pointers += (1<<i) * stat->nodesizes[i];
+ seq_printf(seq, " %d: %d", i, stat->nodesizes[i]);
+ pointers += (1 << i) * stat->nodesizes[i];
}
seq_putc(seq, '\n');
seq_printf(seq, "\tPointers: %d\n", pointers);
@@ -2161,12 +2177,15 @@ static void trie_show_stats(struct seq_f
#ifdef CONFIG_IP_FIB_TRIE_STATS
seq_printf(seq, "Counters:\n---------\n");
- seq_printf(seq,"gets = %d\n", t->stats.gets);
- seq_printf(seq,"backtracks = %d\n", t->stats.backtrack);
- seq_printf(seq,"semantic match passed = %d\n", t->stats.semantic_match_passed);
- seq_printf(seq,"semantic match miss = %d\n", t->stats.semantic_match_miss);
- seq_printf(seq,"null node hit= %d\n", t->stats.null_node_hit);
- seq_printf(seq,"skipped node resize = %d\n", t->stats.resize_node_skipped);
+ seq_printf(seq, "gets = %d\n", t->stats.gets);
+ seq_printf(seq, "backtracks = %d\n", t->stats.backtrack);
+ seq_printf(seq, "semantic match passed = %d\n",
+ t->stats.semantic_match_passed);
+ seq_printf(seq, "semantic match miss = %d\n",
+ t->stats.semantic_match_miss);
+ seq_printf(seq, "null node hit= %d\n", t->stats.null_node_hit);
+ seq_printf(seq, "skipped node resize = %d\n",
+ t->stats.resize_node_skipped);
#ifdef CLEAR_STATS
memset(&(t->stats), 0, sizeof(t->stats));
#endif
@@ -2181,7 +2200,8 @@ static int fib_triestat_seq_show(struct
if (!stat)
return -ENOMEM;
- seq_printf(seq, "Basic info: size of leaf: %Zd bytes, size of tnode: %Zd bytes.\n",
+ seq_printf(seq,
+ "Basic info: size of leaf: %Zd bytes, size of tnode: %Zd bytes.\n",
sizeof(struct leaf), sizeof(struct tnode));
if (trie_local) {
@@ -2213,8 +2233,7 @@ static const struct file_operations fib_
.release = single_release,
};
-static struct node *fib_trie_get_idx(struct fib_trie_iter *iter,
- loff_t pos)
+static struct node *fib_trie_get_idx(struct fib_trie_iter *iter, loff_t pos)
{
loff_t idx = 0;
struct node *n;
@@ -2233,7 +2252,7 @@ static struct node *fib_trie_get_idx(str
return NULL;
}
-static void *fib_trie_seq_start(struct seq_file *seq, loff_t *pos)
+static void *fib_trie_seq_start(struct seq_file *seq, loff_t * pos)
{
rcu_read_lock();
if (*pos == 0)
@@ -2241,7 +2260,7 @@ static void *fib_trie_seq_start(struct s
return fib_trie_get_idx(seq->private, *pos - 1);
}
-static void *fib_trie_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+static void *fib_trie_seq_next(struct seq_file *seq, void *v, loff_t * pos)
{
struct fib_trie_iter *iter = seq->private;
void *l = v;
@@ -2269,7 +2288,8 @@ static void fib_trie_seq_stop(struct seq
static void seq_indent(struct seq_file *seq, int n)
{
- while (n-- > 0) seq_puts(seq, " ");
+ while (n-- > 0)
+ seq_puts(seq, " ");
}
static inline const char *rtn_scope(enum rt_scope_t s)
@@ -2277,11 +2297,16 @@ static inline const char *rtn_scope(enum
static char buf[32];
switch (s) {
- case RT_SCOPE_UNIVERSE: return "universe";
- case RT_SCOPE_SITE: return "site";
- case RT_SCOPE_LINK: return "link";
- case RT_SCOPE_HOST: return "host";
- case RT_SCOPE_NOWHERE: return "nowhere";
+ case RT_SCOPE_UNIVERSE:
+ return "universe";
+ case RT_SCOPE_SITE:
+ return "site";
+ case RT_SCOPE_LINK:
+ return "link";
+ case RT_SCOPE_HOST:
+ return "host";
+ case RT_SCOPE_NOWHERE:
+ return "nowhere";
default:
snprintf(buf, sizeof(buf), "scope=%d", s);
return buf;
@@ -2330,16 +2355,16 @@ static int fib_trie_seq_show(struct seq_
}
if (IS_TNODE(n)) {
- struct tnode *tn = (struct tnode *) n;
+ struct tnode *tn = (struct tnode *)n;
__be32 prf = htonl(mask_pfx(tn->key, tn->pos));
- seq_indent(seq, iter->depth-1);
+ seq_indent(seq, iter->depth - 1);
seq_printf(seq, " +-- %d.%d.%d.%d/%d %d %d %d\n",
NIPQUAD(prf), tn->pos, tn->bits, tn->full_children,
tn->empty_children);
} else {
- struct leaf *l = (struct leaf *) n;
+ struct leaf *l = (struct leaf *)n;
int i;
__be32 val = htonl(l->key);
@@ -2350,7 +2375,7 @@ static int fib_trie_seq_show(struct seq_
if (li) {
struct fib_alias *fa;
list_for_each_entry_rcu(fa, &li->falh, fa_list) {
- seq_indent(seq, iter->depth+1);
+ seq_indent(seq, iter->depth + 1);
seq_printf(seq, " /%d %s %s", i,
rtn_scope(fa->fa_scope),
rtn_type(fa->fa_type));
@@ -2386,7 +2411,7 @@ static int fib_trie_seq_open(struct inod
if (rc)
goto out_kfree;
- seq = file->private_data;
+ seq = file->private_data;
seq->private = s;
memset(s, 0, sizeof(*s));
out:
@@ -2407,7 +2432,8 @@ static const struct file_operations fib_
static unsigned fib_flag_trans(int type, __be32 mask, const struct fib_info *fi)
{
static unsigned type2flags[RTN_MAX + 1] = {
- [7] = RTF_REJECT, [8] = RTF_REJECT,
+ [7] = RTF_REJECT,
+ [8] = RTF_REJECT,
};
unsigned flags = type2flags[type];
@@ -2444,7 +2470,7 @@ static int fib_route_seq_show(struct seq
if (IS_TNODE(l))
return 0;
- for (i=32; i>=0; i--) {
+ for (i = 32; i >= 0; i--) {
struct leaf_info *li = find_leaf_info(l, i);
struct fib_alias *fa;
__be32 mask, prefix;
@@ -2471,7 +2497,7 @@ static int fib_route_seq_show(struct seq
fi->fib_nh->nh_gw, flags, 0, 0,
fi->fib_priority,
mask,
- (fi->fib_advmss ? fi->fib_advmss + 40 : 0),
+ fi->fib_advmss ? fi->fib_advmss + 40 : 0,
fi->fib_window,
fi->fib_rtt >> 3);
else
@@ -2507,7 +2533,7 @@ static int fib_route_seq_open(struct ino
if (rc)
goto out_kfree;
- seq = file->private_data;
+ seq = file->private_data;
seq->private = s;
memset(s, 0, sizeof(*s));
out:
^ permalink raw reply
* Re: [RFT] fib_trie: macro cleanup
From: Andrew Morton @ 2007-07-26 10:54 UTC (permalink / raw)
To: Stephen Hemminger
Cc: David S. Miller, Adrian Bunk, Robert Olsson, Paul E. McKenney,
Ingo Molnar, Josh Triplett, netdev
In-Reply-To: <20070726114334.1e3e446c@oldman.hamilton.local>
On Thu, 26 Jul 2007 11:43:34 +0100 Stephen Hemminger <shemminger@linux-foundation.org> wrote:
> This patch converts the messy macro for MASK_PFX to inline function
> and expands TKEY_GET_MASK in the one place it is used.
>
>
> --- a/net/ipv4/fib_trie.c 2007-07-26 09:26:19.000000000 +0100
> +++ b/net/ipv4/fib_trie.c 2007-07-26 10:17:21.000000000 +0100
> @@ -85,8 +85,6 @@
> #define MAX_STAT_DEPTH 32
>
> #define KEYLENGTH (8*sizeof(t_key))
> -#define MASK_PFX(k, l) (((l)==0)?0:(k >> (KEYLENGTH-l)) << (KEYLENGTH-l))
> -#define TKEY_GET_MASK(offset, bits) (((bits)==0)?0:((t_key)(-1) << (KEYLENGTH - bits) >> offset))
>
> typedef unsigned int t_key;
>
> @@ -192,6 +190,11 @@ static inline int tnode_child_length(con
> return 1 << tn->bits;
> }
>
> +static inline t_key mask_pfx(t_key k, unsigned short l)
> +{
> + return (l == 0) ? 0 : k >> (KEYLENGTH-l) << (KEYLENGTH-l);
> +}
that's a funy way of doing the masking, isn't it? I suppose gcc will turn
it into the single and-immediate.
> static inline t_key tkey_extract_bits(t_key a, int offset, int bits)
> {
> if (offset < KEYLENGTH)
> @@ -676,7 +679,7 @@ static struct tnode *inflate(struct trie
> inode->pos == oldtnode->pos + oldtnode->bits &&
> inode->bits > 1) {
> struct tnode *left, *right;
> - t_key m = TKEY_GET_MASK(inode->pos, 1);
> + t_key m = ~0U << (KEYLENGTH - 1) >> inode->pos;
hm, so we "know" that t_key is an unsigned int. It makes the typedef a bit
pointless.
<wonders what an inode is doing in there>
<oh>
^ permalink raw reply
* Re: [0/6] Allow registration/change name notifications to fail
From: Herbert Xu @ 2007-07-26 11:03 UTC (permalink / raw)
To: Stephen Hemminger; +Cc: David S. Miller, netdev, Patrick McHardy
In-Reply-To: <20070726113715.6a4b5af9@oldman.hamilton.local>
On Thu, Jul 26, 2007 at 11:37:15AM +0100, Stephen Hemminger wrote:
>
> Thanks for looking at this, are there bugs this fixes so it should
> go to stable?
Well it does fix bugs but I'm a bit anxious about pushing it
to stable straight away because the likelihood of it breaking
something else is just as great.
Perhaps once it's been tested a while then we could push it back.
Cheers,
--
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
^ permalink raw reply
* Re: [RFT] fib_trie: cleanup
From: Robert Olsson @ 2007-07-26 10:32 UTC (permalink / raw)
To: David Miller
Cc: shemminger, bunk, Robert.Olsson, akpm, paulmck, mingo, josh,
netdev
In-Reply-To: <20070726.014902.89039353.davem@davemloft.net>
David Miller writes:
> From: Stephen Hemminger <shemminger@linux-foundation.org>
> Date: Thu, 26 Jul 2007 09:46:48 +0100
>
> > Try this out:
> > * replace macro's with inlines
> > * get rid of places doing multiple evaluations of NODE_PARENT
>
> No objections from me.
>
> Robert?
Fine it looks cleaner and compiles... thanks Stephen.
BTW
I think might be possible improve functional/performance parts too. It's the
list handling I'm thinking of.
I've observed that in most cases there is only one leaf_info in the leaf list.
In 96% of current Internet prefixes in the router I just looked into (below).
So optimizing for this case could be an idea. Some variant were the leaf holds
the leaf_info data direct could be worth testing.
Cheers.
--ro
Main:
Aver depth: 2.57
Max depth: 6
Leaves: 215131
Internal nodes: 52394
1: 27662 2: 9982 3: 8510 4: 3625 5: 1684 6: 626 7: 240 8: 64 16: 1
Pointers: 427924
Null ptrs: 160400
Total size: 7102 kB
ip route list | wc -l
224649
215131/224649 = 96%
^ permalink raw reply
* [NET_SCHED]: Fix prio/ingress classification logic error
From: Patrick McHardy @ 2007-07-26 11:32 UTC (permalink / raw)
To: David Miller; +Cc: Linux Netdev List, PJ Waskiewicz
[-- Attachment #1: Type: text/plain, Size: 198 bytes --]
This is the final fix for the problem Peter reported.
Turns out most other schedulers get it right, the only
other case is ingress setting skb->tc_index to the
uninitialized value of res.classid.
[-- Attachment #2: x --]
[-- Type: text/plain, Size: 2133 bytes --]
[NET_SCHED]: Fix prio/ingress classification logic error
Fix handling of empty or completely non-matching filter chains. In
that case -1 is returned and tcf_result is uninitialized, the
qdisc should fall back to default classification in that case.
Noticed by PJ Waskiewicz <peter.p.waskiewicz.jr@intel.com>.
Signed-off-by: Patrick McHardy <kaber@trash.net>
---
commit c98436c161ff45850346b08f89cfb444be7c7817
tree 07e3ea0f508243f41e70645b6c358e23244ea0b4
parent e4903fb59590f86190280a549420f6cb85bd7f7e
author Patrick McHardy <kaber@trash.net> Thu, 26 Jul 2007 13:32:26 +0200
committer Patrick McHardy <kaber@trash.net> Thu, 26 Jul 2007 13:32:26 +0200
net/sched/sch_ingress.c | 3 +--
net/sched/sch_prio.c | 7 +++----
2 files changed, 4 insertions(+), 6 deletions(-)
diff --git a/net/sched/sch_ingress.c b/net/sched/sch_ingress.c
index 51f16b0..2d32fd2 100644
--- a/net/sched/sch_ingress.c
+++ b/net/sched/sch_ingress.c
@@ -158,9 +158,8 @@ static int ingress_enqueue(struct sk_buff *skb,struct Qdisc *sch)
break;
case TC_ACT_RECLASSIFY:
case TC_ACT_OK:
- case TC_ACT_UNSPEC:
- default:
skb->tc_index = TC_H_MIN(res.classid);
+ default:
result = TC_ACT_OK;
break;
}
diff --git a/net/sched/sch_prio.c b/net/sched/sch_prio.c
index 2d8c084..71bafde 100644
--- a/net/sched/sch_prio.c
+++ b/net/sched/sch_prio.c
@@ -38,9 +38,11 @@ prio_classify(struct sk_buff *skb, struct Qdisc *sch, int *qerr)
struct prio_sched_data *q = qdisc_priv(sch);
u32 band = skb->priority;
struct tcf_result res;
+ int err;
*qerr = NET_XMIT_BYPASS;
if (TC_H_MAJ(skb->priority) != sch->handle) {
+ err = tc_classify(skb, q->filter_list, &res);
#ifdef CONFIG_NET_CLS_ACT
switch (tc_classify(skb, q->filter_list, &res)) {
case TC_ACT_STOLEN:
@@ -49,11 +51,8 @@ prio_classify(struct sk_buff *skb, struct Qdisc *sch, int *qerr)
case TC_ACT_SHOT:
return NULL;
}
-
- if (!q->filter_list ) {
-#else
- if (!q->filter_list || tc_classify(skb, q->filter_list, &res)) {
#endif
+ if (!q->filter_list || err < 0) {
if (TC_H_MAJ(band))
band = 0;
band = q->prio2band[band&TC_PRIO_MAX];
^ permalink raw reply related
* Re: [PATCH][netdrvr] lib8390: comment on locking by Alan Cox Re: 2.6.20->2.6.21 - networking dies after random time
From: Alan Cox @ 2007-07-26 12:47 UTC (permalink / raw)
To: Jarek Poplawski
Cc: Thomas Gleixner, Ingo Molnar, Linus Torvalds, Marcin ??lusarz,
Jean-Baptiste Vignaud, linux-kernel, shemminger, linux-net,
netdev, Andrew Morton, Paul Gortmaker, Jeff Garzik
In-Reply-To: <20070726124401.GC3423@ff.dom.local>
On Thu, 26 Jul 2007 14:44:01 +0200
Jarek Poplawski <jarkao2@o2.pl> wrote:
> Hi,
>
> Very below is my patch proposal with a comment, which in my opinion
> is precious enough to save it for future help in reading and
> understanding the code.
>
> I hope Alan will not blame me I've not asked for his permission before
> sending, and he would ack this patch as it is or at least most of this.
Fine by me
^ permalink raw reply
* [PATCH][netdrvr] lib8390: comment on locking by Alan Cox Re: 2.6.20->2.6.21 - networking dies after random time
From: Jarek Poplawski @ 2007-07-26 12:44 UTC (permalink / raw)
To: Alan Cox
Cc: Thomas Gleixner, Ingo Molnar, Linus Torvalds, Marcin ??lusarz,
Jean-Baptiste Vignaud, linux-kernel, shemminger, linux-net,
netdev, Andrew Morton, Paul Gortmaker, Jeff Garzik
In-Reply-To: <20070725154656.54fd6f13@the-village.bc.nu>
Hi,
Very below is my patch proposal with a comment, which in my opinion
is precious enough to save it for future help in reading and
understanding the code.
I hope Alan will not blame me I've not asked for his permission before
sending, and he would ack this patch as it is or at least most of this.
Thanks & regards,
Jarek P.
On Wed, Jul 25, 2007 at 03:46:56PM +0100, Alan Cox wrote:
> > > The code in question lib8390.c does
> > >
> > > disable_irq();
> > > fiddle_with_the_network_card_hardware()
> > > enable_irq();
> > ...
> > >
> > > No idea how this affects the network card, as the code there must be
> > > able to handle interrupts, which are not originated from the card due to
> > > interrupt sharing.
> >
> > I think, in this last yesterday's patch Ingo could be right, yet!
> > The comment at the beginnig points this is done like that because
> > of chip's slowness. And problems with timing are mysterious.
> >
> > On the other hand author of this code didn't use spin_lock_irqsave
> > for some reason, probably after testing this option too. So, I hope
> > this is the right path, but alas, I'm not sure this patch has to
> > prove this 100%.
>
> The author (me) didn't use spin_lock_irqsave because the slowness of the
> card means that approach caused horrible problems like losing serial data
> at 38400 baud on some chips. Rememeber many 8390 nics on PCI were ISA
> chips with FPGA front ends.
>
> > Anyway, in my opinion this situation where interrupts could/have_to
> > be used for such strange things should confirm the need of more
> > options for handling irqs individually.
>
> Ok the logic behind the 8390 is very simple:
>
> Things to know
> - IRQ delivery is asynchronous to the PCI bus
> - Blocking the local CPU IRQ via spin locks was too slow
> - The chip has register windows needing locking work
>
> So the path was once (I say once as people appear to have changed it
> in the mean time and it now looks rather bogus if the changes to use
> disable_irq_nosync_irqsave are disabling the local IRQ)
>
>
> Take the page lock
> Mask the IRQ on chip
> Disable the IRQ (but not mask locally- someone seems to have
> broken this with the lock validator stuff)
> [This must be _nosync as the page lock may otherwise
> deadlock us]
> Drop the page lock and turn IRQs back on
>
> At this point an existing IRQ may still be running but we can't
> get a new one
>
> Take the lock (so we know the IRQ has terminated) but don't mask
> the IRQs on the processor
> Set irqlock [for debug]
>
> Transmit (slow as ****)
>
> re-enable the IRQ
>
>
> We have to use disable_irq because otherwise you will get delayed
> interrupts on the APIC bus deadlocking the transmit path.
>
> Quite hairy but the chip simply wasn't designed for SMP and you can't
> even ACK an interrupt without risking corrupting other parallel
> activities on the chip.
>
> Alan
>
------>
From: Jarek Poplawski <jarkao2@o2.pl>
Subject: lib8390: comment on locking by Alan Cox
Additional explanation of problems with locking by Alan Cox.
Signed-off-by: Jarek Poplawski <jarkao2@o2.pl>
Cc: Alan Cox <alan@lxorguk.ukuu.org.uk>
Cc: Paul Gortmaker <p_gortmaker@yahoo.com>
Cc: Jeff Garzik <jeff@garzik.org>
---
diff -Nurp 2.6.23-rc1-/drivers/net/lib8390.c 2.6.23-rc1/drivers/net/lib8390.c
--- 2.6.23-rc1-/drivers/net/lib8390.c 2007-07-09 01:32:17.000000000 +0200
+++ 2.6.23-rc1/drivers/net/lib8390.c 2007-07-26 13:55:17.000000000 +0200
@@ -143,6 +143,52 @@ static void __NS8390_init(struct net_dev
* annoying the transmit function is called bh atomic. That places
* restrictions on the user context callers as disable_irq won't save
* them.
+ *
+ * Additional explanation of problems with locking by Alan Cox:
+ *
+ * "The author (me) didn't use spin_lock_irqsave because the slowness of the
+ * card means that approach caused horrible problems like losing serial data
+ * at 38400 baud on some chips. Rememeber many 8390 nics on PCI were ISA
+ * chips with FPGA front ends.
+ *
+ * Ok the logic behind the 8390 is very simple:
+ *
+ * Things to know
+ * - IRQ delivery is asynchronous to the PCI bus
+ * - Blocking the local CPU IRQ via spin locks was too slow
+ * - The chip has register windows needing locking work
+ *
+ * So the path was once (I say once as people appear to have changed it
+ * in the mean time and it now looks rather bogus if the changes to use
+ * disable_irq_nosync_irqsave are disabling the local IRQ)
+ *
+ *
+ * Take the page lock
+ * Mask the IRQ on chip
+ * Disable the IRQ (but not mask locally- someone seems to have
+ * broken this with the lock validator stuff)
+ * [This must be _nosync as the page lock may otherwise
+ * deadlock us]
+ * Drop the page lock and turn IRQs back on
+ *
+ * At this point an existing IRQ may still be running but we can't
+ * get a new one
+ *
+ * Take the lock (so we know the IRQ has terminated) but don't mask
+ * the IRQs on the processor
+ * Set irqlock [for debug]
+ *
+ * Transmit (slow as ****)
+ *
+ * re-enable the IRQ
+ *
+ *
+ * We have to use disable_irq because otherwise you will get delayed
+ * interrupts on the APIC bus deadlocking the transmit path.
+ *
+ * Quite hairy but the chip simply wasn't designed for SMP and you can't
+ * even ACK an interrupt without risking corrupting other parallel
+ * activities on the chip." [lkml, 25 Jul 2007]
*/
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox