* [PATCH Round 3 2/2] Core network changes to support network event notification.
From: Steve Wise @ 2006-06-27 20:51 UTC (permalink / raw)
To: davem; +Cc: netdev
In-Reply-To: <20060627205050.30723.25753.stgit@stevo-desktop>
This patch adds netevent and netlink calls for neighbour change, route
add/del, pmtu change, and routing redirect events.
Netlink Details:
Neighbour change events are broadcast as a new ndmsg type RTM_NEIGHUPD.
Path mtu change events are broadcast as a new rtmsg type RTM_ROUTEUPD.
Routing redirect events are broadcast as a pair of rtmsgs, RTM_DELROUTE
and RTM_NEWROUTE.
---
include/linux/rtnetlink.h | 4 ++
net/core/Makefile | 2 +
net/core/neighbour.c | 37 ++++++++++++++++---
net/ipv4/fib_semantics.c | 9 +++++
net/ipv4/route.c | 86 ++++++++++++++++++++++++++++++++++++++++++--
net/ipv6/route.c | 87 +++++++++++++++++++++++++++++++++++++++++++++
6 files changed, 213 insertions(+), 12 deletions(-)
diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h
index facd9ee..340ca4f 100644
--- a/include/linux/rtnetlink.h
+++ b/include/linux/rtnetlink.h
@@ -35,6 +35,8 @@ #define RTM_NEWROUTE RTM_NEWROUTE
#define RTM_DELROUTE RTM_DELROUTE
RTM_GETROUTE,
#define RTM_GETROUTE RTM_GETROUTE
+ RTM_ROUTEUPD,
+#define RTM_ROUTEUPD RTM_ROUTEUPD
RTM_NEWNEIGH = 28,
#define RTM_NEWNEIGH RTM_NEWNEIGH
@@ -42,6 +44,8 @@ #define RTM_NEWNEIGH RTM_NEWNEIGH
#define RTM_DELNEIGH RTM_DELNEIGH
RTM_GETNEIGH,
#define RTM_GETNEIGH RTM_GETNEIGH
+ RTM_NEIGHUPD,
+#define RTM_NEIGHUPD RTM_NEIGHUPD
RTM_NEWRULE = 32,
#define RTM_NEWRULE RTM_NEWRULE
diff --git a/net/core/Makefile b/net/core/Makefile
index e9bd246..2645ba4 100644
--- a/net/core/Makefile
+++ b/net/core/Makefile
@@ -7,7 +7,7 @@ obj-y := sock.o request_sock.o skbuff.o
obj-$(CONFIG_SYSCTL) += sysctl_net_core.o
-obj-y += dev.o ethtool.o dev_mcast.o dst.o \
+obj-y += dev.o ethtool.o dev_mcast.o dst.o netevent.o \
neighbour.o rtnetlink.o utils.o link_watch.o filter.o
obj-$(CONFIG_XFRM) += flow.o
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index 50a8c73..bf70981 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -30,9 +30,11 @@ #include <linux/times.h>
#include <net/neighbour.h>
#include <net/dst.h>
#include <net/sock.h>
+#include <net/netevent.h>
#include <linux/rtnetlink.h>
#include <linux/random.h>
#include <linux/string.h>
+#include <linux/notifier.h>
#define NEIGH_DEBUG 1
@@ -59,6 +61,7 @@ static void neigh_app_notify(struct neig
#endif
static int pneigh_ifdown(struct neigh_table *tbl, struct net_device *dev);
void neigh_changeaddr(struct neigh_table *tbl, struct net_device *dev);
+static void rtm_neigh_change(struct neighbour *n);
static struct neigh_table *neigh_tables;
#ifdef CONFIG_PROC_FS
@@ -755,6 +758,7 @@ #endif
neigh->nud_state = NUD_STALE;
neigh->updated = jiffies;
neigh_suspect(neigh);
+ notify = 1;
}
} else if (state & NUD_DELAY) {
if (time_before_eq(now,
@@ -763,6 +767,7 @@ #endif
neigh->nud_state = NUD_REACHABLE;
neigh->updated = jiffies;
neigh_connect(neigh);
+ notify = 1;
next = neigh->confirmed + neigh->parms->reachable_time;
} else {
NEIGH_PRINTK2("neigh %p is probed.\n", neigh);
@@ -820,6 +825,8 @@ #endif
out:
write_unlock(&neigh->lock);
}
+ if (notify)
+ rtm_neigh_change(neigh);
#ifdef CONFIG_ARPD
if (notify && neigh->parms->app_probes)
@@ -927,9 +934,7 @@ int neigh_update(struct neighbour *neigh
{
u8 old;
int err;
-#ifdef CONFIG_ARPD
int notify = 0;
-#endif
struct net_device *dev;
int update_isrouter = 0;
@@ -949,9 +954,7 @@ #endif
neigh_suspect(neigh);
neigh->nud_state = new;
err = 0;
-#ifdef CONFIG_ARPD
notify = old & NUD_VALID;
-#endif
goto out;
}
@@ -1023,9 +1026,7 @@ #endif
if (!(new & NUD_CONNECTED))
neigh->confirmed = jiffies -
(neigh->parms->base_reachable_time << 1);
-#ifdef CONFIG_ARPD
notify = 1;
-#endif
}
if (new == old)
goto out;
@@ -1056,7 +1057,11 @@ out:
(neigh->flags | NTF_ROUTER) :
(neigh->flags & ~NTF_ROUTER);
}
+
write_unlock_bh(&neigh->lock);
+
+ if (notify)
+ rtm_neigh_change(neigh);
#ifdef CONFIG_ARPD
if (notify && neigh->parms->app_probes)
neigh_app_notify(neigh);
@@ -2370,9 +2375,27 @@ static void neigh_app_notify(struct neig
NETLINK_CB(skb).dst_group = RTNLGRP_NEIGH;
netlink_broadcast(rtnl, skb, 0, RTNLGRP_NEIGH, GFP_ATOMIC);
}
-
#endif /* CONFIG_ARPD */
+static void rtm_neigh_change(struct neighbour *n)
+{
+ struct nlmsghdr *nlh;
+ int size = NLMSG_SPACE(sizeof(struct ndmsg) + 256);
+ struct sk_buff *skb = alloc_skb(size, GFP_ATOMIC);
+
+ call_netevent_notifiers(NETEVENT_NEIGH_UPDATE, n);
+ if (!skb)
+ return;
+
+ if (neigh_fill_info(skb, n, 0, 0, RTM_NEIGHUPD, 0) < 0) {
+ kfree_skb(skb);
+ return;
+ }
+ nlh = (struct nlmsghdr *)skb->data;
+ NETLINK_CB(skb).dst_group = RTNLGRP_NEIGH;
+ netlink_broadcast(rtnl, skb, 0, RTNLGRP_NEIGH, GFP_ATOMIC);
+}
+
#ifdef CONFIG_SYSCTL
static struct neigh_sysctl_table {
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c
index 0f4145b..197c365 100644
--- a/net/ipv4/fib_semantics.c
+++ b/net/ipv4/fib_semantics.c
@@ -45,6 +45,7 @@ #include <net/tcp.h>
#include <net/sock.h>
#include <net/ip_fib.h>
#include <net/ip_mp_alg.h>
+#include <net/netevent.h>
#include "fib_lookup.h"
@@ -280,6 +281,14 @@ void rtmsg_fib(int event, u32 key, struc
struct sk_buff *skb;
u32 pid = req ? req->pid : n->nlmsg_pid;
int size = NLMSG_SPACE(sizeof(struct rtmsg)+256);
+ struct netevent_route_info nri;
+ int netevent;
+
+ nri.family = AF_INET;
+ nri.data = &fa->fa_info;
+ netevent = event == RTM_NEWROUTE ? NETEVENT_ROUTE_ADD
+ : NETEVENT_ROUTE_DEL;
+ call_netevent_notifiers(netevent, &nri);
skb = alloc_skb(size, GFP_KERNEL);
if (!skb)
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 60b11ae..cef7c6d 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -105,6 +105,7 @@ #include <net/tcp.h>
#include <net/icmp.h>
#include <net/xfrm.h>
#include <net/ip_mp_alg.h>
+#include <net/netevent.h>
#ifdef CONFIG_SYSCTL
#include <linux/sysctl.h>
#endif
@@ -152,6 +153,8 @@ static struct dst_entry *ipv4_negative_a
static void ipv4_link_failure(struct sk_buff *skb);
static void ip_rt_update_pmtu(struct dst_entry *dst, u32 mtu);
static int rt_garbage_collect(void);
+static int rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
+ int nowait, unsigned int flags, unsigned int prot);
static struct dst_ops ipv4_dst_ops = {
@@ -1112,6 +1115,52 @@ static void rt_del(unsigned hash, struct
spin_unlock_bh(rt_hash_lock_addr(hash));
}
+static void rtm_redirect(struct rtable *old, struct rtable *new)
+{
+ struct netevent_redirect netevent;
+ struct sk_buff *skb;
+ int err;
+
+ netevent.old = &old->u.dst;
+ netevent.new = &new->u.dst;
+
+ /* notify netevent subscribers */
+ call_netevent_notifiers(NETEVENT_REDIRECT, &netevent);
+
+ /* Post NETLINK messages: RTM_DELROUTE for old route,
+ RTM_NEWROUTE for new route */
+ skb = alloc_skb(NLMSG_GOODSIZE, GFP_ATOMIC);
+ if (!skb)
+ return;
+ skb->mac.raw = skb->nh.raw = skb->data;
+ skb->dst = &old->u.dst;
+ NETLINK_CB(skb).dst_pid = 0;
+
+ err = rt_fill_info(skb, 0, 0, RTM_DELROUTE, 1, 0, RTPROT_UNSPEC);
+ if (err <= 0)
+ goto out_free;
+
+ netlink_broadcast(rtnl, skb, 0, RTNLGRP_IPV4_ROUTE, GFP_ATOMIC);
+
+ skb = alloc_skb(NLMSG_GOODSIZE, GFP_ATOMIC);
+ if (!skb)
+ return;
+ skb->mac.raw = skb->nh.raw = skb->data;
+ skb->dst = &new->u.dst;
+ NETLINK_CB(skb).dst_pid = 0;
+
+ err = rt_fill_info(skb, 0, 0, RTM_NEWROUTE, 1, 0, RTPROT_REDIRECT);
+ if (err <= 0)
+ goto out_free;
+
+ netlink_broadcast(rtnl, skb, 0, RTNLGRP_IPV4_ROUTE, GFP_ATOMIC);
+ return;
+
+out_free:
+ kfree_skb(skb);
+ return;
+}
+
void ip_rt_redirect(u32 old_gw, u32 daddr, u32 new_gw,
u32 saddr, struct net_device *dev)
{
@@ -1211,6 +1260,8 @@ void ip_rt_redirect(u32 old_gw, u32 dadd
rt_drop(rt);
goto do_next;
}
+
+ rtm_redirect(rth, rt);
rt_del(hash, rth);
if (!rt_intern_hash(hash, rt, &rt))
@@ -1437,6 +1488,32 @@ unsigned short ip_rt_frag_needed(struct
return est_mtu ? : new_mtu;
}
+static void rtm_pmtu_update(struct rtable *rt)
+{
+ struct sk_buff *skb;
+ int err;
+
+ call_netevent_notifiers(NETEVENT_PMTU_UPDATE, &rt->u.dst);
+
+ skb = alloc_skb(NLMSG_GOODSIZE, GFP_ATOMIC);
+ if (!skb)
+ return;
+ skb->mac.raw = skb->nh.raw = skb->data;
+ skb->dst = &rt->u.dst;
+ NETLINK_CB(skb).dst_pid = 0;
+
+ err = rt_fill_info(skb, 0, 0, RTM_ROUTEUPD, 1, 0, RTPROT_UNSPEC);
+ if (err <= 0)
+ goto out_free;
+
+ netlink_broadcast(rtnl, skb, 0, RTNLGRP_IPV4_ROUTE, GFP_ATOMIC);
+ return;
+
+out_free:
+ kfree_skb(skb);
+ return;
+}
+
static void ip_rt_update_pmtu(struct dst_entry *dst, u32 mtu)
{
if (dst->metrics[RTAX_MTU-1] > mtu && mtu >= 68 &&
@@ -1447,6 +1524,7 @@ static void ip_rt_update_pmtu(struct dst
}
dst->metrics[RTAX_MTU-1] = mtu;
dst_set_expires(dst, ip_rt_mtu_expires);
+ rtm_pmtu_update((struct rtable *)dst);
}
}
@@ -2622,7 +2700,7 @@ int ip_route_output_key(struct rtable **
}
static int rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
- int nowait, unsigned int flags)
+ int nowait, unsigned int flags, unsigned int prot)
{
struct rtable *rt = (struct rtable*)skb->dst;
struct rtmsg *r;
@@ -2641,7 +2719,7 @@ #endif
r->rtm_table = RT_TABLE_MAIN;
r->rtm_type = rt->rt_type;
r->rtm_scope = RT_SCOPE_UNIVERSE;
- r->rtm_protocol = RTPROT_UNSPEC;
+ r->rtm_protocol = prot;
r->rtm_flags = (rt->rt_flags & ~0xFFFF) | RTM_F_CLONED;
if (rt->rt_flags & RTCF_NOTIFY)
r->rtm_flags |= RTM_F_NOTIFY;
@@ -2787,7 +2865,7 @@ int inet_rtm_getroute(struct sk_buff *in
NETLINK_CB(skb).dst_pid = NETLINK_CB(in_skb).pid;
err = rt_fill_info(skb, NETLINK_CB(in_skb).pid, nlh->nlmsg_seq,
- RTM_NEWROUTE, 0, 0);
+ RTM_NEWROUTE, 0, 0, RTPROT_UNSPEC);
if (!err)
goto out_free;
if (err < 0) {
@@ -2825,7 +2903,7 @@ int ip_rt_dump(struct sk_buff *skb, str
skb->dst = dst_clone(&rt->u.dst);
if (rt_fill_info(skb, NETLINK_CB(cb->skb).pid,
cb->nlh->nlmsg_seq, RTM_NEWROUTE,
- 1, NLM_F_MULTI) <= 0) {
+ 1, NLM_F_MULTI, RTPROT_UNSPEC) <= 0) {
dst_release(xchg(&skb->dst, NULL));
rcu_read_unlock_bh();
goto done;
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 8a77793..95f68bc 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -54,6 +54,7 @@ #include <net/tcp.h>
#include <linux/rtnetlink.h>
#include <net/dst.h>
#include <net/xfrm.h>
+#include <net/netevent.h>
#include <asm/uaccess.h>
@@ -97,6 +98,10 @@ static int ip6_pkt_discard(struct sk_bu
static int ip6_pkt_discard_out(struct sk_buff *skb);
static void ip6_link_failure(struct sk_buff *skb);
static void ip6_rt_update_pmtu(struct dst_entry *dst, u32 mtu);
+static int rt6_fill_node(struct sk_buff *skb, struct rt6_info *rt,
+ struct in6_addr *dst, struct in6_addr *src,
+ int iif, int type, u32 pid, u32 seq,
+ int prefix, unsigned int flags);
#ifdef CONFIG_IPV6_ROUTE_INFO
static struct rt6_info *rt6_add_route_info(struct in6_addr *prefix, int prefixlen,
@@ -732,6 +737,32 @@ static void ip6_link_failure(struct sk_b
}
}
+static void rtm_pmtu_update(struct rt6_info *rt)
+{
+ struct sk_buff *skb;
+ int err;
+
+ call_netevent_notifiers(NETEVENT_PMTU_UPDATE, &rt->u.dst);
+
+ skb = alloc_skb(NLMSG_GOODSIZE, GFP_ATOMIC);
+ if (!skb)
+ return;
+ skb->mac.raw = skb->nh.raw = skb->data;
+ skb->dst = &rt->u.dst;
+ NETLINK_CB(skb).dst_pid = 0;
+
+ err = rt6_fill_node(skb, rt, NULL, NULL, 0, RTM_ROUTEUPD, 0, 0, 0, 0);
+ if (err <= 0)
+ goto out_free;
+
+ netlink_broadcast(rtnl, skb, 0, RTNLGRP_IPV6_ROUTE, GFP_ATOMIC);
+ return;
+
+out_free:
+ kfree_skb(skb);
+ return;
+}
+
static void ip6_rt_update_pmtu(struct dst_entry *dst, u32 mtu)
{
struct rt6_info *rt6 = (struct rt6_info*)dst;
@@ -743,6 +774,7 @@ static void ip6_rt_update_pmtu(struct ds
dst->metrics[RTAX_FEATURES-1] |= RTAX_FEATURE_ALLFRAG;
}
dst->metrics[RTAX_MTU-1] = mtu;
+ rtm_pmtu_update(rt6);
}
}
@@ -908,6 +940,7 @@ int ip6_route_add(struct in6_rtmsg *rtms
struct net_device *dev = NULL;
struct inet6_dev *idev = NULL;
int addr_type;
+ struct netevent_route_info nri;
rta = (struct rtattr **) _rtattr;
@@ -1086,6 +1119,9 @@ install_route:
rt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(dst_mtu(&rt->u.dst));
rt->u.dst.dev = dev;
rt->rt6i_idev = idev;
+ nri.family = AF_INET6;
+ nri.data = rt;
+ call_netevent_notifiers(NETEVENT_ROUTE_ADD, &nri);
return ip6_ins_rt(rt, nlh, _rtattr, req);
out:
@@ -1117,6 +1153,7 @@ static int ip6_route_del(struct in6_rtms
struct fib6_node *fn;
struct rt6_info *rt;
int err = -ESRCH;
+ struct netevent_route_info nri;
read_lock_bh(&rt6_lock);
@@ -1138,6 +1175,10 @@ static int ip6_route_del(struct in6_rtms
continue;
dst_hold(&rt->u.dst);
read_unlock_bh(&rt6_lock);
+
+ nri.family = AF_INET6;
+ nri.data = rt;
+ call_netevent_notifiers(NETEVENT_ROUTE_DEL, &nri);
return ip6_del_rt(rt, nlh, _rtattr, req);
}
@@ -1147,6 +1188,50 @@ static int ip6_route_del(struct in6_rtms
return err;
}
+static void rtm_redirect(struct rt6_info *old, struct rt6_info *new)
+{
+ struct netevent_redirect netevent;
+ struct sk_buff *skb;
+ int err;
+
+ netevent.old = &old->u.dst;
+ netevent.new = &new->u.dst;
+ call_netevent_notifiers(NETEVENT_REDIRECT, &netevent);
+
+ /* Post NETLINK messages: RTM_DELROUTE for old route,
+ RTM_NEWROUTE for new route */
+ skb = alloc_skb(NLMSG_GOODSIZE, GFP_ATOMIC);
+ if (!skb)
+ return;
+ skb->mac.raw = skb->nh.raw = skb->data;
+ NETLINK_CB(skb).dst_pid = 0;
+ NETLINK_CB(skb).dst_group = RTNLGRP_IPV6_ROUTE;
+
+ err = rt6_fill_node(skb, old, NULL, NULL, 0, RTM_DELROUTE, 0, 0, 0, 0);
+ if (err <= 0)
+ goto out_free;
+
+ netlink_broadcast(rtnl, skb, 0, RTNLGRP_IPV6_ROUTE, GFP_ATOMIC);
+
+ skb = alloc_skb(NLMSG_GOODSIZE, GFP_ATOMIC);
+ if (!skb)
+ return;
+ skb->mac.raw = skb->nh.raw = skb->data;
+ NETLINK_CB(skb).dst_pid = 0;
+ NETLINK_CB(skb).dst_group = RTNLGRP_IPV6_ROUTE;
+
+ err = rt6_fill_node(skb, new, NULL, NULL, 0, RTM_NEWROUTE, 0, 0, 0, 0);
+ if (err <= 0)
+ goto out_free;
+
+ netlink_broadcast(rtnl, skb, 0, RTNLGRP_IPV6_ROUTE, GFP_ATOMIC);
+ return;
+
+out_free:
+ kfree_skb(skb);
+ return;
+}
+
/*
* Handle redirects
*/
@@ -1253,6 +1338,8 @@ restart:
if (ip6_ins_rt(nrt, NULL, NULL, NULL))
goto out;
+ rtm_redirect(rt, nrt);
+
if (rt->rt6i_flags&RTF_CACHE) {
ip6_del_rt(rt, NULL, NULL, NULL);
return;
^ permalink raw reply related
* [PATCH Round 3 1/2] Network Event Notifier Mechanism.
From: Steve Wise @ 2006-06-27 20:51 UTC (permalink / raw)
To: davem; +Cc: netdev
In-Reply-To: <20060627205050.30723.25753.stgit@stevo-desktop>
This patch uses notifier blocks to implement a network event
notifier mechanism.
Clients register their callback function by calling
register_netevent_notifier() like this:
static struct notifier_block nb = {
.notifier_call = my_callback_func
};
...
register_netevent_notifier(&nb);
---
include/net/netevent.h | 49 +++++++++++++++++++++++++++++++++++
net/core/netevent.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 117 insertions(+), 0 deletions(-)
diff --git a/include/net/netevent.h b/include/net/netevent.h
new file mode 100644
index 0000000..22214c8
--- /dev/null
+++ b/include/net/netevent.h
@@ -0,0 +1,49 @@
+#ifndef _NET_EVENT_H
+#define _NET_EVENT_H
+
+/*
+ * Generic netevent notifiers
+ *
+ * Authors:
+ * Tom Tucker <tom@opengridcomputing.com>
+ *
+ * Changes:
+ */
+
+#ifdef __KERNEL__
+
+#include <net/dst.h>
+
+/*
+ * Generic route info structure.
+ *
+ * Family Data ptr type
+ * --------------------------------
+ * AF_INET - struct fib_info *
+ * AF_INET6 - struct rt6_info *
+ * AF_DECnet - struct dn_route *
+ */
+struct netevent_route_info {
+ u16 family;
+ void *data;
+};
+
+struct netevent_redirect {
+ struct dst_entry *old;
+ struct dst_entry *new;
+};
+
+enum netevent_notif_type {
+ NETEVENT_NEIGH_UPDATE = 1, /* arg is struct neighbour ptr */
+ NETEVENT_ROUTE_ADD, /* arg is struct netevent_route_info ptr */
+ NETEVENT_ROUTE_DEL, /* arg is struct netevent_route_info ptr */
+ NETEVENT_PMTU_UPDATE, /* arg is struct dst_entry ptr */
+ NETEVENT_REDIRECT, /* arg is struct netevent_redirect ptr */
+};
+
+extern int register_netevent_notifier(struct notifier_block *nb);
+extern int unregister_netevent_notifier(struct notifier_block *nb);
+extern int call_netevent_notifiers(unsigned long val, void *v);
+
+#endif
+#endif
diff --git a/net/core/netevent.c b/net/core/netevent.c
new file mode 100644
index 0000000..e995751
--- /dev/null
+++ b/net/core/netevent.c
@@ -0,0 +1,68 @@
+/*
+ * Network event notifiers
+ *
+ * Authors:
+ * Tom Tucker <tom@opengridcomputing.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * Fixes:
+ */
+
+#include <linux/rtnetlink.h>
+#include <linux/notifier.h>
+
+static ATOMIC_NOTIFIER_HEAD(netevent_notif_chain);
+
+/**
+ * register_netevent_notifier - register a netevent notifier block
+ * @nb: notifier
+ *
+ * Register a notifier to be called when a netevent occurs.
+ * The notifier passed is linked into the kernel structures and must
+ * not be reused until it has been unregistered. A negative errno code
+ * is returned on a failure.
+ */
+int register_netevent_notifier(struct notifier_block *nb)
+{
+ int err;
+
+ err = atomic_notifier_chain_register(&netevent_notif_chain, nb);
+ return err;
+}
+
+/**
+ * netevent_unregister_notifier - unregister a netevent notifier block
+ * @nb: notifier
+ *
+ * Unregister a notifier previously registered by
+ * register_neigh_notifier(). The notifier is unlinked into the
+ * kernel structures and may then be reused. A negative errno code
+ * is returned on a failure.
+ */
+
+int unregister_netevent_notifier(struct notifier_block *nb)
+{
+ return atomic_notifier_chain_unregister(&netevent_notif_chain, nb);
+}
+
+/**
+ * call_netevent_notifiers - call all netevent notifier blocks
+ * @val: value passed unmodified to notifier function
+ * @v: pointer passed unmodified to notifier function
+ *
+ * Call all neighbour notifier blocks. Parameters and return value
+ * are as for notifier_call_chain().
+ */
+
+int call_netevent_notifiers(unsigned long val, void *v)
+{
+ return atomic_notifier_call_chain(&netevent_notif_chain, val, v);
+}
+
+EXPORT_SYMBOL_GPL(register_netevent_notifier);
+EXPORT_SYMBOL_GPL(unregister_netevent_notifier);
+EXPORT_SYMBOL_GPL(call_netevent_notifiers);
^ permalink raw reply related
* [PATCH Round 3 0/2][RFC] Network Event Notifier Mechanism
From: Steve Wise @ 2006-06-27 20:50 UTC (permalink / raw)
To: davem; +Cc: netdev
Round 3 Changes:
- changed netlink msg for neighbour change to (RTM_NEIGHUPD)
- added netlink msg for PMTU change events (RTM_ROUTEUPD)
- added netlink messages for redirect (RTM_DELROUTE + RTM_NEWROUTE)
- tested neighbour change events via netlink for ipv4 and ipv6.
- tested redirect change events via netlink for ipv4.
Round 2 Changes:
- cleaned up event structures per review feedback.
- began integration with netlink (see neighbour changes in patch 2).
- added IPv6 support.
TODO:
- review feedback changes, if any
- more testing
- retest with RDMA NIC
------
This patch implements a mechanism that allows interested clients to
register for notification of certain network events. The intended use
is to allow RDMA devices (linux/drivers/infiniband) to be notified of
neighbour updates, ICMP redirects, path MTU changes, and route changes.
The reason these devices need update events is because they typically
cache this information in hardware and need to be notified when this
information has been updated. For information on RDMA protocols, see:
http://www.ietf.org/html.charters/rddp-charter.html.
The key events of interest are:
- neighbour mac address change
- routing redirect (the next hop neighbour changes for a dst_entry)
- path mtu change (the path mtu for a dst_entry changes).
- route add/deletes
NOTE: These new netevents are also passed up to user space via netlink.
We would like to get this or similar functionality included in 2.6.19
and request comments.
This patchset consists of 2 patches:
1) New files implementing the Network Event Notifier
2) Core network changes to generate network event notifications
Signed-off-by: Tom Tucker <tom@opengridcomputing.com>
Signed-off-by: Steve Wise <swise@opengridcomputing.com>
^ permalink raw reply
* Re: [NET]: Added GSO header verification
From: Michael Chan @ 2006-06-27 20:46 UTC (permalink / raw)
To: Herbert Xu; +Cc: David S. Miller, netdev
In-Reply-To: <20060627120714.GA15270@gondor.apana.org.au>
On Tue, 2006-06-27 at 22:07 +1000, Herbert Xu wrote:
> [NET]: Added GSO header verification
>
> @@ -2166,10 +2166,14 @@ struct sk_buff *tcp_tso_segment(struct s
> if (!pskb_may_pull(skb, thlen))
> goto out;
>
> + segs = NULL;
> + if (skb_gso_ok(skb, features | NETIF_F_GSO_ROBUST))
> + goto out;
> +
This logic doesn't look right to me. Perhaps it's backwards and should
be:
if (!skb_gso_ok(skb, features | NETIF_F_GSO_ROBUST))
^ permalink raw reply
* Re: [PATCH Round 2 0/2][RFC] Network Event Notifier Mechanism
From: David Miller @ 2006-06-27 20:37 UTC (permalink / raw)
To: swise; +Cc: netdev
In-Reply-To: <1151440399.20252.9.camel@stevo-desktop>
From: Steve Wise <swise@opengridcomputing.com>
Date: Tue, 27 Jun 2006 15:33:19 -0500
> From my experimentation with netlink, RTM_NEWROUTE and RTM_DELROUTE
> messages do not get sent up for redirect events. I have, in fact, added
> this with the new patch I'll send out soon. So either way I need to
> change the IPv[46] code to generate a notification for redirects. With
> the single NETEVENT_REDIRECT call, the RDMA driver can, in one sweep,
> update all the connections. It seems more efficient. At the place
> where I've hooked redirect, both the old route and the new route are
> already created.
Ok, let's see what it looks like.
^ permalink raw reply
* Re: Please pull 'upstream' branch of wireless-2.6
From: Larry Finger @ 2006-06-27 20:37 UTC (permalink / raw)
To: Michael Buesch; +Cc: John W. Linville, netdev
In-Reply-To: <200606272223.19928.mb@bu3sch.de>
Michael Buesch wrote:
> On Tuesday 27 June 2006 22:06, Larry Finger wrote:
>> John,
>>
>> I would like to find a diplomatic solution to this impasse between Michael and Jeff, which is why
>> I'm writing to you privately. Michael is correct in that the loop in question will not usually delay
>
> private?
I meant it to be private, but screwed up.
>> long; however, on some hardware it takes longer than on his. On mine, I have seen delays as long as
>> 550 usec.
>
> What's the chip?
bcm43xx: Chip ID 0x4306, rev 0x2
bcm43xx: Number of cores: 6
bcm43xx: Core 0: ID 0x800, rev 0x2, vendor 0x4243, enabled
bcm43xx: Core 1: ID 0x812, rev 0x4, vendor 0x4243, disabled
bcm43xx: Core 2: ID 0x80d, rev 0x1, vendor 0x4243, enabled
bcm43xx: Core 3: ID 0x807, rev 0x1, vendor 0x4243, disabled
bcm43xx: Core 4: ID 0x804, rev 0x7, vendor 0x4243, enabled
bcm43xx: Core 5: ID 0x812, rev 0x4, vendor 0x4243, disabled
bcm43xx: Ignoring additional 802.11 core.
bcm43xx: Detected PHY: Version: 1, Type 2, Revision 1
bcm43xx: Detected Radio: ID: 2205017f (Manuf: 17f Ver: 2050 Rev: 2)
>> In any case, I think that the following code fragment would work and pass Jeff's criticism:
>>
>> for (i=5000; i; i--) {
>> ..........
>> usleep(1);
>
> usleep? Can't find that in my kernel tree.
> In fact, I think the lowest possible sleep time
> depends on HZ and is 1msec on 1000HZ.
I meant udelay, of course.
> Additionally, we are holding a spinlock at this time, so it is
> not as easy as simply replacing udelay() by some sleeping function.
I know that.
>> This would make the worst-case delay be 5 msec, but would provide a cushion of 10X the longest I
>> have seen and should be safe.
>>
>> Do you have any suggestions on what should be done next?
>
> Leave it as is and find out why it takes so long for your strange card. ;)
I once offered you my second, duplicate card for testing, but never heard back. Do you have any
ideas regarding diagnostics to see why it takes so long? Remember, this card used to time-out on the
1 second delay before the periodic work was restructured.
Larry
^ permalink raw reply
* Re: [NET]: Make illegal_highdma more anal
From: David Miller @ 2006-06-27 20:33 UTC (permalink / raw)
To: herbert; +Cc: netdev
In-Reply-To: <20060620234938.GC30522@gondor.apana.org.au>
From: Herbert Xu <herbert@gondor.apana.org.au>
Date: Wed, 21 Jun 2006 09:49:38 +1000
> [NET]: Make illegal_highdma more anal
>
> Rather than having illegal_highdma as a macro when HIGHMEM is off, we
> can turn it into an inline function that returns zero. This will catch
> callers that give it bad arguments.
>
> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Looks sane, applied.
^ permalink raw reply
* Re: [PATCH Round 2 0/2][RFC] Network Event Notifier Mechanism
From: Steve Wise @ 2006-06-27 20:33 UTC (permalink / raw)
To: David Miller; +Cc: netdev
In-Reply-To: <20060627.132132.21596632.davem@davemloft.net>
On Tue, 2006-06-27 at 13:21 -0700, David Miller wrote:
> From: Steve Wise <swise@opengridcomputing.com>
> Date: Tue, 27 Jun 2006 15:19:08 -0500
>
> > For an RDMA NIC, all this logic is in HW, which is why we need the event
> > notification; to tell the HW to change its next hop information.
>
> Back to the route change notification, I still think you can
> get what you need by just looking for the route delete.
>
> You can match if any RDMA connection is using the deleted
> route, mark it "update pending" or something like that,
> and when the you get the "new route" event you can walk the
> "pending" list and try to relookup the route for those
> connections.
>From my experimentation with netlink, RTM_NEWROUTE and RTM_DELROUTE
messages do not get sent up for redirect events. I have, in fact, added
this with the new patch I'll send out soon. So either way I need to
change the IPv[46] code to generate a notification for redirects. With
the single NETEVENT_REDIRECT call, the RDMA driver can, in one sweep,
update all the connections. It seems more efficient. At the place
where I've hooked redirect, both the old route and the new route are
already created.
Steve.
^ permalink raw reply
* Re: [PKT_SCHED]: PSCHED_TADD() and PSCHED_TADD2() can result,tv_usec >= 1000000
From: David Miller @ 2006-06-27 20:32 UTC (permalink / raw)
To: maeda-sxb; +Cc: netdev
In-Reply-To: <44988FC3.5030300@necst.nec.co.jp>
From: Shuya MAEDA <maeda-sxb@necst.nec.co.jp>
Date: Wed, 21 Jun 2006 09:16:03 +0900
> Thank you for the comment.
> I made the patch that used the loop instead of the divide and modulus.
> Are there any comments?
Your email client has corrupted the patch, turning tab characters
into spaces, and also turning lines containing only spaces into
empty lines.
Therefore, I cannot apply your patch, please send your patch properly
so that I may apply it.
Thank you.
^ permalink raw reply
* Re: [PATCH] Export accept queue len of a TCP listening socket via rx_queue
From: David Miller @ 2006-06-27 20:29 UTC (permalink / raw)
To: sri; +Cc: herbert, netdev
In-Reply-To: <1150997897.8365.11.camel@w-sridhar2.beaverton.ibm.com>
From: Sridhar Samudrala <sri@us.ibm.com>
Date: Thu, 22 Jun 2006 10:38:17 -0700
> On Thu, 2006-06-22 at 10:50 +1000, Herbert Xu wrote:
> > Sridhar Samudrala <sri@us.ibm.com> wrote:
> > >>
> > >> What about using the same fields (rqueue/wqueue) as you did for /proc?
> > >
> > > I meant extending tcp_info structure to add new fields. I think the user
> > > space also uses this structure.
> >
> > What about putting it into inet_idiag_msg.idiag_[rw]queue instead?
>
> OK. I was under the mistaken assumption that [rw]queue fields are exported
> via tcp_info. This makes it pretty simple to support netlink users also.
> Here is the updated patch.
This looks fine. Applied, thanks a lot Sridhar.
^ permalink raw reply
* RE: [PATCH Round 2 0/2][RFC] Network Event Notifier Mechanism
From: Caitlin Bestler @ 2006-06-27 20:27 UTC (permalink / raw)
To: David Miller, swise; +Cc: netdev
netdev-owner@vger.kernel.org wrote:
> From: Steve Wise <swise@opengridcomputing.com>
> Date: Tue, 27 Jun 2006 10:02:19 -0500
>
>> For the RDMA kernel subsystem, however, we still need a specific
>> event. We need both the old and new dst_entry struct ptrs to figure
>> out which active connections were using the old dst_entry and should
>> be updated to use the new dst_entry.
>
> This change isn't truly atomic from a kernel standpoint either.
>
> The new dst won't be selected by the socket until later, when
> the socket tries to send something, notices the old dst is
> obsolete, and looks up a new one.
>
> Your code could do the same thing.
The request to "send something" is posted directly form user
mode to a mapped memory ring that is reaped by the hardware.
Having the hardware fault, report that fault, and wait for
the host to update it with the new mapping is somewhat clumbsy.
It also won't work at all for existing hardware.
The best you could do is to have the driver invalidate the old
entry, then *presume* that the hardware will want the replacement
and look that up, and then forward that answer to the hardware.
^ permalink raw reply
* Re: [patch 1/1] netlink: encapsulate eff_cap usage within security framework
From: David Miller @ 2006-06-27 20:26 UTC (permalink / raw)
To: sds; +Cc: netdev, dgoeddel, chrisw, jmorris
In-Reply-To: <1151342346.5264.45.camel@moss-spartans.epoch.ncsc.mil>
From: Stephen Smalley <sds@tycho.nsa.gov>
Date: Mon, 26 Jun 2006 13:19:05 -0400
> This patch encapsulates the usage of eff_cap (in netlink_skb_params) within
> the security framework by extending security_netlink_recv to include a required
> capability parameter and converting all direct usage of eff_caps outside
> of the lsm modules to use the interface. It also updates the SELinux
> implementation of the security_netlink_send and security_netlink_recv
> hooks to take advantage of the sid in the netlink_skb_params struct.
> This also enables SELinux to perform auditing of netlink capability checks.
> Please apply, for 2.6.18 if possible.
>
> Signed-off-by: Darrel Goeddel <dgoeddel@trustedcs.com>
> Signed-off-by: Stephen Smalley <sds@tycho.nsa.gov>
> Acked-by: James Morris <jmorris@namei.org>
Applied, thanks a lot.
^ permalink raw reply
* Re: [PATCHSET] Towards accurate incoming interface information
From: David Miller @ 2006-06-27 20:24 UTC (permalink / raw)
To: tgraf; +Cc: netdev
In-Reply-To: <20060627150727.GV1376@postel.suug.ch>
From: Thomas Graf <tgraf@suug.ch>
Date: Tue, 27 Jun 2006 17:07:27 +0200
> * Thomas Graf <tgraf@suug.ch> 2006-06-26 16:54
> > This patchset transforms skb->input_dev based on a device
> > reference to skb->iif based on an interface index moving
> > towards accurate iif information for routing and classification
> > through the following changesets:
>
> Hold on with this, I haven't noticed this ifb device
> go in and thus missed to update it. I'll post an
> updated patch shortly
Ok.
^ permalink raw reply
* Re: Please pull 'upstream' branch of wireless-2.6
From: Michael Buesch @ 2006-06-27 20:23 UTC (permalink / raw)
To: Larry Finger; +Cc: John W. Linville, netdev
In-Reply-To: <44A18FE3.1080403@lwfinger.net>
On Tuesday 27 June 2006 22:06, Larry Finger wrote:
> John,
>
> I would like to find a diplomatic solution to this impasse between Michael and Jeff, which is why
> I'm writing to you privately. Michael is correct in that the loop in question will not usually delay
private?
> long; however, on some hardware it takes longer than on his. On mine, I have seen delays as long as
> 550 usec.
What's the chip?
> In any case, I think that the following code fragment would work and pass Jeff's criticism:
>
> for (i=5000; i; i--) {
> ..........
> usleep(1);
usleep? Can't find that in my kernel tree.
In fact, I think the lowest possible sleep time
depends on HZ and is 1msec on 1000HZ.
Additionally, we are holding a spinlock at this time, so it is
not as easy as simply replacing udelay() by some sleeping function.
> This would make the worst-case delay be 5 msec, but would provide a cushion of 10X the longest I
> have seen and should be safe.
>
> Do you have any suggestions on what should be done next?
Leave it as is and find out why it takes so long for your strange card. ;)
--
Greetings Michael.
^ permalink raw reply
* Re: [NET]: Added GSO header verification
From: David Miller @ 2006-06-27 20:22 UTC (permalink / raw)
To: herbert; +Cc: netdev
In-Reply-To: <20060627120714.GA15270@gondor.apana.org.au>
From: Herbert Xu <herbert@gondor.apana.org.au>
Date: Tue, 27 Jun 2006 22:07:14 +1000
> This feature is only needed by Xen but most of the code here is useful
> for other things like TCPv4 ECN support.
>
> [NET]: Added GSO header verification
Looks sane, applied.
Thanks Herbert.
^ permalink raw reply
* Re: [PATCH Round 2 0/2][RFC] Network Event Notifier Mechanism
From: David Miller @ 2006-06-27 20:21 UTC (permalink / raw)
To: swise; +Cc: netdev
In-Reply-To: <1151439548.20252.2.camel@stevo-desktop>
From: Steve Wise <swise@opengridcomputing.com>
Date: Tue, 27 Jun 2006 15:19:08 -0500
> For an RDMA NIC, all this logic is in HW, which is why we need the event
> notification; to tell the HW to change its next hop information.
Back to the route change notification, I still think you can
get what you need by just looking for the route delete.
You can match if any RDMA connection is using the deleted
route, mark it "update pending" or something like that,
and when the you get the "new route" event you can walk the
"pending" list and try to relookup the route for those
connections.
^ permalink raw reply
* Re: [PATCH Round 2 0/2][RFC] Network Event Notifier Mechanism
From: Steve Wise @ 2006-06-27 20:19 UTC (permalink / raw)
To: David Miller; +Cc: netdev
In-Reply-To: <20060627.131443.104035750.davem@davemloft.net>
On Tue, 2006-06-27 at 13:14 -0700, David Miller wrote:
> This change isn't truly atomic from a kernel standpoint either.
>
> The new dst won't be selected by the socket until later,
> when the socket tries to send something, notices the old dst
> is obsolete, and looks up a new one.
>
> Your code could do the same thing.
>
For an RDMA NIC, all this logic is in HW, which is why we need the event
notification; to tell the HW to change its next hop information.
^ permalink raw reply
* Re: [PATCH Round 2 0/2][RFC] Network Event Notifier Mechanism
From: David Miller @ 2006-06-27 20:14 UTC (permalink / raw)
To: swise; +Cc: netdev
In-Reply-To: <1151420539.3207.29.camel@stevo-desktop>
From: Steve Wise <swise@opengridcomputing.com>
Date: Tue, 27 Jun 2006 10:02:19 -0500
> For the RDMA kernel subsystem, however, we still need a specific event.
> We need both the old and new dst_entry struct ptrs to figure out which
> active connections were using the old dst_entry and should be updated to
> use the new dst_entry.
This change isn't truly atomic from a kernel standpoint either.
The new dst won't be selected by the socket until later,
when the socket tries to send something, notices the old dst
is obsolete, and looks up a new one.
Your code could do the same thing.
^ permalink raw reply
* Re: Please pull 'upstream' branch of wireless-2.6
From: Larry Finger @ 2006-06-27 20:06 UTC (permalink / raw)
Cc: John W. Linville, netdev
In-Reply-To: <200606272147.04477.mb@bu3sch.de>
Michael Buesch wrote:
> On Tuesday 27 June 2006 21:33, John W. Linville wrote:
>> On Tue, Jun 27, 2006 at 06:31:01PM +0200, Michael Buesch wrote:
>>> On Tuesday 27 June 2006 18:12, Jeff Garzik wrote:
>>>> Michael Buesch wrote:
>>>>> So, I will submit a patch to lower the udelay(10) to udelay(1)
>>>>> and we can close the discussion? ;)
>>>> No, that totally avoids my point. Your "otherwise idle machine" test is
>>>> probably nowhere near worst case in the field, for loops that can
>>>> potentially lock the CPU for a long time upon hardware fault. And then
>>>> there are the huge delays in specific functions that I pointed out...
>>> wtf are you requesting from me?
>>> 1) I proved you that the loop does only spin _once_ or even _less_.
>>> 2) If the hardware is faulty, the user must replace it.
>>> Because, if the hardware is faulty, it can crash the whole
>>> machine anyway, obviously.
>>>
>>> 3) There is no "huge delay". I proved it with my logs.
>>> -> No CPU hog => Nothing to fix.
>> Michael,
>>
>> I think Jeff's concern is that by using udelay you are busy-waiting.
>> And, the for loop limit of 100000 means you could freeze the kernel
>> for up to a whole second. Granted that this won't happen very often
>
> s/very often/ever/
>
> It won't happen, as long as the driver is not buggy, or the device
> is hardware broken. So, if it happens, something has to be fixed.
> In fact, it did happen _never_ for me.
> If it triggers, the device does not work _at all_ anyway.
>
>> and in the grand scheme of things a second isn't all _that_ long,
>> but still it would be better to avoid a delay like that -- a second
>> could be the time it takes to avoid a meltdown at the nuclear power
>> plant. :-)
>>
>> Could you not use msleep instead of udelay (and scale the for loop
>> appropriately)? What would be the problem with that? It would get
>> rid of the busy waiting.
>
> Becauses it horribly _increases_ the delay.
> We "spin" for _at most_ 10 usecs here. Please always remember that.
> We are talking about a 10 usec delay here. And I already sent a
> patch to even reduce this to under 10 usec.
>
>> To be fair, this code was already in the driver and was only being
>> moved by this patch. Still, what better time to fix it than now? :-)
>
> If it ain't broken, don't fix it.
>
>> I'll go ahead and reshuffle wireless-2.6 to drop this patch. A new
>> patch that passes muster w/ Jeff will be most welcome! :-)
>
> A new patch won't appear, as there is no problem with this
> delay.
> Please don't drop anything and apply the following patch on top
> of it:
John,
I would like to find a diplomatic solution to this impasse between Michael and Jeff, which is why
I'm writing to you privately. Michael is correct in that the loop in question will not usually delay
long; however, on some hardware it takes longer than on his. On mine, I have seen delays as long as
550 usec. In any case, I think that the following code fragment would work and pass Jeff's criticism:
for (i=5000; i; i--) {
..........
usleep(1);
}
This would make the worst-case delay be 5 msec, but would provide a cushion of 10X the longest I
have seen and should be safe.
Do you have any suggestions on what should be done next?
Larry
^ permalink raw reply
* Re: Please pull 'upstream' branch of wireless-2.6
From: Michael Buesch @ 2006-06-27 19:47 UTC (permalink / raw)
To: John W. Linville; +Cc: Jeff Garzik, bcm43xx-dev, Larry Finger, netdev
In-Reply-To: <20060627193259.GE1207@tuxdriver.com>
On Tuesday 27 June 2006 21:33, John W. Linville wrote:
> On Tue, Jun 27, 2006 at 06:31:01PM +0200, Michael Buesch wrote:
> > On Tuesday 27 June 2006 18:12, Jeff Garzik wrote:
> > > Michael Buesch wrote:
> > > > So, I will submit a patch to lower the udelay(10) to udelay(1)
> > > > and we can close the discussion? ;)
> > >
> > > No, that totally avoids my point. Your "otherwise idle machine" test is
> > > probably nowhere near worst case in the field, for loops that can
> > > potentially lock the CPU for a long time upon hardware fault. And then
> > > there are the huge delays in specific functions that I pointed out...
> >
> > wtf are you requesting from me?
> > 1) I proved you that the loop does only spin _once_ or even _less_.
> > 2) If the hardware is faulty, the user must replace it.
> > Because, if the hardware is faulty, it can crash the whole
> > machine anyway, obviously.
> >
> > 3) There is no "huge delay". I proved it with my logs.
> > -> No CPU hog => Nothing to fix.
>
> Michael,
>
> I think Jeff's concern is that by using udelay you are busy-waiting.
> And, the for loop limit of 100000 means you could freeze the kernel
> for up to a whole second. Granted that this won't happen very often
s/very often/ever/
It won't happen, as long as the driver is not buggy, or the device
is hardware broken. So, if it happens, something has to be fixed.
In fact, it did happen _never_ for me.
If it triggers, the device does not work _at all_ anyway.
> and in the grand scheme of things a second isn't all _that_ long,
> but still it would be better to avoid a delay like that -- a second
> could be the time it takes to avoid a meltdown at the nuclear power
> plant. :-)
>
> Could you not use msleep instead of udelay (and scale the for loop
> appropriately)? What would be the problem with that? It would get
> rid of the busy waiting.
Becauses it horribly _increases_ the delay.
We "spin" for _at most_ 10 usecs here. Please always remember that.
We are talking about a 10 usec delay here. And I already sent a
patch to even reduce this to under 10 usec.
> To be fair, this code was already in the driver and was only being
> moved by this patch. Still, what better time to fix it than now? :-)
If it ain't broken, don't fix it.
> I'll go ahead and reshuffle wireless-2.6 to drop this patch. A new
> patch that passes muster w/ Jeff will be most welcome! :-)
A new patch won't appear, as there is no problem with this
delay.
Please don't drop anything and apply the following patch on top
of it:
--
Microoptimization:
This reduces the udelay in bcm43xx_mac_suspend.
Signed-off-by: Michael Buesch <mb@bu3sch.de>
Index: wireless-2.6/drivers/net/wireless/bcm43xx/bcm43xx_main.c
===================================================================
--- wireless-2.6.orig/drivers/net/wireless/bcm43xx/bcm43xx_main.c 2006-06-27 17:47:24.000000000 +0200
+++ wireless-2.6/drivers/net/wireless/bcm43xx/bcm43xx_main.c 2006-06-27 17:53:29.000000000 +0200
@@ -2328,7 +2328,7 @@
tmp = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON);
if (tmp & BCM43xx_IRQ_READY)
goto out;
- udelay(10);
+ udelay(1);
}
printkl(KERN_ERR PFX "MAC suspend failed\n");
}
--
Greetings Michael.
^ permalink raw reply
* Re: Re: [RFC 3/7] NetLabel: CIPSOv4 engine
From: Klaus Weidner @ 2006-06-27 19:41 UTC (permalink / raw)
To: James Morris
Cc: Joe Nall, jmorris, Paul Moore, Stephen Smalley, RedHat LSPP,
linux-security-module, SELinux List, netdev, Steve Grubb,
David Miller
In-Reply-To: <Pine.LNX.4.64.0606262031010.26545@d.namei>
On Mon, Jun 26, 2006 at 08:33:57PM -0400, James Morris wrote:
> On Mon, 26 Jun 2006, Joe Nall wrote:
> > For all of the EAL4 LSPP Linux evaluation work is being done by Red
> > Hat/IBM/HP/atsec and others to be useful to integrators, there has to be basic
> > (e.g. CIPSO) multilevel network interoperability with existing multilevel
> > systems and good (e.g IPSec) multilevel networking between SELinux systems.
>
> Just to be clear, my understanding is that the native xfrm labeling is
> suitable for LSPP evaluation, as distinct from CIPSO being desired by
> system integrators from an interoperability point of view.
It's not quite that distinct, the two solutions overlap in some areas but
neither can replace the other.
CIPSO would also be suitable for LSPP evaluation since it is capable of
exporting and importing labeled data. It requires a trusted network since
it doesn't encrypt or authenticate, so the evaluation would need to
restrict the environment accordingly.
The native IPSEC/xfrm approach is useful for more hostile environments
where you can't fully trust the network, but it's not interoperable with
existing deployed systems so it's not a replacement for CIPSO.
>From an evaluation point of view, either CIPSO or IPSEC/xfrm would be
able to meet LSPP requirements but with different restrictions on the
environment.
-Klaus
^ permalink raw reply
* [PATCH] bcm43xx: opencoded locking
From: Michael Buesch @ 2006-06-27 19:38 UTC (permalink / raw)
To: linville; +Cc: akpm, bcm43xx-dev, netdev
As many people don't seem to like the locking "obfuscation"
in the bcm43xx driver, this patch removes it.
Signed-off-by: Michael Buesch <mb@bu3sch.de>
Index: wireless-2.6/drivers/net/wireless/bcm43xx/bcm43xx.h
===================================================================
--- wireless-2.6.orig/drivers/net/wireless/bcm43xx/bcm43xx.h 2006-06-27 17:47:24.000000000 +0200
+++ wireless-2.6/drivers/net/wireless/bcm43xx/bcm43xx.h 2006-06-27 20:44:27.000000000 +0200
@@ -647,6 +647,19 @@
#define bcm43xx_status(bcm) atomic_read(&(bcm)->init_status)
#define bcm43xx_set_status(bcm, stat) atomic_set(&(bcm)->init_status, (stat))
+/* *** THEORY OF LOCKING ***
+ *
+ * We have two different locks in the bcm43xx driver.
+ * => bcm->mutex: General sleeping mutex. Protects struct bcm43xx_private
+ * and the device registers. This mutex does _not_ protect
+ * against concurrency from the IRQ handler.
+ * => bcm->irq_lock: IRQ spinlock. Protects against IRQ handler concurrency.
+ *
+ * Please note that, if you only take the irq_lock, you are not protected
+ * against concurrency from the periodic work handlers.
+ * Most times you want to take _both_ locks.
+ */
+
struct bcm43xx_private {
struct ieee80211_device *ieee;
struct ieee80211softmac_device *softmac;
@@ -657,7 +670,6 @@
void __iomem *mmio_addr;
- /* Locking, see "theory of locking" text below. */
spinlock_t irq_lock;
struct mutex mutex;
@@ -689,6 +701,7 @@
struct bcm43xx_sprominfo sprom;
#define BCM43xx_NR_LEDS 4
struct bcm43xx_led leds[BCM43xx_NR_LEDS];
+ spinlock_t leds_lock;
/* The currently active core. */
struct bcm43xx_coreinfo *current_core;
@@ -759,55 +772,6 @@
};
-/* *** THEORY OF LOCKING ***
- *
- * We have two different locks in the bcm43xx driver.
- * => bcm->mutex: General sleeping mutex. Protects struct bcm43xx_private
- * and the device registers.
- * => bcm->irq_lock: IRQ spinlock. Protects against IRQ handler concurrency.
- *
- * We have three types of helper function pairs to utilize these locks.
- * (Always use the helper functions.)
- * 1) bcm43xx_{un}lock_noirq():
- * Takes bcm->mutex. Does _not_ protect against IRQ concurrency,
- * so it is almost always unsafe, if device IRQs are enabled.
- * So only use this, if device IRQs are masked.
- * Locking may sleep.
- * You can sleep within the critical section.
- * 2) bcm43xx_{un}lock_irqonly():
- * Takes bcm->irq_lock. Does _not_ protect against
- * bcm43xx_lock_noirq() critical sections.
- * Does only protect against the IRQ handler path and other
- * irqonly() critical sections.
- * Locking does not sleep.
- * You must not sleep within the critical section.
- * 3) bcm43xx_{un}lock_irqsafe():
- * This is the cummulative lock and takes both, mutex and irq_lock.
- * Protects against noirq() and irqonly() critical sections (and
- * the IRQ handler path).
- * Locking may sleep.
- * You must not sleep within the critical section.
- */
-
-/* Lock type 1 */
-#define bcm43xx_lock_noirq(bcm) mutex_lock(&(bcm)->mutex)
-#define bcm43xx_unlock_noirq(bcm) mutex_unlock(&(bcm)->mutex)
-/* Lock type 2 */
-#define bcm43xx_lock_irqonly(bcm, flags) \
- spin_lock_irqsave(&(bcm)->irq_lock, flags)
-#define bcm43xx_unlock_irqonly(bcm, flags) \
- spin_unlock_irqrestore(&(bcm)->irq_lock, flags)
-/* Lock type 3 */
-#define bcm43xx_lock_irqsafe(bcm, flags) do { \
- bcm43xx_lock_noirq(bcm); \
- bcm43xx_lock_irqonly(bcm, flags); \
- } while (0)
-#define bcm43xx_unlock_irqsafe(bcm, flags) do { \
- bcm43xx_unlock_irqonly(bcm, flags); \
- bcm43xx_unlock_noirq(bcm); \
- } while (0)
-
-
static inline
struct bcm43xx_private * bcm43xx_priv(struct net_device *dev)
{
Index: wireless-2.6/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c
===================================================================
--- wireless-2.6.orig/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c 2006-06-24 22:13:44.000000000 +0200
+++ wireless-2.6/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c 2006-06-27 20:44:27.000000000 +0200
@@ -77,7 +77,8 @@
down(&big_buffer_sem);
- bcm43xx_lock_irqsafe(bcm, flags);
+ mutex_lock(&bcm->mutex);
+ spin_lock_irqsave(&bcm->irq_lock, flags);
if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) {
fappend("Board not initialized.\n");
goto out;
@@ -121,7 +122,8 @@
fappend("\n");
out:
- bcm43xx_unlock_irqsafe(bcm, flags);
+ spin_unlock_irqrestore(&bcm->irq_lock, flags);
+ mutex_unlock(&bcm->mutex);
res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
up(&big_buffer_sem);
return res;
@@ -159,7 +161,8 @@
unsigned long flags;
down(&big_buffer_sem);
- bcm43xx_lock_irqsafe(bcm, flags);
+ mutex_lock(&bcm->mutex);
+ spin_lock_irqsave(&bcm->irq_lock, flags);
if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) {
fappend("Board not initialized.\n");
goto out;
@@ -169,7 +172,8 @@
fappend("boardflags: 0x%04x\n", bcm->sprom.boardflags);
out:
- bcm43xx_unlock_irqsafe(bcm, flags);
+ spin_unlock_irqrestore(&bcm->irq_lock, flags);
+ mutex_unlock(&bcm->mutex);
res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
up(&big_buffer_sem);
return res;
@@ -188,7 +192,8 @@
u64 tsf;
down(&big_buffer_sem);
- bcm43xx_lock_irqsafe(bcm, flags);
+ mutex_lock(&bcm->mutex);
+ spin_lock_irqsave(&bcm->irq_lock, flags);
if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) {
fappend("Board not initialized.\n");
goto out;
@@ -199,7 +204,8 @@
(unsigned int)(tsf & 0xFFFFFFFFULL));
out:
- bcm43xx_unlock_irqsafe(bcm, flags);
+ spin_unlock_irqrestore(&bcm->irq_lock, flags);
+ mutex_unlock(&bcm->mutex);
res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
up(&big_buffer_sem);
return res;
@@ -221,7 +227,8 @@
res = -EFAULT;
goto out_up;
}
- bcm43xx_lock_irqsafe(bcm, flags);
+ mutex_lock(&bcm->mutex);
+ spin_lock_irqsave(&bcm->irq_lock, flags);
if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) {
printk(KERN_INFO PFX "debugfs: Board not initialized.\n");
res = -EFAULT;
@@ -237,7 +244,8 @@
res = buf_size;
out_unlock:
- bcm43xx_unlock_irqsafe(bcm, flags);
+ spin_unlock_irqrestore(&bcm->irq_lock, flags);
+ mutex_unlock(&bcm->mutex);
out_up:
up(&big_buffer_sem);
return res;
@@ -258,7 +266,8 @@
int i, cnt, j = 0;
down(&big_buffer_sem);
- bcm43xx_lock_irqsafe(bcm, flags);
+ mutex_lock(&bcm->mutex);
+ spin_lock_irqsave(&bcm->irq_lock, flags);
fappend("Last %d logged xmitstatus blobs (Latest first):\n\n",
BCM43xx_NR_LOGGED_XMITSTATUS);
@@ -294,14 +303,15 @@
i = BCM43xx_NR_LOGGED_XMITSTATUS - 1;
}
- bcm43xx_unlock_irqsafe(bcm, flags);
+ spin_unlock_irqrestore(&bcm->irq_lock, flags);
res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
- bcm43xx_lock_irqsafe(bcm, flags);
+ spin_lock_irqsave(&bcm->irq_lock, flags);
if (*ppos == pos) {
/* Done. Drop the copied data. */
e->xmitstatus_printing = 0;
}
- bcm43xx_unlock_irqsafe(bcm, flags);
+ spin_unlock_irqrestore(&bcm->irq_lock, flags);
+ mutex_unlock(&bcm->mutex);
up(&big_buffer_sem);
return res;
}
Index: wireless-2.6/drivers/net/wireless/bcm43xx/bcm43xx_leds.c
===================================================================
--- wireless-2.6.orig/drivers/net/wireless/bcm43xx/bcm43xx_leds.c 2006-06-24 22:13:44.000000000 +0200
+++ wireless-2.6/drivers/net/wireless/bcm43xx/bcm43xx_leds.c 2006-06-27 20:44:27.000000000 +0200
@@ -51,12 +51,12 @@
struct bcm43xx_private *bcm = led->bcm;
unsigned long flags;
- bcm43xx_lock_irqonly(bcm, flags);
+ spin_lock_irqsave(&bcm->leds_lock, flags);
if (led->blink_interval) {
bcm43xx_led_changestate(led);
mod_timer(&led->blink_timer, jiffies + led->blink_interval);
}
- bcm43xx_unlock_irqonly(bcm, flags);
+ spin_unlock_irqrestore(&bcm->leds_lock, flags);
}
static void bcm43xx_led_blink_start(struct bcm43xx_led *led,
@@ -177,7 +177,9 @@
int i, turn_on;
unsigned long interval = 0;
u16 ledctl;
+ unsigned long flags;
+ spin_lock_irqsave(&bcm->leds_lock, flags);
ledctl = bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_CONTROL);
for (i = 0; i < BCM43xx_NR_LEDS; i++) {
led = &(bcm->leds[i]);
@@ -266,6 +268,7 @@
ledctl &= ~(1 << i);
}
bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_CONTROL, ledctl);
+ spin_unlock_irqrestore(&bcm->leds_lock, flags);
}
void bcm43xx_leds_switch_all(struct bcm43xx_private *bcm, int on)
@@ -274,7 +277,9 @@
u16 ledctl;
int i;
int bit_on;
+ unsigned long flags;
+ spin_lock_irqsave(&bcm->leds_lock, flags);
ledctl = bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_CONTROL);
for (i = 0; i < BCM43xx_NR_LEDS; i++) {
led = &(bcm->leds[i]);
@@ -290,4 +295,5 @@
ledctl &= ~(1 << i);
}
bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_CONTROL, ledctl);
+ spin_unlock_irqrestore(&bcm->leds_lock, flags);
}
Index: wireless-2.6/drivers/net/wireless/bcm43xx/bcm43xx_main.c
===================================================================
--- wireless-2.6.orig/drivers/net/wireless/bcm43xx/bcm43xx_main.c 2006-06-27 20:41:18.000000000 +0200
+++ wireless-2.6/drivers/net/wireless/bcm43xx/bcm43xx_main.c 2006-06-27 21:21:17.000000000 +0200
@@ -514,13 +514,13 @@
unsigned long flags;
u32 old;
- bcm43xx_lock_irqonly(bcm, flags);
+ spin_lock_irqsave(&bcm->irq_lock, flags);
if (unlikely(bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED)) {
- bcm43xx_unlock_irqonly(bcm, flags);
+ spin_unlock_irqrestore(&bcm->irq_lock, flags);
return -EBUSY;
}
old = bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
- bcm43xx_unlock_irqonly(bcm, flags);
+ spin_unlock_irqrestore(&bcm->irq_lock, flags);
bcm43xx_synchronize_irq(bcm);
if (oldstate)
@@ -1720,7 +1720,7 @@
# define bcmirq_handled(irq) do { /* nothing */ } while (0)
#endif /* CONFIG_BCM43XX_DEBUG*/
- bcm43xx_lock_irqonly(bcm, flags);
+ spin_lock_irqsave(&bcm->irq_lock, flags);
reason = bcm->irq_reason;
dma_reason[0] = bcm->dma_reason[0];
dma_reason[1] = bcm->dma_reason[1];
@@ -1746,7 +1746,7 @@
dma_reason[2], dma_reason[3]);
bcm43xx_controller_restart(bcm, "DMA error");
mmiowb();
- bcm43xx_unlock_irqonly(bcm, flags);
+ spin_unlock_irqrestore(&bcm->irq_lock, flags);
return;
}
if (unlikely((dma_reason[0] & BCM43xx_DMAIRQ_NONFATALMASK) |
@@ -1834,7 +1834,7 @@
bcm43xx_leds_update(bcm, activity);
bcm43xx_interrupt_enable(bcm, bcm->irq_savedstate);
mmiowb();
- bcm43xx_unlock_irqonly(bcm, flags);
+ spin_unlock_irqrestore(&bcm->irq_lock, flags);
}
static void pio_irq_workaround(struct bcm43xx_private *bcm,
@@ -3193,25 +3193,26 @@
*/
netif_stop_queue(bcm->net_dev);
synchronize_net();
- bcm43xx_lock_irqonly(bcm, flags);
+ spin_lock_irqsave(&bcm->irq_lock, flags);
bcm43xx_mac_suspend(bcm);
if (bcm43xx_using_pio(bcm))
bcm43xx_pio_freeze_txqueues(bcm);
savedirqs = bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
- bcm43xx_unlock_irqonly(bcm, flags);
- bcm43xx_lock_noirq(bcm);
+ spin_unlock_irqrestore(&bcm->irq_lock, flags);
+ mutex_lock(&bcm->mutex);
bcm43xx_synchronize_irq(bcm);
} else {
/* Periodic work should take short time, so we want low
* locking overhead.
*/
- bcm43xx_lock_irqsafe(bcm, flags);
+ mutex_lock(&bcm->mutex);
+ spin_lock_irqsave(&bcm->irq_lock, flags);
}
do_periodic_work(bcm);
if (badness > BADNESS_LIMIT) {
- bcm43xx_lock_irqonly(bcm, flags);
+ spin_lock_irqsave(&bcm->irq_lock, flags);
if (likely(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED)) {
tasklet_enable(&bcm->isr_tasklet);
bcm43xx_interrupt_enable(bcm, savedirqs);
@@ -3220,13 +3221,10 @@
bcm43xx_mac_enable(bcm);
}
netif_wake_queue(bcm->net_dev);
- mmiowb();
- bcm43xx_unlock_irqonly(bcm, flags);
- bcm43xx_unlock_noirq(bcm);
- } else {
- mmiowb();
- bcm43xx_unlock_irqsafe(bcm, flags);
}
+ mmiowb();
+ spin_unlock_irqrestore(&bcm->irq_lock, flags);
+ mutex_unlock(&bcm->mutex);
}
static void bcm43xx_periodic_tasks_delete(struct bcm43xx_private *bcm)
@@ -3255,7 +3253,7 @@
{
int i, err;
- bcm43xx_lock_noirq(bcm);
+ mutex_lock(&bcm->mutex);
bcm43xx_sysfs_unregister(bcm);
bcm43xx_periodic_tasks_delete(bcm);
@@ -3275,7 +3273,7 @@
bcm43xx_pctl_set_crystal(bcm, 0);
bcm43xx_set_status(bcm, BCM43xx_STAT_UNINIT);
- bcm43xx_unlock_noirq(bcm);
+ mutex_unlock(&bcm->mutex);
}
static int bcm43xx_init_board(struct bcm43xx_private *bcm)
@@ -3285,7 +3283,7 @@
might_sleep();
- bcm43xx_lock_noirq(bcm);
+ mutex_lock(&bcm->mutex);
bcm43xx_set_status(bcm, BCM43xx_STAT_INITIALIZING);
err = bcm43xx_pctl_set_crystal(bcm, 1);
@@ -3364,7 +3362,7 @@
assert(err == 0);
out:
- bcm43xx_unlock_noirq(bcm);
+ mutex_unlock(&bcm->mutex);
return err;
@@ -3622,7 +3620,8 @@
struct bcm43xx_radioinfo *radio;
unsigned long flags;
- bcm43xx_lock_irqsafe(bcm, flags);
+ mutex_lock(&bcm->mutex);
+ spin_lock_irqsave(&bcm->irq_lock, flags);
if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) {
bcm43xx_mac_suspend(bcm);
bcm43xx_radio_selectchannel(bcm, channel, 0);
@@ -3631,7 +3630,8 @@
radio = bcm43xx_current_radio(bcm);
radio->initial_channel = channel;
}
- bcm43xx_unlock_irqsafe(bcm, flags);
+ spin_unlock_irqrestore(&bcm->irq_lock, flags);
+ mutex_unlock(&bcm->mutex);
}
/* set_security() callback in struct ieee80211_device */
@@ -3645,7 +3645,8 @@
dprintk(KERN_INFO PFX "set security called");
- bcm43xx_lock_irqsafe(bcm, flags);
+ mutex_lock(&bcm->mutex);
+ spin_lock_irqsave(&bcm->irq_lock, flags);
for (keyidx = 0; keyidx<WEP_KEYS; keyidx++)
if (sec->flags & (1<<keyidx)) {
@@ -3714,7 +3715,8 @@
} else
bcm43xx_clear_keys(bcm);
}
- bcm43xx_unlock_irqsafe(bcm, flags);
+ spin_unlock_irqrestore(&bcm->irq_lock, flags);
+ mutex_unlock(&bcm->mutex);
}
/* hard_start_xmit() callback in struct ieee80211_device */
@@ -3726,10 +3728,10 @@
int err = -ENODEV;
unsigned long flags;
- bcm43xx_lock_irqonly(bcm, flags);
+ spin_lock_irqsave(&bcm->irq_lock, flags);
if (likely(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED))
err = bcm43xx_tx(bcm, txb);
- bcm43xx_unlock_irqonly(bcm, flags);
+ spin_unlock_irqrestore(&bcm->irq_lock, flags);
return err;
}
@@ -3744,9 +3746,9 @@
struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
unsigned long flags;
- bcm43xx_lock_irqonly(bcm, flags);
+ spin_lock_irqsave(&bcm->irq_lock, flags);
bcm43xx_controller_restart(bcm, "TX timeout");
- bcm43xx_unlock_irqonly(bcm, flags);
+ spin_unlock_irqrestore(&bcm->irq_lock, flags);
}
#ifdef CONFIG_NET_POLL_CONTROLLER
@@ -3798,6 +3800,7 @@
bcm->net_dev = net_dev;
bcm->bad_frames_preempt = modparam_bad_frames_preempt;
spin_lock_init(&bcm->irq_lock);
+ spin_lock_init(&bcm->leds_lock);
mutex_init(&bcm->mutex);
tasklet_init(&bcm->isr_tasklet,
(void (*)(unsigned long))bcm43xx_interrupt_tasklet,
@@ -3978,16 +3981,13 @@
{
struct net_device *net_dev = pci_get_drvdata(pdev);
struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
- unsigned long flags;
int try_to_shutdown = 0, err;
dprintk(KERN_INFO PFX "Suspending...\n");
- bcm43xx_lock_irqsafe(bcm, flags);
bcm->was_initialized = (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED);
if (bcm->was_initialized)
try_to_shutdown = 1;
- bcm43xx_unlock_irqsafe(bcm, flags);
netif_device_detach(net_dev);
if (try_to_shutdown) {
Index: wireless-2.6/drivers/net/wireless/bcm43xx/bcm43xx_pio.c
===================================================================
--- wireless-2.6.orig/drivers/net/wireless/bcm43xx/bcm43xx_pio.c 2006-06-24 22:13:44.000000000 +0200
+++ wireless-2.6/drivers/net/wireless/bcm43xx/bcm43xx_pio.c 2006-06-27 20:44:28.000000000 +0200
@@ -262,7 +262,7 @@
int err;
u16 txctl;
- bcm43xx_lock_irqonly(bcm, flags);
+ spin_lock_irqsave(&bcm->irq_lock, flags);
if (queue->tx_frozen)
goto out_unlock;
@@ -300,7 +300,7 @@
continue;
}
out_unlock:
- bcm43xx_unlock_irqonly(bcm, flags);
+ spin_unlock_irqrestore(&bcm->irq_lock, flags);
}
static void setup_txqueues(struct bcm43xx_pioqueue *queue)
Index: wireless-2.6/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c
===================================================================
--- wireless-2.6.orig/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c 2006-06-24 22:13:44.000000000 +0200
+++ wireless-2.6/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c 2006-06-27 20:44:28.000000000 +0200
@@ -120,12 +120,14 @@
GFP_KERNEL);
if (!sprom)
return -ENOMEM;
- bcm43xx_lock_irqsafe(bcm, flags);
+ mutex_lock(&bcm->mutex);
+ spin_lock_irqsave(&bcm->irq_lock, flags);
err = bcm43xx_sprom_read(bcm, sprom);
if (!err)
err = sprom2hex(sprom, buf, PAGE_SIZE);
mmiowb();
- bcm43xx_unlock_irqsafe(bcm, flags);
+ spin_unlock_irqrestore(&bcm->irq_lock, flags);
+ mutex_unlock(&bcm->mutex);
kfree(sprom);
return err;
@@ -150,10 +152,14 @@
err = hex2sprom(sprom, buf, count);
if (err)
goto out_kfree;
- bcm43xx_lock_irqsafe(bcm, flags);
+ mutex_lock(&bcm->mutex);
+ spin_lock_irqsave(&bcm->irq_lock, flags);
+ spin_lock(&bcm->leds_lock);
err = bcm43xx_sprom_write(bcm, sprom);
mmiowb();
- bcm43xx_unlock_irqsafe(bcm, flags);
+ spin_unlock(&bcm->leds_lock);
+ spin_unlock_irqrestore(&bcm->irq_lock, flags);
+ mutex_unlock(&bcm->mutex);
out_kfree:
kfree(sprom);
@@ -176,7 +182,7 @@
if (!capable(CAP_NET_ADMIN))
return -EPERM;
- bcm43xx_lock_noirq(bcm);
+ mutex_lock(&bcm->mutex);
switch (bcm43xx_current_radio(bcm)->interfmode) {
case BCM43xx_RADIO_INTERFMODE_NONE:
@@ -193,7 +199,7 @@
}
err = 0;
- bcm43xx_unlock_noirq(bcm);
+ mutex_unlock(&bcm->mutex);
return err ? err : count;
@@ -229,7 +235,8 @@
return -EINVAL;
}
- bcm43xx_lock_irqsafe(bcm, flags);
+ mutex_lock(&bcm->mutex);
+ spin_lock_irqsave(&bcm->irq_lock, flags);
err = bcm43xx_radio_set_interference_mitigation(bcm, mode);
if (err) {
@@ -237,7 +244,8 @@
"supported by device\n");
}
mmiowb();
- bcm43xx_unlock_irqsafe(bcm, flags);
+ spin_unlock_irqrestore(&bcm->irq_lock, flags);
+ mutex_unlock(&bcm->mutex);
return err ? err : count;
}
@@ -257,7 +265,7 @@
if (!capable(CAP_NET_ADMIN))
return -EPERM;
- bcm43xx_lock_noirq(bcm);
+ mutex_lock(&bcm->mutex);
if (bcm->short_preamble)
count = snprintf(buf, PAGE_SIZE, "1 (Short Preamble enabled)\n");
@@ -265,7 +273,7 @@
count = snprintf(buf, PAGE_SIZE, "0 (Short Preamble disabled)\n");
err = 0;
- bcm43xx_unlock_noirq(bcm);
+ mutex_unlock(&bcm->mutex);
return err ? err : count;
}
@@ -285,12 +293,14 @@
value = get_boolean(buf, count);
if (value < 0)
return value;
- bcm43xx_lock_irqsafe(bcm, flags);
+ mutex_lock(&bcm->mutex);
+ spin_lock_irqsave(&bcm->irq_lock, flags);
bcm->short_preamble = !!value;
err = 0;
- bcm43xx_unlock_irqsafe(bcm, flags);
+ spin_unlock_irqrestore(&bcm->irq_lock, flags);
+ mutex_unlock(&bcm->mutex);
return err ? err : count;
}
Index: wireless-2.6/drivers/net/wireless/bcm43xx/bcm43xx_wx.c
===================================================================
--- wireless-2.6.orig/drivers/net/wireless/bcm43xx/bcm43xx_wx.c 2006-06-27 17:47:24.000000000 +0200
+++ wireless-2.6/drivers/net/wireless/bcm43xx/bcm43xx_wx.c 2006-06-27 21:36:31.000000000 +0200
@@ -56,12 +56,11 @@
{
struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
int i;
- unsigned long flags;
struct bcm43xx_phyinfo *phy;
char suffix[7] = { 0 };
int have_a = 0, have_b = 0, have_g = 0;
- bcm43xx_lock_irqsafe(bcm, flags);
+ mutex_lock(&bcm->mutex);
for (i = 0; i < bcm->nr_80211_available; i++) {
phy = &(bcm->core_80211_ext[i].phy);
switch (phy->type) {
@@ -77,7 +76,7 @@
assert(0);
}
}
- bcm43xx_unlock_irqsafe(bcm, flags);
+ mutex_unlock(&bcm->mutex);
i = 0;
if (have_a) {
@@ -111,7 +110,9 @@
int freq;
int err = -EINVAL;
- bcm43xx_lock_irqsafe(bcm, flags);
+ mutex_lock(&bcm->mutex);
+ spin_lock_irqsave(&bcm->irq_lock, flags);
+
if ((data->freq.m >= 0) && (data->freq.m <= 1000)) {
channel = data->freq.m;
freq = bcm43xx_channel_to_freq(bcm, channel);
@@ -131,7 +132,8 @@
err = 0;
}
out_unlock:
- bcm43xx_unlock_irqsafe(bcm, flags);
+ spin_unlock_irqrestore(&bcm->irq_lock, flags);
+ mutex_unlock(&bcm->mutex);
return err;
}
@@ -143,11 +145,10 @@
{
struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
struct bcm43xx_radioinfo *radio;
- unsigned long flags;
int err = -ENODEV;
u16 channel;
- bcm43xx_lock_irqsafe(bcm, flags);
+ mutex_lock(&bcm->mutex);
radio = bcm43xx_current_radio(bcm);
channel = radio->channel;
if (channel == 0xFF) {
@@ -162,7 +163,7 @@
err = 0;
out_unlock:
- bcm43xx_unlock_irqsafe(bcm, flags);
+ mutex_unlock(&bcm->mutex);
return err;
}
@@ -180,13 +181,15 @@
if (mode == IW_MODE_AUTO)
mode = BCM43xx_INITIAL_IWMODE;
- bcm43xx_lock_irqsafe(bcm, flags);
+ mutex_lock(&bcm->mutex);
+ spin_lock_irqsave(&bcm->irq_lock, flags);
if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) {
if (bcm->ieee->iw_mode != mode)
bcm43xx_set_iwmode(bcm, mode);
} else
bcm->ieee->iw_mode = mode;
- bcm43xx_unlock_irqsafe(bcm, flags);
+ spin_unlock_irqrestore(&bcm->irq_lock, flags);
+ mutex_unlock(&bcm->mutex);
return 0;
}
@@ -197,11 +200,10 @@
char *extra)
{
struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
- unsigned long flags;
- bcm43xx_lock_irqsafe(bcm, flags);
+ mutex_lock(&bcm->mutex);
data->mode = bcm->ieee->iw_mode;
- bcm43xx_unlock_irqsafe(bcm, flags);
+ mutex_unlock(&bcm->mutex);
return 0;
}
@@ -214,7 +216,6 @@
struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
struct iw_range *range = (struct iw_range *)extra;
const struct ieee80211_geo *geo;
- unsigned long flags;
int i, j;
struct bcm43xx_phyinfo *phy;
@@ -254,7 +255,7 @@
IW_ENC_CAPA_CIPHER_TKIP |
IW_ENC_CAPA_CIPHER_CCMP;
- bcm43xx_lock_irqsafe(bcm, flags);
+ mutex_lock(&bcm->mutex);
phy = bcm43xx_current_phy(bcm);
range->num_bitrates = 0;
@@ -301,7 +302,7 @@
}
range->num_frequency = j;
- bcm43xx_unlock_irqsafe(bcm, flags);
+ mutex_unlock(&bcm->mutex);
return 0;
}
@@ -314,11 +315,11 @@
struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
size_t len;
- bcm43xx_lock_noirq(bcm);
+ mutex_lock(&bcm->mutex);
len = min((size_t)data->data.length, (size_t)IW_ESSID_MAX_SIZE);
memcpy(bcm->nick, extra, len);
bcm->nick[len] = '\0';
- bcm43xx_unlock_noirq(bcm);
+ mutex_unlock(&bcm->mutex);
return 0;
}
@@ -331,12 +332,12 @@
struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
size_t len;
- bcm43xx_lock_noirq(bcm);
+ mutex_lock(&bcm->mutex);
len = strlen(bcm->nick) + 1;
memcpy(extra, bcm->nick, len);
data->data.length = (__u16)len;
data->data.flags = 1;
- bcm43xx_unlock_noirq(bcm);
+ mutex_unlock(&bcm->mutex);
return 0;
}
@@ -350,7 +351,8 @@
unsigned long flags;
int err = -EINVAL;
- bcm43xx_lock_irqsafe(bcm, flags);
+ mutex_lock(&bcm->mutex);
+ spin_lock_irqsave(&bcm->irq_lock, flags);
if (data->rts.disabled) {
bcm->rts_threshold = BCM43xx_MAX_RTS_THRESHOLD;
err = 0;
@@ -361,7 +363,8 @@
err = 0;
}
}
- bcm43xx_unlock_irqsafe(bcm, flags);
+ spin_unlock_irqrestore(&bcm->irq_lock, flags);
+ mutex_unlock(&bcm->mutex);
return err;
}
@@ -372,13 +375,12 @@
char *extra)
{
struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
- unsigned long flags;
- bcm43xx_lock_irqsafe(bcm, flags);
+ mutex_lock(&bcm->mutex);
data->rts.value = bcm->rts_threshold;
data->rts.fixed = 0;
data->rts.disabled = (bcm->rts_threshold == BCM43xx_MAX_RTS_THRESHOLD);
- bcm43xx_unlock_irqsafe(bcm, flags);
+ mutex_unlock(&bcm->mutex);
return 0;
}
@@ -392,7 +394,8 @@
unsigned long flags;
int err = -EINVAL;
- bcm43xx_lock_irqsafe(bcm, flags);
+ mutex_lock(&bcm->mutex);
+ spin_lock_irqsave(&bcm->irq_lock, flags);
if (data->frag.disabled) {
bcm->ieee->fts = MAX_FRAG_THRESHOLD;
err = 0;
@@ -403,7 +406,8 @@
err = 0;
}
}
- bcm43xx_unlock_irqsafe(bcm, flags);
+ spin_unlock_irqrestore(&bcm->irq_lock, flags);
+ mutex_unlock(&bcm->mutex);
return err;
}
@@ -414,13 +418,12 @@
char *extra)
{
struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
- unsigned long flags;
- bcm43xx_lock_irqsafe(bcm, flags);
+ mutex_lock(&bcm->mutex);
data->frag.value = bcm->ieee->fts;
data->frag.fixed = 0;
data->frag.disabled = (bcm->ieee->fts == MAX_FRAG_THRESHOLD);
- bcm43xx_unlock_irqsafe(bcm, flags);
+ mutex_unlock(&bcm->mutex);
return 0;
}
@@ -442,7 +445,8 @@
return -EOPNOTSUPP;
}
- bcm43xx_lock_irqsafe(bcm, flags);
+ mutex_lock(&bcm->mutex);
+ spin_lock_irqsave(&bcm->irq_lock, flags);
if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED)
goto out_unlock;
radio = bcm43xx_current_radio(bcm);
@@ -466,7 +470,8 @@
err = 0;
out_unlock:
- bcm43xx_unlock_irqsafe(bcm, flags);
+ spin_unlock_irqrestore(&bcm->irq_lock, flags);
+ mutex_unlock(&bcm->mutex);
return err;
}
@@ -478,10 +483,9 @@
{
struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
struct bcm43xx_radioinfo *radio;
- unsigned long flags;
int err = -ENODEV;
- bcm43xx_lock_irqsafe(bcm, flags);
+ mutex_lock(&bcm->mutex);
if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED)
goto out_unlock;
radio = bcm43xx_current_radio(bcm);
@@ -493,7 +497,7 @@
err = 0;
out_unlock:
- bcm43xx_unlock_irqsafe(bcm, flags);
+ mutex_unlock(&bcm->mutex);
return err;
}
@@ -580,7 +584,8 @@
return -EINVAL;
}
- bcm43xx_lock_irqsafe(bcm, flags);
+ mutex_lock(&bcm->mutex);
+ spin_lock_irqsave(&bcm->irq_lock, flags);
if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) {
err = bcm43xx_radio_set_interference_mitigation(bcm, mode);
if (err) {
@@ -595,7 +600,8 @@
} else
bcm43xx_current_radio(bcm)->interfmode = mode;
}
- bcm43xx_unlock_irqsafe(bcm, flags);
+ spin_unlock_irqrestore(&bcm->irq_lock, flags);
+ mutex_unlock(&bcm->mutex);
return err;
}
@@ -606,12 +612,11 @@
char *extra)
{
struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
- unsigned long flags;
int mode;
- bcm43xx_lock_irqsafe(bcm, flags);
+ mutex_lock(&bcm->mutex);
mode = bcm43xx_current_radio(bcm)->interfmode;
- bcm43xx_unlock_irqsafe(bcm, flags);
+ mutex_unlock(&bcm->mutex);
switch (mode) {
case BCM43xx_RADIO_INTERFMODE_NONE:
@@ -641,9 +646,11 @@
int on;
on = *((int *)extra);
- bcm43xx_lock_irqsafe(bcm, flags);
+ mutex_lock(&bcm->mutex);
+ spin_lock_irqsave(&bcm->irq_lock, flags);
bcm->short_preamble = !!on;
- bcm43xx_unlock_irqsafe(bcm, flags);
+ spin_unlock_irqrestore(&bcm->irq_lock, flags);
+ mutex_unlock(&bcm->mutex);
return 0;
}
@@ -654,12 +661,11 @@
char *extra)
{
struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
- unsigned long flags;
int on;
- bcm43xx_lock_irqsafe(bcm, flags);
+ mutex_lock(&bcm->mutex);
on = bcm->short_preamble;
- bcm43xx_unlock_irqsafe(bcm, flags);
+ mutex_unlock(&bcm->mutex);
if (on)
strncpy(extra, "1 (Short Preamble enabled)", MAX_WX_STRING);
@@ -681,11 +687,13 @@
on = *((int *)extra);
- bcm43xx_lock_irqsafe(bcm, flags);
+ mutex_lock(&bcm->mutex);
+ spin_lock_irqsave(&bcm->irq_lock, flags);
bcm->ieee->host_encrypt = !!on;
bcm->ieee->host_decrypt = !!on;
bcm->ieee->host_build_iv = !on;
- bcm43xx_unlock_irqsafe(bcm, flags);
+ spin_unlock_irqrestore(&bcm->irq_lock, flags);
+ mutex_unlock(&bcm->mutex);
return 0;
}
@@ -696,12 +704,11 @@
char *extra)
{
struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
- unsigned long flags;
int on;
- bcm43xx_lock_irqsafe(bcm, flags);
+ mutex_lock(&bcm->mutex);
on = bcm->ieee->host_encrypt;
- bcm43xx_unlock_irqsafe(bcm, flags);
+ mutex_unlock(&bcm->mutex);
if (on)
strncpy(extra, "1 (SW encryption enabled) ", MAX_WX_STRING);
@@ -764,11 +771,13 @@
if (!sprom)
goto out;
- bcm43xx_lock_irqsafe(bcm, flags);
+ mutex_lock(&bcm->mutex);
+ spin_lock_irqsave(&bcm->irq_lock, flags);
err = -ENODEV;
if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED)
err = bcm43xx_sprom_read(bcm, sprom);
- bcm43xx_unlock_irqsafe(bcm, flags);
+ spin_unlock_irqrestore(&bcm->irq_lock, flags);
+ mutex_unlock(&bcm->mutex);
if (!err)
data->data.length = sprom2hex(sprom, extra);
kfree(sprom);
@@ -809,11 +818,15 @@
if (err)
goto out_kfree;
- bcm43xx_lock_irqsafe(bcm, flags);
+ mutex_lock(&bcm->mutex);
+ spin_lock_irqsave(&bcm->irq_lock, flags);
+ spin_lock(&bcm->leds_lock);
err = -ENODEV;
if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED)
err = bcm43xx_sprom_write(bcm, sprom);
- bcm43xx_unlock_irqsafe(bcm, flags);
+ spin_unlock(&bcm->leds_lock);
+ spin_unlock_irqrestore(&bcm->irq_lock, flags);
+ mutex_unlock(&bcm->mutex);
out_kfree:
kfree(sprom);
out:
--
Greetings Michael.
^ permalink raw reply
* Re: Please pull 'upstream' branch of wireless-2.6
From: John W. Linville @ 2006-06-27 19:33 UTC (permalink / raw)
To: Michael Buesch; +Cc: Jeff Garzik, bcm43xx-dev, Larry Finger, netdev
In-Reply-To: <200606271831.02108.mb@bu3sch.de>
On Tue, Jun 27, 2006 at 06:31:01PM +0200, Michael Buesch wrote:
> On Tuesday 27 June 2006 18:12, Jeff Garzik wrote:
> > Michael Buesch wrote:
> > > So, I will submit a patch to lower the udelay(10) to udelay(1)
> > > and we can close the discussion? ;)
> >
> > No, that totally avoids my point. Your "otherwise idle machine" test is
> > probably nowhere near worst case in the field, for loops that can
> > potentially lock the CPU for a long time upon hardware fault. And then
> > there are the huge delays in specific functions that I pointed out...
>
> wtf are you requesting from me?
> 1) I proved you that the loop does only spin _once_ or even _less_.
> 2) If the hardware is faulty, the user must replace it.
> Because, if the hardware is faulty, it can crash the whole
> machine anyway, obviously.
>
> 3) There is no "huge delay". I proved it with my logs.
> -> No CPU hog => Nothing to fix.
Michael,
I think Jeff's concern is that by using udelay you are busy-waiting.
And, the for loop limit of 100000 means you could freeze the kernel
for up to a whole second. Granted that this won't happen very often
and in the grand scheme of things a second isn't all _that_ long,
but still it would be better to avoid a delay like that -- a second
could be the time it takes to avoid a meltdown at the nuclear power
plant. :-)
Could you not use msleep instead of udelay (and scale the for loop
appropriately)? What would be the problem with that? It would get
rid of the busy waiting.
To be fair, this code was already in the driver and was only being
moved by this patch. Still, what better time to fix it than now? :-)
I'll go ahead and reshuffle wireless-2.6 to drop this patch. A new
patch that passes muster w/ Jeff will be most welcome! :-)
Thanks,
John
--
John W. Linville
linville@tuxdriver.com
^ permalink raw reply
* Re: tg3 driver and interrupt coalescence questions
From: Chris A. Icide @ 2006-06-27 18:55 UTC (permalink / raw)
To: Rick Jones; +Cc: netdev
In-Reply-To: <44A17A13.8090704@hp.com>
Rick Jones wrote:
>
> Are you looking to increase or decrease the settings? I would think
> (initially at least) that for VOIP one might not want to increase them.
>
> rick jones
I'm looking to decrease the interrupt load on the system. During the
test I mentioned above I had some interesting and confusing results.
The changes from the default settings to the settings I posted resulted
in a 100% performance increase (counted by the number of VoIP audio
streams the tested server could support). With default settings one of
the two CPUs in the system maxed out at 99% cpu usage handling
interrupts, while the second CPU was not maxed out, but we started to
drop packets and the VoIP call setups started showing retransmits (which
is the measurement for failure in this test) at about 300 streams. With
the new settings we were able to hit 600 streams.
So I definately recognized a significant improvement. However I'd still
like to get more improvement. At 600 streams and 20ms packets we are
looking at 30,000 pps. The % of cpu (1 CPU as apparently the interrupts
can't be shared across multiple CPUs) used for interrupt handling at
this 600 stream limit was 88.0%.
Now what was interesting was on the test generation side (same hardware
exactly) of things, I was using the SIPP software to generate the VoIP
streams, and each blade in the blade server was only able to generate
~200 streams, with default settings in ethtool, one of the CPUs would
hit max usage for interrupt handling at that point. So I modified the
ethtool settings to match those I listed above and there was no
discernable difference. It was identical performance to the default
settings.
Michael's response clarified for me what the actual parameters in the -C
section of ethtool do, thanks Michael. However I';; be greatly
appreciative of any recommedations anyone might have for interrupt
mitigation settings for 100% UDP RTP traffic of 20ms packets (50 pps per
stream).
-Chris
^ permalink raw reply
* Re: tg3 driver and interrupt coalescence questions
From: Rick Jones @ 2006-06-27 18:33 UTC (permalink / raw)
To: Chris A. Icide; +Cc: netdev
In-Reply-To: <44A167EB.8000805@netgeeks.net>
Chris A. Icide wrote:
> I've been digging around trying to get some information on the
> current status of interrupt mitigation features for a Braodcom 5704 interface.
>
> Specifically I'm sending and receiving lots of VoIP packets (50 pps
> per stream, many streams).
>
> What I can't seem to determine is this:
>
> What version of the linux kernel & tg3 drivers are required to
> support both rx and tx mitigation?
> What do the ethtool coalescence settings actually do (I've not been
Delay interrupts and increase individual packet latency with the
intention being decreasing CPU utilization and allowing a higher
aggregate packet per second limit. IE bandwidth vs latency tradeoffs.
> able to find actual descriptions of the different parameters in the -C
> section)
> Is there anything special that needs to be done when compiling a
> kernel to enable this feature for both the kernel and the tg3 driver.
Are you looking to increase or decrease the settings? I would think
(initially at least) that for VOIP one might not want to increase them.
rick jones
^ 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