[dpdk-dev] [RFC 02/10] virtio: use weak barriers

Stephen Hemminger stephen at networkplumber.org
Tue Aug 26 04:07:48 CEST 2014


The DPDK driver only has to deal with the case of running on PCI
and with SMP. In this case, the code can use the weaker barriers
instead of using hard (fence) barriers. This will help performance.
The rationale is explained in Linux kernel virtio_ring.h.

To make it clearer that this is a virtio thing and not some generic
barrier, prefix the barrier calls with virtio_.

Add missing (and needed) barrier between updating ring data
structure and notifying host.

Signed-off-by: Stephen Hemminger <stephen at networkplumber.org>


---
 lib/librte_pmd_virtio/virtio_ethdev.c |    2 +-
 lib/librte_pmd_virtio/virtio_rxtx.c   |    8 +++++---
 lib/librte_pmd_virtio/virtqueue.h     |   19 ++++++++++++++-----
 3 files changed, 20 insertions(+), 9 deletions(-)

--- a/lib/librte_pmd_virtio/virtio_rxtx.c	2014-08-25 19:00:04.146518448 -0700
+++ b/lib/librte_pmd_virtio/virtio_rxtx.c	2014-08-25 19:00:04.142518425 -0700
@@ -454,7 +454,7 @@ virtio_recv_pkts(void *rx_queue, struct
 
 	nb_used = VIRTQUEUE_NUSED(rxvq);
 
-	rmb();
+	virtio_rmb();
 
 	num = (uint16_t)(likely(nb_used <= nb_pkts) ? nb_used : nb_pkts);
 	num = (uint16_t)(likely(num <= VIRTIO_MBUF_BURST_SZ) ? num : VIRTIO_MBUF_BURST_SZ);
@@ -514,6 +514,7 @@ virtio_recv_pkts(void *rx_queue, struct
 	}
 
 	if (likely(nb_enqueued)) {
+		virtio_wmb();
 		if (unlikely(virtqueue_kick_prepare(rxvq))) {
 			virtqueue_notify(rxvq);
 			PMD_RX_LOG(DEBUG, "Notified\n");
@@ -545,7 +546,7 @@ virtio_recv_mergeable_pkts(void *rx_queu
 
 	nb_used = VIRTQUEUE_NUSED(rxvq);
 
-	rmb();
+	virtio_rmb();
 
 	if (nb_used == 0)
 		return 0;
@@ -694,7 +695,7 @@ virtio_xmit_pkts(void *tx_queue, struct
 	PMD_TX_LOG(DEBUG, "%d packets to xmit", nb_pkts);
 	nb_used = VIRTQUEUE_NUSED(txvq);
 
-	rmb();
+	virtio_rmb();
 
 	num = (uint16_t)(likely(nb_used < VIRTIO_MBUF_BURST_SZ) ? nb_used : VIRTIO_MBUF_BURST_SZ);
 
@@ -729,6 +730,7 @@ virtio_xmit_pkts(void *tx_queue, struct
 		}
 	}
 	vq_update_avail_idx(txvq);
+	virtio_wmb();
 
 	txvq->packets += nb_tx;
 
--- a/lib/librte_pmd_virtio/virtqueue.h	2014-08-25 19:00:04.146518448 -0700
+++ b/lib/librte_pmd_virtio/virtqueue.h	2014-08-25 19:00:04.142518425 -0700
@@ -46,9 +46,18 @@
 #include "virtio_ring.h"
 #include "virtio_logs.h"
 
-#define mb()  rte_mb()
-#define wmb() rte_wmb()
-#define rmb() rte_rmb()
+/*
+ * Per virtio_config.h in Linux.
+ *     For virtio_pci on SMP, we don't need to order with respect to MMIO
+ *     accesses through relaxed memory I/O windows, so smp_mb() et al are
+ *     sufficient.
+ *
+ * This driver is for virtio_pci on SMP and therefore can assume
+ * weaker (compiler barriers)
+ */
+#define virtio_mb()	rte_mb()
+#define virtio_rmb()	rte_compiler_barrier()
+#define virtio_wmb()	rte_compiler_barrier()
 
 #ifdef RTE_PMD_PACKET_PREFETCH
 #define rte_packet_prefetch(p)  rte_prefetch1(p)
@@ -226,7 +235,7 @@ virtqueue_full(const struct virtqueue *v
 static inline void
 vq_update_avail_idx(struct virtqueue *vq)
 {
-	rte_compiler_barrier();
+	virtio_rmb();
 	vq->vq_ring.avail->idx = vq->vq_avail_idx;
 }
 
@@ -256,7 +265,7 @@ static inline void
 virtqueue_notify(struct virtqueue *vq)
 {
 	/*
-	 * Ensure updated avail->idx is visible to host. mb() necessary?
+	 * Ensure updated avail->idx is visible to host.
 	 * For virtio on IA, the notificaiton is through io port operation
 	 * which is a serialization instruction itself.
 	 */
--- a/lib/librte_pmd_virtio/virtio_ethdev.c	2014-08-25 19:00:04.146518448 -0700
+++ b/lib/librte_pmd_virtio/virtio_ethdev.c	2014-08-25 19:00:04.142518425 -0700
@@ -171,7 +171,7 @@ virtio_send_command(struct virtqueue *vq
 		uint32_t idx, desc_idx, used_idx;
 		struct vring_used_elem *uep;
 
-		rmb();
+		virtio_rmb();
 
 		used_idx = (uint32_t)(vq->vq_used_cons_idx
 				& (vq->vq_nentries - 1));



More information about the dev mailing list