Netdev List
 help / color / mirror / Atom feed
* [PATCH net-next v2 3/4] ipv6: use net->rt_genid to check dst validity
From: Nicolas Dichtel @ 2012-09-10 13:22 UTC (permalink / raw)
  To: vyasevich, davem, eric.dumazet; +Cc: sri, linux-sctp, netdev, Nicolas Dichtel
In-Reply-To: <1347283338-4249-1-git-send-email-nicolas.dichtel@6wind.com>

IPv6 dst should take care of rt_genid too. When a xfrm policy is inserted or
deleted, all dst should be invalidated.
To force the validation, dst entries should be created with ->obsolete set to
DST_OBSOLETE_FORCE_CHK. This was already the case for all functions calling
ip6_dst_alloc(), except for ip6_rt_copy().

As a consequence, we can remove the specific code in inet6_connection_sock.

Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
---
 include/net/ip6_fib.h            |  2 +-
 net/ipv6/inet6_connection_sock.c | 23 +----------------------
 net/ipv6/route.c                 | 17 +++++++++++++----
 3 files changed, 15 insertions(+), 27 deletions(-)

diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h
index cd64cf3..5eb93f4 100644
--- a/include/net/ip6_fib.h
+++ b/include/net/ip6_fib.h
@@ -113,7 +113,7 @@ struct rt6_info {
 	unsigned long			_rt6i_peer;
 
 #ifdef CONFIG_XFRM
-	u32				rt6i_flow_cache_genid;
+	u32				rt6i_genid;
 #endif
 	/* more non-fragment space at head required */
 	unsigned short			rt6i_nfheader_len;
diff --git a/net/ipv6/inet6_connection_sock.c b/net/ipv6/inet6_connection_sock.c
index 0251a60..c4f9341 100644
--- a/net/ipv6/inet6_connection_sock.c
+++ b/net/ipv6/inet6_connection_sock.c
@@ -175,33 +175,12 @@ void __inet6_csk_dst_store(struct sock *sk, struct dst_entry *dst,
 			   const struct in6_addr *saddr)
 {
 	__ip6_dst_store(sk, dst, daddr, saddr);
-
-#ifdef CONFIG_XFRM
-	{
-		struct rt6_info *rt = (struct rt6_info  *)dst;
-		rt->rt6i_flow_cache_genid = atomic_read(&flow_cache_genid);
-	}
-#endif
 }
 
 static inline
 struct dst_entry *__inet6_csk_dst_check(struct sock *sk, u32 cookie)
 {
-	struct dst_entry *dst;
-
-	dst = __sk_dst_check(sk, cookie);
-
-#ifdef CONFIG_XFRM
-	if (dst) {
-		struct rt6_info *rt = (struct rt6_info *)dst;
-		if (rt->rt6i_flow_cache_genid != atomic_read(&flow_cache_genid)) {
-			__sk_dst_reset(sk);
-			dst = NULL;
-		}
-	}
-#endif
-
-	return dst;
+	return __sk_dst_check(sk, cookie);
 }
 
 static struct dst_entry *inet6_csk_route_socket(struct sock *sk,
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 339d921..db7b78f 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -281,13 +281,16 @@ static inline struct rt6_info *ip6_dst_alloc(struct net *net,
 					     struct fib6_table *table)
 {
 	struct rt6_info *rt = dst_alloc(&net->ipv6.ip6_dst_ops, dev,
-					0, DST_OBSOLETE_NONE, flags);
+					0, DST_OBSOLETE_FORCE_CHK, flags);
 
 	if (rt) {
 		struct dst_entry *dst = &rt->dst;
 
 		memset(dst + 1, 0, sizeof(*rt) - sizeof(*dst));
 		rt6_init_peer(rt, table ? &table->tb6_peers : net->ipv6.peers);
+#ifdef CONFIG_XFRM
+		rt->rt6i_genid = rt_genid(net);
+#endif
 	}
 	return rt;
 }
@@ -1031,6 +1034,15 @@ static struct dst_entry *ip6_dst_check(struct dst_entry *dst, u32 cookie)
 
 	rt = (struct rt6_info *) dst;
 
+	/* All IPV6 dsts are created with ->obsolete set to the value
+	 * DST_OBSOLETE_FORCE_CHK which forces validation calls down
+	 * into this function always.
+	 */
+#ifdef CONFIG_XFRM
+	if (rt->rt6i_genid != rt_genid(dev_net(rt->dst.dev)))
+		return NULL;
+#endif
+
 	if (rt->rt6i_node && (rt->rt6i_node->fn_sernum == cookie)) {
 		if (rt->rt6i_peer_genid != rt6_peer_genid()) {
 			if (!rt6_has_peer(rt))
@@ -1397,8 +1409,6 @@ int ip6_route_add(struct fib6_config *cfg)
 		goto out;
 	}
 
-	rt->dst.obsolete = -1;
-
 	if (cfg->fc_flags & RTF_EXPIRES)
 		rt6_set_expires(rt, jiffies +
 				clock_t_to_jiffies(cfg->fc_expires));
@@ -2093,7 +2103,6 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev,
 	rt->dst.input = ip6_input;
 	rt->dst.output = ip6_output;
 	rt->rt6i_idev = idev;
-	rt->dst.obsolete = -1;
 
 	rt->rt6i_flags = RTF_UP | RTF_NONEXTHOP;
 	if (anycast)
-- 
1.7.12

^ permalink raw reply related

* [PATCH net-next v2 2/4] xfrm: invalidate dst on policy insertion/deletion
From: Nicolas Dichtel @ 2012-09-10 13:22 UTC (permalink / raw)
  To: vyasevich, davem, eric.dumazet; +Cc: sri, linux-sctp, netdev, Nicolas Dichtel
In-Reply-To: <1347283338-4249-1-git-send-email-nicolas.dichtel@6wind.com>

When a policy is inserted or deleted, all dst should be recalculated.

Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
---
 net/xfrm/xfrm_policy.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 741a32a..67f456d 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -602,6 +602,7 @@ int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl)
 	xfrm_pol_hold(policy);
 	net->xfrm.policy_count[dir]++;
 	atomic_inc(&flow_cache_genid);
+	rt_genid_bump(net);
 	if (delpol)
 		__xfrm_policy_unlink(delpol, dir);
 	policy->index = delpol ? delpol->index : xfrm_gen_index(net, dir);
-- 
1.7.12

^ permalink raw reply related

* [PATCH net-next v2 1/4] netns: move net->ipv4.rt_genid to net->rt_genid
From: Nicolas Dichtel @ 2012-09-10 13:22 UTC (permalink / raw)
  To: vyasevich, davem, eric.dumazet; +Cc: sri, linux-sctp, netdev, Nicolas Dichtel
In-Reply-To: <1347283338-4249-1-git-send-email-nicolas.dichtel@6wind.com>

This commit prepares the use of rt_genid by both IPv4 and IPv6.
Initialization is left in IPv4 part.

Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
---
 include/net/net_namespace.h | 10 ++++++++++
 include/net/netns/ipv4.h    |  1 -
 net/ipv4/route.c            |  9 ++-------
 3 files changed, 12 insertions(+), 8 deletions(-)

diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
index 5ae57f1..037190a 100644
--- a/include/net/net_namespace.h
+++ b/include/net/net_namespace.h
@@ -107,6 +107,7 @@ struct net {
 #endif
 	struct netns_ipvs	*ipvs;
 	struct sock		*diag_nlsk;
+	atomic_t		rt_genid;
 };
 
 /*
@@ -312,5 +313,14 @@ static inline void unregister_net_sysctl_table(struct ctl_table_header *header)
 }
 #endif
 
+static inline int rt_genid(struct net *net)
+{
+	return atomic_read(&net->rt_genid);
+}
+
+static inline void rt_genid_bump(struct net *net)
+{
+	atomic_inc(&net->rt_genid);
+}
 
 #endif /* __NET_NET_NAMESPACE_H */
diff --git a/include/net/netns/ipv4.h b/include/net/netns/ipv4.h
index 7d00583..2ae2b83 100644
--- a/include/net/netns/ipv4.h
+++ b/include/net/netns/ipv4.h
@@ -64,7 +64,6 @@ struct netns_ipv4 {
 	kgid_t sysctl_ping_group_range[2];
 	long sysctl_tcp_mem[3];
 
-	atomic_t rt_genid;
 	atomic_t dev_addr_genid;
 
 #ifdef CONFIG_IP_MROUTE
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index d39edf1..8ff984b 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -202,11 +202,6 @@ EXPORT_SYMBOL(ip_tos2prio);
 static DEFINE_PER_CPU(struct rt_cache_stat, rt_cache_stat);
 #define RT_CACHE_STAT_INC(field) __this_cpu_inc(rt_cache_stat.field)
 
-static inline int rt_genid(struct net *net)
-{
-	return atomic_read(&net->ipv4.rt_genid);
-}
-
 #ifdef CONFIG_PROC_FS
 static void *rt_cache_seq_start(struct seq_file *seq, loff_t *pos)
 {
@@ -449,7 +444,7 @@ static inline bool rt_is_expired(const struct rtable *rth)
 
 void rt_cache_flush(struct net *net)
 {
-	atomic_inc(&net->ipv4.rt_genid);
+	rt_genid_bump(net);
 }
 
 static struct neighbour *ipv4_neigh_lookup(const struct dst_entry *dst,
@@ -2506,7 +2501,7 @@ static __net_initdata struct pernet_operations sysctl_route_ops = {
 
 static __net_init int rt_genid_init(struct net *net)
 {
-	atomic_set(&net->ipv4.rt_genid, 0);
+	atomic_set(&net->rt_genid, 0);
 	get_random_bytes(&net->ipv4.dev_addr_genid,
 			 sizeof(net->ipv4.dev_addr_genid));
 	return 0;
-- 
1.7.12

^ permalink raw reply related

* [PATCH net-next v2] Take care of xfrm policy when checking dst entries
From: Nicolas Dichtel @ 2012-09-10 13:22 UTC (permalink / raw)
  To: vyasevich, davem, eric.dumazet; +Cc: sri, linux-sctp, netdev
In-Reply-To: <20120907.144828.97793990734588625.davem@davemloft.net>

The goal of these patches is to fix the following problem: a session is
established (TCP, SCTP) and after a new policy is inserted. The current
code does not recalculate the route, thus the traffic is not encrypted.

The patch propose to check flow_cache_genid value when checking a dst
entry, which is incremented each time a policy is inserted or deleted.

v2: use net->ipv4.rt_genid instead of flow_cache_genid (and thus save a test
    in fast path). Also move it to net->rt_genid, to be able to use it for IPv6
    too. Note that IPv6 will have one more test in fast path.

Patches are tested with TCP and SCTP, IPv4 and IPv6.

Comments are welcome.

Regards,
Nicolas

^ permalink raw reply

* Re: [PATCH] net, cgroup: Fix boot failure due to iteration of uninitialized list
From: Neil Horman @ 2012-09-10 13:16 UTC (permalink / raw)
  To: Srivatsa S. Bhat
  Cc: Gao feng, eric.dumazet, davem, linux-kernel, netdev,
	mark.d.rustad, john.r.fastabend, lizefan
In-Reply-To: <504DB2EE.2030700@linux.vnet.ibm.com>

On Mon, Sep 10, 2012 at 02:59:18PM +0530, Srivatsa S. Bhat wrote:
> On 07/23/2012 05:10 PM, Neil Horman wrote:
> > On Mon, Jul 23, 2012 at 09:15:05AM +0800, Gao feng wrote:
> >> 于 2012年07月20日 00:27, Srivatsa S. Bhat 写道:
> >>> After commit ef209f15 (net: cgroup: fix access the unallocated memory in
> >>> netprio cgroup), boot fails with the following NULL pointer dereference:
> >>>
> [...]
> >>> Call Trace:
> >>>  [<ffffffff81b1cb78>] cgroup_init_subsys+0x83/0x169
> >>>  [<ffffffff81b1ce13>] cgroup_init+0x36/0x119
> >>>  [<ffffffff81affef7>] start_kernel+0x3ba/0x3ef
> >>>  [<ffffffff81aff95b>] ? kernel_init+0x27b/0x27b
> >>>  [<ffffffff81aff356>] x86_64_start_reservations+0x131/0x136
> >>>  [<ffffffff81aff45e>] x86_64_start_kernel+0x103/0x112
> >>> RIP  [<ffffffff8145e8d6>] cgrp_create+0xf6/0x190
> >>>  RSP <ffffffff81a01ea8>
> >>> CR2: 0000000000000698
> >>> ---[ end trace a7919e7f17c0a725 ]---
> >>> Kernel panic - not syncing: Attempted to kill the idle task!
> >>>
> >>> The code corresponds to:
> >>>
> >>> update_netdev_tables():
> >>>         for_each_netdev(&init_net, dev) {
> >>>                 map = rtnl_dereference(dev->priomap);  <---- HERE
> >>>
> >>>
> >>> The list head is initialized in netdev_init(), which is called much
> >>> later than cgrp_create(). So the problem is that we are calling
> >>> update_netdev_tables() way too early (in cgrp_create()), which will
> >>> end up traversing the not-yet-circular linked list. So at some point,
> >>> the dev pointer will become NULL and hence dev->priomap becomes an
> >>> invalid access.
> >>>
> >>> To fix this, just remove the update_netdev_tables() function entirely,
> >>> since it appears that write_update_netdev_table() will handle things
> >>> just fine.
> >>
> >> The reason I add update_netdev_tables in cgrp_create is to avoid additional
> >> bound checkings when we accessing the dev->priomap.priomap.
> >>
> >> Eric,can we revert this commit 91c68ce2b26319248a32d7baa1226f819d283758 now?
> >> I think it's safe enough to access priomap without bound check.
> >>
> > 
> > I think its probably safe, yes, but lets leave it there for just a bit.  Its not
> > hurting anything, and I'd like to look into getting Srivatsa' patch in first.
> 
> Hi Neil,
> 
> Did you get around to look into this again?
> 
I haven't looked at it specifically no, I apologize.  That said I think the
other changes that went in back in that time frame have had time to soak, and
looking at the way we current update the priomap table, I think its safe for us
to remove the update_netdev_table call and definition.  If you repost your
patch, I'll ack it. 

Thanks!
Neil

> Regards,
> Srivatsa S. Bhat
> 
> 

^ permalink raw reply

* Re: [PATCH 1/2] dst: take into account policy update on check()
From: Eric Dumazet @ 2012-09-10 13:10 UTC (permalink / raw)
  To: nicolas.dichtel; +Cc: David Miller, vyasevich, sri, linux-sctp, netdev
In-Reply-To: <504DE17A.1000908@6wind.com>

On Mon, 2012-09-10 at 14:47 +0200, Nicolas Dichtel wrote:

> So it means that IPv6 dst entries will be invalidated by IPv4 route management. 
> For example, calling rt_cache_flush() will flush IPv6 dst too. Is this acceptable?

If it can save another test in fast path, this is acceptable, yes.

^ permalink raw reply

* [PATCH 3/3] fib6: remove some useless empty lines and comments
From: Cong Wang @ 2012-09-10 12:48 UTC (permalink / raw)
  To: netdev; +Cc: David S. Miller, Cong Wang
In-Reply-To: <1347281326-26890-1-git-send-email-amwang@redhat.com>

There are too many empty lines in this source file,
remove the useless ones, together with some useless
comments.

Signed-off-by: Cong Wang <amwang@redhat.com>
---
 net/ipv6/ip6_fib.c |   78 +--------------------------------------------------
 1 files changed, 2 insertions(+), 76 deletions(-)

diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
index 13690d6..b4faf2d 100644
--- a/net/ipv6/ip6_fib.c
+++ b/net/ipv6/ip6_fib.c
@@ -88,7 +88,6 @@ static int fib6_walk_continue(struct fib6_walker_t *w);
  *	tested when modifications are made to the destination cache as a
  *	result of redirects, path MTU changes, etc.
  */
-
 static __u32 rt_sernum;
 
 static void fib6_gc_timer_cb(unsigned long arg);
@@ -123,10 +122,6 @@ static __inline__ u32 fib6_new_sernum(void)
  *	These assume a 32bit processor (although it will work on
  *	64bit processors)
  */
-
-/*
- *	test bit
- */
 #if defined(__LITTLE_ENDIAN)
 # define BITOP_BE32_SWIZZLE	(0x1F & ~7)
 #else
@@ -369,7 +364,6 @@ static int inet6_dump_fib(struct sk_buff *skb, struct netlink_callback *cb)
 
 	s_h = cb->args[0];
 	s_e = cb->args[1];
-
 	w = (void *)cb->args[2];
 	if (!w) {
 		/* New dump:
@@ -378,7 +372,6 @@ static int inet6_dump_fib(struct sk_buff *skb, struct netlink_callback *cb)
 		 */
 		cb->args[3] = (long)cb->done;
 		cb->done = fib6_dump_done;
-
 		/*
 		 * 2. allocate and initialize walker.
 		 */
@@ -426,7 +419,6 @@ out:
  *	by either creating and inserting or by returning an existing
  *	node.
  */
-
 static struct fib6_node * fib6_add_1(struct fib6_node *root, void *addr,
 				     int addrlen, int plen,
 				     int offset, int allow_create,
@@ -442,12 +434,9 @@ static struct fib6_node * fib6_add_1(struct fib6_node *root, void *addr,
 	RT6_TRACE("fib6_add_1\n");
 
 	/* insert node in tree */
-
 	fn = root;
-
 	do {
 		key = (struct rt6key *)((u8 *)fn->leaf + offset);
-
 		/*
 		 *	Prefix match
 		 */
@@ -466,23 +455,17 @@ static struct fib6_node * fib6_add_1(struct fib6_node *root, void *addr,
 		/*
 		 *	Exact match ?
 		 */
-
 		if (plen == fn->fn_bit) {
 			/* clean up an intermediate node */
 			if (!(fn->fn_flags & RTN_RTINFO)) {
 				rt6_release(fn->leaf);
 				fn->leaf = NULL;
 			}
-
 			fn->fn_sernum = sernum;
 
 			return fn;
 		}
 
-		/*
-		 *	We have more bits to go
-		 */
-
 		/* Try to walk down on tree. */
 		fn->fn_sernum = sernum;
 		dir = addr_bit_set(addr, fn->fn_bit);
@@ -512,11 +495,10 @@ static struct fib6_node * fib6_add_1(struct fib6_node *root, void *addr,
 	 */
 
 	ln = node_alloc();
-
 	if (!ln)
 		return NULL;
-	ln->fn_bit = plen;
 
+	ln->fn_bit = plen;
 	ln->parent = pn;
 	ln->fn_sernum = sernum;
 
@@ -527,7 +509,6 @@ static struct fib6_node * fib6_add_1(struct fib6_node *root, void *addr,
 
 	return ln;
 
-
 insert_above:
 	/*
 	 * split since we don't have a common prefix anymore or
@@ -536,17 +517,13 @@ insert_above:
 	 * this new node will point to the one we need to create
 	 * and the current
 	 */
-
 	pn = fn->parent;
-
 	/* find 1st bit in difference between the 2 addrs.
 
 	   See comment in __ipv6_addr_diff: bit may be an invalid value,
 	   but if it is >= plen, the value is ignored in any case.
 	 */
-
 	bit = __ipv6_addr_diff(addr, &key->addr, addrlen);
-
 	/*
 	 *		(intermediate)[in]
 	 *	          /	   \
@@ -571,15 +548,11 @@ insert_above:
 		 * the branches would not match less specific routes
 		 * in the other branch
 		 */
-
 		in->fn_bit = bit;
-
 		in->parent = pn;
 		in->leaf = fn->leaf;
 		atomic_inc(&in->leaf->rt6i_ref);
-
 		in->fn_sernum = sernum;
-
 		/* update parent pointer */
 		if (dir)
 			pn->right = in;
@@ -587,10 +560,8 @@ insert_above:
 			pn->left  = in;
 
 		ln->fn_bit = plen;
-
 		ln->parent = in;
 		fn->parent = in;
-
 		ln->fn_sernum = sernum;
 
 		if (addr_bit_set(addr, bit)) {
@@ -607,16 +578,12 @@ insert_above:
 		 *	          /	   \
 		 *	     (old node)[fn] NULL
 		 */
-
 		ln = node_alloc();
-
 		if (!ln)
 			return NULL;
 
 		ln->fn_bit = plen;
-
 		ln->parent = pn;
-
 		ln->fn_sernum = sernum;
 
 		if (dir)
@@ -637,7 +604,6 @@ insert_above:
 /*
  *	Insert routing information in a node.
  */
-
 static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt,
 			    struct nl_info *info)
 {
@@ -650,12 +616,10 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt,
 	int found = 0;
 
 	ins = &fn->leaf;
-
 	for (iter = fn->leaf; iter; iter = iter->dst.rt6_next) {
 		/*
 		 *	Search for duplicates
 		 */
-
 		if (iter->rt6i_metric == rt->rt6i_metric) {
 			/*
 			 *	Same priority level
@@ -667,7 +631,6 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt,
 				found++;
 				break;
 			}
-
 			if (iter->dst.dev == rt->dst.dev &&
 			    iter->rt6i_idev == rt->rt6i_idev &&
 			    ipv6_addr_equal(&iter->rt6i_gateway,
@@ -681,24 +644,20 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt,
 				return -EEXIST;
 			}
 		}
-
 		if (iter->rt6i_metric > rt->rt6i_metric)
 			break;
-
 		ins = &iter->dst.rt6_next;
 	}
 
 	/* Reset round-robin state, if necessary */
 	if (ins == &fn->leaf)
 		fn->rr_ptr = NULL;
-
 	/*
 	 *	insert node
 	 */
 	if (!replace) {
 		if (!add)
 			pr_warn("NLM_F_CREATE should be set when creating new route\n");
-
 add:
 		rt->dst.rt6_next = iter;
 		*ins = rt;
@@ -706,12 +665,10 @@ add:
 		atomic_inc(&rt->rt6i_ref);
 		inet6_rt_notify(RTM_NEWROUTE, rt, info);
 		info->nl_net->ipv6.rt6_stats->fib_rt_entries++;
-
 		if (!(fn->fn_flags & RTN_RTINFO)) {
 			info->nl_net->ipv6.rt6_stats->fib_route_nodes++;
 			fn->fn_flags |= RTN_RTINFO;
 		}
-
 	} else {
 		if (!found) {
 			if (add)
@@ -818,7 +775,6 @@ int fib6_add(struct fib6_node *root, struct rt6_info *rt, struct nl_info *info)
 					sizeof(struct in6_addr), rt->rt6i_src.plen,
 					offsetof(struct rt6_info, rt6i_src),
 					allow_create, replace_required);
-
 			if (!sn) {
 				/* If it is failed, discard just allocated
 				   root, and then (in st_failure) stale node
@@ -827,7 +783,6 @@ int fib6_add(struct fib6_node *root, struct rt6_info *rt, struct nl_info *info)
 				node_free(sfn);
 				goto st_failure;
 			}
-
 			/* Now link new subtree to main tree */
 			sfn->parent = fn;
 			fn->subtree = sfn;
@@ -836,7 +791,6 @@ int fib6_add(struct fib6_node *root, struct rt6_info *rt, struct nl_info *info)
 					sizeof(struct in6_addr), rt->rt6i_src.plen,
 					offsetof(struct rt6_info, rt6i_src),
 					allow_create, replace_required);
-
 			if (IS_ERR(sn)) {
 				err = PTR_ERR(sn);
 				sn = NULL;
@@ -852,7 +806,6 @@ int fib6_add(struct fib6_node *root, struct rt6_info *rt, struct nl_info *info)
 		fn = sn;
 	}
 #endif
-
 	err = fib6_add_rt2node(fn, rt, info);
 	if (!err) {
 		fib6_start_gc(info->nl_net, rt);
@@ -916,20 +869,15 @@ static struct fib6_node * fib6_lookup_1(struct fib6_node *root,
 
 	if (unlikely(args->offset == 0))
 		return NULL;
-
 	/*
 	 *	Descend on a tree
 	 */
-
 	fn = root;
-
 	for (;;) {
 		struct fib6_node *next;
 
 		dir = addr_bit_set(args->addr, fn->fn_bit);
-
 		next = dir ? fn->right : fn->left;
-
 		if (next) {
 			fn = next;
 			continue;
@@ -943,7 +891,6 @@ static struct fib6_node * fib6_lookup_1(struct fib6_node *root,
 
 			key = (struct rt6key *) ((u8 *) fn->leaf +
 						 args->offset);
-
 			if (ipv6_prefix_equal(&key->addr, args->addr, key->plen)) {
 #ifdef CONFIG_IPV6_SUBTREES
 				if (fn->subtree)
@@ -953,10 +900,8 @@ static struct fib6_node * fib6_lookup_1(struct fib6_node *root,
 					return fn;
 			}
 		}
-
 		if (fn->fn_flags & RTN_ROOT)
 			break;
-
 		fn = fn->parent;
 	}
 
@@ -994,8 +939,6 @@ struct fib6_node * fib6_lookup(struct fib6_node *root, const struct in6_addr *da
  *	Get node with specified destination prefix (and source prefix,
  *	if subtrees are used)
  */
-
-
 static struct fib6_node * fib6_locate_1(struct fib6_node *root,
 					const struct in6_addr *addr,
 					int plen, int offset)
@@ -1004,17 +947,14 @@ static struct fib6_node * fib6_locate_1(struct fib6_node *root,
 
 	for (fn = root; fn ; ) {
 		struct rt6key *key = (struct rt6key *)((u8 *)fn->leaf + offset);
-
 		/*
 		 *	Prefix match
 		 */
 		if (plen < fn->fn_bit ||
 		    !ipv6_prefix_equal(&key->addr, addr, fn->fn_bit))
 			return NULL;
-
 		if (plen == fn->fn_bit)
 			return fn;
-
 		/*
 		 *	We have more bits to go
 		 */
@@ -1034,7 +974,6 @@ struct fib6_node * fib6_locate(struct fib6_node *root,
 
 	fn = fib6_locate_1(root, daddr, dst_len,
 			   offsetof(struct rt6_info, rt6i_dst));
-
 #ifdef CONFIG_IPV6_SUBTREES
 	if (src_len) {
 		WARN_ON(saddr == NULL);
@@ -1043,19 +982,12 @@ struct fib6_node * fib6_locate(struct fib6_node *root,
 					   offsetof(struct rt6_info, rt6i_src));
 	}
 #endif
-
 	if (fn && fn->fn_flags & RTN_RTINFO)
 		return fn;
 
 	return NULL;
 }
 
-
-/*
- *	Deletion
- *
- */
-
 static struct rt6_info *fib6_find_prefix(struct net *net, struct fib6_node *fn)
 {
 	if (fn->fn_flags & RTN_ROOT)
@@ -1076,7 +1008,6 @@ static struct rt6_info *fib6_find_prefix(struct net *net, struct fib6_node *fn)
  *	Called to trim the tree of intermediate nodes when possible. "fn"
  *	is the node we want to try and remove.
  */
-
 static struct fib6_node *fib6_repair_tree(struct net *net,
 					   struct fib6_node *fn)
 {
@@ -1270,11 +1201,9 @@ int fib6_del(struct rt6_info *rt, struct nl_info *info)
 #endif
 		fib6_prune_clones(info->nl_net, pn, rt);
 	}
-
 	/*
 	 *	Walk the leaf entries looking for ourself
 	 */
-
 	for (rtp = &fn->leaf; *rtp; rtp = &(*rtp)->dst.rt6_next) {
 		if (*rtp == rt) {
 			fib6_del_route(fn, rtp, info);
@@ -1307,7 +1236,6 @@ int fib6_del(struct rt6_info *rt, struct nl_info *info)
  *	>0  -> walk is incomplete (i.e. suspended)
  *	<0  -> walk is terminated by an error.
  */
-
 static int fib6_walk_continue(struct fib6_walker_t *w)
 {
 	struct fib6_node *fn, *pn;
@@ -1444,7 +1372,6 @@ static int fib6_clean_node(struct fib6_walker_t *w)
  *	prune==1 -> only immediate children of node (certainly,
  *	ignoring pure split nodes) will be scanned.
  */
-
 static void fib6_clean_tree(struct net *net, struct fib6_node *root,
 			    int (*func)(struct rt6_info *, void *arg),
 			    int prune, void *arg)
@@ -1483,6 +1410,7 @@ void fib6_clean_all_ro(struct net *net, int (*func)(struct rt6_info *, void *arg
 	}
 	rcu_read_unlock();
 }
+
 void fib6_clean_all(struct net *net, int (*func)(struct rt6_info *, void *arg),
 		    int prune, void *arg)
 {
@@ -1523,7 +1451,6 @@ static void fib6_prune_clones(struct net *net, struct fib6_node *fn,
 /*
  *	Garbage collection
  */
-
 static struct fib6_gc_args
 {
 	int			timeout;
@@ -1541,7 +1468,6 @@ static int fib6_age(struct rt6_info *rt, void *arg)
 	 *	Also age clones. Note, that clones are aged out
 	 *	only if they are not in use now.
 	 */
-
 	if (rt->rt6i_flags & RTF_EXPIRES && rt->dst.expires) {
 		if (time_after(now, rt->dst.expires)) {
 			RT6_TRACE("expiring %p\n", rt);
-- 
1.7.7.6

^ permalink raw reply related

* [PATCH 2/3] ipv6, route: remove BACKTRACK() macro
From: Cong Wang @ 2012-09-10 12:48 UTC (permalink / raw)
  To: netdev; +Cc: David S. Miller, Cong Wang
In-Reply-To: <1347281326-26890-1-git-send-email-amwang@redhat.com>

It doesn't save any code, nor it helps readability.

Signed-off-by: Cong Wang <amwang@redhat.com>
---
 net/ipv6/route.c |   48 ++++++++++++++++++++++++++++--------------------
 1 files changed, 28 insertions(+), 20 deletions(-)

diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index b130bf2..71267e9 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -675,24 +675,6 @@ int rt6_route_rcv(struct net_device *dev, u8 *opt, int len,
 }
 #endif
 
-#define BACKTRACK(__net, saddr)			\
-do { \
-	if (rt == __net->ipv6.ip6_null_entry) {	\
-		struct fib6_node *pn; \
-		while (1) { \
-			if (fn->fn_flags & RTN_TL_ROOT) \
-				goto out; \
-			pn = fn->parent; \
-			if (FIB6_SUBTREE(pn) && FIB6_SUBTREE(pn) != fn) \
-				fn = fib6_lookup(FIB6_SUBTREE(pn), NULL, saddr); \
-			else \
-				fn = pn; \
-			if (fn->fn_flags & RTN_RTINFO) \
-				goto restart; \
-		} \
-	} \
-} while (0)
-
 static struct rt6_info *ip6_pol_route_lookup(struct net *net,
 					     struct fib6_table *table,
 					     struct flowi6 *fl6, int flags)
@@ -705,7 +687,20 @@ static struct rt6_info *ip6_pol_route_lookup(struct net *net,
 restart:
 	rt = fn->leaf;
 	rt = rt6_device_match(net, rt, &fl6->saddr, fl6->flowi6_oif, flags);
-	BACKTRACK(net, &fl6->saddr);
+	if (rt == net->ipv6.ip6_null_entry) {
+		struct fib6_node *pn;
+		while (1) {
+			if (fn->fn_flags & RTN_TL_ROOT)
+				goto out;
+			pn = fn->parent;
+			if (FIB6_SUBTREE(pn) && FIB6_SUBTREE(pn) != fn)
+				fn = fib6_lookup(FIB6_SUBTREE(pn), NULL, &fl6->saddr);
+			else
+				fn = pn;
+			if (fn->fn_flags & RTN_RTINFO)
+				goto restart;
+		}
+	}
 out:
 	dst_use(&rt->dst, jiffies);
 	read_unlock_bh(&table->tb6_lock);
@@ -867,7 +862,20 @@ restart_2:
 restart:
 	rt = rt6_select(fn, oif, strict | reachable);
 
-	BACKTRACK(net, &fl6->saddr);
+	if (rt == net->ipv6.ip6_null_entry) {
+		struct fib6_node *pn;
+		while (1) {
+			if (fn->fn_flags & RTN_TL_ROOT)
+				goto out;
+			pn = fn->parent;
+			if (FIB6_SUBTREE(pn) && FIB6_SUBTREE(pn) != fn)
+				fn = fib6_lookup(FIB6_SUBTREE(pn), NULL, &fl6->saddr);
+			else
+				fn = pn;
+			if (fn->fn_flags & RTN_RTINFO)
+				goto restart;
+		}
+	}
 	if (rt == net->ipv6.ip6_null_entry ||
 	    rt->rt6i_flags & RTF_CACHE)
 		goto out;
-- 
1.7.7.6

^ permalink raw reply related

* [PATCH 1/3] ipv6: remove some useless RCU read lock
From: Cong Wang @ 2012-09-10 12:48 UTC (permalink / raw)
  To: netdev; +Cc: David S. Miller, Cong Wang

After this commit:
	commit 97cac0821af4474ec4ba3a9e7a36b98ed9b6db88
	Author: David S. Miller <davem@davemloft.net>
	Date:   Mon Jul 2 22:43:47 2012 -0700

	    ipv6: Store route neighbour in rt6_info struct.

we no longer use RCU to protect route neighbour.

Cc: "David S. Miller" <davem@davemloft.net>
Signed-off-by: Cong Wang <amwang@redhat.com>
---
 net/ipv6/ip6_output.c |   13 ++-----------
 net/ipv6/route.c      |   15 ++-------------
 2 files changed, 4 insertions(+), 24 deletions(-)

diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index a4f6263..3dd4a37 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -123,16 +123,11 @@ static int ip6_finish_output2(struct sk_buff *skb)
 				skb->len);
 	}
 
-	rcu_read_lock();
 	rt = (struct rt6_info *) dst;
 	neigh = rt->n;
-	if (neigh) {
-		int res = dst_neigh_output(dst, neigh, skb);
+	if (neigh)
+		return dst_neigh_output(dst, neigh, skb);
 
-		rcu_read_unlock();
-		return res;
-	}
-	rcu_read_unlock();
 	IP6_INC_STATS_BH(dev_net(dst->dev),
 			 ip6_dst_idev(dst), IPSTATS_MIB_OUTNOROUTES);
 	kfree_skb(skb);
@@ -983,7 +978,6 @@ static int ip6_dst_lookup_tail(struct sock *sk,
 	 * dst entry and replace it instead with the
 	 * dst entry of the nexthop router
 	 */
-	rcu_read_lock();
 	rt = (struct rt6_info *) *dst;
 	n = rt->n;
 	if (n && !(n->nud_state & NUD_VALID)) {
@@ -991,7 +985,6 @@ static int ip6_dst_lookup_tail(struct sock *sk,
 		struct flowi6 fl_gw6;
 		int redirect;
 
-		rcu_read_unlock();
 		ifp = ipv6_get_ifaddr(net, &fl6->saddr,
 				      (*dst)->dev, 1);
 
@@ -1011,8 +1004,6 @@ static int ip6_dst_lookup_tail(struct sock *sk,
 			if ((err = (*dst)->error))
 				goto out_err_release;
 		}
-	} else {
-		rcu_read_unlock();
 	}
 #endif
 
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 339d921..b130bf2 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -451,10 +451,9 @@ static void rt6_probe(struct rt6_info *rt)
 	 * Router Reachability Probe MUST be rate-limited
 	 * to no more than one per minute.
 	 */
-	rcu_read_lock();
 	neigh = rt ? rt->n : NULL;
 	if (!neigh || (neigh->nud_state & NUD_VALID))
-		goto out;
+		return;
 	read_lock_bh(&neigh->lock);
 	if (!(neigh->nud_state & NUD_VALID) &&
 	    time_after(jiffies, neigh->updated + rt->rt6i_idev->cnf.rtr_probe_interval)) {
@@ -470,8 +469,6 @@ static void rt6_probe(struct rt6_info *rt)
 	} else {
 		read_unlock_bh(&neigh->lock);
 	}
-out:
-	rcu_read_unlock();
 }
 #else
 static inline void rt6_probe(struct rt6_info *rt)
@@ -498,7 +495,6 @@ static inline int rt6_check_neigh(struct rt6_info *rt)
 	struct neighbour *neigh;
 	int m;
 
-	rcu_read_lock();
 	neigh = rt->n;
 	if (rt->rt6i_flags & RTF_NONEXTHOP ||
 	    !(rt->rt6i_flags & RTF_GATEWAY))
@@ -516,7 +512,6 @@ static inline int rt6_check_neigh(struct rt6_info *rt)
 		read_unlock_bh(&neigh->lock);
 	} else
 		m = 0;
-	rcu_read_unlock();
 	return m;
 }
 
@@ -2496,15 +2491,11 @@ static int rt6_fill_node(struct net *net,
 	if (rtnetlink_put_metrics(skb, dst_metrics_ptr(&rt->dst)) < 0)
 		goto nla_put_failure;
 
-	rcu_read_lock();
 	n = rt->n;
 	if (n) {
-		if (nla_put(skb, RTA_GATEWAY, 16, &n->primary_key) < 0) {
-			rcu_read_unlock();
+		if (nla_put(skb, RTA_GATEWAY, 16, &n->primary_key) < 0)
 			goto nla_put_failure;
-		}
 	}
-	rcu_read_unlock();
 
 	if (rt->dst.dev &&
 	    nla_put_u32(skb, RTA_OIF, rt->dst.dev->ifindex))
@@ -2706,14 +2697,12 @@ static int rt6_info_route(struct rt6_info *rt, void *p_arg)
 #else
 	seq_puts(m, "00000000000000000000000000000000 00 ");
 #endif
-	rcu_read_lock();
 	n = rt->n;
 	if (n) {
 		seq_printf(m, "%pi6", n->primary_key);
 	} else {
 		seq_puts(m, "00000000000000000000000000000000");
 	}
-	rcu_read_unlock();
 	seq_printf(m, " %08x %08x %08x %08x %8s\n",
 		   rt->rt6i_metric, atomic_read(&rt->dst.__refcnt),
 		   rt->dst.__use, rt->rt6i_flags,
-- 
1.7.7.6

^ permalink raw reply related

* Re: [PATCH 1/2] dst: take into account policy update on check()
From: Nicolas Dichtel @ 2012-09-10 12:47 UTC (permalink / raw)
  To: David Miller; +Cc: eric.dumazet, vyasevich, sri, linux-sctp, netdev
In-Reply-To: <20120907.144828.97793990734588625.davem@davemloft.net>

Le 07/09/2012 20:48, David Miller a écrit :
> From: Nicolas Dichtel <nicolas.dichtel@6wind.com>
> Date: Fri, 07 Sep 2012 17:13:35 +0200
>
>> Le 07/09/2012 17:09, Eric Dumazet a écrit :
>>> On Fri, 2012-09-07 at 16:47 +0200, Nicolas Dichtel wrote:
>>>> Le 07/09/2012 16:35, Eric Dumazet a écrit :
>>>>>
>>>>> Hmm... cant we reuse rt_genid ?
>>>>>
>>>>> (When changing flow_cache_genid, change &net->ipv4.rt_genid)
>>>>
>>>> And so adding a new field in net->ipv6?
>>>
>>> or move net->ipv4.rt_genid to net->rt_genid
>>>
>>> Having separate field for IPv4/IPv6 is of little interest IMHO
>>>
>> Ok, I will wait feedback from other people and repost a patch after.
>
> A global net->rt_genid is definitely the way to go.
>
So it means that IPv6 dst entries will be invalidated by IPv4 route management. 
For example, calling rt_cache_flush() will flush IPv6 dst too. Is this acceptable?

I will send a new version.

^ permalink raw reply

* [PATCH net v2] ixp4xx_hss: fix build failure due to missing linux/module.h inclusion
From: Florian Fainelli @ 2012-09-10 12:06 UTC (permalink / raw)
  To: netdev; +Cc: khc, joe, David Miller, Florian Fainelli, stable

Commit 36a1211970193ce215de50ed1e4e1272bc814df1 (netprio_cgroup.h:
dont include module.h from other includes) made the following build
error on ixp4xx_hss pop up:

  CC [M]  drivers/net/wan/ixp4xx_hss.o
 drivers/net/wan/ixp4xx_hss.c:1412:20: error: expected ';', ',' or ')'
 before string constant
 drivers/net/wan/ixp4xx_hss.c:1413:25: error: expected ';', ',' or ')'
 before string constant
 drivers/net/wan/ixp4xx_hss.c:1414:21: error: expected ';', ',' or ')'
 before string constant
 drivers/net/wan/ixp4xx_hss.c:1415:19: error: expected ';', ',' or ')'
 before string constant
 make[8]: *** [drivers/net/wan/ixp4xx_hss.o] Error 1

This was previously hidden because ixp4xx_hss includes linux/hdlc.h which
includes linux/netdevice.h which includes linux/netprio_cgroup.h which
used to include linux/module.h. The real issue was actually present since
the initial commit that added this driver since it uses macros from
linux/module.h without including this file.

CC: stable@vger.kernel.org
Signed-off-by: Florian Fainelli <florian@openwrt.org>
---
[stable: 3.3+]

Changes since v1:
- properly identify the bad commit

 drivers/net/wan/ixp4xx_hss.c |    1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/net/wan/ixp4xx_hss.c b/drivers/net/wan/ixp4xx_hss.c
index aaaca9a..3f575af 100644
--- a/drivers/net/wan/ixp4xx_hss.c
+++ b/drivers/net/wan/ixp4xx_hss.c
@@ -10,6 +10,7 @@
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
+#include <linux/module.h>
 #include <linux/bitops.h>
 #include <linux/cdev.h>
 #include <linux/dma-mapping.h>
-- 
1.7.9.5

^ permalink raw reply related

* [PATCH] Generalise "auto-negotiation done" function, move generic PHY code to phy_device.c
From: Alexander Sverdlin @ 2012-09-10 11:22 UTC (permalink / raw)
  To: netdev, Andy Fleming; +Cc: Alexander Sverdlin

From: Alexander Sverdlin <alexander.sverdlin@sysgo.com>

Generalise "auto-negotiation done" function, move generic PHY code to phy_device.c 

Not all devices have "auto-negotiation done" bit at the place, as expected by
phy_aneg_done() in phy.c. Example of such device is Marvell 88E61xx Ethernet 
switch which could be controlled by Linux PHY layer, if struct phy_driver had
abstraction for above function. So move hardware-dependent implementation details
for "generic" PHY to phy_device.c, and modify all PHY drivers to use new field.
Now phy.c contains only high-level state-machine functionality, leaving 
hardware-layer to different drivers.

Signed-off-by: Alexander Sverdlin <alexander.sverdlin@sysgo.com>
---
diff -uprN linux-3.6-rc4.orig/Documentation/networking/phy.txt linux-3.6-rc4/Documentation/networking/phy.txt
--- linux-3.6-rc4.orig/Documentation/networking/phy.txt	2012-09-01 19:39:58.000000000 +0200
+++ linux-3.6-rc4/Documentation/networking/phy.txt	2012-09-10 10:54:52.000000000 +0200
@@ -1,7 +1,7 @@
 
 -------
 PHY Abstraction Layer
-(Updated 2008-04-08)
+(Updated 2012-09-06)
 
 Purpose
 
@@ -257,15 +257,16 @@ Writing a PHY driver
    probe: Does any setup needed by the driver
    suspend/resume: power management
    config_aneg: Changes the speed/duplex/negotiation settings
+   aneg_done: Reads current auto-negotiation state
    read_status: Reads the current speed/duplex/negotiation settings
    ack_interrupt: Clear a pending interrupt
    config_intr: Enable or disable interrupts
    remove: Does any driver take-down
 
- Of these, only config_aneg and read_status are required to be
+ Of these, only config_aneg, aneg_done and read_status are required to be
  assigned by the driver code.  The rest are optional.  Also, it is
- preferred to use the generic phy driver's versions of these two
- functions if at all possible: genphy_read_status and
+ preferred to use the generic phy driver's versions of these three
+ functions if at all possible: genphy_read_status, genphy_aneg_done and
  genphy_config_aneg.  If this is not possible, it is likely that
  you only need to perform some actions before and after invoking
  these functions, and so your functions will wrap the generic
diff -uprN linux-3.6-rc4.orig/drivers/net/phy/amd.c linux-3.6-rc4/drivers/net/phy/amd.c
--- linux-3.6-rc4.orig/drivers/net/phy/amd.c	2012-09-01 19:39:58.000000000 +0200
+++ linux-3.6-rc4/drivers/net/phy/amd.c	2012-09-10 11:04:35.000000000 +0200
@@ -69,6 +69,7 @@ static struct phy_driver am79c_driver = 
 	.flags		= PHY_HAS_INTERRUPT,
 	.config_init	= am79c_config_init,
 	.config_aneg	= genphy_config_aneg,
+	.aneg_done	= genphy_aneg_done,
 	.read_status	= genphy_read_status,
 	.ack_interrupt	= am79c_ack_interrupt,
 	.config_intr	= am79c_config_intr,
diff -uprN linux-3.6-rc4.orig/drivers/net/phy/bcm63xx.c linux-3.6-rc4/drivers/net/phy/bcm63xx.c
--- linux-3.6-rc4.orig/drivers/net/phy/bcm63xx.c	2012-09-01 19:39:58.000000000 +0200
+++ linux-3.6-rc4/drivers/net/phy/bcm63xx.c	2012-09-10 11:10:04.000000000 +0200
@@ -81,6 +81,7 @@ static struct phy_driver bcm63xx_driver[
 	.flags		= PHY_HAS_INTERRUPT,
 	.config_init	= bcm63xx_config_init,
 	.config_aneg	= genphy_config_aneg,
+	.aneg_done	= genphy_aneg_done,
 	.read_status	= genphy_read_status,
 	.ack_interrupt	= bcm63xx_ack_interrupt,
 	.config_intr	= bcm63xx_config_intr,
@@ -94,6 +95,7 @@ static struct phy_driver bcm63xx_driver[
 	.flags		= PHY_HAS_INTERRUPT,
 	.config_init	= bcm63xx_config_init,
 	.config_aneg	= genphy_config_aneg,
+	.aneg_done	= genphy_aneg_done,
 	.read_status	= genphy_read_status,
 	.ack_interrupt	= bcm63xx_ack_interrupt,
 	.config_intr	= bcm63xx_config_intr,
diff -uprN linux-3.6-rc4.orig/drivers/net/phy/bcm87xx.c linux-3.6-rc4/drivers/net/phy/bcm87xx.c
--- linux-3.6-rc4.orig/drivers/net/phy/bcm87xx.c	2012-09-01 19:39:58.000000000 +0200
+++ linux-3.6-rc4/drivers/net/phy/bcm87xx.c	2012-09-10 11:10:59.000000000 +0200
@@ -195,6 +195,7 @@ static struct phy_driver bcm87xx_driver[
 	.flags		= PHY_HAS_INTERRUPT,
 	.config_init	= bcm87xx_config_init,
 	.config_aneg	= bcm87xx_config_aneg,
+	.aneg_done	= genphy_aneg_done,
 	.read_status	= bcm87xx_read_status,
 	.ack_interrupt	= bcm87xx_ack_interrupt,
 	.config_intr	= bcm87xx_config_intr,
@@ -208,6 +209,7 @@ static struct phy_driver bcm87xx_driver[
 	.flags		= PHY_HAS_INTERRUPT,
 	.config_init	= bcm87xx_config_init,
 	.config_aneg	= bcm87xx_config_aneg,
+	.aneg_done	= genphy_aneg_done,
 	.read_status	= bcm87xx_read_status,
 	.ack_interrupt	= bcm87xx_ack_interrupt,
 	.config_intr	= bcm87xx_config_intr,
diff -uprN linux-3.6-rc4.orig/drivers/net/phy/broadcom.c linux-3.6-rc4/drivers/net/phy/broadcom.c
--- linux-3.6-rc4.orig/drivers/net/phy/broadcom.c	2012-09-01 19:39:58.000000000 +0200
+++ linux-3.6-rc4/drivers/net/phy/broadcom.c	2012-09-10 11:09:49.000000000 +0200
@@ -692,6 +692,7 @@ static struct phy_driver broadcom_driver
 	.flags		= PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
 	.config_init	= bcm54xx_config_init,
 	.config_aneg	= genphy_config_aneg,
+	.aneg_done	= genphy_aneg_done,
 	.read_status	= genphy_read_status,
 	.ack_interrupt	= bcm54xx_ack_interrupt,
 	.config_intr	= bcm54xx_config_intr,
@@ -705,6 +706,7 @@ static struct phy_driver broadcom_driver
 	.flags		= PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
 	.config_init	= bcm54xx_config_init,
 	.config_aneg	= genphy_config_aneg,
+	.aneg_done	= genphy_aneg_done,
 	.read_status	= genphy_read_status,
 	.ack_interrupt	= bcm54xx_ack_interrupt,
 	.config_intr	= bcm54xx_config_intr,
@@ -718,6 +720,7 @@ static struct phy_driver broadcom_driver
 	.flags		= PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
 	.config_init	= bcm54xx_config_init,
 	.config_aneg	= genphy_config_aneg,
+	.aneg_done	= genphy_aneg_done,
 	.read_status	= genphy_read_status,
 	.ack_interrupt	= bcm54xx_ack_interrupt,
 	.config_intr	= bcm54xx_config_intr,
@@ -731,6 +734,7 @@ static struct phy_driver broadcom_driver
 	.flags		= PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
 	.config_init	= bcm54xx_config_init,
 	.config_aneg	= genphy_config_aneg,
+	.aneg_done	= genphy_aneg_done,
 	.read_status	= genphy_read_status,
 	.ack_interrupt	= bcm54xx_ack_interrupt,
 	.config_intr	= bcm54xx_config_intr,
@@ -744,6 +748,7 @@ static struct phy_driver broadcom_driver
 	.flags		= PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
 	.config_init	= bcm54xx_config_init,
 	.config_aneg	= bcm5481_config_aneg,
+	.aneg_done	= genphy_aneg_done,
 	.read_status	= genphy_read_status,
 	.ack_interrupt	= bcm54xx_ack_interrupt,
 	.config_intr	= bcm54xx_config_intr,
@@ -757,6 +762,7 @@ static struct phy_driver broadcom_driver
 	.flags		= PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
 	.config_init	= bcm5482_config_init,
 	.config_aneg	= genphy_config_aneg,
+	.aneg_done	= genphy_aneg_done,
 	.read_status	= bcm5482_read_status,
 	.ack_interrupt	= bcm54xx_ack_interrupt,
 	.config_intr	= bcm54xx_config_intr,
@@ -770,6 +776,7 @@ static struct phy_driver broadcom_driver
 	.flags		= PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
 	.config_init	= bcm54xx_config_init,
 	.config_aneg	= genphy_config_aneg,
+	.aneg_done	= genphy_aneg_done,
 	.read_status	= genphy_read_status,
 	.ack_interrupt	= bcm54xx_ack_interrupt,
 	.config_intr	= bcm54xx_config_intr,
@@ -783,6 +790,7 @@ static struct phy_driver broadcom_driver
 	.flags		= PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
 	.config_init	= bcm54xx_config_init,
 	.config_aneg	= genphy_config_aneg,
+	.aneg_done	= genphy_aneg_done,
 	.read_status	= genphy_read_status,
 	.ack_interrupt	= bcm54xx_ack_interrupt,
 	.config_intr	= bcm54xx_config_intr,
@@ -796,6 +804,7 @@ static struct phy_driver broadcom_driver
 	.flags		= PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
 	.config_init	= bcm54xx_config_init,
 	.config_aneg	= genphy_config_aneg,
+	.aneg_done	= genphy_aneg_done,
 	.read_status	= genphy_read_status,
 	.ack_interrupt	= bcm54xx_ack_interrupt,
 	.config_intr	= bcm54xx_config_intr,
@@ -809,6 +818,7 @@ static struct phy_driver broadcom_driver
 	.flags		= PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
 	.config_init	= brcm_fet_config_init,
 	.config_aneg	= genphy_config_aneg,
+	.aneg_done	= genphy_aneg_done,
 	.read_status	= genphy_read_status,
 	.ack_interrupt	= brcm_fet_ack_interrupt,
 	.config_intr	= brcm_fet_config_intr,
@@ -822,6 +832,7 @@ static struct phy_driver broadcom_driver
 	.flags		= PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
 	.config_init	= brcm_fet_config_init,
 	.config_aneg	= genphy_config_aneg,
+	.aneg_done	= genphy_aneg_done,
 	.read_status	= genphy_read_status,
 	.ack_interrupt	= brcm_fet_ack_interrupt,
 	.config_intr	= brcm_fet_config_intr,
diff -uprN linux-3.6-rc4.orig/drivers/net/phy/cicada.c linux-3.6-rc4/drivers/net/phy/cicada.c
--- linux-3.6-rc4.orig/drivers/net/phy/cicada.c	2012-09-01 19:39:58.000000000 +0200
+++ linux-3.6-rc4/drivers/net/phy/cicada.c	2012-09-10 11:06:41.000000000 +0200
@@ -111,6 +111,7 @@ static struct phy_driver cis820x_driver[
 	.flags		= PHY_HAS_INTERRUPT,
 	.config_init	= &cis820x_config_init,
 	.config_aneg	= &genphy_config_aneg,
+	.aneg_done	= genphy_aneg_done,
 	.read_status	= &genphy_read_status,
 	.ack_interrupt	= &cis820x_ack_interrupt,
 	.config_intr	= &cis820x_config_intr,
@@ -123,6 +124,7 @@ static struct phy_driver cis820x_driver[
 	.flags		= PHY_HAS_INTERRUPT,
 	.config_init	= &cis820x_config_init,
 	.config_aneg	= &genphy_config_aneg,
+	.aneg_done	= genphy_aneg_done,
 	.read_status	= &genphy_read_status,
 	.ack_interrupt	= &cis820x_ack_interrupt,
 	.config_intr	= &cis820x_config_intr,
diff -uprN linux-3.6-rc4.orig/drivers/net/phy/davicom.c linux-3.6-rc4/drivers/net/phy/davicom.c
--- linux-3.6-rc4.orig/drivers/net/phy/davicom.c	2012-09-01 19:39:58.000000000 +0200
+++ linux-3.6-rc4/drivers/net/phy/davicom.c	2012-09-10 11:05:54.000000000 +0200
@@ -152,6 +152,7 @@ static struct phy_driver dm91xx_driver[]
 	.features	= PHY_BASIC_FEATURES,
 	.config_init	= dm9161_config_init,
 	.config_aneg	= dm9161_config_aneg,
+	.aneg_done	= genphy_aneg_done,
 	.read_status	= genphy_read_status,
 	.driver		= { .owner = THIS_MODULE,},
 }, {
@@ -161,6 +162,7 @@ static struct phy_driver dm91xx_driver[]
 	.features	= PHY_BASIC_FEATURES,
 	.config_init	= dm9161_config_init,
 	.config_aneg	= dm9161_config_aneg,
+	.aneg_done	= genphy_aneg_done,
 	.read_status	= genphy_read_status,
 	.driver		= { .owner = THIS_MODULE,},
 }, {
@@ -170,6 +172,7 @@ static struct phy_driver dm91xx_driver[]
 	.features	= PHY_BASIC_FEATURES,
 	.flags		= PHY_HAS_INTERRUPT,
 	.config_aneg	= genphy_config_aneg,
+	.aneg_done	= genphy_aneg_done,
 	.read_status	= genphy_read_status,
 	.ack_interrupt	= dm9161_ack_interrupt,
 	.config_intr	= dm9161_config_intr,
diff -uprN linux-3.6-rc4.orig/drivers/net/phy/dp83640.c linux-3.6-rc4/drivers/net/phy/dp83640.c
--- linux-3.6-rc4.orig/drivers/net/phy/dp83640.c	2012-09-01 19:39:58.000000000 +0200
+++ linux-3.6-rc4/drivers/net/phy/dp83640.c	2012-09-10 11:10:16.000000000 +0200
@@ -1257,6 +1257,7 @@ static struct phy_driver dp83640_driver 
 	.probe		= dp83640_probe,
 	.remove		= dp83640_remove,
 	.config_aneg	= genphy_config_aneg,
+	.aneg_done	= genphy_aneg_done,
 	.read_status	= genphy_read_status,
 	.ts_info	= dp83640_ts_info,
 	.hwtstamp	= dp83640_hwtstamp,
diff -uprN linux-3.6-rc4.orig/drivers/net/phy/et1011c.c linux-3.6-rc4/drivers/net/phy/et1011c.c
--- linux-3.6-rc4.orig/drivers/net/phy/et1011c.c	2012-09-01 19:39:58.000000000 +0200
+++ linux-3.6-rc4/drivers/net/phy/et1011c.c	2012-09-10 11:04:08.000000000 +0200
@@ -94,6 +94,7 @@ static struct phy_driver et1011c_driver 
 	.features	= (PHY_BASIC_FEATURES | SUPPORTED_1000baseT_Full),
 	.flags		= PHY_POLL,
 	.config_aneg	= et1011c_config_aneg,
+	.aneg_done	= genphy_aneg_done,
 	.read_status	= et1011c_read_status,
 	.driver 	= { .owner = THIS_MODULE,},
 };
diff -uprN linux-3.6-rc4.orig/drivers/net/phy/icplus.c linux-3.6-rc4/drivers/net/phy/icplus.c
--- linux-3.6-rc4.orig/drivers/net/phy/icplus.c	2012-09-01 19:39:58.000000000 +0200
+++ linux-3.6-rc4/drivers/net/phy/icplus.c	2012-09-10 11:05:27.000000000 +0200
@@ -210,6 +210,7 @@ static struct phy_driver icplus_driver[]
 	.features	= PHY_BASIC_FEATURES,
 	.config_init	= &ip175c_config_init,
 	.config_aneg	= &ip175c_config_aneg,
+	.aneg_done	= genphy_aneg_done,
 	.read_status	= &ip175c_read_status,
 	.suspend	= genphy_suspend,
 	.resume		= genphy_resume,
@@ -222,6 +223,7 @@ static struct phy_driver icplus_driver[]
 			  SUPPORTED_Asym_Pause,
 	.config_init	= &ip1001_config_init,
 	.config_aneg	= &genphy_config_aneg,
+	.aneg_done	= genphy_aneg_done,
 	.read_status	= &genphy_read_status,
 	.suspend	= genphy_suspend,
 	.resume		= genphy_resume,
@@ -236,6 +238,7 @@ static struct phy_driver icplus_driver[]
 	.ack_interrupt	= ip101a_g_ack_interrupt,
 	.config_init	= &ip101a_g_config_init,
 	.config_aneg	= &genphy_config_aneg,
+	.aneg_done	= genphy_aneg_done,
 	.read_status	= &genphy_read_status,
 	.suspend	= genphy_suspend,
 	.resume		= genphy_resume,
diff -uprN linux-3.6-rc4.orig/drivers/net/phy/lxt.c linux-3.6-rc4/drivers/net/phy/lxt.c
--- linux-3.6-rc4.orig/drivers/net/phy/lxt.c	2012-09-01 19:39:58.000000000 +0200
+++ linux-3.6-rc4/drivers/net/phy/lxt.c	2012-09-10 11:06:12.000000000 +0200
@@ -158,6 +158,7 @@ static struct phy_driver lxt97x_driver[]
 	.flags		= PHY_HAS_INTERRUPT,
 	.config_init	= lxt970_config_init,
 	.config_aneg	= genphy_config_aneg,
+	.aneg_done	= genphy_aneg_done,
 	.read_status	= genphy_read_status,
 	.ack_interrupt	= lxt970_ack_interrupt,
 	.config_intr	= lxt970_config_intr,
@@ -169,6 +170,7 @@ static struct phy_driver lxt97x_driver[]
 	.features	= PHY_BASIC_FEATURES,
 	.flags		= PHY_HAS_INTERRUPT,
 	.config_aneg	= genphy_config_aneg,
+	.aneg_done	= genphy_aneg_done,
 	.read_status	= genphy_read_status,
 	.ack_interrupt	= lxt971_ack_interrupt,
 	.config_intr	= lxt971_config_intr,
@@ -181,6 +183,7 @@ static struct phy_driver lxt97x_driver[]
 	.flags		= 0,
 	.probe		= lxt973_probe,
 	.config_aneg	= lxt973_config_aneg,
+	.aneg_done	= genphy_aneg_done,
 	.read_status	= genphy_read_status,
 	.driver		= { .owner = THIS_MODULE,},
 } };
diff -uprN linux-3.6-rc4.orig/drivers/net/phy/marvell.c linux-3.6-rc4/drivers/net/phy/marvell.c
--- linux-3.6-rc4.orig/drivers/net/phy/marvell.c	2012-09-01 19:39:58.000000000 +0200
+++ linux-3.6-rc4/drivers/net/phy/marvell.c	2012-09-10 11:07:30.000000000 +0200
@@ -713,6 +713,7 @@ static struct phy_driver marvell_drivers
 		.features = PHY_GBIT_FEATURES,
 		.flags = PHY_HAS_INTERRUPT,
 		.config_aneg = &marvell_config_aneg,
+		.aneg_done = genphy_aneg_done,
 		.read_status = &genphy_read_status,
 		.ack_interrupt = &marvell_ack_interrupt,
 		.config_intr = &marvell_config_intr,
@@ -726,6 +727,7 @@ static struct phy_driver marvell_drivers
 		.flags = PHY_HAS_INTERRUPT,
 		.config_init = &m88e1111_config_init,
 		.config_aneg = &marvell_config_aneg,
+		.aneg_done = genphy_aneg_done,
 		.read_status = &genphy_read_status,
 		.ack_interrupt = &marvell_ack_interrupt,
 		.config_intr = &marvell_config_intr,
@@ -739,6 +741,7 @@ static struct phy_driver marvell_drivers
 		.flags = PHY_HAS_INTERRUPT,
 		.config_init = &m88e1111_config_init,
 		.config_aneg = &marvell_config_aneg,
+		.aneg_done = genphy_aneg_done,
 		.read_status = &marvell_read_status,
 		.ack_interrupt = &marvell_ack_interrupt,
 		.config_intr = &marvell_config_intr,
@@ -752,6 +755,7 @@ static struct phy_driver marvell_drivers
 		.flags = PHY_HAS_INTERRUPT,
 		.config_init = &m88e1118_config_init,
 		.config_aneg = &m88e1118_config_aneg,
+		.aneg_done = genphy_aneg_done,
 		.read_status = &genphy_read_status,
 		.ack_interrupt = &marvell_ack_interrupt,
 		.config_intr = &marvell_config_intr,
@@ -764,6 +768,7 @@ static struct phy_driver marvell_drivers
 		.features = PHY_GBIT_FEATURES,
 		.flags = PHY_HAS_INTERRUPT,
 		.config_aneg = &m88e1121_config_aneg,
+		.aneg_done = genphy_aneg_done,
 		.read_status = &marvell_read_status,
 		.ack_interrupt = &marvell_ack_interrupt,
 		.config_intr = &marvell_config_intr,
@@ -777,6 +782,7 @@ static struct phy_driver marvell_drivers
 		.features = PHY_GBIT_FEATURES,
 		.flags = PHY_HAS_INTERRUPT,
 		.config_aneg = &m88e1318_config_aneg,
+		.aneg_done = genphy_aneg_done,
 		.read_status = &marvell_read_status,
 		.ack_interrupt = &marvell_ack_interrupt,
 		.config_intr = &marvell_config_intr,
@@ -791,6 +797,7 @@ static struct phy_driver marvell_drivers
 		.flags = PHY_HAS_INTERRUPT,
 		.config_init = &m88e1145_config_init,
 		.config_aneg = &marvell_config_aneg,
+		.aneg_done = genphy_aneg_done,
 		.read_status = &genphy_read_status,
 		.ack_interrupt = &marvell_ack_interrupt,
 		.config_intr = &marvell_config_intr,
@@ -804,6 +811,7 @@ static struct phy_driver marvell_drivers
 		.flags = PHY_HAS_INTERRUPT,
 		.config_init = &m88e1149_config_init,
 		.config_aneg = &m88e1118_config_aneg,
+		.aneg_done = genphy_aneg_done,
 		.read_status = &genphy_read_status,
 		.ack_interrupt = &marvell_ack_interrupt,
 		.config_intr = &marvell_config_intr,
@@ -817,6 +825,7 @@ static struct phy_driver marvell_drivers
 		.flags = PHY_HAS_INTERRUPT,
 		.config_init = &m88e1111_config_init,
 		.config_aneg = &marvell_config_aneg,
+		.aneg_done = genphy_aneg_done,
 		.read_status = &genphy_read_status,
 		.ack_interrupt = &marvell_ack_interrupt,
 		.config_intr = &marvell_config_intr,
diff -uprN linux-3.6-rc4.orig/drivers/net/phy/micrel.c linux-3.6-rc4/drivers/net/phy/micrel.c
--- linux-3.6-rc4.orig/drivers/net/phy/micrel.c	2012-09-01 19:39:58.000000000 +0200
+++ linux-3.6-rc4/drivers/net/phy/micrel.c	2012-09-10 11:07:55.000000000 +0200
@@ -123,6 +123,7 @@ static struct phy_driver ksphy_driver[] 
 	.flags		= PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
 	.config_init	= kszphy_config_init,
 	.config_aneg	= genphy_config_aneg,
+	.aneg_done	= genphy_aneg_done,
 	.read_status	= genphy_read_status,
 	.ack_interrupt	= kszphy_ack_interrupt,
 	.config_intr	= ks8737_config_intr,
@@ -136,6 +137,7 @@ static struct phy_driver ksphy_driver[] 
 	.flags		= PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
 	.config_init	= kszphy_config_init,
 	.config_aneg	= genphy_config_aneg,
+	.aneg_done	= genphy_aneg_done,
 	.read_status	= genphy_read_status,
 	.ack_interrupt	= kszphy_ack_interrupt,
 	.config_intr	= kszphy_config_intr,
@@ -149,6 +151,7 @@ static struct phy_driver ksphy_driver[] 
 	.flags		= PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
 	.config_init	= ks8051_config_init,
 	.config_aneg	= genphy_config_aneg,
+	.aneg_done	= genphy_aneg_done,
 	.read_status	= genphy_read_status,
 	.ack_interrupt	= kszphy_ack_interrupt,
 	.config_intr	= kszphy_config_intr,
@@ -161,6 +164,7 @@ static struct phy_driver ksphy_driver[] 
 	.flags		= PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
 	.config_init	= kszphy_config_init,
 	.config_aneg	= genphy_config_aneg,
+	.aneg_done	= genphy_aneg_done,
 	.read_status	= genphy_read_status,
 	.ack_interrupt	= kszphy_ack_interrupt,
 	.config_intr	= kszphy_config_intr,
@@ -174,6 +178,7 @@ static struct phy_driver ksphy_driver[] 
 	.flags		= PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
 	.config_init	= kszphy_config_init,
 	.config_aneg	= genphy_config_aneg,
+	.aneg_done	= genphy_aneg_done,
 	.read_status	= genphy_read_status,
 	.ack_interrupt	= kszphy_ack_interrupt,
 	.config_intr	= ksz9021_config_intr,
diff -uprN linux-3.6-rc4.orig/drivers/net/phy/national.c linux-3.6-rc4/drivers/net/phy/national.c
--- linux-3.6-rc4.orig/drivers/net/phy/national.c	2012-09-01 19:39:58.000000000 +0200
+++ linux-3.6-rc4/drivers/net/phy/national.c	2012-09-10 11:08:27.000000000 +0200
@@ -137,6 +137,7 @@ static struct phy_driver dp83865_driver 
 	.flags = PHY_HAS_INTERRUPT,
 	.config_init = ns_config_init,
 	.config_aneg = genphy_config_aneg,
+	.aneg_done = genphy_aneg_done,
 	.read_status = genphy_read_status,
 	.ack_interrupt = ns_ack_interrupt,
 	.config_intr = ns_config_intr,
diff -uprN linux-3.6-rc4.orig/drivers/net/phy/phy.c linux-3.6-rc4/drivers/net/phy/phy.c
--- linux-3.6-rc4.orig/drivers/net/phy/phy.c	2012-09-01 19:39:58.000000000 +0200
+++ linux-3.6-rc4/drivers/net/phy/phy.c	2012-09-10 11:24:18.000000000 +0200
@@ -95,24 +95,6 @@ static int phy_config_interrupt(struct p
 	return err;
 }
 
-
-/**
- * phy_aneg_done - return auto-negotiation status
- * @phydev: target phy_device struct
- *
- * Description: Reads the status register and returns 0 either if
- *   auto-negotiation is incomplete, or if there was an error.
- *   Returns BMSR_ANEGCOMPLETE if auto-negotiation is done.
- */
-static inline int phy_aneg_done(struct phy_device *phydev)
-{
-	int retval;
-
-	retval = phy_read(phydev, MII_BMSR);
-
-	return (retval < 0) ? retval : (retval & BMSR_ANEGCOMPLETE);
-}
-
 /* A structure for mapping a particular speed and duplex
  * combination to a particular SUPPORTED and ADVERTISED value */
 struct phy_setting {
@@ -807,7 +789,7 @@ void phy_state_machine(struct work_struc
 
 			/* Check if negotiation is done.  Break
 			 * if there's an error */
-			err = phy_aneg_done(phydev);
+			err = phydev->drv->aneg_done(phydev);
 			if (err < 0)
 				break;
 
@@ -921,7 +903,7 @@ void phy_state_machine(struct work_struc
 				break;
 
 			if (AUTONEG_ENABLE == phydev->autoneg) {
-				err = phy_aneg_done(phydev);
+				err = phydev->drv->aneg_done(phydev);
 				if (err < 0)
 					break;
 
diff -uprN linux-3.6-rc4.orig/drivers/net/phy/phy_device.c linux-3.6-rc4/drivers/net/phy/phy_device.c
--- linux-3.6-rc4.orig/drivers/net/phy/phy_device.c	2012-09-01 19:39:58.000000000 +0200
+++ linux-3.6-rc4/drivers/net/phy/phy_device.c	2012-09-06 15:00:32.000000000 +0200
@@ -785,6 +785,23 @@ int genphy_config_aneg(struct phy_device
 EXPORT_SYMBOL(genphy_config_aneg);
 
 /**
+ * genphy_aneg_done - return auto-negotiation status
+ * @phydev: target phy_device struct
+ *
+ * Description: Reads the status register and returns positive value if
+ * auto-negotiation is complete, 0 if incomplete and negative on failure.
+ */
+int genphy_aneg_done(struct phy_device *phydev)
+{
+	int retval;
+
+	retval = phy_read(phydev, MII_BMSR);
+
+	return (retval < 0) ? retval : (retval & BMSR_ANEGCOMPLETE);
+}
+EXPORT_SYMBOL(genphy_aneg_done);
+
+/**
  * genphy_update_link - update link status in @phydev
  * @phydev: target phy_device struct
  *
@@ -1117,6 +1134,7 @@ static struct phy_driver genphy_driver =
 	.config_init	= genphy_config_init,
 	.features	= 0,
 	.config_aneg	= genphy_config_aneg,
+	.aneg_done	= genphy_aneg_done,
 	.read_status	= genphy_read_status,
 	.suspend	= genphy_suspend,
 	.resume		= genphy_resume,
diff -uprN linux-3.6-rc4.orig/drivers/net/phy/qsemi.c linux-3.6-rc4/drivers/net/phy/qsemi.c
--- linux-3.6-rc4.orig/drivers/net/phy/qsemi.c	2012-09-01 19:39:58.000000000 +0200
+++ linux-3.6-rc4/drivers/net/phy/qsemi.c	2012-09-10 11:11:08.000000000 +0200
@@ -119,6 +119,7 @@ static struct phy_driver qs6612_driver =
 	.flags		= PHY_HAS_INTERRUPT,
 	.config_init	= qs6612_config_init,
 	.config_aneg	= genphy_config_aneg,
+	.aneg_done	= genphy_aneg_done,
 	.read_status	= genphy_read_status,
 	.ack_interrupt	= qs6612_ack_interrupt,
 	.config_intr	= qs6612_config_intr,
diff -uprN linux-3.6-rc4.orig/drivers/net/phy/realtek.c linux-3.6-rc4/drivers/net/phy/realtek.c
--- linux-3.6-rc4.orig/drivers/net/phy/realtek.c	2012-09-01 19:39:58.000000000 +0200
+++ linux-3.6-rc4/drivers/net/phy/realtek.c	2012-09-10 11:11:49.000000000 +0200
@@ -57,6 +57,7 @@ static struct phy_driver rtl821x_driver 
 	.features	= PHY_GBIT_FEATURES,
 	.flags		= PHY_HAS_INTERRUPT,
 	.config_aneg	= &genphy_config_aneg,
+	.aneg_done	= genphy_aneg_done,
 	.read_status	= &genphy_read_status,
 	.ack_interrupt	= &rtl821x_ack_interrupt,
 	.config_intr	= &rtl821x_config_intr,
diff -uprN linux-3.6-rc4.orig/drivers/net/phy/smsc.c linux-3.6-rc4/drivers/net/phy/smsc.c
--- linux-3.6-rc4.orig/drivers/net/phy/smsc.c	2012-09-01 19:39:58.000000000 +0200
+++ linux-3.6-rc4/drivers/net/phy/smsc.c	2012-09-10 11:11:35.000000000 +0200
@@ -73,6 +73,7 @@ static struct phy_driver smsc_phy_driver
 
 	/* basic functions */
 	.config_aneg	= genphy_config_aneg,
+	.aneg_done	= genphy_aneg_done,
 	.read_status	= genphy_read_status,
 	.config_init	= smsc_phy_config_init,
 
@@ -95,6 +96,7 @@ static struct phy_driver smsc_phy_driver
 
 	/* basic functions */
 	.config_aneg	= genphy_config_aneg,
+	.aneg_done	= genphy_aneg_done,
 	.read_status	= genphy_read_status,
 	.config_init	= smsc_phy_config_init,
 
@@ -117,6 +119,7 @@ static struct phy_driver smsc_phy_driver
 
 	/* basic functions */
 	.config_aneg	= genphy_config_aneg,
+	.aneg_done	= genphy_aneg_done,
 	.read_status	= genphy_read_status,
 	.config_init	= smsc_phy_config_init,
 
@@ -139,6 +142,7 @@ static struct phy_driver smsc_phy_driver
 
 	/* basic functions */
 	.config_aneg	= genphy_config_aneg,
+	.aneg_done	= genphy_aneg_done,
 	.read_status	= genphy_read_status,
 	.config_init	= lan911x_config_init,
 
@@ -161,6 +165,7 @@ static struct phy_driver smsc_phy_driver
 
 	/* basic functions */
 	.config_aneg	= genphy_config_aneg,
+	.aneg_done	= genphy_aneg_done,
 	.read_status	= genphy_read_status,
 	.config_init	= smsc_phy_config_init,
 
diff -uprN linux-3.6-rc4.orig/drivers/net/phy/ste10Xp.c linux-3.6-rc4/drivers/net/phy/ste10Xp.c
--- linux-3.6-rc4.orig/drivers/net/phy/ste10Xp.c	2012-09-01 19:39:58.000000000 +0200
+++ linux-3.6-rc4/drivers/net/phy/ste10Xp.c	2012-09-10 11:10:37.000000000 +0200
@@ -90,6 +90,7 @@ static struct phy_driver ste10xp_pdriver
 	.flags = PHY_HAS_INTERRUPT,
 	.config_init = ste10Xp_config_init,
 	.config_aneg = genphy_config_aneg,
+	.aneg_done = genphy_aneg_done,
 	.read_status = genphy_read_status,
 	.ack_interrupt = ste10Xp_ack_interrupt,
 	.config_intr = ste10Xp_config_intr,
@@ -104,6 +105,7 @@ static struct phy_driver ste10xp_pdriver
 	.flags = PHY_HAS_INTERRUPT,
 	.config_init = ste10Xp_config_init,
 	.config_aneg = genphy_config_aneg,
+	.aneg_done = genphy_aneg_done,
 	.read_status = genphy_read_status,
 	.ack_interrupt = ste10Xp_ack_interrupt,
 	.config_intr = ste10Xp_config_intr,
diff -uprN linux-3.6-rc4.orig/drivers/net/phy/vitesse.c linux-3.6-rc4/drivers/net/phy/vitesse.c
--- linux-3.6-rc4.orig/drivers/net/phy/vitesse.c	2012-09-01 19:39:58.000000000 +0200
+++ linux-3.6-rc4/drivers/net/phy/vitesse.c	2012-09-10 11:06:28.000000000 +0200
@@ -160,6 +160,7 @@ static struct phy_driver vsc82xx_driver[
 	.flags		= PHY_HAS_INTERRUPT,
 	.config_init	= &vsc824x_config_init,
 	.config_aneg	= &genphy_config_aneg,
+	.aneg_done	= genphy_aneg_done,
 	.read_status	= &genphy_read_status,
 	.ack_interrupt	= &vsc824x_ack_interrupt,
 	.config_intr	= &vsc82xx_config_intr,
@@ -173,6 +174,7 @@ static struct phy_driver vsc82xx_driver[
 	.flags		= PHY_HAS_INTERRUPT,
 	.config_init	= &vsc8221_config_init,
 	.config_aneg	= &genphy_config_aneg,
+	.aneg_done	= genphy_aneg_done,
 	.read_status	= &genphy_read_status,
 	.ack_interrupt	= &vsc824x_ack_interrupt,
 	.config_intr	= &vsc82xx_config_intr,
diff -uprN linux-3.6-rc4.orig/include/linux/phy.h linux-3.6-rc4/include/linux/phy.h
--- linux-3.6-rc4.orig/include/linux/phy.h	2012-09-01 19:39:58.000000000 +0200
+++ linux-3.6-rc4/include/linux/phy.h	2012-09-06 15:06:40.000000000 +0200
@@ -369,8 +369,8 @@ struct phy_device {
  * flags: A bitfield defining certain other features this PHY
  *   supports (like interrupts)
  *
- * The drivers must implement config_aneg and read_status.  All
- * other functions are optional. Note that none of these
+ * The drivers must implement config_aneg, aneg_done  and read_status.
+ * All other functions are optional. Note that none of these
  * functions should be called from interrupt time.  The goal is
  * for the bus read/write functions to be able to block when the
  * bus transaction is happening, and be freed up by an interrupt
@@ -408,6 +408,13 @@ struct phy_driver {
 	 */
 	int (*config_aneg)(struct phy_device *phydev);
 
+	/*
+	 * Reads auto-negotiation status. Returns positive value if
+	 * auto-negotiation is complete, 0 if incomplete and negative
+	 * value on error
+	 */
+	int (*aneg_done)(struct phy_device *phydev);
+
 	/* Determines the negotiated speed and duplex */
 	int (*read_status)(struct phy_device *phydev);
 
@@ -528,6 +535,7 @@ static inline int phy_read_status(struct
 
 int genphy_restart_aneg(struct phy_device *phydev);
 int genphy_config_aneg(struct phy_device *phydev);
+int genphy_aneg_done(struct phy_device *phydev);
 int genphy_update_link(struct phy_device *phydev);
 int genphy_read_status(struct phy_device *phydev);
 int genphy_suspend(struct phy_device *phydev);

^ permalink raw reply

* Re: [tcpdump-workers] Modular arithmetic
From: Daniel Borkmann @ 2012-09-10 11:49 UTC (permalink / raw)
  To: David Laight
  Cc: Eric Dumazet, Andi Kleen, George Bakos, tcpdump-workers,
	Jay Schulist, netdev
In-Reply-To: <AE90C24D6B3A694183C094C60CF0A2F6026B6FE5@saturn3.aculab.com>

On Mon, Sep 10, 2012 at 12:41 PM, David Laight <David.Laight@aculab.com> wrote:
>> > What about the other OS - eg all the BSDs?
>> > I had a vague idea that BPF was supposed to be reasonable portable.
>>
>> Yes, does it mean BPF is frozen ?
>>
>> Or is BSD so hard to update these days ?
>
> Not really - but it some other places that need updating in order
> to make this useful for cross-platform tools (like tcpdump).
>
> The 'real fun (tm)' happens when NetBSD tries to run Linux binaries
> that include the Linux libpcap.

Correct me if I'm wrong, but if you want to run the _Linux_ version of
libpcap, then you would also need PF_PACKET's RX_RING API in NetBSD.
Otherwise, it doesn't run either. Probably then this BPF instruction
is the smaller problem for NetBSD.

^ permalink raw reply

* [PATCH] Generalise "auto-negotiation done" function, move generic PHY code to phy_device.c
From: Alexander Sverdlin @ 2012-09-10 11:30 UTC (permalink / raw)
  To: netdev, Andy Fleming; +Cc: Alexander Sverdlin

From: Alexander Sverdlin <alexander.sverdlin@sysgo.com>

Generalise "auto-negotiation done" function, move generic PHY code to phy_device.c 

Not all devices have "auto-negotiation done" bit at the place, as expected by
phy_aneg_done() in phy.c. Example of such device is Marvell 88E61xx Ethernet 
switch which could be controlled by Linux PHY layer, if struct phy_driver had
abstraction for above function. So move hardware-dependent implementation details
for "generic" PHY to phy_device.c, and modify all PHY drivers to use new field.
Now phy.c contains only high-level state-machine functionality, leaving 
hardware-layer to different drivers.

Signed-off-by: Alexander Sverdlin <alexander.sverdlin@sysgo.com>
---
diff -uprN linux-3.6-rc4.orig/Documentation/networking/phy.txt linux-3.6-rc4/Documentation/networking/phy.txt
--- linux-3.6-rc4.orig/Documentation/networking/phy.txt	2012-09-01 19:39:58.000000000 +0200
+++ linux-3.6-rc4/Documentation/networking/phy.txt	2012-09-10 10:54:52.000000000 +0200
@@ -1,7 +1,7 @@
 
 -------
 PHY Abstraction Layer
-(Updated 2008-04-08)
+(Updated 2012-09-06)
 
 Purpose
 
@@ -257,15 +257,16 @@ Writing a PHY driver
    probe: Does any setup needed by the driver
    suspend/resume: power management
    config_aneg: Changes the speed/duplex/negotiation settings
+   aneg_done: Reads current auto-negotiation state
    read_status: Reads the current speed/duplex/negotiation settings
    ack_interrupt: Clear a pending interrupt
    config_intr: Enable or disable interrupts
    remove: Does any driver take-down
 
- Of these, only config_aneg and read_status are required to be
+ Of these, only config_aneg, aneg_done and read_status are required to be
  assigned by the driver code.  The rest are optional.  Also, it is
- preferred to use the generic phy driver's versions of these two
- functions if at all possible: genphy_read_status and
+ preferred to use the generic phy driver's versions of these three
+ functions if at all possible: genphy_read_status, genphy_aneg_done and
  genphy_config_aneg.  If this is not possible, it is likely that
  you only need to perform some actions before and after invoking
  these functions, and so your functions will wrap the generic
diff -uprN linux-3.6-rc4.orig/drivers/net/phy/amd.c linux-3.6-rc4/drivers/net/phy/amd.c
--- linux-3.6-rc4.orig/drivers/net/phy/amd.c	2012-09-01 19:39:58.000000000 +0200
+++ linux-3.6-rc4/drivers/net/phy/amd.c	2012-09-10 11:04:35.000000000 +0200
@@ -69,6 +69,7 @@ static struct phy_driver am79c_driver = 
 	.flags		= PHY_HAS_INTERRUPT,
 	.config_init	= am79c_config_init,
 	.config_aneg	= genphy_config_aneg,
+	.aneg_done	= genphy_aneg_done,
 	.read_status	= genphy_read_status,
 	.ack_interrupt	= am79c_ack_interrupt,
 	.config_intr	= am79c_config_intr,
diff -uprN linux-3.6-rc4.orig/drivers/net/phy/bcm63xx.c linux-3.6-rc4/drivers/net/phy/bcm63xx.c
--- linux-3.6-rc4.orig/drivers/net/phy/bcm63xx.c	2012-09-01 19:39:58.000000000 +0200
+++ linux-3.6-rc4/drivers/net/phy/bcm63xx.c	2012-09-10 11:10:04.000000000 +0200
@@ -81,6 +81,7 @@ static struct phy_driver bcm63xx_driver[
 	.flags		= PHY_HAS_INTERRUPT,
 	.config_init	= bcm63xx_config_init,
 	.config_aneg	= genphy_config_aneg,
+	.aneg_done	= genphy_aneg_done,
 	.read_status	= genphy_read_status,
 	.ack_interrupt	= bcm63xx_ack_interrupt,
 	.config_intr	= bcm63xx_config_intr,
@@ -94,6 +95,7 @@ static struct phy_driver bcm63xx_driver[
 	.flags		= PHY_HAS_INTERRUPT,
 	.config_init	= bcm63xx_config_init,
 	.config_aneg	= genphy_config_aneg,
+	.aneg_done	= genphy_aneg_done,
 	.read_status	= genphy_read_status,
 	.ack_interrupt	= bcm63xx_ack_interrupt,
 	.config_intr	= bcm63xx_config_intr,
diff -uprN linux-3.6-rc4.orig/drivers/net/phy/bcm87xx.c linux-3.6-rc4/drivers/net/phy/bcm87xx.c
--- linux-3.6-rc4.orig/drivers/net/phy/bcm87xx.c	2012-09-01 19:39:58.000000000 +0200
+++ linux-3.6-rc4/drivers/net/phy/bcm87xx.c	2012-09-10 11:10:59.000000000 +0200
@@ -195,6 +195,7 @@ static struct phy_driver bcm87xx_driver[
 	.flags		= PHY_HAS_INTERRUPT,
 	.config_init	= bcm87xx_config_init,
 	.config_aneg	= bcm87xx_config_aneg,
+	.aneg_done	= genphy_aneg_done,
 	.read_status	= bcm87xx_read_status,
 	.ack_interrupt	= bcm87xx_ack_interrupt,
 	.config_intr	= bcm87xx_config_intr,
@@ -208,6 +209,7 @@ static struct phy_driver bcm87xx_driver[
 	.flags		= PHY_HAS_INTERRUPT,
 	.config_init	= bcm87xx_config_init,
 	.config_aneg	= bcm87xx_config_aneg,
+	.aneg_done	= genphy_aneg_done,
 	.read_status	= bcm87xx_read_status,
 	.ack_interrupt	= bcm87xx_ack_interrupt,
 	.config_intr	= bcm87xx_config_intr,
diff -uprN linux-3.6-rc4.orig/drivers/net/phy/broadcom.c linux-3.6-rc4/drivers/net/phy/broadcom.c
--- linux-3.6-rc4.orig/drivers/net/phy/broadcom.c	2012-09-01 19:39:58.000000000 +0200
+++ linux-3.6-rc4/drivers/net/phy/broadcom.c	2012-09-10 11:09:49.000000000 +0200
@@ -692,6 +692,7 @@ static struct phy_driver broadcom_driver
 	.flags		= PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
 	.config_init	= bcm54xx_config_init,
 	.config_aneg	= genphy_config_aneg,
+	.aneg_done	= genphy_aneg_done,
 	.read_status	= genphy_read_status,
 	.ack_interrupt	= bcm54xx_ack_interrupt,
 	.config_intr	= bcm54xx_config_intr,
@@ -705,6 +706,7 @@ static struct phy_driver broadcom_driver
 	.flags		= PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
 	.config_init	= bcm54xx_config_init,
 	.config_aneg	= genphy_config_aneg,
+	.aneg_done	= genphy_aneg_done,
 	.read_status	= genphy_read_status,
 	.ack_interrupt	= bcm54xx_ack_interrupt,
 	.config_intr	= bcm54xx_config_intr,
@@ -718,6 +720,7 @@ static struct phy_driver broadcom_driver
 	.flags		= PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
 	.config_init	= bcm54xx_config_init,
 	.config_aneg	= genphy_config_aneg,
+	.aneg_done	= genphy_aneg_done,
 	.read_status	= genphy_read_status,
 	.ack_interrupt	= bcm54xx_ack_interrupt,
 	.config_intr	= bcm54xx_config_intr,
@@ -731,6 +734,7 @@ static struct phy_driver broadcom_driver
 	.flags		= PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
 	.config_init	= bcm54xx_config_init,
 	.config_aneg	= genphy_config_aneg,
+	.aneg_done	= genphy_aneg_done,
 	.read_status	= genphy_read_status,
 	.ack_interrupt	= bcm54xx_ack_interrupt,
 	.config_intr	= bcm54xx_config_intr,
@@ -744,6 +748,7 @@ static struct phy_driver broadcom_driver
 	.flags		= PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
 	.config_init	= bcm54xx_config_init,
 	.config_aneg	= bcm5481_config_aneg,
+	.aneg_done	= genphy_aneg_done,
 	.read_status	= genphy_read_status,
 	.ack_interrupt	= bcm54xx_ack_interrupt,
 	.config_intr	= bcm54xx_config_intr,
@@ -757,6 +762,7 @@ static struct phy_driver broadcom_driver
 	.flags		= PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
 	.config_init	= bcm5482_config_init,
 	.config_aneg	= genphy_config_aneg,
+	.aneg_done	= genphy_aneg_done,
 	.read_status	= bcm5482_read_status,
 	.ack_interrupt	= bcm54xx_ack_interrupt,
 	.config_intr	= bcm54xx_config_intr,
@@ -770,6 +776,7 @@ static struct phy_driver broadcom_driver
 	.flags		= PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
 	.config_init	= bcm54xx_config_init,
 	.config_aneg	= genphy_config_aneg,
+	.aneg_done	= genphy_aneg_done,
 	.read_status	= genphy_read_status,
 	.ack_interrupt	= bcm54xx_ack_interrupt,
 	.config_intr	= bcm54xx_config_intr,
@@ -783,6 +790,7 @@ static struct phy_driver broadcom_driver
 	.flags		= PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
 	.config_init	= bcm54xx_config_init,
 	.config_aneg	= genphy_config_aneg,
+	.aneg_done	= genphy_aneg_done,
 	.read_status	= genphy_read_status,
 	.ack_interrupt	= bcm54xx_ack_interrupt,
 	.config_intr	= bcm54xx_config_intr,
@@ -796,6 +804,7 @@ static struct phy_driver broadcom_driver
 	.flags		= PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
 	.config_init	= bcm54xx_config_init,
 	.config_aneg	= genphy_config_aneg,
+	.aneg_done	= genphy_aneg_done,
 	.read_status	= genphy_read_status,
 	.ack_interrupt	= bcm54xx_ack_interrupt,
 	.config_intr	= bcm54xx_config_intr,
@@ -809,6 +818,7 @@ static struct phy_driver broadcom_driver
 	.flags		= PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
 	.config_init	= brcm_fet_config_init,
 	.config_aneg	= genphy_config_aneg,
+	.aneg_done	= genphy_aneg_done,
 	.read_status	= genphy_read_status,
 	.ack_interrupt	= brcm_fet_ack_interrupt,
 	.config_intr	= brcm_fet_config_intr,
@@ -822,6 +832,7 @@ static struct phy_driver broadcom_driver
 	.flags		= PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
 	.config_init	= brcm_fet_config_init,
 	.config_aneg	= genphy_config_aneg,
+	.aneg_done	= genphy_aneg_done,
 	.read_status	= genphy_read_status,
 	.ack_interrupt	= brcm_fet_ack_interrupt,
 	.config_intr	= brcm_fet_config_intr,
diff -uprN linux-3.6-rc4.orig/drivers/net/phy/cicada.c linux-3.6-rc4/drivers/net/phy/cicada.c
--- linux-3.6-rc4.orig/drivers/net/phy/cicada.c	2012-09-01 19:39:58.000000000 +0200
+++ linux-3.6-rc4/drivers/net/phy/cicada.c	2012-09-10 11:06:41.000000000 +0200
@@ -111,6 +111,7 @@ static struct phy_driver cis820x_driver[
 	.flags		= PHY_HAS_INTERRUPT,
 	.config_init	= &cis820x_config_init,
 	.config_aneg	= &genphy_config_aneg,
+	.aneg_done	= genphy_aneg_done,
 	.read_status	= &genphy_read_status,
 	.ack_interrupt	= &cis820x_ack_interrupt,
 	.config_intr	= &cis820x_config_intr,
@@ -123,6 +124,7 @@ static struct phy_driver cis820x_driver[
 	.flags		= PHY_HAS_INTERRUPT,
 	.config_init	= &cis820x_config_init,
 	.config_aneg	= &genphy_config_aneg,
+	.aneg_done	= genphy_aneg_done,
 	.read_status	= &genphy_read_status,
 	.ack_interrupt	= &cis820x_ack_interrupt,
 	.config_intr	= &cis820x_config_intr,
diff -uprN linux-3.6-rc4.orig/drivers/net/phy/davicom.c linux-3.6-rc4/drivers/net/phy/davicom.c
--- linux-3.6-rc4.orig/drivers/net/phy/davicom.c	2012-09-01 19:39:58.000000000 +0200
+++ linux-3.6-rc4/drivers/net/phy/davicom.c	2012-09-10 11:05:54.000000000 +0200
@@ -152,6 +152,7 @@ static struct phy_driver dm91xx_driver[]
 	.features	= PHY_BASIC_FEATURES,
 	.config_init	= dm9161_config_init,
 	.config_aneg	= dm9161_config_aneg,
+	.aneg_done	= genphy_aneg_done,
 	.read_status	= genphy_read_status,
 	.driver		= { .owner = THIS_MODULE,},
 }, {
@@ -161,6 +162,7 @@ static struct phy_driver dm91xx_driver[]
 	.features	= PHY_BASIC_FEATURES,
 	.config_init	= dm9161_config_init,
 	.config_aneg	= dm9161_config_aneg,
+	.aneg_done	= genphy_aneg_done,
 	.read_status	= genphy_read_status,
 	.driver		= { .owner = THIS_MODULE,},
 }, {
@@ -170,6 +172,7 @@ static struct phy_driver dm91xx_driver[]
 	.features	= PHY_BASIC_FEATURES,
 	.flags		= PHY_HAS_INTERRUPT,
 	.config_aneg	= genphy_config_aneg,
+	.aneg_done	= genphy_aneg_done,
 	.read_status	= genphy_read_status,
 	.ack_interrupt	= dm9161_ack_interrupt,
 	.config_intr	= dm9161_config_intr,
diff -uprN linux-3.6-rc4.orig/drivers/net/phy/dp83640.c linux-3.6-rc4/drivers/net/phy/dp83640.c
--- linux-3.6-rc4.orig/drivers/net/phy/dp83640.c	2012-09-01 19:39:58.000000000 +0200
+++ linux-3.6-rc4/drivers/net/phy/dp83640.c	2012-09-10 11:10:16.000000000 +0200
@@ -1257,6 +1257,7 @@ static struct phy_driver dp83640_driver 
 	.probe		= dp83640_probe,
 	.remove		= dp83640_remove,
 	.config_aneg	= genphy_config_aneg,
+	.aneg_done	= genphy_aneg_done,
 	.read_status	= genphy_read_status,
 	.ts_info	= dp83640_ts_info,
 	.hwtstamp	= dp83640_hwtstamp,
diff -uprN linux-3.6-rc4.orig/drivers/net/phy/et1011c.c linux-3.6-rc4/drivers/net/phy/et1011c.c
--- linux-3.6-rc4.orig/drivers/net/phy/et1011c.c	2012-09-01 19:39:58.000000000 +0200
+++ linux-3.6-rc4/drivers/net/phy/et1011c.c	2012-09-10 11:04:08.000000000 +0200
@@ -94,6 +94,7 @@ static struct phy_driver et1011c_driver 
 	.features	= (PHY_BASIC_FEATURES | SUPPORTED_1000baseT_Full),
 	.flags		= PHY_POLL,
 	.config_aneg	= et1011c_config_aneg,
+	.aneg_done	= genphy_aneg_done,
 	.read_status	= et1011c_read_status,
 	.driver 	= { .owner = THIS_MODULE,},
 };
diff -uprN linux-3.6-rc4.orig/drivers/net/phy/icplus.c linux-3.6-rc4/drivers/net/phy/icplus.c
--- linux-3.6-rc4.orig/drivers/net/phy/icplus.c	2012-09-01 19:39:58.000000000 +0200
+++ linux-3.6-rc4/drivers/net/phy/icplus.c	2012-09-10 11:05:27.000000000 +0200
@@ -210,6 +210,7 @@ static struct phy_driver icplus_driver[]
 	.features	= PHY_BASIC_FEATURES,
 	.config_init	= &ip175c_config_init,
 	.config_aneg	= &ip175c_config_aneg,
+	.aneg_done	= genphy_aneg_done,
 	.read_status	= &ip175c_read_status,
 	.suspend	= genphy_suspend,
 	.resume		= genphy_resume,
@@ -222,6 +223,7 @@ static struct phy_driver icplus_driver[]
 			  SUPPORTED_Asym_Pause,
 	.config_init	= &ip1001_config_init,
 	.config_aneg	= &genphy_config_aneg,
+	.aneg_done	= genphy_aneg_done,
 	.read_status	= &genphy_read_status,
 	.suspend	= genphy_suspend,
 	.resume		= genphy_resume,
@@ -236,6 +238,7 @@ static struct phy_driver icplus_driver[]
 	.ack_interrupt	= ip101a_g_ack_interrupt,
 	.config_init	= &ip101a_g_config_init,
 	.config_aneg	= &genphy_config_aneg,
+	.aneg_done	= genphy_aneg_done,
 	.read_status	= &genphy_read_status,
 	.suspend	= genphy_suspend,
 	.resume		= genphy_resume,
diff -uprN linux-3.6-rc4.orig/drivers/net/phy/lxt.c linux-3.6-rc4/drivers/net/phy/lxt.c
--- linux-3.6-rc4.orig/drivers/net/phy/lxt.c	2012-09-01 19:39:58.000000000 +0200
+++ linux-3.6-rc4/drivers/net/phy/lxt.c	2012-09-10 11:06:12.000000000 +0200
@@ -158,6 +158,7 @@ static struct phy_driver lxt97x_driver[]
 	.flags		= PHY_HAS_INTERRUPT,
 	.config_init	= lxt970_config_init,
 	.config_aneg	= genphy_config_aneg,
+	.aneg_done	= genphy_aneg_done,
 	.read_status	= genphy_read_status,
 	.ack_interrupt	= lxt970_ack_interrupt,
 	.config_intr	= lxt970_config_intr,
@@ -169,6 +170,7 @@ static struct phy_driver lxt97x_driver[]
 	.features	= PHY_BASIC_FEATURES,
 	.flags		= PHY_HAS_INTERRUPT,
 	.config_aneg	= genphy_config_aneg,
+	.aneg_done	= genphy_aneg_done,
 	.read_status	= genphy_read_status,
 	.ack_interrupt	= lxt971_ack_interrupt,
 	.config_intr	= lxt971_config_intr,
@@ -181,6 +183,7 @@ static struct phy_driver lxt97x_driver[]
 	.flags		= 0,
 	.probe		= lxt973_probe,
 	.config_aneg	= lxt973_config_aneg,
+	.aneg_done	= genphy_aneg_done,
 	.read_status	= genphy_read_status,
 	.driver		= { .owner = THIS_MODULE,},
 } };
diff -uprN linux-3.6-rc4.orig/drivers/net/phy/marvell.c linux-3.6-rc4/drivers/net/phy/marvell.c
--- linux-3.6-rc4.orig/drivers/net/phy/marvell.c	2012-09-01 19:39:58.000000000 +0200
+++ linux-3.6-rc4/drivers/net/phy/marvell.c	2012-09-10 11:07:30.000000000 +0200
@@ -713,6 +713,7 @@ static struct phy_driver marvell_drivers
 		.features = PHY_GBIT_FEATURES,
 		.flags = PHY_HAS_INTERRUPT,
 		.config_aneg = &marvell_config_aneg,
+		.aneg_done = genphy_aneg_done,
 		.read_status = &genphy_read_status,
 		.ack_interrupt = &marvell_ack_interrupt,
 		.config_intr = &marvell_config_intr,
@@ -726,6 +727,7 @@ static struct phy_driver marvell_drivers
 		.flags = PHY_HAS_INTERRUPT,
 		.config_init = &m88e1111_config_init,
 		.config_aneg = &marvell_config_aneg,
+		.aneg_done = genphy_aneg_done,
 		.read_status = &genphy_read_status,
 		.ack_interrupt = &marvell_ack_interrupt,
 		.config_intr = &marvell_config_intr,
@@ -739,6 +741,7 @@ static struct phy_driver marvell_drivers
 		.flags = PHY_HAS_INTERRUPT,
 		.config_init = &m88e1111_config_init,
 		.config_aneg = &marvell_config_aneg,
+		.aneg_done = genphy_aneg_done,
 		.read_status = &marvell_read_status,
 		.ack_interrupt = &marvell_ack_interrupt,
 		.config_intr = &marvell_config_intr,
@@ -752,6 +755,7 @@ static struct phy_driver marvell_drivers
 		.flags = PHY_HAS_INTERRUPT,
 		.config_init = &m88e1118_config_init,
 		.config_aneg = &m88e1118_config_aneg,
+		.aneg_done = genphy_aneg_done,
 		.read_status = &genphy_read_status,
 		.ack_interrupt = &marvell_ack_interrupt,
 		.config_intr = &marvell_config_intr,
@@ -764,6 +768,7 @@ static struct phy_driver marvell_drivers
 		.features = PHY_GBIT_FEATURES,
 		.flags = PHY_HAS_INTERRUPT,
 		.config_aneg = &m88e1121_config_aneg,
+		.aneg_done = genphy_aneg_done,
 		.read_status = &marvell_read_status,
 		.ack_interrupt = &marvell_ack_interrupt,
 		.config_intr = &marvell_config_intr,
@@ -777,6 +782,7 @@ static struct phy_driver marvell_drivers
 		.features = PHY_GBIT_FEATURES,
 		.flags = PHY_HAS_INTERRUPT,
 		.config_aneg = &m88e1318_config_aneg,
+		.aneg_done = genphy_aneg_done,
 		.read_status = &marvell_read_status,
 		.ack_interrupt = &marvell_ack_interrupt,
 		.config_intr = &marvell_config_intr,
@@ -791,6 +797,7 @@ static struct phy_driver marvell_drivers
 		.flags = PHY_HAS_INTERRUPT,
 		.config_init = &m88e1145_config_init,
 		.config_aneg = &marvell_config_aneg,
+		.aneg_done = genphy_aneg_done,
 		.read_status = &genphy_read_status,
 		.ack_interrupt = &marvell_ack_interrupt,
 		.config_intr = &marvell_config_intr,
@@ -804,6 +811,7 @@ static struct phy_driver marvell_drivers
 		.flags = PHY_HAS_INTERRUPT,
 		.config_init = &m88e1149_config_init,
 		.config_aneg = &m88e1118_config_aneg,
+		.aneg_done = genphy_aneg_done,
 		.read_status = &genphy_read_status,
 		.ack_interrupt = &marvell_ack_interrupt,
 		.config_intr = &marvell_config_intr,
@@ -817,6 +825,7 @@ static struct phy_driver marvell_drivers
 		.flags = PHY_HAS_INTERRUPT,
 		.config_init = &m88e1111_config_init,
 		.config_aneg = &marvell_config_aneg,
+		.aneg_done = genphy_aneg_done,
 		.read_status = &genphy_read_status,
 		.ack_interrupt = &marvell_ack_interrupt,
 		.config_intr = &marvell_config_intr,
diff -uprN linux-3.6-rc4.orig/drivers/net/phy/micrel.c linux-3.6-rc4/drivers/net/phy/micrel.c
--- linux-3.6-rc4.orig/drivers/net/phy/micrel.c	2012-09-01 19:39:58.000000000 +0200
+++ linux-3.6-rc4/drivers/net/phy/micrel.c	2012-09-10 11:07:55.000000000 +0200
@@ -123,6 +123,7 @@ static struct phy_driver ksphy_driver[] 
 	.flags		= PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
 	.config_init	= kszphy_config_init,
 	.config_aneg	= genphy_config_aneg,
+	.aneg_done	= genphy_aneg_done,
 	.read_status	= genphy_read_status,
 	.ack_interrupt	= kszphy_ack_interrupt,
 	.config_intr	= ks8737_config_intr,
@@ -136,6 +137,7 @@ static struct phy_driver ksphy_driver[] 
 	.flags		= PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
 	.config_init	= kszphy_config_init,
 	.config_aneg	= genphy_config_aneg,
+	.aneg_done	= genphy_aneg_done,
 	.read_status	= genphy_read_status,
 	.ack_interrupt	= kszphy_ack_interrupt,
 	.config_intr	= kszphy_config_intr,
@@ -149,6 +151,7 @@ static struct phy_driver ksphy_driver[] 
 	.flags		= PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
 	.config_init	= ks8051_config_init,
 	.config_aneg	= genphy_config_aneg,
+	.aneg_done	= genphy_aneg_done,
 	.read_status	= genphy_read_status,
 	.ack_interrupt	= kszphy_ack_interrupt,
 	.config_intr	= kszphy_config_intr,
@@ -161,6 +164,7 @@ static struct phy_driver ksphy_driver[] 
 	.flags		= PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
 	.config_init	= kszphy_config_init,
 	.config_aneg	= genphy_config_aneg,
+	.aneg_done	= genphy_aneg_done,
 	.read_status	= genphy_read_status,
 	.ack_interrupt	= kszphy_ack_interrupt,
 	.config_intr	= kszphy_config_intr,
@@ -174,6 +178,7 @@ static struct phy_driver ksphy_driver[] 
 	.flags		= PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
 	.config_init	= kszphy_config_init,
 	.config_aneg	= genphy_config_aneg,
+	.aneg_done	= genphy_aneg_done,
 	.read_status	= genphy_read_status,
 	.ack_interrupt	= kszphy_ack_interrupt,
 	.config_intr	= ksz9021_config_intr,
diff -uprN linux-3.6-rc4.orig/drivers/net/phy/national.c linux-3.6-rc4/drivers/net/phy/national.c
--- linux-3.6-rc4.orig/drivers/net/phy/national.c	2012-09-01 19:39:58.000000000 +0200
+++ linux-3.6-rc4/drivers/net/phy/national.c	2012-09-10 11:08:27.000000000 +0200
@@ -137,6 +137,7 @@ static struct phy_driver dp83865_driver 
 	.flags = PHY_HAS_INTERRUPT,
 	.config_init = ns_config_init,
 	.config_aneg = genphy_config_aneg,
+	.aneg_done = genphy_aneg_done,
 	.read_status = genphy_read_status,
 	.ack_interrupt = ns_ack_interrupt,
 	.config_intr = ns_config_intr,
diff -uprN linux-3.6-rc4.orig/drivers/net/phy/phy.c linux-3.6-rc4/drivers/net/phy/phy.c
--- linux-3.6-rc4.orig/drivers/net/phy/phy.c	2012-09-01 19:39:58.000000000 +0200
+++ linux-3.6-rc4/drivers/net/phy/phy.c	2012-09-10 11:24:18.000000000 +0200
@@ -95,24 +95,6 @@ static int phy_config_interrupt(struct p
 	return err;
 }
 
-
-/**
- * phy_aneg_done - return auto-negotiation status
- * @phydev: target phy_device struct
- *
- * Description: Reads the status register and returns 0 either if
- *   auto-negotiation is incomplete, or if there was an error.
- *   Returns BMSR_ANEGCOMPLETE if auto-negotiation is done.
- */
-static inline int phy_aneg_done(struct phy_device *phydev)
-{
-	int retval;
-
-	retval = phy_read(phydev, MII_BMSR);
-
-	return (retval < 0) ? retval : (retval & BMSR_ANEGCOMPLETE);
-}
-
 /* A structure for mapping a particular speed and duplex
  * combination to a particular SUPPORTED and ADVERTISED value */
 struct phy_setting {
@@ -807,7 +789,7 @@ void phy_state_machine(struct work_struc
 
 			/* Check if negotiation is done.  Break
 			 * if there's an error */
-			err = phy_aneg_done(phydev);
+			err = phydev->drv->aneg_done(phydev);
 			if (err < 0)
 				break;
 
@@ -921,7 +903,7 @@ void phy_state_machine(struct work_struc
 				break;
 
 			if (AUTONEG_ENABLE == phydev->autoneg) {
-				err = phy_aneg_done(phydev);
+				err = phydev->drv->aneg_done(phydev);
 				if (err < 0)
 					break;
 
diff -uprN linux-3.6-rc4.orig/drivers/net/phy/phy_device.c linux-3.6-rc4/drivers/net/phy/phy_device.c
--- linux-3.6-rc4.orig/drivers/net/phy/phy_device.c	2012-09-01 19:39:58.000000000 +0200
+++ linux-3.6-rc4/drivers/net/phy/phy_device.c	2012-09-06 15:00:32.000000000 +0200
@@ -785,6 +785,23 @@ int genphy_config_aneg(struct phy_device
 EXPORT_SYMBOL(genphy_config_aneg);
 
 /**
+ * genphy_aneg_done - return auto-negotiation status
+ * @phydev: target phy_device struct
+ *
+ * Description: Reads the status register and returns positive value if
+ * auto-negotiation is complete, 0 if incomplete and negative on failure.
+ */
+int genphy_aneg_done(struct phy_device *phydev)
+{
+	int retval;
+
+	retval = phy_read(phydev, MII_BMSR);
+
+	return (retval < 0) ? retval : (retval & BMSR_ANEGCOMPLETE);
+}
+EXPORT_SYMBOL(genphy_aneg_done);
+
+/**
  * genphy_update_link - update link status in @phydev
  * @phydev: target phy_device struct
  *
@@ -1117,6 +1134,7 @@ static struct phy_driver genphy_driver =
 	.config_init	= genphy_config_init,
 	.features	= 0,
 	.config_aneg	= genphy_config_aneg,
+	.aneg_done	= genphy_aneg_done,
 	.read_status	= genphy_read_status,
 	.suspend	= genphy_suspend,
 	.resume		= genphy_resume,
diff -uprN linux-3.6-rc4.orig/drivers/net/phy/qsemi.c linux-3.6-rc4/drivers/net/phy/qsemi.c
--- linux-3.6-rc4.orig/drivers/net/phy/qsemi.c	2012-09-01 19:39:58.000000000 +0200
+++ linux-3.6-rc4/drivers/net/phy/qsemi.c	2012-09-10 11:11:08.000000000 +0200
@@ -119,6 +119,7 @@ static struct phy_driver qs6612_driver =
 	.flags		= PHY_HAS_INTERRUPT,
 	.config_init	= qs6612_config_init,
 	.config_aneg	= genphy_config_aneg,
+	.aneg_done	= genphy_aneg_done,
 	.read_status	= genphy_read_status,
 	.ack_interrupt	= qs6612_ack_interrupt,
 	.config_intr	= qs6612_config_intr,
diff -uprN linux-3.6-rc4.orig/drivers/net/phy/realtek.c linux-3.6-rc4/drivers/net/phy/realtek.c
--- linux-3.6-rc4.orig/drivers/net/phy/realtek.c	2012-09-01 19:39:58.000000000 +0200
+++ linux-3.6-rc4/drivers/net/phy/realtek.c	2012-09-10 11:11:49.000000000 +0200
@@ -57,6 +57,7 @@ static struct phy_driver rtl821x_driver 
 	.features	= PHY_GBIT_FEATURES,
 	.flags		= PHY_HAS_INTERRUPT,
 	.config_aneg	= &genphy_config_aneg,
+	.aneg_done	= genphy_aneg_done,
 	.read_status	= &genphy_read_status,
 	.ack_interrupt	= &rtl821x_ack_interrupt,
 	.config_intr	= &rtl821x_config_intr,
diff -uprN linux-3.6-rc4.orig/drivers/net/phy/smsc.c linux-3.6-rc4/drivers/net/phy/smsc.c
--- linux-3.6-rc4.orig/drivers/net/phy/smsc.c	2012-09-01 19:39:58.000000000 +0200
+++ linux-3.6-rc4/drivers/net/phy/smsc.c	2012-09-10 11:11:35.000000000 +0200
@@ -73,6 +73,7 @@ static struct phy_driver smsc_phy_driver
 
 	/* basic functions */
 	.config_aneg	= genphy_config_aneg,
+	.aneg_done	= genphy_aneg_done,
 	.read_status	= genphy_read_status,
 	.config_init	= smsc_phy_config_init,
 
@@ -95,6 +96,7 @@ static struct phy_driver smsc_phy_driver
 
 	/* basic functions */
 	.config_aneg	= genphy_config_aneg,
+	.aneg_done	= genphy_aneg_done,
 	.read_status	= genphy_read_status,
 	.config_init	= smsc_phy_config_init,
 
@@ -117,6 +119,7 @@ static struct phy_driver smsc_phy_driver
 
 	/* basic functions */
 	.config_aneg	= genphy_config_aneg,
+	.aneg_done	= genphy_aneg_done,
 	.read_status	= genphy_read_status,
 	.config_init	= smsc_phy_config_init,
 
@@ -139,6 +142,7 @@ static struct phy_driver smsc_phy_driver
 
 	/* basic functions */
 	.config_aneg	= genphy_config_aneg,
+	.aneg_done	= genphy_aneg_done,
 	.read_status	= genphy_read_status,
 	.config_init	= lan911x_config_init,
 
@@ -161,6 +165,7 @@ static struct phy_driver smsc_phy_driver
 
 	/* basic functions */
 	.config_aneg	= genphy_config_aneg,
+	.aneg_done	= genphy_aneg_done,
 	.read_status	= genphy_read_status,
 	.config_init	= smsc_phy_config_init,
 
diff -uprN linux-3.6-rc4.orig/drivers/net/phy/ste10Xp.c linux-3.6-rc4/drivers/net/phy/ste10Xp.c
--- linux-3.6-rc4.orig/drivers/net/phy/ste10Xp.c	2012-09-01 19:39:58.000000000 +0200
+++ linux-3.6-rc4/drivers/net/phy/ste10Xp.c	2012-09-10 11:10:37.000000000 +0200
@@ -90,6 +90,7 @@ static struct phy_driver ste10xp_pdriver
 	.flags = PHY_HAS_INTERRUPT,
 	.config_init = ste10Xp_config_init,
 	.config_aneg = genphy_config_aneg,
+	.aneg_done = genphy_aneg_done,
 	.read_status = genphy_read_status,
 	.ack_interrupt = ste10Xp_ack_interrupt,
 	.config_intr = ste10Xp_config_intr,
@@ -104,6 +105,7 @@ static struct phy_driver ste10xp_pdriver
 	.flags = PHY_HAS_INTERRUPT,
 	.config_init = ste10Xp_config_init,
 	.config_aneg = genphy_config_aneg,
+	.aneg_done = genphy_aneg_done,
 	.read_status = genphy_read_status,
 	.ack_interrupt = ste10Xp_ack_interrupt,
 	.config_intr = ste10Xp_config_intr,
diff -uprN linux-3.6-rc4.orig/drivers/net/phy/vitesse.c linux-3.6-rc4/drivers/net/phy/vitesse.c
--- linux-3.6-rc4.orig/drivers/net/phy/vitesse.c	2012-09-01 19:39:58.000000000 +0200
+++ linux-3.6-rc4/drivers/net/phy/vitesse.c	2012-09-10 11:06:28.000000000 +0200
@@ -160,6 +160,7 @@ static struct phy_driver vsc82xx_driver[
 	.flags		= PHY_HAS_INTERRUPT,
 	.config_init	= &vsc824x_config_init,
 	.config_aneg	= &genphy_config_aneg,
+	.aneg_done	= genphy_aneg_done,
 	.read_status	= &genphy_read_status,
 	.ack_interrupt	= &vsc824x_ack_interrupt,
 	.config_intr	= &vsc82xx_config_intr,
@@ -173,6 +174,7 @@ static struct phy_driver vsc82xx_driver[
 	.flags		= PHY_HAS_INTERRUPT,
 	.config_init	= &vsc8221_config_init,
 	.config_aneg	= &genphy_config_aneg,
+	.aneg_done	= genphy_aneg_done,
 	.read_status	= &genphy_read_status,
 	.ack_interrupt	= &vsc824x_ack_interrupt,
 	.config_intr	= &vsc82xx_config_intr,
diff -uprN linux-3.6-rc4.orig/include/linux/phy.h linux-3.6-rc4/include/linux/phy.h
--- linux-3.6-rc4.orig/include/linux/phy.h	2012-09-01 19:39:58.000000000 +0200
+++ linux-3.6-rc4/include/linux/phy.h	2012-09-06 15:06:40.000000000 +0200
@@ -369,8 +369,8 @@ struct phy_device {
  * flags: A bitfield defining certain other features this PHY
  *   supports (like interrupts)
  *
- * The drivers must implement config_aneg and read_status.  All
- * other functions are optional. Note that none of these
+ * The drivers must implement config_aneg, aneg_done  and read_status.
+ * All other functions are optional. Note that none of these
  * functions should be called from interrupt time.  The goal is
  * for the bus read/write functions to be able to block when the
  * bus transaction is happening, and be freed up by an interrupt
@@ -408,6 +408,13 @@ struct phy_driver {
 	 */
 	int (*config_aneg)(struct phy_device *phydev);
 
+	/*
+	 * Reads auto-negotiation status. Returns positive value if
+	 * auto-negotiation is complete, 0 if incomplete and negative
+	 * value on error
+	 */
+	int (*aneg_done)(struct phy_device *phydev);
+
 	/* Determines the negotiated speed and duplex */
 	int (*read_status)(struct phy_device *phydev);
 
@@ -528,6 +535,7 @@ static inline int phy_read_status(struct
 
 int genphy_restart_aneg(struct phy_device *phydev);
 int genphy_config_aneg(struct phy_device *phydev);
+int genphy_aneg_done(struct phy_device *phydev);
 int genphy_update_link(struct phy_device *phydev);
 int genphy_read_status(struct phy_device *phydev);
 int genphy_suspend(struct phy_device *phydev);


-- 
Best regards,
Alexander Sverdlin.

^ permalink raw reply

* Re: [PATCHv4] virtio-spec: virtio network device multiqueue support
From: Jason Wang @ 2012-09-10 11:00 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: rick.jones2, kvm, netdev, virtualization, levinsasha928, pbonzini,
	Tom Herbert
In-Reply-To: <20120910063346.GA17338@redhat.com>

On 09/10/2012 02:33 PM, Michael S. Tsirkin wrote:
> On Mon, Sep 10, 2012 at 09:27:38AM +0300, Michael S. Tsirkin wrote:
>> On Mon, Sep 10, 2012 at 09:16:29AM +0300, Michael S. Tsirkin wrote:
>>> On Mon, Sep 10, 2012 at 11:42:25AM +0930, Rusty Russell wrote:
>>>> OK, I read the spec (pasted below for easy of reading), but I'm still
>>>> confused over how this will work.
>>>>
>>>> I thought normal net drivers have the hardware provide an rxhash for
>>>> each packet, and we map that to CPU to queue the packet on[1].  We hope
>>>> that the receiving process migrates to that CPU, so xmit queue
>>>> matches.
>>> This ony works sometimes.  For example it's common to pin netperf to a
>>> cpu to get consistent performance.  Proper hardware must obey what
>>> applications want it to do, not the other way around.
>>>
>>>> For virtio this would mean a new per-packet rxhash value, right?
>>>>
>>>> Why are we doing something different?  What am I missing?
>>>>
>>>> Thanks,
>>>> Rusty.
>>>> [1] Everything I Know About Networking I Learned From LWN:
>>>>      https://lwn.net/Articles/362339/
>>> I think you missed this:
>>>
>>> 	Some network interfaces can help with the distribution of incoming
>>> 	packets; they have multiple receive queues and multiple interrupt lines.
>>> 	Others, though, are equipped with a single queue, meaning that the
>>> 	driver for that hardware must deal with all incoming packets in a
>>> 	single, serialized stream. Parallelizing such a stream requires some
>>> 	intelligence on the part of the host operating system.
>>>
>>> In other words RPS is a hack to speed up networking on cheapo
>>> hardware, this is one of the reasons it is off by default.
>>> Good hardware has multiple receive queues.
>>> We can implement a good one so we do not need RPS.
>>>
>>> Also not all guest OS-es support RPS.
>>>
>>> Does this clarify?
>> I would like to add that on many processors, sending
>> IPCs between guest CPUs requires exits on sending *and*
>> receiving path, making it very expensive.
> A final addition: what you suggest above would be
> "TX follows RX", right?
> It is in anticipation of something like that, that I made
> steering programming so generic.
> I think TX follows RX is more immediately useful for reasons above
> but we can add both to spec and let drivers and devices
> decide what they want to support.
> Pls let me know.

AFAIK, ixgbe does "rx follows tx". The only differences between ixgbe 
and virtio-net is that ixgbe driver programs the flow director during 
packet transmission but we suggest to do it silently in the device for 
simplicity. Even with this, more co-operation is still needed for the 
driver ( e.g ixgbe try to use per-cpu queue by setting affinity hint and 
using cpuid to choose the txq which could be reused in virtio-net driver).
>
>>>> ---
>>>> Transmit Packet Steering
>>>>
>>>> When VIRTIO_NET_F_MULTIQUEUE feature bit is negotiated, guest can use any of multiple configured transmit queues to transmit a given packet. To avoid packet reordering by device (which generally leads to performance degradation) driver should attempt to utilize the same transmit virtqueue for all packets of a given transmit flow. For bi-directional protocols (in practice, TCP), a given network connection can utilize both transmit and receive queues. For best performance, packets from a single connection should utilize the paired transmit and receive queues from the same virtqueue pair; for example both transmitqN and receiveqN. This rule makes it possible to optimize processing on the device side, but this is not a hard requirement: devices should function correctly even when this rul
 e is not followed.
>>>>
>>>> Driver selects an active steering rule using VIRTIO_NET_CTRL_STEERING command (this controls both which virtqueue is selected for a given packet for receive and notifies the device which virtqueues are about to be used for transmit).
>>>>
>>>> This command accepts a single out argument in the following format:
>>>>
>>>> #define VIRTIO_NET_CTRL_STEERING               4
>>>>
>>>> The field rule specifies the function used to select transmit virtqueue for a given packet; the field param makes it possible to pass an extra parameter if appropriate. When rule is set to VIRTIO_NET_CTRL_STEERING_SINGLE (this is the default) all packets are steered to the default virtqueue transmitq (1); param is unused; this is the default. With any other rule, When rule is set to VIRTIO_NET_CTRL_STEERING_RX_FOLLOWS_TX packets are steered by driver to the first N=(param+1) multiqueue virtqueues transmitq1...transmitqN; the default transmitq is unused. Driver must have configured all these (param+1) virtqueues beforehand.
>>>>
>>>> Supported steering rules can be added and removed in the future. Driver should check that the request to change the steering rule was successful by checking ack values of the command. As selecting a specific steering is an optimization feature, drivers should avoid hard failure and fall back on using a supported steering rule if this command fails. The default steering rule is VIRTIO_NET_CTRL_STEERING_SINGLE. It will not be removed.
>>>>
>>>> When the steering rule is modified, some packets can still be outstanding in one or more of the transmit virtqueues. Since drivers might choose to modify the current steering rule at a high rate (e.g. adaptively in response to changes in the workload) to avoid reordering packets, device is recommended to complete processing of the transmit queue(s) utilized by the original steering before processing any packets delivered by the modified steering rule.
>>>>
>>>> For debugging, the current steering rule can also be read from the configuration space.
>>>>
>>>> Receive Packet Steering
>>>>
>>>> When VIRTIO_NET_F_MULTIQUEUE feature bit is negotiated, device can use any of multiple configured receive queues to pass a given packet to driver. Driver controls which virtqueue is selected in practice by configuring packet steering rule using VIRTIO_NET_CTRL_STEERING command, as described above[sub:Transmit-Packet-Steering].
>>>>
>>>> The field rule specifies the function used to select receive virtqueue for a given packet; the field param makes it possible to pass an extra parameter if appropriate. When rule is set to VIRTIO_NET_CTRL_STEERING_SINGLE all packets are steered to the default virtqueue receiveq (0); param is unused; this is the default. When rule is set to VIRTIO_NET_CTRL_STEERING_RX_FOLLOWS_TX packets are steered by host to the first N=(param+1) multiqueue virtqueues receiveq1...receiveqN; the default receiveq is unused. Driver must have configured all these (param+1) virtqueues beforehand. For best performance for bi-directional flows (such as TCP) device should detect the flow to virtqueue pair mapping on transmit and select the receive virtqueue from the same virtqueue pair. For uni-directional flo
 ws, or when this mapping information is missing, a device-specific steering function is used.
>>>>
>>>> Supported steering rules can be added and removed in the future. Driver should probe for supported rules by checking ack values of the command.
>>>>
>>>> When the steering rule is modified, some packets can still be outstanding in one or more of the virtqueues. Device is not required to wait for these packets to be consumed before delivering packets using the new streering rule. Drivers modifying the steering rule at a high rate (e.g. adaptively in response to changes in the workload) are recommended to complete processing of the receive queue(s) utilized by the original steering before processing any packets delivered by the modified steering rule.
> --
> To unsubscribe from this list: send the line "unsubscribe kvm" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: Modular arithmetic
From: David Laight @ 2012-09-10 10:41 UTC (permalink / raw)
  To: Eric Dumazet; +Cc: netdev, Jay Schulist, Andi Kleen, tcpdump-workers
In-Reply-To: <1347269124.1234.1326.camel@edumazet-glaptop>

> > What about the other OS - eg all the BSDs?
> > I had a vague idea that BPF was supposed to be reasonable portable.
> 
> Yes, does it mean BPF is frozen ?
> 
> Or is BSD so hard to update these days ?

Not really - but it some other places that need updating in order
to make this useful for cross-platform tools (like tcpdump).

The 'real fun (tm)' happens when NetBSD tries to run Linux binaries
that include the Linux libpcap.

	David
_______________________________________________
tcpdump-workers mailing list
tcpdump-workers@lists.tcpdump.org
https://lists.sandelman.ca/mailman/listinfo/tcpdump-workers

^ permalink raw reply

* Re: kernel 3.5.2/amd64: iwlwifi 0000:03:00.0: failed to allocate pci memory
From: Johannes Berg @ 2012-09-10 10:24 UTC (permalink / raw)
  To: Marc MERLIN
  Cc: wey-yi.w.guy-ral2JQCrhuEAvxtiuMwx3w, ilw-VuQAYsv1563Yd54FQh9/CA,
	linux-wireless-u79uwXL29TY76Z2rM5mHXA,
	netdev-q7rQbLoQdy39qxiX1TGQuw
In-Reply-To: <1347130641.11167.0.camel-8Nb76shvtaUJvtFkdXX2HixXY32XiHfO@public.gmane.org>

On Sat, 2012-09-08 at 20:57 +0200, Johannes Berg wrote:

> > [856806.497959]  [<ffffffff810cf54c>] warn_alloc_failed+0x117/0x12c
> > [856806.497963]  [<ffffffff810d23af>] __alloc_pages_nodemask+0x6e3/0x792
> > [856806.497969]  [<ffffffff812b7f41>] ? pfn_to_dma_pte+0x116/0x15e
> > [856806.497976]  [<ffffffff810ff58b>] alloc_pages_current+0xcd/0xee
> > [856806.497979]  [<ffffffff810cecca>] __get_free_pages+0x9/0x45
> > [856806.497982]  [<ffffffff812ba67d>] intel_alloc_coherent+0x84/0xe7
> > [856806.497986]  [<ffffffff81085cf8>] ? arch_local_irq_save+0x15/0x1b
> > [856806.497999]  [<ffffffffa0b84afc>] iwl_ucode_callback+0xa49/0xc0d [iwlwifi]
> 
> Yes, unfortunately we need a whole bunch of contiguous memory to load
> the firmware.
> 
> > Any ideas?
> 
> Nothing we can do from the driver side, I'm afraid.

Turns out I was wrong. Here's a patch you can test. Note that we still
need a lot of DMA-coherent memory for other things, but at least for the
firmware image we don't.

http://p.sipsolutions.net/11ea33b376a5bac5.txt

johannes

--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH -next v1] wireless: ath9k-htc: only load firmware in need
From: Mohammed Shafi @ 2012-09-10 10:23 UTC (permalink / raw)
  To: Ming Lei
  Cc: linux-wireless, netdev, ath9k-devel, Luis R. Rodriguez,
	Jouni Malinen, Vasanthakumar Thiagarajan, Senthil Balasubramanian,
	John W. Linville
In-Reply-To: <CACVXFVPX1NB5uJ6yXkNbDWoX4OVdYfRU_=tsWC529-tH+3WfDA@mail.gmail.com>

Hi,

On Sat, Sep 1, 2012 at 10:41 AM, Ming Lei <ming.lei@canonical.com> wrote:
> On Tue, Aug 21, 2012 at 4:04 PM, Ming Lei <ming.lei@canonical.com> wrote:
>> It is not necessary to hold the firmware memory during the whole
>> driver lifetime, and obviously it does waste memory. Suppose there
>> are 4 ath9k-htc usb dongles working, kernel has to consume about
>> 4*50KBytes RAM to cache firmware for all dongles. After applying the
>> patch, kernel only caches one single firmware image in RAM for
>> all ath9k-htc devices just during system suspend/resume cycle.
>>
>> When system is ready for loading firmware, ath9k-htc can request
>> the loading from usersapce. During system resume, ath9k-htc still
>> can load the firmware which was cached in kernel memory before
>> system suspend.
>>
>> Cc: ath9k-devel@lists.ath9k.org
>> Cc: "Luis R. Rodriguez" <mcgrof@qca.qualcomm.com>
>> Cc: Jouni Malinen <jouni@qca.qualcomm.com>
>> Cc: Vasanthakumar Thiagarajan <vthiagar@qca.qualcomm.com>
>> Cc: Senthil Balasubramanian <senthilb@qca.qualcomm.com>
>> Cc: "John W. Linville" <linville@tuxdriver.com>
>> Signed-off-by: Ming Lei <ming.lei@canonical.com>
>> ---
>> v1:
>>         fix double free of firmware in failue path of
>>         ath9k_hif_usb_firmware_cb
>
> Gentle ping, :-)

this patch is now in wireless-testing :-)

>
>
> Thanks,
> --
> Ming Lei
> --
> To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html



-- 
thanks,
shafi

^ permalink raw reply

* hi!:) I am Dannielle:)
From: Dannielle Kearney @ 2012-09-10 10:15 UTC (permalink / raw)
  To: latinboy12345@yahoo.com

My name is Dannielle by the way.
It's exciting, isn't it?))))

^ permalink raw reply

* Re: Failure to send fragmented IP packet in case of missing ARP entry
From: Eric Dumazet @ 2012-09-10  9:53 UTC (permalink / raw)
  To: Andrei Dolnikov; +Cc: netdev
In-Reply-To: <1347270171.1234.1353.camel@edumazet-glaptop>

On Mon, 2012-09-10 at 11:42 +0200, Eric Dumazet wrote:
> On Mon, 2012-09-10 at 12:59 +0400, Andrei Dolnikov wrote:
> > Hello all,
> > 
> > The following issue is observed on most Linux distributions:
> > Transmission of fragmented IP packets in case of missing ARP entry for 
> > destination IP fails.
> > Actually ARP request is sent, and, once ARP response is received, only 
> > few queued fragments are transmitted. Remaining fragments are lost.
> > It can be easily reproduced as follows:
> >      # arp -d <dst IP>
> >      # ping -s 65000 -c 1 <dst IP>
> > Ping result is: "1 packets transmitted, 0 received, 100% packet loss, 
> > time 0ms".
> > 
> > The latest kernel version I tried was 3.5.0-1 x86_64, but I also was 
> > able to reproduce it with 3.2.x, 3.0.x and 2.6.32.
> > It doesn't depend on hardware: was able to reproduce with VMWare Player, 
> > Intel based laptop, Intel Atom and ARM based custom boards.
> > As I'm not a networking standards expert I'm not sure if it's a real bug 
> > or acceptable behaviour, but decided to raise the issue here as I can't 
> > reproduce this anomaly with the Windows 7 PC.
> > 
> > Thanks,
> > Andrei.
> > --
> 
> Its a bit better with linux-3.3, with commit
> 8b5c171bb3dc0686b2647a84e990199c5faa9ef8
> (neigh: new unresolved queue limits)
> 
> +neigh/default/unres_qlen_bytes - INTEGER
> +       The maximum number of bytes which may be used by packets
> +       queued for each unresolved address by other network layers.
> +       (added in linux 3.3)
> +
> +neigh/default/unres_qlen - INTEGER
> +       The maximum number of packets which may be queued for each
> +       unresolved address by other network layers.
> +       (deprecated in linux 3.3) : use unres_qlen_bytes instead.
> 
> 
> Problem is : unres_qlen_bytes default value is 65536, so its a bit too
> small once you take into account truesize overhead
> 
> I guess following patch would be needed :
> 
> diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c
> index 4780045..3395bb6 100644
> --- a/net/ipv4/arp.c
> +++ b/net/ipv4/arp.c
> @@ -171,7 +171,7 @@ struct neigh_table arp_tbl = {
>  		.gc_staletime		= 60 * HZ,
>  		.reachable_time		= 30 * HZ,
>  		.delay_probe_time	= 5 * HZ,
> -		.queue_len_bytes	= 64*1024,
> +		.queue_len_bytes	= 64 * SKB_TRUESIZE(1024),
>  		.ucast_probes		= 3,
>  		.mcast_probes		= 3,
>  		.anycast_delay		= 1 * HZ,

In the mean time, you can also do

echo 50 >/proc/sys/net/ipv4/neigh/eth0/unres_qlen

(change eth0 by the name of your interface)

^ permalink raw reply

* Re: net/ipv4/route.c:645 suspicious rcu_dereference_check() usage!
From: Eric Dumazet @ 2012-09-10  9:46 UTC (permalink / raw)
  To: chris; +Cc: netdev, linux-kernel
In-Reply-To: <84c8a8$5m6f27@orsmga001.jf.intel.com>

On Mon, 2012-09-10 at 09:44 +0100, chris@chris-wilson.co.uk wrote:
> I've not seen this reported yet, so here's a warning that happens
> occasionally:
> 
> [192979.475833] 
> [192979.475840] ===============================
> [192979.475841] [ INFO: suspicious RCU usage. ]
> [192979.475844] 3.6.0-rc2+ #33 Not tainted
> [192979.475846] -------------------------------
> [192979.475848] net/ipv4/route.c:645 suspicious rcu_dereference_check() usage!
> [192979.475850] 
> [192979.475850] other info that might help us debug this:
> [192979.475850] 
> [192979.475853] 
> [192979.475853] rcu_scheduler_active = 1, debug_locks = 0
> [192979.475856] 2 locks held by firefox-bin/4634:
> [192979.475858]  #0:  (slock-AF_INET){+.-...}, at: [<ffffffff814261b4>] release_sock+0x34/0x1e0
> [192979.475870]  #1:  (fnhe_lock){+.-...}, at: [<ffffffff81461c94>] update_or_create_fnhe.isra.30+0x44/0x480
> [192979.475878] 
> [192979.475878] stack backtrace:
> [192979.475881] Pid: 4634, comm: firefox-bin Not tainted 3.6.0-rc2+ #33
> [192979.475883] Call Trace:
> [192979.475891]  [<ffffffff810903cd>] lockdep_rcu_suspicious+0xfd/0x130
> [192979.475895]  [<ffffffff81461e8e>] update_or_create_fnhe.isra.30+0x23e/0x480
> [192979.475899]  [<ffffffff814624ba>] __ip_rt_update_pmtu.isra.31+0x6a/0xb0
> [192979.475903]  [<ffffffff81465038>] ip_rt_update_pmtu+0x48/0xd0
> [192979.475907]  [<ffffffff814759b1>] inet_csk_update_pmtu+0x31/0x80
> [192979.475912]  [<ffffffff8148b663>] tcp_v4_mtu_reduced+0x33/0xd0
> [192979.475915]  [<ffffffff814888be>] tcp_release_cb+0x5e/0xb0
> [192979.475919]  [<ffffffff81426289>] release_sock+0x109/0x1e0
> [192979.475922]  [<ffffffff81479037>] tcp_sendmsg+0x527/0x1030
> [192979.475927]  [<ffffffff814a4d9d>] inet_sendmsg+0xed/0x240
> [192979.475931]  [<ffffffff814a4cb0>] ? inet_autobind+0x70/0x70
> [192979.475934]  [<ffffffff81424e8a>] ? sock_update_classid+0xaa/0x370
> [192979.475937]  [<ffffffff81424eb8>] ? sock_update_classid+0xd8/0x370
> [192979.475941]  [<ffffffff8141ee1b>] sock_sendmsg+0xab/0xe0
> [192979.475946]  [<ffffffff814222be>] sys_sendto+0x11e/0x160
> [192979.475951]  [<ffffffff8153e547>] ? sysret_check+0x1b/0x56
> [192979.475956]  [<ffffffff8125849e>] ? trace_hardirqs_on_thunk+0x3a/0x3f
> [192979.475960]  [<ffffffff8153e522>] system_call_fastpath+0x16/0x1b
> 

Probably already fixed in commit c5ae7d41927d (ipv4: must use rcu
protection while calling fib_lookup)

3.6.0-rc2 is quite old for a dev kernel ;)

Thanks

^ permalink raw reply

* Re: Failure to send fragmented IP packet in case of missing ARP entry
From: Eric Dumazet @ 2012-09-10  9:42 UTC (permalink / raw)
  To: Andrei Dolnikov; +Cc: netdev
In-Reply-To: <504DAC02.8040808@cogentembedded.com>

On Mon, 2012-09-10 at 12:59 +0400, Andrei Dolnikov wrote:
> Hello all,
> 
> The following issue is observed on most Linux distributions:
> Transmission of fragmented IP packets in case of missing ARP entry for 
> destination IP fails.
> Actually ARP request is sent, and, once ARP response is received, only 
> few queued fragments are transmitted. Remaining fragments are lost.
> It can be easily reproduced as follows:
>      # arp -d <dst IP>
>      # ping -s 65000 -c 1 <dst IP>
> Ping result is: "1 packets transmitted, 0 received, 100% packet loss, 
> time 0ms".
> 
> The latest kernel version I tried was 3.5.0-1 x86_64, but I also was 
> able to reproduce it with 3.2.x, 3.0.x and 2.6.32.
> It doesn't depend on hardware: was able to reproduce with VMWare Player, 
> Intel based laptop, Intel Atom and ARM based custom boards.
> As I'm not a networking standards expert I'm not sure if it's a real bug 
> or acceptable behaviour, but decided to raise the issue here as I can't 
> reproduce this anomaly with the Windows 7 PC.
> 
> Thanks,
> Andrei.
> --

Its a bit better with linux-3.3, with commit
8b5c171bb3dc0686b2647a84e990199c5faa9ef8
(neigh: new unresolved queue limits)

+neigh/default/unres_qlen_bytes - INTEGER
+       The maximum number of bytes which may be used by packets
+       queued for each unresolved address by other network layers.
+       (added in linux 3.3)
+
+neigh/default/unres_qlen - INTEGER
+       The maximum number of packets which may be queued for each
+       unresolved address by other network layers.
+       (deprecated in linux 3.3) : use unres_qlen_bytes instead.


Problem is : unres_qlen_bytes default value is 65536, so its a bit too
small once you take into account truesize overhead

I guess following patch would be needed :

diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c
index 4780045..3395bb6 100644
--- a/net/ipv4/arp.c
+++ b/net/ipv4/arp.c
@@ -171,7 +171,7 @@ struct neigh_table arp_tbl = {
 		.gc_staletime		= 60 * HZ,
 		.reachable_time		= 30 * HZ,
 		.delay_probe_time	= 5 * HZ,
-		.queue_len_bytes	= 64*1024,
+		.queue_len_bytes	= 64 * SKB_TRUESIZE(1024),
 		.ucast_probes		= 3,
 		.mcast_probes		= 3,
 		.anycast_delay		= 1 * HZ,

^ permalink raw reply related

* Re: [PATCH net] ixp4xx_hss: fix build failure after logging conversion
From: Florian Fainelli @ 2012-09-10  9:35 UTC (permalink / raw)
  To: Joe Perches; +Cc: netdev, khc, David Miller, stable
In-Reply-To: <1347267855.6069.2.camel@joe2Laptop>

On Monday 10 September 2012 02:04:15 Joe Perches wrote:
> On Mon, 2012-09-10 at 10:43 +0200, Florian Fainelli wrote:
> > Commit c75bb2c6f0cf455c23e60f14d780e841dd47f801 (ixp4xx_hss: Update to
> > current logging forms) converted the ixp4xx_hss module to use the current
> > logging macros, but forgot to include linux/module.h, leading to the
> > following build failures:
> 
> Bad explanation.
> This commit had nothing to do with any missing module.h.

You are right, this issue dates back from day one when this driver got merged, 
I will repost a v2 with the proper commit.
--
Florian

^ permalink raw reply

* Re: [PATCH] net, cgroup: Fix boot failure due to iteration of uninitialized list
From: Srivatsa S. Bhat @ 2012-09-10  9:29 UTC (permalink / raw)
  To: Neil Horman
  Cc: Gao feng, eric.dumazet, davem, linux-kernel, netdev,
	mark.d.rustad, john.r.fastabend, lizefan
In-Reply-To: <20120723114057.GA16518@hmsreliant.think-freely.org>

On 07/23/2012 05:10 PM, Neil Horman wrote:
> On Mon, Jul 23, 2012 at 09:15:05AM +0800, Gao feng wrote:
>> 于 2012年07月20日 00:27, Srivatsa S. Bhat 写道:
>>> After commit ef209f15 (net: cgroup: fix access the unallocated memory in
>>> netprio cgroup), boot fails with the following NULL pointer dereference:
>>>
[...]
>>> Call Trace:
>>>  [<ffffffff81b1cb78>] cgroup_init_subsys+0x83/0x169
>>>  [<ffffffff81b1ce13>] cgroup_init+0x36/0x119
>>>  [<ffffffff81affef7>] start_kernel+0x3ba/0x3ef
>>>  [<ffffffff81aff95b>] ? kernel_init+0x27b/0x27b
>>>  [<ffffffff81aff356>] x86_64_start_reservations+0x131/0x136
>>>  [<ffffffff81aff45e>] x86_64_start_kernel+0x103/0x112
>>> RIP  [<ffffffff8145e8d6>] cgrp_create+0xf6/0x190
>>>  RSP <ffffffff81a01ea8>
>>> CR2: 0000000000000698
>>> ---[ end trace a7919e7f17c0a725 ]---
>>> Kernel panic - not syncing: Attempted to kill the idle task!
>>>
>>> The code corresponds to:
>>>
>>> update_netdev_tables():
>>>         for_each_netdev(&init_net, dev) {
>>>                 map = rtnl_dereference(dev->priomap);  <---- HERE
>>>
>>>
>>> The list head is initialized in netdev_init(), which is called much
>>> later than cgrp_create(). So the problem is that we are calling
>>> update_netdev_tables() way too early (in cgrp_create()), which will
>>> end up traversing the not-yet-circular linked list. So at some point,
>>> the dev pointer will become NULL and hence dev->priomap becomes an
>>> invalid access.
>>>
>>> To fix this, just remove the update_netdev_tables() function entirely,
>>> since it appears that write_update_netdev_table() will handle things
>>> just fine.
>>
>> The reason I add update_netdev_tables in cgrp_create is to avoid additional
>> bound checkings when we accessing the dev->priomap.priomap.
>>
>> Eric,can we revert this commit 91c68ce2b26319248a32d7baa1226f819d283758 now?
>> I think it's safe enough to access priomap without bound check.
>>
> 
> I think its probably safe, yes, but lets leave it there for just a bit.  Its not
> hurting anything, and I'd like to look into getting Srivatsa' patch in first.

Hi Neil,

Did you get around to look into this again?

Regards,
Srivatsa S. Bhat

^ permalink raw reply

* RE: [tcpdump-workers] Modular arithmetic
From: Eric Dumazet @ 2012-09-10  9:25 UTC (permalink / raw)
  To: David Laight
  Cc: Andi Kleen, George Bakos, tcpdump-workers, Jay Schulist, netdev
In-Reply-To: <AE90C24D6B3A694183C094C60CF0A2F6026B6FE4@saturn3.aculab.com>

On Mon, 2012-09-10 at 09:41 +0100, David Laight wrote:
> > On Fri, Sep 07, 2012 at 07:49:10AM +0000, George Bakos wrote:
> > > Gents,
> > > Any fundamental reason why the following (, etc.) shouldn't be
> > > included in net/core/filter.c?
> > >
> > >                 case BPF_S_ALU_MOD_X:
> > >                         if (X == 0)
> > >                                 return 0;
> > >                         A %= X;
> > >                         continue;
> > 
> > Copying netdev.
> > 
> > In principle no reason against it, but you may need to update
> > the various BPF JITs too that Linux now has too.
> 
> What about the other OS - eg all the BSDs?
> I had a vague idea that BPF was supposed to be reasonable portable.

Yes, does it mean BPF is frozen ?

Or is BSD so hard to update these days ?

modulus can be implemented using fallback to div and sub, I am not sure
libpcap should sense kernel support or not.

George, make sure libpcap optimizer correctly replaces MOD X  by AND (X
- 1) if X is a power of two.

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox