Netdev List
 help / color / mirror / Atom feed
* [PATCH net-next v2 05/10] net: dsa: debugfs: add port regs
From: Vivien Didelot @ 2017-08-28 19:17 UTC (permalink / raw)
  To: netdev
  Cc: linux-kernel, kernel, David S. Miller, Florian Fainelli,
	Andrew Lunn, Egil Hjelmeland, John Crispin, Woojung Huh,
	Sean Wang, Nikita Yushchenko, Chris Healy, Vivien Didelot
In-Reply-To: <20170828191748.19492-1-vivien.didelot@savoirfairelinux.com>

Add a debug filesystem "regs" entry to query a port's hardware registers
through the .get_regs_len and .get_regs_len switch operations.

This is very convenient because it allows one to dump the registers of
DSA links, which are not exposed to userspace.

Here are the registers of a zii-rev-b CPU and DSA ports:

    # pr -mt switch0/port{5,6}/regs
     0: 4e07			     0: 4d04
     1: 403e			     1: 003d
     2: 0000			     2: 0000
     3: 3521			     3: 3521
     4: 0533			     4: 373f
     5: 8000			     5: 0000
     6: 005f			     6: 003f
     7: 002a			     7: 002a
     8: 2080			     8: 2080
     9: 0001			     9: 0001
    10: 0000			    10: 0000
    11: 0020			    11: 0000
    12: 0000			    12: 0000
    13: 0000			    13: 0000
    14: 0000			    14: 0000
    15: 9100			    15: dada
    16: 0000			    16: 0000
    17: 0000			    17: 0000
    18: 0000			    18: 0000
    19: 0000			    19: 00d8
    20: 0000			    20: 0000
    21: 0000			    21: 0000
    22: 0022			    22: 0000
    23: 0000			    23: 0000
    24: 3210			    24: 3210
    25: 7654			    25: 7654
    26: 0000			    26: 0000
    27: 8000			    27: 8000
    28: 0000			    28: 0000
    29: 0000			    29: 0000
    30: 0000			    30: 0000
    31: 0000			    31: 0000

Signed-off-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
---
 net/dsa/debugfs.c | 39 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 39 insertions(+)

diff --git a/net/dsa/debugfs.c b/net/dsa/debugfs.c
index 997bbc8eb502..7b299c9d9892 100644
--- a/net/dsa/debugfs.c
+++ b/net/dsa/debugfs.c
@@ -109,6 +109,40 @@ static int dsa_debugfs_create_file(struct dsa_switch *ds, struct dentry *dir,
 	return 0;
 }
 
