* [PATCH v2 net-next 0/5] Export SERDES stats via ethtool -S
@ 2018-03-01 1:02 Andrew Lunn
2018-03-01 1:02 ` [PATCH v2 net-next 1/5] dsa: Pass the port to get_sset_count() Andrew Lunn
` (5 more replies)
0 siblings, 6 replies; 9+ messages in thread
From: Andrew Lunn @ 2018-03-01 1:02 UTC (permalink / raw)
To: David Miller; +Cc: netdev, Vivien Didelot, Florian Fainelli, Andrew Lunn
The mv88e6352 family has a SERDES interface which can be used for
example to connect to SFF/SFP modules. This interface has a couple of
statistics counters. Add support for including these counters in the
output of ethtool -S.
Andrew Lunn (5):
dsa: Pass the port to get_sset_count()
net: dsa: mv88e6xxx: Hold mutex while doing stats operations
net: dsa: mv88e6xxx: Allow the SERDES interfaces to have statistics
net: dsa: mv88e6xxx: Add helper to determining if port has SERDES
net: dsa: mv88e6xxx: Get mv88e6352 SERDES statistics
drivers/net/dsa/b53/b53_common.c | 2 +-
drivers/net/dsa/b53/b53_priv.h | 2 +-
drivers/net/dsa/dsa_loop.c | 2 +-
drivers/net/dsa/lan9303-core.c | 2 +-
drivers/net/dsa/microchip/ksz_common.c | 2 +-
drivers/net/dsa/mt7530.c | 2 +-
drivers/net/dsa/mv88e6xxx/chip.c | 90 ++++++++++++++++++++--------
drivers/net/dsa/mv88e6xxx/chip.h | 23 +++++--
drivers/net/dsa/mv88e6xxx/serdes.c | 106 +++++++++++++++++++++++++++++++--
drivers/net/dsa/mv88e6xxx/serdes.h | 6 +-
drivers/net/dsa/qca8k.c | 2 +-
include/net/dsa.h | 2 +-
net/dsa/master.c | 4 +-
net/dsa/slave.c | 2 +-
14 files changed, 200 insertions(+), 47 deletions(-)
--
2.16.2
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v2 net-next 1/5] dsa: Pass the port to get_sset_count()
2018-03-01 1:02 [PATCH v2 net-next 0/5] Export SERDES stats via ethtool -S Andrew Lunn
@ 2018-03-01 1:02 ` Andrew Lunn
2018-03-01 1:02 ` [PATCH v2 net-next 2/5] net: dsa: mv88e6xxx: Hold mutex while doing stats operations Andrew Lunn
` (4 subsequent siblings)
5 siblings, 0 replies; 9+ messages in thread
From: Andrew Lunn @ 2018-03-01 1:02 UTC (permalink / raw)
To: David Miller; +Cc: netdev, Vivien Didelot, Florian Fainelli, Andrew Lunn
By passing the port, we allow different ports to have different
statistics. This is useful since some ports have SERDES interfaces
with their own statistic counters.
Signed-off-by: Andrew Lunn <andrew@lunn.ch>
Tested-by: Florian Fainelli <f.fainelli@gmail.com>
Reviewed-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
---
drivers/net/dsa/b53/b53_common.c | 2 +-
drivers/net/dsa/b53/b53_priv.h | 2 +-
drivers/net/dsa/dsa_loop.c | 2 +-
drivers/net/dsa/lan9303-core.c | 2 +-
drivers/net/dsa/microchip/ksz_common.c | 2 +-
drivers/net/dsa/mt7530.c | 2 +-
drivers/net/dsa/mv88e6xxx/chip.c | 2 +-
drivers/net/dsa/qca8k.c | 2 +-
include/net/dsa.h | 2 +-
net/dsa/master.c | 4 ++--
net/dsa/slave.c | 2 +-
11 files changed, 12 insertions(+), 12 deletions(-)
diff --git a/drivers/net/dsa/b53/b53_common.c b/drivers/net/dsa/b53/b53_common.c
index db830a1141d9..cd16067265dd 100644
--- a/drivers/net/dsa/b53/b53_common.c
+++ b/drivers/net/dsa/b53/b53_common.c
@@ -852,7 +852,7 @@ void b53_get_ethtool_stats(struct dsa_switch *ds, int port, uint64_t *data)
}
EXPORT_SYMBOL(b53_get_ethtool_stats);
-int b53_get_sset_count(struct dsa_switch *ds)
+int b53_get_sset_count(struct dsa_switch *ds, int port)
{
struct b53_device *dev = ds->priv;
diff --git a/drivers/net/dsa/b53/b53_priv.h b/drivers/net/dsa/b53/b53_priv.h
index d954cf36ecd8..1187ebd79287 100644
--- a/drivers/net/dsa/b53/b53_priv.h
+++ b/drivers/net/dsa/b53/b53_priv.h
@@ -288,7 +288,7 @@ void b53_imp_vlan_setup(struct dsa_switch *ds, int cpu_port);
int b53_configure_vlan(struct dsa_switch *ds);
void b53_get_strings(struct dsa_switch *ds, int port, uint8_t *data);
void b53_get_ethtool_stats(struct dsa_switch *ds, int port, uint64_t *data);
-int b53_get_sset_count(struct dsa_switch *ds);
+int b53_get_sset_count(struct dsa_switch *ds, int port);
int b53_br_join(struct dsa_switch *ds, int port, struct net_device *bridge);
void b53_br_leave(struct dsa_switch *ds, int port, struct net_device *bridge);
void b53_br_set_stp_state(struct dsa_switch *ds, int port, u8 state);
diff --git a/drivers/net/dsa/dsa_loop.c b/drivers/net/dsa/dsa_loop.c
index 7aa84ee4e771..f77be9f85cb3 100644
--- a/drivers/net/dsa/dsa_loop.c
+++ b/drivers/net/dsa/dsa_loop.c
@@ -86,7 +86,7 @@ static int dsa_loop_setup(struct dsa_switch *ds)
return 0;
}
-static int dsa_loop_get_sset_count(struct dsa_switch *ds)
+static int dsa_loop_get_sset_count(struct dsa_switch *ds, int port)
{
return __DSA_LOOP_CNT_MAX;
}
diff --git a/drivers/net/dsa/lan9303-core.c b/drivers/net/dsa/lan9303-core.c
index 6171c0853ff1..fefa454f3e56 100644
--- a/drivers/net/dsa/lan9303-core.c
+++ b/drivers/net/dsa/lan9303-core.c
@@ -1007,7 +1007,7 @@ static void lan9303_get_ethtool_stats(struct dsa_switch *ds, int port,
}
}
-static int lan9303_get_sset_count(struct dsa_switch *ds)
+static int lan9303_get_sset_count(struct dsa_switch *ds, int port)
{
return ARRAY_SIZE(lan9303_mib);
}
diff --git a/drivers/net/dsa/microchip/ksz_common.c b/drivers/net/dsa/microchip/ksz_common.c
index 663b0d5b982b..bcb3e6c734f2 100644
--- a/drivers/net/dsa/microchip/ksz_common.c
+++ b/drivers/net/dsa/microchip/ksz_common.c
@@ -439,7 +439,7 @@ static void ksz_disable_port(struct dsa_switch *ds, int port,
ksz_port_cfg(dev, port, REG_PORT_CTRL_0, PORT_MAC_LOOPBACK, true);
}
-static int ksz_sset_count(struct dsa_switch *ds)
+static int ksz_sset_count(struct dsa_switch *ds, int port)
{
return TOTAL_SWITCH_COUNTER_NUM;
}
diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c
index 8a0bb000d056..511ca134f13f 100644
--- a/drivers/net/dsa/mt7530.c
+++ b/drivers/net/dsa/mt7530.c
@@ -604,7 +604,7 @@ mt7530_get_ethtool_stats(struct dsa_switch *ds, int port,
}
static int
-mt7530_get_sset_count(struct dsa_switch *ds)
+mt7530_get_sset_count(struct dsa_switch *ds, int port)
{
return ARRAY_SIZE(mt7530_mib);
}
diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
index 24486f96dd39..8c9a30d1b06f 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.c
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
@@ -754,7 +754,7 @@ static int mv88e6320_stats_get_sset_count(struct mv88e6xxx_chip *chip)
STATS_TYPE_BANK1);
}
-static int mv88e6xxx_get_sset_count(struct dsa_switch *ds)
+static int mv88e6xxx_get_sset_count(struct dsa_switch *ds, int port)
{
struct mv88e6xxx_chip *chip = ds->priv;
diff --git a/drivers/net/dsa/qca8k.c b/drivers/net/dsa/qca8k.c
index 9df22ebee822..600d5ad1fbde 100644
--- a/drivers/net/dsa/qca8k.c
+++ b/drivers/net/dsa/qca8k.c
@@ -631,7 +631,7 @@ qca8k_get_ethtool_stats(struct dsa_switch *ds, int port,
}
static int
-qca8k_get_sset_count(struct dsa_switch *ds)
+qca8k_get_sset_count(struct dsa_switch *ds, int port)
{
return ARRAY_SIZE(ar8327_mib);
}
diff --git a/include/net/dsa.h b/include/net/dsa.h
index 0ad17b63684d..60fb4ec8ba61 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -359,7 +359,7 @@ struct dsa_switch_ops {
void (*get_strings)(struct dsa_switch *ds, int port, uint8_t *data);
void (*get_ethtool_stats)(struct dsa_switch *ds,
int port, uint64_t *data);
- int (*get_sset_count)(struct dsa_switch *ds);
+ int (*get_sset_count)(struct dsa_switch *ds, int port);
/*
* ethtool Wake-on-LAN
diff --git a/net/dsa/master.c b/net/dsa/master.c
index 00589147f042..90e6df0351eb 100644
--- a/net/dsa/master.c
+++ b/net/dsa/master.c
@@ -42,7 +42,7 @@ static int dsa_master_get_sset_count(struct net_device *dev, int sset)
count += ops->get_sset_count(dev, sset);
if (sset == ETH_SS_STATS && ds->ops->get_sset_count)
- count += ds->ops->get_sset_count(ds);
+ count += ds->ops->get_sset_count(ds, cpu_dp->index);
return count;
}
@@ -76,7 +76,7 @@ static void dsa_master_get_strings(struct net_device *dev, uint32_t stringset,
* constructed earlier
*/
ds->ops->get_strings(ds, port, ndata);
- count = ds->ops->get_sset_count(ds);
+ count = ds->ops->get_sset_count(ds, port);
for (i = 0; i < count; i++) {
memmove(ndata + (i * len + sizeof(pfx)),
ndata + i * len, len - sizeof(pfx));
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index 3376dad6dcfd..18561af7a8f1 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -605,7 +605,7 @@ static int dsa_slave_get_sset_count(struct net_device *dev, int sset)
count = 4;
if (ds->ops->get_sset_count)
- count += ds->ops->get_sset_count(ds);
+ count += ds->ops->get_sset_count(ds, dp->index);
return count;
}
--
2.16.2
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH v2 net-next 2/5] net: dsa: mv88e6xxx: Hold mutex while doing stats operations
2018-03-01 1:02 [PATCH v2 net-next 0/5] Export SERDES stats via ethtool -S Andrew Lunn
2018-03-01 1:02 ` [PATCH v2 net-next 1/5] dsa: Pass the port to get_sset_count() Andrew Lunn
@ 2018-03-01 1:02 ` Andrew Lunn
2018-03-01 1:02 ` [PATCH v2 net-next 3/5] net: dsa: mv88e6xxx: Allow the SERDES interfaces to have statistics Andrew Lunn
` (3 subsequent siblings)
5 siblings, 0 replies; 9+ messages in thread
From: Andrew Lunn @ 2018-03-01 1:02 UTC (permalink / raw)
To: David Miller; +Cc: netdev, Vivien Didelot, Florian Fainelli, Andrew Lunn
Until now, there has been no need to hold the reg mutex while getting
the count of statistics, or the strings, because the hardware was not
accessed. When adding support for SERDES statistics, it is necessary
to access the hardware, to determine if a port is using the SERDES
interface. So add mutex lock/unlocks.
Signed-off-by: Andrew Lunn <andrew@lunn.ch>
Tested-by: Florian Fainelli <f.fainelli@gmail.com>
---
v2: Consolidate get_sset_count into one function
---
drivers/net/dsa/mv88e6xxx/chip.c | 11 +++++++++--
1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
index 8c9a30d1b06f..27ca0fcb1040 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.c
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
@@ -724,8 +724,12 @@ static void mv88e6xxx_get_strings(struct dsa_switch *ds, int port,
{
struct mv88e6xxx_chip *chip = ds->priv;
+ mutex_lock(&chip->reg_lock);
+
if (chip->info->ops->stats_get_strings)
chip->info->ops->stats_get_strings(chip, data);
+
+ mutex_unlock(&chip->reg_lock);
}
static int mv88e6xxx_stats_get_sset_count(struct mv88e6xxx_chip *chip,
@@ -757,11 +761,14 @@ static int mv88e6320_stats_get_sset_count(struct mv88e6xxx_chip *chip)
static int mv88e6xxx_get_sset_count(struct dsa_switch *ds, int port)
{
struct mv88e6xxx_chip *chip = ds->priv;
+ int ret = 0;
+ mutex_lock(&chip->reg_lock);
if (chip->info->ops->stats_get_sset_count)
- return chip->info->ops->stats_get_sset_count(chip);
+ ret = chip->info->ops->stats_get_sset_count(chip);
+ mutex_unlock(&chip->reg_lock);
- return 0;
+ return ret;
}
static void mv88e6xxx_stats_get_stats(struct mv88e6xxx_chip *chip, int port,
--
2.16.2
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH v2 net-next 3/5] net: dsa: mv88e6xxx: Allow the SERDES interfaces to have statistics
2018-03-01 1:02 [PATCH v2 net-next 0/5] Export SERDES stats via ethtool -S Andrew Lunn
2018-03-01 1:02 ` [PATCH v2 net-next 1/5] dsa: Pass the port to get_sset_count() Andrew Lunn
2018-03-01 1:02 ` [PATCH v2 net-next 2/5] net: dsa: mv88e6xxx: Hold mutex while doing stats operations Andrew Lunn
@ 2018-03-01 1:02 ` Andrew Lunn
2018-03-01 1:02 ` [PATCH v2 net-next 4/5] net: dsa: mv88e6xxx: Add helper to determining if port has SERDES Andrew Lunn
` (2 subsequent siblings)
5 siblings, 0 replies; 9+ messages in thread
From: Andrew Lunn @ 2018-03-01 1:02 UTC (permalink / raw)
To: David Miller; +Cc: netdev, Vivien Didelot, Florian Fainelli, Andrew Lunn
When gettting the number of statistics, the strings and the actual
statistics, call the SERDES ops if implemented. This means the stats
code needs to return the number of strings/stats they have placed into
the data, so that the SERDES strings/stats can follow on.
Signed-off-by: Andrew Lunn <andrew@lunn.ch>
Tested-by: Florian Fainelli <f.fainelli@gmail.com>
---
drivers/net/dsa/mv88e6xxx/chip.c | 76 +++++++++++++++++++++++++++-------------
drivers/net/dsa/mv88e6xxx/chip.h | 13 +++++--
2 files changed, 62 insertions(+), 27 deletions(-)
diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
index 27ca0fcb1040..243d274aace5 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.c
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
@@ -689,8 +689,8 @@ static uint64_t _mv88e6xxx_get_ethtool_stat(struct mv88e6xxx_chip *chip,
return value;
}
-static void mv88e6xxx_stats_get_strings(struct mv88e6xxx_chip *chip,
- uint8_t *data, int types)
+static int mv88e6xxx_stats_get_strings(struct mv88e6xxx_chip *chip,
+ uint8_t *data, int types)
{
struct mv88e6xxx_hw_stat *stat;
int i, j;
@@ -703,31 +703,39 @@ static void mv88e6xxx_stats_get_strings(struct mv88e6xxx_chip *chip,
j++;
}
}
+
+ return j;
}
-static void mv88e6095_stats_get_strings(struct mv88e6xxx_chip *chip,
- uint8_t *data)
+static int mv88e6095_stats_get_strings(struct mv88e6xxx_chip *chip,
+ uint8_t *data)
{
- mv88e6xxx_stats_get_strings(chip, data,
- STATS_TYPE_BANK0 | STATS_TYPE_PORT);
+ return mv88e6xxx_stats_get_strings(chip, data,
+ STATS_TYPE_BANK0 | STATS_TYPE_PORT);
}
-static void mv88e6320_stats_get_strings(struct mv88e6xxx_chip *chip,
- uint8_t *data)
+static int mv88e6320_stats_get_strings(struct mv88e6xxx_chip *chip,
+ uint8_t *data)
{
- mv88e6xxx_stats_get_strings(chip, data,
- STATS_TYPE_BANK0 | STATS_TYPE_BANK1);
+ return mv88e6xxx_stats_get_strings(chip, data,
+ STATS_TYPE_BANK0 | STATS_TYPE_BANK1);
}
static void mv88e6xxx_get_strings(struct dsa_switch *ds, int port,
uint8_t *data)
{
struct mv88e6xxx_chip *chip = ds->priv;
+ int count = 0;
mutex_lock(&chip->reg_lock);
if (chip->info->ops->stats_get_strings)
- chip->info->ops->stats_get_strings(chip, data);
+ count = chip->info->ops->stats_get_strings(chip, data);
+
+ if (chip->info->ops->serdes_get_strings) {
+ data += count * ETH_GSTRING_LEN;
+ chip->info->ops->serdes_get_strings(chip, port, data);
+ }
mutex_unlock(&chip->reg_lock);
}
@@ -761,19 +769,31 @@ static int mv88e6320_stats_get_sset_count(struct mv88e6xxx_chip *chip)
static int mv88e6xxx_get_sset_count(struct dsa_switch *ds, int port)
{
struct mv88e6xxx_chip *chip = ds->priv;
- int ret = 0;
+ int serdes_count = 0;
+ int count = 0;
mutex_lock(&chip->reg_lock);
if (chip->info->ops->stats_get_sset_count)
- ret = chip->info->ops->stats_get_sset_count(chip);
+ count = chip->info->ops->stats_get_sset_count(chip);
+ if (count < 0)
+ goto out;
+
+ if (chip->info->ops->serdes_get_sset_count)
+ serdes_count = chip->info->ops->serdes_get_sset_count(chip,
+ port);
+ if (serdes_count < 0)
+ count = serdes_count;
+ else
+ count += serdes_count;
+out:
mutex_unlock(&chip->reg_lock);
- return ret;
+ return count;
}
-static void mv88e6xxx_stats_get_stats(struct mv88e6xxx_chip *chip, int port,
- uint64_t *data, int types,
- u16 bank1_select, u16 histogram)
+static int mv88e6xxx_stats_get_stats(struct mv88e6xxx_chip *chip, int port,
+ uint64_t *data, int types,
+ u16 bank1_select, u16 histogram)
{
struct mv88e6xxx_hw_stat *stat;
int i, j;
@@ -790,18 +810,19 @@ static void mv88e6xxx_stats_get_stats(struct mv88e6xxx_chip *chip, int port,
j++;
}
}
+ return j;
}
-static void mv88e6095_stats_get_stats(struct mv88e6xxx_chip *chip, int port,
- uint64_t *data)
+static int mv88e6095_stats_get_stats(struct mv88e6xxx_chip *chip, int port,
+ uint64_t *data)
{
return mv88e6xxx_stats_get_stats(chip, port, data,
STATS_TYPE_BANK0 | STATS_TYPE_PORT,
0, MV88E6XXX_G1_STATS_OP_HIST_RX_TX);
}
-static void mv88e6320_stats_get_stats(struct mv88e6xxx_chip *chip, int port,
- uint64_t *data)
+static int mv88e6320_stats_get_stats(struct mv88e6xxx_chip *chip, int port,
+ uint64_t *data)
{
return mv88e6xxx_stats_get_stats(chip, port, data,
STATS_TYPE_BANK0 | STATS_TYPE_BANK1,
@@ -809,8 +830,8 @@ static void mv88e6320_stats_get_stats(struct mv88e6xxx_chip *chip, int port,
MV88E6XXX_G1_STATS_OP_HIST_RX_TX);
}
-static void mv88e6390_stats_get_stats(struct mv88e6xxx_chip *chip, int port,
- uint64_t *data)
+static int mv88e6390_stats_get_stats(struct mv88e6xxx_chip *chip, int port,
+ uint64_t *data)
{
return mv88e6xxx_stats_get_stats(chip, port, data,
STATS_TYPE_BANK0 | STATS_TYPE_BANK1,
@@ -821,8 +842,15 @@ static void mv88e6390_stats_get_stats(struct mv88e6xxx_chip *chip, int port,
static void mv88e6xxx_get_stats(struct mv88e6xxx_chip *chip, int port,
uint64_t *data)
{
+ int count = 0;
+
if (chip->info->ops->stats_get_stats)
- chip->info->ops->stats_get_stats(chip, port, data);
+ count = chip->info->ops->stats_get_stats(chip, port, data);
+
+ if (chip->info->ops->serdes_get_stats) {
+ data += count;
+ chip->info->ops->serdes_get_stats(chip, port, data);
+ }
}
static void mv88e6xxx_get_ethtool_stats(struct dsa_switch *ds, int port,
diff --git a/drivers/net/dsa/mv88e6xxx/chip.h b/drivers/net/dsa/mv88e6xxx/chip.h
index d6a1391dc268..e1ed1b7ca319 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.h
+++ b/drivers/net/dsa/mv88e6xxx/chip.h
@@ -386,9 +386,9 @@ struct mv88e6xxx_ops {
/* Return the number of strings describing statistics */
int (*stats_get_sset_count)(struct mv88e6xxx_chip *chip);
- void (*stats_get_strings)(struct mv88e6xxx_chip *chip, uint8_t *data);
- void (*stats_get_stats)(struct mv88e6xxx_chip *chip, int port,
- uint64_t *data);
+ int (*stats_get_strings)(struct mv88e6xxx_chip *chip, uint8_t *data);
+ int (*stats_get_stats)(struct mv88e6xxx_chip *chip, int port,
+ uint64_t *data);
int (*set_cpu_port)(struct mv88e6xxx_chip *chip, int port);
int (*set_egress_port)(struct mv88e6xxx_chip *chip, int port);
const struct mv88e6xxx_irq_ops *watchdog_ops;
@@ -398,6 +398,13 @@ struct mv88e6xxx_ops {
/* Power on/off a SERDES interface */
int (*serdes_power)(struct mv88e6xxx_chip *chip, int port, bool on);
+ /* Statistics from the SERDES interface */
+ int (*serdes_get_sset_count)(struct mv88e6xxx_chip *chip, int port);
+ void (*serdes_get_strings)(struct mv88e6xxx_chip *chip, int port,
+ uint8_t *data);
+ void (*serdes_get_stats)(struct mv88e6xxx_chip *chip, int port,
+ uint64_t *data);
+
/* VLAN Translation Unit operations */
int (*vtu_getnext)(struct mv88e6xxx_chip *chip,
struct mv88e6xxx_vtu_entry *entry);
--
2.16.2
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH v2 net-next 4/5] net: dsa: mv88e6xxx: Add helper to determining if port has SERDES
2018-03-01 1:02 [PATCH v2 net-next 0/5] Export SERDES stats via ethtool -S Andrew Lunn
` (2 preceding siblings ...)
2018-03-01 1:02 ` [PATCH v2 net-next 3/5] net: dsa: mv88e6xxx: Allow the SERDES interfaces to have statistics Andrew Lunn
@ 2018-03-01 1:02 ` Andrew Lunn
2018-03-01 1:02 ` [PATCH v2 net-next 5/5] net: dsa: mv88e6xxx: Get mv88e6352 SERDES statistics Andrew Lunn
2018-03-04 18:35 ` [PATCH v2 net-next 0/5] Export SERDES stats via ethtool -S David Miller
5 siblings, 0 replies; 9+ messages in thread
From: Andrew Lunn @ 2018-03-01 1:02 UTC (permalink / raw)
To: David Miller; +Cc: netdev, Vivien Didelot, Florian Fainelli, Andrew Lunn
Refactor the existing code. This helper will be used for SERDES
statistics.
Signed-off-by: Andrew Lunn <andrew@lunn.ch>
Tested-by: Florian Fainelli <f.fainelli@gmail.com>
---
v2: Use Boolean return value
---
drivers/net/dsa/mv88e6xxx/serdes.c | 22 +++++++++++++++++-----
1 file changed, 17 insertions(+), 5 deletions(-)
diff --git a/drivers/net/dsa/mv88e6xxx/serdes.c b/drivers/net/dsa/mv88e6xxx/serdes.c
index f3c01119b3d1..4487d18132a4 100644
--- a/drivers/net/dsa/mv88e6xxx/serdes.c
+++ b/drivers/net/dsa/mv88e6xxx/serdes.c
@@ -55,18 +55,30 @@ static int mv88e6352_serdes_power_set(struct mv88e6xxx_chip *chip, bool on)
return err;
}
-int mv88e6352_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on)
+static bool mv88e6352_port_has_serdes(struct mv88e6xxx_chip *chip, int port)
{
- int err;
u8 cmode;
+ int err;
err = mv88e6xxx_port_get_cmode(chip, port, &cmode);
- if (err)
- return err;
+ if (err) {
+ dev_err(chip->dev, "failed to read cmode\n");
+ return 0;
+ }
if ((cmode == MV88E6XXX_PORT_STS_CMODE_100BASE_X) ||
(cmode == MV88E6XXX_PORT_STS_CMODE_1000BASE_X) ||
- (cmode == MV88E6XXX_PORT_STS_CMODE_SGMII)) {
+ (cmode == MV88E6XXX_PORT_STS_CMODE_SGMII))
+ return 1;
+
+ return 0;
+}
+
+int mv88e6352_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on)
+{
+ int err;
+
+ if (mv88e6352_port_has_serdes(chip, port)) {
err = mv88e6352_serdes_power_set(chip, on);
if (err < 0)
return err;
--
2.16.2
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH v2 net-next 5/5] net: dsa: mv88e6xxx: Get mv88e6352 SERDES statistics
2018-03-01 1:02 [PATCH v2 net-next 0/5] Export SERDES stats via ethtool -S Andrew Lunn
` (3 preceding siblings ...)
2018-03-01 1:02 ` [PATCH v2 net-next 4/5] net: dsa: mv88e6xxx: Add helper to determining if port has SERDES Andrew Lunn
@ 2018-03-01 1:02 ` Andrew Lunn
2018-03-02 3:10 ` Andrew Lunn
2018-03-04 18:35 ` [PATCH v2 net-next 0/5] Export SERDES stats via ethtool -S David Miller
5 siblings, 1 reply; 9+ messages in thread
From: Andrew Lunn @ 2018-03-01 1:02 UTC (permalink / raw)
To: David Miller; +Cc: netdev, Vivien Didelot, Florian Fainelli, Andrew Lunn
Add support for reading the SERDES statistics of the mv88e8352, using
the standard ethtool -S option. The SERDES interface can be mapped to
either port 4 or 5, so only return statistics on those ports, if the
SERDES interface is in use.
The counters are reset on read, so need to be accumulated. Add a per
port structure to hold the stats counters. The 6352 only has a single
SERDES interface and so only one port will using the newly added
array. However the 6390 family has as many SERDES interfaces as ports,
each with statistics counters. Also, PTP has a number of counters per
port which will also need accumulating.
Signed-off-by: Andrew Lunn <andrew@lunn.ch>
Tested-by: Florian Fainelli <f.fainelli@gmail.com>
---
v2: rename sizeof_stat to size
remove extra space
---
drivers/net/dsa/mv88e6xxx/chip.c | 7 +++-
drivers/net/dsa/mv88e6xxx/chip.h | 10 ++++-
drivers/net/dsa/mv88e6xxx/serdes.c | 84 ++++++++++++++++++++++++++++++++++++++
drivers/net/dsa/mv88e6xxx/serdes.h | 6 ++-
4 files changed, 103 insertions(+), 4 deletions(-)
diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
index 243d274aace5..cfd53632a655 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.c
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
@@ -666,7 +666,7 @@ static uint64_t _mv88e6xxx_get_ethtool_stat(struct mv88e6xxx_chip *chip,
return UINT64_MAX;
low = reg;
- if (s->sizeof_stat == 4) {
+ if (s->size == 4) {
err = mv88e6xxx_port_read(chip, port, s->reg + 1, ®);
if (err)
return UINT64_MAX;
@@ -679,7 +679,7 @@ static uint64_t _mv88e6xxx_get_ethtool_stat(struct mv88e6xxx_chip *chip,
case STATS_TYPE_BANK0:
reg |= s->reg | histogram;
mv88e6xxx_g1_stats_read(chip, reg, &low);
- if (s->sizeof_stat == 8)
+ if (s->size == 8)
mv88e6xxx_g1_stats_read(chip, reg + 1, &high);
break;
default:
@@ -3225,6 +3225,9 @@ static const struct mv88e6xxx_ops mv88e6352_ops = {
.serdes_power = mv88e6352_serdes_power,
.gpio_ops = &mv88e6352_gpio_ops,
.avb_ops = &mv88e6352_avb_ops,
+ .serdes_get_sset_count = mv88e6352_serdes_get_sset_count,
+ .serdes_get_strings = mv88e6352_serdes_get_strings,
+ .serdes_get_stats = mv88e6352_serdes_get_stats,
};
static const struct mv88e6xxx_ops mv88e6390_ops = {
diff --git a/drivers/net/dsa/mv88e6xxx/chip.h b/drivers/net/dsa/mv88e6xxx/chip.h
index e1ed1b7ca319..26b9a618cdee 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.h
+++ b/drivers/net/dsa/mv88e6xxx/chip.h
@@ -191,6 +191,10 @@ struct mv88e6xxx_port_hwtstamp {
struct hwtstamp_config tstamp_config;
};
+struct mv88e6xxx_port {
+ u64 serdes_stats[2];
+};
+
struct mv88e6xxx_chip {
const struct mv88e6xxx_info *info;
@@ -244,6 +248,7 @@ struct mv88e6xxx_chip {
int irq;
int device_irq;
int watchdog_irq;
+
int atu_prob_irq;
int vtu_prob_irq;
struct kthread_worker *kworker;
@@ -268,6 +273,9 @@ struct mv88e6xxx_chip {
/* Per-port timestamping resources. */
struct mv88e6xxx_port_hwtstamp port_hwtstamp[DSA_MAX_PORTS];
+
+ /* Array of port structures. */
+ struct mv88e6xxx_port ports[DSA_MAX_PORTS];
};
struct mv88e6xxx_bus_ops {
@@ -469,7 +477,7 @@ struct mv88e6xxx_avb_ops {
struct mv88e6xxx_hw_stat {
char string[ETH_GSTRING_LEN];
- int sizeof_stat;
+ size_t size;
int reg;
int type;
};
diff --git a/drivers/net/dsa/mv88e6xxx/serdes.c b/drivers/net/dsa/mv88e6xxx/serdes.c
index 4487d18132a4..4756969c1546 100644
--- a/drivers/net/dsa/mv88e6xxx/serdes.c
+++ b/drivers/net/dsa/mv88e6xxx/serdes.c
@@ -87,6 +87,90 @@ int mv88e6352_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on)
return 0;
}
+struct mv88e6352_serdes_hw_stat {
+ char string[ETH_GSTRING_LEN];
+ int sizeof_stat;
+ int reg;
+};
+
+static struct mv88e6352_serdes_hw_stat mv88e6352_serdes_hw_stats[] = {
+ { "serdes_fibre_rx_error", 16, 21 },
+ { "serdes_PRBS_error", 32, 24 },
+};
+
+int mv88e6352_serdes_get_sset_count(struct mv88e6xxx_chip *chip, int port)
+{
+ if (mv88e6352_port_has_serdes(chip, port))
+ return ARRAY_SIZE(mv88e6352_serdes_hw_stats);
+
+ return 0;
+}
+
+void mv88e6352_serdes_get_strings(struct mv88e6xxx_chip *chip,
+ int port, uint8_t *data)
+{
+ struct mv88e6352_serdes_hw_stat *stat;
+ int i;
+
+ if (!mv88e6352_port_has_serdes(chip, port))
+ return;
+
+ for (i = 0; i < ARRAY_SIZE(mv88e6352_serdes_hw_stats); i++) {
+ stat = &mv88e6352_serdes_hw_stats[i];
+ memcpy(data + i * ETH_GSTRING_LEN, stat->string,
+ ETH_GSTRING_LEN);
+ }
+}
+
+static uint64_t mv88e6352_serdes_get_stat(struct mv88e6xxx_chip *chip,
+ struct mv88e6352_serdes_hw_stat *stat)
+{
+ u64 val = 0;
+ u16 reg;
+ int err;
+
+ err = mv88e6352_serdes_read(chip, stat->reg, ®);
+ if (err) {
+ dev_err(chip->dev, "failed to read statistic\n");
+ return 0;
+ }
+
+ val = reg;
+
+ if (stat->sizeof_stat == 32) {
+ err = mv88e6352_serdes_read(chip, stat->reg + 1, ®);
+ if (err) {
+ dev_err(chip->dev, "failed to read statistic\n");
+ return 0;
+ }
+ val = val << 16 | reg;
+ }
+
+ return val;
+}
+
+void mv88e6352_serdes_get_stats(struct mv88e6xxx_chip *chip, int port,
+ uint64_t *data)
+{
+ struct mv88e6xxx_port *mv88e6xxx_port = &chip->ports[port];
+ struct mv88e6352_serdes_hw_stat *stat;
+ u64 value;
+ int i;
+
+ if (!mv88e6352_port_has_serdes(chip, port))
+ return;
+
+ BUILD_BUG_ON(ARRAY_SIZE(mv88e6352_serdes_hw_stats) >
+ ARRAY_SIZE(mv88e6xxx_port->serdes_stats));
+
+ for (i = 0; i < ARRAY_SIZE(mv88e6352_serdes_hw_stats); i++) {
+ stat = &mv88e6352_serdes_hw_stats[i];
+ value = mv88e6352_serdes_get_stat(chip, stat);
+ mv88e6xxx_port->serdes_stats[i] += value;
+ data[i] = mv88e6xxx_port->serdes_stats[i];
+ }
+}
+
/* Set the power on/off for 10GBASE-R and 10GBASE-X4/X2 */
static int mv88e6390_serdes_10g(struct mv88e6xxx_chip *chip, int addr, bool on)
{
diff --git a/drivers/net/dsa/mv88e6xxx/serdes.h b/drivers/net/dsa/mv88e6xxx/serdes.h
index 5c1cd6d8e9a5..641baa75f910 100644
--- a/drivers/net/dsa/mv88e6xxx/serdes.h
+++ b/drivers/net/dsa/mv88e6xxx/serdes.h
@@ -44,5 +44,9 @@
int mv88e6352_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on);
int mv88e6390_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on);
-
+int mv88e6352_serdes_get_sset_count(struct mv88e6xxx_chip *chip, int port);
+void mv88e6352_serdes_get_strings(struct mv88e6xxx_chip *chip,
+ int port, uint8_t *data);
+void mv88e6352_serdes_get_stats(struct mv88e6xxx_chip *chip, int port,
+ uint64_t *data);
#endif
--
2.16.2
^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH v2 net-next 5/5] net: dsa: mv88e6xxx: Get mv88e6352 SERDES statistics
2018-03-01 1:02 ` [PATCH v2 net-next 5/5] net: dsa: mv88e6xxx: Get mv88e6352 SERDES statistics Andrew Lunn
@ 2018-03-02 3:10 ` Andrew Lunn
2018-03-04 18:48 ` Florian Fainelli
0 siblings, 1 reply; 9+ messages in thread
From: Andrew Lunn @ 2018-03-02 3:10 UTC (permalink / raw)
To: David Miller; +Cc: netdev, Vivien Didelot, Florian Fainelli
> +void mv88e6352_serdes_get_strings(struct mv88e6xxx_chip *chip,
> + int port, uint8_t *data)
> +{
> + struct mv88e6352_serdes_hw_stat *stat;
> + int i;
> +
> + if (!mv88e6352_port_has_serdes(chip, port))
> + return;
> +
> + for (i = 0; i < ARRAY_SIZE(mv88e6352_serdes_hw_stats); i++) {
> + stat = &mv88e6352_serdes_hw_stats[i];
> + memcpy(data + i * ETH_GSTRING_LEN, stat->string,
> + ETH_GSTRING_LEN);
This has the same problem as Florain just fixed, using memcpy instead
of strcnpy. I will spin a new version with this fixed.
Andrew
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v2 net-next 0/5] Export SERDES stats via ethtool -S
2018-03-01 1:02 [PATCH v2 net-next 0/5] Export SERDES stats via ethtool -S Andrew Lunn
` (4 preceding siblings ...)
2018-03-01 1:02 ` [PATCH v2 net-next 5/5] net: dsa: mv88e6xxx: Get mv88e6352 SERDES statistics Andrew Lunn
@ 2018-03-04 18:35 ` David Miller
5 siblings, 0 replies; 9+ messages in thread
From: David Miller @ 2018-03-04 18:35 UTC (permalink / raw)
To: andrew; +Cc: netdev, vivien.didelot, f.fainelli
From: Andrew Lunn <andrew@lunn.ch>
Date: Thu, 1 Mar 2018 02:02:26 +0100
> The mv88e6352 family has a SERDES interface which can be used for
> example to connect to SFF/SFP modules. This interface has a couple of
> statistics counters. Add support for including these counters in the
> output of ethtool -S.
Series applied, thanks Andrew.
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v2 net-next 5/5] net: dsa: mv88e6xxx: Get mv88e6352 SERDES statistics
2018-03-02 3:10 ` Andrew Lunn
@ 2018-03-04 18:48 ` Florian Fainelli
0 siblings, 0 replies; 9+ messages in thread
From: Florian Fainelli @ 2018-03-04 18:48 UTC (permalink / raw)
To: Andrew Lunn, David Miller; +Cc: netdev, Vivien Didelot
On 03/01/2018 07:10 PM, Andrew Lunn wrote:
>> +void mv88e6352_serdes_get_strings(struct mv88e6xxx_chip *chip,
>> + int port, uint8_t *data)
>> +{
>> + struct mv88e6352_serdes_hw_stat *stat;
>> + int i;
>> +
>> + if (!mv88e6352_port_has_serdes(chip, port))
>> + return;
>> +
>> + for (i = 0; i < ARRAY_SIZE(mv88e6352_serdes_hw_stats); i++) {
>> + stat = &mv88e6352_serdes_hw_stats[i];
>> + memcpy(data + i * ETH_GSTRING_LEN, stat->string,
>> + ETH_GSTRING_LEN);
>
> This has the same problem as Florain just fixed, using memcpy instead
> of strcnpy. I will spin a new version with this fixed.
This is fine actually, your strings are defined as an array of
ETH_GSTRING_LEN characters so while the memcpy() is a bit inefficient
and will typically lead to copying a lot of NUL bytes, this won't be
causing out of bounds accesses though.
--
Florian
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2018-03-04 18:48 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2018-03-01 1:02 [PATCH v2 net-next 0/5] Export SERDES stats via ethtool -S Andrew Lunn
2018-03-01 1:02 ` [PATCH v2 net-next 1/5] dsa: Pass the port to get_sset_count() Andrew Lunn
2018-03-01 1:02 ` [PATCH v2 net-next 2/5] net: dsa: mv88e6xxx: Hold mutex while doing stats operations Andrew Lunn
2018-03-01 1:02 ` [PATCH v2 net-next 3/5] net: dsa: mv88e6xxx: Allow the SERDES interfaces to have statistics Andrew Lunn
2018-03-01 1:02 ` [PATCH v2 net-next 4/5] net: dsa: mv88e6xxx: Add helper to determining if port has SERDES Andrew Lunn
2018-03-01 1:02 ` [PATCH v2 net-next 5/5] net: dsa: mv88e6xxx: Get mv88e6352 SERDES statistics Andrew Lunn
2018-03-02 3:10 ` Andrew Lunn
2018-03-04 18:48 ` Florian Fainelli
2018-03-04 18:35 ` [PATCH v2 net-next 0/5] Export SERDES stats via ethtool -S 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).