atl1: do not drop rx/tx interrupts before they are scheduled
authorTony Zelenoff <antonz@parallels.com>
Fri, 13 Apr 2012 06:09:54 +0000 (06:09 +0000)
committerDavid S. Miller <davem@davemloft.net>
Sun, 15 Apr 2012 17:00:12 +0000 (13:00 -0400)
To prevent interrupts lost they should be dropped only if
they are scheduled via napi interfaces. In other case, there is
exists situation when napi handler process TX interrupt, stay in
RX processing and in that moment any other interrupt received.
Then before this patch TX bit in ISR will be cleaned, napi
schedule will not occur in case of currently processing event and
TX interrupt definitely will be lost.

Signed-off-by: Tony Zelenoff <antonz@parallels.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/atheros/atlx/atl1.c

index 066b980cc2f07a30f5b10721db61e3f51789a561..7f1e498c3c06ce5200dbad0e4d2c38f60f589340 100644 (file)
@@ -2504,8 +2504,12 @@ static irqreturn_t atl1_intr(int irq, void *data)
        if (!status)
                return IRQ_NONE;
 
-       /* clear CMB interrupt status at once */
-       adapter->cmb.cmb->int_stats = 0;
+       /* clear CMB interrupt status at once,
+        * but leave rx/tx interrupt status in case it should be dropped
+        * only if rx/tx processing queued. In other case interrupt
+        * can be lost.
+        */
+       adapter->cmb.cmb->int_stats = status & (ISR_CMB_TX | ISR_CMB_RX);
 
        if (status & ISR_GPHY)  /* clear phy status */
                atlx_clear_phy_int(adapter);
@@ -2547,8 +2551,10 @@ static irqreturn_t atl1_intr(int irq, void *data)
        }
 
        /* transmit or receive event */
-       if (status & (ISR_CMB_TX | ISR_CMB_RX))
-           atl1_sched_rings_clean(adapter);
+       if (status & (ISR_CMB_TX | ISR_CMB_RX) &&
+           atl1_sched_rings_clean(adapter))
+               adapter->cmb.cmb->int_stats = adapter->cmb.cmb->int_stats &
+                                             ~(ISR_CMB_TX | ISR_CMB_RX);
 
        /* rx exception */
        if (unlikely(status & (ISR_RXF_OV | ISR_RFD_UNRUN |