236 lines
7.8 KiB
Diff
236 lines
7.8 KiB
Diff
Index: include/uapi/linux/ethtool.h
|
|
===================================================================
|
|
--- include/uapi/linux/ethtool.h
|
|
+++ linux-imx/include/uapi/linux/ethtool.h
|
|
@@ -1377,6 +1377,7 @@ enum ethtool_fec_config_bits {
|
|
#define ETHTOOL_PHY_STUNABLE 0x0000004f /* Set PHY tunable configuration */
|
|
#define ETHTOOL_GFECPARAM 0x00000050 /* Get FEC settings */
|
|
#define ETHTOOL_SFECPARAM 0x00000051 /* Set FEC settings */
|
|
+#define ETHTOOL_CSTATS 0x00000052 /* Clear statistics */
|
|
|
|
/* compatibility with older code */
|
|
#define SPARC_ETH_GSET ETHTOOL_GSET
|
|
Index: net/core/ethtool.c
|
|
===================================================================
|
|
--- net/core/ethtool.c
|
|
+++ linux-imx/net/core/ethtool.c
|
|
@@ -1938,6 +1938,15 @@ static int ethtool_get_stats(struct net_
|
|
return ret;
|
|
}
|
|
|
|
+static int ethtool_clear_stats(struct net_device *dev)
|
|
+{
|
|
+ if (!dev->ethtool_ops->clear_ethtool_stats)
|
|
+ return -EOPNOTSUPP;
|
|
+
|
|
+ dev->ethtool_ops->clear_ethtool_stats(dev);
|
|
+ return 0;
|
|
+}
|
|
+
|
|
static int ethtool_get_phy_stats(struct net_device *dev, void __user *useraddr)
|
|
{
|
|
struct ethtool_stats stats;
|
|
@@ -2577,6 +2586,7 @@ int dev_ethtool(struct net *net, struct
|
|
case ETHTOOL_GSSET_INFO:
|
|
case ETHTOOL_GSTRINGS:
|
|
case ETHTOOL_GSTATS:
|
|
+ case ETHTOOL_CSTATS:
|
|
case ETHTOOL_GPHYSTATS:
|
|
case ETHTOOL_GTSO:
|
|
case ETHTOOL_GPERMADDR:
|
|
@@ -2688,6 +2698,9 @@ int dev_ethtool(struct net *net, struct
|
|
case ETHTOOL_GSTATS:
|
|
rc = ethtool_get_stats(dev, useraddr);
|
|
break;
|
|
+ case ETHTOOL_CSTATS:
|
|
+ rc = ethtool_clear_stats(dev);
|
|
+ break;
|
|
case ETHTOOL_GPERMADDR:
|
|
rc = ethtool_get_perm_addr(dev, useraddr);
|
|
break;
|
|
Index: include/linux/ethtool.h
|
|
===================================================================
|
|
--- include/linux/ethtool.h
|
|
+++ linux-imx/include/linux/ethtool.h
|
|
@@ -347,6 +347,7 @@ struct ethtool_ops {
|
|
int (*set_phys_id)(struct net_device *, enum ethtool_phys_id_state);
|
|
void (*get_ethtool_stats)(struct net_device *,
|
|
struct ethtool_stats *, u64 *);
|
|
+ void (*clear_ethtool_stats)(struct net_device *);
|
|
int (*begin)(struct net_device *);
|
|
void (*complete)(struct net_device *);
|
|
u32 (*get_priv_flags)(struct net_device *);
|
|
Index: net/dsa/slave.c
|
|
===================================================================
|
|
--- net/dsa/slave.c
|
|
+++ linux-imx/net/dsa/slave.c
|
|
@@ -1019,6 +1019,30 @@ static int dsa_slave_set_rxnfc(struct ne
|
|
return ds->ops->set_rxnfc(ds, p->dp->index, nfc);
|
|
}
|
|
|
|
+static void dsa_slave_clear_ethtool_stats(struct net_device *dev)
|
|
+{
|
|
+ struct dsa_slave_priv *p = netdev_priv(dev);
|
|
+ struct dsa_switch *ds = p->dp->ds;
|
|
+ struct pcpu_sw_netstats *s;
|
|
+ unsigned int start;
|
|
+ int i;
|
|
+
|
|
+ memset(&dev->stats, 0, sizeof(struct net_device_stats));
|
|
+ for_each_possible_cpu(i) {
|
|
+ s = per_cpu_ptr(p->stats64, i);
|
|
+ do {
|
|
+ start = u64_stats_fetch_begin_irq(&s->syncp);
|
|
+ s->tx_packets = 0L;
|
|
+ s->tx_bytes = 0L;
|
|
+ s->rx_packets = 0L;
|
|
+ s->rx_bytes = 0L;
|
|
+ } while (u64_stats_fetch_retry_irq(&s->syncp, start));
|
|
+ }
|
|
+
|
|
+ if (ds->ops->clear_ethtool_stats)
|
|
+ ds->ops->clear_ethtool_stats(ds, p->dp->index);
|
|
+}
|
|
+
|
|
static const struct ethtool_ops dsa_slave_ethtool_ops = {
|
|
.get_drvinfo = dsa_slave_get_drvinfo,
|
|
.get_regs_len = dsa_slave_get_regs_len,
|
|
@@ -1039,6 +1063,7 @@ static const struct ethtool_ops dsa_slav
|
|
.set_link_ksettings = dsa_slave_set_link_ksettings,
|
|
.get_rxnfc = dsa_slave_get_rxnfc,
|
|
.set_rxnfc = dsa_slave_set_rxnfc,
|
|
+ .clear_ethtool_stats = dsa_slave_clear_ethtool_stats,
|
|
};
|
|
|
|
static const struct net_device_ops dsa_slave_netdev_ops = {
|
|
Index: drivers/net/dsa/mv88e6xxx/chip.h
|
|
===================================================================
|
|
--- drivers/net/dsa/mv88e6xxx/chip.h
|
|
+++ linux-imx/drivers/net/dsa/mv88e6xxx/chip.h
|
|
@@ -330,6 +330,7 @@ struct mv88e6xxx_ops {
|
|
void (*stats_get_strings)(struct mv88e6xxx_chip *chip, uint8_t *data);
|
|
void (*stats_get_stats)(struct mv88e6xxx_chip *chip, int port,
|
|
uint64_t *data);
|
|
+ void (*stats_clear_stats)(struct mv88e6xxx_chip *chip, int port);
|
|
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;
|
|
Index: include/net/dsa.h
|
|
===================================================================
|
|
--- include/net/dsa.h
|
|
+++ linux-imx/include/net/dsa.h
|
|
@@ -320,6 +320,7 @@ struct dsa_switch_ops {
|
|
void (*get_ethtool_stats)(struct dsa_switch *ds,
|
|
int port, uint64_t *data);
|
|
int (*get_sset_count)(struct dsa_switch *ds);
|
|
+ void (*clear_ethtool_stats)(struct dsa_switch *ds, int port);
|
|
|
|
/*
|
|
* ethtool Wake-on-LAN
|
|
Index: drivers/net/dsa/mv88e6xxx/chip.c
|
|
===================================================================
|
|
--- drivers/net/dsa/mv88e6xxx/chip.c
|
|
+++ linux-imx/drivers/net/dsa/mv88e6xxx/chip.c
|
|
@@ -648,6 +648,46 @@ static void mv88e6xxx_get_ethtool_stats(
|
|
mutex_unlock(&chip->reg_lock);
|
|
}
|
|
|
|
+static void mv88e6xxx_stats_clear_stats(struct mv88e6xxx_chip *chip, int port)
|
|
+{
|
|
+ u16 histogram = 0;
|
|
+ int err;
|
|
+
|
|
+ err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_STATS_OP, &histogram);
|
|
+ if (err)
|
|
+ return;
|
|
+
|
|
+ histogram &= 0xC00;
|
|
+ /* Clear the statistics counters for given port */
|
|
+ err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_STATS_OP,
|
|
+ MV88E6XXX_G1_STATS_OP_BUSY |
|
|
+ MV88E6XXX_G1_STATS_OP_FLUSH_PORT |
|
|
+ (port +1) << 5 |
|
|
+ histogram);
|
|
+}
|
|
+
|
|
+static void mv88e6250_stats_clear_stats(struct mv88e6xxx_chip *chip, int port)
|
|
+{
|
|
+ mv88e6xxx_stats_clear_stats(chip, port);
|
|
+}
|
|
+
|
|
+static void mv88e6xxx_clear_stats(struct mv88e6xxx_chip *chip, int port)
|
|
+{
|
|
+ if (chip->info->ops->stats_clear_stats)
|
|
+ chip->info->ops->stats_clear_stats(chip, port);
|
|
+}
|
|
+
|
|
+static void mv88e6xxx_clear_ethtool_stats(struct dsa_switch *ds, int port)
|
|
+{
|
|
+ struct mv88e6xxx_chip *chip = ds->priv;
|
|
+
|
|
+ mutex_lock(&chip->reg_lock);
|
|
+
|
|
+ mv88e6xxx_clear_stats(chip, port);
|
|
+
|
|
+ mutex_unlock(&chip->reg_lock);
|
|
+}
|
|
+
|
|
static int mv88e6xxx_stats_set_histogram(struct mv88e6xxx_chip *chip)
|
|
{
|
|
if (chip->info->ops->stats_set_histogram)
|
|
@@ -2801,6 +2841,7 @@ static const struct mv88e6xxx_ops mv88e6
|
|
.stats_get_sset_count = mv88e6250_stats_get_sset_count,
|
|
.stats_get_strings = mv88e6250_stats_get_strings,
|
|
.stats_get_stats = mv88e6250_stats_get_stats,
|
|
+ .stats_clear_stats = mv88e6250_stats_clear_stats,
|
|
.set_cpu_port = mv88e6095_g1_set_cpu_port,
|
|
.set_egress_port = mv88e6095_g1_set_egress_port,
|
|
.watchdog_ops = &mv88e6250_watchdog_ops,
|
|
@@ -3837,6 +3878,7 @@ static const struct dsa_switch_ops mv88e
|
|
.adjust_link = mv88e6xxx_adjust_link,
|
|
.get_strings = mv88e6xxx_get_strings,
|
|
.get_ethtool_stats = mv88e6xxx_get_ethtool_stats,
|
|
+ .clear_ethtool_stats = mv88e6xxx_clear_ethtool_stats,
|
|
.get_sset_count = mv88e6xxx_get_sset_count,
|
|
.port_enable = mv88e6xxx_port_enable,
|
|
.port_disable = mv88e6xxx_port_disable,
|
|
Index: net/8021q/vlan_dev.c
|
|
===================================================================
|
|
--- net/8021q/vlan_dev.c
|
|
+++ linux-imx/net/8021q/vlan_dev.c
|
|
@@ -681,6 +681,26 @@ static int vlan_ethtool_get_ts_info(stru
|
|
return 0;
|
|
}
|
|
|
|
+static void vlan_clear_ethtool_stats(struct net_device *dev)
|
|
+{
|
|
+ struct vlan_pcpu_stats *p;
|
|
+ unsigned int start;
|
|
+ int i;
|
|
+
|
|
+ memset(&dev->stats, 0, sizeof(struct net_device_stats));
|
|
+ for_each_possible_cpu(i) {
|
|
+ p = per_cpu_ptr(vlan_dev_priv(dev)->vlan_pcpu_stats, i);
|
|
+ do {
|
|
+ start = u64_stats_fetch_begin_irq(&p->syncp);
|
|
+ p->rx_packets = 0L;
|
|
+ p->rx_bytes = 0L;
|
|
+ p->rx_multicast = 0L;
|
|
+ p->tx_packets = 0L;
|
|
+ p->tx_bytes = 0L;
|
|
+ } while (u64_stats_fetch_retry_irq(&p->syncp, start));
|
|
+ }
|
|
+}
|
|
+
|
|
static void vlan_dev_get_stats64(struct net_device *dev,
|
|
struct rtnl_link_stats64 *stats)
|
|
{
|
|
@@ -771,6 +791,7 @@ static const struct ethtool_ops vlan_eth
|
|
.get_drvinfo = vlan_ethtool_get_drvinfo,
|
|
.get_link = ethtool_op_get_link,
|
|
.get_ts_info = vlan_ethtool_get_ts_info,
|
|
+ .clear_ethtool_stats = vlan_clear_ethtool_stats,
|
|
};
|
|
|
|
static const struct net_device_ops vlan_netdev_ops = {
|