avf: tx dequeue optimizations 37/16637/2
authorDamjan Marion <damarion@cisco.com>
Fri, 28 Dec 2018 16:43:22 +0000 (17:43 +0100)
committerDamjan Marion <dmarion@me.com>
Sat, 29 Dec 2018 08:01:36 +0000 (08:01 +0000)
Change-Id: I9d8fcf930132e832941e5678a9278a029e104dc3
Signed-off-by: Damjan Marion <damarion@cisco.com>
src/plugins/avf/avf.h
src/plugins/avf/device.c
src/plugins/avf/output.c

index a1bfa0e..60d49e7 100644 (file)
@@ -114,6 +114,7 @@ typedef struct
   avf_tx_desc_t *descs;
   u32 *bufs;
   u16 n_enqueued;
+  u16 *rs_slots;
 } avf_txq_t;
 
 typedef struct
index 9a8afa2..f6a00a1 100644 (file)
@@ -16,6 +16,7 @@
  */
 
 #include <vlib/vlib.h>
+#include <vppinfra/ring.h>
 #include <vlib/unix/unix.h>
 #include <vlib/pci/pci.h>
 #include <vnet/ethernet/ethernet.h>
@@ -289,6 +290,9 @@ avf_txq_init (vlib_main_t * vm, avf_device_t * ad, u16 qid, u16 txq_size)
   vec_validate_aligned (txq->bufs, txq->size, CLIB_CACHE_LINE_BYTES);
   txq->qtx_tail = ad->bar0 + AVF_QTX_TAIL (qid);
 
+  /* initialize ring of pending RS slots */
+  clib_ring_new_aligned (txq->rs_slots, 32, CLIB_CACHE_LINE_BYTES);
+
   ad->n_tx_queues = clib_min (ad->num_queue_pairs, qid + 1);
   return 0;
 }
@@ -1166,6 +1170,7 @@ avf_delete_if (vlib_main_t * vm, avf_device_t * ad)
                                      txq->n_enqueued);
        }
       vec_free (txq->bufs);
+      clib_ring_free (txq->rs_slots);
     }
   /* *INDENT-ON* */
   vec_free (ad->txqs);
index 5a728f9..0db333b 100644 (file)
@@ -18,6 +18,7 @@
 #include <vlib/vlib.h>
 #include <vlib/unix/unix.h>
 #include <vlib/pci/pci.h>
+#include <vppinfra/ring.h>
 #include <vnet/ethernet/ethernet.h>
 #include <vnet/devices/devices.h>
 
@@ -34,9 +35,9 @@ avf_tx_enqueue (vlib_main_t * vm, avf_txq_t * txq, u32 * buffers,
                u32 n_packets, int use_va_dma)
 {
   u16 next = txq->next;
-  u64 bits = (AVF_TXD_CMD_EOP | AVF_TXD_CMD_RS | AVF_TXD_CMD_RSV);
+  u64 bits = AVF_TXD_CMD_EOP | AVF_TXD_CMD_RSV;
   u16 n_desc = 0;
-  u16 n_desc_left, n_packets_left = n_packets;
+  u16 *slot, n_desc_left, n_packets_left = n_packets;
   u16 mask = txq->size - 1;
   vlib_buffer_t *b[4];
   avf_tx_desc_t *d = txq->descs + next;
@@ -114,6 +115,13 @@ avf_tx_enqueue (vlib_main_t * vm, avf_txq_t * txq, u32 * buffers,
       d += 1;
     }
 
+  if ((slot = clib_ring_enq (txq->rs_slots)))
+    {
+      u16 rs_slot = slot[0] = (next - 1) & mask;
+      d = txq->descs + rs_slot;
+      d[0].qword[1] |= AVF_TXD_CMD_RS;
+    }
+
   CLIB_MEMORY_BARRIER ();
   *(txq->qtx_tail) = txq->next = next & mask;
   txq->n_enqueued += n_desc;
@@ -142,19 +150,28 @@ retry:
   /* release consumed bufs */
   if (txq->n_enqueued)
     {
-      avf_tx_desc_t *d0;
-      u16 first, slot, n_free = 0, mask = txq->size - 1;
-      first = slot = (txq->next - txq->n_enqueued) & mask;
-      d0 = txq->descs + slot;
-      while (n_free < txq->n_enqueued && avf_tx_desc_get_dtyp (d0) == 0x0F)
+      i32 complete_slot = -1;
+      while (1)
        {
-         n_free++;
-         slot = (slot + 1) & mask;
-         d0 = txq->descs + slot;
+         u16 *slot = clib_ring_get_first (txq->rs_slots);
+
+         if (slot == 0)
+           break;
+
+         complete_slot = slot[0];
+         if (avf_tx_desc_get_dtyp (txq->descs + complete_slot) != 0x0F)
+           break;
+
+         clib_ring_deq (txq->rs_slots);
        }
 
-      if (n_free)
+      if (complete_slot >= 0)
        {
+         u16 first, mask, n_free;
+         mask = txq->size - 1;
+         first = (txq->next - txq->n_enqueued) & mask;
+         n_free = (complete_slot + 1 - first) & mask;
+
          txq->n_enqueued -= n_free;
          vlib_buffer_free_from_ring (vm, txq->bufs, first, txq->size,
                                      n_free);