From patchwork Fri Sep 1 03:28:18 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Renyong Wan X-Patchwork-Id: 131042 X-Patchwork-Delegate: ferruh.yigit@amd.com 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 1108642219; Fri, 1 Sep 2023 05:32:44 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id A6CE0402B0; Fri, 1 Sep 2023 05:31:30 +0200 (CEST) Received: from VLXDG1SPAM1.ramaxel.com (email.ramaxel.com [221.4.138.186]) by mails.dpdk.org (Postfix) with ESMTP id 2DD19402AE for ; Fri, 1 Sep 2023 05:31:28 +0200 (CEST) Received: from V12DG1MBS03.ramaxel.local ([172.26.18.33]) by VLXDG1SPAM1.ramaxel.com with ESMTP id 3813SrjI033292; Fri, 1 Sep 2023 11:28:53 +0800 (GMT-8) (envelope-from wanry@3snic.com) Received: from localhost.localdomain (10.64.136.151) by V12DG1MBS03.ramaxel.local (172.26.18.33) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.2375.17; Fri, 1 Sep 2023 11:28:52 +0800 From: To: CC: , Renyong Wan , Steven Song Subject: [PATCH v3 08/32] net/sssnic/base: add work queue Date: Fri, 1 Sep 2023 11:28:18 +0800 Message-ID: <20230901032842.223547-9-wanry@3snic.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230901032842.223547-1-wanry@3snic.com> References: <20230901032842.223547-1-wanry@3snic.com> MIME-Version: 1.0 X-Originating-IP: [10.64.136.151] X-ClientProxiedBy: V12DG1MBS03.ramaxel.local (172.26.18.33) To V12DG1MBS03.ramaxel.local (172.26.18.33) X-DNSRBL: X-SPAM-SOURCE-CHECK: pass X-MAIL: VLXDG1SPAM1.ramaxel.com 3813SrjI033292 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 From: Renyong Wan Work queue is used to maintain hardware queue information by driver, it is usually used in control queue, rx queue and tx queue. Signed-off-by: Steven Song Signed-off-by: Renyong Wan --- v2: * Removed error.h from including files. --- drivers/net/sssnic/base/meson.build | 1 + drivers/net/sssnic/base/sssnic_workq.c | 141 +++++++++++++++++++++++++ drivers/net/sssnic/base/sssnic_workq.h | 108 +++++++++++++++++++ 3 files changed, 250 insertions(+) create mode 100644 drivers/net/sssnic/base/sssnic_workq.c create mode 100644 drivers/net/sssnic/base/sssnic_workq.h diff --git a/drivers/net/sssnic/base/meson.build b/drivers/net/sssnic/base/meson.build index 4abd1a0daf..7c23a82ff3 100644 --- a/drivers/net/sssnic/base/meson.build +++ b/drivers/net/sssnic/base/meson.build @@ -6,6 +6,7 @@ sources = [ 'sssnic_eventq.c', 'sssnic_msg.c', 'sssnic_mbox.c', + 'sssnic_workq.c', ] c_args = cflags diff --git a/drivers/net/sssnic/base/sssnic_workq.c b/drivers/net/sssnic/base/sssnic_workq.c new file mode 100644 index 0000000000..25b7585246 --- /dev/null +++ b/drivers/net/sssnic/base/sssnic_workq.c @@ -0,0 +1,141 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2018-2022 Shenzhen 3SNIC Information Technology Co., Ltd. + */ + +#include +#include +#include +#include + +#include "../sssnic_log.h" +#include "sssnic_workq.h" + +/* Consume num_entries and increase CI + * Return the first entry address of previous CI position + */ +void * +sssnic_workq_consume(struct sssnic_workq *workq, uint16_t num_entries, + uint16_t *ci) +{ + void *e; + uint16_t current_ci; + + if (workq->idle_entries + num_entries > workq->num_entries) + return NULL; + + current_ci = sssnic_workq_ci_get(workq); + e = (void *)sssnic_workq_entry_get(workq, current_ci); + workq->idle_entries += num_entries; + workq->ci += num_entries; + if (ci != NULL) + *ci = current_ci; + + return e; +} + +/* Produce num_entries and increase pi. + * Return the first entry address of previous PI position + */ +void * +sssnic_workq_produce(struct sssnic_workq *workq, uint16_t num_entries, + uint16_t *pi) +{ + void *e; + uint16_t current_pi; + + if (workq->idle_entries < num_entries) + return NULL; + + current_pi = sssnic_workq_pi_get(workq); + e = (void *)sssnic_workq_entry_get(workq, current_pi); + workq->idle_entries -= num_entries; + workq->pi += num_entries; + if (pi != NULL) + *pi = current_pi; + + return e; +} + +static int +sssnic_workq_init(struct sssnic_workq *workq, const char *name, int socket_id, + uint32_t entry_size, uint32_t depth) +{ + char zname[RTE_MEMZONE_NAMESIZE]; + + if (!rte_is_power_of_2(entry_size)) { + PMD_DRV_LOG(ERR, + "The entry size(%u) of workq(%s) is not power of 2", + entry_size, name); + return -EINVAL; + } + + if (!rte_is_power_of_2(depth)) { + PMD_DRV_LOG(ERR, "The depth(%u) of workq(%s) is not power of 2", + depth, name); + return -EINVAL; + } + + workq->buf_size = entry_size * depth; + workq->entry_size = entry_size; + workq->entry_shift = rte_log2_u32(entry_size); + workq->num_entries = depth; + workq->idle_entries = depth; + workq->index_mask = depth - 1; + + snprintf(zname, sizeof(zname), "%s_mz", name); + workq->buf_mz = rte_memzone_reserve_aligned(zname, workq->buf_size, + socket_id, RTE_MEMZONE_IOVA_CONTIG, RTE_PGSIZE_256K); + if (workq->buf_mz == NULL) { + PMD_DRV_LOG(ERR, "Failed to alloc DMA memory for %s", name); + return -ENOMEM; + } + workq->buf_addr = workq->buf_mz->addr; + workq->buf_phyaddr = workq->buf_mz->iova; + + return 0; +} + +static void +sssnic_workq_cleanup(struct sssnic_workq *workq) +{ + if (workq != NULL && workq->buf_mz != NULL) + rte_memzone_free(workq->buf_mz); +} + +/* Cleanup a work queue and free it*/ +void +sssnic_workq_destroy(struct sssnic_workq *workq) +{ + if (workq != NULL) { + sssnic_workq_cleanup(workq); + rte_free(workq); + } +} + +/*Create a work queue and initialize*/ +struct sssnic_workq * +sssnic_workq_new(const char *name, int socket_id, uint32_t entry_size, + uint32_t depth) +{ + int ret; + struct sssnic_workq *workq; + + if (name == NULL) { + PMD_DRV_LOG(ERR, "Bad parameter, workq name is NULL"); + return NULL; + } + + workq = rte_zmalloc(name, sizeof(struct sssnic_workq), 0); + if (workq == NULL) { + PMD_DRV_LOG(ERR, "Could not alloc memory for %s", name); + return NULL; + } + ret = sssnic_workq_init(workq, name, socket_id, entry_size, depth); + if (ret) { + PMD_DRV_LOG(ERR, "Failed to initialize %s", name); + rte_free(workq); + return NULL; + } + + return workq; +} diff --git a/drivers/net/sssnic/base/sssnic_workq.h b/drivers/net/sssnic/base/sssnic_workq.h new file mode 100644 index 0000000000..470aef6409 --- /dev/null +++ b/drivers/net/sssnic/base/sssnic_workq.h @@ -0,0 +1,108 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2018-2022 Shenzhen 3SNIC Information Technology Co., Ltd. + */ + +#ifndef _SSSNIC_WORKQ_H_ +#define _SSSNIC_WORKQ_H_ + +struct sssnic_workq { + /* DMA buffer of entries*/ + const struct rte_memzone *buf_mz; + /* Virtual address of DMA buffer */ + uint8_t *buf_addr; + /* Physic address of DMA buffer */ + uint64_t buf_phyaddr; + /* DMA buffer size */ + uint32_t buf_size; + /* element size */ + uint32_t entry_size; + /* number of bits of entry size */ + uint16_t entry_shift; + /* Max number of entries in buf */ + uint16_t num_entries; + /* Number of entries not be used */ + uint16_t idle_entries; + /* Consumer index */ + uint16_t ci; + /* Producer index */ + uint16_t pi; + /* CI and PI mask */ + uint16_t index_mask; +} __rte_cache_aligned; + +#define SSSNIC_WORKQ_ENTRY_CAST(workq, idx, type) \ + (((type *)((workq)->buf_addr)) + (idx)) +#define SSSNIC_WORKQ_BUF_PHYADDR(workq) ((workq)->buf_phyaddr) + +static inline void * +sssnic_workq_entry_get(struct sssnic_workq *workq, uint32_t index) +{ + return (void *)(workq->buf_addr + (index << workq->entry_shift)); +} + +/* Return the entry address of current CI position. */ +static inline void * +sssnic_workq_peek(struct sssnic_workq *workq) +{ + if ((workq->idle_entries + 1) > workq->num_entries) + return NULL; + + return sssnic_workq_entry_get(workq, workq->ci & workq->index_mask); +} + +static inline uint16_t +sssnic_workq_num_used_entries(struct sssnic_workq *workq) +{ + return workq->num_entries - workq->idle_entries; +} + +static inline uint16_t +sssnic_workq_num_idle_entries(struct sssnic_workq *workq) +{ + return workq->idle_entries; +} + +static inline uint16_t +sssnic_workq_ci_get(struct sssnic_workq *workq) +{ + return workq->ci & workq->index_mask; +} + +static inline uint16_t +sssnic_workq_pi_get(struct sssnic_workq *workq) +{ + return workq->pi & workq->index_mask; +} + +static inline void +sssnic_workq_consume_fast(struct sssnic_workq *workq, uint16_t num_entries) +{ + workq->idle_entries += num_entries; + workq->ci += num_entries; +} + +static inline void +sssnic_workq_produce_fast(struct sssnic_workq *workq, uint16_t num_entries) +{ + workq->idle_entries -= num_entries; + workq->pi += num_entries; +} + +static inline void +sssnic_workq_reset(struct sssnic_workq *workq) +{ + workq->ci = 0; + workq->pi = 0; + workq->idle_entries = workq->num_entries; +} + +void *sssnic_workq_consume(struct sssnic_workq *workq, uint16_t num_entries, + uint16_t *ci); +void *sssnic_workq_produce(struct sssnic_workq *workq, uint16_t num_entries, + uint16_t *pi); + +struct sssnic_workq *sssnic_workq_new(const char *name, int socket_id, + uint32_t entry_size, uint32_t depth); +void sssnic_workq_destroy(struct sssnic_workq *workq); + +#endif /* _SSSNIC_WORKQ_H_ */