get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 36172,
    "url": "https://patches.dpdk.org/api/patches/36172/?format=api",
    "web_url": "https://patches.dpdk.org/project/dpdk/patch/20180316152120.13199-18-jfreimann@redhat.com/",
    "project": {
        "id": 1,
        "url": "https://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": "<20180316152120.13199-18-jfreimann@redhat.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20180316152120.13199-18-jfreimann@redhat.com",
    "date": "2018-03-16T15:21:20",
    "name": "[dpdk-dev,17/17] vhost: support mergeable rx buffers with packed queues",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "7b68ab054fea4033baa486d0dc528557a6f43dc5",
    "submitter": {
        "id": 745,
        "url": "https://patches.dpdk.org/api/people/745/?format=api",
        "name": "Jens Freimann",
        "email": "jfreimann@redhat.com"
    },
    "delegate": {
        "id": 2642,
        "url": "https://patches.dpdk.org/api/users/2642/?format=api",
        "username": "mcoquelin",
        "first_name": "Maxime",
        "last_name": "Coquelin",
        "email": "maxime.coquelin@redhat.com"
    },
    "mbox": "https://patches.dpdk.org/project/dpdk/patch/20180316152120.13199-18-jfreimann@redhat.com/mbox/",
    "series": [],
    "comments": "https://patches.dpdk.org/api/patches/36172/comments/",
    "check": "fail",
    "checks": "https://patches.dpdk.org/api/patches/36172/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@dpdk.org",
        "Delivered-To": "patchwork@dpdk.org",
        "Received": [
            "from [92.243.14.124] (localhost [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id 3C2EC5F72;\n\tFri, 16 Mar 2018 16:22:34 +0100 (CET)",
            "from mx1.redhat.com (mx3-rdu2.redhat.com [66.187.233.73])\n\tby dpdk.org (Postfix) with ESMTP id 1BFB55F18\n\tfor <dev@dpdk.org>; Fri, 16 Mar 2018 16:22:33 +0100 (CET)",
            "from smtp.corp.redhat.com\n\t(int-mx03.intmail.prod.int.rdu2.redhat.com [10.11.54.3])\n\t(using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits))\n\t(No client certificate requested)\n\tby mx1.redhat.com (Postfix) with ESMTPS id B6837402277A;\n\tFri, 16 Mar 2018 15:22:32 +0000 (UTC)",
            "from localhost (dhcp-192-241.str.redhat.com [10.33.192.241])\n\tby smtp.corp.redhat.com (Postfix) with ESMTPS id E9CD010B00A9;\n\tFri, 16 Mar 2018 15:22:25 +0000 (UTC)"
        ],
        "From": "Jens Freimann <jfreimann@redhat.com>",
        "To": "dev@dpdk.org",
        "Cc": "tiwei.bie@intel.com, yliu@fridaylinux.org, maxime.coquelin@redhat.com,\n\tmst@redhat.com",
        "Date": "Fri, 16 Mar 2018 16:21:20 +0100",
        "Message-Id": "<20180316152120.13199-18-jfreimann@redhat.com>",
        "In-Reply-To": "<20180316152120.13199-1-jfreimann@redhat.com>",
        "References": "<20180316152120.13199-1-jfreimann@redhat.com>",
        "X-Scanned-By": "MIMEDefang 2.78 on 10.11.54.3",
        "X-Greylist": [
            "Sender IP whitelisted, not delayed by milter-greylist-4.5.16\n\t(mx1.redhat.com [10.11.55.7]); Fri, 16 Mar 2018 15:22:32 +0000 (UTC)",
            "inspected by milter-greylist-4.5.16 (mx1.redhat.com\n\t[10.11.55.7]); \n\tFri, 16 Mar 2018 15:22:32 +0000 (UTC) for IP:'10.11.54.3'\n\tDOMAIN:'int-mx03.intmail.prod.int.rdu2.redhat.com'\n\tHELO:'smtp.corp.redhat.com' FROM:'jfreimann@redhat.com' RCPT:''"
        ],
        "Subject": "[dpdk-dev] [PATCH 17/17] vhost: support mergeable rx buffers with\n\tpacked queues",
        "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://dpdk.org/ml/options/dev>,\n\t<mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://dpdk.org/ml/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<https://dpdk.org/ml/listinfo/dev>,\n\t<mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "This implements support for mergeable receive buffers in vhost when using\npacked virtqueues. The difference to split virtqueues is not big, it differs\nmostly where descriptor flags are touched and virtio features are checked.\n\nSigned-off-by: Jens Freimann <jfreimann@redhat.com>\n---\n lib/librte_vhost/vhost.c      |   2 +\n lib/librte_vhost/virtio_net.c | 160 +++++++++++++++++++++++++++++++++---------\n 2 files changed, 127 insertions(+), 35 deletions(-)",
    "diff": "diff --git a/lib/librte_vhost/vhost.c b/lib/librte_vhost/vhost.c\nindex 8cba10d..18ff6c6 100644\n--- a/lib/librte_vhost/vhost.c\n+++ b/lib/librte_vhost/vhost.c\n@@ -561,6 +561,8 @@ struct virtio_net *\n \n \tif (dev == NULL)\n \t\treturn -1;\n+\tif (dev->features & (1ULL << VIRTIO_F_RING_PACKED))\n+\t\treturn -1;\n \n \tif (enable) {\n \t\tRTE_LOG(ERR, VHOST_CONFIG,\ndiff --git a/lib/librte_vhost/virtio_net.c b/lib/librte_vhost/virtio_net.c\nindex d96d717..f247911 100644\n--- a/lib/librte_vhost/virtio_net.c\n+++ b/lib/librte_vhost/virtio_net.c\n@@ -401,17 +401,53 @@\n }\n \n static __rte_always_inline int\n-fill_vec_buf(struct virtio_net *dev, struct vhost_virtqueue *vq,\n-\t\t\t uint32_t avail_idx, uint32_t *vec_idx,\n-\t\t\t struct buf_vector *buf_vec, uint16_t *desc_chain_head,\n-\t\t\t uint16_t *desc_chain_len)\n+__fill_vec_buf_packed(struct virtio_net *dev, struct vhost_virtqueue *vq,\n+\t\t\t struct buf_vector *buf_vec,\n+\t\t\t uint32_t *len, uint32_t *vec_id)\n+{\n+\tuint16_t idx = vq->last_avail_idx & (vq->size - 1);\n+\tstruct vring_desc_packed *descs= vq->desc_packed;\n+\tuint32_t _vec_id = *vec_id;\n+\n+\tif (vq->desc_packed[idx].flags & VRING_DESC_F_INDIRECT) {\n+\t\tdescs = (struct vring_desc_packed *)(uintptr_t)\n+\t\t\tvhost_iova_to_vva(dev, vq, vq->desc_packed[idx].addr,\n+\t\t\t\t\t\tvq->desc_packed[idx].len,\n+\t\t\t\t\t\tVHOST_ACCESS_RO);\n+\t\tif (unlikely(!descs))\n+\t\t\treturn -1;\n+\n+\t\tidx = 0;\n+\t}\n+\n+\twhile (1) {\n+\t\tif (unlikely(_vec_id >= BUF_VECTOR_MAX || idx >= vq->size))\n+\t\t\treturn -1;\n+\n+\t\t*len += descs[idx & (vq->size - 1)].len;\n+\t\tbuf_vec[_vec_id].buf_addr = descs[idx].addr;\n+\t\tbuf_vec[_vec_id].buf_len  = descs[idx].len;\n+\t\tbuf_vec[_vec_id].desc_idx = idx;\n+\t\t_vec_id++;\n+\n+\t\tif ((descs[idx & (vq->size - 1)].flags & VRING_DESC_F_NEXT) == 0)\n+\t\t\tbreak;\n+\n+\t\tidx++;\n+\t}\n+\t*vec_id = _vec_id;\n+\n+\treturn 0;\n+}\n+\n+static __rte_always_inline int\n+__fill_vec_buf_split(struct virtio_net *dev, struct vhost_virtqueue *vq,\n+\t\t\t struct buf_vector *buf_vec,\n+\t\t\t uint32_t *len, uint32_t *vec_id, uint32_t avail_idx)\n {\n \tuint16_t idx = vq->avail->ring[avail_idx & (vq->size - 1)];\n-\tuint32_t vec_id = *vec_idx;\n-\tuint32_t len    = 0;\n \tstruct vring_desc *descs = vq->desc;\n-\n-\t*desc_chain_head = idx;\n+\tuint32_t _vec_id = *vec_id;\n \n \tif (vq->desc[idx].flags & VRING_DESC_F_INDIRECT) {\n \t\tdescs = (struct vring_desc *)(uintptr_t)\n@@ -425,20 +461,53 @@\n \t}\n \n \twhile (1) {\n-\t\tif (unlikely(vec_id >= BUF_VECTOR_MAX || idx >= vq->size))\n+\t\tif (unlikely(_vec_id >= BUF_VECTOR_MAX || idx >= vq->size))\n \t\t\treturn -1;\n \n-\t\tlen += descs[idx].len;\n-\t\tbuf_vec[vec_id].buf_addr = descs[idx].addr;\n-\t\tbuf_vec[vec_id].buf_len  = descs[idx].len;\n-\t\tbuf_vec[vec_id].desc_idx = idx;\n-\t\tvec_id++;\n+\t\t*len += descs[idx].len;\n+\t\tbuf_vec[_vec_id].buf_addr = descs[idx].addr;\n+\t\tbuf_vec[_vec_id].buf_len  = descs[idx].len;\n+\t\tbuf_vec[_vec_id].desc_idx = idx;\n+\t\t_vec_id++;\n \n \t\tif ((descs[idx].flags & VRING_DESC_F_NEXT) == 0)\n \t\t\tbreak;\n \n \t\tidx = descs[idx].next;\n \t}\n+\t*vec_id = _vec_id;\n+\n+\treturn 0;\n+}\n+\n+static __rte_always_inline int\n+fill_vec_buf(struct virtio_net *dev, struct vhost_virtqueue *vq,\n+\t\t\t uint32_t avail_idx, uint32_t *vec_idx,\n+\t\t\t struct buf_vector *buf_vec, uint16_t *desc_chain_head,\n+\t\t\t uint16_t *desc_chain_len)\n+{\n+\tuint16_t idx;\n+\tuint32_t vec_id = *vec_idx;\n+\tuint32_t len    = 0;\n+\n+\tif (dev->features & (1ULL << VIRTIO_F_RING_PACKED)) {\n+\t\tidx = vq->last_avail_idx & (vq->size -1);\n+\t} else {\n+\t\tidx = vq->avail->ring[avail_idx & (vq->size - 1)];\n+\t}\n+\n+\n+\t*desc_chain_head = idx;\n+\n+\tif (dev->features & (1ULL << VIRTIO_F_RING_PACKED)) {\n+\t\tif (__fill_vec_buf_packed(dev, vq,\n+\t\t\t\tbuf_vec, &len, &vec_id))\n+\t\t\treturn -1;\n+\t} else {\n+\t\tif (__fill_vec_buf_split(dev, vq,\n+\t\t\t\tbuf_vec, &len, &vec_id, avail_idx))\n+\t\t\treturn -1;\n+\t}\n \n \t*desc_chain_len = len;\n \t*vec_idx = vec_id;\n@@ -465,14 +534,16 @@\n \tcur_idx  = vq->last_avail_idx;\n \n \twhile (size > 0) {\n-\t\tif (unlikely(cur_idx == avail_head))\n+\t\tif (unlikely(cur_idx == avail_head) &&\n+\t\t\t!(dev->features & (1ull < VIRTIO_F_RING_PACKED)))\n \t\t\treturn -1;\n \n \t\tif (unlikely(fill_vec_buf(dev, vq, cur_idx, &vec_idx, buf_vec,\n \t\t\t\t\t\t&head_idx, &len) < 0))\n \t\t\treturn -1;\n \t\tlen = RTE_MIN(len, size);\n-\t\tupdate_shadow_used_ring(vq, head_idx, len);\n+\t\tif (!(dev->features & (1ULL << VIRTIO_F_RING_PACKED)))\n+\t\t\tupdate_shadow_used_ring(vq, head_idx, len);\n \t\tsize -= len;\n \n \t\tcur_idx++;\n@@ -620,6 +691,8 @@\n \tuint16_t num_buffers;\n \tstruct buf_vector buf_vec[BUF_VECTOR_MAX];\n \tuint16_t avail_head;\n+\tuint16_t i;\n+\tstruct vring_desc_packed *descs = NULL;\n \n \tLOG_DEBUG(VHOST_DATA, \"(%d) %s\\n\", dev->vid, __func__);\n \tif (unlikely(!is_valid_virt_queue_idx(queue_id, 0, dev->nr_vring))) {\n@@ -634,7 +707,6 @@\n \n \tif (unlikely(vq->enabled == 0))\n \t\tgoto out_access_unlock;\n-\n \tif (dev->features & (1ULL << VIRTIO_F_IOMMU_PLATFORM))\n \t\tvhost_user_iotlb_rd_lock(vq);\n \n@@ -648,10 +720,14 @@\n \n \tvq->batch_copy_nb_elems = 0;\n \n-\trte_prefetch0(&vq->avail->ring[vq->last_avail_idx & (vq->size - 1)]);\n-\n-\tvq->shadow_used_idx = 0;\n-\tavail_head = *((volatile uint16_t *)&vq->avail->idx);\n+\tif (dev->features & (1ULL << VIRTIO_F_RING_PACKED)) {\n+\t\tavail_head = vq->last_avail_idx;\n+\t\tdescs = vq->desc_packed;\n+\t} else {\n+\t\trte_prefetch0(&vq->avail->ring[vq->last_avail_idx & (vq->size - 1)]);\n+\t\tavail_head = *((volatile uint16_t *)&vq->avail->idx);\n+\t\tvq->shadow_used_idx = 0;\n+\t}\n \tfor (pkt_idx = 0; pkt_idx < count; pkt_idx++) {\n \t\tuint32_t pkt_len = pkts[pkt_idx]->pkt_len + dev->vhost_hlen;\n \n@@ -661,7 +737,9 @@\n \t\t\tLOG_DEBUG(VHOST_DATA,\n \t\t\t\t\"(%d) failed to get enough desc from vring\\n\",\n \t\t\t\tdev->vid);\n-\t\t\tvq->shadow_used_idx -= num_buffers;\n+\n+\t\t\tif (!dev->features & (1ULL & VIRTIO_F_RING_PACKED))\n+\t\t\t\tvq->shadow_used_idx -= num_buffers;\n \t\t\tbreak;\n \t\t}\n \n@@ -671,7 +749,8 @@\n \n \t\tif (copy_mbuf_to_desc_mergeable(dev, vq, pkts[pkt_idx],\n \t\t\t\t\t\tbuf_vec, num_buffers) < 0) {\n-\t\t\tvq->shadow_used_idx -= num_buffers;\n+\t\t\tif (!dev->features & (1ULL & VIRTIO_F_RING_PACKED))\n+\t\t\t\tvq->shadow_used_idx -= num_buffers;\n \t\t\tbreak;\n \t\t}\n \n@@ -680,9 +759,18 @@\n \n \tdo_data_copy_enqueue(dev, vq);\n \n-\tif (likely(vq->shadow_used_idx)) {\n-\t\tflush_shadow_used_ring(dev, vq);\n-\t\tvhost_vring_call(dev, vq);\n+\tif (!(dev->features & (1ULL << VIRTIO_F_RING_PACKED))) {\n+\t\tif (likely(vq->shadow_used_idx)) {\n+\t\t\tflush_shadow_used_ring(dev, vq);\n+\t\t\tvhost_vring_call(dev, vq);\n+\t\t}\n+\t} else {\n+\t\trte_smp_wmb();\n+\t\tfor (i = avail_head; i < vq->last_avail_idx; i++) {\n+\t\t\tif ((i & (vq->size - 1)) == 0)\n+\t\t\t\ttoggle_wrap_counter(vq);\n+\t\t\tset_desc_used(vq, &descs[i & (vq->size - 1)]);\n+\t\t}\n \t}\n \n out:\n@@ -774,7 +862,7 @@ static inline uint32_t __attribute__((always_inline))\n \t\t\t\t\tgoto out;\n \t\t\t\t}\n \n-\t\t\t\tidx = (idx + 1);\n+\t\t\t\tidx = (idx + 1) & mask;\n \t\t\t\tdesc = &descs[idx];\n \t\t\t\tif (unlikely(!desc_is_avail(vq, desc)))\n \t\t\t\t\tgoto out ;\n@@ -840,10 +928,11 @@ static inline uint32_t __attribute__((always_inline))\n \t\treturn 0;\n \t}\n \n-\tif (dev->features & (1ULL << VIRTIO_F_RING_PACKED))\n-\t\treturn vhost_enqueue_burst_packed(dev, queue_id, pkts, count);\n-\telse if (dev->features & (1 << VIRTIO_NET_F_MRG_RXBUF))\n+\tif ((dev->features & (1 << VIRTIO_NET_F_MRG_RXBUF)) &&\n+\t    (dev->features & (1ULL << VIRTIO_F_RING_PACKED)))\n \t\treturn virtio_dev_merge_rx(dev, queue_id, pkts, count);\n+\telse if (dev->features & (1ULL << VIRTIO_F_RING_PACKED))\n+\t\treturn vhost_enqueue_burst_packed(dev, queue_id, pkts, count);\n \telse\n \t\treturn virtio_dev_rx(dev, queue_id, pkts, count);\n }\n@@ -1266,8 +1355,6 @@ static inline uint32_t __attribute__((always_inline))\n \tint wrap_counter = vq->used_wrap_counter;\n \tint rc = 0;\n \n-\trte_spinlock_lock(&vq->access_lock);\n-\n \tif (unlikely(vq->enabled == 0))\n \t\tgoto out;\n \n@@ -1451,6 +1538,9 @@ static inline uint32_t __attribute__((always_inline))\n \tstruct vring_desc_packed *desc = vq->desc_packed;\n \tint err;\n \n+\tif (unlikely(rte_spinlock_trylock(&vq->access_lock) == 0))\n+\t\treturn 0;\n+\n \tcount = RTE_MIN(MAX_PKT_BURST, count);\n \tfor (i = 0; i < count; i++) {\n \t\tidx = vq->last_used_idx & (vq->size - 1);\n@@ -1509,15 +1599,15 @@ static inline uint32_t __attribute__((always_inline))\n \n \tvq = dev->virtqueue[queue_id];\n \n+\tif (dev->features & (1ULL << VIRTIO_F_RING_PACKED))\n+\t\treturn vhost_dequeue_burst_packed(dev, vq, mbuf_pool, pkts, count);\n+\n \tif (unlikely(rte_spinlock_trylock(&vq->access_lock) == 0))\n \t\treturn 0;\n \n \tif (unlikely(vq->enabled == 0))\n \t\tgoto out_access_unlock;\n \n-\tif (dev->features & (1ULL << VIRTIO_F_RING_PACKED))\n-\t\treturn vhost_dequeue_burst_packed(dev, vq, mbuf_pool, pkts, count);\n-\n \tvq->batch_copy_nb_elems = 0;\n \n \tif (dev->features & (1ULL << VIRTIO_F_IOMMU_PLATFORM))\n",
    "prefixes": [
        "dpdk-dev",
        "17/17"
    ]
}