Netdev List
 help / color / mirror / Atom feed
* [PATCH 1/3] seq_file: add RCU versions of new hlist/list iterators (v3)
From: Stephen Hemminger @ 2010-02-19 21:59 UTC (permalink / raw)
  To: Alexander Viro, Andrew Morton, Rusty Russell, Peter Oberparleiter,
	Miklos 
  Cc: netdev
In-Reply-To: <20100219215913.819285957@vyatta.com>

[-- Attachment #1: seq_hlist_rcu.patch --]
[-- Type: text/plain, Size: 3528 bytes --]

Many usages of seq_file use RCU protected lists, so non RCU
iterators will not work safely.

Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>

---
This version drops the list_rcu variants because not needed yet

 fs/seq_file.c            |   56 +++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/rculist.h  |    5 ++++
 include/linux/seq_file.h |   12 +++++++---
 3 files changed, 70 insertions(+), 3 deletions(-)

--- a/fs/seq_file.c	2010-02-18 21:46:46.978333060 -0800
+++ b/fs/seq_file.c	2010-02-19 11:22:30.540260974 -0800
@@ -750,3 +750,59 @@ struct hlist_node *seq_hlist_next(void *
 		return node->next;
 }
 EXPORT_SYMBOL(seq_hlist_next);
+
+/**
+ * seq_hlist_start_rcu - start an iteration of a hlist protected by RCU
+ * @head: the head of the hlist
+ * @pos:  the start position of the sequence
+ *
+ * Called at seq_file->op->start().
+ */
+struct hlist_node *seq_hlist_start_rcu(struct hlist_head *head, loff_t pos)
+{
+	struct hlist_node *node;
+
+	__hlist_for_each_rcu(node, head)
+		if (pos-- == 0)
+			return node;
+	return NULL;
+}
+EXPORT_SYMBOL(seq_hlist_start_rcu);
+
+/**
+ * seq_hlist_start_head_rcu - start an iteration of a hlist protected by RCU
+ * @head: the head of the hlist
+ * @pos:  the start position of the sequence
+ *
+ * Called at seq_file->op->start(). Call this function if you want to
+ * print a header at the top of the output.
+ */
+struct hlist_node *seq_hlist_start_head_rcu(struct hlist_head *head, loff_t pos)
+{
+	if (!pos)
+		return SEQ_START_TOKEN;
+
+	return seq_hlist_start_rcu(head, pos - 1);
+}
+EXPORT_SYMBOL(seq_hlist_start_head_rcu);
+
+/**
+ * seq_hlist_next_rcu - move to the next position of the hlist protected by RCU
+ * @v:    the current iterator
+ * @head: the head of the hlist
+ * @pos:  the current posision
+ *
+ * Called at seq_file->op->next().
+ */
+struct hlist_node *seq_hlist_next_rcu(void *v, struct hlist_head *head,
+				      loff_t *ppos)
+{
+	struct hlist_node *node = v;
+
+	++*ppos;
+	if (v == SEQ_START_TOKEN)
+		return rcu_dereference(head->first);
+	else
+		return rcu_dereference(node->next);
+}
+EXPORT_SYMBOL(seq_hlist_next_rcu);
--- a/include/linux/seq_file.h	2010-02-18 21:46:47.014333155 -0800
+++ b/include/linux/seq_file.h	2010-02-19 11:24:42.356546569 -0800
@@ -140,10 +140,16 @@ extern struct list_head *seq_list_next(v
  */
 
 extern struct hlist_node *seq_hlist_start(struct hlist_head *head,
-		loff_t pos);
+					  loff_t pos);
 extern struct hlist_node *seq_hlist_start_head(struct hlist_head *head,
-		loff_t pos);
+					       loff_t pos);
 extern struct hlist_node *seq_hlist_next(void *v, struct hlist_head *head,
-		loff_t *ppos);
+					 loff_t *ppos);
 
+extern struct hlist_node *seq_hlist_start_rcu(struct hlist_head *head,
+					      loff_t pos);
+extern struct hlist_node *seq_hlist_start_head_rcu(struct hlist_head *head,
+						   loff_t pos);
+extern struct hlist_node *seq_hlist_next_rcu(void *v, struct hlist_head *head,
+					     loff_t *ppos);
 #endif
--- a/include/linux/rculist.h	2010-02-18 21:46:46.998211692 -0800
+++ b/include/linux/rculist.h	2010-02-19 11:21:32.880295586 -0800
@@ -406,6 +406,11 @@ static inline void hlist_add_after_rcu(s
 		n->next->pprev = &n->next;
 }
 
+#define __hlist_for_each_rcu(pos, head)			\
+	for (pos = rcu_dereference((head)->first);	\
+	     pos && ({ prefetch(pos->next); 1; });	\
+	     pos = rcu_dereference(pos->next))
+
 /**
  * hlist_for_each_entry_rcu - iterate over rcu list of given type
  * @tpos:	the type * to use as a loop cursor.

-- 


^ permalink raw reply

* [PATCH 2/3] packet: convert socket list to RCU (v2)
From: Stephen Hemminger @ 2010-02-19 21:59 UTC (permalink / raw)
  To: Alexander Viro, Andrew Morton, Rusty Russell, Peter Oberparleiter,
	Miklos 
  Cc: netdev
In-Reply-To: <20100219215913.819285957@vyatta.com>

[-- Attachment #1: packet-list-rcu.patch --]
[-- Type: text/plain, Size: 5991 bytes --]

Convert AF_PACKET to use RCU, eliminating one more reader/writer lock.

There is no need for a real sk_del_node_init_rcu(), because sk_del_node_init
is doing the equivalent thing to hlst_del_init_rcu already; but added
some comments to try and make that obvious.

Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>

---
Incorporates Eric fix for race between notify and destroy.

 include/net/netns/packet.h |    4 ++--
 include/net/sock.h         |   10 ++++++++++
 net/packet/af_packet.c     |   42 ++++++++++++++++++++----------------------
 3 files changed, 32 insertions(+), 24 deletions(-)

--- a/include/net/netns/packet.h	2010-02-18 21:46:44.986333046 -0800
+++ b/include/net/netns/packet.h	2010-02-19 11:27:30.324174014 -0800
@@ -4,11 +4,11 @@
 #ifndef __NETNS_PACKET_H__
 #define __NETNS_PACKET_H__
 
-#include <linux/list.h>
+#include <linux/rculist.h>
 #include <linux/spinlock.h>
 
 struct netns_packet {
-	rwlock_t		sklist_lock;
+	spinlock_t		sklist_lock;
 	struct hlist_head	sklist;
 };
 
--- a/net/packet/af_packet.c	2010-02-18 21:46:44.965880598 -0800
+++ b/net/packet/af_packet.c	2010-02-19 11:33:52.345168396 -0800
@@ -1262,24 +1262,23 @@ static int packet_release(struct socket 
 	net = sock_net(sk);
 	po = pkt_sk(sk);
 
-	write_lock_bh(&net->packet.sklist_lock);
-	sk_del_node_init(sk);
+	spin_lock_bh(&net->packet.sklist_lock);
+	sk_del_node_init_rcu(sk);
 	sock_prot_inuse_add(net, sk->sk_prot, -1);
-	write_unlock_bh(&net->packet.sklist_lock);
-
-	/*
-	 *	Unhook packet receive handler.
-	 */
+	spin_unlock_bh(&net->packet.sklist_lock);
 
+	spin_lock(&po->bind_lock);
 	if (po->running) {
 		/*
-		 *	Remove the protocol hook
+		 * Remove from protocol table
+		 *  does synchronize_net()
 		 */
 		dev_remove_pack(&po->prot_hook);
 		po->running = 0;
 		po->num = 0;
 		__sock_put(sk);
 	}
+	spin_unlock(&po->bind_lock);
 
 	packet_flush_mclist(sk);
 
@@ -1478,10 +1477,11 @@ static int packet_create(struct net *net
 		po->running = 1;
 	}
 
-	write_lock_bh(&net->packet.sklist_lock);
-	sk_add_node(sk, &net->packet.sklist);
+	spin_lock_bh(&net->packet.sklist_lock);
+	sk_add_node_rcu(sk, &net->packet.sklist);
 	sock_prot_inuse_add(net, &packet_proto, 1);
-	write_unlock_bh(&net->packet.sklist_lock);
+	spin_unlock_bh(&net->packet.sklist_lock);
+
 	return 0;
 out:
 	return err;
