88 lines
		
	
	
		
			2.5 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			88 lines
		
	
	
		
			2.5 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
From: Felix Fietkau <nbd@nbd.name>
 | 
						|
Date: Sun, 12 Apr 2015 10:08:04 +0200
 | 
						|
Subject: [PATCH] bgmac: leave interrupts disabled as long as there is work
 | 
						|
 to do
 | 
						|
 | 
						|
Always poll rx and tx during NAPI poll instead of relying on the status
 | 
						|
of the first interrupt. This prevents bgmac_poll from leaving unfinished
 | 
						|
work around until the next IRQ.
 | 
						|
In my tests this makes bridging/routing throughput under heavy load more
 | 
						|
stable and ensures that no new IRQs arrive as long as bgmac_poll uses up
 | 
						|
the entire budget.
 | 
						|
 | 
						|
Signed-off-by: Felix Fietkau <nbd@nbd.name>
 | 
						|
---
 | 
						|
 | 
						|
--- a/drivers/net/ethernet/broadcom/bgmac.c
 | 
						|
+++ b/drivers/net/ethernet/broadcom/bgmac.c
 | 
						|
@@ -1109,8 +1109,6 @@ static void bgmac_chip_reset(struct bgma
 | 
						|
 	bgmac_phy_init(bgmac);
 | 
						|
 
 | 
						|
 	netdev_reset_queue(bgmac->net_dev);
 | 
						|
-
 | 
						|
-	bgmac->int_status = 0;
 | 
						|
 }
 | 
						|
 
 | 
						|
 static void bgmac_chip_intrs_on(struct bgmac *bgmac)
 | 
						|
@@ -1225,14 +1223,13 @@ static irqreturn_t bgmac_interrupt(int i
 | 
						|
 	if (!int_status)
 | 
						|
 		return IRQ_NONE;
 | 
						|
 
 | 
						|
-	/* Ack */
 | 
						|
-	bgmac_write(bgmac, BGMAC_INT_STATUS, int_status);
 | 
						|
+	int_status &= ~(BGMAC_IS_TX0 | BGMAC_IS_RX);
 | 
						|
+	if (int_status)
 | 
						|
+		bgmac_err(bgmac, "Unknown IRQs: 0x%08X\n", int_status);
 | 
						|
 
 | 
						|
 	/* Disable new interrupts until handling existing ones */
 | 
						|
 	bgmac_chip_intrs_off(bgmac);
 | 
						|
 
 | 
						|
-	bgmac->int_status = int_status;
 | 
						|
-
 | 
						|
 	napi_schedule(&bgmac->napi);
 | 
						|
 
 | 
						|
 	return IRQ_HANDLED;
 | 
						|
@@ -1241,25 +1238,17 @@ static irqreturn_t bgmac_interrupt(int i
 | 
						|
 static int bgmac_poll(struct napi_struct *napi, int weight)
 | 
						|
 {
 | 
						|
 	struct bgmac *bgmac = container_of(napi, struct bgmac, napi);
 | 
						|
-	struct bgmac_dma_ring *ring;
 | 
						|
 	int handled = 0;
 | 
						|
 
 | 
						|
-	if (bgmac->int_status & BGMAC_IS_TX0) {
 | 
						|
-		ring = &bgmac->tx_ring[0];
 | 
						|
-		bgmac_dma_tx_free(bgmac, ring);
 | 
						|
-		bgmac->int_status &= ~BGMAC_IS_TX0;
 | 
						|
-	}
 | 
						|
+	/* Ack */
 | 
						|
+	bgmac_write(bgmac, BGMAC_INT_STATUS, ~0);
 | 
						|
 
 | 
						|
-	if (bgmac->int_status & BGMAC_IS_RX) {
 | 
						|
-		ring = &bgmac->rx_ring[0];
 | 
						|
-		handled += bgmac_dma_rx_read(bgmac, ring, weight);
 | 
						|
-		bgmac->int_status &= ~BGMAC_IS_RX;
 | 
						|
-	}
 | 
						|
+	bgmac_dma_tx_free(bgmac, &bgmac->tx_ring[0]);
 | 
						|
+	handled += bgmac_dma_rx_read(bgmac, &bgmac->rx_ring[0], weight);
 | 
						|
 
 | 
						|
-	if (bgmac->int_status) {
 | 
						|
-		bgmac_err(bgmac, "Unknown IRQs: 0x%08X\n", bgmac->int_status);
 | 
						|
-		bgmac->int_status = 0;
 | 
						|
-	}
 | 
						|
+	/* Poll again if more events arrived in the meantime */
 | 
						|
+	if (bgmac_read(bgmac, BGMAC_INT_STATUS) & (BGMAC_IS_TX0 | BGMAC_IS_RX))
 | 
						|
+		return handled;
 | 
						|
 
 | 
						|
 	if (handled < weight) {
 | 
						|
 		napi_complete(napi);
 | 
						|
--- a/drivers/net/ethernet/broadcom/bgmac.h
 | 
						|
+++ b/drivers/net/ethernet/broadcom/bgmac.h
 | 
						|
@@ -452,7 +452,6 @@ struct bgmac {
 | 
						|
 
 | 
						|
 	/* Int */
 | 
						|
 	u32 int_mask;
 | 
						|
-	u32 int_status;
 | 
						|
 
 | 
						|
 	/* Current MAC state */
 | 
						|
 	int mac_speed;
 |