get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 7731,
    "url": "https://patches.dpdk.org/api/patches/7731/?format=api",
    "web_url": "https://patches.dpdk.org/project/dpdk/patch/1445231772-17467-4-git-send-email-stephen@networkplumber.org/",
    "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": "<1445231772-17467-4-git-send-email-stephen@networkplumber.org>",
    "list_archive_url": "https://inbox.dpdk.org/dev/1445231772-17467-4-git-send-email-stephen@networkplumber.org",
    "date": "2015-10-19T05:16:10",
    "name": "[dpdk-dev,3/5] virtio: use indirect ring elements",
    "commit_ref": null,
    "pull_url": null,
    "state": "changes-requested",
    "archived": true,
    "hash": "feff445de2fb9422cb3ccd0fded551be4491e7cd",
    "submitter": {
        "id": 27,
        "url": "https://patches.dpdk.org/api/people/27/?format=api",
        "name": "Stephen Hemminger",
        "email": "stephen@networkplumber.org"
    },
    "delegate": null,
    "mbox": "https://patches.dpdk.org/project/dpdk/patch/1445231772-17467-4-git-send-email-stephen@networkplumber.org/mbox/",
    "series": [],
    "comments": "https://patches.dpdk.org/api/patches/7731/comments/",
    "check": "pending",
    "checks": "https://patches.dpdk.org/api/patches/7731/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 [IPv6:::1])\n\tby dpdk.org (Postfix) with ESMTP id BF4548E90;\n\tMon, 19 Oct 2015 07:16:12 +0200 (CEST)",
            "from mail-pa0-f41.google.com (mail-pa0-f41.google.com\n\t[209.85.220.41]) by dpdk.org (Postfix) with ESMTP id 46EBC8E82\n\tfor <dev@dpdk.org>; Mon, 19 Oct 2015 07:16:08 +0200 (CEST)",
            "by pabrc13 with SMTP id rc13so179467675pab.0\n\tfor <dev@dpdk.org>; Sun, 18 Oct 2015 22:16:07 -0700 (PDT)",
            "from xeon-e3.home.lan (static-50-53-82-155.bvtn.or.frontiernet.net.\n\t[50.53.82.155]) by smtp.gmail.com with ESMTPSA id\n\tk10sm33681035pbq.78.2015.10.18.22.16.06\n\t(version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128);\n\tSun, 18 Oct 2015 22:16:06 -0700 (PDT)"
        ],
        "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20130820;\n\th=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to\n\t:references;\n\tbh=Ta9WXu3yY9jn7SX7N6isMaWxg35HDTv3xIEGd9m1ckg=;\n\tb=G1aajiLjT9oSckdpTKzAE1AV8QOXNJtryXnHuHOSM6bUOWxdaX6m1r0RLo/7fg5ovr\n\tTV6cnIZQ9On9TdkOCa7UrTDTOnwaN4S3dOSJVfk8e5mfcUeY2xBfyIA/Tci4dB6bktfD\n\tKBHJsQkbKxXben1P180imh5n1kFpveTYkjrbar8+1VOJE18vlbco8ZrzGtr33R09XuSZ\n\t3QXZMMA0SEl83o7GeNHzs34X9cPQ6RnlbgCz8QdLiLjE7tYfTyTrMI1Or5cP7ldqDklU\n\tB9uqjbhJvoAk6rW7t6AJNGiPR2lhchy+xOZHoOWGRyV+cdZU0SqZlvthiUxyO70h7kTd\n\tprLQ==",
        "X-Gm-Message-State": "ALoCoQkvWVIVwryrhiPVK1VcgKAaEyThHLJ5l90fQQ03DNFWMBY9OPTxU2JfIVrrQQC+uWCFxMeV",
        "X-Received": "by 10.67.22.34 with SMTP id hp2mr32020735pad.92.1445231767702;\n\tSun, 18 Oct 2015 22:16:07 -0700 (PDT)",
        "From": "Stephen Hemminger <stephen@networkplumber.org>",
        "To": "huawei.xie@intel.com,\n\tchangchun.ouyang@intel.com",
        "Date": "Sun, 18 Oct 2015 22:16:10 -0700",
        "Message-Id": "<1445231772-17467-4-git-send-email-stephen@networkplumber.org>",
        "X-Mailer": "git-send-email 2.1.4",
        "In-Reply-To": "<1445231772-17467-1-git-send-email-stephen@networkplumber.org>",
        "References": "<1445231772-17467-1-git-send-email-stephen@networkplumber.org>",
        "Cc": "dev@dpdk.org",
        "Subject": "[dpdk-dev] [PATCH 3/5] virtio: use indirect ring elements",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.15",
        "Precedence": "list",
        "List-Id": "patches and discussions about DPDK <dev.dpdk.org>",
        "List-Unsubscribe": "<http://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": "<http://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": "The virtio ring in QEMU/KVM is usually limited to 256 entries\nand the normal way that virtio driver was queuing mbufs required\nnsegs + 1 ring elements. By using the indirect ring element feature\nif available, each packet will take only one ring slot even for\nmulti-segment packets.\n\nSigned-off-by: Stephen Hemminger <stephen@networkplumber.org>\n---\n drivers/net/virtio/virtio_ethdev.c | 38 +++++++++++++++++------\n drivers/net/virtio/virtio_ethdev.h |  3 +-\n drivers/net/virtio/virtio_rxtx.c   | 62 +++++++++++++++++++++++++++-----------\n drivers/net/virtio/virtqueue.h     | 19 ++++++++++++\n 4 files changed, 94 insertions(+), 28 deletions(-)",
    "diff": "diff --git a/drivers/net/virtio/virtio_ethdev.c b/drivers/net/virtio/virtio_ethdev.c\nindex 465d3cd..cfce4f0 100644\n--- a/drivers/net/virtio/virtio_ethdev.c\n+++ b/drivers/net/virtio/virtio_ethdev.c\n@@ -357,27 +357,45 @@ int virtio_dev_queue_setup(struct rte_eth_dev *dev,\n \tvq->virtio_net_hdr_mem = 0;\n \n \tif (queue_type == VTNET_TQ) {\n+\t\tconst struct rte_memzone *hdr_mz;\n+\t\tstruct virtio_tx_region *txr;\n+\t\tint i;\n+\n \t\t/*\n \t\t * For each xmit packet, allocate a virtio_net_hdr\n+\t\t * and indirect ring elements\n \t\t */\n \t\tsnprintf(vq_name, sizeof(vq_name), \"port%d_tvq%d_hdrzone\",\n \t\t\tdev->data->port_id, queue_idx);\n-\t\tvq->virtio_net_hdr_mz = rte_memzone_reserve_aligned(vq_name,\n-\t\t\tvq_size * hw->vtnet_hdr_size,\n+\t\thdr_mz = rte_memzone_reserve_aligned(vq_name,\n+\t\t\tvq_size * sizeof(*txr),\n \t\t\tsocket_id, 0, RTE_CACHE_LINE_SIZE);\n-\t\tif (vq->virtio_net_hdr_mz == NULL) {\n+\t\tif (hdr_mz == NULL) {\n \t\t\tif (rte_errno == EEXIST)\n-\t\t\t\tvq->virtio_net_hdr_mz =\n-\t\t\t\t\trte_memzone_lookup(vq_name);\n-\t\t\tif (vq->virtio_net_hdr_mz == NULL) {\n+\t\t\t\thdr_mz = rte_memzone_lookup(vq_name);\n+\t\t\tif (hdr_mz == NULL) {\n \t\t\t\trte_free(vq);\n \t\t\t\treturn -ENOMEM;\n \t\t\t}\n \t\t}\n-\t\tvq->virtio_net_hdr_mem =\n-\t\t\tvq->virtio_net_hdr_mz->phys_addr;\n-\t\tmemset(vq->virtio_net_hdr_mz->addr, 0,\n-\t\t\tvq_size * hw->vtnet_hdr_size);\n+\t\tvq->virtio_net_hdr_mz = hdr_mz;\n+\t\tvq->virtio_net_hdr_mem = hdr_mz->phys_addr;\n+\n+\t\ttxr = hdr_mz->addr;\n+\t\tmemset(txr, 0, vq_size * sizeof(*txr));\n+\t\tfor (i = 0; i < vq_size; i++) {\n+\t\t\tstruct vring_desc *start_dp = txr[i].tx_indir;\n+\n+\t\t\tvring_desc_init(start_dp, VIRTIO_MAX_INDIRECT);\n+\n+\t\t\t/* first indirect descriptor is always the tx header */\n+\t\t\tstart_dp->addr = vq->virtio_net_hdr_mem\n+\t\t\t\t+ i * sizeof(*txr)\n+\t\t\t\t+ offsetof(struct virtio_tx_region, tx_hdr);\n+\n+\t\t\tstart_dp->len = vq->hw->vtnet_hdr_size;\n+\t\t\tstart_dp->flags = VRING_DESC_F_NEXT;\n+\t\t}\n \t} else if (queue_type == VTNET_CQ) {\n \t\t/* Allocate a page for control vq command, data and status */\n \t\tsnprintf(vq_name, sizeof(vq_name), \"port%d_cvq_hdrzone\",\ndiff --git a/drivers/net/virtio/virtio_ethdev.h b/drivers/net/virtio/virtio_ethdev.h\nindex 9026d42..07a9265 100644\n--- a/drivers/net/virtio/virtio_ethdev.h\n+++ b/drivers/net/virtio/virtio_ethdev.h\n@@ -64,7 +64,8 @@\n \t 1u << VIRTIO_NET_F_CTRL_VQ\t  |\t\\\n \t 1u << VIRTIO_NET_F_CTRL_RX\t  |\t\\\n \t 1u << VIRTIO_NET_F_CTRL_VLAN\t  |\t\\\n-\t 1u << VIRTIO_NET_F_MRG_RXBUF)\n+\t 1u << VIRTIO_NET_F_MRG_RXBUF     |\t\\\n+\t 1u << VIRTIO_RING_F_INDIRECT_DESC)\n \n /*\n  * CQ function prototype\ndiff --git a/drivers/net/virtio/virtio_rxtx.c b/drivers/net/virtio/virtio_rxtx.c\nindex dbe6665..f68ab8f 100644\n--- a/drivers/net/virtio/virtio_rxtx.c\n+++ b/drivers/net/virtio/virtio_rxtx.c\n@@ -199,14 +199,15 @@ virtqueue_enqueue_recv_refill(struct virtqueue *vq, struct rte_mbuf *cookie)\n }\n \n static int\n-virtqueue_enqueue_xmit(struct virtqueue *txvq, struct rte_mbuf *cookie)\n+virtqueue_enqueue_xmit(struct virtqueue *txvq, struct rte_mbuf *cookie,\n+\t\t       int use_indirect)\n {\n \tstruct vq_desc_extra *dxp;\n \tstruct vring_desc *start_dp;\n \tuint16_t seg_num = cookie->nb_segs;\n-\tuint16_t needed = 1 + seg_num;\n+\tuint16_t needed = use_indirect ? 1 : 1 + seg_num;\n \tuint16_t head_idx, idx;\n-\tuint16_t head_size = txvq->hw->vtnet_hdr_size;\n+\tunsigned long offs;\n \n \tif (unlikely(txvq->vq_free_cnt == 0))\n \t\treturn -ENOSPC;\n@@ -220,12 +221,29 @@ virtqueue_enqueue_xmit(struct virtqueue *txvq, struct rte_mbuf *cookie)\n \tdxp = &txvq->vq_descx[idx];\n \tdxp->cookie = (void *)cookie;\n \tdxp->ndescs = needed;\n-\n \tstart_dp = txvq->vq_ring.desc;\n-\tstart_dp[idx].addr =\n-\t\ttxvq->virtio_net_hdr_mem + idx * head_size;\n-\tstart_dp[idx].len = (uint32_t)head_size;\n-\tstart_dp[idx].flags = VRING_DESC_F_NEXT;\n+\n+\tif (use_indirect) {\n+\t\tstruct virtio_tx_region *txr\n+\t\t\t= txvq->virtio_net_hdr_mz->addr;\n+\n+\t\toffs = idx * sizeof(struct virtio_tx_region)\n+\t\t\t+ offsetof(struct virtio_tx_region, tx_indir);\n+\n+\t\tstart_dp[idx].addr  = txvq->virtio_net_hdr_mem + offs;\n+\t\tstart_dp[idx].len   = (seg_num + 1) * sizeof(struct vring_desc);\n+\t\tstart_dp[idx].flags = VRING_DESC_F_INDIRECT;\n+\n+\t\tstart_dp = txr[idx].tx_indir;\n+\t\tidx = 0;\n+\t} else {\n+\t\toffs = idx * sizeof(struct virtio_tx_region)\n+\t\t\t+ offsetof(struct virtio_tx_region, tx_hdr);\n+\n+\t\tstart_dp[idx].addr  = txvq->virtio_net_hdr_mem + offs;\n+\t\tstart_dp[idx].len   = txvq->hw->vtnet_hdr_size;\n+\t\tstart_dp[idx].flags = VRING_DESC_F_NEXT;\n+\t}\n \n \tfor (; ((seg_num > 0) && (cookie != NULL)); seg_num--) {\n \t\tidx = start_dp[idx].next;\n@@ -236,7 +254,12 @@ virtqueue_enqueue_xmit(struct virtqueue *txvq, struct rte_mbuf *cookie)\n \t}\n \n \tstart_dp[idx].flags &= ~VRING_DESC_F_NEXT;\n-\tidx = start_dp[idx].next;\n+\n+\tif (use_indirect)\n+\t\tidx = txvq->vq_ring.desc[head_idx].next;\n+\telse\n+\t\tidx = start_dp[idx].next;\n+\n \ttxvq->vq_desc_head_idx = idx;\n \tif (txvq->vq_desc_head_idx == VQ_RING_DESC_CHAIN_END)\n \t\ttxvq->vq_desc_tail_idx = idx;\n@@ -261,7 +284,7 @@ static void\n virtio_dev_vring_start(struct virtqueue *vq, int queue_type)\n {\n \tstruct rte_mbuf *m;\n-\tint i, nbufs, error, size = vq->vq_nentries;\n+\tint nbufs, error, size = vq->vq_nentries;\n \tstruct vring *vr = &vq->vq_ring;\n \tuint8_t *ring_mem = vq->vq_ring_virt_mem;\n \n@@ -279,10 +302,7 @@ virtio_dev_vring_start(struct virtqueue *vq, int queue_type)\n \tvq->vq_free_cnt = vq->vq_nentries;\n \tmemset(vq->vq_descx, 0, sizeof(struct vq_desc_extra) * vq->vq_nentries);\n \n-\t/* Chain all the descriptors in the ring with an END */\n-\tfor (i = 0; i < size - 1; i++)\n-\t\tvr->desc[i].next = (uint16_t)(i + 1);\n-\tvr->desc[i].next = VQ_RING_DESC_CHAIN_END;\n+\tvring_desc_init(vr->desc, size);\n \n \t/*\n \t * Disable device(host) interrupting guest\n@@ -760,7 +780,15 @@ virtio_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)\n \n \tfor (nb_tx = 0; nb_tx < nb_pkts; nb_tx++) {\n \t\tstruct rte_mbuf *txm = tx_pkts[nb_tx];\n-\t\tint need = txm->nb_segs - txvq->vq_free_cnt + 1;\n+\t\tint use_indirect, slots, need;\n+\n+\t\tuse_indirect = vtpci_with_feature(txvq->hw,\n+\t\t\t\t\t\t  VIRTIO_RING_F_INDIRECT_DESC)\n+\t\t\t&& (txm->nb_segs < VIRTIO_MAX_TX_INDIRECT);\n+\n+\t\t/* How many ring entries are needed to this Tx? */\n+\t\tslots = use_indirect ? 1 : 1 + txm->nb_segs;\n+\t\tneed = slots - txvq->vq_free_cnt;\n \n \t\t/* Positive value indicates it need free vring descriptors */\n \t\tif (need > 0) {\n@@ -769,7 +797,7 @@ virtio_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)\n \t\t\tneed = RTE_MIN(need, (int)nb_used);\n \n \t\t\tvirtio_xmit_cleanup(txvq, need);\n-\t\t\tneed = txm->nb_segs - txvq->vq_free_cnt + 1;\n+\t\t\tneed = slots - txvq->vq_free_cnt;\n \t\t\tif (unlikely(need > 0)) {\n \t\t\t\tPMD_TX_LOG(ERR,\n \t\t\t\t\t   \"No free tx descriptors to transmit\");\n@@ -787,7 +815,7 @@ virtio_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)\n \t\t}\n \n \t\t/* Enqueue Packet buffers */\n-\t\terror = virtqueue_enqueue_xmit(txvq, txm);\n+\t\terror = virtqueue_enqueue_xmit(txvq, txm, use_indirect);\n \t\tif (unlikely(error)) {\n \t\t\tif (error == ENOSPC)\n \t\t\t\tPMD_TX_LOG(ERR, \"virtqueue_enqueue Free count = 0\");\ndiff --git a/drivers/net/virtio/virtqueue.h b/drivers/net/virtio/virtqueue.h\nindex 7789411..fe3fa66 100644\n--- a/drivers/net/virtio/virtqueue.h\n+++ b/drivers/net/virtio/virtqueue.h\n@@ -237,6 +237,25 @@ struct virtio_net_hdr_mrg_rxbuf {\n \tuint16_t num_buffers; /**< Number of merged rx buffers */\n };\n \n+/* Region reserved to allow for transmit header and indirect ring */\n+#define VIRTIO_MAX_TX_INDIRECT 8\n+struct virtio_tx_region {\n+\tstruct virtio_net_hdr_mrg_rxbuf tx_hdr;\n+\tstruct vring_desc tx_indir[VIRTIO_MAX_TX_INDIRECT]\n+\t\t\t   __attribute__((__aligned__(16)));\n+};\n+\n+/* Chain all the descriptors in the ring with an END */\n+static inline void\n+vring_desc_init(struct vring_desc *dp, uint16_t n)\n+{\n+\tuint16_t i;\n+\n+\tfor (i = 0; i < n - 1; i++)\n+\t\tdp[i].next = (uint16_t)(i + 1);\n+\tdp[i].next = VQ_RING_DESC_CHAIN_END;\n+}\n+\n /**\n  * Tell the backend not to interrupt us.\n  */\n",
    "prefixes": [
        "dpdk-dev",
        "3/5"
    ]
}