180 lines
		
	
	
		
			5.8 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			180 lines
		
	
	
		
			5.8 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
From: Gregory CLEMENT <gregory.clement@free-electrons.com>
 | 
						|
Date: Thu, 4 Feb 2016 22:09:27 +0100
 | 
						|
Subject: [PATCH] net: mvneta: Modify the queue related fields from each cpu
 | 
						|
 | 
						|
In the MVNETA_INTR_* registers, the queues related fields are per cpu,
 | 
						|
according to the datasheet (comment in [] are added by me):
 | 
						|
"In a multi-CPU system, bits of RX[or TX] queues for which the access by
 | 
						|
the reading[or writing] CPU is disabled are read as 0, and cannot be
 | 
						|
cleared[or written]."
 | 
						|
 | 
						|
That means that each time we want to manipulate these bits we had to do
 | 
						|
it on each cpu and not only on the current cpu.
 | 
						|
 | 
						|
Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
 | 
						|
Signed-off-by: David S. Miller <davem@davemloft.net>
 | 
						|
---
 | 
						|
 | 
						|
--- a/drivers/net/ethernet/marvell/mvneta.c
 | 
						|
+++ b/drivers/net/ethernet/marvell/mvneta.c
 | 
						|
@@ -1036,6 +1036,43 @@ static void mvneta_set_autoneg(struct mv
 | 
						|
 	}
 | 
						|
 }
 | 
						|
 
 | 
						|
+static void mvneta_percpu_unmask_interrupt(void *arg)
 | 
						|
+{
 | 
						|
+	struct mvneta_port *pp = arg;
 | 
						|
+
 | 
						|
+	/* All the queue are unmasked, but actually only the ones
 | 
						|
+	 * mapped to this CPU will be unmasked
 | 
						|
+	 */
 | 
						|
+	mvreg_write(pp, MVNETA_INTR_NEW_MASK,
 | 
						|
+		    MVNETA_RX_INTR_MASK_ALL |
 | 
						|
+		    MVNETA_TX_INTR_MASK_ALL |
 | 
						|
+		    MVNETA_MISCINTR_INTR_MASK);
 | 
						|
+}
 | 
						|
+
 | 
						|
+static void mvneta_percpu_mask_interrupt(void *arg)
 | 
						|
+{
 | 
						|
+	struct mvneta_port *pp = arg;
 | 
						|
+
 | 
						|
+	/* All the queue are masked, but actually only the ones
 | 
						|
+	 * mapped to this CPU will be masked
 | 
						|
+	 */
 | 
						|
+	mvreg_write(pp, MVNETA_INTR_NEW_MASK, 0);
 | 
						|
+	mvreg_write(pp, MVNETA_INTR_OLD_MASK, 0);
 | 
						|
+	mvreg_write(pp, MVNETA_INTR_MISC_MASK, 0);
 | 
						|
+}
 | 
						|
+
 | 
						|
+static void mvneta_percpu_clear_intr_cause(void *arg)
 | 
						|
+{
 | 
						|
+	struct mvneta_port *pp = arg;
 | 
						|
+
 | 
						|
+	/* All the queue are cleared, but actually only the ones
 | 
						|
+	 * mapped to this CPU will be cleared
 | 
						|
+	 */
 | 
						|
+	mvreg_write(pp, MVNETA_INTR_NEW_CAUSE, 0);
 | 
						|
+	mvreg_write(pp, MVNETA_INTR_MISC_CAUSE, 0);
 | 
						|
+	mvreg_write(pp, MVNETA_INTR_OLD_CAUSE, 0);
 | 
						|
+}
 | 
						|
+
 | 
						|
 /* This method sets defaults to the NETA port:
 | 
						|
  *	Clears interrupt Cause and Mask registers.
 | 
						|
  *	Clears all MAC tables.
 | 
						|
@@ -1053,14 +1090,10 @@ static void mvneta_defaults_set(struct m
 | 
						|
 	int max_cpu = num_present_cpus();
 | 
						|
 
 | 
						|
 	/* Clear all Cause registers */
 | 
						|
