xref: /spdk/test/external_code/accel/module.c (revision ee02082435277878c711ede7d612063ddc074c0b)
1d58439d3SEugene Kobyak /*   SPDX-License-Identifier: BSD-3-Clause
2d58439d3SEugene Kobyak  *   Copyright (C) 2023 Intel Corporation.
3*ee020824SAlexey Marchuk  *   Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES.
4d58439d3SEugene Kobyak  *   All rights reserved.
5d58439d3SEugene Kobyak  */
6d58439d3SEugene Kobyak 
7d58439d3SEugene Kobyak #include "spdk/accel.h"
8d58439d3SEugene Kobyak #include "spdk/accel_module.h"
9d58439d3SEugene Kobyak #include "spdk/thread.h"
10d58439d3SEugene Kobyak 
11d58439d3SEugene Kobyak static struct spdk_accel_module_if g_ex_module;
12d58439d3SEugene Kobyak 
13d58439d3SEugene Kobyak struct ex_accel_io_channel {
14d58439d3SEugene Kobyak 	struct spdk_poller *completion_poller;
15*ee020824SAlexey Marchuk 	STAILQ_HEAD(, spdk_accel_task) tasks_to_complete;
16d58439d3SEugene Kobyak };
17d58439d3SEugene Kobyak 
18d58439d3SEugene Kobyak static int
ex_accel_copy_iovs(struct iovec * dst_iovs,uint32_t dst_iovcnt,struct iovec * src_iovs,uint32_t src_iovcnt)19d58439d3SEugene Kobyak ex_accel_copy_iovs(struct iovec *dst_iovs, uint32_t dst_iovcnt,
20d58439d3SEugene Kobyak 		   struct iovec *src_iovs, uint32_t src_iovcnt)
21d58439d3SEugene Kobyak {
22d58439d3SEugene Kobyak 	struct spdk_ioviter iter;
23d58439d3SEugene Kobyak 	void *src, *dst;
24d58439d3SEugene Kobyak 	size_t len;
25d58439d3SEugene Kobyak 
26d58439d3SEugene Kobyak 	for (len = spdk_ioviter_first(&iter, src_iovs, src_iovcnt,
27d58439d3SEugene Kobyak 				      dst_iovs, dst_iovcnt, &src, &dst);
28d58439d3SEugene Kobyak 	     len != 0;
29d58439d3SEugene Kobyak 	     len = spdk_ioviter_next(&iter, &src, &dst)) {
30d58439d3SEugene Kobyak 		memcpy(dst, src, len);
31d58439d3SEugene Kobyak 	}
32d58439d3SEugene Kobyak 
33d58439d3SEugene Kobyak 	return 0;
34d58439d3SEugene Kobyak }
35d58439d3SEugene Kobyak 
36d58439d3SEugene Kobyak static int
ex_accel_compare(struct iovec * src_iovs,uint32_t src_iovcnt,struct iovec * src2_iovs,uint32_t src2_iovcnt)37d58439d3SEugene Kobyak ex_accel_compare(struct iovec *src_iovs, uint32_t src_iovcnt,
38d58439d3SEugene Kobyak 		 struct iovec *src2_iovs, uint32_t src2_iovcnt)
39d58439d3SEugene Kobyak {
40d58439d3SEugene Kobyak 	if (spdk_unlikely(src_iovcnt != 1 || src2_iovcnt != 1)) {
41d58439d3SEugene Kobyak 		return -EINVAL;
42d58439d3SEugene Kobyak 	}
43d58439d3SEugene Kobyak 
44d58439d3SEugene Kobyak 	if (spdk_unlikely(src_iovs[0].iov_len != src2_iovs[0].iov_len)) {
45d58439d3SEugene Kobyak 		return -EINVAL;
46d58439d3SEugene Kobyak 	}
47d58439d3SEugene Kobyak 
48d58439d3SEugene Kobyak 	return memcmp(src_iovs[0].iov_base, src2_iovs[0].iov_base, src_iovs[0].iov_len);
49d58439d3SEugene Kobyak }
50d58439d3SEugene Kobyak 
51d58439d3SEugene Kobyak static int
ex_accel_fill(struct iovec * iovs,uint32_t iovcnt,uint8_t fill)52d58439d3SEugene Kobyak ex_accel_fill(struct iovec *iovs, uint32_t iovcnt, uint8_t fill)
53d58439d3SEugene Kobyak {
54d58439d3SEugene Kobyak 	void *dst;
55d58439d3SEugene Kobyak 	size_t nbytes;
56d58439d3SEugene Kobyak 
57d58439d3SEugene Kobyak 	if (spdk_unlikely(iovcnt != 1)) {
58d58439d3SEugene Kobyak 		fprintf(stderr, "Unexpected number of iovs: %" PRIu32 "\n", iovcnt);
59d58439d3SEugene Kobyak 		return -EINVAL;
60d58439d3SEugene Kobyak 	}
61d58439d3SEugene Kobyak 
62d58439d3SEugene Kobyak 	dst = iovs[0].iov_base;
63d58439d3SEugene Kobyak 	nbytes = iovs[0].iov_len;
64d58439d3SEugene Kobyak 
65d58439d3SEugene Kobyak 	memset(dst, fill, nbytes);
66d58439d3SEugene Kobyak 
67d58439d3SEugene Kobyak 	return 0;
68d58439d3SEugene Kobyak }
69d58439d3SEugene Kobyak 
70d58439d3SEugene Kobyak static int
ex_accel_comp_poll(void * arg)71d58439d3SEugene Kobyak ex_accel_comp_poll(void *arg)
72d58439d3SEugene Kobyak {
73d58439d3SEugene Kobyak 	struct ex_accel_io_channel *ex_ch = arg;
74*ee020824SAlexey Marchuk 	STAILQ_HEAD(, spdk_accel_task) tasks_to_complete;
75d58439d3SEugene Kobyak 	struct spdk_accel_task *accel_task;
76d58439d3SEugene Kobyak 
77*ee020824SAlexey Marchuk 	if (STAILQ_EMPTY(&ex_ch->tasks_to_complete)) {
78d58439d3SEugene Kobyak 		return SPDK_POLLER_IDLE;
79d58439d3SEugene Kobyak 	}
80d58439d3SEugene Kobyak 
81*ee020824SAlexey Marchuk 	STAILQ_INIT(&tasks_to_complete);
82*ee020824SAlexey Marchuk 	STAILQ_SWAP(&tasks_to_complete, &ex_ch->tasks_to_complete, spdk_accel_task);
83d58439d3SEugene Kobyak 
84*ee020824SAlexey Marchuk 	while ((accel_task = STAILQ_FIRST(&tasks_to_complete))) {
85*ee020824SAlexey Marchuk 		STAILQ_REMOVE_HEAD(&tasks_to_complete, link);
86d58439d3SEugene Kobyak 		spdk_accel_task_complete(accel_task, accel_task->status);
87d58439d3SEugene Kobyak 	}
88d58439d3SEugene Kobyak 
89d58439d3SEugene Kobyak 	return SPDK_POLLER_BUSY;
90d58439d3SEugene Kobyak }
91d58439d3SEugene Kobyak 
92d58439d3SEugene Kobyak static int
ex_accel_create_cb(void * io_device,void * ctx_buf)93d58439d3SEugene Kobyak ex_accel_create_cb(void *io_device, void *ctx_buf)
94d58439d3SEugene Kobyak {
95d58439d3SEugene Kobyak 	struct ex_accel_io_channel *ex_ch = ctx_buf;
96d58439d3SEugene Kobyak 
97*ee020824SAlexey Marchuk 	STAILQ_INIT(&ex_ch->tasks_to_complete);
98d58439d3SEugene Kobyak 	ex_ch->completion_poller = SPDK_POLLER_REGISTER(ex_accel_comp_poll, ex_ch, 0);
99d58439d3SEugene Kobyak 
100d58439d3SEugene Kobyak 	return 0;
101d58439d3SEugene Kobyak }
102d58439d3SEugene Kobyak 
103d58439d3SEugene Kobyak static void
ex_accel_destroy_cb(void * io_device,void * ctx_buf)104d58439d3SEugene Kobyak ex_accel_destroy_cb(void *io_device, void *ctx_buf)
105d58439d3SEugene Kobyak {
106d58439d3SEugene Kobyak 	struct ex_accel_io_channel *ex_ch = ctx_buf;
107d58439d3SEugene Kobyak 
108d58439d3SEugene Kobyak 	spdk_poller_unregister(&ex_ch->completion_poller);
109d58439d3SEugene Kobyak }
110d58439d3SEugene Kobyak 
111d58439d3SEugene Kobyak static int
ex_accel_module_init(void)112d58439d3SEugene Kobyak ex_accel_module_init(void)
113d58439d3SEugene Kobyak {
114d58439d3SEugene Kobyak 	spdk_io_device_register(&g_ex_module, ex_accel_create_cb, ex_accel_destroy_cb,
115d58439d3SEugene Kobyak 				sizeof(struct ex_accel_io_channel), "external_accel_module");
116d58439d3SEugene Kobyak 
117d58439d3SEugene Kobyak 	return 0;
118d58439d3SEugene Kobyak }
119d58439d3SEugene Kobyak 
120d58439d3SEugene Kobyak static void
ex_accel_module_fini(void * ctx)121d58439d3SEugene Kobyak ex_accel_module_fini(void *ctx)
122d58439d3SEugene Kobyak {
123d58439d3SEugene Kobyak 	spdk_io_device_unregister(&g_ex_module, NULL);
124d58439d3SEugene Kobyak 	spdk_accel_module_finish();
125d58439d3SEugene Kobyak }
126d58439d3SEugene Kobyak 
127d58439d3SEugene Kobyak static size_t
ex_accel_module_get_ctx_size(void)128d58439d3SEugene Kobyak ex_accel_module_get_ctx_size(void)
129d58439d3SEugene Kobyak {
130d58439d3SEugene Kobyak 	return sizeof(struct spdk_accel_task);
131d58439d3SEugene Kobyak }
132d58439d3SEugene Kobyak 
133d58439d3SEugene Kobyak inline static void
add_to_comp_list(struct ex_accel_io_channel * ex_ch,struct spdk_accel_task * accel_task)134d58439d3SEugene Kobyak add_to_comp_list(struct ex_accel_io_channel *ex_ch, struct spdk_accel_task *accel_task)
135d58439d3SEugene Kobyak {
136*ee020824SAlexey Marchuk 	STAILQ_INSERT_TAIL(&ex_ch->tasks_to_complete, accel_task, link);
137d58439d3SEugene Kobyak }
138d58439d3SEugene Kobyak 
139d58439d3SEugene Kobyak static bool
ex_accel_supports_opcode(enum spdk_accel_opcode opc)140d58439d3SEugene Kobyak ex_accel_supports_opcode(enum spdk_accel_opcode opc)
141d58439d3SEugene Kobyak {
142d58439d3SEugene Kobyak 	switch (opc) {
143d58439d3SEugene Kobyak 	case SPDK_ACCEL_OPC_COPY:
144d58439d3SEugene Kobyak 	case SPDK_ACCEL_OPC_FILL:
145d58439d3SEugene Kobyak 	case SPDK_ACCEL_OPC_COMPARE:
146d58439d3SEugene Kobyak 		return true;
147d58439d3SEugene Kobyak 	default:
148d58439d3SEugene Kobyak 		return false;
149d58439d3SEugene Kobyak 	}
150d58439d3SEugene Kobyak }
151d58439d3SEugene Kobyak 
152d58439d3SEugene Kobyak static struct spdk_io_channel *
ex_accel_get_io_channel(void)153d58439d3SEugene Kobyak ex_accel_get_io_channel(void)
154d58439d3SEugene Kobyak {
155d58439d3SEugene Kobyak 	return spdk_get_io_channel(&g_ex_module);
156d58439d3SEugene Kobyak }
157d58439d3SEugene Kobyak 
158d58439d3SEugene Kobyak static int
ex_accel_submit_tasks(struct spdk_io_channel * ch,struct spdk_accel_task * accel_task)159d58439d3SEugene Kobyak ex_accel_submit_tasks(struct spdk_io_channel *ch, struct spdk_accel_task *accel_task)
160d58439d3SEugene Kobyak {
161d58439d3SEugene Kobyak 	struct ex_accel_io_channel *ex_ch = spdk_io_channel_get_ctx(ch);
162d58439d3SEugene Kobyak 
163d58439d3SEugene Kobyak 	printf("Running on accel module task with code: %" PRIu8 "\n", accel_task->op_code);
164d58439d3SEugene Kobyak 	switch (accel_task->op_code) {
165d58439d3SEugene Kobyak 	case SPDK_ACCEL_OPC_COPY:
166d58439d3SEugene Kobyak 		accel_task->status = ex_accel_copy_iovs(accel_task->d.iovs, accel_task->d.iovcnt,
167d58439d3SEugene Kobyak 							accel_task->s.iovs, accel_task->s.iovcnt);
168d58439d3SEugene Kobyak 		break;
169d58439d3SEugene Kobyak 	case SPDK_ACCEL_OPC_FILL:
170d58439d3SEugene Kobyak 		accel_task->status = ex_accel_fill(accel_task->d.iovs, accel_task->d.iovcnt,
171d58439d3SEugene Kobyak 						   accel_task->fill_pattern);
172d58439d3SEugene Kobyak 		break;
173d58439d3SEugene Kobyak 	case SPDK_ACCEL_OPC_COMPARE:
174d58439d3SEugene Kobyak 		accel_task->status = ex_accel_compare(accel_task->s.iovs, accel_task->s.iovcnt,
175d58439d3SEugene Kobyak 						      accel_task->s2.iovs, accel_task->s2.iovcnt);
176d58439d3SEugene Kobyak 		break;
177d58439d3SEugene Kobyak 	default:
178d58439d3SEugene Kobyak 		fprintf(stderr, "Unsupported accel opcode: %" PRIu8 "\n", accel_task->op_code);
179d58439d3SEugene Kobyak 		accel_task->status = 1;
180d58439d3SEugene Kobyak 		break;
181d58439d3SEugene Kobyak 	}
182d58439d3SEugene Kobyak 
183d58439d3SEugene Kobyak 	add_to_comp_list(ex_ch, accel_task);
184d58439d3SEugene Kobyak 
185d58439d3SEugene Kobyak 	return accel_task->status;
186d58439d3SEugene Kobyak }
187d58439d3SEugene Kobyak 
188d58439d3SEugene Kobyak static struct spdk_accel_module_if g_ex_module = {
189d58439d3SEugene Kobyak 	.module_init			= ex_accel_module_init,
190d58439d3SEugene Kobyak 	.module_fini			= ex_accel_module_fini,
191d58439d3SEugene Kobyak 	.get_ctx_size			= ex_accel_module_get_ctx_size,
192d58439d3SEugene Kobyak 	.name				= "external",
193d58439d3SEugene Kobyak 	.supports_opcode		= ex_accel_supports_opcode,
194d58439d3SEugene Kobyak 	.get_io_channel			= ex_accel_get_io_channel,
195d58439d3SEugene Kobyak 	.submit_tasks			= ex_accel_submit_tasks,
196d58439d3SEugene Kobyak };
197d58439d3SEugene Kobyak 
198d58439d3SEugene Kobyak SPDK_ACCEL_MODULE_REGISTER(external, &g_ex_module)
199