get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/65757/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 65757,
    "url": "http://patches.dpdk.org/api/patches/65757/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/20200212092456.29433-2-joyce.kong@arm.com/",
    "project": {
        "id": 1,
        "url": "http://patches.dpdk.org/api/projects/1/?format=api",
        "name": "DPDK",
        "link_name": "dpdk",
        "list_id": "dev.dpdk.org",
        "list_email": "dev@dpdk.org",
        "web_url": "http://core.dpdk.org",
        "scm_url": "git://dpdk.org/dpdk",
        "webscm_url": "http://git.dpdk.org/dpdk",
        "list_archive_url": "https://inbox.dpdk.org/dev",
        "list_archive_url_format": "https://inbox.dpdk.org/dev/{}",
        "commit_url_format": ""
    },
    "msgid": "<20200212092456.29433-2-joyce.kong@arm.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20200212092456.29433-2-joyce.kong@arm.com",
    "date": "2020-02-12T09:24:55",
    "name": "[v1,1/2] virtio: one way barrier for split vring used idx",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "e9973df45d7c82a9053ab77e3c04f6f81b181f7e",
    "submitter": {
        "id": 970,
        "url": "http://patches.dpdk.org/api/people/970/?format=api",
        "name": "Joyce Kong",
        "email": "joyce.kong@arm.com"
    },
    "delegate": {
        "id": 2642,
        "url": "http://patches.dpdk.org/api/users/2642/?format=api",
        "username": "mcoquelin",
        "first_name": "Maxime",
        "last_name": "Coquelin",
        "email": "maxime.coquelin@redhat.com"
    },
    "mbox": "http://patches.dpdk.org/project/dpdk/patch/20200212092456.29433-2-joyce.kong@arm.com/mbox/",
    "series": [
        {
            "id": 8511,
            "url": "http://patches.dpdk.org/api/series/8511/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=8511",
            "date": "2020-02-12T09:24:54",
            "name": "one way barrier for split vring idx",
            "version": 1,
            "mbox": "http://patches.dpdk.org/series/8511/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/65757/comments/",
    "check": "success",
    "checks": "http://patches.dpdk.org/api/patches/65757/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@inbox.dpdk.org",
        "Delivered-To": "patchwork@inbox.dpdk.org",
        "Received": [
            "from dpdk.org (dpdk.org [92.243.14.124])\n\tby inbox.dpdk.org (Postfix) with ESMTP id 3361CA0530;\n\tWed, 12 Feb 2020 10:25:44 +0100 (CET)",
            "from [92.243.14.124] (localhost [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id 110012C18;\n\tWed, 12 Feb 2020 10:25:39 +0100 (CET)",
            "from foss.arm.com (foss.arm.com [217.140.110.172])\n by dpdk.org (Postfix) with ESMTP id F21B62BFA\n for <dev@dpdk.org>; Wed, 12 Feb 2020 10:25:36 +0100 (CET)",
            "from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14])\n by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 693E831B;\n Wed, 12 Feb 2020 01:25:36 -0800 (PST)",
            "from net-arm-thunderx2-03.shanghai.arm.com\n (net-arm-thunderx2-03.shanghai.arm.com [10.169.41.185])\n by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id D27693F6CF;\n Wed, 12 Feb 2020 01:25:33 -0800 (PST)"
        ],
        "From": "Joyce Kong <joyce.kong@arm.com>",
        "To": "dev@dpdk.org",
        "Cc": "nd@arm.com, maxime.coquelin@redhat.com, tiwei.bie@intel.com,\n zhihong.wang@intel.com, thomas@monjalon.net, jerinj@marvell.com,\n yinan.wang@intel.com, honnappa.nagarahalli@arm.com, gavin.hu@arm.com",
        "Date": "Wed, 12 Feb 2020 17:24:55 +0800",
        "Message-Id": "<20200212092456.29433-2-joyce.kong@arm.com>",
        "X-Mailer": "git-send-email 2.17.1",
        "In-Reply-To": "<20200212092456.29433-1-joyce.kong@arm.com>",
        "References": "<20200212092456.29433-1-joyce.kong@arm.com>",
        "Subject": "[dpdk-dev] [PATCH v1 1/2] virtio: one way barrier for split vring\n\tused idx",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.15",
        "Precedence": "list",
        "List-Id": "DPDK patches and discussions <dev.dpdk.org>",
        "List-Unsubscribe": "<https://mails.dpdk.org/options/dev>,\n <mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://mails.dpdk.org/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<https://mails.dpdk.org/listinfo/dev>,\n <mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "In case VIRTIO_F_ORDER_PLATFORM(36) is not negotiated, then the frontend\nand backend are assumed to be implemented in software, that is they can\nrun on identical CPUs in an SMP configuration.\nThus a weak form of memory barriers like rte_smp_r/wmb, other than\nrte_cio_r/wmb, is sufficient for this case(vq->hw->weak_barriers == 1)\nand yields better performance.\nFor the above case, this patch helps yielding even better performance\nby replacing the two-way barriers with C11 one-way barriers for used\nindex in split ring.\n\nSigned-off-by: Joyce Kong <joyce.kong@arm.com>\nReviewed-by: Gavin Hu <gavin.hu@arm.com>\n---\n drivers/net/virtio/virtio_ethdev.c            |  9 ++--\n drivers/net/virtio/virtio_ring.h              |  2 +-\n drivers/net/virtio/virtio_rxtx.c              | 46 +++++++++----------\n drivers/net/virtio/virtio_rxtx_simple_neon.c  |  5 +-\n drivers/net/virtio/virtio_rxtx_simple_sse.c   |  5 +-\n .../net/virtio/virtio_user/virtio_user_dev.c  |  8 ++--\n drivers/net/virtio/virtqueue.c                |  2 +-\n drivers/net/virtio/virtqueue.h                | 34 +++++++++++---\n lib/librte_vhost/virtio_net.c                 |  5 +-\n 9 files changed, 68 insertions(+), 48 deletions(-)",
    "diff": "diff --git a/drivers/net/virtio/virtio_ethdev.c b/drivers/net/virtio/virtio_ethdev.c\nindex f9d0ea70d..a4a865bfa 100644\n--- a/drivers/net/virtio/virtio_ethdev.c\n+++ b/drivers/net/virtio/virtio_ethdev.c\n@@ -285,13 +285,12 @@ virtio_send_command_split(struct virtnet_ctl *cvq,\n \n \tvirtqueue_notify(vq);\n \n-\trte_rmb();\n-\twhile (VIRTQUEUE_NUSED(vq) == 0) {\n-\t\trte_rmb();\n+\t/* virtqueue_nused has a load-acquire or rte_cio_rmb inside */\n+\twhile (virtqueue_nused(vq) == 0)\n \t\tusleep(100);\n-\t}\n \n-\twhile (VIRTQUEUE_NUSED(vq)) {\n+\t/* virtqueue_nused has a load-acquire or rte_cio_rmb inside */\n+\twhile (virtqueue_nused(vq)) {\n \t\tuint32_t idx, desc_idx, used_idx;\n \t\tstruct vring_used_elem *uep;\n \ndiff --git a/drivers/net/virtio/virtio_ring.h b/drivers/net/virtio/virtio_ring.h\nindex 7ba34662e..0f6574f68 100644\n--- a/drivers/net/virtio/virtio_ring.h\n+++ b/drivers/net/virtio/virtio_ring.h\n@@ -59,7 +59,7 @@ struct vring_used_elem {\n \n struct vring_used {\n \tuint16_t flags;\n-\tvolatile uint16_t idx;\n+\tuint16_t idx;\n \tstruct vring_used_elem ring[0];\n };\n \ndiff --git a/drivers/net/virtio/virtio_rxtx.c b/drivers/net/virtio/virtio_rxtx.c\nindex 752faa0f6..9ba26fd95 100644\n--- a/drivers/net/virtio/virtio_rxtx.c\n+++ b/drivers/net/virtio/virtio_rxtx.c\n@@ -45,7 +45,7 @@ virtio_dev_rx_queue_done(void *rxq, uint16_t offset)\n \tstruct virtnet_rx *rxvq = rxq;\n \tstruct virtqueue *vq = rxvq->vq;\n \n-\treturn VIRTQUEUE_NUSED(vq) >= offset;\n+\treturn virtqueue_nused(vq) >= offset;\n }\n \n void\n@@ -1243,9 +1243,8 @@ virtio_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts)\n \tif (unlikely(hw->started == 0))\n \t\treturn nb_rx;\n \n-\tnb_used = VIRTQUEUE_NUSED(vq);\n-\n-\tvirtio_rmb(hw->weak_barriers);\n+\t/* virtqueue_nused has a load-acquire or rte_cio_rmb inside */\n+\tnb_used = virtqueue_nused(vq);\n \n \tnum = likely(nb_used <= nb_pkts) ? nb_used : nb_pkts;\n \tif (unlikely(num > VIRTIO_MBUF_BURST_SZ))\n@@ -1458,12 +1457,11 @@ virtio_recv_pkts_inorder(void *rx_queue,\n \tif (unlikely(hw->started == 0))\n \t\treturn nb_rx;\n \n-\tnb_used = VIRTQUEUE_NUSED(vq);\n+\t/* virtqueue_nused has a load-acquire or rte_cio_rmb inside */\n+\tnb_used = virtqueue_nused(vq);\n \tnb_used = RTE_MIN(nb_used, nb_pkts);\n \tnb_used = RTE_MIN(nb_used, VIRTIO_MBUF_BURST_SZ);\n \n-\tvirtio_rmb(hw->weak_barriers);\n-\n \tPMD_RX_LOG(DEBUG, \"used:%d\", nb_used);\n \n \tnb_enqueued = 0;\n@@ -1552,8 +1550,8 @@ virtio_recv_pkts_inorder(void *rx_queue,\n \t\tuint16_t rcv_cnt = RTE_MIN((uint16_t)seg_res,\n \t\t\t\t\tVIRTIO_MBUF_BURST_SZ);\n \n-\t\tif (likely(VIRTQUEUE_NUSED(vq) >= rcv_cnt)) {\n-\t\t\tvirtio_rmb(hw->weak_barriers);\n+\t\t/* virtqueue_nused has a load-acquire or rte_cio_rmb inside */\n+\t\tif (likely(virtqueue_nused(vq) >= rcv_cnt)) {\n \t\t\tnum = virtqueue_dequeue_rx_inorder(vq, rcv_pkts, len,\n \t\t\t\t\t\t\t   rcv_cnt);\n \t\t\tuint16_t extra_idx = 0;\n@@ -1644,9 +1642,8 @@ virtio_recv_mergeable_pkts(void *rx_queue,\n \tif (unlikely(hw->started == 0))\n \t\treturn nb_rx;\n \n-\tnb_used = VIRTQUEUE_NUSED(vq);\n-\n-\tvirtio_rmb(hw->weak_barriers);\n+\t/* virtqueue_nused has a load-acquire or rte_cio_rmb inside */\n+\tnb_used = virtqueue_nused(vq);\n \n \tPMD_RX_LOG(DEBUG, \"used:%d\", nb_used);\n \n@@ -1734,8 +1731,8 @@ virtio_recv_mergeable_pkts(void *rx_queue,\n \t\tuint16_t rcv_cnt = RTE_MIN((uint16_t)seg_res,\n \t\t\t\t\tVIRTIO_MBUF_BURST_SZ);\n \n-\t\tif (likely(VIRTQUEUE_NUSED(vq) >= rcv_cnt)) {\n-\t\t\tvirtio_rmb(hw->weak_barriers);\n+\t\t/* virtqueue_nused has a load-acquire or rte_cio_rmb inside */\n+\t\tif (likely(virtqueue_nused(vq) >= rcv_cnt)) {\n \t\t\tnum = virtqueue_dequeue_burst_rx(vq, rcv_pkts, len,\n \t\t\t\t\t\t\t   rcv_cnt);\n \t\t\tuint16_t extra_idx = 0;\n@@ -2108,9 +2105,10 @@ virtio_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)\n \t\treturn nb_pkts;\n \n \tPMD_TX_LOG(DEBUG, \"%d packets to xmit\", nb_pkts);\n-\tnb_used = VIRTQUEUE_NUSED(vq);\n \n-\tvirtio_rmb(hw->weak_barriers);\n+\t/* virtqueue_nused has a load-acquire or rte_cio_rmb inside */\n+\tnb_used = virtqueue_nused(vq);\n+\n \tif (likely(nb_used > vq->vq_nentries - vq->vq_free_thresh))\n \t\tvirtio_xmit_cleanup(vq, nb_used);\n \n@@ -2142,8 +2140,11 @@ virtio_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)\n \n \t\t/* Positive value indicates it need free vring descriptors */\n \t\tif (unlikely(need > 0)) {\n-\t\t\tnb_used = VIRTQUEUE_NUSED(vq);\n-\t\t\tvirtio_rmb(hw->weak_barriers);\n+\t\t\t/* virtqueue_nused has a load-acquire or\n+\t\t\t * rte_cio_rmb inside\n+\t\t\t */\n+\t\t\tnb_used = virtqueue_nused(vq);\n+\n \t\t\tneed = RTE_MIN(need, (int)nb_used);\n \n \t\t\tvirtio_xmit_cleanup(vq, need);\n@@ -2180,11 +2181,10 @@ static __rte_always_inline int\n virtio_xmit_try_cleanup_inorder(struct virtqueue *vq, uint16_t need)\n {\n \tuint16_t nb_used, nb_clean, nb_descs;\n-\tstruct virtio_hw *hw = vq->hw;\n \n \tnb_descs = vq->vq_free_cnt + need;\n-\tnb_used = VIRTQUEUE_NUSED(vq);\n-\tvirtio_rmb(hw->weak_barriers);\n+\t/* virtqueue_nused has a load-acquire or rte_cio_rmb inside */\n+\tnb_used = virtqueue_nused(vq);\n \tnb_clean = RTE_MIN(need, (int)nb_used);\n \n \tvirtio_xmit_cleanup_inorder(vq, nb_clean);\n@@ -2213,9 +2213,9 @@ virtio_xmit_pkts_inorder(void *tx_queue,\n \n \tVIRTQUEUE_DUMP(vq);\n \tPMD_TX_LOG(DEBUG, \"%d packets to xmit\", nb_pkts);\n-\tnb_used = VIRTQUEUE_NUSED(vq);\n+\t/* virtqueue_nused has a load-acquire or rte_cio_rmb inside */\n+\tnb_used = virtqueue_nused(vq);\n \n-\tvirtio_rmb(hw->weak_barriers);\n \tif (likely(nb_used > vq->vq_nentries - vq->vq_free_thresh))\n \t\tvirtio_xmit_cleanup_inorder(vq, nb_used);\n \ndiff --git a/drivers/net/virtio/virtio_rxtx_simple_neon.c b/drivers/net/virtio/virtio_rxtx_simple_neon.c\nindex 992e71f01..363e2b330 100644\n--- a/drivers/net/virtio/virtio_rxtx_simple_neon.c\n+++ b/drivers/net/virtio/virtio_rxtx_simple_neon.c\n@@ -83,9 +83,8 @@ virtio_recv_pkts_vec(void *rx_queue, struct rte_mbuf **rx_pkts,\n \tif (unlikely(nb_pkts < RTE_VIRTIO_DESC_PER_LOOP))\n \t\treturn 0;\n \n-\tnb_used = VIRTQUEUE_NUSED(vq);\n-\n-\trte_rmb();\n+\t/* virtqueue_nused has a load-acquire or rte_cio_rmb inside */\n+\tnb_used = virtqueue_nused(vq);\n \n \tif (unlikely(nb_used == 0))\n \t\treturn 0;\ndiff --git a/drivers/net/virtio/virtio_rxtx_simple_sse.c b/drivers/net/virtio/virtio_rxtx_simple_sse.c\nindex f9ec4ae69..45a45e6f4 100644\n--- a/drivers/net/virtio/virtio_rxtx_simple_sse.c\n+++ b/drivers/net/virtio/virtio_rxtx_simple_sse.c\n@@ -85,9 +85,8 @@ virtio_recv_pkts_vec(void *rx_queue, struct rte_mbuf **rx_pkts,\n \tif (unlikely(nb_pkts < RTE_VIRTIO_DESC_PER_LOOP))\n \t\treturn 0;\n \n-\tnb_used = VIRTQUEUE_NUSED(vq);\n-\n-\trte_compiler_barrier();\n+\t/* virtqueue_nused has a load-acquire or rte_cio_rmb inside */\n+\tnb_used = virtqueue_nused(vq);\n \n \tif (unlikely(nb_used == 0))\n \t\treturn 0;\ndiff --git a/drivers/net/virtio/virtio_user/virtio_user_dev.c b/drivers/net/virtio/virtio_user/virtio_user_dev.c\nindex 1c6b26f8d..7fb135f49 100644\n--- a/drivers/net/virtio/virtio_user/virtio_user_dev.c\n+++ b/drivers/net/virtio/virtio_user/virtio_user_dev.c\n@@ -730,8 +730,10 @@ virtio_user_handle_cq(struct virtio_user_dev *dev, uint16_t queue_idx)\n \tstruct vring *vring = &dev->vrings[queue_idx];\n \n \t/* Consume avail ring, using used ring idx as first one */\n-\twhile (vring->used->idx != vring->avail->idx) {\n-\t\tavail_idx = (vring->used->idx) & (vring->num - 1);\n+\twhile (__atomic_load_n(&vring->used->idx, __ATOMIC_RELAXED)\n+\t       != vring->avail->idx) {\n+\t\tavail_idx = __atomic_load_n(&vring->used->idx, __ATOMIC_RELAXED)\n+\t\t\t    & (vring->num - 1);\n \t\tdesc_idx = vring->avail->ring[avail_idx];\n \n \t\tn_descs = virtio_user_handle_ctrl_msg(dev, vring, desc_idx);\n@@ -741,6 +743,6 @@ virtio_user_handle_cq(struct virtio_user_dev *dev, uint16_t queue_idx)\n \t\tuep->id = desc_idx;\n \t\tuep->len = n_descs;\n \n-\t\tvring->used->idx++;\n+\t\t__atomic_add_fetch(&vring->used->idx, 1, __ATOMIC_RELAXED);\n \t}\n }\ndiff --git a/drivers/net/virtio/virtqueue.c b/drivers/net/virtio/virtqueue.c\nindex 0b4e3bf3e..b0f61dabc 100644\n--- a/drivers/net/virtio/virtqueue.c\n+++ b/drivers/net/virtio/virtqueue.c\n@@ -92,7 +92,7 @@ virtqueue_rxvq_flush_split(struct virtqueue *vq)\n \tuint16_t used_idx, desc_idx;\n \tuint16_t nb_used, i;\n \n-\tnb_used = VIRTQUEUE_NUSED(vq);\n+\tnb_used = virtqueue_nused(vq);\n \n \tfor (i = 0; i < nb_used; i++) {\n \t\tused_idx = vq->vq_used_cons_idx & (vq->vq_nentries - 1);\ndiff --git a/drivers/net/virtio/virtqueue.h b/drivers/net/virtio/virtqueue.h\nindex 58ad7309a..13fdcb13a 100644\n--- a/drivers/net/virtio/virtqueue.h\n+++ b/drivers/net/virtio/virtqueue.h\n@@ -464,8 +464,29 @@ virtio_get_queue_type(struct virtio_hw *hw, uint16_t vtpci_queue_idx)\n \t\treturn VTNET_TQ;\n }\n \n-#define VIRTQUEUE_NUSED(vq) ((uint16_t)((vq)->vq_split.ring.used->idx - \\\n-\t\t\t\t\t(vq)->vq_used_cons_idx))\n+static inline uint16_t\n+virtqueue_nused(struct virtqueue *vq)\n+{\n+\tuint16_t idx;\n+\tif (vq->hw->weak_barriers) {\n+/* x86 prefers to using rte_smp_rmb over __atomic_load_n as it reports\n+ * a slightly better perf, which comes from the saved branch by the compiler.\n+ * The if and else branches are identical with the smp and cio barriers both\n+ * defined as compiler barriers on x86.\n+ */\n+#ifdef RTE_ARCH_X86_64\n+\t\tidx = vq->vq_split.ring.used->idx;\n+\t\trte_smp_rmb();\n+#else\n+\t\tidx = __atomic_load_n(&(vq)->vq_split.ring.used->idx,\n+\t\t\t\t__ATOMIC_ACQUIRE);\n+#endif\n+\t} else {\n+\t\tidx = vq->vq_split.ring.used->idx;\n+\t\trte_cio_rmb();\n+\t}\n+\treturn (idx - vq->vq_used_cons_idx);\n+}\n \n void vq_ring_free_chain(struct virtqueue *vq, uint16_t desc_idx);\n void vq_ring_free_chain_packed(struct virtqueue *vq, uint16_t used_idx);\n@@ -534,7 +555,8 @@ virtqueue_notify(struct virtqueue *vq)\n #ifdef RTE_LIBRTE_VIRTIO_DEBUG_DUMP\n #define VIRTQUEUE_DUMP(vq) do { \\\n \tuint16_t used_idx, nused; \\\n-\tused_idx = (vq)->vq_split.ring.used->idx; \\\n+\tused_idx = __atomic_load_n(&(vq)->vq_split.ring.used->idx, \\\n+\t\t\t\t   __ATOMIC_RELAXED);\n \tnused = (uint16_t)(used_idx - (vq)->vq_used_cons_idx); \\\n \tif (vtpci_packed_queue((vq)->hw)) { \\\n \t\tPMD_INIT_LOG(DEBUG, \\\n@@ -549,9 +571,9 @@ virtqueue_notify(struct virtqueue *vq)\n \t  \"VQ: - size=%d; free=%d; used=%d; desc_head_idx=%d;\" \\\n \t  \" avail.idx=%d; used_cons_idx=%d; used.idx=%d;\" \\\n \t  \" avail.flags=0x%x; used.flags=0x%x\", \\\n-\t  (vq)->vq_nentries, (vq)->vq_free_cnt, nused, \\\n-\t  (vq)->vq_desc_head_idx, (vq)->vq_split.ring.avail->idx, \\\n-\t  (vq)->vq_used_cons_idx, (vq)->vq_split.ring.used->idx, \\\n+\t  (vq)->vq_nentries, (vq)->vq_free_cnt, nused, (vq)->vq_desc_head_idx, \\\n+\t  (vq)->vq_split.ring.avail->idx, (vq)->vq_used_cons_idx, \\\n+\t  __atomic_load_n(&(vq)->vq_split.ring.used->idx, __ATOMIC_RELAXED), \\\n \t  (vq)->vq_split.ring.avail->flags, (vq)->vq_split.ring.used->flags); \\\n } while (0)\n #else\ndiff --git a/lib/librte_vhost/virtio_net.c b/lib/librte_vhost/virtio_net.c\nindex 37c47c7dc..7f6e7f2c1 100644\n--- a/lib/librte_vhost/virtio_net.c\n+++ b/lib/librte_vhost/virtio_net.c\n@@ -77,11 +77,10 @@ flush_shadow_used_ring_split(struct virtio_net *dev, struct vhost_virtqueue *vq)\n \t}\n \tvq->last_used_idx += vq->shadow_used_idx;\n \n-\trte_smp_wmb();\n-\n \tvhost_log_cache_sync(dev, vq);\n \n-\t*(volatile uint16_t *)&vq->used->idx += vq->shadow_used_idx;\n+\t__atomic_add_fetch(&vq->used->idx, vq->shadow_used_idx,\n+\t\t\t   __ATOMIC_RELEASE);\n \tvq->shadow_used_idx = 0;\n \tvhost_log_used_vring(dev, vq, offsetof(struct vring_used, idx),\n \t\tsizeof(vq->used->idx));\n",
    "prefixes": [
        "v1",
        "1/2"
    ]
}