-	mvreg_write(pp, MVNETA_INTR_NEW_CAUSE, 0);
 | 
						|
-	mvreg_write(pp, MVNETA_INTR_OLD_CAUSE, 0);
 | 
						|
-	mvreg_write(pp, MVNETA_INTR_MISC_CAUSE, 0);
 | 
						|
+	on_each_cpu(mvneta_percpu_clear_intr_cause, pp, true);
 | 
						|
 
 | 
						|
 	/* Mask all interrupts */
 | 
						|
-	mvreg_write(pp, MVNETA_INTR_NEW_MASK, 0);
 | 
						|
-	mvreg_write(pp, MVNETA_INTR_OLD_MASK, 0);
 | 
						|
-	mvreg_write(pp, MVNETA_INTR_MISC_MASK, 0);
 | 
						|
+	on_each_cpu(mvneta_percpu_mask_interrupt, pp, true);
 | 
						|
 	mvreg_write(pp, MVNETA_INTR_ENABLE, 0);
 | 
						|
 
 | 
						|
 	/* Enable MBUS Retry bit16 */
 | 
						|
@@ -2526,31 +2559,6 @@ static int mvneta_setup_txqs(struct mvne
 | 
						|
 	return 0;
 | 
						|
 }
 | 
						|
 
 | 
						|
-static void mvneta_percpu_unmask_interrupt(void *arg)
 | 
						|
-{
 | 
						|
-	struct mvneta_port *pp = arg;
 | 
						|
-
 | 
						|
-	/* All the queue are unmasked, but actually only the ones
 | 
						|
-	 * maped to this CPU will be unmasked
 | 
						|
-	 */
 | 
						|
-	mvreg_write(pp, MVNETA_INTR_NEW_MASK,
 | 
						|
-		    MVNETA_RX_INTR_MASK_ALL |
 | 
						|
-		    MVNETA_TX_INTR_MASK_ALL |
 | 
						|
-		    MVNETA_MISCINTR_INTR_MASK);
 | 
						|
-}
 | 
						|
-
 | 
						|
-static void mvneta_percpu_mask_interrupt(void *arg)
 | 
						|
-{
 | 
						|
-	struct mvneta_port *pp = arg;
 | 
						|
-
 | 
						|
-	/* All the queue are masked, but actually only the ones
 | 
						|
-	 * maped to this CPU will be masked
 | 
						|
-	 */
 | 
						|
-	mvreg_write(pp, MVNETA_INTR_NEW_MASK, 0);
 | 
						|
-	mvreg_write(pp, MVNETA_INTR_OLD_MASK, 0);
 | 
						|
-	mvreg_write(pp, MVNETA_INTR_MISC_MASK, 0);
 | 
						|
-}
 | 
						|
