bgmac: leave interrupts disabled as long as there is work to do
authorFelix Fietkau <nbd@openwrt.org>
Tue, 14 Apr 2015 10:07:55 +0000 (12:07 +0200)
committerDavid S. Miller <davem@davemloft.net>
Tue, 14 Apr 2015 18:57:10 +0000 (14:57 -0400)
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@openwrt.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/broadcom/bgmac.c
drivers/net/ethernet/broadcom/bgmac.h

index b9e02e484d7278410496300160c07672d9896f2a..9c3b2ff33e6308e6838657cc9e1d0b72319abfa6 100644 (file)
@@ -1109,8 +1109,6 @@ static void bgmac_chip_reset(struct bgmac *bgmac)
        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 irq, void *dev_id)
        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 irq, void *dev_id)
 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);
index 5a198d56f3e74b65d3fc8afd3db4d3aeed75c7d6..abd50d128e6c7f263ad2de958f4b9488503f5193 100644 (file)
@@ -452,7 +452,6 @@ struct bgmac {
 
        /* Int */
        u32 int_mask;
-       u32 int_status;
 
        /* Current MAC state */
        int mac_speed;