ethoc: Double check pending RX packet
authorJonas Bonn <jonas@southpole.se>
Thu, 25 Nov 2010 02:30:28 +0000 (02:30 +0000)
committerDavid S. Miller <davem@davemloft.net>
Sun, 28 Nov 2010 19:16:36 +0000 (11:16 -0800)
An interrupt may occur between checking bd.stat and clearing the
interrupt source register which would result in the packet going totally
unnoticed as the interrupt will be missed.  Double check bd.stat after
clearing the interrupt source register to guard against such an
occurrence.

Signed-off-by: Jonas Bonn <jonas@southpole.se>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethoc.c

index db444a73e4b11b87a912b3ce7b2c9ab665d6a680..a12a07ea02b615fe8973b440bd960f43481cf6de 100644 (file)
@@ -414,8 +414,19 @@ static int ethoc_rx(struct net_device *dev, int limit)
 
                entry = priv->num_tx + (priv->cur_rx % priv->num_rx);
                ethoc_read_bd(priv, entry, &bd);
-               if (bd.stat & RX_BD_EMPTY)
-                       break;
+               if (bd.stat & RX_BD_EMPTY) {
+                       ethoc_ack_irq(priv, INT_MASK_RX);
+                       /* If packet (interrupt) came in between checking
+                        * BD_EMTPY and clearing the interrupt source, then we
+                        * risk missing the packet as the RX interrupt won't
+                        * trigger right away when we reenable it; hence, check
+                        * BD_EMTPY here again to make sure there isn't such a
+                        * packet waiting for us...
+                        */
+                       ethoc_read_bd(priv, entry, &bd);
+                       if (bd.stat & RX_BD_EMPTY)
+                               break;
+               }
 
                if (ethoc_update_rx_stats(priv, &bd) == 0) {
                        int size = bd.stat >> 16;