From 48e2331197b82c425e12ab728bb5332e49c78f63 Mon Sep 17 00:00:00 2001 From: Vivien Didelot Date: Fri, 2 Aug 2019 15:34:55 -0400 Subject: [PATCH] net: dsa: dump CPU port regs through master Merge the CPU port registers dump into the master interface registers dump through ethtool, by nesting the ethtool_drvinfo and ethtool_regs structures of the CPU port into the dump. drvinfo->regdump_len will contain the full data length, while regs->len will contain only the master interface registers dump length. This allows for example to dump the CPU port registers on a ZII Dev C board like this: # ethtool -d eth1 0x004: 0x00000000 0x008: 0x0a8000aa 0x010: 0x01000000 0x014: 0x00000000 0x024: 0xf0000102 0x040: 0x6d82c800 0x044: 0x00000020 0x064: 0x40000000 0x084: RCR (Receive Control Register) 0x47c00104 MAX_FL (Maximum frame length) 1984 FCE (Flow control enable) 0 BC_REJ (Broadcast frame reject) 0 PROM (Promiscuous mode) 0 DRT (Disable receive on transmit) 0 LOOP (Internal loopback) 0 0x0c4: TCR (Transmit Control Register) 0x00000004 RFC_PAUSE (Receive frame control pause) 0 TFC_PAUSE (Transmit frame control pause) 0 FDEN (Full duplex enable) 1 HBC (Heartbeat control) 0 GTS (Graceful transmit stop) 0 0x0e4: 0x76735d6d 0x0e8: 0x7e9e8808 0x0ec: 0x00010000 . . . 88E6352 Switch Port Registers ------------------------------ 00: Port Status 0x4d04 Pause Enabled 0 My Pause 1 802.3 PHY Detected 0 Link Status Up Duplex Full Speed 100 or 200 Mbps EEE Enabled 0 Transmitter Paused 0 Flow Control 0 Config Mode 0x4 01: Physical Control 0x003d RGMII Receive Timing Control Default RGMII Transmit Timing Control Default 200 BASE Mode 100 Flow Control's Forced value 0 Force Flow Control 0 Link's Forced value Up Force Link 1 Duplex's Forced value Full Force Duplex 1 Force Speed 100 or 200 Mbps . . . Signed-off-by: Vivien Didelot Signed-off-by: David S. Miller --- net/dsa/master.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/net/dsa/master.c b/net/dsa/master.c index 4b52f8bac5e1..a8e52c9967f4 100644 --- a/net/dsa/master.c +++ b/net/dsa/master.c @@ -8,6 +8,70 @@ #include "dsa_priv.h" +static int dsa_master_get_regs_len(struct net_device *dev) +{ + struct dsa_port *cpu_dp = dev->dsa_ptr; + const struct ethtool_ops *ops = cpu_dp->orig_ethtool_ops; + struct dsa_switch *ds = cpu_dp->ds; + int port = cpu_dp->index; + int ret = 0; + int len; + + if (ops->get_regs_len) { + len = ops->get_regs_len(dev); + if (len < 0) + return len; + ret += len; + } + + ret += sizeof(struct ethtool_drvinfo); + ret += sizeof(struct ethtool_regs); + + if (ds->ops->get_regs_len) { + len = ds->ops->get_regs_len(ds, port); + if (len < 0) + return len; + ret += len; + } + + return ret; +} + +static void dsa_master_get_regs(struct net_device *dev, + struct ethtool_regs *regs, void *data) +{ + struct dsa_port *cpu_dp = dev->dsa_ptr; + const struct ethtool_ops *ops = cpu_dp->orig_ethtool_ops; + struct dsa_switch *ds = cpu_dp->ds; + struct ethtool_drvinfo *cpu_info; + struct ethtool_regs *cpu_regs; + int port = cpu_dp->index; + int len; + + if (ops->get_regs_len && ops->get_regs) { + len = ops->get_regs_len(dev); + if (len < 0) + return; + regs->len = len; + ops->get_regs(dev, regs, data); + data += regs->len; + } + + cpu_info = (struct ethtool_drvinfo *)data; + strlcpy(cpu_info->driver, "dsa", sizeof(cpu_info->driver)); + data += sizeof(*cpu_info); + cpu_regs = (struct ethtool_regs *)data; + data += sizeof(*cpu_regs); + + if (ds->ops->get_regs_len && ds->ops->get_regs) { + len = ds->ops->get_regs_len(ds, port); + if (len < 0) + return; + cpu_regs->len = len; + ds->ops->get_regs(ds, port, cpu_regs, data); + } +} + static void dsa_master_get_ethtool_stats(struct net_device *dev, struct ethtool_stats *stats, uint64_t *data) @@ -147,6 +211,8 @@ static int dsa_master_ethtool_setup(struct net_device *dev) if (cpu_dp->orig_ethtool_ops) memcpy(ops, cpu_dp->orig_ethtool_ops, sizeof(*ops)); + ops->get_regs_len = dsa_master_get_regs_len; + ops->get_regs = dsa_master_get_regs; ops->get_sset_count = dsa_master_get_sset_count; ops->get_ethtool_stats = dsa_master_get_ethtool_stats; ops->get_strings = dsa_master_get_strings;