+static void dsa_debugfs_regs_read_count(struct dsa_switch *ds, int id,
+					struct seq_file *seq, int count)
+{
+	u16 data[count * ETH_GSTRING_LEN];
+	struct ethtool_regs regs;
+	int i;
+
+	ds->ops->get_regs(ds, id, &regs, data);
+
+	for (i = 0; i < count / 2; i++)
+		seq_printf(seq, "%2d: %04x\n", i, data[i]);
+}
+
+static int dsa_debugfs_regs_read(struct dsa_switch *ds, int id,
+				 struct seq_file *seq)
+{
+	int count;
+
+	if (!ds->ops->get_regs_len || !ds->ops->get_regs)
+		return -EOPNOTSUPP;
+
+	count = ds->ops->get_regs_len(ds, id);
+	if (count < 0)
+		return count;
+
+	dsa_debugfs_regs_read_count(ds, id, seq, count);
+
+	return 0;
+}
+
+static const struct dsa_debugfs_ops dsa_debugfs_regs_ops = {
+	.read = dsa_debugfs_regs_read,
+};
+
 static void dsa_debugfs_stats_read_count(struct dsa_switch *ds, int id,
 					 struct seq_file *seq, int count)
 {
@@ -188,6 +222,11 @@ static int dsa_debugfs_create_port(struct dsa_switch *ds, int port)
 	if (IS_ERR_OR_NULL(dir))
 		return -EFAULT;
 
+	err = dsa_debugfs_create_file(ds, dir, "regs", port,
+				      &dsa_debugfs_regs_ops);
+	if (err)
+		return err;
+
 	err = dsa_debugfs_create_file(ds, dir, "stats", port,
 				      &dsa_debugfs_stats_ops);
 	if (err)
-- 
2.14.1

^ permalink raw reply related

* [PATCH net-next v2 04/10] net: dsa: debugfs: add port stats
From: Vivien Didelot @ 2017-08-28 19:17 UTC (permalink / raw)
  To: netdev
  Cc: linux-kernel, kernel, David S. Miller, Florian Fainelli,
	Andrew Lunn, Egil Hjelmeland, John Crispin, Woojung Huh,
	Sean Wang, Nikita Yushchenko, Chris Healy, Vivien Didelot
In-Reply-To: <20170828191748.19492-1-vivien.didelot@savoirfairelinux.com>

Add a debug filesystem "stats" entry to query a port's hardware
statistics through the DSA switch .get_sset_count, .get_strings and
.get_ethtool_stats operations.

This allows one to get statistics about DSA links interconnecting
switches, which is very convenient because this kind of port is not
exposed to userspace.

Here are the stats of a zii-rev-b DSA and CPU ports:

    # pr -mt switch0/port{5,6}/stats
    in_good_octets      : 0             in_good_octets      : 13824
    in_bad_octets       : 0             in_bad_octets       : 0
    in_unicast          : 0             in_unicast          : 0
    in_broadcasts       : 0             in_broadcasts       : 216
    in_multicasts       : 0             in_multicasts       : 0
    in_pause            : 0             in_pause            : 0
    in_undersize        : 0             in_undersize        : 0
    in_fragments        : 0             in_fragments        : 0
    in_oversize         : 0             in_oversize         : 0
    in_jabber           : 0             in_jabber           : 0
    in_rx_error         : 0             in_rx_error         : 0
    in_fcs_error        : 0             in_fcs_error        : 0
    out_octets          : 9216          out_octets          : 0
    out_unicast         : 0             out_unicast         : 0
    out_broadcasts      : 144           out_broadcasts      : 0
    out_multicasts      : 0             out_multicasts      : 0
    out_pause           : 0             out_pause           : 0
    excessive           : 0             excessive           : 0
    collisions          : 0             collisions          : 0
    deferred            : 0             deferred            : 0
    single              : 0             single              : 0
    multiple            : 0             multiple            : 0
    out_fcs_error       : 0             out_fcs_error       : 0
    late                : 0             late                : 0
    hist_64bytes        : 0             hist_64bytes        : 0
    hist_65_127bytes    : 0             hist_65_127bytes    : 0
    hist_128_255bytes   : 0             hist_128_255bytes   : 0
    hist_256_511bytes   : 0             hist_256_511bytes   : 0
    hist_512_1023bytes  : 0             hist_512_1023bytes  : 0
    hist_1024_max_bytes : 0             hist_1024_max_bytes : 0
    sw_in_discards      : 0             sw_in_discards      : 0
    sw_in_filtered      : 0             sw_in_filtered      : 0
    sw_out_filtered     : 0             sw_out_filtered     : 216

Signed-off-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
---
 net/dsa/debugfs.c | 43 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 43 insertions(+)

diff --git a/net/dsa/debugfs.c b/net/dsa/debugfs.c
index 8a0e4311ff8c..997bbc8eb502 100644
--- a/net/dsa/debugfs.c
+++ b/net/dsa/debugfs.c
@@ -109,6 +109,43 @@ static int dsa_debugfs_create_file(struct dsa_switch *ds, struct dentry *dir,
 	return 0;
 }
 
+static void dsa_debugfs_stats_read_count(struct dsa_switch *ds, int id,
+					 struct seq_file *seq, int count)
+{
+	u8 strings[count * ETH_GSTRING_LEN];
+	u64 stats[count];
+	int i;
+
+	ds->ops->get_strings(ds, id, strings);
+	ds->ops->get_ethtool_stats(ds, id, stats);
+
+	for (i = 0; i < count; i++)
+		seq_printf(seq, "%-20s: %lld\n", strings + i * ETH_GSTRING_LEN,
+			   stats[i]);
+}
+
+static int dsa_debugfs_stats_read(struct dsa_switch *ds, int id,
+				  struct seq_file *seq)
+{
+	int count;
+
+	if (!ds->ops->get_sset_count || !ds->ops->get_strings ||
+	    !ds->ops->get_ethtool_stats)
+		return -EOPNOTSUPP;
+
+	count = ds->ops->get_sset_count(ds);
+	if (count < 0)
+		return count;
+
+	dsa_debugfs_stats_read_count(ds, id, seq, count);
+
+	return 0;
+}
+
+static const struct dsa_debugfs_ops dsa_debugfs_stats_ops = {
+	.read = dsa_debugfs_stats_read,
+};
+
 static int dsa_debugfs_tag_protocol_read(struct dsa_switch *ds, int id,
 					 struct seq_file *seq)
 {
@@ -143,6 +180,7 @@ static int dsa_debugfs_create_port(struct dsa_switch *ds, int port)
 {
 	struct dentry *dir;
 	char name[32];
+	int err;
 
 	snprintf(name, sizeof(name), DSA_PORT_FMT, port);
 
@@ -150,6 +188,11 @@ static int dsa_debugfs_create_port(struct dsa_switch *ds, int port)
 	if (IS_ERR_OR_NULL(dir))
 		return -EFAULT;
 
+	err = dsa_debugfs_create_file(ds, dir, "stats", port,
+				      &dsa_debugfs_stats_ops);
+	if (err)
+		return err;
+
 	return 0;
 }
 
-- 
2.14.1

^ permalink raw reply related

* [PATCH net-next v2 02/10] net: dsa: debugfs: add tree
From: Vivien Didelot @ 2017-08-28 19:17 UTC (permalink / raw)
  To: netdev
  Cc: linux-kernel, kernel, David S. Miller, Florian Fainelli,
	Andrew Lunn, Egil Hjelmeland, John Crispin, Woojung Huh,
	Sean Wang, Nikita Yushchenko, Chris Healy, Vivien Didelot
In-Reply-To: <20170828191748.19492-1-vivien.didelot@savoirfairelinux.com>

This commit adds the boiler plate to create a DSA related debug
filesystem entry as well as a "tree" file, containing the tree index.

    # cat switch1/tree
    0

Signed-off-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
---
 net/dsa/debugfs.c | 107 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 107 insertions(+)

diff --git a/net/dsa/debugfs.c b/net/dsa/debugfs.c
index b6b5e5c97389..54e97e05a9d7 100644
--- a/net/dsa/debugfs.c
+++ b/net/dsa/debugfs.c
@@ -10,6 +10,7 @@
  */
 
 #include <linux/debugfs.h>
+#include <linux/seq_file.h>
 
 #include "dsa_priv.h"
 
@@ -19,6 +20,107 @@
 /* DSA module debugfs directory */
 static struct dentry *dsa_debugfs_dir;
 
+struct dsa_debugfs_ops {
+	int (*read)(struct dsa_switch *ds, int id, struct seq_file *seq);
+	int (*write)(struct dsa_switch *ds, int id, char *buf);
+};
+
+struct dsa_debugfs_priv {
+	const struct dsa_debugfs_ops *ops;
+	struct dsa_switch *ds;
+	int id;
+};
+
+static int dsa_debugfs_show(struct seq_file *seq, void *p)
+{
+	struct dsa_debugfs_priv *priv = seq->private;
+	struct dsa_switch *ds = priv->ds;
+
+	/* Somehow file mode is bypassed... Double check here */
+	if (!priv->ops->read)
+		return -EOPNOTSUPP;
+
+	return priv->ops->read(ds, priv->id, seq);
+}
+
+static ssize_t dsa_debugfs_write(struct file *file, const char __user *user_buf,
+				 size_t count, loff_t *ppos)
+{
+	struct seq_file *seq = file->private_data;
+	struct dsa_debugfs_priv *priv = seq->private;
+	struct dsa_switch *ds = priv->ds;
+	char buf[count + 1];
+	int err;
+
+	/* Somehow file mode is bypassed... Double check here */
+	if (!priv->ops->write)
+		return -EOPNOTSUPP;
+
+	if (copy_from_user(buf, user_buf, count))
+		return -EFAULT;
+
+	buf[count] = '\0';
+
+	err = priv->ops->write(ds, priv->id, buf);
+
+	return err ? err : count;
+}
+
+static int dsa_debugfs_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, dsa_debugfs_show, inode->i_private);
+}
+
+static const struct file_operations dsa_debugfs_fops = {
+	.open = dsa_debugfs_open,
+	.read = seq_read,
+	.write = dsa_debugfs_write,
+	.llseek = no_llseek,
+	.release = single_release,
+	.owner = THIS_MODULE,
+};
+
+static int dsa_debugfs_create_file(struct dsa_switch *ds, struct dentry *dir,
+				   char *name, int id,
+				   const struct dsa_debugfs_ops *ops)
+{
+	struct dsa_debugfs_priv *priv;
+	struct dentry *entry;
+	umode_t mode;
+
+	priv = devm_kzalloc(ds->dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	priv->ops = ops;
+	priv->ds = ds;
+	priv->id = id;
+
+	mode = 0;
+	if (ops->read)
+		mode |= 0444;
+	if (ops->write)
+		mode |= 0200;
+
+	entry = debugfs_create_file(name, mode, dir, priv, &dsa_debugfs_fops);
+	if (IS_ERR_OR_NULL(entry))
+		return -EFAULT;
+
+	return 0;
+}
+
+static int dsa_debugfs_tree_read(struct dsa_switch *ds, int id,
+				 struct seq_file *seq)
+{
+	seq_printf(seq, "%d\n", ds->dst->tree);
+
+	return 0;
+}
+
+static const struct dsa_debugfs_ops dsa_debugfs_tree_ops = {
+	.read = dsa_debugfs_tree_read,
+};
+
 static int dsa_debugfs_create_port(struct dsa_switch *ds, int port)
 {
 	struct dentry *dir;
@@ -48,6 +150,11 @@ static int dsa_debugfs_create_switch(struct dsa_switch *ds)
 	if (IS_ERR_OR_NULL(ds->debugfs_dir))
 		return -EFAULT;
 
+	err = dsa_debugfs_create_file(ds, ds->debugfs_dir, "tree", -1,
+				      &dsa_debugfs_tree_ops);
+	if (err)
+		return err;
+
 	for (i = 0; i < ds->num_ports; i++) {
 		if (ds->enabled_port_mask & BIT(i)) {
 			err = dsa_debugfs_create_port(ds, i);
-- 
2.14.1

^ permalink raw reply related

* [PATCH net-next v2 01/10] net: dsa: add debugfs interface
From: Vivien Didelot @ 2017-08-28 19:17 UTC (permalink / raw)
  To: netdev
  Cc: linux-kernel, kernel, David S. Miller, Florian Fainelli,
	Andrew Lunn, Egil Hjelmeland, John Crispin, Woojung Huh,
	Sean Wang, Nikita Yushchenko, Chris Healy, Vivien Didelot
In-Reply-To: <20170828191748.19492-1-vivien.didelot@savoirfairelinux.com>

This commit adds a DEBUG_FS dependent DSA core file creating a generic
debug filesystem interface for the DSA switch devices.

The interface can be mounted with:

    # mount -t debugfs none /sys/kernel/debug

The dsa directory contains one directory per switch chip:

    # cd /sys/kernel/debug/dsa/
    # ls
    switch0  switch1 switch2

Each chip directory contains one directory per port:

    # ls -l switch0/
    drwxr-xr-x 2 root root 0 Jan  1 00:00 port0
    drwxr-xr-x 2 root root 0 Jan  1 00:00 port1
    drwxr-xr-x 2 root root 0 Jan  1 00:00 port2
    drwxr-xr-x 2 root root 0 Jan  1 00:00 port5
    drwxr-xr-x 2 root root 0 Jan  1 00:00 port6

Future patches will add entry files to these directories.

Signed-off-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
---
 include/net/dsa.h  |   7 ++++
 net/dsa/Kconfig    |  14 +++++++
 net/dsa/Makefile   |   1 +
 net/dsa/debugfs.c  | 118 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 net/dsa/dsa.c      |   3 ++
 net/dsa/dsa2.c     |   4 ++
 net/dsa/dsa_priv.h |  13 ++++++
 net/dsa/legacy.c   |   4 ++
 8 files changed, 164 insertions(+)
 create mode 100644 net/dsa/debugfs.c

diff --git a/include/net/dsa.h b/include/net/dsa.h
index 398ca8d70ccd..7341178319f5 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -210,6 +210,13 @@ struct dsa_switch {
 	 */
 	void *priv;
 
+#ifdef CONFIG_NET_DSA_DEBUGFS
+	/*
+	 * Debugfs interface.
+	 */
+	struct dentry *debugfs_dir;
+#endif
+
 	/*
 	 * Configuration data for this switch.
 	 */
diff --git a/net/dsa/Kconfig b/net/dsa/Kconfig
index cc5f8f971689..0f05a1e59dd2 100644
--- a/net/dsa/Kconfig
+++ b/net/dsa/Kconfig
@@ -15,6 +15,20 @@ config NET_DSA
 
 if NET_DSA
 
+config NET_DSA_DEBUGFS
+	bool "Distributed Switch Architecture debugfs interface"
+	depends on DEBUG_FS
+	---help---
+	  Enable creation of debugfs files for the DSA core.
+
+	  These debugfs files provide per-switch information, such as the tag
+	  protocol in use and ports connectivity. They also allow querying the
+	  hardware directly through the switch operations for debugging instead
+	  of going through the bridge, switchdev and DSA layers.
+
+	  This is also a way to inspect the stats and FDB, MDB or VLAN entries
+	  of CPU and DSA links, since they are not exposed to userspace.
+
 # tagging formats
 config NET_DSA_TAG_BRCM
 	bool
diff --git a/net/dsa/Makefile b/net/dsa/Makefile
index fcce25da937c..7f60c6dfaffb 100644
--- a/net/dsa/Makefile
+++ b/net/dsa/Makefile
@@ -1,6 +1,7 @@
 # the core
 obj-$(CONFIG_NET_DSA) += dsa_core.o
 dsa_core-y += dsa.o dsa2.o legacy.o port.o slave.o switch.o
+dsa_core-$(CONFIG_NET_DSA_DEBUGFS) += debugfs.o
 
 # tagging formats
 dsa_core-$(CONFIG_NET_DSA_TAG_BRCM) += tag_brcm.o
diff --git a/net/dsa/debugfs.c b/net/dsa/debugfs.c
new file mode 100644
index 000000000000..b6b5e5c97389
--- /dev/null
+++ b/net/dsa/debugfs.c
@@ -0,0 +1,118 @@
+/*
+ * net/dsa/debugfs.c - DSA debugfs interface
+ * Copyright (c) 2017 Savoir-faire Linux, Inc.
+ *	Vivien Didelot <vivien.didelot@savoirfairelinux.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/debugfs.h>
+
+#include "dsa_priv.h"
+
+#define DSA_SWITCH_FMT	"switch%d"
+#define DSA_PORT_FMT	"port%d"
+
+/* DSA module debugfs directory */
+static struct dentry *dsa_debugfs_dir;
+
+static int dsa_debugfs_create_port(struct dsa_switch *ds, int port)
+{
+	struct dentry *dir;
+	char name[32];
+
+	snprintf(name, sizeof(name), DSA_PORT_FMT, port);
+
+	dir = debugfs_create_dir(name, ds->debugfs_dir);
+	if (IS_ERR_OR_NULL(dir))
+		return -EFAULT;
+
+	return 0;
+}
+
+static int dsa_debugfs_create_switch(struct dsa_switch *ds)
+{
+	char name[32];
+	int i, err;
+
+	/* skip if there is no debugfs support */
+	if (!dsa_debugfs_dir)
+		return 0;
+
+	snprintf(name, sizeof(name), DSA_SWITCH_FMT, ds->index);
+
+	ds->debugfs_dir = debugfs_create_dir(name, dsa_debugfs_dir);
+	if (IS_ERR_OR_NULL(ds->debugfs_dir))
+		return -EFAULT;
+
+	for (i = 0; i < ds->num_ports; i++) {
+		if (ds->enabled_port_mask & BIT(i)) {
+			err = dsa_debugfs_create_port(ds, i);
+			if (err)
+				return err;
+		}
+	}
+
+	return 0;
+}
+
+static void dsa_debugfs_destroy_switch(struct dsa_switch *ds)
+{
+	/* handles NULL */
+	debugfs_remove_recursive(ds->debugfs_dir);
+}
+
+void dsa_debugfs_create_tree(struct dsa_switch_tree *dst)
+{
+	struct dsa_switch *ds;
+	int i, err;
+
+	for (i = 0; i < DSA_MAX_SWITCHES; i++) {
+		ds = dst->ds[i];
+		if (!ds)
+			continue;
+
+		err = dsa_debugfs_create_switch(ds);
+		if (err) {
+			pr_warn("DSA: failed to create debugfs interface for switch %d (%d)\n",
+				ds->index, err);
+			dsa_debugfs_destroy_tree(dst);
+			break;
+		}
+	}
+}
+
+void dsa_debugfs_destroy_tree(struct dsa_switch_tree *dst)
+{
+	struct dsa_switch *ds;
+	int i;
+
+	for (i = 0; i < DSA_MAX_SWITCHES; i++) {
+		ds = dst->ds[i];
+		if (!ds)
+			continue;
+
+		dsa_debugfs_destroy_switch(ds);
+	}
+}
+
+void dsa_debugfs_create_module(void)
+{
+	dsa_debugfs_dir = debugfs_create_dir("dsa", NULL);
+	if (IS_ERR(dsa_debugfs_dir)) {
+		pr_warn("DSA: failed to create debugfs interface\n");
+		dsa_debugfs_dir = NULL;
+	}
+
+	if (dsa_debugfs_dir)
+		pr_info("DSA: debugfs interface created\n");
+}
+
+void dsa_debugfs_destroy_module(void)
+{
+	/* handles NULL */
+	debugfs_remove_recursive(dsa_debugfs_dir);
+}
diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c
index 03c58b0eb082..b23f1be50c71 100644
--- a/net/dsa/dsa.c
+++ b/net/dsa/dsa.c
@@ -308,12 +308,15 @@ static int __init dsa_init_module(void)
 
 	dev_add_pack(&dsa_pack_type);
 
+	dsa_debugfs_create_module();
+
 	return 0;
 }
 module_init(dsa_init_module);
 
 static void __exit dsa_cleanup_module(void)
 {
+	dsa_debugfs_destroy_module();
 	dsa_slave_unregister_notifier();
 	dev_remove_pack(&dsa_pack_type);
 	dsa_legacy_unregister();
diff --git a/net/dsa/dsa2.c b/net/dsa/dsa2.c
index cceaa4dd9f53..5912618ad63d 100644
--- a/net/dsa/dsa2.c
+++ b/net/dsa/dsa2.c
@@ -447,6 +447,8 @@ static int dsa_dst_apply(struct dsa_switch_tree *dst)
 	dst->cpu_dp->netdev->dsa_ptr = dst;
 	dst->applied = true;
 
+	dsa_debugfs_create_tree(dst);
+
 	return 0;
 }
 
@@ -458,6 +460,8 @@ static void dsa_dst_unapply(struct dsa_switch_tree *dst)
 	if (!dst->applied)
 		return;
 
+	dsa_debugfs_destroy_tree(dst);
+
 	dst->cpu_dp->netdev->dsa_ptr = NULL;
 
 	/* If we used a tagging format that doesn't have an ethertype
diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h
index 9c3eeb72462d..84ca3a50a58b 100644
--- a/net/dsa/dsa_priv.h
+++ b/net/dsa/dsa_priv.h
@@ -93,6 +93,19 @@ struct dsa_slave_priv {
 	struct list_head	mall_tc_list;
 };
 
+/* debugfs.c */
+#ifdef CONFIG_NET_DSA_DEBUGFS
+void dsa_debugfs_create_module(void);
+void dsa_debugfs_destroy_module(void);
+void dsa_debugfs_create_tree(struct dsa_switch_tree *dst);
+void dsa_debugfs_destroy_tree(struct dsa_switch_tree *dst);
+#else
+static inline void dsa_debugfs_create_module(void) { }
+static inline void dsa_debugfs_destroy_module(void) { }
+static inline void dsa_debugfs_create_tree(struct dsa_switch_tree *dst) { }
+static inline void dsa_debugfs_destroy_tree(struct dsa_switch_tree *dst) { }
+#endif
+
 /* dsa.c */
 int dsa_cpu_dsa_setup(struct dsa_port *port);
 void dsa_cpu_dsa_destroy(struct dsa_port *dport);
diff --git a/net/dsa/legacy.c b/net/dsa/legacy.c
index 91e6f7981d39..8aa3de540552 100644
--- a/net/dsa/legacy.c
+++ b/net/dsa/legacy.c
@@ -606,6 +606,8 @@ static int dsa_setup_dst(struct dsa_switch_tree *dst, struct net_device *dev,
 	wmb();
 	dev->dsa_ptr = dst;
 
+	dsa_debugfs_create_tree(dst);
+
 	return 0;
 }
 
@@ -671,6 +673,8 @@ static void dsa_remove_dst(struct dsa_switch_tree *dst)
 {
 	int i;
 
+	dsa_debugfs_destroy_tree(dst);
+
 	dst->cpu_dp->netdev->dsa_ptr = NULL;
 
 	/* If we used a tagging format that doesn't have an ethertype
-- 
2.14.1

^ permalink raw reply related

* [PATCH net-next v2 00/10] net: dsa: add generic debugfs interface
From: Vivien Didelot @ 2017-08-28 19:17 UTC (permalink / raw)
  To: netdev
  Cc: linux-kernel, kernel, David S. Miller, Florian Fainelli,
	Andrew Lunn, Egil Hjelmeland, John Crispin, Woojung Huh,
	Sean Wang, Nikita Yushchenko, Chris Healy, Vivien Didelot

This patch series adds a generic debugfs interface for the DSA
framework, so that all switch devices benefit from it, e.g. Marvell,
Broadcom, Microchip or any other DSA driver.

This is really convenient for debugging, especially CPU ports and DSA
links which are not exposed to userspace as net device. This interface
is currently the only way to easily inspect the hardware for such ports.

With the patch series, any switch device user is able to query the
hardware for the supported tagging protocol, the ports stats and
registers, as well as their FDB, MDB and VLAN entries.

This support is only compiled if CONFIG_DEBUG_FS is enabled. Below is
and example of usage of this interface on a multi-chip switch fabric:

    # mount -t debugfs none /sys/kernel/debug
    # cd /sys/kernel/debug/dsa/
    # ls
    switch0  switch1 switch2
    # ls -l switch0/
    drwxr-xr-x 2 root root 0 Jan  1 00:00 port0
    drwxr-xr-x 2 root root 0 Jan  1 00:00 port1
    drwxr-xr-x 2 root root 0 Jan  1 00:00 port2
    drwxr-xr-x 2 root root 0 Jan  1 00:00 port5
    drwxr-xr-x 2 root root 0 Jan  1 00:00 port6
    -r--r--r-- 1 root root 0 Jan  1 00:00 tag_protocol
    -r--r--r-- 1 root root 0 Jan  1 00:00 tree
    # ls -l switch0/port6
    -r--r--r-- 1 root root 0 Jan  1 00:00 fdb
    -r--r--r-- 1 root root 0 Jan  1 00:00 mdb
    -r--r--r-- 1 root root 0 Jan  1 00:00 regs
    -r--r--r-- 1 root root 0 Jan  1 00:00 stats
    -r--r--r-- 1 root root 0 Jan  1 00:00 vlan
    # cat switch0/port2/vlan
    vid 42  untagged  pvid
    # cat switch0/port1/fdb
    vid 0  12:34:56:78:90:ab  unicast  static
    # pr -mt switch0/port{5,6}/stats
    in_good_octets      : 0             in_good_octets      : 13824
    in_bad_octets       : 0             in_bad_octets       : 0
    in_unicast          : 0             in_unicast          : 0
    in_broadcasts       : 0             in_broadcasts       : 216
    in_multicasts       : 0             in_multicasts       : 0
    in_pause            : 0             in_pause            : 0
    in_undersize        : 0             in_undersize        : 0
    ...
    # pr -mt switch0/port{5,6}/regs
     0: 4e07			     0: 4d04
     1: 403e			     1: 003d
     2: 0000			     2: 0000
     3: 3521			     3: 3521
     4: 0533			     4: 373f
     5: 8000			     5: 0000
     6: 005f			     6: 003f
     7: 002a			     7: 002a
    ...

where switch0 port5 and port6 are CPU and DSA ports of a ZII Rev B.

Changes in v2:
  - KISS, drop the WARN_ON if !dst->applied
  - use ds->enabled_port_mask instead of OF nodes
  - add a tag protocol to string helper
  - use %pM to print MAC addresses
  - explicit "tagged" VLANs

Vivien Didelot (10):
  net: dsa: add debugfs interface
  net: dsa: debugfs: add tree
  net: dsa: debugfs: add tag_protocol
  net: dsa: debugfs: add port stats
  net: dsa: debugfs: add port regs
  net: dsa: debugfs: add port fdb
  net: dsa: restore mdb dump
  net: dsa: debugfs: add port mdb
  net: dsa: restore VLAN dump
  net: dsa: debugfs: add port vlan

 drivers/net/dsa/b53/b53_common.c       |  41 ++++
 drivers/net/dsa/b53/b53_priv.h         |   2 +
 drivers/net/dsa/bcm_sf2.c              |   1 +
 drivers/net/dsa/dsa_loop.c             |  38 +++
 drivers/net/dsa/microchip/ksz_common.c |  41 ++++
 drivers/net/dsa/mv88e6xxx/chip.c       |  82 ++++++-
 include/net/dsa.h                      |  41 ++++
 net/dsa/Kconfig                        |  14 ++
 net/dsa/Makefile                       |   1 +
 net/dsa/debugfs.c                      | 409 +++++++++++++++++++++++++++++++++
 net/dsa/dsa.c                          |   3 +
 net/dsa/dsa2.c                         |   4 +
 net/dsa/dsa_priv.h                     |  13 ++
 net/dsa/legacy.c                       |   4 +
 14 files changed, 686 insertions(+), 8 deletions(-)
 create mode 100644 net/dsa/debugfs.c

-- 
2.14.1

^ permalink raw reply

* Re: [PATCH iproute2 net-next 1/2] iproute: add support for seg6 l2encap mode
From: David Lebrun @ 2017-08-28 19:11 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: netdev
In-Reply-To: <20170828120724.53904cbf@xeon-e3>


[-- Attachment #1.1: Type: text/plain, Size: 301 bytes --]

On 08/28/2017 08:07 PM, Stephen Hemminger wrote:
> Since these values probably will grow over time, it would make
> sense to have this a name/value table.

I wasn't sure if it was worth it for 3 values. I do not foresee a large
growth either, but I will send a v2 will a table anyway

David


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

^ permalink raw reply

* [PATCH iproute2 4/4] man: tc-ife: add default type note
From: Alexander Aring @ 2017-08-28 19:07 UTC (permalink / raw)
  To: jhs; +Cc: yotamg, xiyou.wangcong, jiri, netdev, Alexander Aring
In-Reply-To: <20170828190738.26829-1-aring@mojatatu.com>

This patch updates the tc-ife man page that the default IFE ethertype
will be used if it's not specified.

Signed-off-by: Alexander Aring <aring@mojatatu.com>
---
 man/man8/tc-ife.8 | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/man/man8/tc-ife.8 b/man/man8/tc-ife.8
index 3a42d51b..fd2df6c3 100644
--- a/man/man8/tc-ife.8
+++ b/man/man8/tc-ife.8
@@ -82,7 +82,7 @@ is required only when
 Optional six byte destination or source MAC address to encode.
 .TP
 .BI type " TYPE"
-Optional 16-bit ethertype to encode.
+Optional 16-bit ethertype to encode. If not specified value of 0xED3E will be used.
 .TP
 .BI CONTROL
 Action to take following an encode/decode.
-- 
2.11.0

^ permalink raw reply related

* [PATCH iproute2 3/4] tc: m_ife: report about kernels default type
From: Alexander Aring @ 2017-08-28 19:07 UTC (permalink / raw)
  To: jhs; +Cc: yotamg, xiyou.wangcong, jiri, netdev, Alexander Aring
In-Reply-To: <20170828190738.26829-1-aring@mojatatu.com>

This patch will report about if the ethertype for IFE is not specified
that the default IFE type is used.

Signed-off-by: Alexander Aring <aring@mojatatu.com>
---
 tc/m_ife.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/tc/m_ife.c b/tc/m_ife.c
index 7b57130e..5633ab90 100644
--- a/tc/m_ife.c
+++ b/tc/m_ife.c
@@ -189,6 +189,8 @@ static int parse_ife(struct action_util *a, int *argc_p, char ***argv_p,
 		addattr_l(n, MAX_MSG, TCA_IFE_DMAC, dbuf, ETH_ALEN);
 	if (user_type)
 		addattr_l(n, MAX_MSG, TCA_IFE_TYPE, &ife_type, 2);
+	else
+		fprintf(stderr, "IFE type 0x%04X\n", ETH_P_IFE);
 	if (saddr)
 		addattr_l(n, MAX_MSG, TCA_IFE_SMAC, sbuf, ETH_ALEN);
 
-- 
2.11.0

^ permalink raw reply related

* [PATCH iproute2 2/4] tc: m_ife: print IEEE ethertype format
From: Alexander Aring @ 2017-08-28 19:07 UTC (permalink / raw)
  To: jhs; +Cc: yotamg, xiyou.wangcong, jiri, netdev, Alexander Aring
In-Reply-To: <20170828190738.26829-1-aring@mojatatu.com>

This patch uses the usually IEEE format to display an ethertype which is
4-digits and every digit in upper case.

Signed-off-by: Alexander Aring <aring@mojatatu.com>
---
 tc/m_ife.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tc/m_ife.c b/tc/m_ife.c
index e05e2276..7b57130e 100644
--- a/tc/m_ife.c
+++ b/tc/m_ife.c
@@ -125,7 +125,7 @@ static int parse_ife(struct action_util *a, int *argc_p, char ***argv_p,
 			NEXT_ARG();
 			if (get_u16(&ife_type, *argv, 0))
 				invarg("ife type is invalid", *argv);
-			fprintf(stderr, "IFE type 0x%x\n", ife_type);
+			fprintf(stderr, "IFE type 0x%04X\n", ife_type);
 			user_type = 1;
 		} else if (matches(*argv, "dst") == 0) {
 			NEXT_ARG();
-- 
2.11.0

^ permalink raw reply related

* [PATCH iproute2 1/4] tc: m_ife: allow ife type to zero
From: Alexander Aring @ 2017-08-28 19:07 UTC (permalink / raw)
  To: jhs; +Cc: yotamg, xiyou.wangcong, jiri, netdev, Alexander Aring
In-Reply-To: <20170828190738.26829-1-aring@mojatatu.com>

This patch allows to set an ethertype for IFE which is zero. There is no
kernel side validation which forbids a type to zero.

Signed-off-by: Alexander Aring <aring@mojatatu.com>
---
 tc/m_ife.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/tc/m_ife.c b/tc/m_ife.c
index e3521e62..e05e2276 100644
--- a/tc/m_ife.c
+++ b/tc/m_ife.c
@@ -63,6 +63,7 @@ static int parse_ife(struct action_util *a, int *argc_p, char ***argv_p,
 	char dbuf[ETH_ALEN];
 	char sbuf[ETH_ALEN];
 	__u16 ife_type = 0;
+	int user_type = 0;
 	__u32 ife_prio = 0;
 	__u32 ife_prio_v = 0;
 	__u32 ife_mark = 0;
@@ -125,6 +126,7 @@ static int parse_ife(struct action_util *a, int *argc_p, char ***argv_p,
 			if (get_u16(&ife_type, *argv, 0))
 				invarg("ife type is invalid", *argv);
 			fprintf(stderr, "IFE type 0x%x\n", ife_type);
+			user_type = 1;
 		} else if (matches(*argv, "dst") == 0) {
 			NEXT_ARG();
 			daddr = *argv;
@@ -185,7 +187,7 @@ static int parse_ife(struct action_util *a, int *argc_p, char ***argv_p,
 
 	if (daddr)
 		addattr_l(n, MAX_MSG, TCA_IFE_DMAC, dbuf, ETH_ALEN);
-	if (ife_type)
+	if (user_type)
 		addattr_l(n, MAX_MSG, TCA_IFE_TYPE, &ife_type, 2);
 	if (saddr)
 		addattr_l(n, MAX_MSG, TCA_IFE_SMAC, sbuf, ETH_ALEN);
-- 
2.11.0

^ permalink raw reply related

* [PATCH iproute2 0/4] tc: m_ife: handle IFE ethertype value
From: Alexander Aring @ 2017-08-28 19:07 UTC (permalink / raw)
  To: jhs; +Cc: yotamg, xiyou.wangcong, jiri, netdev, Alexander Aring

Hi,

this patch series fix some ife type handling for example it allows to set
ethertype to zero and prints IFE type like IEE specification.

Also it will report about the new introduced IFE type as fallback if no
IFE type as parameter is given. This new behaviour is also added to the
manpage of tc-ife.

Note: Please wait until the related kernel patches comes in. This
patch series contains an UAPI change which need to be accepted by netdev
at first. Thanks.

- Alex

Alexander Aring (4):
  tc: m_ife: allow ife type to zero
  tc: m_ife: print IEEE ethertype format
  tc: m_ife: report about kernels default type
  man: tc-ife: add default type note

 man/man8/tc-ife.8 | 2 +-
 tc/m_ife.c        | 8 ++++++--
 2 files changed, 7 insertions(+), 3 deletions(-)

-- 
2.11.0

^ permalink raw reply

* Re: [PATCH iproute2 net-next 1/2] iproute: add support for seg6 l2encap mode
From: Stephen Hemminger @ 2017-08-28 19:07 UTC (permalink / raw)
  To: David Lebrun; +Cc: netdev
In-Reply-To: <20170828190525.15655-2-david.lebrun@uclouvain.be>

On Mon, 28 Aug 2017 20:05:24 +0100
David Lebrun <david.lebrun@uclouvain.be> wrote:

>  
> +static const char *format_seg6mode_type(int mode)
> +{
> +	if (mode == SEG6_IPTUN_MODE_ENCAP)
> +		return "encap";
> +	else if (mode == SEG6_IPTUN_MODE_INLINE)
> +		return "inline";
> +	else if (mode == SEG6_IPTUN_MODE_L2ENCAP)
> +		return "l2encap";
> +
> +	return "<unknown>";
> +}
> +
> +static int read_seg6mode_type(const char *mode)
> +{
> +	if (strcmp(mode, "encap") == 0)
> +		return SEG6_IPTUN_MODE_ENCAP;
> +	else if (strcmp(mode, "inline") == 0)
> +		return SEG6_IPTUN_MODE_INLINE;
> +	else if (strcmp(mode, "l2encap") == 0)
> +		return SEG6_IPTUN_MODE_L2ENCAP;
> +
> +	return -1;
> +}

Since these values probably will grow over time, it would make
sense to have this a name/value table.

^ permalink raw reply

* Re: [PATCH net-next 06/11] bnxt_en: Improve -ENOMEM logic in NAPI poll loop.
From: Martin KaFai Lau @ 2017-08-28 19:05 UTC (permalink / raw)
  To: Michael Chan; +Cc: davem, netdev
In-Reply-To: <1503942035-24924-7-git-send-email-michael.chan@broadcom.com>

On Mon, Aug 28, 2017 at 01:40:30PM -0400, Michael Chan wrote:
> If we cannot allocate RX buffers in the NAPI poll loop when processing
> an RX event, the current code does not count that event towards the NAPI
> budget.  This can cause us to potentially loop forever in NAPI if we
> consistently cannot allocate new buffers.  Improve it by counting
> -ENOMEM event as 1 towards the NAPI budget.
>
> Cc: Martin KaFai Lau <kafai@fb.com>
> Signed-off-by: Michael Chan <michael.chan@broadcom.com>
Thanks for fixing it.

Reported-by: Martin KaFai Lau <kafai@fb.com>
Acked-by: Martin KaFai Lau <kafai@fb.com>

> ---
>  drivers/net/ethernet/broadcom/bnxt/bnxt.c | 7 +++++++
>  1 file changed, 7 insertions(+)
>
> diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
> index 1afb408..a34fcdd 100644
> --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
> +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
> @@ -1850,6 +1850,13 @@ static int bnxt_poll_work(struct bnxt *bp, struct bnxt_napi *bnapi, int budget)
>  							   &event);
>  			if (likely(rc >= 0))
>  				rx_pkts += rc;
> +			/* Increment rx_pkts when rc is -ENOMEM to count towards
> +			 * the NAPI budget.  Otherwise, we may potentially loop
> +			 * here forever if we consistently cannot allocate
> +			 * buffers.
> +			 */
> +			else if (rc == -ENOMEM)
> +				rx_pkts++;
>  			else if (rc == -EBUSY)	/* partial completion */
>  				break;
>  		} else if (unlikely((TX_CMP_TYPE(txcmp) ==
> --
> 1.8.3.1
>

^ permalink raw reply

* [PATCH iproute2 net-next 2/2] man: add documentation for seg6 l2encap mode
From: David Lebrun @ 2017-08-28 19:05 UTC (permalink / raw)
  To: netdev; +Cc: David Lebrun
In-Reply-To: <20170828190525.15655-1-david.lebrun@uclouvain.be>

This patch adds documentation for the seg6 L2ENCAP encapsulation mode.

Signed-off-by: David Lebrun <david.lebrun@uclouvain.be>
---
 man/man8/ip-route.8.in | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/man/man8/ip-route.8.in b/man/man8/ip-route.8.in
index 11dd9d0..803de3b 100644
--- a/man/man8/ip-route.8.in
+++ b/man/man8/ip-route.8.in
@@ -214,7 +214,7 @@ throw " | " unreachable " | " prohibit " | " blackhole " | " nat " ]"
 .IR ENCAP_SEG6 " := "
 .B seg6
 .BR mode " [ "
-.BR encap " | " inline " ] "
+.BR encap " | " inline " | " l2encap " ] "
 .B segs
 .IR SEGMENTS " [ "
 .B hmac
@@ -750,6 +750,10 @@ is a set of encapsulation attributes specific to the
 - Encapsulate packet in an outer IPv6 header with SRH
 .sp
 
+.B mode l2encap
+- Encapsulate ingress L2 frame within an outer IPv6 header and SRH
+.sp
+
 .I SEGMENTS
 - List of comma-separated IPv6 addresses
 .sp
-- 
2.10.2

^ permalink raw reply related

* [PATCH iproute2 net-next 1/2] iproute: add support for seg6 l2encap mode
From: David Lebrun @ 2017-08-28 19:05 UTC (permalink / raw)
  To: netdev; +Cc: David Lebrun
In-Reply-To: <20170828190525.15655-1-david.lebrun@uclouvain.be>

This patch adds support for the L2ENCAP seg6 mode, enabling to encapsulate
L2 frames within SRv6 packets.

Signed-off-by: David Lebrun <david.lebrun@uclouvain.be>
---
 ip/iproute_lwtunnel.c | 39 ++++++++++++++++++++++++++++-----------
 1 file changed, 28 insertions(+), 11 deletions(-)

diff --git a/ip/iproute_lwtunnel.c b/ip/iproute_lwtunnel.c
index 14294c6..f125670 100644
--- a/ip/iproute_lwtunnel.c
+++ b/ip/iproute_lwtunnel.c
@@ -110,6 +110,30 @@ static void print_srh(FILE *fp, struct ipv6_sr_hdr *srh)
 	}
 }
 
+static const char *format_seg6mode_type(int mode)
+{
+	if (mode == SEG6_IPTUN_MODE_ENCAP)
+		return "encap";
+	else if (mode == SEG6_IPTUN_MODE_INLINE)
+		return "inline";
+	else if (mode == SEG6_IPTUN_MODE_L2ENCAP)
+		return "l2encap";
+
+	return "<unknown>";
+}
+
+static int read_seg6mode_type(const char *mode)
+{
+	if (strcmp(mode, "encap") == 0)
+		return SEG6_IPTUN_MODE_ENCAP;
+	else if (strcmp(mode, "inline") == 0)
+		return SEG6_IPTUN_MODE_INLINE;
+	else if (strcmp(mode, "l2encap") == 0)
+		return SEG6_IPTUN_MODE_L2ENCAP;
+
+	return -1;
+}
+
 static void print_encap_seg6(FILE *fp, struct rtattr *encap)
 {
 	struct rtattr *tb[SEG6_IPTUNNEL_MAX+1];
@@ -121,8 +145,7 @@ static void print_encap_seg6(FILE *fp, struct rtattr *encap)
 		return;
 
 	tuninfo = RTA_DATA(tb[SEG6_IPTUNNEL_SRH]);
-	fprintf(fp, "mode %s ",
-		(tuninfo->mode == SEG6_IPTUN_MODE_ENCAP) ? "encap" : "inline");
+	fprintf(fp, "mode %s ", format_seg6mode_type(tuninfo->mode));
 
 	print_srh(fp, tuninfo->srh);
 }
@@ -457,11 +480,8 @@ static int parse_encap_seg6(struct rtattr *rta, size_t len, int *argcp,
 			NEXT_ARG();
 			if (mode_ok++)
 				duparg2("mode", *argv);
-			if (strcmp(*argv, "encap") == 0)
-				encap = 1;
-			else if (strcmp(*argv, "inline") == 0)
-				encap = 0;
-			else
+			encap = read_seg6mode_type(*argv);
+			if (encap < 0)
 				invarg("\"mode\" value is invalid\n", *argv);
 		} else if (strcmp(*argv, "segs") == 0) {
 			NEXT_ARG();
@@ -490,10 +510,7 @@ static int parse_encap_seg6(struct rtattr *rta, size_t len, int *argcp,
 	tuninfo = malloc(sizeof(*tuninfo) + srhlen);
 	memset(tuninfo, 0, sizeof(*tuninfo) + srhlen);
 
-	if (encap)
-		tuninfo->mode = SEG6_IPTUN_MODE_ENCAP;
-	else
-		tuninfo->mode = SEG6_IPTUN_MODE_INLINE;
+	tuninfo->mode = encap;
 
 	memcpy(tuninfo->srh, srh, srhlen);
 
-- 
2.10.2

^ permalink raw reply related

* [PATCH iproute2 net-next 0/2] Add support for seg6 l2encap mode
From: David Lebrun @ 2017-08-28 19:05 UTC (permalink / raw)
  To: netdev; +Cc: David Lebrun

This patch series adds support for the new L2ENCAP mode for SRv6
encapsulations.

David Lebrun (2):
  iproute: add support for seg6 l2encap mode
  man: add documentation for seg6 l2encap mode

 ip/iproute_lwtunnel.c  | 39 ++++++++++++++++++++++++++++-----------
 man/man8/ip-route.8.in |  6 +++++-
 2 files changed, 33 insertions(+), 12 deletions(-)

-- 
2.10.2

^ permalink raw reply

* [PATCH net-next 3/3] tc-testing: add test for testing ife type
From: Alexander Aring @ 2017-08-28 19:03 UTC (permalink / raw)
  To: jhs
  Cc: yotamg, xiyou.wangcong, jiri, lucasb, netdev, linux-kselftest,
	Alexander Aring
In-Reply-To: <20170828190315.26646-1-aring@mojatatu.com>

This patch adds a new testcase for the IFE type setting in tc. In case
of user specified the type it will check if the ife is correctly
configured to react on it. If it's not specified the default IFE type
should be used.

Signed-off-by: Alexander Aring <aring@mojatatu.com>
---
 .../tc-testing/tc-tests/actions/tests.json         | 50 ++++++++++++++++++++++
 1 file changed, 50 insertions(+)

diff --git a/tools/testing/selftests/tc-testing/tc-tests/actions/tests.json b/tools/testing/selftests/tc-testing/tc-tests/actions/tests.json
index af519bc97a8e..6973bdc5b5bf 100644
--- a/tools/testing/selftests/tc-testing/tc-tests/actions/tests.json
+++ b/tools/testing/selftests/tc-testing/tc-tests/actions/tests.json
@@ -1111,5 +1111,55 @@
         "teardown": [
             "$TC actions flush action gact"
         ]
+    },
+    {
+        "id": "a568",
+        "name": "Add action with ife type",
+        "category": [
+            "actions",
+            "ife"
+        ],
+        "setup": [
+            [
+                "$TC actions flush action ife",
+                0,
+                1,
+                255
+            ],
+            "$TC actions add action ife encode type 0xDEAD index 1"
+        ],
+        "cmdUnderTest": "$TC actions get action ife index 1",
+        "expExitCode": "0",
+        "verifyCmd": "$TC actions get action ife index 1",
+        "matchPattern": "type 0xDEAD",
+        "matchCount": "1",
+        "teardown": [
+            "$TC actions flush action ife"
+        ]
+    },
+    {
+        "id": "b983",
+        "name": "Add action without ife type",
+        "category": [
+            "actions",
+            "ife"
+        ],
+        "setup": [
+            [
+                "$TC actions flush action ife",
+                0,
+                1,
+                255
+            ],
+            "$TC actions add action ife encode index 1"
+        ],
+        "cmdUnderTest": "$TC actions get action ife index 1",
+        "expExitCode": "0",
+        "verifyCmd": "$TC actions get action ife index 1",
+        "matchPattern": "type 0xED3E",
+        "matchCount": "1",
+        "teardown": [
+            "$TC actions flush action ife"
+        ]
     }
 ]
\ No newline at end of file
-- 
2.11.0

^ permalink raw reply related

* [PATCH net-next 2/3] act_ife: use registered ife_type as fallback
From: Alexander Aring @ 2017-08-28 19:03 UTC (permalink / raw)
  To: jhs
  Cc: yotamg, xiyou.wangcong, jiri, lucasb, netdev, linux-kselftest,
	Alexander Aring
In-Reply-To: <20170828190315.26646-1-aring@mojatatu.com>

This patch handles a default IFE type if it's not given by user space
netlink api. The default IFE type will be the registered ethertype by
IEEE for IFE ForCES.

Signed-off-by: Alexander Aring <aring@mojatatu.com>
---
 net/sched/act_ife.c | 17 +++--------------
 1 file changed, 3 insertions(+), 14 deletions(-)

diff --git a/net/sched/act_ife.c b/net/sched/act_ife.c
index c5dec308b8b1..7ed1be80ee86 100644
--- a/net/sched/act_ife.c
+++ b/net/sched/act_ife.c
@@ -435,8 +435,8 @@ static int tcf_ife_init(struct net *net, struct nlattr *nla,
 	struct nlattr *tb[TCA_IFE_MAX + 1];
 	struct nlattr *tb2[IFE_META_MAX + 1];
 	struct tcf_ife_info *ife;
+	u16 ife_type = ETH_P_IFE;
 	struct tc_ife *parm;
-	u16 ife_type = 0;
 	u8 *daddr = NULL;
 	u8 *saddr = NULL;
 	bool exists = false;
@@ -456,18 +456,6 @@ static int tcf_ife_init(struct net *net, struct nlattr *nla,
 	if (exists && bind)
 		return 0;
 
-	if (parm->flags & IFE_ENCODE) {
-		/* Until we get issued the ethertype, we cant have
-		 * a default..
-		**/
-		if (!tb[TCA_IFE_TYPE]) {
-			if (exists)
-				tcf_hash_release(*a, bind);
-			pr_info("You MUST pass etherype for encoding\n");
-			return -EINVAL;
-		}
-	}
-
 	if (!exists) {
 		ret = tcf_hash_create(tn, parm->index, est, a, &act_ife_ops,
 				      bind, false);
@@ -484,7 +472,8 @@ static int tcf_ife_init(struct net *net, struct nlattr *nla,
 	ife->flags = parm->flags;
 
 	if (parm->flags & IFE_ENCODE) {
-		ife_type = nla_get_u16(tb[TCA_IFE_TYPE]);
+		if (tb[TCA_IFE_TYPE])
+			ife_type = nla_get_u16(tb[TCA_IFE_TYPE]);
 		if (tb[TCA_IFE_DMAC])
 			daddr = nla_data(tb[TCA_IFE_DMAC]);
 		if (tb[TCA_IFE_SMAC])
-- 
2.11.0

^ permalink raw reply related

* [PATCH net-next 1/3] if_ether: add forces ife lfb type
From: Alexander Aring @ 2017-08-28 19:03 UTC (permalink / raw)
  To: jhs
  Cc: yotamg, xiyou.wangcong, jiri, lucasb, netdev, linux-kselftest,
	Alexander Aring
In-Reply-To: <20170828190315.26646-1-aring@mojatatu.com>

This patch adds the forces IFE lfb type according to IEEE registered
ethertypes. See http://standards-oui.ieee.org/ethertype/eth.txt for more
information. Since there exists the IFE subsystem it can be used there.

This patch also use the correct word "ForCES" instead of "FoRCES" which
is a spelling error inside the IEEE ethertype specification.

Signed-off-by: Alexander Aring <aring@mojatatu.com>
---
 include/uapi/linux/if_ether.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/include/uapi/linux/if_ether.h b/include/uapi/linux/if_ether.h
index 5bc9bfd816b7..22bf8effefef 100644
--- a/include/uapi/linux/if_ether.h
+++ b/include/uapi/linux/if_ether.h
@@ -103,6 +103,7 @@
 #define ETH_P_QINQ2	0x9200		/* deprecated QinQ VLAN [ NOT AN OFFICIALLY REGISTERED ID ] */
 #define ETH_P_QINQ3	0x9300		/* deprecated QinQ VLAN [ NOT AN OFFICIALLY REGISTERED ID ] */
 #define ETH_P_EDSA	0xDADA		/* Ethertype DSA [ NOT AN OFFICIALLY REGISTERED ID ] */
+#define ETH_P_IFE	0xED3E		/* ForCES inter-FE LFB type */
 #define ETH_P_AF_IUCV   0xFBFB		/* IBM af_iucv [ NOT AN OFFICIALLY REGISTERED ID ] */
 
 #define ETH_P_802_3_MIN	0x0600		/* If the value in the ethernet type is less than this value
-- 
2.11.0

^ permalink raw reply related

* [PATCH net-next 0/3] tc: act_ife: handle IEEE IFE ethertype as default
From: Alexander Aring @ 2017-08-28 19:03 UTC (permalink / raw)
  To: jhs
  Cc: yotamg, xiyou.wangcong, jiri, lucasb, netdev, linux-kselftest,
	Alexander Aring

Hi,

this patch series will introduce the IFE ethertype which is registered by
IEEE. If the netlink act_ife type netlink attribute is not given it will
use this value by default now.
At least it will introduce some UAPI testcases to check if the default type
is used if not specified and vice versa.

- Alex

Alexander Aring (3):
  if_ether: add forces ife lfb type
  act_ife: use registered ife_type as fallback
  tc-testing: add test for testing ife type

 include/uapi/linux/if_ether.h                      |  1 +
 net/sched/act_ife.c                                | 17 ++------
 .../tc-testing/tc-tests/actions/tests.json         | 50 ++++++++++++++++++++++
 3 files changed, 54 insertions(+), 14 deletions(-)

-- 
2.11.0

^ permalink raw reply

* Re: Fwd: DA850-evm MAC Address is random
From: Grygorii Strashko @ 2017-08-28 18:54 UTC (permalink / raw)
  To: Adam Ford, linux-omap, netdev, Sekhar Nori
In-Reply-To: <CAHCN7xKwFd7dHF0ySEd1hOSr0sZEgh9fuwy=RkUTHvEh59hojQ@mail.gmail.com>

Cc: Sekhar

On 08/28/2017 10:32 AM, Adam Ford wrote:
> The davinvi_emac MAC address seems to attempt a call to
> ti_cm_get_macid in cpsw-common.c but it returns the message
> 'davinci_emac davinci_emac.1: incompatible machine/device type for
> reading mac address ' and then generates a random MAC address.
> 
> The function appears to lookup varions boards using
> 'of_machine_is_compaible' and supports dm8148, am33xx, am3517, dm816,
> am4372 and dra7.  I don't see the ti,davinci-dm6467-emac which is
> what's shown in the da850 device tree.
> 
> Is there a patch somewhere for supporting the da850-evm?

Not sure if MAC address can be read from Control module.
May be Sekhar can say more?

> 
> If not, is there a way to pass the MAC address from U-Boot to the
> driver so it doesn't generate a random MAC?

"local-mac-address" dt porp

-- 
regards,
-grygorii

^ permalink raw reply

* [PATCH net v2 6/6] net:ethernet:aquantia: Show info message if bad firmware version detected.
From: Pavel Belous @ 2017-08-28 18:52 UTC (permalink / raw)
  To: David S . Miller
  Cc: netdev, David Arcari, Igor Russkikh, Nadezhda Krupnina,
	Simon Edelhaus, Pavel Belous, Pavel Belous
In-Reply-To: <cover.1503945861.git.pavel.belous@aquantia.com>

From: Pavel Belous <pavel.belous@aquantia.com>

We should inform user about wrong firmware version
by printing message in dmesg.

Fixes: 3d2ff7eebe26 ("net: ethernet: aquantia: Atlantic hardware abstraction layer")
Signed-off-by: Pavel Belous <Pavel.Belous@aquantia.com>
---
 drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c
index 7a1332e..4f5ec9a 100644
--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c
+++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c
@@ -141,6 +141,12 @@ static int hw_atl_utils_init_ucp(struct aq_hw_s *self,
 
 	err = hw_atl_utils_ver_match(aq_hw_caps->fw_ver_expected,
 				     aq_hw_read_reg(self, 0x18U));
+
+	if (err < 0)
+		pr_err("%s: Bad FW version detected: expected=%x, actual=%x\n",
+		       AQ_CFG_DRV_NAME,
+		       aq_hw_caps->fw_ver_expected,
+		       aq_hw_read_reg(self, 0x18U));
 	return err;
 }
 
-- 
2.7.4

^ permalink raw reply related

* [PATCH net v2 5/6] net:ethernet:aquantia: Fix for multicast filter handling.
From: Pavel Belous @ 2017-08-28 18:52 UTC (permalink / raw)
  To: David S . Miller
  Cc: netdev, David Arcari, Igor Russkikh, Nadezhda Krupnina,
	Simon Edelhaus
In-Reply-To: <cover.1503945861.git.pavel.belous@aquantia.com>

From: Igor Russkikh <Igor.Russkikh@aquantia.com>

Since the HW supports up to 32 multicast filters we should
track count of multicast filters to avoid overflow.
If we attempt to add >32 multicast filter - just set NETIF_ALLMULTI flag
instead.

Fixes: 94f6c9e4cdf6 ("net: ethernet: aquantia: Support for NIC-specific code")
Signed-off-by: Igor Russkikh <Igor.Russkikh@aquantia.com>
---
 drivers/net/ethernet/aquantia/atlantic/aq_nic.c | 17 ++++++++++++++++-
 1 file changed, 16 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
index dce17a5..6ac9e26 100644
--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
@@ -669,11 +669,26 @@ int aq_nic_set_multicast_list(struct aq_nic_s *self, struct net_device *ndev)
 	netdev_for_each_mc_addr(ha, ndev) {
 		ether_addr_copy(self->mc_list.ar[i++], ha->addr);
 		++self->mc_list.count;
+
+		if (i >= AQ_CFG_MULTICAST_ADDRESS_MAX)
+			break;
 	}
 
-	return self->aq_hw_ops.hw_multicast_list_set(self->aq_hw,
+	if (i >= AQ_CFG_MULTICAST_ADDRESS_MAX) {
+		/* Number of filters is too big: atlantic does not support this.
+		 * Force all multi filter to support this.
+		 * With this we disable all UC filters and setup "all pass"
+		 * multicast mask
+		 */
+		self->packet_filter |= IFF_ALLMULTI;
+		self->aq_hw->aq_nic_cfg->mc_list_count = 0;
+		return self->aq_hw_ops.hw_packet_filter_set(self->aq_hw,
+							self->packet_filter);
+	} else {
+		return self->aq_hw_ops.hw_multicast_list_set(self->aq_hw,
 						    self->mc_list.ar,
 						    self->mc_list.count);
+	}
 }
 
 int aq_nic_set_mtu(struct aq_nic_s *self, int new_mtu)
-- 
2.7.4

^ permalink raw reply related

* [PATCH net v2 4/6] net:ethernet:aquantia: Fix for incorrect speed index.
From: Pavel Belous @ 2017-08-28 18:52 UTC (permalink / raw)
  To: David S . Miller
  Cc: netdev, David Arcari, Igor Russkikh, Nadezhda Krupnina,
	Simon Edelhaus, Pavel Belous, Pavel Belous
In-Reply-To: <cover.1503945861.git.pavel.belous@aquantia.com>

From: Pavel Belous <pavel.belous@aquantia.com>

The driver choose the optimal interrupt throttling settings depends
of current link speed.
Due this bug link_status field from aq_hw is never updated and as result
always used same interrupt throttling values.

Fixes: 3d2ff7eebe26 ("net: ethernet: aquantia: Atlantic hardware abstraction layer")
Signed-off-by: Pavel Belous <Pavel.Belous@aquantia.com>
---
 drivers/net/ethernet/aquantia/atlantic/aq_hw.h     |  3 +--
 drivers/net/ethernet/aquantia/atlantic/aq_nic.c    | 31 ++++++++++------------
 .../aquantia/atlantic/hw_atl/hw_atl_utils.c        |  4 +--
 .../aquantia/atlantic/hw_atl/hw_atl_utils.h        |  3 +--
 4 files changed, 18 insertions(+), 23 deletions(-)

diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_hw.h b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h
index fce0fd3..bf9b3f0 100644
--- a/drivers/net/ethernet/aquantia/atlantic/aq_hw.h
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h
@@ -105,8 +105,7 @@ struct aq_hw_ops {
 
 	int (*hw_set_mac_address)(struct aq_hw_s *self, u8 *mac_addr);
 
-	int (*hw_get_link_status)(struct aq_hw_s *self,
-				  struct aq_hw_link_status_s *link_status);
+	int (*hw_get_link_status)(struct aq_hw_s *self);
 
 	int (*hw_set_link_speed)(struct aq_hw_s *self, u32 speed);
 
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
index d6d8e70..dce17a5 100644
--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
@@ -125,33 +125,30 @@ static void aq_nic_service_timer_cb(unsigned long param)
 	struct net_device *ndev = aq_nic_get_ndev(self);
 	int err = 0;
 	unsigned int i = 0U;
-	struct aq_hw_link_status_s link_status;
 	struct aq_ring_stats_rx_s stats_rx;
 	struct aq_ring_stats_tx_s stats_tx;
 
 	if (aq_utils_obj_test(&self->header.flags, AQ_NIC_FLAGS_IS_NOT_READY))
 		goto err_exit;
 
-	err = self->aq_hw_ops.hw_get_link_status(self->aq_hw, &link_status);
+	err = self->aq_hw_ops.hw_get_link_status(self->aq_hw);
 	if (err < 0)
 		goto err_exit;
 
-	self->aq_hw_ops.hw_interrupt_moderation_set(self->aq_hw,
-			    self->aq_nic_cfg.is_interrupt_moderation);
-
-	if (memcmp(&link_status, &self->link_status, sizeof(link_status))) {
-		if (link_status.mbps) {
-			aq_utils_obj_set(&self->header.flags,
-					 AQ_NIC_FLAG_STARTED);
-			aq_utils_obj_clear(&self->header.flags,
-					   AQ_NIC_LINK_DOWN);
-			netif_carrier_on(self->ndev);
-		} else {
-			netif_carrier_off(self->ndev);
-			aq_utils_obj_set(&self->header.flags, AQ_NIC_LINK_DOWN);
-		}
+	self->link_status = self->aq_hw->aq_link_status;
 
-		self->link_status = link_status;
+	self->aq_hw_ops.hw_interrupt_moderation_set(self->aq_hw,
+		    self->aq_nic_cfg.is_interrupt_moderation);
+
+	if (self->link_status.mbps) {
+		aq_utils_obj_set(&self->header.flags,
+				 AQ_NIC_FLAG_STARTED);
+		aq_utils_obj_clear(&self->header.flags,
+				   AQ_NIC_LINK_DOWN);
+		netif_carrier_on(self->ndev);
+	} else {
+		netif_carrier_off(self->ndev);
+		aq_utils_obj_set(&self->header.flags, AQ_NIC_LINK_DOWN);
 	}
 
 	memset(&stats_rx, 0U, sizeof(struct aq_ring_stats_rx_s));
diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c
index 8d6d8f5..7a1332e 100644
--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c
+++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c
@@ -313,11 +313,11 @@ void hw_atl_utils_mpi_set(struct aq_hw_s *self,
 err_exit:;
 }
 
-int hw_atl_utils_mpi_get_link_status(struct aq_hw_s *self,
-				     struct aq_hw_link_status_s *link_status)
+int hw_atl_utils_mpi_get_link_status(struct aq_hw_s *self)
 {
 	u32 cp0x036C = aq_hw_read_reg(self, HW_ATL_MPI_STATE_ADR);
 	u32 link_speed_mask = cp0x036C >> HW_ATL_MPI_SPEED_SHIFT;
+	struct aq_hw_link_status_s *link_status = &self->aq_link_status;
 
 	if (!link_speed_mask) {
 		link_status->mbps = 0U;
diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h
index a66aee5..e0360a6 100644
--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h
+++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h
@@ -180,8 +180,7 @@ void hw_atl_utils_mpi_set(struct aq_hw_s *self,
 int hw_atl_utils_mpi_set_speed(struct aq_hw_s *self, u32 speed,
 			       enum hal_atl_utils_fw_state_e state);
 
-int hw_atl_utils_mpi_get_link_status(struct aq_hw_s *self,
-				     struct aq_hw_link_status_s *link_status);
+int hw_atl_utils_mpi_get_link_status(struct aq_hw_s *self);
 
 int hw_atl_utils_get_mac_permanent(struct aq_hw_s *self,
 				   struct aq_hw_caps_s *aq_hw_caps,
-- 
2.7.4

^ permalink raw reply related

* [PATCH net v2 3/6] net:ethernet:aquantia: Workaround for HW checksum bug.
From: Pavel Belous @ 2017-08-28 18:52 UTC (permalink / raw)
  To: David S . Miller
  Cc: netdev, David Arcari, Igor Russkikh, Nadezhda Krupnina,
	Simon Edelhaus, Pavel Belous, Pavel Belous
In-Reply-To: <cover.1503945861.git.pavel.belous@aquantia.com>

From: Pavel Belous <pavel.belous@aquantia.com>

The hardware has the HW Checksum Offload bug when small
TCP patckets (with length <= 60 bytes) has wrong "checksum valid" bit.

The solution is - ignore checksum valid bit for small packets
(with length <= 60 bytes) and mark this as CHECKSUM_NONE to allow
network stack recalculate checksum itself.

Fixes: ccf9a5ed14be ("net: ethernet: aquantia: Atlantic A0 and B0 specific functions.")
Signed-off-by: Pavel Belous <Pavel.Belous@aquantia.com>
---
 drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c | 6 ++++++
 drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c | 6 ++++++
 2 files changed, 12 insertions(+)

diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c
index faeb493..c5a02df 100644
--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c
+++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c
@@ -629,6 +629,12 @@ static int hw_atl_a0_hw_ring_rx_receive(struct aq_hw_s *self,
 				buff->is_udp_cso = (is_err & 0x10U) ? 0 : 1;
 			else if (0x0U == (pkt_type & 0x1CU))
 				buff->is_tcp_cso = (is_err & 0x10U) ? 0 : 1;
+
+			/* Checksum offload workaround for small packets */
+			if (rxd_wb->pkt_len <= 60) {
+				buff->is_ip_cso = 0U;
+				buff->is_cso_err = 0U;
+			}
 		}
 
 		is_err &= ~0x18U;
diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c
index 1bceb73..21784cc 100644
--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c
+++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c
@@ -645,6 +645,12 @@ static int hw_atl_b0_hw_ring_rx_receive(struct aq_hw_s *self,
 				buff->is_udp_cso = buff->is_cso_err ? 0U : 1U;
 			else if (0x0U == (pkt_type & 0x1CU))
 				buff->is_tcp_cso = buff->is_cso_err ? 0U : 1U;
+
+			/* Checksum offload workaround for small packets */
+			if (rxd_wb->pkt_len <= 60) {
+				buff->is_ip_cso = 0U;
+				buff->is_cso_err = 0U;
+			}
 		}
 
 		is_err &= ~0x18U;
-- 
2.7.4

^ permalink raw reply related


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