mlx4: Fix NAPI polling
authorBarret Rhoden <brho@cs.berkeley.edu>
Mon, 26 Jun 2017 16:26:12 +0000 (12:26 -0400)
committerBarret Rhoden <brho@cs.berkeley.edu>
Thu, 20 Jul 2017 12:19:46 +0000 (08:19 -0400)
I triggered this by trying to send a lot of packets at once, specifically
by removing the kthread_yield() from tcp.c.  When we poll and exceed the
budget, in Linux the NAPI code will call the poll function again.  We
weren't, and we weren't rearming the NIC's TX IRQ.  Then we'd never be able
to send another packet, since the transmit ring would always be full.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
kern/drivers/net/mlx4/en_rx.c
kern/drivers/net/mlx4/en_tx.c

index 46ebe33..d3d096b 100644 (file)
@@ -1105,7 +1105,16 @@ static void mlx4_en_poll_rx_cq(uint32_t srcid, long a0, long a1, long a2)
        if (!mlx4_en_cq_lock_napi(cq))
                return;
 
-       done = mlx4_en_process_rx_cq(dev, cq, budget);
+       /* Linux only requests more NAPI polls if we're on the right CPU.  I left
+        * the code below.  On Akaros, we can kthread_yield in a loop instead of
+        * interfacing with NAPI. */
+       while (1) {
+               done = mlx4_en_process_rx_cq(dev, cq, budget);
+               if (done < budget)
+                       break;
+               /* If we used up all the quota - we're probably not done yet... */
+               kthread_yield();
+       }
 
        mlx4_en_cq_unlock_napi(cq);
 
index 10a9543..c66d97c 100644 (file)
@@ -530,10 +530,15 @@ static void mlx4_en_poll_tx_cq(uint32_t srcid, long a0, long a1, long a2)
        struct mlx4_en_priv *priv = netdev_priv(dev);
        int clean_complete;
 
-       clean_complete = mlx4_en_process_tx_cq(dev, cq);
-       if (!clean_complete)
-               return;
-
+       /* On Linux, when we didn't finish the clean, we ask for another NAPI run,
+        * or rather we don't stop the polling.  On Akaros, we're in a kthread /
+        * KMSG, so we can just yield. */
+       while (1) {
+               clean_complete = mlx4_en_process_tx_cq(dev, cq);
+               if (clean_complete)
+                       break;
+               kthread_yield();
+       }
        mlx4_en_arm_cq(priv, cq);
 }