* [PATCH 0/6] debugfs for mv88e6xxx
@ 2015-06-20 16:42 Andrew Lunn
2015-06-20 16:42 ` [PATCH 1/6] dsa: mv88e6xxx: Add debugfs interface for registers Andrew Lunn
` (6 more replies)
0 siblings, 7 replies; 8+ messages in thread
From: Andrew Lunn @ 2015-06-20 16:42 UTC (permalink / raw)
To: David Miller
Cc: netdev, Guenter Roeck, Vivien Didelot, Cory Tusar, Andrew Lunn
This patchset adds some debugfs files for seeing into a mv88e6xxx
family of switch chips.
# cat atu
DB T/P Vec State Addr
003 Port 008 7 00:22:02:00:18:44
003 Port 008 6 80:ee:73:83:60:27
005 Port 020 7 94:10:3e:80:bc:f3
0f8 Port 001 6 8e:25:13:53:44:de
This walks all possible entries, so is a bit slow, but is always
correct.
# cat device_map
Target Port
0 15
1 15
2 15
3 15
4 15
5 15
6 15
7 15
8 15
9 15
-->snip<--
31 15
A rather boring example, since i only have one switch here. But this shows
the routing between multiple switches.
# cat regs
GLOBAL GLOBAL2 0 1 2 3 4 5 6
0: c804 0 1e4f 100f 100f 1e4f 1e0f e07 e07
1: fe 0 3 3 3 3 3 c03e c03f
2: 0 ffff 0 0 0 0 0 0 0
3: 0 ffff 1721 1721 1721 1721 1721 1721 1721
4: 6000 258 433 431 431 433 433 373f 433
5: 0 ff 0 0 0 0 0 0 0
6: c000 1f0f 2026 2025 2023 3020 4020 501f 6020
7: 0 707f 0 0 0 0 0 0 0
8: 0 7800 2080 2080 2080 2080 2080 2080 2080
9: 0 1600 1 1 1 1 1 1 1
a: 148 0 0 0 0 0 0 0 0
b: 4000 1000 1 2 4 8 10 20 40
c: 0 7f 0 0 0 0 0 0 0
d: ffff 5f3 0 0 0 0 0 0 0
e: ffff 6 0 0 0 0 0 0 0
f: ffff f00 dada dada dada dada dada dada dada
10: 0 0 0 0 0 0 0 0 0
11: 0 0 0 0 0 0 0 0 0
12: 5555 0 0 0 0 0 0 0 0
13: 5555 0 1a 0 0 1df0 0 1e07 0
14: aaaa 400 0 0 0 0 0 0 0
15: aaaa 0 0 0 0 0 0 0 0
16: ffff 0 6011 6011 6011 6011 33 33 0
17: ffff 0 0 0 0 0 0 0 0
18: fa41 1844 3210 3210 3210 3210 3210 3210 3210
19: 0 1e1 7654 7654 7654 7654 7654 7654 7654
1a: 5550 0 0 0 0 0 0 0 0
1b: 1fb f869 8000 8000 8000 8000 8000 8000 8000
1c: 0 0 0 0 0 0 0 0 0
1d: c00 0 0 0 0 0 0 0 0
1e: 0 0 0 0 0 0 0 0 0
1f: 0 0 0 0 0 0 0 0 0
All the switch registers which are directly accessible.
# cat stats
Statistic Port 0 Port 1 Port 2 Port 3 Port 4 Port 5 Port 6
in_good_octets: 2176 0 0 4263711 0 499540 0
in_bad_octets: 46050 0 0 50196 0 0 0
in_unicast: 0 0 0 7693 0 7691 0
in_broadcasts: 0 0 0 0 0 3 0
in_multicasts: 34 0 0 0 0 27 0
in_pause: 0 0 0 0 0 0 0
in_undersize: 0 0 0 0 0 0 0
in_fragments: 45 0 0 2 0 0 0
in_oversize: 0 0 0 0 0 0 0
in_jabber: 0 0 0 0 0 0 0
in_rx_error: 0 0 0 0 0 0 0
in_fcs_error: 159 0 0 37 0 0 0
out_octets: 808 0 0 496608 336 4267159 0
out_unicast: 0 0 0 7691 0 7693 0
out_broadcasts: 1 0 0 3 0 0 0
out_multicasts: 9 0 0 6 4 34 0
out_pause: 0 0 0 0 0 0 0
excessive: 0 0 0 0 0 0 0
collisions: 0 0 0 0 0 0 0
deferred: 0 0 0 0 0 0 0
single: 0 0 0 0 0 0 0
multiple: 0 0 0 0 0 0 0
out_fcs_error: 0 0 0 0 0 0 0
late: 0 0 0 0 0 0 0
hist_64bytes: 36 0 0 7577 0 7574 0
hist_65_127bytes: 53 0 0 241 4 298 0
hist_128_255bytes: 50 0 0 12 0 10 0
hist_256_511bytes: 43 0 0 8 0 2 0
hist_512_1023bytes: 18 0 0 7573 0 7564 0
hist_1024_max_bytes: 3 0 0 19 0 0 0
sw_in_discards: 0 0 0 0 0 0 0
sw_in_filtered: 0 0 0 0 0 0 0
sw_out_filtered: 34 0 0 7693 0 7721 0
Of particular interest here is that you get to see all ports,
including the CPU port and any DSA ports. You cannot get statistics
for these ports via ethtool.
Andrew Lunn (6):
dsa: mv88e6xxx: Add debugfs interface for registers
dsa: mv88e6xxx: Add debugfs interface for ATU
dsa: mv88x6xxx: Refactor getting a single statistic
dsa: mv88x6xxx: Add debugfs interface for statistics
dsa: mv88x6xxx: Add debugfs interface for device map
dsa: mv88x6xxx: Add debugfs interface for scratch registers
drivers/net/dsa/mv88e6xxx.c | 348 ++++++++++++++++++++++++++++++++++++++++----
drivers/net/dsa/mv88e6xxx.h | 13 ++
2 files changed, 334 insertions(+), 27 deletions(-)
--
2.1.4
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 1/6] dsa: mv88e6xxx: Add debugfs interface for registers
2015-06-20 16:42 [PATCH 0/6] debugfs for mv88e6xxx Andrew Lunn
@ 2015-06-20 16:42 ` Andrew Lunn
2015-06-20 16:42 ` [PATCH 2/6] dsa: mv88e6xxx: Add debugfs interface for ATU Andrew Lunn
` (5 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Andrew Lunn @ 2015-06-20 16:42 UTC (permalink / raw)
To: David Miller
Cc: netdev, Guenter Roeck, Vivien Didelot, Cory Tusar, Andrew Lunn
Allow the contents of the registers to be shown in debugfs.
Signed-off-by: Andrew Lunn <andrew@lunn.ch>
---
drivers/net/dsa/mv88e6xxx.c | 50 +++++++++++++++++++++++++++++++++++++++++++++
drivers/net/dsa/mv88e6xxx.h | 2 ++
2 files changed, 52 insertions(+)
diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c
index 39530fa142b0..e6dbc4a8110e 100644
--- a/drivers/net/dsa/mv88e6xxx.c
+++ b/drivers/net/dsa/mv88e6xxx.c
@@ -8,6 +8,7 @@
* (at your option) any later version.
*/
+#include <linux/debugfs.h>
#include <linux/delay.h>
#include <linux/etherdevice.h>
#include <linux/if_bridge.h>
@@ -16,6 +17,7 @@
#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/phy.h>
+#include <linux/seq_file.h>
#include <net/dsa.h>
#include "mv88e6xxx.h"
@@ -1601,9 +1603,50 @@ int mv88e6xxx_setup_ports(struct dsa_switch *ds)
return 0;
}
+static int mv88e6xxx_regs_show(struct seq_file *s, void *p)
+{
+ struct dsa_switch *ds = s->private;
+
+ struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
+ int reg, port;
+
+ seq_puts(s, " GLOBAL GLOBAL2 ");
+ for (port = 0 ; port < ps->num_ports; port++)
+ seq_printf(s, " %2d ", port);
+ seq_puts(s, "\n");
+
+ for (reg = 0; reg < 32; reg++) {
+ seq_printf(s, "%2x: ", reg);
+ seq_printf(s, " %4x %4x ",
+ mv88e6xxx_reg_read(ds, REG_GLOBAL, reg),
+ mv88e6xxx_reg_read(ds, REG_GLOBAL2, reg));
+
+ for (port = 0 ; port < ps->num_ports; port++)
+ seq_printf(s, "%4x ",
+ mv88e6xxx_reg_read(ds, REG_PORT(port), reg));
+ seq_puts(s, "\n");
+ }
+
+ return 0;
+}
+
+static int mv88e6xxx_regs_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, mv88e6xxx_regs_show, inode->i_private);
+}
+
+static const struct file_operations mv88e6xxx_regs_fops = {
+ .open = mv88e6xxx_regs_open,
+ .read = seq_read,
+ .llseek = no_llseek,
+ .release = single_release,
+ .owner = THIS_MODULE,
+};
+
int mv88e6xxx_setup_common(struct dsa_switch *ds)
{
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
+ char *name;
mutex_init(&ps->smi_mutex);
@@ -1613,6 +1656,13 @@ int mv88e6xxx_setup_common(struct dsa_switch *ds)
INIT_WORK(&ps->bridge_work, mv88e6xxx_bridge_work);
+ name = kasprintf(GFP_KERNEL, "dsa%d", ds->index);
+ ps->dbgfs = debugfs_create_dir(name, NULL);
+ kfree(name);
+
+ debugfs_create_file("regs", S_IRUGO, ps->dbgfs, ds,
+ &mv88e6xxx_regs_fops);
+
return 0;
}
diff --git a/drivers/net/dsa/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx.h
index e10ccdb4ffbc..5fc291cbdae0 100644
--- a/drivers/net/dsa/mv88e6xxx.h
+++ b/drivers/net/dsa/mv88e6xxx.h
@@ -339,6 +339,8 @@ struct mv88e6xxx_priv_state {
u8 port_state[DSA_MAX_PORTS];
struct work_struct bridge_work;
+
+ struct dentry *dbgfs;
};
struct mv88e6xxx_hw_stat {
--
2.1.4
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 2/6] dsa: mv88e6xxx: Add debugfs interface for ATU
2015-06-20 16:42 [PATCH 0/6] debugfs for mv88e6xxx Andrew Lunn
2015-06-20 16:42 ` [PATCH 1/6] dsa: mv88e6xxx: Add debugfs interface for registers Andrew Lunn
@ 2015-06-20 16:42 ` Andrew Lunn
2015-06-20 16:42 ` [PATCH 3/6] dsa: mv88x6xxx: Refactor getting a single statistic Andrew Lunn
` (4 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Andrew Lunn @ 2015-06-20 16:42 UTC (permalink / raw)
To: David Miller
Cc: netdev, Guenter Roeck, Vivien Didelot, Cory Tusar, Andrew Lunn
Dump the Address Translation Unit via a file in debugfs.
Signed-off-by: Andrew Lunn <andrew@lunn.ch>
---
drivers/net/dsa/mv88e6xxx.c | 81 +++++++++++++++++++++++++++++++++++++++++++++
drivers/net/dsa/mv88e6xxx.h | 3 ++
2 files changed, 84 insertions(+)
diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c
index e6dbc4a8110e..6e684f3d377c 100644
--- a/drivers/net/dsa/mv88e6xxx.c
+++ b/drivers/net/dsa/mv88e6xxx.c
@@ -1643,6 +1643,84 @@ static const struct file_operations mv88e6xxx_regs_fops = {
.owner = THIS_MODULE,
};
+static void mv88e6xxx_atu_show_header(struct seq_file *s)
+{
+ seq_puts(s, "DB T/P Vec State Addr\n");
+}
+
+static void mv88e6xxx_atu_show_entry(struct seq_file *s, int dbnum,
+ unsigned char *addr, int data)
+{
+ bool trunk = !!(data & GLOBAL_ATU_DATA_TRUNK);
+ int portvec = ((data & GLOBAL_ATU_DATA_PORT_VECTOR_MASK) >>
+ GLOBAL_ATU_DATA_PORT_VECTOR_SHIFT);
+ int state = data & GLOBAL_ATU_DATA_STATE_MASK;
+
+ seq_printf(s, "%03x %5s %10pb %x %pM\n",
+ dbnum, (trunk ? "Trunk" : "Port"), &portvec, state, addr);
+}
+
+static int mv88e6xxx_atu_show_db(struct seq_file *s, struct dsa_switch *ds,
+ int dbnum)
+{
+ unsigned char bcast[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+ unsigned char addr[6];
+ int ret, data, state;
+
+ ret = __mv88e6xxx_write_addr(ds, bcast);
+ if (ret < 0)
+ return ret;
+
+ do {
+ ret = _mv88e6xxx_atu_cmd(ds, dbnum, GLOBAL_ATU_OP_GET_NEXT_DB);
+ if (ret < 0)
+ return ret;
+ data = _mv88e6xxx_reg_read(ds, REG_GLOBAL, GLOBAL_ATU_DATA);
+ if (data < 0)
+ return data;
+
+ state = data & GLOBAL_ATU_DATA_STATE_MASK;
+ if (state == GLOBAL_ATU_DATA_STATE_UNUSED)
+ break;
+ ret = __mv88e6xxx_read_addr(ds, addr);
+ if (ret < 0)
+ return ret;
+ mv88e6xxx_atu_show_entry(s, dbnum, addr, data);
+ } while (state != GLOBAL_ATU_DATA_STATE_UNUSED);
+
+ return 0;
+}
+
+static int mv88e6xxx_atu_show(struct seq_file *s, void *p)
+{
+ struct dsa_switch *ds = s->private;
+ struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
+ int dbnum;
+
+ mv88e6xxx_atu_show_header(s);
+
+ for (dbnum = 0; dbnum < 255; dbnum++) {
+ mutex_lock(&ps->smi_mutex);
+ mv88e6xxx_atu_show_db(s, ds, dbnum);
+ mutex_unlock(&ps->smi_mutex);
+ }
+
+ return 0;
+}
+
+static int mv88e6xxx_atu_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, mv88e6xxx_atu_show, inode->i_private);
+}
+
+static const struct file_operations mv88e6xxx_atu_fops = {
+ .open = mv88e6xxx_atu_open,
+ .read = seq_read,
+ .llseek = no_llseek,
+ .release = single_release,
+ .owner = THIS_MODULE,
+};
+
int mv88e6xxx_setup_common(struct dsa_switch *ds)
{
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
@@ -1663,6 +1741,9 @@ int mv88e6xxx_setup_common(struct dsa_switch *ds)
debugfs_create_file("regs", S_IRUGO, ps->dbgfs, ds,
&mv88e6xxx_regs_fops);
+ debugfs_create_file("atu", S_IRUGO, ps->dbgfs, ds,
+ &mv88e6xxx_atu_fops);
+
return 0;
}
diff --git a/drivers/net/dsa/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx.h
index 5fc291cbdae0..8b9c76b66ddb 100644
--- a/drivers/net/dsa/mv88e6xxx.h
+++ b/drivers/net/dsa/mv88e6xxx.h
@@ -193,6 +193,9 @@
#define GLOBAL_ATU_OP_FLUSH_NON_STATIC_DB ((6 << 12) | GLOBAL_ATU_OP_BUSY)
#define GLOBAL_ATU_OP_GET_CLR_VIOLATION ((7 << 12) | GLOBAL_ATU_OP_BUSY)
#define GLOBAL_ATU_DATA 0x0c
+#define GLOBAL_ATU_DATA_TRUNK BIT(15)
+#define GLOBAL_ATU_DATA_PORT_VECTOR_MASK 0x3ff0
+#define GLOBAL_ATU_DATA_PORT_VECTOR_SHIFT 4
#define GLOBAL_ATU_DATA_STATE_MASK 0x0f
#define GLOBAL_ATU_DATA_STATE_UNUSED 0x00
#define GLOBAL_ATU_DATA_STATE_UC_MGMT 0x0d
--
2.1.4
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 3/6] dsa: mv88x6xxx: Refactor getting a single statistic
2015-06-20 16:42 [PATCH 0/6] debugfs for mv88e6xxx Andrew Lunn
2015-06-20 16:42 ` [PATCH 1/6] dsa: mv88e6xxx: Add debugfs interface for registers Andrew Lunn
2015-06-20 16:42 ` [PATCH 2/6] dsa: mv88e6xxx: Add debugfs interface for ATU Andrew Lunn
@ 2015-06-20 16:42 ` Andrew Lunn
2015-06-20 16:42 ` [PATCH 4/6] dsa: mv88x6xxx: Add debugfs interface for statistics Andrew Lunn
` (3 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Andrew Lunn @ 2015-06-20 16:42 UTC (permalink / raw)
To: David Miller
Cc: netdev, Guenter Roeck, Vivien Didelot, Cory Tusar, Andrew Lunn
Move the code to retrieve a statistics counter into a function of its
own, so it can later be reused.
Signed-off-by: Andrew Lunn <andrew@lunn.ch>
---
drivers/net/dsa/mv88e6xxx.c | 63 ++++++++++++++++++++++++++-------------------
drivers/net/dsa/mv88e6xxx.h | 4 +++
2 files changed, 40 insertions(+), 27 deletions(-)
diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c
index 6e684f3d377c..43c1515a8319 100644
--- a/drivers/net/dsa/mv88e6xxx.c
+++ b/drivers/net/dsa/mv88e6xxx.c
@@ -681,6 +681,40 @@ static void _mv88e6xxx_get_strings(struct dsa_switch *ds,
}
}
+static uint64_t _mv88e6xxx_get_ethtool_stat(struct dsa_switch *ds,
+ int stat,
+ struct mv88e6xxx_hw_stat *stats,
+ int port)
+{
+ struct mv88e6xxx_hw_stat *s = stats + stat;
+ u32 low;
+ u32 high = 0;
+ int ret;
+ u64 value;
+
+ if (s->reg >= 0x100) {
+ ret = _mv88e6xxx_reg_read(ds, REG_PORT(port),
+ s->reg - 0x100);
+ if (ret < 0)
+ return UINT64_MAX;
+
+ low = ret;
+ if (s->sizeof_stat == 4) {
+ ret = _mv88e6xxx_reg_read(ds, REG_PORT(port),
+ s->reg - 0x100 + 1);
+ if (ret < 0)
+ return UINT64_MAX;
+ high = ret;
+ }
+ } else {
+ _mv88e6xxx_stats_read(ds, s->reg, &low);
+ if (s->sizeof_stat == 8)
+ _mv88e6xxx_stats_read(ds, s->reg + 1, &high);
+ }
+ value = (((u64)high) << 16) | low;
+ return value;
+}
+
static void _mv88e6xxx_get_ethtool_stats(struct dsa_switch *ds,
int nr_stats,
struct mv88e6xxx_hw_stat *stats,
@@ -699,34 +733,9 @@ static void _mv88e6xxx_get_ethtool_stats(struct dsa_switch *ds,
}
/* Read each of the counters. */
- for (i = 0; i < nr_stats; i++) {
- struct mv88e6xxx_hw_stat *s = stats + i;
- u32 low;
- u32 high = 0;
+ for (i = 0; i < nr_stats; i++)
+ data[i] = _mv88e6xxx_get_ethtool_stat(ds, i, stats, port);
- if (s->reg >= 0x100) {
- ret = _mv88e6xxx_reg_read(ds, REG_PORT(port),
- s->reg - 0x100);
- if (ret < 0)
- goto error;
- low = ret;
- if (s->sizeof_stat == 4) {
- ret = _mv88e6xxx_reg_read(ds, REG_PORT(port),
- s->reg - 0x100 + 1);
- if (ret < 0)
- goto error;
- high = ret;
- }
- data[i] = (((u64)high) << 16) | low;
- continue;
- }
- _mv88e6xxx_stats_read(ds, s->reg, &low);
- if (s->sizeof_stat == 8)
- _mv88e6xxx_stats_read(ds, s->reg + 1, &high);
-
- data[i] = (((u64)high) << 32) | low;
- }
-error:
mutex_unlock(&ps->smi_mutex);
}
diff --git a/drivers/net/dsa/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx.h
index 8b9c76b66ddb..7cccff202586 100644
--- a/drivers/net/dsa/mv88e6xxx.h
+++ b/drivers/net/dsa/mv88e6xxx.h
@@ -11,6 +11,10 @@
#ifndef __MV88E6XXX_H
#define __MV88E6XXX_H
+#ifndef UINT64_MAX
+#define UINT64_MAX (u64)(~((u64)0))
+#endif
+
#define SMI_CMD 0x00
#define SMI_CMD_BUSY BIT(15)
#define SMI_CMD_CLAUSE_22 BIT(12)
--
2.1.4
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 4/6] dsa: mv88x6xxx: Add debugfs interface for statistics
2015-06-20 16:42 [PATCH 0/6] debugfs for mv88e6xxx Andrew Lunn
` (2 preceding siblings ...)
2015-06-20 16:42 ` [PATCH 3/6] dsa: mv88x6xxx: Refactor getting a single statistic Andrew Lunn
@ 2015-06-20 16:42 ` Andrew Lunn
2015-06-20 16:42 ` [PATCH 5/6] dsa: mv88x6xxx: Add debugfs interface for device map Andrew Lunn
` (2 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Andrew Lunn @ 2015-06-20 16:42 UTC (permalink / raw)
To: David Miller
Cc: netdev, Guenter Roeck, Vivien Didelot, Cory Tusar, Andrew Lunn
Allow the contents of the statistics counters to be shown in debugfs.
This is particularly useful for the cpu and dsa ports, which cannot be
seen using ethtools -S.
Signed-off-by: Andrew Lunn <andrew@lunn.ch>
---
drivers/net/dsa/mv88e6xxx.c | 59 +++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 59 insertions(+)
diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c
index 43c1515a8319..fc5d4fdfcb02 100644
--- a/drivers/net/dsa/mv88e6xxx.c
+++ b/drivers/net/dsa/mv88e6xxx.c
@@ -1730,6 +1730,62 @@ static const struct file_operations mv88e6xxx_atu_fops = {
.owner = THIS_MODULE,
};
+static void mv88e6xxx_stats_show_header(struct seq_file *s,
+ struct mv88e6xxx_priv_state *ps)
+{
+ int port;
+
+ seq_puts(s, " Statistic ");
+ for (port = 0 ; port < ps->num_ports; port++)
+ seq_printf(s, "Port %2d ", port);
+ seq_puts(s, "\n");
+}
+
+static int mv88e6xxx_stats_show(struct seq_file *s, void *p)
+{
+ struct dsa_switch *ds = s->private;
+ struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
+ struct mv88e6xxx_hw_stat *stats = mv88e6xxx_hw_stats;
+ int port, stat, max_stats;
+ uint64_t value;
+
+ if (have_sw_in_discards(ds))
+ max_stats = ARRAY_SIZE(mv88e6xxx_hw_stats);
+ else
+ max_stats = ARRAY_SIZE(mv88e6xxx_hw_stats) - 3;
+
+ mv88e6xxx_stats_show_header(s, ps);
+
+ mutex_lock(&ps->smi_mutex);
+
+ for (stat = 0; stat < max_stats; stat++) {
+ seq_printf(s, "%19s: ", stats[stat].string);
+ for (port = 0 ; port < ps->num_ports; port++) {
+ _mv88e6xxx_stats_snapshot(ds, port);
+ value = _mv88e6xxx_get_ethtool_stat(ds, stat, stats,
+ port);
+ seq_printf(s, "%8llu ", value);
+ }
+ seq_puts(s, "\n");
+ }
+ mutex_unlock(&ps->smi_mutex);
+
+ return 0;
+}
+
+static int mv88e6xxx_stats_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, mv88e6xxx_stats_show, inode->i_private);
+}
+
+static const struct file_operations mv88e6xxx_stats_fops = {
+ .open = mv88e6xxx_stats_open,
+ .read = seq_read,
+ .llseek = no_llseek,
+ .release = single_release,
+ .owner = THIS_MODULE,
+};
+
int mv88e6xxx_setup_common(struct dsa_switch *ds)
{
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
@@ -1753,6 +1809,9 @@ int mv88e6xxx_setup_common(struct dsa_switch *ds)
debugfs_create_file("atu", S_IRUGO, ps->dbgfs, ds,
&mv88e6xxx_atu_fops);
+ debugfs_create_file("stats", S_IRUGO, ps->dbgfs, ds,
+ &mv88e6xxx_stats_fops);
+
return 0;
}
--
2.1.4
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 5/6] dsa: mv88x6xxx: Add debugfs interface for device map
2015-06-20 16:42 [PATCH 0/6] debugfs for mv88e6xxx Andrew Lunn
` (3 preceding siblings ...)
2015-06-20 16:42 ` [PATCH 4/6] dsa: mv88x6xxx: Add debugfs interface for statistics Andrew Lunn
@ 2015-06-20 16:42 ` Andrew Lunn
2015-06-20 16:42 ` [PATCH 6/6] dsa: mv88x6xxx: Add debugfs interface for scratch registers Andrew Lunn
2015-06-23 13:34 ` [PATCH 0/6] debugfs for mv88e6xxx David Miller
6 siblings, 0 replies; 8+ messages in thread
From: Andrew Lunn @ 2015-06-20 16:42 UTC (permalink / raw)
To: David Miller
Cc: netdev, Guenter Roeck, Vivien Didelot, Cory Tusar, Andrew Lunn
The device map is used to route packets between cascaded switches.
Add dumping a switches device map via debugfs.
Signed-off-by: Andrew Lunn <andrew@lunn.ch>
---
drivers/net/dsa/mv88e6xxx.c | 41 +++++++++++++++++++++++++++++++++++++++++
drivers/net/dsa/mv88e6xxx.h | 1 +
2 files changed, 42 insertions(+)
diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c
index fc5d4fdfcb02..7e12a31e9dae 100644
--- a/drivers/net/dsa/mv88e6xxx.c
+++ b/drivers/net/dsa/mv88e6xxx.c
@@ -1786,6 +1786,45 @@ static const struct file_operations mv88e6xxx_stats_fops = {
.owner = THIS_MODULE,
};
+static int mv88e6xxx_device_map_show(struct seq_file *s, void *p)
+{
+ struct dsa_switch *ds = s->private;
+ struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
+ int target, ret;
+
+ seq_puts(s, "Target Port\n");
+
+ mutex_lock(&ps->smi_mutex);
+ for (target = 0; target < 32; target++) {
+ ret = _mv88e6xxx_reg_write(
+ ds, REG_GLOBAL2, GLOBAL2_DEVICE_MAPPING,
+ target << GLOBAL2_DEVICE_MAPPING_TARGET_SHIFT);
+ if (ret < 0)
+ goto out;
+ ret = _mv88e6xxx_reg_read(ds, REG_GLOBAL2,
+ GLOBAL2_DEVICE_MAPPING);
+ seq_printf(s, " %2d %2d\n", target,
+ ret & GLOBAL2_DEVICE_MAPPING_PORT_MASK);
+ }
+out:
+ mutex_unlock(&ps->smi_mutex);
+
+ return 0;
+}
+
+static int mv88e6xxx_device_map_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, mv88e6xxx_device_map_show, inode->i_private);
+}
+
+static const struct file_operations mv88e6xxx_device_map_fops = {
+ .open = mv88e6xxx_device_map_open,
+ .read = seq_read,
+ .llseek = no_llseek,
+ .release = single_release,
+ .owner = THIS_MODULE,
+};
+
int mv88e6xxx_setup_common(struct dsa_switch *ds)
{
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
@@ -1812,6 +1851,8 @@ int mv88e6xxx_setup_common(struct dsa_switch *ds)
debugfs_create_file("stats", S_IRUGO, ps->dbgfs, ds,
&mv88e6xxx_stats_fops);
+ debugfs_create_file("device_map", S_IRUGO, ps->dbgfs, ds,
+ &mv88e6xxx_device_map_fops);
return 0;
}
diff --git a/drivers/net/dsa/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx.h
index 7cccff202586..a2c9ac0c54ab 100644
--- a/drivers/net/dsa/mv88e6xxx.h
+++ b/drivers/net/dsa/mv88e6xxx.h
@@ -260,6 +260,7 @@
#define GLOBAL2_DEVICE_MAPPING 0x06
#define GLOBAL2_DEVICE_MAPPING_UPDATE BIT(15)
#define GLOBAL2_DEVICE_MAPPING_TARGET_SHIFT 8
+#define GLOBAL2_DEVICE_MAPPING_PORT_MASK 0x0f
#define GLOBAL2_TRUNK_MASK 0x07
#define GLOBAL2_TRUNK_MASK_UPDATE BIT(15)
#define GLOBAL2_TRUNK_MASK_NUM_SHIFT 12
--
2.1.4
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 6/6] dsa: mv88x6xxx: Add debugfs interface for scratch registers
2015-06-20 16:42 [PATCH 0/6] debugfs for mv88e6xxx Andrew Lunn
` (4 preceding siblings ...)
2015-06-20 16:42 ` [PATCH 5/6] dsa: mv88x6xxx: Add debugfs interface for device map Andrew Lunn
@ 2015-06-20 16:42 ` Andrew Lunn
2015-06-23 13:34 ` [PATCH 0/6] debugfs for mv88e6xxx David Miller
6 siblings, 0 replies; 8+ messages in thread
From: Andrew Lunn @ 2015-06-20 16:42 UTC (permalink / raw)
To: David Miller
Cc: netdev, Guenter Roeck, Vivien Didelot, Cory Tusar, Andrew Lunn
Allow the contents of the scratch registers to be shown in debugfs.
Signed-off-by: Andrew Lunn <andrew@lunn.ch>
---
drivers/net/dsa/mv88e6xxx.c | 54 +++++++++++++++++++++++++++++++++++++++++++++
drivers/net/dsa/mv88e6xxx.h | 3 +++
2 files changed, 57 insertions(+)
diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c
index 7e12a31e9dae..c938d7ce5215 100644
--- a/drivers/net/dsa/mv88e6xxx.c
+++ b/drivers/net/dsa/mv88e6xxx.c
@@ -901,6 +901,13 @@ static int _mv88e6xxx_atu_wait(struct dsa_switch *ds)
GLOBAL_ATU_OP_BUSY);
}
+/* Must be called with SMI lock held */
+static int _mv88e6xxx_scratch_wait(struct dsa_switch *ds)
+{
+ return _mv88e6xxx_wait(ds, REG_GLOBAL2, GLOBAL2_SCRATCH_MISC,
+ GLOBAL2_SCRATCH_BUSY);
+}
+
/* Must be called with SMI mutex held */
static int _mv88e6xxx_phy_read_indirect(struct dsa_switch *ds, int addr,
int regnum)
@@ -1825,6 +1832,50 @@ static const struct file_operations mv88e6xxx_device_map_fops = {
.owner = THIS_MODULE,
};
+static int mv88e6xxx_scratch_show(struct seq_file *s, void *p)
+{
+ struct dsa_switch *ds = s->private;
+ struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
+ int reg, ret;
+
+ seq_puts(s, "Register Value\n");
+
+ mutex_lock(&ps->smi_mutex);
+ for (reg = 0; reg < 0x80; reg++) {
+ ret = _mv88e6xxx_reg_write(
+ ds, REG_GLOBAL2, GLOBAL2_SCRATCH_MISC,
+ reg << GLOBAL2_SCRATCH_REGISTER_SHIFT);
+ if (ret < 0)
+ goto out;
+
+ ret = _mv88e6xxx_scratch_wait(ds);
+ if (ret < 0)
+ goto out;
+
+ ret = _mv88e6xxx_reg_read(ds, REG_GLOBAL2,
+ GLOBAL2_SCRATCH_MISC);
+ seq_printf(s, " %2x %2x\n", reg,
+ ret & GLOBAL2_SCRATCH_VALUE_MASK);
+ }
+out:
+ mutex_unlock(&ps->smi_mutex);
+
+ return 0;
+}
+
+static int mv88e6xxx_scratch_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, mv88e6xxx_scratch_show, inode->i_private);
+}
+
+static const struct file_operations mv88e6xxx_scratch_fops = {
+ .open = mv88e6xxx_scratch_open,
+ .read = seq_read,
+ .llseek = no_llseek,
+ .release = single_release,
+ .owner = THIS_MODULE,
+};
+
int mv88e6xxx_setup_common(struct dsa_switch *ds)
{
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
@@ -1853,6 +1904,9 @@ int mv88e6xxx_setup_common(struct dsa_switch *ds)
debugfs_create_file("device_map", S_IRUGO, ps->dbgfs, ds,
&mv88e6xxx_device_map_fops);
+
+ debugfs_create_file("scratch", S_IRUGO, ps->dbgfs, ds,
+ &mv88e6xxx_scratch_fops);
return 0;
}
diff --git a/drivers/net/dsa/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx.h
index a2c9ac0c54ab..a650b2656de9 100644
--- a/drivers/net/dsa/mv88e6xxx.h
+++ b/drivers/net/dsa/mv88e6xxx.h
@@ -297,6 +297,9 @@
#define GLOBAL2_SMI_OP_45_READ_DATA ((2 << 10) | GLOBAL2_SMI_OP_BUSY)
#define GLOBAL2_SMI_DATA 0x19
#define GLOBAL2_SCRATCH_MISC 0x1a
+#define GLOBAL2_SCRATCH_BUSY BIT(15)
+#define GLOBAL2_SCRATCH_REGISTER_SHIFT 8
+#define GLOBAL2_SCRATCH_VALUE_MASK 0xff
#define GLOBAL2_WDOG_CONTROL 0x1b
#define GLOBAL2_QOS_WEIGHT 0x1c
#define GLOBAL2_MISC 0x1d
--
2.1.4
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH 0/6] debugfs for mv88e6xxx
2015-06-20 16:42 [PATCH 0/6] debugfs for mv88e6xxx Andrew Lunn
` (5 preceding siblings ...)
2015-06-20 16:42 ` [PATCH 6/6] dsa: mv88x6xxx: Add debugfs interface for scratch registers Andrew Lunn
@ 2015-06-23 13:34 ` David Miller
6 siblings, 0 replies; 8+ messages in thread
From: David Miller @ 2015-06-23 13:34 UTC (permalink / raw)
To: andrew; +Cc: netdev, linux, vivien.didelot, cory.tusar
From: Andrew Lunn <andrew@lunn.ch>
Date: Sat, 20 Jun 2015 18:42:27 +0200
> This patchset adds some debugfs files for seeing into a mv88e6xxx
> family of switch chips.
Series applied, thanks.
Although, long term, I'm very disappointed that we can't extend
ethtool to demux on the DSA ports via some new key or similar
facility.
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2015-06-23 13:22 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-06-20 16:42 [PATCH 0/6] debugfs for mv88e6xxx Andrew Lunn
2015-06-20 16:42 ` [PATCH 1/6] dsa: mv88e6xxx: Add debugfs interface for registers Andrew Lunn
2015-06-20 16:42 ` [PATCH 2/6] dsa: mv88e6xxx: Add debugfs interface for ATU Andrew Lunn
2015-06-20 16:42 ` [PATCH 3/6] dsa: mv88x6xxx: Refactor getting a single statistic Andrew Lunn
2015-06-20 16:42 ` [PATCH 4/6] dsa: mv88x6xxx: Add debugfs interface for statistics Andrew Lunn
2015-06-20 16:42 ` [PATCH 5/6] dsa: mv88x6xxx: Add debugfs interface for device map Andrew Lunn
2015-06-20 16:42 ` [PATCH 6/6] dsa: mv88x6xxx: Add debugfs interface for scratch registers Andrew Lunn
2015-06-23 13:34 ` [PATCH 0/6] debugfs for mv88e6xxx David Miller
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).