Commit 878983bd authored by Konrad Sztyber's avatar Konrad Sztyber Committed by Tomasz Zawadzki
Browse files

accel: add module priority



We already had a notion of some kind of module priorities, i.e. the
software module had the lowest priority and was always chosen as a
fallback to the hardware modules.  It relied on keeping the software
module first on the list of modules.

This patch makes this mechanism more generic and allows for specifying
the priority of any module.  The software module has a priority of
SPDK_ACCEL_SW_PRIORITY (-1), all hardware modules should set their
priorities to a non-negative value.

It will make it possible to define modules that would only be used for
testing.  Their priority would be set to a value lower than -1, so
they'd never be used unless explicitly assigned to an operation via
spdk_accel_assign_opc().

Signed-off-by: default avatarKonrad Sztyber <konrad.sztyber@intel.com>
Change-Id: Ifd5648fe973d9ba68835786ccceba5c8ad6700ec
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/20434


Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: default avatarAleksey Marchuk <alexeymar@nvidia.com>
Reviewed-by: default avatarJim Harris <jim.harris@samsung.com>
Community-CI: Mellanox Build Bot
parent b7351518
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -147,6 +147,15 @@ struct spdk_accel_module_if {
	/** Name of the module. */
	const char *name;

	/**
	 * Priority of the module.  It's used to select a module to execute an operation when
	 * multiple modules support it.  Higher value means higher priority.  Software module has a
	 * priority of `SPDK_ACCEL_SW_PRIORITY`.  Of course, this value is only relevant when none
	 * of the modules have been explicitly assigned to execute a given operation via
	 * `spdk_accel_assign_opc()`.
	 */
	int priority;

	/**
	 * Initialization function for the module.  Called by the application during startup.
	 *
@@ -231,6 +240,9 @@ static void __attribute__((constructor)) _spdk_accel_module_register_##name(void
	spdk_accel_module_list_add(module); \
}

/* Priority of the accel_sw module */
#define SPDK_ACCEL_SW_PRIORITY (-1)

/**
 * Called by an accel module when cleanup initiated during .module_fini has completed
 */
+2 −2
Original line number Diff line number Diff line
@@ -7,8 +7,8 @@
SPDK_ROOT_DIR := $(abspath $(CURDIR)/../..)
include $(SPDK_ROOT_DIR)/mk/spdk.common.mk

SO_VER := 13
SO_MINOR := 1
SO_VER := 14
SO_MINOR := 0
SO_SUFFIX := $(SO_VER).$(SO_MINOR)

LIBNAME = accel
+15 −11
Original line number Diff line number Diff line
@@ -2308,18 +2308,22 @@ spdk_accel_crypto_key_get(const char *name)
void
spdk_accel_module_list_add(struct spdk_accel_module_if *accel_module)
{
	struct spdk_accel_module_if *tmp;

	if (_module_find_by_name(accel_module->name)) {
		SPDK_NOTICELOG("Module %s already registered\n", accel_module->name);
		assert(false);
		return;
	}

	/* Make sure that the software module is at the head of the list, this
	 * will assure that all opcodes are later assigned to software first and
	 * then updated to HW modules as they are registered.
	 */
	if (strcmp(accel_module->name, "software") == 0) {
		TAILQ_INSERT_HEAD(&spdk_accel_module_list, accel_module, tailq);
	TAILQ_FOREACH(tmp, &spdk_accel_module_list, tailq) {
		if (accel_module->priority < tmp->priority) {
			break;
		}
	}

	if (tmp != NULL) {
		TAILQ_INSERT_BEFORE(tmp, accel_module, tailq);
	} else {
		TAILQ_INSERT_TAIL(&spdk_accel_module_list, accel_module, tailq);
	}
@@ -2531,11 +2535,11 @@ spdk_accel_initialize(void)
		return rc;
	}

	/* Create our priority global map of opcodes to modules, we populate starting
	 * with the software module (guaranteed to be first on the list) and then
	 * updating opcodes with HW modules that have been initialized.
	 * NOTE: all opcodes must be supported by software in the event that no HW
	 * modules are initialized to support the operation.
	/* The module list is order by priority, with the highest priority modules being at the end
	 * of the list.  The software module should be somewhere at the beginning of the list,
	 * before all HW modules.
	 * NOTE: all opcodes must be supported by software in the event that no HW modules are
	 * initialized to support the operation.
	 */
	TAILQ_FOREACH(accel_module, &spdk_accel_module_list, tailq) {
		for (op = 0; op < SPDK_ACCEL_OPC_LAST; op++) {
+1 −0
Original line number Diff line number Diff line
@@ -675,6 +675,7 @@ static struct spdk_accel_module_if g_sw_module = {
	.write_config_json		= NULL,
	.get_ctx_size			= sw_accel_module_get_ctx_size,
	.name				= "software",
	.priority			= SPDK_ACCEL_SW_PRIORITY,
	.supports_opcode		= sw_accel_supports_opcode,
	.get_io_channel			= sw_accel_get_io_channel,
	.submit_tasks			= sw_accel_submit_tasks,
+51 −34
Original line number Diff line number Diff line
@@ -563,49 +563,66 @@ test_spdk_accel_module_find_by_name(void)
	CU_ASSERT(accel_module == NULL);
}

static int
ut_module_init_nop(void)
{
	return 0;
}

static bool
ut_supports_opcode_all(enum spdk_accel_opcode opcode)
{
	return true;
}

static void
ut_accel_module_priority_finish_done(void *done)
{
	*(int *)done = 1;
}

static void
test_spdk_accel_module_register(void)
{
	struct spdk_accel_module_if mod1 = {};
	struct spdk_accel_module_if mod2 = {};
	struct spdk_accel_module_if mod3 = {};
	struct spdk_accel_module_if mod4 = {};
	struct spdk_accel_module_if *accel_module = NULL;
	int i = 0;
	struct spdk_accel_module_if mods[] = {
		{ .name = "mod1", .priority = 1, },
		{ .name = "mod3", .priority = 3, },
		{ .name = "mod0", .priority = 0, },
		{ .name = "mod2", .priority = 2, },
	};
	int rc, done = 0;
	const char *modname = NULL;
	size_t i;

	mod1.name = "ioat";
	mod2.name = "idxd";
	mod3.name = "software";
	mod4.name = "nothing";
	allocate_cores(1);
	allocate_threads(1);
	set_thread(0);

	TAILQ_INIT(&spdk_accel_module_list);
	for (i = 0; i < SPDK_COUNTOF(mods); ++i) {
		mods[i].module_init = ut_module_init_nop;
		mods[i].supports_opcode = ut_supports_opcode_all;
		spdk_accel_module_list_add(&mods[i]);
	}

	spdk_accel_module_list_add(&mod1);
	spdk_accel_module_list_add(&mod2);
	spdk_accel_module_list_add(&mod3);
	spdk_accel_module_list_add(&mod4);
	rc = spdk_accel_initialize();
	CU_ASSERT_EQUAL(rc, 0);

	/* Now confirm they're in the right order. */
	TAILQ_FOREACH(accel_module, &spdk_accel_module_list, tailq) {
		switch (i++) {
		case 0:
			CU_ASSERT(strcmp(accel_module->name, "software") == 0);
			break;
		case 1:
			CU_ASSERT(strcmp(accel_module->name, "ioat") == 0);
			break;
		case 2:
			CU_ASSERT(strcmp(accel_module->name, "idxd") == 0);
			break;
		case 3:
			CU_ASSERT(strcmp(accel_module->name, "nothing") == 0);
			break;
		default:
			CU_ASSERT(false);
			break;
	/* All opcodes should be assigned to the module with highest prio - mod3 */
	for (i = 0; i < SPDK_ACCEL_OPC_LAST; ++i) {
		rc = spdk_accel_get_opc_module_name((enum spdk_accel_opcode)i, &modname);
		CU_ASSERT_EQUAL(rc, 0);
		CU_ASSERT_STRING_EQUAL(modname, "mod3");
	}

	spdk_accel_finish(ut_accel_module_priority_finish_done, &done);
	while (!done) {
		poll_threads();
	}
	CU_ASSERT(i == 4);

	TAILQ_INIT(&spdk_accel_module_list);
	free_threads();
	free_cores();
}

struct ut_sequence {