From mboxrd@z Thu Jan  1 00:00:00 1970
Return-Path: <dev-bounces@dpdk.org>
Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124])
	by inbox.dpdk.org (Postfix) with ESMTP id 7636A424E7;
	Mon,  4 Sep 2023 06:58:20 +0200 (CEST)
Received: from mails.dpdk.org (localhost [127.0.0.1])
	by mails.dpdk.org (Postfix) with ESMTP id ADD37402EE;
	Mon,  4 Sep 2023 06:57:37 +0200 (CEST)
Received: from VLXDG1SPAM1.ramaxel.com (email.ramaxel.com [221.4.138.186])
 by mails.dpdk.org (Postfix) with ESMTP id 6408C402C7
 for <dev@dpdk.org>; Mon,  4 Sep 2023 06:57:35 +0200 (CEST)
Received: from V12DG1MBS03.ramaxel.local ([172.26.18.33])
 by VLXDG1SPAM1.ramaxel.com with ESMTP id 3844vB2i054253;
 Mon, 4 Sep 2023 12:57:11 +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; Mon, 4 Sep 2023 12:57:10 +0800
From: <wanry@3snic.com>
To: <dev@dpdk.org>
CC: <ferruh.yigit@amd.com>, Renyong Wan <wanry@3snic.com>, Steven Song
 <steven.song@3snic.com>
Subject: [PATCH v5 08/32] net/sssnic/base: add work queue
Date: Mon, 4 Sep 2023 12:56:34 +0800
Message-ID: <20230904045658.238185-9-wanry@3snic.com>
X-Mailer: git-send-email 2.25.1
In-Reply-To: <20230904045658.238185-1-wanry@3snic.com>
References: <20230904045658.238185-1-wanry@3snic.com>
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Type: text/plain
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 3844vB2i054253
X-BeenThere: dev@dpdk.org
X-Mailman-Version: 2.1.29
Precedence: list
List-Id: DPDK patches and discussions <dev.dpdk.org>
List-Unsubscribe: <https://mails.dpdk.org/options/dev>,
 <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>,
 <mailto:dev-request@dpdk.org?subject=subscribe>
Errors-To: dev-bounces@dpdk.org

From: Renyong Wan <wanry@3snic.com>

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 <steven.song@3snic.com>
Signed-off-by: Renyong Wan <wanry@3snic.com>
---
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 <rte_common.h>
+#include <rte_malloc.h>
+#include <rte_memcpy.h>
+#include <rte_memzone.h>
+
+#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_ */
-- 
2.27.0