From patchwork Thu Mar 18 18:20:41 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bruce Richardson X-Patchwork-Id: 89506 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id AFB58A0561; Thu, 18 Mar 2021 19:21:43 +0100 (CET) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id E8989140EF7; Thu, 18 Mar 2021 19:21:36 +0100 (CET) Received: from mga17.intel.com (mga17.intel.com [192.55.52.151]) by mails.dpdk.org (Postfix) with ESMTP id B23FF140EE6 for ; Thu, 18 Mar 2021 19:21:34 +0100 (CET) IronPort-SDR: XiPVc/DQYpR/1xahfFnWVbtJ5BCAhQytYLbYW8eUx8b1yFFEwe9tDGlGOxtWsgK3cQ2jtTJtnO 3bwS3qs5ZhNQ== X-IronPort-AV: E=McAfee;i="6000,8403,9927"; a="169668106" X-IronPort-AV: E=Sophos;i="5.81,259,1610438400"; d="scan'208";a="169668106" Received: from orsmga007.jf.intel.com ([10.7.209.58]) by fmsmga107.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 18 Mar 2021 11:21:33 -0700 IronPort-SDR: aGBe+eRqcDSrR48mfBLrss9M0alMt0XJazvmehUoHzDku/wbnHhXpEg/HOrBCjMIb/jALgCWdt 7QYzzvfoRv/g== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.81,259,1610438400"; d="scan'208";a="411998935" Received: from silpixa00399126.ir.intel.com ([10.237.223.184]) by orsmga007.jf.intel.com with ESMTP; 18 Mar 2021 11:21:31 -0700 From: Bruce Richardson To: dev@dpdk.org Cc: Kevin Laatz , Bruce Richardson Date: Thu, 18 Mar 2021 18:20:41 +0000 Message-Id: <20210318182042.43658-6-bruce.richardson@intel.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20210318182042.43658-1-bruce.richardson@intel.com> References: <20210318182042.43658-1-bruce.richardson@intel.com> MIME-Version: 1.0 Subject: [dpdk-dev] [PATCH v1 5/6] raw/ioat: add api to query remaining ring space X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" From: Kevin Laatz Add a new API to query remaining descriptor ring capacity. This API is useful, for example, when an application needs to enqueue a fragmented packet and wants to ensure that all segments of the packet will be enqueued together. Signed-off-by: Kevin Laatz Tested-by: Sunil Pai G --- drivers/raw/ioat/ioat_rawdev_test.c | 136 +++++++++++++++++++++++++ drivers/raw/ioat/rte_ioat_rawdev_fns.h | 46 +++++++++ 2 files changed, 182 insertions(+) diff --git a/drivers/raw/ioat/ioat_rawdev_test.c b/drivers/raw/ioat/ioat_rawdev_test.c index 3de8273704..3a4c7a5161 100644 --- a/drivers/raw/ioat/ioat_rawdev_test.c +++ b/drivers/raw/ioat/ioat_rawdev_test.c @@ -202,6 +202,138 @@ test_enqueue_fill(int dev_id) return 0; } +static int +test_burst_capacity(int dev_id, unsigned int ring_size) +{ + unsigned int i, j; + unsigned int length = 1024; + + /* Test to make sure it does not enqueue if we cannot fit the entire burst */ + do { +#define BURST_SIZE 19 +#define EXPECTED_REJECTS 5 + struct rte_mbuf *srcs[BURST_SIZE], *dsts[BURST_SIZE]; + struct rte_mbuf *completed_src[BURST_SIZE]; + struct rte_mbuf *completed_dst[BURST_SIZE]; + unsigned int cnt_success = 0; + unsigned int cnt_rejected = 0; + unsigned int valid_iters = (ring_size - 1)/BURST_SIZE; + + /* Enqueue burst until they won't fit + some extra iterations which should + * be rejected + */ + for (i = 0; i < valid_iters + EXPECTED_REJECTS; i++) { + if (rte_ioat_burst_capacity(dev_id) >= BURST_SIZE) { + for (j = 0; j < BURST_SIZE; j++) { + + srcs[j] = rte_pktmbuf_alloc(pool); + dsts[j] = rte_pktmbuf_alloc(pool); + srcs[j]->data_len = srcs[j]->pkt_len = length; + dsts[j]->data_len = dsts[j]->pkt_len = length; + + if (rte_ioat_enqueue_copy(dev_id, + srcs[j]->buf_iova + srcs[j]->data_off, + dsts[j]->buf_iova + dsts[j]->data_off, + length, + (uintptr_t)srcs[j], + (uintptr_t)dsts[j]) != 1) { + PRINT_ERR("Error with rte_ioat_enqueue_copy\n"); + return -1; + } + + rte_pktmbuf_free(srcs[j]); + rte_pktmbuf_free(dsts[j]); + cnt_success++; + } + } else { + cnt_rejected++; + } + } + + /* do cleanup before next tests */ + rte_ioat_perform_ops(dev_id); + usleep(100); + for (i = 0; i < valid_iters; i++) { + if (rte_ioat_completed_ops(dev_id, BURST_SIZE, (void *)completed_src, + (void *)completed_dst) != BURST_SIZE) { + PRINT_ERR("error with completions\n"); + return -1; + } + } + + printf("successful_enqueues: %u expected_successful: %u rejected_iters: %u expected_rejects: %u\n", + cnt_success, valid_iters * BURST_SIZE, cnt_rejected, + EXPECTED_REJECTS); + + if (!(cnt_success == (valid_iters * BURST_SIZE)) && + !(cnt_rejected == EXPECTED_REJECTS)) { + PRINT_ERR("Burst Capacity test failed\n"); + return -1; + } + } while (0); + + /* Verify that space is taken and free'd as expected. + * Repeat the test to verify wrap-around handling is correct in + * rte_ioat_burst_capacity(). + */ + for (i = 0; i < ring_size / 32; i++) { + struct rte_mbuf *srcs[64], *dsts[64]; + struct rte_mbuf *completed_src[64]; + struct rte_mbuf *completed_dst[64]; + + /* Make sure the ring is clean before we start */ + if (rte_ioat_burst_capacity(dev_id) != ring_size - 1) { + PRINT_ERR("Error, ring should be empty\n"); + return -1; + } + + /* Enqueue 64 mbufs & verify that space is taken */ + for (j = 0; j < 64; j++) { + srcs[j] = rte_pktmbuf_alloc(pool); + dsts[j] = rte_pktmbuf_alloc(pool); + srcs[j]->data_len = srcs[j]->pkt_len = length; + dsts[j]->data_len = dsts[j]->pkt_len = length; + + if (rte_ioat_enqueue_copy(dev_id, + srcs[j]->buf_iova + srcs[j]->data_off, + dsts[j]->buf_iova + dsts[j]->data_off, + length, + (uintptr_t)srcs[j], + (uintptr_t)dsts[j]) != 1) { + PRINT_ERR("Error with rte_ioat_enqueue_copy\n"); + return -1; + } + + rte_pktmbuf_free(srcs[j]); + rte_pktmbuf_free(dsts[j]); + } + + if (rte_ioat_burst_capacity(dev_id) != (ring_size - 1) - 64) { + PRINT_ERR("Error, space available not as expected\n"); + return -1; + } + + /* Copy, gather completions, and make sure the space is free'd again */ + rte_ioat_perform_ops(dev_id); + usleep(100); + for (j = 0; j < 2; j++) { + if (rte_ioat_completed_ops(dev_id, 32, (void *)completed_src, + (void *)completed_dst) != 32) { + PRINT_ERR("error with completions\n"); + return -1; + } + } + + if (rte_ioat_burst_capacity(dev_id) != ring_size - 1) { + PRINT_ERR("Error, space available not as expected\n"); + return -1; + } + + } + + return 0; +} + int ioat_rawdev_test(uint16_t dev_id) { @@ -310,6 +442,10 @@ ioat_rawdev_test(uint16_t dev_id) } printf("\n"); + printf("Running Burst Capacity Test\n"); + if (test_burst_capacity(dev_id, expected_ring_size[dev_id]) != 0) + goto err; + rte_rawdev_stop(dev_id); if (rte_rawdev_xstats_reset(dev_id, NULL, 0) != 0) { PRINT_ERR("Error resetting xstat values\n"); diff --git a/drivers/raw/ioat/rte_ioat_rawdev_fns.h b/drivers/raw/ioat/rte_ioat_rawdev_fns.h index 231aa72612..ba40f29c25 100644 --- a/drivers/raw/ioat/rte_ioat_rawdev_fns.h +++ b/drivers/raw/ioat/rte_ioat_rawdev_fns.h @@ -199,6 +199,19 @@ struct rte_idxd_rawdev { struct rte_idxd_user_hdl *hdl_ring; }; +static __rte_always_inline uint16_t +__ioat_burst_capacity(int dev_id) +{ + struct rte_ioat_rawdev *ioat = + (struct rte_ioat_rawdev *)rte_rawdevs[dev_id].dev_private; + unsigned short size = ioat->ring_size - 1; + unsigned short read = ioat->next_read; + unsigned short write = ioat->next_write; + unsigned short space = size - (write - read); + + return space; +} + static __rte_always_inline int __ioat_write_desc(int dev_id, uint32_t op, uint64_t src, phys_addr_t dst, unsigned int length, uintptr_t src_hdl, uintptr_t dst_hdl) @@ -357,6 +370,28 @@ __ioat_completed_ops(int dev_id, uint8_t max_copies, return count; } +static __rte_always_inline uint16_t +__idxd_burst_capacity(int dev_id) +{ + struct rte_idxd_rawdev *idxd = + (struct rte_idxd_rawdev *)rte_rawdevs[dev_id].dev_private; + uint16_t write_idx = idxd->batch_start + idxd->batch_size; + uint16_t used_space; + + /* Check for space in the batch ring */ + if ((idxd->batch_idx_read == 0 && idxd->batch_idx_write == idxd->max_batches) || + idxd->batch_idx_write + 1 == idxd->batch_idx_read) + return 0; + + /* for descriptors, check for wrap-around on write but not read */ + if (idxd->hdls_read > write_idx) + write_idx += idxd->desc_ring_mask + 1; + used_space = write_idx - idxd->hdls_read; + + /* Return amount of free space in the descriptor ring */ + return idxd->desc_ring_mask - used_space; +} + static __rte_always_inline int __idxd_write_desc(int dev_id, const uint32_t op_flags, @@ -538,6 +573,17 @@ __idxd_completed_ops(int dev_id, uint8_t max_ops, return n; } +static inline uint16_t +rte_ioat_burst_capacity(int dev_id) +{ + enum rte_ioat_dev_type *type = + (enum rte_ioat_dev_type *)rte_rawdevs[dev_id].dev_private; + if (*type == RTE_IDXD_DEV) + return __idxd_burst_capacity(dev_id); + else + return __ioat_burst_capacity(dev_id); +} + static inline int rte_ioat_enqueue_fill(int dev_id, uint64_t pattern, phys_addr_t dst, unsigned int len, uintptr_t dst_hdl)