@@ -2075,8 +2075,8 @@ static int packet_notifier(struct notifi
 	struct net_device *dev = data;
 	struct net *net = dev_net(dev);
 
-	read_lock(&net->packet.sklist_lock);
-	sk_for_each(sk, node, &net->packet.sklist) {
+	rcu_read_lock();
+	sk_for_each_rcu(sk, node, &net->packet.sklist) {
 		struct packet_sock *po = pkt_sk(sk);
 
 		switch (msg) {
@@ -2104,18 +2104,19 @@ static int packet_notifier(struct notifi
 			}
 			break;
 		case NETDEV_UP:
-			spin_lock(&po->bind_lock);
-			if (dev->ifindex == po->ifindex && po->num &&
-			    !po->running) {
-				dev_add_pack(&po->prot_hook);
-				sock_hold(sk);
-				po->running = 1;
+			if (dev->ifindex == po->ifindex) {
+				spin_lock(&po->bind_lock);
+				if (po->num && !po->running) {
+					dev_add_pack(&po->prot_hook);
+					sock_hold(sk);
+					po->running = 1;
+				}
+				spin_unlock(&po->bind_lock);
 			}
-			spin_unlock(&po->bind_lock);
 			break;
 		}
 	}
-	read_unlock(&net->packet.sklist_lock);
+	rcu_read_unlock();
 	return NOTIFY_DONE;
 }
 
@@ -2512,24 +2513,24 @@ static struct notifier_block packet_netd
 #ifdef CONFIG_PROC_FS
 
 static void *packet_seq_start(struct seq_file *seq, loff_t *pos)
-	__acquires(seq_file_net(seq)->packet.sklist_lock)
+	__acquires(RCU)
 {
 	struct net *net = seq_file_net(seq);
-	read_lock(&net->packet.sklist_lock);
-	return seq_hlist_start_head(&net->packet.sklist, *pos);
+
+	rcu_read_lock();
+	return seq_hlist_start_head_rcu(&net->packet.sklist, *pos);
 }
 
 static void *packet_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 {
 	struct net *net = seq_file_net(seq);
-	return seq_hlist_next(v, &net->packet.sklist, pos);
+	return seq_hlist_next_rcu(v, &net->packet.sklist, pos);
 }
 
 static void packet_seq_stop(struct seq_file *seq, void *v)
-	__releases(seq_file_net(seq)->packet.sklist_lock)
+	__releases(RCU)
 {
-	struct net *net = seq_file_net(seq);
-	read_unlock(&net->packet.sklist_lock);
+	rcu_read_unlock();
 }
 
 static int packet_seq_show(struct seq_file *seq, void *v)
@@ -2581,7 +2582,7 @@ static const struct file_operations pack
 
 static int __net_init packet_net_init(struct net *net)
 {
-	rwlock_init(&net->packet.sklist_lock);
+	spin_lock_init(&net->packet.sklist_lock);
 	INIT_HLIST_HEAD(&net->packet.sklist);
 
 	if (!proc_net_fops_create(net, "packet", 0, &packet_seq_fops))
--- a/include/net/sock.h	2010-02-18 21:46:44.998333363 -0800
+++ b/include/net/sock.h	2010-02-19 11:27:30.344173061 -0800
@@ -381,6 +381,7 @@ static __inline__ void __sk_del_node(str
 	__hlist_del(&sk->sk_node);
 }
 
+/* NB: equivalent to hlist_del_init_rcu */
 static __inline__ int __sk_del_node_init(struct sock *sk)
 {
 	if (sk_hashed(sk)) {
@@ -421,6 +422,7 @@ static __inline__ int sk_del_node_init(s
 	}
 	return rc;
 }
+#define sk_del_node_init_rcu(sk)	sk_del_node_init(sk)
 
 static __inline__ int __sk_nulls_del_node_init_rcu(struct sock *sk)
 {
@@ -454,6 +456,12 @@ static __inline__ void sk_add_node(struc
 	__sk_add_node(sk, list);
 }
 
+static __inline__ void sk_add_node_rcu(struct sock *sk, struct hlist_head *list)
+{
+	sock_hold(sk);
+	hlist_add_head_rcu(&sk->sk_node, list);
+}
+
 static __inline__ void __sk_nulls_add_node_rcu(struct sock *sk, struct hlist_nulls_head *list)
 {
 	hlist_nulls_add_head_rcu(&sk->sk_nulls_node, list);
@@ -478,6 +486,8 @@ static __inline__ void sk_add_bind_node(
 
 #define sk_for_each(__sk, node, list) \
 	hlist_for_each_entry(__sk, node, list, sk_node)
+#define sk_for_each_rcu(__sk, node, list) \
+	hlist_for_each_entry_rcu(__sk, node, list, sk_node)
 #define sk_nulls_for_each(__sk, node, list) \
 	hlist_nulls_for_each_entry(__sk, node, list, sk_nulls_node)
 #define sk_nulls_for_each_rcu(__sk, node, list) \

-- 


^ permalink raw reply

* [PATCH 3/3] af_key: locking change
From: Stephen Hemminger @ 2010-02-19 21:59 UTC (permalink / raw)
  To: Alexander Viro, Andrew Morton, Rusty Russell, Peter Oberparleiter,
	Miklos 
  Cc: netdev
In-Reply-To: <20100219215913.819285957@vyatta.com>

[-- Attachment #1: pfkey-rcu.patch --]
[-- Type: text/plain, Size: 4076 bytes --]

Get rid of custom locking that was using wait queue, lock, and atomic
to basically build a queued mutex.  Use RCU for read side.

Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>

--- a/net/key/af_key.c	2010-02-19 13:58:18.185494054 -0800
+++ b/net/key/af_key.c	2010-02-19 13:58:48.805994639 -0800
@@ -41,9 +41,7 @@ struct netns_pfkey {
 	struct hlist_head table;
 	atomic_t socks_nr;
 };
-static DECLARE_WAIT_QUEUE_HEAD(pfkey_table_wait);
-static DEFINE_RWLOCK(pfkey_table_lock);
-static atomic_t pfkey_table_users = ATOMIC_INIT(0);
+static DEFINE_MUTEX(pfkey_mutex);
 
 struct pfkey_sock {
 	/* struct sock must be the first member of struct pfkey_sock */
@@ -108,50 +106,6 @@ static void pfkey_sock_destruct(struct s
 	atomic_dec(&net_pfkey->socks_nr);
 }
 
-static void pfkey_table_grab(void)
-{
-	write_lock_bh(&pfkey_table_lock);
-
-	if (atomic_read(&pfkey_table_users)) {
-		DECLARE_WAITQUEUE(wait, current);
-
-		add_wait_queue_exclusive(&pfkey_table_wait, &wait);
-		for(;;) {
-			set_current_state(TASK_UNINTERRUPTIBLE);
-			if (atomic_read(&pfkey_table_users) == 0)
-				break;
-			write_unlock_bh(&pfkey_table_lock);
-			schedule();
-			write_lock_bh(&pfkey_table_lock);
-		}
-
-		__set_current_state(TASK_RUNNING);
-		remove_wait_queue(&pfkey_table_wait, &wait);
-	}
-}
-
-static __inline__ void pfkey_table_ungrab(void)
-{
-	write_unlock_bh(&pfkey_table_lock);
-	wake_up(&pfkey_table_wait);
-}
-
-static __inline__ void pfkey_lock_table(void)
-{
-	/* read_lock() synchronizes us to pfkey_table_grab */
-
-	read_lock(&pfkey_table_lock);
-	atomic_inc(&pfkey_table_users);
-	read_unlock(&pfkey_table_lock);
-}
-
-static __inline__ void pfkey_unlock_table(void)
-{
-	if (atomic_dec_and_test(&pfkey_table_users))
-		wake_up(&pfkey_table_wait);
-}
-
-
 static const struct proto_ops pfkey_ops;
 
 static void pfkey_insert(struct sock *sk)
@@ -159,16 +113,16 @@ static void pfkey_insert(struct sock *sk
 	struct net *net = sock_net(sk);
 	struct netns_pfkey *net_pfkey = net_generic(net, pfkey_net_id);
 
-	pfkey_table_grab();
-	sk_add_node(sk, &net_pfkey->table);
-	pfkey_table_ungrab();
+	mutex_lock(&pfkey_mutex);
+	sk_add_node_rcu(sk, &net_pfkey->table);
+	mutex_unlock(&pfkey_mutex);
 }
 
 static void pfkey_remove(struct sock *sk)
 {
-	pfkey_table_grab();
-	sk_del_node_init(sk);
-	pfkey_table_ungrab();
+	mutex_lock(&pfkey_mutex);
+	sk_del_node_init_rcu(sk);
+	mutex_unlock(&pfkey_mutex);
 }
 
 static struct proto key_proto = {
@@ -223,6 +177,7 @@ static int pfkey_release(struct socket *
 	sock_orphan(sk);
 	sock->sk = NULL;
 	skb_queue_purge(&sk->sk_write_queue);
+	synchronize_sched();
 	sock_put(sk);
 
 	return 0;
@@ -277,8 +232,8 @@ static int pfkey_broadcast(struct sk_buf
 	if (!skb)
 		return -ENOMEM;
 
-	pfkey_lock_table();
-	sk_for_each(sk, node, &net_pfkey->table) {
+	rcu_read_lock();
+	sk_for_each_rcu(sk, node, &net_pfkey->table) {
 		struct pfkey_sock *pfk = pfkey_sk(sk);
 		int err2;
 
@@ -309,7 +264,7 @@ static int pfkey_broadcast(struct sk_buf
 		if ((broadcast_flags & BROADCAST_REGISTERED) && err)
 			err = err2;
 	}
-	pfkey_unlock_table();
+	rcu_read_unlock();
 
 	if (one_sk != NULL)
 		err = pfkey_broadcast_one(skb, &skb2, allocation, one_sk);
@@ -3702,8 +3657,8 @@ static void *pfkey_seq_start(struct seq_
 	struct net *net = seq_file_net(f);
 	struct netns_pfkey *net_pfkey = net_generic(net, pfkey_net_id);
 
-	read_lock(&pfkey_table_lock);
-	return seq_hlist_start_head(&net_pfkey->table, *ppos);
+	rcu_read_lock();
+	return seq_hlist_start_head_rcu(&net_pfkey->table, *ppos);
 }
 
 static void *pfkey_seq_next(struct seq_file *f, void *v, loff_t *ppos)
@@ -3711,12 +3666,12 @@ static void *pfkey_seq_next(struct seq_f
 	struct net *net = seq_file_net(f);
 	struct netns_pfkey *net_pfkey = net_generic(net, pfkey_net_id);
 
-	return seq_hlist_next(v, &net_pfkey->table, ppos);
+	return seq_hlist_next_rcu(v, &net_pfkey->table, ppos);
 }
 
 static void pfkey_seq_stop(struct seq_file *f, void *v)
 {
-	read_unlock(&pfkey_table_lock);
+	rcu_read_unlock();
 }
 
 static const struct seq_operations pfkey_seq_ops = {

-- 


^ permalink raw reply

* Re: [PATCH 1/3] seq_file: add RCU versions of new hlist/list iterators (v3)
From: Al Viro @ 2010-02-19 22:22 UTC (permalink / raw)
  To: Stephen Hemminger
  Cc: Andrew Morton, Rusty Russell, Peter Oberparleiter, Miklos Szeredi,
	Eric Dumazet, Paul E. McKenney, David S. Miller, Jiri Pirko,
	Jiri Olsa, Ingo Molnar, Alexey Dobriyan, Jamal Hadi Salim,
	Neil Horman, netdev
In-Reply-To: <20100219220111.692855800@vyatta.com>

On Fri, Feb 19, 2010 at 01:59:14PM -0800, Stephen Hemminger wrote:
> Many usages of seq_file use RCU protected lists, so non RCU
> iterators will not work safely.

Looks sane, provided that you give strong warnings about access to
contents of list elements...

^ permalink raw reply

* [PATCH] packet: convert socket list to RCU (v3)
From: Stephen Hemminger @ 2010-02-19 22:23 UTC (permalink / raw)
  To: Stephen Hemminger
  Cc: Alexander Viro, Andrew Morton, Rusty Russell, Peter Oberparleiter,
	Miklos Szeredi, Eric Dumazet, Paul E. McKenney, David S. Miller,
	Jiri Pirko, Jiri Olsa, Ingo Molnar, Alexey Dobriyan,
	Jamal Hadi Salim, Neil Horman, netdev
In-Reply-To: <20100219220111.772997037@vyatta.com>

Convert AF_PACKET to use RCU, eliminating one more reader/writer lock.

There is no need for a real sk_del_node_init_rcu(), because sk_del_node_init
is doing the equivalent thing to hlst_del_init_rcu already; but added
some comments to try and make that obvious.

Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>

---
v2 - > v3: Need to not call remove_packet with lock held.

 include/net/netns/packet.h |    4 ++--
 include/net/sock.h         |   10 ++++++++++
 net/packet/af_packet.c     |   42 ++++++++++++++++++++----------------------
 3 files changed, 32 insertions(+), 24 deletions(-)

--- a/include/net/netns/packet.h	2010-02-19 13:57:59.990116946 -0800
+++ b/include/net/netns/packet.h	2010-02-19 13:58:48.026119562 -0800
@@ -4,11 +4,11 @@
 #ifndef __NETNS_PACKET_H__
 #define __NETNS_PACKET_H__
 
-#include <linux/list.h>
+#include <linux/rculist.h>
 #include <linux/spinlock.h>
 
 struct netns_packet {
-	rwlock_t		sklist_lock;
+	spinlock_t		sklist_lock;
 	struct hlist_head	sklist;
 };
 
--- a/net/packet/af_packet.c	2010-02-19 13:57:59.978117421 -0800
+++ b/net/packet/af_packet.c	2010-02-19 14:14:56.893492702 -0800
@@ -1262,24 +1262,22 @@ static int packet_release(struct socket 
 	net = sock_net(sk);
 	po = pkt_sk(sk);
 
-	write_lock_bh(&net->packet.sklist_lock);
-	sk_del_node_init(sk);
+	spin_lock_bh(&net->packet.sklist_lock);
+	sk_del_node_init_rcu(sk);
 	sock_prot_inuse_add(net, sk->sk_prot, -1);
-	write_unlock_bh(&net->packet.sklist_lock);
-
-	/*
-	 *	Unhook packet receive handler.
-	 */
+	spin_unlock_bh(&net->packet.sklist_lock);
 
+	spin_lock(&po->bind_lock);
 	if (po->running) {
 		/*
-		 *	Remove the protocol hook
+		 * Remove from protocol table
 		 */
-		dev_remove_pack(&po->prot_hook);
 		po->running = 0;
 		po->num = 0;
+		__dev_remove_pack(&po->prot_hook);
 		__sock_put(sk);
 	}
+	spin_unlock(&po->bind_lock);
 
 	packet_flush_mclist(sk);
 
@@ -1291,10 +1289,10 @@ static int packet_release(struct socket 
 	if (po->tx_ring.pg_vec)
 		packet_set_ring(sk, &req, 1, 1);
 
+	synchronize_net();
 	/*
 	 *	Now the socket is dead. No more input will appear.
 	 */
-
 	sock_orphan(sk);
 	sock->sk = NULL;
 
@@ -1478,10 +1476,11 @@ static int packet_create(struct net *net
 		po->running = 1;
 	}
 
-	write_lock_bh(&net->packet.sklist_lock);
-	sk_add_node(sk, &net->packet.sklist);
+	spin_lock_bh(&net->packet.sklist_lock);
+	sk_add_node_rcu(sk, &net->packet.sklist);
 	sock_prot_inuse_add(net, &packet_proto, 1);
-	write_unlock_bh(&net->packet.sklist_lock);
+	spin_unlock_bh(&net->packet.sklist_lock);
+
 	return 0;
 out:
 	return err;
@@ -2075,8 +2074,8 @@ static int packet_notifier(struct notifi
 	struct net_device *dev = data;
 	struct net *net = dev_net(dev);
 
-	read_lock(&net->packet.sklist_lock);
-	sk_for_each(sk, node, &net->packet.sklist) {
+	rcu_read_lock();
+	sk_for_each_rcu(sk, node, &net->packet.sklist) {
 		struct packet_sock *po = pkt_sk(sk);
 
 		switch (msg) {
@@ -2104,18 +2103,19 @@ static int packet_notifier(struct notifi
 			}
 			break;
 		case NETDEV_UP:
-			spin_lock(&po->bind_lock);
-			if (dev->ifindex == po->ifindex && po->num &&
-			    !po->running) {
-				dev_add_pack(&po->prot_hook);
-				sock_hold(sk);
-				po->running = 1;
+			if (dev->ifindex == po->ifindex) {
+				spin_lock(&po->bind_lock);
+				if (po->num && !po->running) {
+					dev_add_pack(&po->prot_hook);
+					sock_hold(sk);
+					po->running = 1;
+				}
+				spin_unlock(&po->bind_lock);
 			}
-			spin_unlock(&po->bind_lock);
 			break;
 		}
 	}
-	read_unlock(&net->packet.sklist_lock);
+	rcu_read_unlock();
 	return NOTIFY_DONE;
 }
 
@@ -2512,24 +2512,24 @@ static struct notifier_block packet_netd
 #ifdef CONFIG_PROC_FS
 
 static void *packet_seq_start(struct seq_file *seq, loff_t *pos)
-	__acquires(seq_file_net(seq)->packet.sklist_lock)
+	__acquires(RCU)
 {
 	struct net *net = seq_file_net(seq);
-	read_lock(&net->packet.sklist_lock);
-	return seq_hlist_start_head(&net->packet.sklist, *pos);
+
+	rcu_read_lock();
+	return seq_hlist_start_head_rcu(&net->packet.sklist, *pos);
 }
 
 static void *packet_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 {
 	struct net *net = seq_file_net(seq);
-	return seq_hlist_next(v, &net->packet.sklist, pos);
+	return seq_hlist_next_rcu(v, &net->packet.sklist, pos);
 }
 
 static void packet_seq_stop(struct seq_file *seq, void *v)
-	__releases(seq_file_net(seq)->packet.sklist_lock)
+	__releases(RCU)
 {
-	struct net *net = seq_file_net(seq);
-	read_unlock(&net->packet.sklist_lock);
+	rcu_read_unlock();
 }
 
 static int packet_seq_show(struct seq_file *seq, void *v)
@@ -2581,7 +2581,7 @@ static const struct file_operations pack
 
 static int __net_init packet_net_init(struct net *net)
 {
-	rwlock_init(&net->packet.sklist_lock);
+	spin_lock_init(&net->packet.sklist_lock);
 	INIT_HLIST_HEAD(&net->packet.sklist);
 
 	if (!proc_net_fops_create(net, "packet", 0, &packet_seq_fops))
--- a/include/net/sock.h	2010-02-19 13:58:00.006118906 -0800
+++ b/include/net/sock.h	2010-02-19 13:58:48.030119401 -0800
@@ -381,6 +381,7 @@ static __inline__ void __sk_del_node(str
 	__hlist_del(&sk->sk_node);
 }
 
+/* NB: equivalent to hlist_del_init_rcu */
 static __inline__ int __sk_del_node_init(struct sock *sk)
 {
 	if (sk_hashed(sk)) {
@@ -421,6 +422,7 @@ static __inline__ int sk_del_node_init(s
 	}
 	return rc;
 }
+#define sk_del_node_init_rcu(sk)	sk_del_node_init(sk)
 
 static __inline__ int __sk_nulls_del_node_init_rcu(struct sock *sk)
 {
@@ -454,6 +456,12 @@ static __inline__ void sk_add_node(struc
 	__sk_add_node(sk, list);
 }
 
+static __inline__ void sk_add_node_rcu(struct sock *sk, struct hlist_head *list)
+{
+	sock_hold(sk);
+	hlist_add_head_rcu(&sk->sk_node, list);
+}
+
 static __inline__ void __sk_nulls_add_node_rcu(struct sock *sk, struct hlist_nulls_head *list)
 {
 	hlist_nulls_add_head_rcu(&sk->sk_nulls_node, list);
@@ -478,6 +486,8 @@ static __inline__ void sk_add_bind_node(
 
 #define sk_for_each(__sk, node, list) \
 	hlist_for_each_entry(__sk, node, list, sk_node)
+#define sk_for_each_rcu(__sk, node, list) \
+	hlist_for_each_entry_rcu(__sk, node, list, sk_node)
 #define sk_nulls_for_each(__sk, node, list) \
 	hlist_nulls_for_each_entry(__sk, node, list, sk_nulls_node)
 #define sk_nulls_for_each_rcu(__sk, node, list) \

^ permalink raw reply

* [PATCH 1/2] net:  Fix sysctl restarts...
From: Eric W. Biederman @ 2010-02-19 23:22 UTC (permalink / raw)
  To: David Miller; +Cc: netdev


Yuck.  It turns out that when we restart sysctls we were restarting
with the values already changed.  Which unfortunately meant that
the second time through we thought there was no change and skipped
all kinds of work, despite the fact that there was indeed a change.

I have fixed this the simplest way possible by restoring the changed
values when we restart the sysctl write.

One of my coworkers spotted this bug when after disabling forwarding
on an interface pings were still forwarded.

Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
---
 net/ipv4/devinet.c  |    7 ++++++-
 net/ipv6/addrconf.c |   16 ++++++++++++++--
 2 files changed, 20 insertions(+), 3 deletions(-)

diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index 014982b..51ca946 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -1317,14 +1317,19 @@ static int devinet_sysctl_forward(ctl_table *ctl, int write,
 {
 	int *valp = ctl->data;
 	int val = *valp;
+	loff_t pos = *ppos;
 	int ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
 
 	if (write && *valp != val) {
 		struct net *net = ctl->extra2;
 
 		if (valp != &IPV4_DEVCONF_DFLT(net, FORWARDING)) {
-			if (!rtnl_trylock())
+			if (!rtnl_trylock()) {
+				/* Restore the original values before restarting */
+				*valp = val;
+				*ppos = pos;
 				return restart_syscall();
+			}
 			if (valp == &IPV4_DEVCONF_ALL(net, FORWARDING)) {
 				inet_forward_change(net);
 			} else if (*valp) {
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index b0d4a4b..5bcf0d3 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -502,8 +502,11 @@ static int addrconf_fixup_forwarding(struct ctl_table *table, int *p, int old)
 	if (p == &net->ipv6.devconf_dflt->forwarding)
 		return 0;
 
-	if (!rtnl_trylock())
+	if (!rtnl_trylock()) {
+		/* Restore the original values before restarting */
+		*p = old; 
 		return restart_syscall();
+	}
 
 	if (p == &net->ipv6.devconf_all->forwarding) {
 		__s32 newf = net->ipv6.devconf_all->forwarding;
@@ -4042,12 +4045,15 @@ int addrconf_sysctl_forward(ctl_table *ctl, int write,
 {
 	int *valp = ctl->data;
 	int val = *valp;
+	loff_t pos = *ppos;
 	int ret;
 
 	ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
 
 	if (write)
 		ret = addrconf_fixup_forwarding(ctl, valp, val);
+	if (ret)
+		*ppos = pos;
 	return ret;
 }
 
@@ -4089,8 +4095,11 @@ static int addrconf_disable_ipv6(struct ctl_table *table, int *p, int old)
 	if (p == &net->ipv6.devconf_dflt->disable_ipv6)
 		return 0;
 
-	if (!rtnl_trylock())
+	if (!rtnl_trylock()) {
+		/* Restore the original values before restarting */
+		*p = old; 
 		return restart_syscall();
+	}
 
 	if (p == &net->ipv6.devconf_all->disable_ipv6) {
 		__s32 newf = net->ipv6.devconf_all->disable_ipv6;
@@ -4109,12 +4118,15 @@ int addrconf_sysctl_disable(ctl_table *ctl, int write,
 {
 	int *valp = ctl->data;
 	int val = *valp;
+	loff_t pos = *ppos;
 	int ret;
 
 	ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
 
 	if (write)
 		ret = addrconf_disable_ipv6(ctl, valp, val);
+	if (ret)
+		*ppos = pos;
 	return ret;
 }
 
-- 
1.6.5.2.143.g8cc62


^ permalink raw reply related

* [PATCH 2/2] net-sysfs: Use rtnl_trylock in wireless sysfs methods.
From: Eric W. Biederman @ 2010-02-19 23:23 UTC (permalink / raw)
  To: David Miller; +Cc: netdev
In-Reply-To: <m14olcu7xo.fsf@fess.ebiederm.org>


The wireless sysfs methods like the rest of the networking sysfs
methods are removed with the rtnl_lock held and block until
the existing methods stop executing.  So use rtnl_trylock
and restart_syscall so that the code continues to work.

Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
---
 net/core/net-sysfs.c |    3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c
index fbc1c74..099c753 100644
--- a/net/core/net-sysfs.c
+++ b/net/core/net-sysfs.c
@@ -410,7 +410,8 @@ static ssize_t wireless_show(struct device *d, char *buf,
 	const struct iw_statistics *iw;
 	ssize_t ret = -EINVAL;
 
-	rtnl_lock();
+	if (!rtnl_trylock())
+		return restart_syscall();
 	if (dev_isalive(dev)) {
 		iw = get_wireless_stats(dev);
 		if (iw)
-- 
1.6.5.2.143.g8cc62


^ permalink raw reply related

* [PATCH net-2.6 1/2] sfc: Fix sign of efx_mcdi_poll_reboot() error in efx_mcdi_poll()
From: Ben Hutchings @ 2010-02-19 23:29 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, linux-net-drivers

efx_mcdi_poll() uses positive error numbers, matching the MCDI
protocol.  It must negate the result of efx_mcdi_poll_reboot() which
returns the usual negative error numbers.

Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
---
 drivers/net/sfc/mcdi.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/net/sfc/mcdi.c b/drivers/net/sfc/mcdi.c
index 9f035b9..f66b3da 100644
--- a/drivers/net/sfc/mcdi.c
+++ b/drivers/net/sfc/mcdi.c
@@ -127,7 +127,7 @@ static int efx_mcdi_poll(struct efx_nic *efx)
 	efx_dword_t reg;
 
 	/* Check for a reboot atomically with respect to efx_mcdi_copyout() */
-	rc = efx_mcdi_poll_reboot(efx);
+	rc = -efx_mcdi_poll_reboot(efx);
 	if (rc)
 		goto out;
 
-- 
1.6.2.5


-- 
Ben Hutchings, Senior Software Engineer, Solarflare Communications
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.


^ permalink raw reply related

* Re: [PATCH 1/2] net: Fix sysctl restarts...
From: David Miller @ 2010-02-19 23:29 UTC (permalink / raw)
  To: ebiederm; +Cc: netdev
In-Reply-To: <m14olcu7xo.fsf@fess.ebiederm.org>

From: ebiederm@xmission.com (Eric W. Biederman)
Date: Fri, 19 Feb 2010 15:22:59 -0800

> 
> Yuck.  It turns out that when we restart sysctls we were restarting
> with the values already changed.  Which unfortunately meant that
> the second time through we thought there was no change and skipped
> all kinds of work, despite the fact that there was indeed a change.
> 
> I have fixed this the simplest way possible by restoring the changed
> values when we restart the sysctl write.
> 
> One of my coworkers spotted this bug when after disabling forwarding
> on an interface pings were still forwarded.
> 
> Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>

What commit added this bug?

^ permalink raw reply

* [PATCH net-2.6 2/2] sfc: SFE4002/SFN4112F: Widen temperature and voltage tolerances
From: Ben Hutchings @ 2010-02-19 23:34 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, linux-net-drivers

The temperature and voltage limits currently set on these boards are
too conservative and will cause the driver to stop the net device
erroneously in some systems.

Based on a review of the chip datasheets and advice from the designer
of these boards:

- Raise the maximum board temperatures to the specified maximum ambient
  temperatures for their PHYs plus the expected temperature bias of the
  board
- Raise the maximum controller temperature to 90 degrees
- Lower the minimum temperatures to 0 degrees
- Widen the voltage tolerances to at least +/- 10%

Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
---
 drivers/net/sfc/falcon_boards.c |   45 +++++++++++++++++++++++---------------
 1 files changed, 27 insertions(+), 18 deletions(-)

diff --git a/drivers/net/sfc/falcon_boards.c b/drivers/net/sfc/falcon_boards.c
index bf0b96a..5712fdd 100644
--- a/drivers/net/sfc/falcon_boards.c
+++ b/drivers/net/sfc/falcon_boards.c
@@ -29,6 +29,15 @@
 #define FALCON_BOARD_SFN4111T 0x51
 #define FALCON_BOARD_SFN4112F 0x52
 
+/* Board temperature is about 15°C above ambient when air flow is
+ * limited. */
+#define FALCON_BOARD_TEMP_BIAS	15
+
+/* SFC4000 datasheet says: 'The maximum permitted junction temperature
+ * is 125°C; the thermal design of the environment for the SFC4000
+ * should aim to keep this well below 100°C.' */
+#define FALCON_JUNC_TEMP_MAX	90
+
 /*****************************************************************************
  * Support for LM87 sensor chip used on several boards
  */
@@ -548,16 +557,16 @@ fail_hwmon:
 static u8 sfe4002_lm87_channel = 0x03; /* use AIN not FAN inputs */
 
 static const u8 sfe4002_lm87_regs[] = {
-	LM87_IN_LIMITS(0, 0x83, 0x91),		/* 2.5V:  1.8V +/- 5% */
-	LM87_IN_LIMITS(1, 0x51, 0x5a),		/* Vccp1: 1.2V +/- 5% */
-	LM87_IN_LIMITS(2, 0xb6, 0xca),		/* 3.3V:  3.3V +/- 5% */
-	LM87_IN_LIMITS(3, 0xb0, 0xc9),		/* 5V:    4.6-5.2V */
-	LM87_IN_LIMITS(4, 0xb0, 0xe0),		/* 12V:   11-14V */
-	LM87_IN_LIMITS(5, 0x44, 0x4b),		/* Vccp2: 1.0V +/- 5% */
-	LM87_AIN_LIMITS(0, 0xa0, 0xb2),		/* AIN1:  1.66V +/- 5% */
-	LM87_AIN_LIMITS(1, 0x91, 0xa1),		/* AIN2:  1.5V +/- 5% */
-	LM87_TEMP_INT_LIMITS(10, 60),		/* board */
-	LM87_TEMP_EXT1_LIMITS(10, 70),		/* Falcon */
+	LM87_IN_LIMITS(0, 0x7c, 0x99),		/* 2.5V:  1.8V +/- 10% */
+	LM87_IN_LIMITS(1, 0x4c, 0x5e),		/* Vccp1: 1.2V +/- 10% */
+	LM87_IN_LIMITS(2, 0xac, 0xd4),		/* 3.3V:  3.3V +/- 10% */
+	LM87_IN_LIMITS(3, 0xac, 0xd4),		/* 5V:    5.0V +/- 10% */
+	LM87_IN_LIMITS(4, 0xac, 0xe0),		/* 12V:   10.8-14V */
+	LM87_IN_LIMITS(5, 0x3f, 0x4f),		/* Vccp2: 1.0V +/- 10% */
+	LM87_AIN_LIMITS(0, 0x98, 0xbb),		/* AIN1:  1.66V +/- 10% */
+	LM87_AIN_LIMITS(1, 0x8a, 0xa9),		/* AIN2:  1.5V +/- 10% */
+	LM87_TEMP_INT_LIMITS(0, 80 + FALCON_BOARD_TEMP_BIAS),
+	LM87_TEMP_EXT1_LIMITS(0, FALCON_JUNC_TEMP_MAX),
 	0
 };
 
@@ -619,14 +628,14 @@ static int sfe4002_init(struct efx_nic *efx)
 static u8 sfn4112f_lm87_channel = 0x03; /* use AIN not FAN inputs */
 
 static const u8 sfn4112f_lm87_regs[] = {
-	LM87_IN_LIMITS(0, 0x83, 0x91),		/* 2.5V:  1.8V +/- 5% */
-	LM87_IN_LIMITS(1, 0x51, 0x5a),		/* Vccp1: 1.2V +/- 5% */
-	LM87_IN_LIMITS(2, 0xb6, 0xca),		/* 3.3V:  3.3V +/- 5% */
-	LM87_IN_LIMITS(4, 0xb0, 0xe0),		/* 12V:   11-14V */
-	LM87_IN_LIMITS(5, 0x44, 0x4b),		/* Vccp2: 1.0V +/- 5% */
-	LM87_AIN_LIMITS(1, 0x91, 0xa1),		/* AIN2:  1.5V +/- 5% */
-	LM87_TEMP_INT_LIMITS(10, 60),		/* board */
-	LM87_TEMP_EXT1_LIMITS(10, 70),		/* Falcon */
+	LM87_IN_LIMITS(0, 0x7c, 0x99),		/* 2.5V:  1.8V +/- 10% */
+	LM87_IN_LIMITS(1, 0x4c, 0x5e),		/* Vccp1: 1.2V +/- 10% */
+	LM87_IN_LIMITS(2, 0xac, 0xd4),		/* 3.3V:  3.3V +/- 10% */
+	LM87_IN_LIMITS(4, 0xac, 0xe0),		/* 12V:   10.8-14V */
+	LM87_IN_LIMITS(5, 0x3f, 0x4f),		/* Vccp2: 1.0V +/- 10% */
+	LM87_AIN_LIMITS(1, 0x8a, 0xa9),		/* AIN2:  1.5V +/- 10% */
+	LM87_TEMP_INT_LIMITS(0, 60 + FALCON_BOARD_TEMP_BIAS),
+	LM87_TEMP_EXT1_LIMITS(0, FALCON_JUNC_TEMP_MAX),
 	0
 };
 
-- 
1.6.2.5

-- 
Ben Hutchings, Senior Software Engineer, Solarflare Communications
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.


^ permalink raw reply related

* Re: [PATCH 1/2] net: Fix sysctl restarts...
From: Eric W. Biederman @ 2010-02-19 23:35 UTC (permalink / raw)
  To: David Miller; +Cc: netdev
In-Reply-To: <20100219.152954.39315470.davem@davemloft.net>

David Miller <davem@davemloft.net> writes:

> From: ebiederm@xmission.com (Eric W. Biederman)
> Date: Fri, 19 Feb 2010 15:22:59 -0800
>
>> 
>> Yuck.  It turns out that when we restart sysctls we were restarting
>> with the values already changed.  Which unfortunately meant that
>> the second time through we thought there was no change and skipped
>> all kinds of work, despite the fact that there was indeed a change.
>> 
>> I have fixed this the simplest way possible by restoring the changed
>> values when we restart the sysctl write.
>> 
>> One of my coworkers spotted this bug when after disabling forwarding
>> on an interface pings were still forwarded.
>> 
>> Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
>
> What commit added this bug?

When we I fixed the deadlock that can happen if you write to forwarding
while removing the device.  The deadlock was fixed, the restart worked
but I somehow missed the fact that proc_dointvec modifies state and so
defeated the change detection.  *embarrassing*

commit 9b8adb5ea005fe73acd5dd58f9bd47eafa74c9d1
Author: Eric W. Biederman <ebiederm@xmission.com>
Date:   Wed May 13 16:59:21 2009 +0000

    net: Fix devinet_sysctl_forward
    
    sysctls are unregistered with the rntl_lock held making
    it unsafe to unconditionally grab the the rtnl_lock.  Instead
    we need to call rtnl_trylock and restart the system call
    if we can not grab it.  Otherwise we could deadlock at unregistration
    time.
    
    Signed-off-by: Eric W. Biederman <ebiederm@aristanetworks.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>





^ permalink raw reply

* Re: [PATCH 1/2] net: Fix sysctl restarts...
From: David Miller @ 2010-02-19 23:41 UTC (permalink / raw)
  To: ebiederm; +Cc: netdev
In-Reply-To: <m1ocjksssg.fsf@fess.ebiederm.org>

From: ebiederm@xmission.com (Eric W. Biederman)
Date: Fri, 19 Feb 2010 15:35:27 -0800

> When we I fixed the deadlock that can happen if you write to forwarding
> while removing the device.  The deadlock was fixed, the restart worked
> but I somehow missed the fact that proc_dointvec modifies state and so
> defeated the change detection.  *embarrassing*

Ok, I'll have to push these around to Linus and a couple -stable
releases.

Thanks.

^ permalink raw reply

* [PATCH 1/4] be2net: update copyright dates
From: Ajit Khaparde @ 2010-02-19 23:54 UTC (permalink / raw)
  To: David Miller; +Cc: netdev


Signed-off-by: Ajit Khaparde <ajitk@serverengines.com>
---
 drivers/net/benet/be.h         |    2 +-
 drivers/net/benet/be_cmds.c    |    2 +-
 drivers/net/benet/be_cmds.h    |    2 +-
 drivers/net/benet/be_ethtool.c |    2 +-
 drivers/net/benet/be_hw.h      |    2 +-
 drivers/net/benet/be_main.c    |    2 +-
 6 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/net/benet/be.h b/drivers/net/benet/be.h
index 2734a41..e3a4665 100644
--- a/drivers/net/benet/be.h
+++ b/drivers/net/benet/be.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005 - 2009 ServerEngines
+ * Copyright (C) 2005 - 2010 ServerEngines
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or
diff --git a/drivers/net/benet/be_cmds.c b/drivers/net/benet/be_cmds.c
index d7546b4..ee16b37 100644
--- a/drivers/net/benet/be_cmds.c
+++ b/drivers/net/benet/be_cmds.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005 - 2009 ServerEngines
+ * Copyright (C) 2005 - 2010 ServerEngines
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or
diff --git a/drivers/net/benet/be_cmds.h b/drivers/net/benet/be_cmds.h
index 01501db..3464924 100644
--- a/drivers/net/benet/be_cmds.h
+++ b/drivers/net/benet/be_cmds.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005 - 2009 ServerEngines
+ * Copyright (C) 2005 - 2010 ServerEngines
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or
diff --git a/drivers/net/benet/be_ethtool.c b/drivers/net/benet/be_ethtool.c
index dcc7f37..9560d48 100644
--- a/drivers/net/benet/be_ethtool.c
+++ b/drivers/net/benet/be_ethtool.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005 - 2009 ServerEngines
+ * Copyright (C) 2005 - 2010 ServerEngines
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or
diff --git a/drivers/net/benet/be_hw.h b/drivers/net/benet/be_hw.h
index bb2ae6f..5ffb149 100644
--- a/drivers/net/benet/be_hw.h
+++ b/drivers/net/benet/be_hw.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005 - 2009 ServerEngines
+ * Copyright (C) 2005 - 2010 ServerEngines
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or
diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c
index 545c841..f667044 100644
--- a/drivers/net/benet/be_main.c
+++ b/drivers/net/benet/be_main.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005 - 2009 ServerEngines
+ * Copyright (C) 2005 - 2010 ServerEngines
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or
-- 
1.6.3.3


^ permalink raw reply related

* [PATCH 2/4] be2net: Maintain tx and rx counters in driver
From: Ajit Khaparde @ 2010-02-19 23:57 UTC (permalink / raw)
  To: David Miller; +Cc: netdev

For certain skews of the BE adapter, H/W Tx and Rx
counters could be common for more than one interface.
Add Tx and Rx counters in the adapter structure
(to maintain stats on a per interfae basis).

Signed-off-by: Ajit Khaparde <ajitk@serverengines.com>
---
 drivers/net/benet/be.h      |    2 ++
 drivers/net/benet/be_main.c |   18 +++++++++---------
 2 files changed, 11 insertions(+), 9 deletions(-)

diff --git a/drivers/net/benet/be.h b/drivers/net/benet/be.h
index e3a4665..42c7a2b 100644
--- a/drivers/net/benet/be.h
+++ b/drivers/net/benet/be.h
@@ -164,6 +164,7 @@ struct be_drvr_stats {
 	ulong be_tx_jiffies;
 	u64 be_tx_bytes;
 	u64 be_tx_bytes_prev;
+	u64 be_tx_pkts;
 	u32 be_tx_rate;
 
 	u32 cache_barrier[16];
@@ -175,6 +176,7 @@ struct be_drvr_stats {
 	ulong be_rx_jiffies;
 	u64 be_rx_bytes;
 	u64 be_rx_bytes_prev;
+	u64 be_rx_pkts;
 	u32 be_rx_rate;
 	/* number of non ether type II frames dropped where
 	 * frame len > length field of Mac Hdr */
diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c
index f667044..de0830e 100644
--- a/drivers/net/benet/be_main.c
+++ b/drivers/net/benet/be_main.c
@@ -159,13 +159,10 @@ void netdev_stats_update(struct be_adapter *adapter)
 	struct net_device_stats *dev_stats = &adapter->netdev->stats;
 	struct be_erx_stats *erx_stats = &hw_stats->erx;
 
-	dev_stats->rx_packets = port_stats->rx_total_frames;
-	dev_stats->tx_packets = port_stats->tx_unicastframes +
-		port_stats->tx_multicastframes + port_stats->tx_broadcastframes;
-	dev_stats->rx_bytes = (u64) port_stats->rx_bytes_msd << 32 |
-				(u64) port_stats->rx_bytes_lsd;
-	dev_stats->tx_bytes = (u64) port_stats->tx_bytes_msd << 32 |
-				(u64) port_stats->tx_bytes_lsd;
+	dev_stats->rx_packets = drvr_stats(adapter)->be_rx_pkts;
+	dev_stats->tx_packets = drvr_stats(adapter)->be_tx_pkts;
+	dev_stats->rx_bytes = drvr_stats(adapter)->be_rx_bytes;
+	dev_stats->tx_bytes = drvr_stats(adapter)->be_tx_bytes;
 
 	/* bad pkts received */
 	dev_stats->rx_errors = port_stats->rx_crc_errors +
@@ -322,12 +319,13 @@ static void be_tx_rate_update(struct be_adapter *adapter)
 }
 
 static void be_tx_stats_update(struct be_adapter *adapter,
-			u32 wrb_cnt, u32 copied, bool stopped)
+			u32 wrb_cnt, u32 copied, u32 gso_segs, bool stopped)
 {
 	struct be_drvr_stats *stats = drvr_stats(adapter);
 	stats->be_tx_reqs++;
 	stats->be_tx_wrbs += wrb_cnt;
 	stats->be_tx_bytes += copied;
+	stats->be_tx_pkts += (gso_segs ? gso_segs : 1);
 	if (stopped)
 		stats->be_tx_stops++;
 }
@@ -472,7 +470,8 @@ static netdev_tx_t be_xmit(struct sk_buff *skb,
 
 		be_txq_notify(adapter, txq->id, wrb_cnt);
 
-		be_tx_stats_update(adapter, wrb_cnt, copied, stopped);
+		be_tx_stats_update(adapter, wrb_cnt, copied,
+				skb_shinfo(skb)->gso_segs, stopped);
 	} else {
 		txq->head = start;
 		dev_kfree_skb_any(skb);
@@ -619,6 +618,7 @@ static void be_rx_stats_update(struct be_adapter *adapter,
 	stats->be_rx_compl++;
 	stats->be_rx_frags += numfrags;
 	stats->be_rx_bytes += pktsize;
+	stats->be_rx_pkts++;
 }
 
 static inline bool do_pkt_csum(struct be_eth_rx_compl *rxcp, bool cso)
-- 
1.6.3.3


^ permalink raw reply related

* Re: [PATCH 1/2] net: Fix sysctl restarts...
From: Eric W. Biederman @ 2010-02-19 23:58 UTC (permalink / raw)
  To: David Miller; +Cc: netdev
In-Reply-To: <20100219.154140.77047519.davem@davemloft.net>

David Miller <davem@davemloft.net> writes:

2> From: ebiederm@xmission.com (Eric W. Biederman)
> Date: Fri, 19 Feb 2010 15:35:27 -0800
>
>> When we I fixed the deadlock that can happen if you write to forwarding
>> while removing the device.  The deadlock was fixed, the restart worked
>> but I somehow missed the fact that proc_dointvec modifies state and so
>> defeated the change detection.  *embarrassing*
>
> Ok, I'll have to push these around to Linus and a couple -stable
> releases.

The second patch fixes an issue which isn't quite as old.

I caught it when I was looking for other rtnl_lock issues that
I may have missed.  Thankfully the worst sysfs does is re-read
the string from userspace on a restart so none of the sysfs
rtnl_trylock cases have a nasty deadlock associated.

Eric


commit a160ee69c6a4622ed30c377a978554015e9931cb
Author: Johannes Berg <johannes@sipsolutions.net>
Date:   Mon Oct 5 02:22:23 2009 -0700

    wext: let get_wireless_stats() sleep
    
    A number of drivers (recently including cfg80211-based ones)
    assume that all wireless handlers, including statistics, can
    sleep and they often also implicitly assume that the rtnl is
    held around their invocation. This is almost always true now
    except when reading from sysfs:
    
      BUG: sleeping function called from invalid context at kernel/mutex.c:280
      in_atomic(): 1, irqs_disabled(): 0, pid: 10450, name: head
      2 locks held by head/10450:
       #0:  (&buffer->mutex){+.+.+.}, at: [<c10ceb99>] sysfs_read_file+0x24/0xf4
       #1:  (dev_base_lock){++.?..}, at: [<c12844ee>] wireless_show+0x1a/0x4c
      Pid: 10450, comm: head Not tainted 2.6.32-rc3 #1
      Call Trace:
       [<c102301c>] __might_sleep+0xf0/0xf7
       [<c1324355>] mutex_lock_nested+0x1a/0x33
       [<f8cea53b>] wdev_lock+0xd/0xf [cfg80211]
       [<f8cea58f>] cfg80211_wireless_stats+0x45/0x12d [cfg80211]
       [<c13118d6>] get_wireless_stats+0x16/0x1c
       [<c12844fe>] wireless_show+0x2a/0x4c
    
    Fix this by using the rtnl instead of dev_base_lock.
    
    Reported-by: Miles Lane <miles.lane@gmail.com>
    Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
    Signed-off-by: David S. Miller <davem@davemloft.net>

^ permalink raw reply

* [PATCH 4/4] MAINTAINERS: Add two maintainers for be2net driver
From: Ajit Khaparde @ 2010-02-20  0:00 UTC (permalink / raw)
  To: David Miller; +Cc: netdev


Signed-off-by: Ajit Khaparde <ajitk@serverengines.com>
---
 MAINTAINERS |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/MAINTAINERS b/MAINTAINERS
index 2c8b0d3..9b0557a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -4844,6 +4844,8 @@ F:	drivers/scsi/be2iscsi/
 SERVER ENGINES 10Gbps NIC - BladeEngine 2 DRIVER
 M:	Sathya Perla <sathyap@serverengines.com>
 M:	Subbu Seetharaman <subbus@serverengines.com>
+M:	Sarveshwar Bandi <sarveshwarb@serverengines.com>
+M:	Ajit Khaparde <ajitk@serverengines.com>
 L:	netdev@vger.kernel.org
 W:	http://www.serverengines.com
 S:	Supported
-- 
1.6.3.3


^ permalink raw reply related

* Re: [PATCH 1/2] net: Fix sysctl restarts...
From: David Miller @ 2010-02-20  0:02 UTC (permalink / raw)
  To: ebiederm; +Cc: netdev
In-Reply-To: <m1aav4srpe.fsf@fess.ebiederm.org>

From: ebiederm@xmission.com (Eric W. Biederman)
Date: Fri, 19 Feb 2010 15:58:53 -0800

> David Miller <davem@davemloft.net> writes:
> 
> 2> From: ebiederm@xmission.com (Eric W. Biederman)
>> Date: Fri, 19 Feb 2010 15:35:27 -0800
>>
>>> When we I fixed the deadlock that can happen if you write to forwarding
>>> while removing the device.  The deadlock was fixed, the restart worked
>>> but I somehow missed the fact that proc_dointvec modifies state and so
>>> defeated the change detection.  *embarrassing*
>>
>> Ok, I'll have to push these around to Linus and a couple -stable
>> releases.
> 
> The second patch fixes an issue which isn't quite as old.
> 
> I caught it when I was looking for other rtnl_lock issues that
> I may have missed.  Thankfully the worst sysfs does is re-read
> the string from userspace on a restart so none of the sysfs
> rtnl_trylock cases have a nasty deadlock associated.
> 
> Eric
> 
> 
> commit a160ee69c6a4622ed30c377a978554015e9931cb
> Author: Johannes Berg <johannes@sipsolutions.net>
> Date:   Mon Oct 5 02:22:23 2009 -0700

So the second patch needs to go to less -stable releases than the
other one.  Thanks for the info.

^ permalink raw reply

* [PATCH 3/4] be2net: Bump the driver version number
From: Ajit Khaparde @ 2010-02-19 23:58 UTC (permalink / raw)
  To: David Miller; +Cc: netdev


Signed-off-by: Ajit Khaparde <ajitk@serverengines.com>
---
 drivers/net/benet/be.h |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/net/benet/be.h b/drivers/net/benet/be.h
index 42c7a2b..be81fb2 100644
--- a/drivers/net/benet/be.h
+++ b/drivers/net/benet/be.h
@@ -32,7 +32,7 @@
 
 #include "be_hw.h"
 
-#define DRV_VER			"2.101.346u"
+#define DRV_VER			"2.102.147u"
 #define DRV_NAME		"be2net"
 #define BE_NAME			"ServerEngines BladeEngine2 10Gbps NIC"
 #define BE3_NAME		"ServerEngines BladeEngine3 10Gbps NIC"
-- 
1.6.3.3


^ permalink raw reply related

* [PATCH 2.6.34] r8169: enable 64-bit DMA by default for PCI Express devices (v2)
From: Robert Hancock @ 2010-02-20  1:00 UTC (permalink / raw)
  To: David Miller; +Cc: linux-kernel, netdev, romieu
In-Reply-To: <20100219.131718.115496278.davem@davemloft.net>

Currently use of 64-bit DMA is disabled in r8169 unless the user passes the
use_dac module option. This is reasonable for conventional PCI devices where
broken chipsets may not handle dual-address-cycle transfers properly for
32-bit slots and so this may not be safe. However, PCI Express should not have
this problem and not using 64-bit DMA results in DMA transfers needlessly using
the IOMMU or SWIOTLB. Set the use_dac module parameter to a new default value of
-1 which results in 64-bit DMA being enabled by default for PCI Express devices
only.

Signed-off-by: Robert Hancock <hancockrwd@gmail.com>

diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
index 616ae5a..83965ee 100644
--- a/drivers/net/r8169.c
+++ b/drivers/net/r8169.c
@@ -187,7 +187,7 @@ static DEFINE_PCI_DEVICE_TABLE(rtl8169_pci_tbl) = {
 MODULE_DEVICE_TABLE(pci, rtl8169_pci_tbl);
 
 static int rx_copybreak = 200;
-static int use_dac;
+static int use_dac = -1;
 static struct {
 	u32 msg_enable;
 } debug = { -1 };
@@ -511,7 +511,8 @@ MODULE_DESCRIPTION("RealTek RTL-8169 Gigabit Ethernet driver");
 module_param(rx_copybreak, int, 0);
 MODULE_PARM_DESC(rx_copybreak, "Copy breakpoint for copy-only-tiny-frames");
 module_param(use_dac, int, 0);
-MODULE_PARM_DESC(use_dac, "Enable PCI DAC. Unsafe on 32 bit PCI slot.");
+MODULE_PARM_DESC(use_dac, "Enable PCI DAC. -1 defaults on for PCI Express only."
+" Unsafe on 32 bit PCI slot.");
 module_param_named(debug, debug.msg_enable, int, 0);
 MODULE_PARM_DESC(debug, "Debug verbosity level (0=none, ..., 16=all)");
 MODULE_LICENSE("GPL");
@@ -2973,6 +2974,7 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 	void __iomem *ioaddr;
 	unsigned int i;
 	int rc;
+	int this_use_dac = use_dac;
 
 	if (netif_msg_drv(&debug)) {
 		printk(KERN_INFO "%s Gigabit Ethernet driver %s loaded\n",
@@ -3038,8 +3040,17 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 
 	tp->cp_cmd = PCIMulRW | RxChkSum;
 
+	tp->pcie_cap = pci_find_capability(pdev, PCI_CAP_ID_EXP);
+	if (!tp->pcie_cap)
+		netif_info(tp, probe, dev, "no PCI Express capability\n");
+
+	if (this_use_dac < 0)
+		this_use_dac = tp->pcie_cap != 0;
+
 	if ((sizeof(dma_addr_t) > 4) &&
-	    !pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) && use_dac) {
+	    this_use_dac &&
+	    !pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) {
+		netif_info(tp, probe, dev, "using 64-bit DMA\n");
 		tp->cp_cmd |= PCIDAC;
 		dev->features |= NETIF_F_HIGHDMA;
 	} else {
@@ -3058,10 +3069,6 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 		goto err_out_free_res_4;
 	}
 
-	tp->pcie_cap = pci_find_capability(pdev, PCI_CAP_ID_EXP);
-	if (!tp->pcie_cap)
-		netif_info(tp, probe, dev, "no PCI Express capability\n");
-
 	RTL_W16(IntrMask, 0x0000);
 
 	/* Soft reset the chip. */

^ permalink raw reply related

* Re: [PATCH net-2.6 1/2] sfc: Fix sign of efx_mcdi_poll_reboot() error in efx_mcdi_poll()
From: David Miller @ 2010-02-20  1:03 UTC (permalink / raw)
  To: bhutchings; +Cc: netdev, linux-net-drivers
In-Reply-To: <1266622168.2091.5.camel@achroite.uk.solarflarecom.com>

From: Ben Hutchings <bhutchings@solarflare.com>
Date: Fri, 19 Feb 2010 23:29:27 +0000

> efx_mcdi_poll() uses positive error numbers, matching the MCDI
> protocol.  It must negate the result of efx_mcdi_poll_reboot() which
> returns the usual negative error numbers.
> 
> Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>

Applied.

^ permalink raw reply

* Re: [PATCH net-2.6 2/2] sfc: SFE4002/SFN4112F: Widen temperature and voltage tolerances
From: David Miller @ 2010-02-20  1:03 UTC (permalink / raw)
  To: bhutchings; +Cc: netdev, linux-net-drivers
In-Reply-To: <1266622444.2091.10.camel@achroite.uk.solarflarecom.com>

From: Ben Hutchings <bhutchings@solarflare.com>
Date: Fri, 19 Feb 2010 23:34:03 +0000

> The temperature and voltage limits currently set on these boards are
> too conservative and will cause the driver to stop the net device
> erroneously in some systems.
> 
> Based on a review of the chip datasheets and advice from the designer
> of these boards:
> 
> - Raise the maximum board temperatures to the specified maximum ambient
>   temperatures for their PHYs plus the expected temperature bias of the
>   board
> - Raise the maximum controller temperature to 90 degrees
> - Lower the minimum temperatures to 0 degrees
> - Widen the voltage tolerances to at least +/- 10%
> 
> Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>

Applied.

^ permalink raw reply

* [GIT]: Networking
From: David Miller @ 2010-02-20  1:09 UTC (permalink / raw)
  To: torvalds; +Cc: akpm, netdev, linux-kernel


Some stragglers.  I know it's late but I really would be
remiss to not submit the sysctl fixes.

1) When we fixed a deadlock on the RTNL lock, when writing to
   forwarding control sysctl values while at the same time
   removing a device, we added a new bug.  The commit was
   9b8adb5ea005 ("net: Fix devinet_sysctl_forward")

   By the time these sysctl handlers have been called, the
   generic sysctl code has already changed the value of the
   integer.  So if we retry to avoid a deadlock, we have to
   undo that modification.

   Fix from Eric W. Biederman.

2) When the the wireless get stats output method were changed to use
   the RTNL lock instead of dev_base_lock (commit a160ee69c6a "wext:
   let get_wireless_stats() sleep") , it acquired the same kind of
   deadlock that the forwarding controls have.  Fix it in the same
   way.

   Also from Eric W. Biederman.

3) Two SFC driver bug fixes from Ben Hucthings.  First, propagate
   properly signed error codes back from efc_mcdi_poll_reboot()
   and also adjust temperature and voltage tolerances so that they
   do not prematurely trigger.

Please pull, thanks a lot!

The following changes since commit f8b55f251012e104093e105483c45c5d85ad3040:
  Christine Caulfield (1):
        Orphan DECnet

are available in the git repository at:

  master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6.git master

Ben Hutchings (2):
      sfc: Fix sign of efx_mcdi_poll_reboot() error in efx_mcdi_poll()
      sfc: SFE4002/SFN4112F: Widen temperature and voltage tolerances

Eric W. Biederman (2):
      net: Fix sysctl restarts...
      net-sysfs: Use rtnl_trylock in wireless sysfs methods.

 drivers/net/sfc/falcon_boards.c |   45 +++++++++++++++++++++++---------------
 drivers/net/sfc/mcdi.c          |    2 +-
 net/core/net-sysfs.c            |    3 +-
 net/ipv4/devinet.c              |    7 +++++-
 net/ipv6/addrconf.c             |   16 ++++++++++++-
 5 files changed, 50 insertions(+), 23 deletions(-)

^ permalink raw reply

* Re: [PATCH 2.6.34] r8169: enable 64-bit DMA by default for PCI Express devices (v2)
From: David Miller @ 2010-02-20  1:10 UTC (permalink / raw)
  To: hancockrwd; +Cc: linux-kernel, netdev, romieu
In-Reply-To: <4B7F343E.4040409@gmail.com>

From: Robert Hancock <hancockrwd@gmail.com>
Date: Fri, 19 Feb 2010 19:00:46 -0600

> Currently use of 64-bit DMA is disabled in r8169 unless the user passes the
> use_dac module option. This is reasonable for conventional PCI devices where
> broken chipsets may not handle dual-address-cycle transfers properly for
> 32-bit slots and so this may not be safe. However, PCI Express should not have
> this problem and not using 64-bit DMA results in DMA transfers needlessly using
> the IOMMU or SWIOTLB. Set the use_dac module parameter to a new default value of
> -1 which results in 64-bit DMA being enabled by default for PCI Express devices
> only.
> 
> Signed-off-by: Robert Hancock <hancockrwd@gmail.com>

Applied, thanks Robert.

^ permalink raw reply

* Re: [PATCH 1/4] be2net: update copyright dates
From: David Miller @ 2010-02-20  1:12 UTC (permalink / raw)
  To: ajitk, ajitkhaparde; +Cc: netdev
In-Reply-To: <20100219235443.GA12890@serverengines.com>

From: Ajit Khaparde <ajitkhaparde@gmail.com>
Date: Sat, 20 Feb 2010 05:24:58 +0530

> 
> Signed-off-by: Ajit Khaparde <ajitk@serverengines.com>

Applied.

^ permalink raw reply

* Re: [PATCH 2/4] be2net: Maintain tx and rx counters in driver
From: David Miller @ 2010-02-20  1:12 UTC (permalink / raw)
  To: ajitk, ajitkhaparde; +Cc: netdev
In-Reply-To: <20100219235702.GA12931@serverengines.com>

From: Ajit Khaparde <ajitkhaparde@gmail.com>
Date: Sat, 20 Feb 2010 05:27:12 +0530

> For certain skews of the BE adapter, H/W Tx and Rx
> counters could be common for more than one interface.
> Add Tx and Rx counters in the adapter structure
> (to maintain stats on a per interfae basis).
> 
> Signed-off-by: Ajit Khaparde <ajitk@serverengines.com>

Applied.

^ 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