.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);
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;
}