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 = {