-
 | 
						|
 static void mvneta_start_dev(struct mvneta_port *pp)
 | 
						|
 {
 | 
						|
 	int cpu;
 | 
						|
@@ -2601,13 +2609,10 @@ static void mvneta_stop_dev(struct mvnet
 | 
						|
 	mvneta_port_disable(pp);
 | 
						|
 
 | 
						|
 	/* Clear all ethernet port interrupts */
 | 
						|
-	mvreg_write(pp, MVNETA_INTR_MISC_CAUSE, 0);
 | 
						|
-	mvreg_write(pp, MVNETA_INTR_OLD_CAUSE, 0);
 | 
						|
+	on_each_cpu(mvneta_percpu_clear_intr_cause, pp, true);
 | 
						|
 
 | 
						|
 	/* Mask all ethernet port interrupts */
 | 
						|
-	mvreg_write(pp, MVNETA_INTR_NEW_MASK, 0);
 | 
						|
-	mvreg_write(pp, MVNETA_INTR_OLD_MASK, 0);
 | 
						|
-	mvreg_write(pp, MVNETA_INTR_MISC_MASK, 0);
 | 
						|
+	on_each_cpu(mvneta_percpu_mask_interrupt, pp, true);
 | 
						|
 
 | 
						|
 	mvneta_tx_reset(pp);
 | 
						|
 	mvneta_rx_reset(pp);
 | 
						|
@@ -2919,9 +2924,7 @@ static int mvneta_percpu_notifier(struct
 | 
						|
 		}
 | 
						|
 
 | 
						|
 		/* Mask all ethernet port interrupts */
 | 
						|
-		mvreg_write(pp, MVNETA_INTR_NEW_MASK, 0);
 | 
						|
-		mvreg_write(pp, MVNETA_INTR_OLD_MASK, 0);
 | 
						|
-		mvreg_write(pp, MVNETA_INTR_MISC_MASK, 0);
 | 
						|
+		on_each_cpu(mvneta_percpu_mask_interrupt, pp, true);
 | 
						|
 		napi_enable(&port->napi);
 | 
						|
 
 | 
						|
 
 | 
						|
@@ -2936,14 +2939,8 @@ static int mvneta_percpu_notifier(struct
 | 
						|
 		 */
 | 
						|
 		mvneta_percpu_elect(pp);
 | 
						|
 
 | 
						|
-		/* Unmask all ethernet port interrupts, as this
 | 
						|
-		 * notifier is called for each CPU then the CPU to
 | 
						|
-		 * Queue mapping is applied
 | 
						|
-		 */
 | 
						|
-		mvreg_write(pp, MVNETA_INTR_NEW_MASK,
 | 
						|
-			MVNETA_RX_INTR_MASK(rxq_number) |
 | 
						|
-			MVNETA_TX_INTR_MASK(txq_number) |
 | 
						|
-			MVNETA_MISCINTR_INTR_MASK);
 | 
						|
+		/* Unmask all ethernet port interrupts */
 | 
						|
+		on_each_cpu(mvneta_percpu_unmask_interrupt, pp, true);
 | 
						|
 		mvreg_write(pp, MVNETA_INTR_MISC_MASK,
 | 
						|
 			MVNETA_CAUSE_PHY_STATUS_CHANGE |
 | 
						|
 			MVNETA_CAUSE_LINK_CHANGE |
 | 
						|
@@ -2954,9 +2951,7 @@ static int mvneta_percpu_notifier(struct
 | 
						|
 	case CPU_DOWN_PREPARE_FROZEN:
 | 
						|
 		netif_tx_stop_all_queues(pp->dev);
 | 
						|
 		/* Mask all ethernet port interrupts */
 | 
						|
-		mvreg_write(pp, MVNETA_INTR_NEW_MASK, 0);
 | 
						|
-		mvreg_write(pp, MVNETA_INTR_OLD_MASK, 0);
 | 
						|
-		mvreg_write(pp, MVNETA_INTR_MISC_MASK, 0);
 | 
						|
+		on_each_cpu(mvneta_percpu_mask_interrupt, pp, true);
 | 
						|
 
 | 
						|
 		napi_synchronize(&port->napi);
 | 
						|
 		napi_disable(&port->napi);
 | 
						|
@@ -2972,10 +2967,7 @@ static int mvneta_percpu_notifier(struct
 | 
						|
 		/* Check if a new CPU must be elected now this on is down */
 | 
						|
 		mvneta_percpu_elect(pp);
 | 
						|
 		/* Unmask all ethernet port interrupts */
 | 
						|
-		mvreg_write(pp, MVNETA_INTR_NEW_MASK,
 | 
						|
-			MVNETA_RX_INTR_MASK(rxq_number) |
 | 
						|
-			MVNETA_TX_INTR_MASK(txq_number) |
 | 
						|
-			MVNETA_MISCINTR_INTR_MASK);
 | 
						|
+		on_each_cpu(mvneta_percpu_unmask_interrupt, pp, true);
 | 
						|
 		mvreg_write(pp, MVNETA_INTR_MISC_MASK,
 | 
						|
 			MVNETA_CAUSE_PHY_STATUS_CHANGE |
 | 
						|
 			MVNETA_CAUSE_LINK_CHANGE |
 |