From 5d246e343440ee4915109dac66543d02d71ca900 Mon Sep 17 00:00:00 2001
From: Xiaoliang Yang <xiaoliang.yang_1@nxp.com>
Date: Tue, 11 Feb 2020 15:33:46 +0800
Subject: [PATCH] LF-457: ocelot: tsn: clean preempt interrupt status

The INTB interrupt is used both for 1588 interrupt and preemption status
change interrupt on each port. So clean preempt status interrupt in IRQ
handle function. Without handling it, driver may get interrupt storm.

Signed-off-by: Xiaoliang Yang <xiaoliang.yang_1@nxp.com>
Reviewed-by: Po Liu <Po.Liu@nxp.com>
---
 drivers/net/dsa/ocelot/felix.c         |  5 +----
 drivers/net/ethernet/mscc/ocelot_tsn.c | 14 ++++++++++++++
 include/soc/mscc/ocelot.h              |  1 +
 3 files changed, 16 insertions(+), 4 deletions(-)

--- a/drivers/net/dsa/ocelot/felix.c
+++ b/drivers/net/dsa/ocelot/felix.c
@@ -688,12 +688,9 @@ static irqreturn_t felix_irq_handler(int
 
 	/* The INTB interrupt is used for both PTP TX timestamp interrupt
 	 * and preemption status change interrupt on each port.
-	 *
-	 * - Get txtstamp if have
-	 * - TODO: handle preemption. Without handling it, driver may get
-	 *   interrupt storm.
 	 */
 
+	ocelot_preempt_irq_clean(ocelot);
 	ocelot_get_txtstamp(ocelot);
 
 	return IRQ_HANDLED;
--- a/drivers/net/ethernet/mscc/ocelot_tsn.c
+++ b/drivers/net/ethernet/mscc/ocelot_tsn.c
@@ -1570,3 +1570,17 @@ int ocelot_dscp_set(struct ocelot *ocelo
 
 	return 0;
 }
+
+void ocelot_preempt_irq_clean(struct ocelot *ocelot)
+{
+	struct ocelot_port *ocelot_port;
+	int port;
+	u32 val;
+
+	val = DEV_GMII_MM_STATISTICS_MM_STATUS_PRMPT_ACTIVE_STICKY;
+	for (port = 0; port < ocelot->num_phys_ports; port++) {
+		ocelot_port = ocelot->ports[port];
+		ocelot_port_rmwl(ocelot_port, val, val,
+				 DEV_GMII_MM_STATISTICS_MM_STATUS);
+	}
+}
--- a/include/soc/mscc/ocelot.h
+++ b/include/soc/mscc/ocelot.h
@@ -592,4 +592,5 @@ int ocelot_rtag_parse_enable(struct ocel
 int ocelot_dscp_set(struct ocelot *ocelot, int port,
 		    bool enable, const u8 dscp_ix,
 		    struct tsn_qos_switch_dscp_conf *c);
+void ocelot_preempt_irq_clean(struct ocelot *ocelot);
 #endif
