xref: /spdk/module/accel/error/accel_error.c (revision b264e22f0a79822588cc09c257bc84dedc4e1862)
164b16edaSKonrad Sztyber /* SPDX-License-Identifier: BSD-3-Clause
264b16edaSKonrad Sztyber  * Copyright (C) 2023 Intel Corporation. All rights reserved.
364b16edaSKonrad Sztyber  */
464b16edaSKonrad Sztyber 
58625cc18SKonrad Sztyber #include "accel_error.h"
664b16edaSKonrad Sztyber #include "spdk/accel.h"
764b16edaSKonrad Sztyber #include "spdk/accel_module.h"
838a1f6bfSKonrad Sztyber #include "spdk/json.h"
964b16edaSKonrad Sztyber #include "spdk/thread.h"
1064b16edaSKonrad Sztyber 
118625cc18SKonrad Sztyber struct accel_error_inject_info {
128625cc18SKonrad Sztyber 	/* Error injection options */
138625cc18SKonrad Sztyber 	struct accel_error_inject_opts	opts;
148625cc18SKonrad Sztyber 	/* Number of errors already injected on this channel */
158625cc18SKonrad Sztyber 	uint64_t			count;
16760cb023SKonrad Sztyber 	/* Number of operations executed since last error injection */
17760cb023SKonrad Sztyber 	uint64_t			interval;
188625cc18SKonrad Sztyber };
198625cc18SKonrad Sztyber 
200732c143SKonrad Sztyber struct accel_error_task;
210732c143SKonrad Sztyber 
2264b16edaSKonrad Sztyber struct accel_error_channel {
2364b16edaSKonrad Sztyber 	struct spdk_io_channel		*swch;
240732c143SKonrad Sztyber 	struct spdk_poller		*poller;
258625cc18SKonrad Sztyber 	struct accel_error_inject_info	injects[SPDK_ACCEL_OPC_LAST];
260732c143SKonrad Sztyber 	STAILQ_HEAD(, accel_error_task)	tasks;
2764b16edaSKonrad Sztyber };
2864b16edaSKonrad Sztyber 
2964b16edaSKonrad Sztyber struct accel_error_task {
30dce597cbSKonrad Sztyber 	struct accel_error_channel		*ch;
31*b264e22fSKonrad Sztyber 	union {
32*b264e22fSKonrad Sztyber 		spdk_accel_completion_cb	cpl;
33*b264e22fSKonrad Sztyber 		spdk_accel_step_cb		step;
34*b264e22fSKonrad Sztyber 	} cb_fn;
3564b16edaSKonrad Sztyber 	void					*cb_arg;
360732c143SKonrad Sztyber 	int					status;
370732c143SKonrad Sztyber 	STAILQ_ENTRY(accel_error_task)		link;
3864b16edaSKonrad Sztyber };
3964b16edaSKonrad Sztyber 
4064b16edaSKonrad Sztyber static struct spdk_accel_module_if *g_sw_module;
418625cc18SKonrad Sztyber static struct accel_error_inject_opts g_injects[SPDK_ACCEL_OPC_LAST];
4264b16edaSKonrad Sztyber static size_t g_task_offset;
4364b16edaSKonrad Sztyber 
4464b16edaSKonrad Sztyber static struct accel_error_task *
4564b16edaSKonrad Sztyber accel_error_get_task_ctx(struct spdk_accel_task *task)
4664b16edaSKonrad Sztyber {
4764b16edaSKonrad Sztyber 	return (void *)((uint8_t *)task + g_task_offset);
4864b16edaSKonrad Sztyber }
4964b16edaSKonrad Sztyber 
500732c143SKonrad Sztyber static struct spdk_accel_task *
510732c143SKonrad Sztyber accel_error_get_task_from_ctx(struct accel_error_task *errtask)
520732c143SKonrad Sztyber {
530732c143SKonrad Sztyber 	return (void *)((uint8_t *)errtask - g_task_offset);
540732c143SKonrad Sztyber }
550732c143SKonrad Sztyber 
5664b16edaSKonrad Sztyber static void
57dce597cbSKonrad Sztyber accel_error_corrupt_task(struct spdk_accel_task *task)
58dce597cbSKonrad Sztyber {
59dce597cbSKonrad Sztyber 	switch (task->op_code) {
60dce597cbSKonrad Sztyber 	case SPDK_ACCEL_OPC_CRC32C:
61dce597cbSKonrad Sztyber 		*task->crc_dst += 1;
62dce597cbSKonrad Sztyber 		break;
63dce597cbSKonrad Sztyber 	default:
64dce597cbSKonrad Sztyber 		break;
65dce597cbSKonrad Sztyber 	}
66dce597cbSKonrad Sztyber }
67dce597cbSKonrad Sztyber 
68dce597cbSKonrad Sztyber static void
690732c143SKonrad Sztyber accel_error_corrupt_cb(void *arg, int status)
7064b16edaSKonrad Sztyber {
7164b16edaSKonrad Sztyber 	struct spdk_accel_task *task = arg;
7264b16edaSKonrad Sztyber 	struct accel_error_task *errtask = accel_error_get_task_ctx(task);
73*b264e22fSKonrad Sztyber 	spdk_accel_completion_cb cb_fn = errtask->cb_fn.cpl;
7464b16edaSKonrad Sztyber 	void *cb_arg = errtask->cb_arg;
7564b16edaSKonrad Sztyber 
76dce597cbSKonrad Sztyber 	accel_error_corrupt_task(task);
7764b16edaSKonrad Sztyber 	cb_fn(cb_arg, status);
7864b16edaSKonrad Sztyber }
7964b16edaSKonrad Sztyber 
80*b264e22fSKonrad Sztyber static void
81*b264e22fSKonrad Sztyber accel_error_corrupt_step_cb(void *arg)
82*b264e22fSKonrad Sztyber {
83*b264e22fSKonrad Sztyber 	struct spdk_accel_task *task = arg;
84*b264e22fSKonrad Sztyber 	struct accel_error_task *errtask = accel_error_get_task_ctx(task);
85*b264e22fSKonrad Sztyber 	spdk_accel_step_cb cb_fn = errtask->cb_fn.step;
86*b264e22fSKonrad Sztyber 	void *cb_arg = errtask->cb_arg;
87*b264e22fSKonrad Sztyber 
88*b264e22fSKonrad Sztyber 	accel_error_corrupt_task(task);
89*b264e22fSKonrad Sztyber 
90*b264e22fSKonrad Sztyber 	cb_fn(cb_arg);
91*b264e22fSKonrad Sztyber }
92*b264e22fSKonrad Sztyber 
93b53b961cSKonrad Sztyber static bool
94b53b961cSKonrad Sztyber accel_error_should_inject(struct spdk_io_channel *ch, struct spdk_accel_task *task)
9564b16edaSKonrad Sztyber {
9664b16edaSKonrad Sztyber 	struct accel_error_channel *errch = spdk_io_channel_get_ctx(ch);
97c9f92cbfSKonrad Sztyber 	struct accel_error_inject_info *info = &errch->injects[task->op_code];
9864b16edaSKonrad Sztyber 
99c9f92cbfSKonrad Sztyber 	if (info->opts.type == ACCEL_ERROR_INJECT_DISABLE) {
100b53b961cSKonrad Sztyber 		return false;
101c9f92cbfSKonrad Sztyber 	}
102c9f92cbfSKonrad Sztyber 
103c9f92cbfSKonrad Sztyber 	info->interval++;
104c9f92cbfSKonrad Sztyber 	if (info->interval >= info->opts.interval) {
105c9f92cbfSKonrad Sztyber 		info->interval = 0;
106c9f92cbfSKonrad Sztyber 		info->count++;
107c9f92cbfSKonrad Sztyber 
108c9f92cbfSKonrad Sztyber 		if (info->count <= info->opts.count) {
109b53b961cSKonrad Sztyber 			return true;
110c9f92cbfSKonrad Sztyber 		} else {
111c9f92cbfSKonrad Sztyber 			info->opts.type = ACCEL_ERROR_INJECT_DISABLE;
112c9f92cbfSKonrad Sztyber 			info->interval = 0;
113c9f92cbfSKonrad Sztyber 			info->count = 0;
114c9f92cbfSKonrad Sztyber 		}
115c9f92cbfSKonrad Sztyber 	}
116b53b961cSKonrad Sztyber 
117b53b961cSKonrad Sztyber 	return false;
118b53b961cSKonrad Sztyber }
119b53b961cSKonrad Sztyber 
120b53b961cSKonrad Sztyber static int
121b53b961cSKonrad Sztyber accel_error_submit_tasks(struct spdk_io_channel *ch, struct spdk_accel_task *task)
122b53b961cSKonrad Sztyber {
123b53b961cSKonrad Sztyber 	struct accel_error_channel *errch = spdk_io_channel_get_ctx(ch);
124b53b961cSKonrad Sztyber 	struct accel_error_task *errtask = accel_error_get_task_ctx(task);
1250732c143SKonrad Sztyber 	struct accel_error_inject_info *info = &errch->injects[task->op_code];
126b53b961cSKonrad Sztyber 
127b53b961cSKonrad Sztyber 	if (!accel_error_should_inject(ch, task)) {
128b53b961cSKonrad Sztyber 		goto submit;
129b53b961cSKonrad Sztyber 	}
130b53b961cSKonrad Sztyber 
1310732c143SKonrad Sztyber 	switch (info->opts.type) {
1320732c143SKonrad Sztyber 	case ACCEL_ERROR_INJECT_CORRUPT:
133b53b961cSKonrad Sztyber 		errtask->ch = errch;
134b53b961cSKonrad Sztyber 		errtask->cb_arg = task->cb_arg;
135b53b961cSKonrad Sztyber 		task->cb_arg = task;
136*b264e22fSKonrad Sztyber 		if (task->seq != NULL) {
137*b264e22fSKonrad Sztyber 			errtask->cb_fn.step = task->step_cb_fn;
138*b264e22fSKonrad Sztyber 			task->step_cb_fn = accel_error_corrupt_step_cb;
139*b264e22fSKonrad Sztyber 		} else {
140*b264e22fSKonrad Sztyber 			errtask->cb_fn.cpl = task->cb_fn;
141*b264e22fSKonrad Sztyber 			task->cb_fn = accel_error_corrupt_cb;
142*b264e22fSKonrad Sztyber 		}
1430732c143SKonrad Sztyber 		break;
1440732c143SKonrad Sztyber 	case ACCEL_ERROR_INJECT_FAILURE:
1450732c143SKonrad Sztyber 		errtask->status = info->opts.errcode;
1460732c143SKonrad Sztyber 		STAILQ_INSERT_TAIL(&errch->tasks, errtask, link);
1470732c143SKonrad Sztyber 		return 0;
1480732c143SKonrad Sztyber 	default:
1490732c143SKonrad Sztyber 		break;
1500732c143SKonrad Sztyber 	}
151c9f92cbfSKonrad Sztyber submit:
15264b16edaSKonrad Sztyber 	return g_sw_module->submit_tasks(errch->swch, task);
15364b16edaSKonrad Sztyber }
15464b16edaSKonrad Sztyber 
1550732c143SKonrad Sztyber static int
1560732c143SKonrad Sztyber accel_error_poller(void *arg)
1570732c143SKonrad Sztyber {
1580732c143SKonrad Sztyber 	struct accel_error_channel *errch = arg;
1590732c143SKonrad Sztyber 	struct accel_error_task *errtask;
1600732c143SKonrad Sztyber 	STAILQ_HEAD(, accel_error_task) tasks;
1610732c143SKonrad Sztyber 	struct spdk_accel_task *task;
1620732c143SKonrad Sztyber 
1630732c143SKonrad Sztyber 	if (STAILQ_EMPTY(&errch->tasks)) {
1640732c143SKonrad Sztyber 		return SPDK_POLLER_IDLE;
1650732c143SKonrad Sztyber 	}
1660732c143SKonrad Sztyber 
1670732c143SKonrad Sztyber 	STAILQ_INIT(&tasks);
1680732c143SKonrad Sztyber 	STAILQ_SWAP(&tasks, &errch->tasks, accel_error_task);
1690732c143SKonrad Sztyber 
1700732c143SKonrad Sztyber 	while (!STAILQ_EMPTY(&tasks)) {
1710732c143SKonrad Sztyber 		errtask = STAILQ_FIRST(&tasks);
1720732c143SKonrad Sztyber 		STAILQ_REMOVE_HEAD(&tasks, link);
1730732c143SKonrad Sztyber 
1740732c143SKonrad Sztyber 		task = accel_error_get_task_from_ctx(errtask);
1750732c143SKonrad Sztyber 		spdk_accel_task_complete(task, errtask->status);
1760732c143SKonrad Sztyber 	}
1770732c143SKonrad Sztyber 
1780732c143SKonrad Sztyber 	return SPDK_POLLER_BUSY;
1790732c143SKonrad Sztyber }
1800732c143SKonrad Sztyber 
1818625cc18SKonrad Sztyber static void
1828625cc18SKonrad Sztyber accel_error_inject_channel(struct spdk_io_channel_iter *iter)
1838625cc18SKonrad Sztyber {
1848625cc18SKonrad Sztyber 	struct spdk_io_channel *ch = spdk_io_channel_iter_get_channel(iter);
1858625cc18SKonrad Sztyber 	struct accel_error_channel *errch = spdk_io_channel_get_ctx(ch);
1868625cc18SKonrad Sztyber 	struct accel_error_inject_opts *opts = spdk_io_channel_iter_get_ctx(iter);
1878625cc18SKonrad Sztyber 	struct accel_error_inject_info *info = &errch->injects[opts->opcode];
1888625cc18SKonrad Sztyber 
1898625cc18SKonrad Sztyber 	info->count = 0;
1908625cc18SKonrad Sztyber 	memcpy(&info->opts, opts, sizeof(info->opts));
1918625cc18SKonrad Sztyber 
1928625cc18SKonrad Sztyber 	spdk_for_each_channel_continue(iter, 0);
1938625cc18SKonrad Sztyber }
1948625cc18SKonrad Sztyber 
1958625cc18SKonrad Sztyber static bool accel_error_supports_opcode(enum spdk_accel_opcode opcode);
1968625cc18SKonrad Sztyber 
1978625cc18SKonrad Sztyber int
1988625cc18SKonrad Sztyber accel_error_inject_error(struct accel_error_inject_opts *opts)
1998625cc18SKonrad Sztyber {
2008625cc18SKonrad Sztyber 	struct accel_error_inject_opts *curr = &g_injects[opts->opcode];
2018625cc18SKonrad Sztyber 
2028625cc18SKonrad Sztyber 	if (!accel_error_supports_opcode(opts->opcode)) {
2038625cc18SKonrad Sztyber 		return -EINVAL;
2048625cc18SKonrad Sztyber 	}
2058625cc18SKonrad Sztyber 
2068625cc18SKonrad Sztyber 	memcpy(curr, opts, sizeof(*opts));
2078625cc18SKonrad Sztyber 	if (curr->type == ACCEL_ERROR_INJECT_DISABLE) {
2088625cc18SKonrad Sztyber 		curr->count = 0;
2098625cc18SKonrad Sztyber 	}
2108625cc18SKonrad Sztyber 	if (curr->count == 0) {
2118625cc18SKonrad Sztyber 		curr->type = ACCEL_ERROR_INJECT_DISABLE;
2128625cc18SKonrad Sztyber 	}
2138625cc18SKonrad Sztyber 
2148625cc18SKonrad Sztyber 	spdk_for_each_channel(&g_sw_module, accel_error_inject_channel, curr, NULL);
2158625cc18SKonrad Sztyber 
2168625cc18SKonrad Sztyber 	return 0;
2178625cc18SKonrad Sztyber }
2188625cc18SKonrad Sztyber 
21964b16edaSKonrad Sztyber static int
22064b16edaSKonrad Sztyber accel_error_channel_create_cb(void *io_device, void *ctx)
22164b16edaSKonrad Sztyber {
22264b16edaSKonrad Sztyber 	struct accel_error_channel *errch = ctx;
2238625cc18SKonrad Sztyber 	size_t i;
22464b16edaSKonrad Sztyber 
2250732c143SKonrad Sztyber 	STAILQ_INIT(&errch->tasks);
2260732c143SKonrad Sztyber 	errch->poller = SPDK_POLLER_REGISTER(accel_error_poller, errch, 0);
2270732c143SKonrad Sztyber 	if (errch->poller == NULL) {
2280732c143SKonrad Sztyber 		return -ENOMEM;
2290732c143SKonrad Sztyber 	}
2300732c143SKonrad Sztyber 
23164b16edaSKonrad Sztyber 	errch->swch = g_sw_module->get_io_channel();
23264b16edaSKonrad Sztyber 	if (errch->swch == NULL) {
2330732c143SKonrad Sztyber 		spdk_poller_unregister(&errch->poller);
23464b16edaSKonrad Sztyber 		return -ENOMEM;
23564b16edaSKonrad Sztyber 	}
23664b16edaSKonrad Sztyber 
2378625cc18SKonrad Sztyber 	for (i = 0; i < SPDK_COUNTOF(errch->injects); ++i) {
2388625cc18SKonrad Sztyber 		memcpy(&errch->injects[i].opts, &g_injects[i], sizeof(g_injects[i]));
2398625cc18SKonrad Sztyber 		errch->injects[i].count = 0;
2408625cc18SKonrad Sztyber 	}
2418625cc18SKonrad Sztyber 
24264b16edaSKonrad Sztyber 	return 0;
24364b16edaSKonrad Sztyber }
24464b16edaSKonrad Sztyber 
24564b16edaSKonrad Sztyber static void
24664b16edaSKonrad Sztyber accel_error_channel_destroy_cb(void *io_device, void *ctx)
24764b16edaSKonrad Sztyber {
24864b16edaSKonrad Sztyber 	struct accel_error_channel *errch = ctx;
24964b16edaSKonrad Sztyber 
2500732c143SKonrad Sztyber 	assert(STAILQ_EMPTY(&errch->tasks));
2510732c143SKonrad Sztyber 	spdk_poller_unregister(&errch->poller);
25264b16edaSKonrad Sztyber 	spdk_put_io_channel(errch->swch);
25364b16edaSKonrad Sztyber }
25464b16edaSKonrad Sztyber 
25564b16edaSKonrad Sztyber static int
25664b16edaSKonrad Sztyber accel_error_module_init(void)
25764b16edaSKonrad Sztyber {
25864b16edaSKonrad Sztyber 	g_sw_module = spdk_accel_get_module("software");
25964b16edaSKonrad Sztyber 	if (g_sw_module == NULL) {
26064b16edaSKonrad Sztyber 		/* Should never really happen */
2611f88c365STomasz Zawadzki 		return -ENOTSUP;
26264b16edaSKonrad Sztyber 	}
26364b16edaSKonrad Sztyber 
26464b16edaSKonrad Sztyber 	g_task_offset = g_sw_module->get_ctx_size();
26564b16edaSKonrad Sztyber 
26664b16edaSKonrad Sztyber 	spdk_io_device_register(&g_sw_module, accel_error_channel_create_cb,
26764b16edaSKonrad Sztyber 				accel_error_channel_destroy_cb,
26864b16edaSKonrad Sztyber 				sizeof(struct accel_error_channel), "accel_error");
26964b16edaSKonrad Sztyber 
27064b16edaSKonrad Sztyber 	return 0;
27164b16edaSKonrad Sztyber }
27264b16edaSKonrad Sztyber 
27364b16edaSKonrad Sztyber static void
27464b16edaSKonrad Sztyber accel_error_unregister_cb(void *unused)
27564b16edaSKonrad Sztyber {
27664b16edaSKonrad Sztyber 	spdk_accel_module_finish();
27764b16edaSKonrad Sztyber }
27864b16edaSKonrad Sztyber 
27964b16edaSKonrad Sztyber static void
28064b16edaSKonrad Sztyber accel_error_module_fini(void *unused)
28164b16edaSKonrad Sztyber {
28264b16edaSKonrad Sztyber 	spdk_io_device_unregister(&g_sw_module, accel_error_unregister_cb);
28364b16edaSKonrad Sztyber }
28464b16edaSKonrad Sztyber 
28564b16edaSKonrad Sztyber static bool
28664b16edaSKonrad Sztyber accel_error_supports_opcode(enum spdk_accel_opcode opcode)
28764b16edaSKonrad Sztyber {
288dce597cbSKonrad Sztyber 	switch (opcode) {
289dce597cbSKonrad Sztyber 	case SPDK_ACCEL_OPC_CRC32C:
290dce597cbSKonrad Sztyber 		return true;
291dce597cbSKonrad Sztyber 	default:
29264b16edaSKonrad Sztyber 		return false;
29364b16edaSKonrad Sztyber 	}
294dce597cbSKonrad Sztyber }
29564b16edaSKonrad Sztyber 
29664b16edaSKonrad Sztyber static struct spdk_io_channel *
29764b16edaSKonrad Sztyber accel_error_get_io_channel(void)
29864b16edaSKonrad Sztyber {
29964b16edaSKonrad Sztyber 	return spdk_get_io_channel(&g_sw_module);
30064b16edaSKonrad Sztyber }
30164b16edaSKonrad Sztyber 
30264b16edaSKonrad Sztyber static size_t
30364b16edaSKonrad Sztyber accel_error_get_ctx_size(void)
30464b16edaSKonrad Sztyber {
30564b16edaSKonrad Sztyber 	return g_task_offset + sizeof(struct accel_error_task);
30664b16edaSKonrad Sztyber }
30764b16edaSKonrad Sztyber 
3088625cc18SKonrad Sztyber const char *
3098625cc18SKonrad Sztyber accel_error_get_type_name(enum accel_error_inject_type type)
3108625cc18SKonrad Sztyber {
3118625cc18SKonrad Sztyber 	const char *typenames[] = {
3128625cc18SKonrad Sztyber 		[ACCEL_ERROR_INJECT_DISABLE] = "disable",
3138625cc18SKonrad Sztyber 		[ACCEL_ERROR_INJECT_CORRUPT] = "corrupt",
314bb019612SKonrad Sztyber 		[ACCEL_ERROR_INJECT_FAILURE] = "failure",
3158625cc18SKonrad Sztyber 		[ACCEL_ERROR_INJECT_MAX] = NULL
3168625cc18SKonrad Sztyber 	};
3178625cc18SKonrad Sztyber 
3188625cc18SKonrad Sztyber 	if ((int)type >= ACCEL_ERROR_INJECT_MAX) {
3198625cc18SKonrad Sztyber 		return NULL;
3208625cc18SKonrad Sztyber 	}
3218625cc18SKonrad Sztyber 
3228625cc18SKonrad Sztyber 	return typenames[type];
3238625cc18SKonrad Sztyber }
3248625cc18SKonrad Sztyber 
32538a1f6bfSKonrad Sztyber static void
32638a1f6bfSKonrad Sztyber accel_error_write_config_json(struct spdk_json_write_ctx *w)
32738a1f6bfSKonrad Sztyber {
32838a1f6bfSKonrad Sztyber 	struct accel_error_inject_opts *opts;
32938a1f6bfSKonrad Sztyber 	int opcode;
33038a1f6bfSKonrad Sztyber 
33138a1f6bfSKonrad Sztyber 	for (opcode = 0; opcode < SPDK_ACCEL_OPC_LAST; ++opcode) {
33238a1f6bfSKonrad Sztyber 		opts = &g_injects[opcode];
33338a1f6bfSKonrad Sztyber 		if (opts->type == ACCEL_ERROR_INJECT_DISABLE) {
33438a1f6bfSKonrad Sztyber 			continue;
33538a1f6bfSKonrad Sztyber 		}
33638a1f6bfSKonrad Sztyber 		spdk_json_write_object_begin(w);
33738a1f6bfSKonrad Sztyber 		spdk_json_write_named_string(w, "method", "accel_error_inject_error");
33838a1f6bfSKonrad Sztyber 		spdk_json_write_named_object_begin(w, "params");
33938a1f6bfSKonrad Sztyber 		spdk_json_write_named_string(w, "opcode", spdk_accel_get_opcode_name(opcode));
34038a1f6bfSKonrad Sztyber 		spdk_json_write_named_string(w, "type", accel_error_get_type_name(opts->type));
34138a1f6bfSKonrad Sztyber 		spdk_json_write_named_uint64(w, "count", opts->count);
342760cb023SKonrad Sztyber 		spdk_json_write_named_uint64(w, "interval", opts->interval);
34338a1f6bfSKonrad Sztyber 		spdk_json_write_object_end(w);
34438a1f6bfSKonrad Sztyber 		spdk_json_write_object_end(w);
34538a1f6bfSKonrad Sztyber 	}
34638a1f6bfSKonrad Sztyber }
34738a1f6bfSKonrad Sztyber 
34864b16edaSKonrad Sztyber static struct spdk_accel_module_if g_accel_error_module = {
34964b16edaSKonrad Sztyber 	.name			= "error",
35064b16edaSKonrad Sztyber 	.priority		= INT_MIN,
35164b16edaSKonrad Sztyber 	.module_init		= accel_error_module_init,
35264b16edaSKonrad Sztyber 	.module_fini		= accel_error_module_fini,
35364b16edaSKonrad Sztyber 	.supports_opcode	= accel_error_supports_opcode,
35464b16edaSKonrad Sztyber 	.get_ctx_size		= accel_error_get_ctx_size,
35564b16edaSKonrad Sztyber 	.get_io_channel		= accel_error_get_io_channel,
35664b16edaSKonrad Sztyber 	.submit_tasks		= accel_error_submit_tasks,
35738a1f6bfSKonrad Sztyber 	.write_config_json	= accel_error_write_config_json,
35864b16edaSKonrad Sztyber };
35964b16edaSKonrad Sztyber SPDK_ACCEL_MODULE_REGISTER(error, &g_accel_error_module)
360