Netdev List
 help / color / mirror / Atom feed
* Re: Potential out-of-bounds access in ip6_finish_output2
From: Hannes Frederic Sowa @ 2013-09-21 15:14 UTC (permalink / raw)
  To: Dmitry Vyukov, yoshfuji, netdev, Paul Turner, Andrey Konovalov,
	Kostya Serebryany, Tom Herbert
In-Reply-To: <20130917224851.GB8947@order.stressinduktion.org>

On Wed, Sep 18, 2013 at 12:48:51AM +0200, Hannes Frederic Sowa wrote:
> On Mon, Sep 16, 2013 at 10:13:10PM -0700, Dmitry Vyukov wrote:
> > I am working on AddressSanitizer -- a tool that detects use-after-free
> > and out-of-bounds bugs
> > (https://code.google.com/p/address-sanitizer/wiki/AddressSanitizerForKernel).
> > 
> > I've got a dozen of reports in ip6_finish_output2. Below are 2 of
> > them. They are always followed by kernel crash. Unfortunately I don't
> > have a reproducer because I am using trinity fuzzer. I would
> > appreciate if somebody familiar with the code look at sources and
> > maybe spot the bug.
> 
> Thanks for the report!
> 
> I tried reproducing the bug and hit some other bugs nearby. I'll try to fix
> them, but this could take some time.

I fixed the first bug I encountered with trinity here:
http://patchwork.ozlabs.org/patch/276835/

The main cause of this bug has nothing to do with raw sockets, so I first
thought they are not related. But I left my machine run trinity while
I was sleeping and did not see any other splats (I added some manually
range checks in ip6_append_data). So maybe your bug happend because the
premature exit in the dontfrag check without resetting cork->length. Maybe
you could give this patch a try? I'll have a second look later today.

Thanks,

  Hannes

^ permalink raw reply

* [PATCH net-next 2/2] ipv6: compare sernum when walking fib for /proc/net/ipv6_route as safety net
From: Hannes Frederic Sowa @ 2013-09-21 14:56 UTC (permalink / raw)
  To: netdev; +Cc: greearb, kaber, yoshfuji, davem

This patch provides an additional safety net against NULL
pointer dereferences while walking the fib trie for the new
/proc/net/ipv6_route walkers. I never needed it myself and am unsure
if it is needed at all, but the same checks where introduced in
2bec5a369ee79576a3eea2c23863325089785a2c ("ipv6: fib: fix crash when
changing large fib while dumping it") to fix NULL pointer bugs.

This patch is separated from the first patch to make it easier to revert
if we are sure we can drop this logic.

Cc: Ben Greear <greearb@candelatech.com>
Cc: Patrick McHardy <kaber@trash.net>
Cc: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Signed-off-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
---
 net/ipv6/ip6_fib.c | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
index 05ffa54..5550a81 100644
--- a/net/ipv6/ip6_fib.c
+++ b/net/ipv6/ip6_fib.c
@@ -1771,6 +1771,7 @@ struct ipv6_route_iter {
 	struct fib6_walker_t w;
 	loff_t skip;
 	struct fib6_table *tbl;
+	__u32 sernum;
 };
 
 static int ipv6_route_seq_show(struct seq_file *seq, void *v)
@@ -1823,6 +1824,7 @@ static void ipv6_route_seq_setup_walk(struct ipv6_route_iter *iter)
 	iter->w.state = FWS_INIT;
 	iter->w.node = iter->w.root;
 	iter->w.args = iter;
+	iter->sernum = iter->w.root->fn_sernum;
 	INIT_LIST_HEAD(&iter->w.lh);
 	fib6_walker_link(&iter->w);
 }
@@ -1848,6 +1850,17 @@ static struct fib6_table *ipv6_route_seq_next_table(struct fib6_table *tbl,
 	return hlist_entry_safe(node, struct fib6_table, tb6_hlist);
 }
 
+static void ipv6_route_check_sernum(struct ipv6_route_iter *iter)
+{
+	if (iter->sernum != iter->w.root->fn_sernum) {
+		iter->sernum = iter->w.root->fn_sernum;
+		iter->w.state = FWS_INIT;
+		iter->w.node = iter->w.root;
+		WARN_ON(iter->w.skip);
+		iter->w.skip = iter->w.count;
+	}
+}
+
 static void *ipv6_route_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 {
 	int r;
@@ -1865,6 +1878,7 @@ static void *ipv6_route_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 	}
 
 iter_table:
+	ipv6_route_check_sernum(iter);
 	read_lock(&iter->tbl->tb6_lock);
 	r = fib6_walk_continue(&iter->w);
 	read_unlock(&iter->tbl->tb6_lock);
-- 
1.8.3.1

^ permalink raw reply related

* [PATCH net-next 1/2] ipv6: avoid high order memory allocations for /proc/net/ipv6_route
From: Hannes Frederic Sowa @ 2013-09-21 14:55 UTC (permalink / raw)
  To: netdev; +Cc: greearb, kaber, yoshfuji, davem

Dumping routes on a system with lots rt6_infos in the fibs causes up to
11-order allocations in seq_file (which fail). While we could switch
there to vmalloc we could just implement the streaming interface for
/proc/net/ipv6_route. This patch switches /proc/net/ipv6_route from
single_open_net to seq_open_net.

loff_t *pos tracks dst entries.

Also kill never used struct rt6_proc_arg and now unused function
fib6_clean_all_ro.

Cc: Ben Greear <greearb@candelatech.com>
Cc: Patrick McHardy <kaber@trash.net>
Cc: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Signed-off-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
---
 include/net/ip6_fib.h |   7 +-
 net/ipv6/ip6_fib.c    | 191 +++++++++++++++++++++++++++++++++++++++++++++-----
 net/ipv6/route.c      |  46 +-----------
 3 files changed, 176 insertions(+), 68 deletions(-)

diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h
index 48ec25a..f9f8a1e 100644
--- a/include/net/ip6_fib.h
+++ b/include/net/ip6_fib.h
@@ -281,10 +281,6 @@ struct fib6_node		*fib6_locate(struct fib6_node *root,
 					     const struct in6_addr *daddr, int dst_len,
 					     const struct in6_addr *saddr, int src_len);
 
-extern void			fib6_clean_all_ro(struct net *net,
-					       int (*func)(struct rt6_info *, void *arg),
-					       int prune, void *arg);
-
 extern void			fib6_clean_all(struct net *net,
 					       int (*func)(struct rt6_info *, void *arg),
 					       int prune, void *arg);
@@ -306,6 +302,9 @@ extern void			fib6_gc_cleanup(void);
 
 extern int			fib6_init(void);
 
+int				ipv6_route_open(struct inode *inode,
+						struct file *file);
+
 #ifdef CONFIG_IPV6_MULTIPLE_TABLES
 extern int			fib6_rules_init(void);
 extern void			fib6_rules_cleanup(void);
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
index 5bec666..05ffa54 100644
--- a/net/ipv6/ip6_fib.c
+++ b/net/ipv6/ip6_fib.c
@@ -1529,25 +1529,6 @@ static void fib6_clean_tree(struct net *net, struct fib6_node *root,
 	fib6_walk(&c.w);
 }
 
-void fib6_clean_all_ro(struct net *net, int (*func)(struct rt6_info *, void *arg),
-		    int prune, void *arg)
-{
-	struct fib6_table *table;
-	struct hlist_head *head;
-	unsigned int h;
-
-	rcu_read_lock();
-	for (h = 0; h < FIB6_TABLE_HASHSZ; h++) {
-		head = &net->ipv6.fib_table_hash[h];
-		hlist_for_each_entry_rcu(table, head, tb6_hlist) {
-			read_lock_bh(&table->tb6_lock);
-			fib6_clean_tree(net, &table->tb6_root,
-					func, prune, arg);
-			read_unlock_bh(&table->tb6_lock);
-		}
-	}
-	rcu_read_unlock();
-}
 void fib6_clean_all(struct net *net, int (*func)(struct rt6_info *, void *arg),
 		    int prune, void *arg)
 {
@@ -1782,3 +1763,175 @@ void fib6_gc_cleanup(void)
 	unregister_pernet_subsys(&fib6_net_ops);
 	kmem_cache_destroy(fib6_node_kmem);
 }
+
+#ifdef CONFIG_PROC_FS
+
+struct ipv6_route_iter {
+	struct seq_net_private p;
+	struct fib6_walker_t w;
+	loff_t skip;
+	struct fib6_table *tbl;
+};
+
+static int ipv6_route_seq_show(struct seq_file *seq, void *v)
+{
+	struct rt6_info *rt = v;
+	struct ipv6_route_iter *iter = seq->private;
+
+	seq_printf(seq, "%pi6 %02x ", &rt->rt6i_dst.addr, rt->rt6i_dst.plen);
+
+#ifdef CONFIG_IPV6_SUBTREES
+	seq_printf(seq, "%pi6 %02x ", &rt->rt6i_src.addr, rt->rt6i_src.plen);
+#else
+	seq_puts(seq, "00000000000000000000000000000000 00 ");
+#endif
+	if (rt->rt6i_flags & RTF_GATEWAY)
+		seq_printf(seq, "%pi6", &rt->rt6i_gateway);
+	else
+		seq_puts(seq, "00000000000000000000000000000000");
+
+	seq_printf(seq, " %08x %08x %08x %08x %8s\n",
+		   rt->rt6i_metric, atomic_read(&rt->dst.__refcnt),
+		   rt->dst.__use, rt->rt6i_flags,
+		   rt->dst.dev ? rt->dst.dev->name : "");
+	iter->w.leaf = NULL;
+	return 0;
+}
+
+static int ipv6_route_yield(struct fib6_walker_t *w)
+{
+	struct ipv6_route_iter *iter = w->args;
+
+	if (!iter->skip)
+		return 1;
+
+	do {
+		iter->w.leaf = iter->w.leaf->dst.rt6_next;
+		iter->skip--;
+		if (!iter->skip && iter->w.leaf)
+			return 1;
+	} while (iter->w.leaf);
+
+	return 0;
+}
+
+static void ipv6_route_seq_setup_walk(struct ipv6_route_iter *iter)
+{
+	memset(&iter->w, 0, sizeof(iter->w));
+	iter->w.func = ipv6_route_yield;
+	iter->w.root = &iter->tbl->tb6_root;
+	iter->w.state = FWS_INIT;
+	iter->w.node = iter->w.root;
+	iter->w.args = iter;
+	INIT_LIST_HEAD(&iter->w.lh);
+	fib6_walker_link(&iter->w);
+}
+
+static struct fib6_table *ipv6_route_seq_next_table(struct fib6_table *tbl,
+						    struct net *net)
+{
+	unsigned int h;
+	struct hlist_node *node;
+
+	if (tbl) {
+		h = (tbl->tb6_id & (FIB6_TABLE_HASHSZ - 1)) + 1;
+		node = rcu_dereference_bh(hlist_next_rcu(&tbl->tb6_hlist));
+	} else {
+		h = 0;
+		node = NULL;
+	}
+
+	while (!node && h < FIB6_TABLE_HASHSZ) {
+		node = rcu_dereference_bh(
+			hlist_first_rcu(&net->ipv6.fib_table_hash[h++]));
+	}
+	return hlist_entry_safe(node, struct fib6_table, tb6_hlist);
+}
+
+static void *ipv6_route_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+	int r;
+	struct rt6_info *n;
+	struct net *net = seq_file_net(seq);
+	struct ipv6_route_iter *iter = seq->private;
+
+	if (!v)
+		goto iter_table;
+
+	n = ((struct rt6_info *)v)->dst.rt6_next;
+	if (n) {
+		++*pos;
+		return n;
+	}
+
+iter_table:
+	read_lock(&iter->tbl->tb6_lock);
+	r = fib6_walk_continue(&iter->w);
+	read_unlock(&iter->tbl->tb6_lock);
+	if (r > 0) {
+		if (v)
+			++*pos;
+		return iter->w.leaf;
+	} else if (r < 0) {
+		fib6_walker_unlink(&iter->w);
+		return NULL;
+	}
+	fib6_walker_unlink(&iter->w);
+
+	iter->tbl = ipv6_route_seq_next_table(iter->tbl, net);
+	if (!iter->tbl)
+		return NULL;
+
+	ipv6_route_seq_setup_walk(iter);
+	goto iter_table;
+}
+
+static void *ipv6_route_seq_start(struct seq_file *seq, loff_t *pos)
+	__acquires(RCU_BH)
+{
+	struct net *net = seq_file_net(seq);
+	struct ipv6_route_iter *iter = seq->private;
+
+	rcu_read_lock_bh();
+	iter->tbl = ipv6_route_seq_next_table(NULL, net);
+	iter->skip = *pos;
+
+	if (iter->tbl) {
+		ipv6_route_seq_setup_walk(iter);
+		return ipv6_route_seq_next(seq, NULL, pos);
+	} else {
+		return NULL;
+	}
+}
+
+static bool ipv6_route_iter_active(struct ipv6_route_iter *iter)
+{
+	struct fib6_walker_t *w = &iter->w;
+	return w->node && !(w->state == FWS_U && w->node == w->root);
+}
+
+static void ipv6_route_seq_stop(struct seq_file *seq, void *v)
+	__releases(RCU_BH)
+{
+	struct ipv6_route_iter *iter = seq->private;
+
+	if (ipv6_route_iter_active(iter))
+		fib6_walker_unlink(&iter->w);
+
+	rcu_read_unlock_bh();
+}
+
+static const struct seq_operations ipv6_route_seq_ops = {
+	.start	= ipv6_route_seq_start,
+	.next	= ipv6_route_seq_next,
+	.stop	= ipv6_route_seq_stop,
+	.show	= ipv6_route_seq_show
+};
+
+int ipv6_route_open(struct inode *inode, struct file *file)
+{
+	return seq_open_net(inode, file, &ipv6_route_seq_ops,
+			    sizeof(struct ipv6_route_iter));
+}
+
+#endif /* CONFIG_PROC_FS */
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index c979dd9..aa901bb 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -2800,56 +2800,12 @@ static int ip6_route_dev_notify(struct notifier_block *this,
 
 #ifdef CONFIG_PROC_FS
 
-struct rt6_proc_arg
-{
-	char *buffer;
-	int offset;
-	int length;
-	int skip;
-	int len;
-};
-
-static int rt6_info_route(struct rt6_info *rt, void *p_arg)
-{
-	struct seq_file *m = p_arg;
-
-	seq_printf(m, "%pi6 %02x ", &rt->rt6i_dst.addr, rt->rt6i_dst.plen);
-
-#ifdef CONFIG_IPV6_SUBTREES
-	seq_printf(m, "%pi6 %02x ", &rt->rt6i_src.addr, rt->rt6i_src.plen);
-#else
-	seq_puts(m, "00000000000000000000000000000000 00 ");
-#endif
-	if (rt->rt6i_flags & RTF_GATEWAY) {
-		seq_printf(m, "%pi6", &rt->rt6i_gateway);
-	} else {
-		seq_puts(m, "00000000000000000000000000000000");
-	}
-	seq_printf(m, " %08x %08x %08x %08x %8s\n",
-		   rt->rt6i_metric, atomic_read(&rt->dst.__refcnt),
-		   rt->dst.__use, rt->rt6i_flags,
-		   rt->dst.dev ? rt->dst.dev->name : "");
-	return 0;
-}
-
-static int ipv6_route_show(struct seq_file *m, void *v)
-{
-	struct net *net = (struct net *)m->private;
-	fib6_clean_all_ro(net, rt6_info_route, 0, m);
-	return 0;
-}
-
-static int ipv6_route_open(struct inode *inode, struct file *file)
-{
-	return single_open_net(inode, file, ipv6_route_show);
-}
-
 static const struct file_operations ipv6_route_proc_fops = {
 	.owner		= THIS_MODULE,
 	.open		= ipv6_route_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
-	.release	= single_release_net,
+	.release	= seq_release_net,
 };
 
 static int rt6_stats_seq_show(struct seq_file *seq, void *v)
-- 
1.8.3.1

^ permalink raw reply related

* [PATCH 1/2] net: phy: at803x: don't pass function pointers with &
From: Daniel Mack @ 2013-09-21 14:53 UTC (permalink / raw)
  To: netdev; +Cc: davem, mugunthanvnm, ujhelyi.m, sergei.shtylyov, Daniel Mack

Just a cosmetic cleanup.

Signed-off-by: Daniel Mack <zonque@gmail.com>
---
 drivers/net/phy/at803x.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/net/phy/at803x.c b/drivers/net/phy/at803x.c
index ac22283..4179228 100644
--- a/drivers/net/phy/at803x.c
+++ b/drivers/net/phy/at803x.c
@@ -163,8 +163,8 @@ static struct phy_driver at803x_driver[] = {
 	.get_wol	= at803x_get_wol,
 	.features	= PHY_GBIT_FEATURES,
 	.flags		= PHY_HAS_INTERRUPT,
-	.config_aneg	= &genphy_config_aneg,
-	.read_status	= &genphy_read_status,
+	.config_aneg	= genphy_config_aneg,
+	.read_status	= genphy_read_status,
 	.driver		= {
 		.owner = THIS_MODULE,
 	},
@@ -178,8 +178,8 @@ static struct phy_driver at803x_driver[] = {
 	.get_wol	= at803x_get_wol,
 	.features	= PHY_GBIT_FEATURES,
 	.flags		= PHY_HAS_INTERRUPT,
-	.config_aneg	= &genphy_config_aneg,
-	.read_status	= &genphy_read_status,
+	.config_aneg	= genphy_config_aneg,
+	.read_status	= genphy_read_status,
 	.driver		= {
 		.owner = THIS_MODULE,
 	},
@@ -193,8 +193,8 @@ static struct phy_driver at803x_driver[] = {
 	.get_wol	= at803x_get_wol,
 	.features	= PHY_GBIT_FEATURES,
 	.flags		= PHY_HAS_INTERRUPT,
-	.config_aneg	= &genphy_config_aneg,
-	.read_status	= &genphy_read_status,
+	.config_aneg	= genphy_config_aneg,
+	.read_status	= genphy_read_status,
 	.driver		= {
 		.owner = THIS_MODULE,
 	},
-- 
1.8.3.1

^ permalink raw reply related

* [PATCH 2/2] net: phy: at803x: add suspend/resume callbacks
From: Daniel Mack @ 2013-09-21 14:53 UTC (permalink / raw)
  To: netdev; +Cc: davem, mugunthanvnm, ujhelyi.m, sergei.shtylyov, Daniel Mack
In-Reply-To: <1379775182-1271-1-git-send-email-zonque@gmail.com>

When WOL is enabled, the chip can't be put into power-down (BMCR_PDOWN)
mode, as that will also switch off the MAC, which consequently leads to
a link loss.

Use BMCR_ISOLATE in that case, which will at least save us some
milliamperes in comparison to normal operation mode.

Signed-off-by: Daniel Mack <zonque@gmail.com>
---
 drivers/net/phy/at803x.c | 45 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 45 insertions(+)

diff --git a/drivers/net/phy/at803x.c b/drivers/net/phy/at803x.c
index 4179228..bc71947 100644
--- a/drivers/net/phy/at803x.c
+++ b/drivers/net/phy/at803x.c
@@ -100,6 +100,45 @@ static void at803x_get_wol(struct phy_device *phydev,
 		wol->wolopts |= WAKE_MAGIC;
 }
 
+static int at803x_suspend(struct phy_device *phydev)
+{
+	int value;
+	int wol_enabled;
+
+	mutex_lock(&phydev->lock);
+
+	value = phy_read(phydev, AT803X_INTR_ENABLE);
+	wol_enabled = value & AT803X_WOL_ENABLE;
+
+	value = phy_read(phydev, MII_BMCR);
+
+	if (wol_enabled)
+		value |= BMCR_ISOLATE;
+	else
+		value |= BMCR_PDOWN;
+
+	phy_write(phydev, MII_BMCR, value);
+
+	mutex_unlock(&phydev->lock);
+
+	return 0;
+}
+
+static int at803x_resume(struct phy_device *phydev)
+{
+	int value;
+
+	mutex_lock(&phydev->lock);
+
+	value = phy_read(phydev, MII_BMCR);
+	value &= ~(BMCR_PDOWN | BMCR_ISOLATE);
+	phy_write(phydev, MII_BMCR, value);
+
+	mutex_unlock(&phydev->lock);
+
+	return 0;
+}
+
 static int at803x_config_init(struct phy_device *phydev)
 {
 	int val;
@@ -161,6 +200,8 @@ static struct phy_driver at803x_driver[] = {
 	.config_init	= at803x_config_init,
 	.set_wol	= at803x_set_wol,
 	.get_wol	= at803x_get_wol,
+	.suspend	= at803x_suspend,
+	.resume		= at803x_resume,
 	.features	= PHY_GBIT_FEATURES,
 	.flags		= PHY_HAS_INTERRUPT,
 	.config_aneg	= genphy_config_aneg,
@@ -176,6 +217,8 @@ static struct phy_driver at803x_driver[] = {
 	.config_init	= at803x_config_init,
 	.set_wol	= at803x_set_wol,
 	.get_wol	= at803x_get_wol,
+	.suspend	= at803x_suspend,
+	.resume		= at803x_resume,
 	.features	= PHY_GBIT_FEATURES,
 	.flags		= PHY_HAS_INTERRUPT,
 	.config_aneg	= genphy_config_aneg,
@@ -191,6 +234,8 @@ static struct phy_driver at803x_driver[] = {
 	.config_init	= at803x_config_init,
 	.set_wol	= at803x_set_wol,
 	.get_wol	= at803x_get_wol,
+	.suspend	= at803x_suspend,
+	.resume		= at803x_resume,
 	.features	= PHY_GBIT_FEATURES,
 	.flags		= PHY_HAS_INTERRUPT,
 	.config_aneg	= genphy_config_aneg,
-- 
1.8.3.1

^ permalink raw reply related

* pull-request: can 2013-09-21
From: Marc Kleine-Budde @ 2013-09-21 14:08 UTC (permalink / raw)
  To: netdev; +Cc: davem, linux-can, kernel

Hello David,

here is a fixes for the v3.12 release cycle. Alexey Khoroshilov from the Linux
Driver Verification project submitted a patch that fixes a memory leak in the
failure paths of the peak USB driver.


regards,
Marc

---

The following changes since commit dcb30e659287a6b40dafed1362532da42ec27229:

  Merge tag 'arm64-stable' of git://git.kernel.org/pub/scm/linux/kernel/git/cmarinas/linux-aarch64 (2013-09-20 08:18:51 -0500)

are available in the git repository at:


  git://gitorious.org/linux-can/linux-can.git fixes-for-3.12

for you to fetch changes up to f37d6e701f2a3a04e66690397340a6417f6e053f:

  can: pcan_usb_core: fix memory leak on failure paths in peak_usb_start() (2013-09-20 20:58:21 +0200)

----------------------------------------------------------------
Alexey Khoroshilov (1):
      can: pcan_usb_core: fix memory leak on failure paths in peak_usb_start()

 drivers/net/can/usb/peak_usb/pcan_usb_core.c | 15 +++++++++++----
 1 file changed, 11 insertions(+), 4 deletions(-)

^ permalink raw reply

* [PATCH] can: pcan_usb_core: fix memory leak on failure paths in peak_usb_start()
From: Marc Kleine-Budde @ 2013-09-21 14:08 UTC (permalink / raw)
  To: netdev; +Cc: davem, linux-can, kernel, Alexey Khoroshilov, Marc Kleine-Budde
In-Reply-To: <1379772493-7856-1-git-send-email-mkl@pengutronix.de>

From: Alexey Khoroshilov <khoroshilov@ispras.ru>

Tx and rx urbs are not deallocated if something goes wrong in peak_usb_start().
The patch fixes error handling to deallocate all the resources.

Found by Linux Driver Verification project (linuxtesting.org).

Signed-off-by: Alexey Khoroshilov <khoroshilov@ispras.ru>
Acked-by: Stephane Grosjean <s.grosjean@peak-system.com>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/net/can/usb/peak_usb/pcan_usb_core.c | 15 +++++++++++----
 1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/drivers/net/can/usb/peak_usb/pcan_usb_core.c b/drivers/net/can/usb/peak_usb/pcan_usb_core.c
index a0f647f..0b7a4c3 100644
--- a/drivers/net/can/usb/peak_usb/pcan_usb_core.c
+++ b/drivers/net/can/usb/peak_usb/pcan_usb_core.c
@@ -463,7 +463,7 @@ static int peak_usb_start(struct peak_usb_device *dev)
 	if (i < PCAN_USB_MAX_TX_URBS) {
 		if (i == 0) {
 			netdev_err(netdev, "couldn't setup any tx URB\n");
-			return err;
+			goto err_tx;
 		}
 
 		netdev_warn(netdev, "tx performance may be slow\n");
@@ -472,7 +472,7 @@ static int peak_usb_start(struct peak_usb_device *dev)
 	if (dev->adapter->dev_start) {
 		err = dev->adapter->dev_start(dev);
 		if (err)
-			goto failed;
+			goto err_adapter;
 	}
 
 	dev->state |= PCAN_USB_STATE_STARTED;
@@ -481,19 +481,26 @@ static int peak_usb_start(struct peak_usb_device *dev)
 	if (dev->adapter->dev_set_bus) {
 		err = dev->adapter->dev_set_bus(dev, 1);
 		if (err)
-			goto failed;
+			goto err_adapter;
 	}
 
 	dev->can.state = CAN_STATE_ERROR_ACTIVE;
 
 	return 0;
 
-failed:
+err_adapter:
 	if (err == -ENODEV)
 		netif_device_detach(dev->netdev);
 
 	netdev_warn(netdev, "couldn't submit control: %d\n", err);
 
+	for (i = 0; i < PCAN_USB_MAX_TX_URBS; i++) {
+		usb_free_urb(dev->tx_contexts[i].urb);
+		dev->tx_contexts[i].urb = NULL;
+	}
+err_tx:
+	usb_kill_anchored_urbs(&dev->rx_submitted);
+
 	return err;
 }
 
-- 
1.8.4.rc3

^ permalink raw reply related

* pull-request: can-next 2013-09-21
From: Marc Kleine-Budde @ 2013-09-21 13:54 UTC (permalink / raw)
  To: Linux Netdev List
  Cc: linux-can@vger.kernel.org, David Miller, kernel@pengutronix.de

[-- Attachment #1: Type: text/plain, Size: 3162 bytes --]

Hello David,

this is a pull request for net-next. It consists of two patches by Uwe
Kleine-König, they add explicit copyrights to the uapi CAN headers
(including Acked-bys of the header authors). And 12 cleanup patches by
Jingoo Han. Several drivers are converted to use dev_get_platdata()
instead of open coding it, two unnecessary pci_set_drvdata() are
removed from the CAN PCI drivers.

regards,
Marc

---

The following changes since commit 19717d05848849a3b1dddeced9abb5884cff9152:

  declance: Remove `incompatible pointer type' warnings (2013-09-20 14:41:03 -0400)

are available in the git repository at:

  git://gitorious.org/linux-can/linux-can-next.git for-davem

for you to fetch changes up to a0c7d83322521880caf8c9c1ef20a2a1cd5cb955:

  can: sja1000: remove unnecessary pci_set_drvdata() (2013-09-21 15:43:16 +0200)

----------------------------------------------------------------
Jingoo Han (12):
      can: at91_can: use dev_get_platdata()
      can: bfin_can: use dev_get_platdata()
      can: cc770: use dev_get_platdata()
      can: flexcan: use dev_get_platdata()
      can: janz-ican3: use dev_get_platdata()
      can: mcp251x: use dev_get_platdata()
      can: sja1000: use dev_get_platdata()
      can: softing: use dev_get_platdata()
      can: ti_hecc: use dev_get_platdata()
      can: c_can: remove unnecessary pci_set_drvdata()
      can: pch_can: remove unnecessary pci_set_drvdata()
      can: sja1000: remove unnecessary pci_set_drvdata()

Uwe Kleine-König (2):
      can: add explicit copyrights to can headers
      can: add explicit copyrights to can's netlink header

 drivers/net/can/at91_can.c                 |  2 +-
 drivers/net/can/bfin_can.c                 |  2 +-
 drivers/net/can/c_can/c_can_pci.c          |  2 --
 drivers/net/can/cc770/cc770_platform.c     |  4 ++--
 drivers/net/can/flexcan.c                  |  2 +-
 drivers/net/can/janz-ican3.c               |  2 +-
 drivers/net/can/mcp251x.c                  |  2 +-
 drivers/net/can/pch_can.c                  |  1 -
 drivers/net/can/sja1000/ems_pci.c          |  1 -
 drivers/net/can/sja1000/kvaser_pci.c       |  1 -
 drivers/net/can/sja1000/peak_pci.c         |  2 --
 drivers/net/can/sja1000/plx_pci.c          |  1 -
 drivers/net/can/sja1000/sja1000_platform.c |  2 +-
 drivers/net/can/softing/softing_main.c     |  2 +-
 drivers/net/can/ti_hecc.c                  |  2 +-
 include/uapi/linux/can/bcm.h               | 32 ++++++++++++++++++++++++++++++
 include/uapi/linux/can/error.h             | 32 ++++++++++++++++++++++++++++++
 include/uapi/linux/can/gw.h                | 32 ++++++++++++++++++++++++++++++
 include/uapi/linux/can/netlink.h           |  8 ++++++++
 include/uapi/linux/can/raw.h               | 32 ++++++++++++++++++++++++++++++
 20 files changed, 146 insertions(+), 18 deletions(-)

-- 
Pengutronix e.K.                  | Marc Kleine-Budde           |
Industrial Linux Solutions        | Phone: +49-231-2826-924     |
Vertretung West/Dortmund          | Fax:   +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686  | http://www.pengutronix.de   |


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 259 bytes --]

^ permalink raw reply

* [PATCH] via-rhine: fix VLAN priority field (PCP, IEEE 802.1p)
From: Roger Luethi @ 2013-09-21 12:24 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, Peter Boström

From: Roger Luethi <rl@hellgate.ch>

Outgoing packets sent by via-rhine have their VLAN PCP field off by one
(when hardware acceleration is enabled). The TX descriptor expects only VID
and PCP (without a CFI/DEI bit).

Peter Boström noticed and reported the bug.

Signed-off-by: Roger Luethi <rl@hellgate.ch>
Cc: Peter Boström <peter.bostrom@netrounds.com>
---
 drivers/net/ethernet/via/via-rhine.c |    9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/via/via-rhine.c b/drivers/net/ethernet/via/via-rhine.c
index c8f088a..bdf697b 100644
--- a/drivers/net/ethernet/via/via-rhine.c
+++ b/drivers/net/ethernet/via/via-rhine.c
@@ -32,7 +32,7 @@
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
 #define DRV_NAME	"via-rhine"
-#define DRV_VERSION	"1.5.0"
+#define DRV_VERSION	"1.5.1"
 #define DRV_RELDATE	"2010-10-09"
 
 #include <linux/types.h>
@@ -1704,7 +1704,12 @@ static netdev_tx_t rhine_start_tx(struct sk_buff *skb,
 		cpu_to_le32(TXDESC | (skb->len >= ETH_ZLEN ? skb->len : ETH_ZLEN));
 
 	if (unlikely(vlan_tx_tag_present(skb))) {
-		rp->tx_ring[entry].tx_status = cpu_to_le32((vlan_tx_tag_get(skb)) << 16);
+		u16 vid_pcp = vlan_tx_tag_get(skb);
+
+		/* drop CFI/DEI bit, register needs VID and PCP */
+		vid_pcp = (vid_pcp & VLAN_VID_MASK) |
+			  ((vid_pcp & VLAN_PRIO_MASK) >> 1);
+		rp->tx_ring[entry].tx_status = cpu_to_le32((vid_pcp) << 16);
 		/* request tagging */
 		rp->tx_ring[entry].desc_length |= cpu_to_le32(0x020000);
 	}

^ permalink raw reply related

* [PATCH v2] arm: bpf_jit: support MOD operation
From: Vladimir Murzin @ 2013-09-21  7:32 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: netdev, davem, linux, mgherzan, dborkman, edumazet, will.daecon,
	Vladimir Murzin

commit b6069a9570 (filter: add MOD operation) added generic
support for modulus operation in BPF.

This patch brings JIT support for ARM.

Signed-off-by: Vladimir Murzin <murzin.v@gmail.com>
---
v1->v2
    - wrapper for udiv_mod is added
    - MUL and SUB are squashed into MLS instruction
    
For BPF program

(000) ldh      [12]
(001) jeq      #0x800           jt 2	jf 10
(002) ldh      [16]
(003) sub      #20
(004) mod      #5
(005) jeq      #0x0             jt 10	jf 6
(006) ldb      [20]
(007) and      #0x20
(008) jeq      #0x20            jt 9	jf 10
(009) ret      #65535
(010) ret      #0

Following code is generated

256 bytes emitted from JIT compiler (pass:2, flen:11)
bf008000 + <x>:
   0:	push	{r4, r6, r7, r8, lr}
   4:	mov	r6, r0
   8:	ldr	r7, [r6, #168]	; 0xa8
   c:	ldr	r8, [r6, #80]	; 0x50
  10:	ldr	r0, [r6, #84]	; 0x54
  14:	sub	r8, r8, r0
  18:	mov	r1, #12
  1c:	sub	r0, r8, #2
  20:	cmp	r0, r1
  24:	addcs	r0, r1, r7
  28:	ldrhcs	r4, [r0]
  2c:	rev16cs	r4, r4
  30:	bcs	0x00000054
  34:	movw	r3, #7012	; 0x1b64
  38:	movt	r3, #49154	; 0xc002
  3c:	mov	r0, r6
  40:	blx	r3
  44:	cmp	r1, #0
  48:	bne	0x000000f8
  4c:	nop			; (mov r0, r0)
  50:	mov	r4, r0
  54:	cmp	r4, #2048	; 0x800
  58:	bne	0x000000f8
  5c:	mov	r1, #16
  60:	sub	r0, r8, #2
  64:	cmp	r0, r1
  68:	addcs	r0, r1, r7
  6c:	ldrhcs	r4, [r0]
  70:	rev16cs	r4, r4
  74:	bcs	0x00000098
  78:	movw	r3, #7012	; 0x1b64
  7c:	movt	r3, #49154	; 0xc002
  80:	mov	r0, r6
  84:	blx	r3
  88:	cmp	r1, #0
  8c:	bne	0x000000f8
  90:	nop			; (mov r0, r0)
  94:	mov	r4, r0
  98:	sub	r4, r4, #20
  9c:	mov	r0, #5
  a0:	udiv	r3, r4, r0
  a4:	mls	r4, r3, r0, r4
  a8:	cmp	r4, #0
  ac:	beq	0x000000f8
  b0:	mov	r1, #20
  b4:	cmp	r8, r1
  b8:	addhi	r0, r1, r7
  bc:	ldrbhi	r4, [r0]
  c0:	bhi	0x000000e4
  c4:	movw	r3, #7068	; 0x1b9c
  c8:	movt	r3, #49154	; 0xc002
  cc:	mov	r0, r6
  d0:	blx	r3
  d4:	cmp	r1, #0
  d8:	bne	0x000000f8
  dc:	nop			; (mov r0, r0)
  e0:	mov	r4, r0
  e4:	and	r4, r4, #32
  e8:	cmp	r4, #32
  ec:	bne	0x000000f8
  f0:	movw	r0, #65535	; 0xffff
  f4:	b	0x000000fc
  f8:	mov	r0, #0
  fc:	pop	{r4, r6, r7, r8, pc}

Raw opcodes are

flen=11 proglen=256 pass=2 image=bf008000
JIT code: 00000000: d0 41 2d e9 00 60 a0 e1 a8 70 96 e5 50 80 96 e5
JIT code: 00000010: 54 00 96 e5 00 80 48 e0 0c 10 a0 e3 02 00 48 e2
JIT code: 00000020: 01 00 50 e1 07 00 81 20 b0 40 d0 21 b4 4f bf 26
JIT code: 00000030: 07 00 00 2a 64 3b 01 e3 02 30 4c e3 06 00 a0 e1
JIT code: 00000040: 33 ff 2f e1 00 00 51 e3 2a 00 00 1a 00 00 a0 e1
JIT code: 00000050: 00 40 a0 e1 02 0b 54 e3 26 00 00 1a 10 10 a0 e3
JIT code: 00000060: 02 00 48 e2 01 00 50 e1 07 00 81 20 b0 40 d0 21
JIT code: 00000070: b4 4f bf 26 07 00 00 2a 64 3b 01 e3 02 30 4c e3
JIT code: 00000080: 06 00 a0 e1 33 ff 2f e1 00 00 51 e3 19 00 00 1a
JIT code: 00000090: 00 00 a0 e1 00 40 a0 e1 14 40 44 e2 05 00 a0 e3
JIT code: 000000a0: 14 f0 33 e7 93 40 64 e0 00 00 54 e3 11 00 00 0a
JIT code: 000000b0: 14 10 a0 e3 01 00 58 e1 07 00 81 80 00 40 d0 85
JIT code: 000000c0: 07 00 00 8a 9c 3b 01 e3 02 30 4c e3 06 00 a0 e1
JIT code: 000000d0: 33 ff 2f e1 00 00 51 e3 06 00 00 1a 00 00 a0 e1
JIT code: 000000e0: 00 40 a0 e1 20 40 04 e2 20 00 54 e3 01 00 00 1a
JIT code: 000000f0: ff 0f 0f e3 00 00 00 ea 00 00 a0 e3 d0 81 bd e8

 arch/arm/net/bpf_jit_32.c |   38 ++++++++++++++++++++++++++++++++++++++
 arch/arm/net/bpf_jit_32.h |    3 +++
 2 files changed, 41 insertions(+)

diff --git a/arch/arm/net/bpf_jit_32.c b/arch/arm/net/bpf_jit_32.c
index f50d223..faec4d3 100644
--- a/arch/arm/net/bpf_jit_32.c
+++ b/arch/arm/net/bpf_jit_32.c
@@ -111,6 +111,11 @@ static u32 jit_udiv(u32 dividend, u32 divisor)
 	return dividend / divisor;
 }
 
+static u32 jit_udiv_mod(u32 dividend, u32 divisor)
+{
+	return dividend % divisor;
+}
+
 static inline void _emit(int cond, u32 inst, struct jit_ctx *ctx)
 {
 	if (ctx->target != NULL)
@@ -458,6 +463,29 @@ static inline void emit_udiv(u8 rd, u8 rm, u8 rn, struct jit_ctx *ctx)
 		emit(ARM_MOV_R(rd, ARM_R0), ctx);
 }
 
+static inline void emit_udiv_mod(u8 rd, u8 rm, u8 rn, struct jit_ctx *ctx)
+{
+#if __LINUX_ARM_ARCH__ == 7
+	if (elf_hwcap & HWCAP_IDIVA) {
+		emit(ARM_UDIV(ARM_R3, rm, rn), ctx);
+		emit(ARM_MLS(rd, ARM_R3, rn, rm), ctx);
+		return;
+	}
+#endif
+	if (rm != ARM_R0)
+		emit(ARM_MOV_R(ARM_R0, rm), ctx);
+	if (rn != ARM_R1)
+		emit(ARM_MOV_R(ARM_R1, rn), ctx);
+
+	ctx->seen |= SEEN_CALL;
+	emit_mov_i(ARM_R3, (u32)jit_udiv_mod, ctx);
+	emit_blx_r(ARM_R3, ctx);
+
+	if (rd != ARM_R0)
+		emit(ARM_MOV_R(rd, ARM_R0), ctx);
+}
+
+
 static inline void update_on_xread(struct jit_ctx *ctx)
 {
 	if (!(ctx->seen & SEEN_X))
@@ -636,6 +664,16 @@ load_ind:
 			update_on_xread(ctx);
 			emit(ARM_MUL(r_A, r_A, r_X), ctx);
 			break;
+		case BPF_S_ALU_MOD_X: /* A %= X; */
+			update_on_xread(ctx);
+			emit(ARM_CMP_I(r_X, 0), ctx);
+			emit_err_ret(ARM_COND_EQ, ctx);
+			emit_udiv_mod(r_A, r_A, r_X, ctx);
+			break;
+		case BPF_S_ALU_MOD_K: /* A %= K; */
+			emit_mov_i(r_scratch, k, ctx);
+			emit_udiv_mod(r_A, r_A, r_scratch, ctx);
+			break;
 		case BPF_S_ALU_DIV_K:
 			/* current k == reciprocal_value(userspace k) */
 			emit_mov_i(r_scratch, k, ctx);
diff --git a/arch/arm/net/bpf_jit_32.h b/arch/arm/net/bpf_jit_32.h
index afb8462..640a8fd 100644
--- a/arch/arm/net/bpf_jit_32.h
+++ b/arch/arm/net/bpf_jit_32.h
@@ -90,6 +90,7 @@
 #define ARM_INST_MOVT		0x03400000
 
 #define ARM_INST_MUL		0x00000090
+#define ARM_INST_MLS		0x00600090
 
 #define ARM_INST_POP		0x08bd0000
 #define ARM_INST_PUSH		0x092d0000
@@ -192,5 +193,7 @@
 
 #define ARM_UMULL(rd_lo, rd_hi, rn, rm)	(ARM_INST_UMULL | (rd_hi) << 16 \
 					 | (rd_lo) << 12 | (rm) << 8 | rn)
+#define ARM_MLS(rd, rn, rm, ra)	(ARM_INST_MLS | (rd) << 16 \
+					 | (ra) << 12 | (rm) << 8 | rn)
 
 #endif /* PFILTER_OPCODES_ARM_H */
-- 
1.7.10.4

^ permalink raw reply related

* [RESEND PATCH 2/2] ppc: bpf_jit: support MOD operation
From: Vladimir Murzin @ 2013-09-21  7:25 UTC (permalink / raw)
  To: linuxppc-dev
  Cc: netdev, davem, benh, paulus, matt, edumazet, dborkman,
	Vladimir Murzin
In-Reply-To: <1379748334-3313-1-git-send-email-murzin.v@gmail.com>

commit b6069a9570 (filter: add MOD operation) added generic
support for modulus operation in BPF.

This patch brings JIT support for PPC64

Signed-off-by: Vladimir Murzin <murzin.v@gmail.com>
Acked-by: Matt Evans <matt@ozlabs.org>
---
 arch/powerpc/net/bpf_jit_comp.c | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/arch/powerpc/net/bpf_jit_comp.c b/arch/powerpc/net/bpf_jit_comp.c
index bf56e33..96f24dc 100644
--- a/arch/powerpc/net/bpf_jit_comp.c
+++ b/arch/powerpc/net/bpf_jit_comp.c
@@ -193,6 +193,28 @@ static int bpf_jit_build_body(struct sk_filter *fp, u32 *image,
 				PPC_MUL(r_A, r_A, r_scratch1);
 			}
 			break;
+		case BPF_S_ALU_MOD_X: /* A %= X; */
+			ctx->seen |= SEEN_XREG;
+			PPC_CMPWI(r_X, 0);
+			if (ctx->pc_ret0 != -1) {
+				PPC_BCC(COND_EQ, addrs[ctx->pc_ret0]);
+			} else {
+				PPC_BCC_SHORT(COND_NE, (ctx->idx*4)+12);
+				PPC_LI(r_ret, 0);
+				PPC_JMP(exit_addr);
+			}
+			PPC_DIVWU(r_scratch1, r_A, r_X);
+			PPC_MUL(r_scratch1, r_X, r_scratch1);
+			PPC_SUB(r_A, r_A, r_scratch1);
+			break;
+		case BPF_S_ALU_MOD_K: /* A %= K; */
+#define r_scratch2 (r_scratch1 + 1)
+			PPC_LI32(r_scratch2, K);
+			PPC_DIVWU(r_scratch1, r_A, r_scratch2);
+			PPC_MUL(r_scratch1, r_scratch2, r_scratch1);
+			PPC_SUB(r_A, r_A, r_scratch1);
+#undef r_scratch2
+			break;
 		case BPF_S_ALU_DIV_X: /* A /= X; */
 			ctx->seen |= SEEN_XREG;
 			PPC_CMPWI(r_X, 0);
-- 
1.8.1.5

^ permalink raw reply related

* [RESEND PATCH 1/2] powerpc: net: filter: fix DIVWU instruction opcode
From: Vladimir Murzin @ 2013-09-21  7:25 UTC (permalink / raw)
  To: linuxppc-dev
  Cc: netdev, davem, benh, paulus, matt, edumazet, dborkman,
	Vladimir Murzin

Currently DIVWU stands for *signed* divw opcode:

7d 2a 4b 96 	divwu   r9,r10,r9
7d 2a 4b d6 	divw    r9,r10,r9

Use the *unsigned* divw opcode for DIVWU.

Signed-off-by: Vladimir Murzin <murzin.v@gmail.com>
Acked-by: Matt Evans <matt@ozlabs.org>
---
 arch/powerpc/include/asm/ppc-opcode.h |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/powerpc/include/asm/ppc-opcode.h b/arch/powerpc/include/asm/ppc-opcode.h
index d7fe9f5..c91842c 100644
--- a/arch/powerpc/include/asm/ppc-opcode.h
+++ b/arch/powerpc/include/asm/ppc-opcode.h
@@ -218,7 +218,7 @@
 #define PPC_INST_MULLW			0x7c0001d6
 #define PPC_INST_MULHWU			0x7c000016
 #define PPC_INST_MULLI			0x1c000000
-#define PPC_INST_DIVWU			0x7c0003d6
+#define PPC_INST_DIVWU			0x7c000396
 #define PPC_INST_RLWINM			0x54000000
 #define PPC_INST_RLDICR			0x78000004
 #define PPC_INST_SLW			0x7c000030
-- 
1.7.10.4

^ permalink raw reply related

* [PATCH net-next] net: neighbour: use source address of last enqueued packet for solicitation
From: Hannes Frederic Sowa @ 2013-09-21  4:32 UTC (permalink / raw)
  To: netdev; +Cc: davem, ja

Currently we always use the first member of the arp_queue to determine
the sender ip address of the arp packet (or in case of IPv6 - source
address of the ndisc packet). This skb is fixed as long as the queue is
not drained by a complete purge because of a timeout or by a successful
response.

If the first packet enqueued on the arp_queue is from a local application
with a manually set source address and the to be discovered system
does some kind of uRPF checks on the source address in the arp packet
the resolving process hangs until a timeout and restarts. This hurts
communication with the participating network node.

This could be mitigated a bit if we use the latest enqueued skb's
source address for the resolving process, which is not as static as
the arp_queue's head. This change of the source address could result in
better recovery of a failed solicitation.

Cc: "David S. Miller" <davem@davemloft.net>
Cc: Julian Anastasov <ja@ssi.bg>
Reviewed-by: Julian Anastasov <ja@ssi.bg>
Signed-off-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
---
 net/core/neighbour.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index 6072610..ca15f32 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -867,7 +867,7 @@ static void neigh_invalidate(struct neighbour *neigh)
 static void neigh_probe(struct neighbour *neigh)
 	__releases(neigh->lock)
 {
-	struct sk_buff *skb = skb_peek(&neigh->arp_queue);
+	struct sk_buff *skb = skb_peek_tail(&neigh->arp_queue);
 	/* keep skb alive even if arp_queue overflows */
 	if (skb)
 		skb = skb_copy(skb, GFP_ATOMIC);
-- 
1.8.3.1

^ permalink raw reply related

* [PATCH] ipv6: udp packets following an UFO enqueued packet need also be handled by UFO
From: Hannes Frederic Sowa @ 2013-09-21  4:27 UTC (permalink / raw)
  To: netdev; +Cc: yoshfuji, davem

In the following scenario the socket is corked:
If the first UDP packet is larger then the mtu we try to append it to the
write queue via ip6_ufo_append_data. A following packet, which is smaller
than the mtu would be appended to the already queued up gso-skb via
plain ip6_append_data. This causes random memory corruptions.

In ip6_ufo_append_data we also have to be careful to not queue up the
same skb multiple times. So setup the gso frame only when no first skb
is available.

This also fixes a shortcoming where we add the current packet's length to
cork->length but return early because of a packet > mtu with dontfrag set
(instead of sutracting it again).

Found with trinity.

Cc: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Signed-off-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
---

I could only test this with virtualized UFO enabled network cards. Could
someone test this on real hardware?

 net/ipv6/ip6_output.c | 53 +++++++++++++++++++++------------------------------
 1 file changed, 22 insertions(+), 31 deletions(-)

diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 3a692d5..a54c45c 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -1015,6 +1015,8 @@ static inline int ip6_ufo_append_data(struct sock *sk,
 	 * udp datagram
 	 */
 	if ((skb = skb_peek_tail(&sk->sk_write_queue)) == NULL) {
+		struct frag_hdr fhdr;
+
 		skb = sock_alloc_send_skb(sk,
 			hh_len + fragheaderlen + transhdrlen + 20,
 			(flags & MSG_DONTWAIT), &err);
@@ -1036,12 +1038,6 @@ static inline int ip6_ufo_append_data(struct sock *sk,
 		skb->protocol = htons(ETH_P_IPV6);
 		skb->ip_summed = CHECKSUM_PARTIAL;
 		skb->csum = 0;
-	}
-
-	err = skb_append_datato_frags(sk,skb, getfrag, from,
-				      (length - transhdrlen));
-	if (!err) {
-		struct frag_hdr fhdr;
 
 		/* Specify the length of each IPv6 datagram fragment.
 		 * It has to be a multiple of 8.
@@ -1052,15 +1048,10 @@ static inline int ip6_ufo_append_data(struct sock *sk,
 		ipv6_select_ident(&fhdr, rt);
 		skb_shinfo(skb)->ip6_frag_id = fhdr.identification;
 		__skb_queue_tail(&sk->sk_write_queue, skb);
-
-		return 0;
 	}
-	/* There is not enough support do UPD LSO,
-	 * so follow normal path
-	 */
-	kfree_skb(skb);
 
-	return err;
+	return skb_append_datato_frags(sk, skb, getfrag, from,
+				       (length - transhdrlen));
 }
 
 static inline struct ipv6_opt_hdr *ip6_opt_dup(struct ipv6_opt_hdr *src,
@@ -1227,27 +1218,27 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
 	 * --yoshfuji
 	 */
 
-	cork->length += length;
-	if (length > mtu) {
-		int proto = sk->sk_protocol;
-		if (dontfrag && (proto == IPPROTO_UDP || proto == IPPROTO_RAW)){
-			ipv6_local_rxpmtu(sk, fl6, mtu-exthdrlen);
-			return -EMSGSIZE;
-		}
-
-		if (proto == IPPROTO_UDP &&
-		    (rt->dst.dev->features & NETIF_F_UFO)) {
+	if ((length > mtu) && dontfrag && (sk->sk_protocol == IPPROTO_UDP ||
+					   sk->sk_protocol == IPPROTO_RAW)) {
+		ipv6_local_rxpmtu(sk, fl6, mtu-exthdrlen);
+		return -EMSGSIZE;
+	}
 
-			err = ip6_ufo_append_data(sk, getfrag, from, length,
-						  hh_len, fragheaderlen,
-						  transhdrlen, mtu, flags, rt);
-			if (err)
-				goto error;
-			return 0;
-		}
+	skb = skb_peek_tail(&sk->sk_write_queue);
+	cork->length += length;
+	if (((length > mtu) ||
+	     (skb && skb_is_gso(skb))) &&
+	    (sk->sk_protocol == IPPROTO_UDP) &&
+	    (rt->dst.dev->features & NETIF_F_UFO)) {
+		err = ip6_ufo_append_data(sk, getfrag, from, length,
+					  hh_len, fragheaderlen,
+					  transhdrlen, mtu, flags, rt);
+		if (err)
+			goto error;
+		return 0;
 	}
 
-	if ((skb = skb_peek_tail(&sk->sk_write_queue)) == NULL)
+	if (!skb)
 		goto alloc_new_skb;
 
 	while (length > 0) {
-- 
1.8.3.1

^ permalink raw reply related

* [PATCH net-next] ipv6: do not allow ipv6 module to be removed
From: Cong Wang @ 2013-09-21  3:12 UTC (permalink / raw)
  To: netdev; +Cc: David S. Miller, Hideaki YOSHIFUJI, Stephen Hemminger, Cong Wang

From: Cong Wang <amwang@redhat.com>

There was some bug report on ipv6 module removal path before.
Also, as Stephen pointed out, after vxlan module gets ipv6 support,
the ipv6 stub it used is not safe against this module removal either.
So, let's just remove inet6_exit() so that ipv6 module will not be
able to be unloaded.

Cc: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
Cc: Stephen Hemminger <stephen@networkplumber.org>
Cc: David S. Miller <davem@davemloft.net>
Signed-off-by: Cong Wang <amwang@redhat.com>

---
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index 7c96100..4966b12 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -1028,52 +1028,4 @@ out_unregister_tcp_proto:
 }
 module_init(inet6_init);
 
-static void __exit inet6_exit(void)
-{
-	if (disable_ipv6_mod)
-		return;
-
-	/* First of all disallow new sockets creation. */
-	sock_unregister(PF_INET6);
-	/* Disallow any further netlink messages */
-	rtnl_unregister_all(PF_INET6);
-
-	udpv6_exit();
-	udplitev6_exit();
-	tcpv6_exit();
-
-	/* Cleanup code parts. */
-	ipv6_packet_cleanup();
-	ipv6_frag_exit();
-	ipv6_exthdrs_exit();
-	addrconf_cleanup();
-	ip6_flowlabel_cleanup();
-	ndisc_late_cleanup();
-	ip6_route_cleanup();
-#ifdef CONFIG_PROC_FS
-
-	/* Cleanup code parts. */
-	if6_proc_exit();
-	ipv6_misc_proc_exit();
-	udplite6_proc_exit();
-	raw6_proc_exit();
-#endif
-	ipv6_netfilter_fini();
-	ipv6_stub = NULL;
-	igmp6_cleanup();
-	ndisc_cleanup();
-	ip6_mr_cleanup();
-	icmpv6_cleanup();
-	rawv6_exit();
-
-	unregister_pernet_subsys(&inet6_net_ops);
-	proto_unregister(&rawv6_prot);
-	proto_unregister(&udplitev6_prot);
-	proto_unregister(&udpv6_prot);
-	proto_unregister(&tcpv6_prot);
-
-	rcu_barrier(); /* Wait for completion of call_rcu()'s */
-}
-module_exit(inet6_exit);
-
 MODULE_ALIAS_NETPROTO(PF_INET6);

^ permalink raw reply related

* [RESEND PATCH iproute2] vxlan: add ipv6 support
From: Cong Wang @ 2013-09-21  2:35 UTC (permalink / raw)
  To: netdev; +Cc: David S. Miller, Cong Wang, Stephen Hemminger

From: Cong Wang <amwang@redhat.com>

The kernel already supports it, so add the support
to iproute2 as well.
    
Cc: Stephen Hemminger <stephen@networkplumber.org>
Signed-off-by: Cong Wang <amwang@redhat.com>

---
 include/linux/if_link.h |    2 +
 ip/iplink_vxlan.c       |   69 ++++++++++++++++++++++++++++++++++++++--------
 2 files changed, 59 insertions(+), 12 deletions(-)

diff --git a/include/linux/if_link.h b/include/linux/if_link.h
index d07aeca..0c37561 100644
--- a/include/linux/if_link.h
+++ b/include/linux/if_link.h
@@ -311,6 +311,8 @@ enum {
 	IFLA_VXLAN_L2MISS,
 	IFLA_VXLAN_L3MISS,
 	IFLA_VXLAN_PORT,	/* destination port */
+	IFLA_VXLAN_GROUP6,
+	IFLA_VXLAN_LOCAL6,
 	__IFLA_VXLAN_MAX
 };
 #define IFLA_VXLAN_MAX	(__IFLA_VXLAN_MAX - 1)
diff --git a/ip/iplink_vxlan.c b/ip/iplink_vxlan.c
index 4304b0d..12e1c74 100644
--- a/ip/iplink_vxlan.c
+++ b/ip/iplink_vxlan.c
@@ -43,6 +43,9 @@ static int vxlan_parse_opt(struct link_util *lu, int argc, char **argv,
 	__u32 saddr = 0;
 	__u32 gaddr = 0;
 	__u32 daddr = 0;
+	struct in6_addr saddr6 = IN6ADDR_ANY_INIT;
+	struct in6_addr gaddr6 = IN6ADDR_ANY_INIT;
+	struct in6_addr daddr6 = IN6ADDR_ANY_INIT;
 	unsigned link = 0;
 	__u8 tos = 0;
 	__u8 ttl = 0;
@@ -66,21 +69,36 @@ static int vxlan_parse_opt(struct link_util *lu, int argc, char **argv,
 			vni_set = 1;
 		} else if (!matches(*argv, "group")) {
 			NEXT_ARG();
-			gaddr = get_addr32(*argv);
-
-			if (!IN_MULTICAST(ntohl(gaddr)))
-				invarg("invalid group address", *argv);
+			if (!inet_pton(AF_INET, *argv, &gaddr)) {
+				if (!inet_pton(AF_INET6, *argv, &gaddr6)) {
+					fprintf(stderr, "Invalid address \"%s\"\n", *argv);
+					return -1;
+				} else if (!IN6_IS_ADDR_MULTICAST(&gaddr6))
+					invarg("invald group address", *argv);
+			} else if (!IN_MULTICAST(ntohl(gaddr)))
+					invarg("invald group address", *argv);
 		} else if (!matches(*argv, "remote")) {
 			NEXT_ARG();
-			daddr = get_addr32(*argv);
-
-			if (IN_MULTICAST(ntohl(daddr)))
-				invarg("invalid remote address", *argv);
+			if (!inet_pton(AF_INET, *argv, &daddr)) {
+				if (!inet_pton(AF_INET6, *argv, &daddr6)) {
+					fprintf(stderr, "Invalid address \"%s\"\n", *argv);
+					return -1;
+				} else if (IN6_IS_ADDR_MULTICAST(&daddr6))
+					invarg("invald remote address", *argv);
+			} else if (IN_MULTICAST(ntohl(daddr)))
+					invarg("invald remote address", *argv);
 		} else if (!matches(*argv, "local")) {
 			NEXT_ARG();
-			if (strcmp(*argv, "any"))
-				saddr = get_addr32(*argv);
-			if (IN_MULTICAST(ntohl(saddr)))
+			if (strcmp(*argv, "any")) {
+				if (!inet_pton(AF_INET, *argv, &saddr)) {
+					if (!inet_pton(AF_INET6, *argv, &saddr6)) {
+						fprintf(stderr, "Invalid address \"%s\"\n", *argv);
+						return -1;
+					}
+				}
+			}
+
+			if (IN_MULTICAST(ntohl(saddr)) || IN6_IS_ADDR_MULTICAST(&saddr6))
 				invarg("invalid local address", *argv);
 		} else if (!matches(*argv, "dev")) {
 			NEXT_ARG();
@@ -167,7 +185,9 @@ static int vxlan_parse_opt(struct link_util *lu, int argc, char **argv,
 		fprintf(stderr, "vxlan: missing virtual network identifier\n");
 		return -1;
 	}
-	if (gaddr && daddr) {
+	if ((gaddr && daddr) ||
+		(memcmp(&gaddr6, &in6addr_any, sizeof(gaddr6)) &&
+		 memcmp(&daddr6, &in6addr_any, sizeof(daddr6)))) {
 		fprintf(stderr, "vxlan: both group and remote cannot be specified\n");
 		return -1;
 	}
@@ -176,8 +196,16 @@ static int vxlan_parse_opt(struct link_util *lu, int argc, char **argv,
 		addattr_l(n, 1024, IFLA_VXLAN_GROUP, &gaddr, 4);
 	else if (daddr)
 		addattr_l(n, 1024, IFLA_VXLAN_GROUP, &daddr, 4);
+	if (memcmp(&gaddr6, &in6addr_any, sizeof(gaddr6)) != 0)
+		addattr_l(n, 1024, IFLA_VXLAN_GROUP6, &gaddr6, sizeof(struct in6_addr));
+	else if (memcmp(&daddr6, &in6addr_any, sizeof(daddr6)) != 0)
+		addattr_l(n, 1024, IFLA_VXLAN_GROUP6, &daddr6, sizeof(struct in6_addr));
+
 	if (saddr)
 		addattr_l(n, 1024, IFLA_VXLAN_LOCAL, &saddr, 4);
+	else if (memcmp(&saddr6, &in6addr_any, sizeof(saddr6)) != 0)
+		addattr_l(n, 1024, IFLA_VXLAN_LOCAL6, &saddr6, sizeof(struct in6_addr));
+
 	if (link)
 		addattr32(n, 1024, IFLA_VXLAN_LINK, link);
 	addattr8(n, 1024, IFLA_VXLAN_TTL, ttl);
@@ -229,6 +257,17 @@ static void vxlan_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
 				fprintf(f, "remote %s ",
 					format_host(AF_INET, 4, &addr, s1, sizeof(s1)));
 		}
+	} else if (tb[IFLA_VXLAN_GROUP6]) {
+		struct in6_addr addr;
+		memcpy(&addr, RTA_DATA(tb[IFLA_VXLAN_GROUP6]), sizeof(struct in6_addr));
+		if (memcmp(&addr, &in6addr_any, sizeof(addr)) != 0) {
+			if (IN6_IS_ADDR_MULTICAST(&addr))
+				fprintf(f, "group %s ",
+					format_host(AF_INET6, sizeof(struct in6_addr), &addr, s1, sizeof(s1)));
+			else
+				fprintf(f, "remote %s ",
+					format_host(AF_INET6, sizeof(struct in6_addr), &addr, s1, sizeof(s1)));
+		}
 	}
 
 	if (tb[IFLA_VXLAN_LOCAL]) {
@@ -236,6 +275,12 @@ static void vxlan_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
 		if (addr)
 			fprintf(f, "local %s ",
 				format_host(AF_INET, 4, &addr, s1, sizeof(s1)));
+	} else if (tb[IFLA_VXLAN_LOCAL6]) {
+		struct in6_addr addr;
+		memcpy(&addr, RTA_DATA(tb[IFLA_VXLAN_LOCAL6]), sizeof(struct in6_addr));
+		if (memcmp(&addr, &in6addr_any, sizeof(addr)) != 0)
+			fprintf(f, "local %s ",
+				format_host(AF_INET6, sizeof(struct in6_addr), &addr, s1, sizeof(s1)));
 	}
 
 	if (tb[IFLA_VXLAN_LINK] &&
-- 
1.7.7.6

^ permalink raw reply related

* Re: [PATCH 1/1] mrp: add periodictimer to allow retries when packets get lost
From: Ward, David - 0663 - MITLL @ 2013-09-21  1:32 UTC (permalink / raw)
  To: David Miller
  Cc: noel@burton-krahn.com, netdev@vger.kernel.org, joe@perches.com
In-Reply-To: <20130920.145903.1454447110808820874.davem@davemloft.net>

[-- Attachment #1: Type: text/plain, Size: 878 bytes --]

Noel, thanks for your patch. This timer was apparently not in the GARP 
standard but added in the MRP standard and I missed it. Looks good to me.

Acked-by: David Ward <david.ward@ll.mit.edu>


On 09/20/2013 02:59 PM, David Miller wrote:
> Re: [PATCH 1/1] mrp: add periodictimer to allow retries when packets 
> get lost
>
> From: Noel Burton-Krahn <noel@burton-krahn.com>
> Date: Wed, 18 Sep 2013 12:24:40 -0700
>
> > MRP doesn't implement the periodictimer in 802.1Q, so it never retries
> > if packets get lost.  I ran into this problem when MRP sent a MVRP
> > JoinIn before the interface was fully up.  The JoinIn was lost, MRP
> > didn't retry, and MVRP registration failed.
> >
> > Tested against Juniper QFabric switches
> >
> > Signed-off-by: Noel Burton-Krahn <noel@burton-krahn.com>
>
> David W., please review this patch.
>
> Thanks.
>



[-- Attachment #2: S/MIME Cryptographic Signature --]
[-- Type: application/pkcs7-signature, Size: 4571 bytes --]

^ permalink raw reply

* Re: [PATCH v4] net/hsr: Add support for the High-availability Seamless Redundancy protocol (HSRv0)
From: Arvid Brodin @ 2013-09-21  1:28 UTC (permalink / raw)
  To: David Miller
  Cc: Arvid Brodin, netdev, shemminger, joe, jboticario, balferreira,
	elias.molina
In-Reply-To: <523CF077.8010607@xdin.com>

On 2013-09-21 03:03, Arvid Brodin wrote:
> On 2013-09-21 02:43, Arvid Brodin wrote:
>> It's weird though, the "len" bug doesn't show up in my practical tests - 
>> scp of 16 MiB file (sha1sum compared afterwards) and ping with default 
>> and 65 KB packets work just fine before and after this change - even
>> between one fixed system and one with the bug remaining. Could it be
>> that none of the network device drivers we use (e1000e and macb) make 
>> use of nonlinear skbs?
> 
> Forget about this, e1000e is running on an architecture with 
> HAVE_EFFICIENT_UNALIGNED_ACCESS, and on macb it does affect things - 
> with the "fix" nothing works. :-| 

... and that is because I have already shortened the packet through the
call to strip_hsr_tag() a few lines above, which calls 
skb_pull(..., HSR_TAGLEN) in turn. So ->len is already correct.

Moving both ->data and ->tail, and all data between them, HSR_TAGLEN bytes
lower, should not be a problem if

a) the space ahead of ->data is vacant (not part of the packet),
b) there is enough headroom,
c) it does not break 32-bit alignment, and
d) there are no references to headers etc in the data being moved.

Right? 


-- 
Arvid Brodin | Consultant (Linux)
XDIN AB | Knarrarnäsgatan 7 | SE-164 40 Kista | Sweden | xdin.com

^ permalink raw reply

* Re: [PATCH v4] net/hsr: Add support for the High-availability Seamless Redundancy protocol (HSRv0)
From: Arvid Brodin @ 2013-09-21  1:03 UTC (permalink / raw)
  To: David Miller
  Cc: Arvid Brodin, netdev, shemminger, joe, jboticario, balferreira,
	elias.molina
In-Reply-To: <523CEBCD.10808@xdin.com>

On 2013-09-21 02:43, Arvid Brodin wrote:
> It's weird though, the "len" bug doesn't show up in my practical tests - 
> scp of 16 MiB file (sha1sum compared afterwards) and ping with default 
> and 65 KB packets work just fine before and after this change - even
> between one fixed system and one with the bug remaining. Could it be
> that none of the network device drivers we use (e1000e and macb) make 
> use of nonlinear skbs?

Forget about this, e1000e is running on an architecture with 
HAVE_EFFICIENT_UNALIGNED_ACCESS, and on macb it does affect things - 
with the "fix" nothing works. :-| 


-- 
Arvid Brodin | Consultant (Linux)
XDIN AB | Knarrarnäsgatan 7 | SE-164 40 Kista | Sweden | xdin.com

^ permalink raw reply

* Re: [PATCH v4] net/hsr: Add support for the High-availability Seamless Redundancy protocol (HSRv0)
From: Arvid Brodin @ 2013-09-21  0:43 UTC (permalink / raw)
  To: David Miller
  Cc: netdev, shemminger, joe, jboticario, balferreira, elias.molina,
	Arvid Brodin
In-Reply-To: <20130920.151017.2125552741552759738.davem@davemloft.net>

On 2013-09-20 21:10, David Miller wrote:
> From: Arvid Brodin <arvid.brodin@xdin.com>
> Date: Thu, 19 Sep 2013 03:11:58 +0200
> 
>> +#if !defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
>> +		/* We need to memmove the whole header to work around
>> +		 * alignment problems caused by the 6-byte HSR tag.
>> +		 */
>> +		memmove(skb_deliver->data - HSR_TAGLEN, skb_deliver->data,
>> +			skb_headlen(skb_deliver));
>> +		skb_deliver->data -= HSR_TAGLEN;
>> +		skb_deliver->tail -= HSR_TAGLEN;
>> +#endif
> 
> You can't do this.
> 
> First of all, you have no idea if subtracting skb->data a given amount
> will underflow the skb buffer start.  You aren't even checking, all
> of the standard skb_*() data adjustment interfaces do.

Isn't it reasonable to assume that skb points to an sk_buff with a
valid Ethernet header, and with skb->data pointing to the end of that
header, at the start of ETH_P_... protocol handlers?


> Secondly, everything after the header is now at the wrong offset from
> the beginning of the packet.
> 
> You will have to memmove() the entire packet if you want to realign
> where it starts.

Are you saying packet data may contain offsets from itself to the mac 
header? Or are you talking about fragments? This being the Ethernet 
protocol handler, e.g. skb->network_header and skb->transport_header 
should not have been set yet.

Anyway, I should do
	skb_deliver->len -= HSR_TAGLEN;
here! (I'm removing 6 bytes after the mac header from the packet, not 
just realigning it.)

Given all this, and looking at e.g. __pskb_pull_tail(), it should be 
correct to memmove() only the linear part of the packet after the removed 
bytes - any fragments will just be appended directly after the end of the 
(shortened) linear part on use?

It's weird though, the "len" bug doesn't show up in my practical tests - 
scp of 16 MiB file (sha1sum compared afterwards) and ping with default 
and 65 KB packets work just fine before and after this change - even
between one fixed system and one with the bug remaining. Could it be
that none of the network device drivers we use (e1000e and macb) make 
use of nonlinear skbs?


-- 
Arvid Brodin | Consultant (Linux)
XDIN AB | Knarrarnäsgatan 7 | SE-164 40 Kista | Sweden | xdin.com

^ permalink raw reply

* Re: [PATCH] sh_eth: call phy_scan_fixups() after PHY reset
From: Sergei Shtylyov @ 2013-09-21  0:39 UTC (permalink / raw)
  To: David Miller, nobuhiro.iwamatsu.yj
  Cc: netdev, linux-sh, laurent.pinchart+renesas
In-Reply-To: <20130917.154446.554384673039269498.davem@davemloft.net>

Hello.

On 09/17/2013 11:44 PM, David Miller wrote:

>> Sometimes the PHY reset that sh_eth_phy_start() does effects the PHY registers
>> registers values of which are vital for the correct functioning of the driver.
>> Unfortunately, the existing PHY platform fixup mechanism doesn't help  here as
>> it only hooks PHY resets done by ioctl() calls. Calling phy_scan_fixups() from
>> the driver helps here. With a proper platform fixup, this fixes NFS timeouts on
>> the SH-Mobile Lager board.

    "And sets the PHY LED pins to the desired mode", I should have added.

>> Signed-off-by: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>

> The PHY layer is designed to naturally already take care of this kind of
> thing.  I think that part of the problem is that you're fighting the
> natural control flow the PHY layer provides.

> When the phy_connect() is performed, what we end up doing is calling
> phy_attach_direct() which invokes the ->probe() method of the driver
> and then afterwards we do phy_init_hw() which takes care of doing
> the fixup calls.

    Yes, I have studied the code paths beforehand.

> So if you really need to do a BMCR reset then run the fixups I'd like
> you to look into making that happen within the provided control
> flow rather than with an exceptional explicit call to run the fixups.

    That could change the behavior of many Ethernet drivers in sometimes 
unpredictable ways I think (due to extended registers the PHYs sometimes have, 
like in this case) if you meant including the PHY reset into phylib control 
flows. Anyway, that would have required more complex patches only good for 
merging at the merge window time while I aimed at a quick fix for a problem at 
hand (which is NFS timeout/slowdown and LED mode mismatch to what was designed 
for the board).
    Some other drivers also do reset the PHYs but usually that's accompanied 
by a loop polling for reset completion, so a naive code like that one on the 
phylib's ioctl() path couldn't have helped if I wanted to hook reset writes in 
the same fashion in phy_write(). In my case reset seems just quick enough for 
the extended PHY register reads/writes to work correctly without polling the 
reset bit first...
    That's why I took an easy way and used already exported phy_scan_fixups() 
to undo what the PHY reset did to some of the PHY's registers. The question is 
why it was exported in the first place? It doesn't seem to be used by anything 
but phylib internally...

> I'm willing to be convinced that this is a better or necessary approach
> but you'll need to explain it to me.

    Well, I didn't write this driver, so I'm probably not the best person to 
be asked about its design (maybe Iwamatsu-san could add something here). I 
don't know about the purpose of the explicit PHY reset in the driver more than 
the accompanying comment says (and it doesn't say much other than that it 
takes the PHY out of power-down). Perhaps we could just painlessly remove it, 
who knows?

> Thanks.

WBR, Sergei


^ permalink raw reply

* Re: [PATCH 1/2] remove all uses of printf's %n
From: Tetsuo Handa @ 2013-09-21  0:28 UTC (permalink / raw)
  To: keescook, jslaby
  Cc: viro, xemul, remi.denis-courmont, linux-kernel, netdev,
	linux-sctp, linux, akpm, dan.carpenter, geert, JBeulich, joe,
	kosaki.motohiro
In-Reply-To: <CAGXu5jLENb+x6b9XOY7-pWMT7GsFgnLr0=A8VNFLkqMi0BX4=w@mail.gmail.com>

Kees Cook wrote:
> >> -                     seq_printf(seq, "%*s\n", 127 - len, "");
> >> +                     seq_pad(seq, '\n');
> >
> > Hmm, seq_pad is unintuitive. I would say it pads the string by '\n'. Of
> > course it does not, but...
> 
> I don't think this is a very serious problem. Currently, the padding
> character is always ' ' for all existing callers, so it only makes
> sense to make the trailing character an argument.

If you want, we can rename seq_pad() to seq_pad_and_putc(). Also we can pass
both the padding character (e.g. ' ') and the trailing character (e.g. '\n')
like seq_pad_and_putc((' ' << 8) | '\n'), though I wonder someone wants to
use '\0', '\t', '\n' etc. as the padding character...

^ permalink raw reply

* [PATCH net-next 6/8] tg3: Appropriately classify interrupts during request_irq
From: Nithin Nayak Sujir @ 2013-09-20 23:47 UTC (permalink / raw)
  To: davem; +Cc: netdev, Nithin Nayak Sujir, Michael Chan
In-Reply-To: <1379720822-6500-1-git-send-email-nsujir@broadcom.com>

Distinguish between tx, rx and txrx interrupts.

Signed-off-by: Nithin Nayak Sujir <nsujir@broadcom.com>
Signed-off-by: Michael Chan <mchan@broadcom.com>
---
 drivers/net/ethernet/broadcom/tg3.c | 13 ++++++++++++-
 1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c
index e56e4f8..b0dd391 100644
--- a/drivers/net/ethernet/broadcom/tg3.c
+++ b/drivers/net/ethernet/broadcom/tg3.c
@@ -11038,7 +11038,18 @@ static int tg3_request_irq(struct tg3 *tp, int irq_num)
 		name = tp->dev->name;
 	else {
 		name = &tnapi->irq_lbl[0];
-		snprintf(name, IFNAMSIZ, "%s-%d", tp->dev->name, irq_num);
+		if (tnapi->tx_buffers && tnapi->rx_rcb)
+			snprintf(name, IFNAMSIZ,
+				 "%s-txrx-%d", tp->dev->name, irq_num);
+		else if (tnapi->tx_buffers)
+			snprintf(name, IFNAMSIZ,
+				 "%s-tx-%d", tp->dev->name, irq_num);
+		else if (tnapi->rx_rcb)
+			snprintf(name, IFNAMSIZ,
+				 "%s-rx-%d", tp->dev->name, irq_num);
+		else
+			snprintf(name, IFNAMSIZ,
+				 "%s-%d", tp->dev->name, irq_num);
 		name[IFNAMSIZ-1] = 0;
 	}
 
-- 
1.8.1.4

^ permalink raw reply related

* [PATCH net-next 1/8] tg3: Add function tg3_phy_shdw_write()
From: Nithin Nayak Sujir @ 2013-09-20 23:46 UTC (permalink / raw)
  To: davem; +Cc: netdev, Nithin Nayak Sujir, Michael Chan
In-Reply-To: <1379720822-6500-1-git-send-email-nsujir@broadcom.com>

For consistency with other register access functions, add shadow
register access function of the type (register/val).

Signed-off-by: Nithin Nayak Sujir <nsujir@broadcom.com>
Signed-off-by: Michael Chan <mchan@broadcom.com>
---
 drivers/net/ethernet/broadcom/tg3.c | 18 ++++++++++--------
 1 file changed, 10 insertions(+), 8 deletions(-)

diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c
index 5701f3d..d2bc391 100644
--- a/drivers/net/ethernet/broadcom/tg3.c
+++ b/drivers/net/ethernet/broadcom/tg3.c
@@ -1326,6 +1326,12 @@ static int tg3_phy_toggle_auxctl_smdsp(struct tg3 *tp, bool enable)
 	return err;
 }
 
+static int tg3_phy_shdw_write(struct tg3 *tp, int reg, u32 val)
+{
+	return tg3_writephy(tp, MII_TG3_MISC_SHDW,
+			    reg | val | MII_TG3_MISC_SHDW_WREN);
+}
+
 static int tg3_bmcr_reset(struct tg3 *tp)
 {
 	u32 phy_control;
@@ -2218,25 +2224,21 @@ static void tg3_phy_toggle_apd(struct tg3 *tp, bool enable)
 		return;
 	}
 
-	reg = MII_TG3_MISC_SHDW_WREN |
-	      MII_TG3_MISC_SHDW_SCR5_SEL |
-	      MII_TG3_MISC_SHDW_SCR5_LPED |
+	reg = MII_TG3_MISC_SHDW_SCR5_LPED |
 	      MII_TG3_MISC_SHDW_SCR5_DLPTLM |
 	      MII_TG3_MISC_SHDW_SCR5_SDTL |
 	      MII_TG3_MISC_SHDW_SCR5_C125OE;
 	if (tg3_asic_rev(tp) != ASIC_REV_5784 || !enable)
 		reg |= MII_TG3_MISC_SHDW_SCR5_DLLAPD;
 
-	tg3_writephy(tp, MII_TG3_MISC_SHDW, reg);
+	tg3_phy_shdw_write(tp, MII_TG3_MISC_SHDW_SCR5_SEL, reg);
 
 
-	reg = MII_TG3_MISC_SHDW_WREN |
-	      MII_TG3_MISC_SHDW_APD_SEL |
-	      MII_TG3_MISC_SHDW_APD_WKTM_84MS;
+	reg = MII_TG3_MISC_SHDW_APD_WKTM_84MS;
 	if (enable)
 		reg |= MII_TG3_MISC_SHDW_APD_ENABLE;
 
-	tg3_writephy(tp, MII_TG3_MISC_SHDW, reg);
+	tg3_phy_shdw_write(tp, MII_TG3_MISC_SHDW_APD_SEL, reg);
 }
 
 static void tg3_phy_toggle_automdix(struct tg3 *tp, bool enable)
-- 
1.8.1.4

^ permalink raw reply related

* [PATCH net-next 0/8] tg3: Misc cleanups and fixes.
From: Nithin Nayak Sujir @ 2013-09-20 23:46 UTC (permalink / raw)
  To: davem; +Cc: netdev, Nithin Nayak Sujir

Nithin Nayak Sujir (8):
  tg3: Add function tg3_phy_shdw_write()
  tg3: Add support for new 577xx device ids
  tg3: LED in shared mode does not blink during traffic
  tg3: Remove if 0'd code
  tg3: Remove redundant if check
  tg3: Appropriately classify interrupts during request_irq
  tg3: Remove unnecessary spinlock
  tg3: Update version to 3.134

 drivers/net/ethernet/broadcom/tg3.c | 81 ++++++++++++++++++++-----------------
 drivers/net/ethernet/broadcom/tg3.h |  3 ++
 2 files changed, 47 insertions(+), 37 deletions(-)

-- 
1.8.1.4

^ 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