[Accel-config] [PATCH 2/7] accel-config: Add config-user-default command

Fenghua Yu <[email protected]> Tue, 1 Aug 2023 14:52:27 -0700
Newsgroups dev.linux.lists.accel-config
Message-ID <[email protected]>
Although current accel-config provides thorough ways to configure
IDXD devices and WQs, sometimes user needs an easier way to configure
and enable them without many knowledges of IDXD.

A new command "config-user-default" is added to configure and enable
all available devices and WQs for user usage in the following default
configurations:

1. Fixed configurations:
	"mode":"shared",
	"group_id":0,
	"priority":10,
	"block_on_fault":1,
	"name":"user_default_wq",
	"ats_disable":0,
	"prs_disable":1
	"type": "user"
	"driver_name":"user",

2. Calculated configurations:
	"size": max WQ size / max WQs
	"threshold": WQ size

3. Default configurations that have been set by IDXD driver:
	"max_batch_size"
	"max_transfer_size"
	"op_config"

Signed-off-by: Fenghua Yu <[email protected]>
Reviewed-by: Ramesh Thomas <[email protected]>
---
 accfg/accel-config.c    |   1 +
 accfg/config.c          | 268 ++++++++++++++++++++++++++++++++++++++++
 accfg/libaccel_config.h |   1 +
 builtin.h               |   1 +
 4 files changed, 271 insertions(+)

diff --git a/accfg/accel-config.c b/accfg/accel-config.c
index a897608..cf3882e 100644
--- a/accfg/accel-config.c
+++ b/accfg/accel-config.c
@@ -67,6 +67,7 @@ static struct cmd_struct commands[] = {
 	{"config-group", cmd_config_group},
 	{"config-wq", cmd_config_wq},
 	{"config-engine", cmd_config_engine},
+	{"config-user-default", cmd_config_default},
 #ifdef ENABLE_TEST
 	{"test", cmd_test},
 #endif
diff --git a/accfg/config.c b/accfg/config.c
index 2631fd9..f3fa83f 100644
--- a/accfg/config.c
+++ b/accfg/config.c
@@ -119,6 +119,87 @@ static bool is_wq_threshold_writable(struct accfg_wq *wq, int val);
 static bool is_wq_prs_disable_writable(struct accfg_wq *wq, int val);
 static bool is_wq_ats_disable_writable(struct accfg_wq *wq, int val);
 
+static int get_wq_size(struct accfg_device *dev)
+{
+	int max_wq_size, max_wqs;
+
+	max_wq_size = accfg_device_get_max_work_queues_size(dev);
+	max_wqs = accfg_device_get_max_work_queues(dev);
+
+	return max_wq_size / max_wqs;
+}
+
+static int config_default_wq_set_prs_disable(struct accfg_wq *wq, int val)
+{
+	if (!is_wq_prs_disable_writable(wq, val))
+		return -EPERM;
+
+	return accfg_wq_set_prs_disable(wq, val);
+}
+
+static int config_default_wq_set_ats_disable(struct accfg_wq *wq, int val)
+{
+	if (!is_wq_ats_disable_writable(wq, val))
+		return -EPERM;
+
+	return accfg_wq_set_ats_disable(wq, val);
+}
+
+static int config_default_wq_set_threshold(struct accfg_wq *wq, int val)
+{
+	if (!is_wq_threshold_writable(wq, val))
+		return -EPERM;
+
+	return accfg_wq_set_threshold(wq, val);
+}
+
+static struct conf_def_wq_param {
+	struct wq_parameters param;
+	bool configured;
+} conf_def_wq_param[ACCFG_DEVICE_MAX];
+
+/* Return WQ parameter for dev type. */
+static struct wq_parameters *get_conf_def_wq_param(enum accfg_device_type type)
+{
+	if (type == ACCFG_DEVICE_DSA)
+		return &conf_def_wq_param[ACCFG_DEVICE_DSA].param;
+	else if (type == ACCFG_DEVICE_IAX)
+		return &conf_def_wq_param[ACCFG_DEVICE_IAX].param;
+
+	return NULL;
+}
+
+/* Check if dev is configured. */
+static bool conf_def_dev_configured(struct accfg_device *dev)
+{
+	if (accfg_device_get_type(dev) == ACCFG_DEVICE_DSA)
+		return conf_def_wq_param[ACCFG_DEVICE_DSA].configured;
+	else if (accfg_device_get_type(dev) == ACCFG_DEVICE_IAX)
+		return conf_def_wq_param[ACCFG_DEVICE_IAX].configured;
+
+	return false;
+}
+
+/* Set WQ parameters based on device cap: size and threshold. */
+static int config_default_wq_set_on_dev(struct accfg_device *dev)
+{
+	enum accfg_device_type dev_type;
+	struct wq_parameters *p;
+
+	dev_type = accfg_device_get_type(dev);
+	p = get_conf_def_wq_param(dev_type);
+	if (!p)
+		return -EINVAL;
+
+	p->wq_size = get_wq_size(dev);
+	if (p->wq_size <= 0)
+		return -ENOSPC;
+
+	p->threshold = p->wq_size;
+
+	return 0;
+}
+
 static const struct wq_set_table wq_table[] = {
 	{ "size", accfg_wq_set_size, NULL, NULL, NULL },
 	{ "priority", accfg_wq_set_priority, NULL, NULL, NULL },
@@ -1234,3 +1315,190 @@ int cmd_config(int argc, const char **argv, void *ctx)
 
 	return rc;
 }
+
+static int config_default_wq(struct accfg_wq *wq)
+{
+	struct accfg_device *dev = accfg_wq_get_device(wq);
+	enum accfg_device_type dev_type;
+	struct wq_parameters *p;
+
+	if (!conf_def_dev_configured(dev))
+		return 0;
+
+	dev_type = accfg_device_get_type(dev);
+	p = get_conf_def_wq_param(dev_type);
+	if (!p)
+		return -EINVAL;
+
+	accfg_wq_set_priority(wq, p->priority);
+	accfg_wq_set_group_id(wq, p->group_id);
+	accfg_wq_set_block_on_fault(wq, p->block_on_fault);
+	accfg_wq_set_str_mode(wq, p->mode);
+	accfg_wq_set_str_type(wq, p->type);
+	accfg_wq_set_str_name(wq, p->name);
+	accfg_wq_set_str_driver_name(wq, p->driver_name);
+
+	accfg_wq_set_size(wq, p->wq_size);
+	config_default_wq_set_threshold(wq, p->threshold);
+	config_default_wq_set_prs_disable(wq, p->prs_disable);
+	config_default_wq_set_ats_disable(wq, p->ats_disable);
+
+	return 0;
+}
+
+static int config_default_engine(struct accfg_engine *engine,
+				 struct accfg_device *dev)
+{
+	enum accfg_device_type dev_type;
+	struct wq_parameters *p;
+
+	/* Engine's group_id is same as WQ's. */
+	dev_type = accfg_device_get_type(dev);
+	p = get_conf_def_wq_param(dev_type);
+	if (!p)
+		return -EINVAL;
+
+	return accfg_engine_set_group_id(engine, p->group_id);
+}
+
+static void config_default_activate_devices(void *ctx)
+{
+	enum accfg_device_state dev_state;
+	const char *dev_name, *wq_name;
+	struct accfg_engine *engine;
+	struct accfg_device *dev;
+	struct accfg_wq *wq;
+	int rc = 0;
+
+	accfg_device_foreach(ctx, dev) {
+		/* Skip device that is not configured. */
+		if (!conf_def_dev_configured(dev))
+			continue;
+
+		/* Don't enable WQs/engines on partially enabled devices. */
+		dev_state = accfg_device_get_state(dev);
+		if (dev_state == ACCFG_DEVICE_ENABLED)
+			continue;
+
+		/* Set WQ parameters calculated based on dev. */
+		config_default_wq_set_on_dev(dev);
+
+		/* Config WQs */
+		accfg_wq_foreach(dev, wq) {
+			if (verbose)
+				printf("config %s\n", accfg_wq_get_devname(wq));
+
+			config_default_wq(wq);
+		}
+
+		/* Config engines */
+		accfg_engine_foreach(dev, engine)
+			config_default_engine(engine, dev);
+
+		/* Enable device */
+		dev_name = accfg_device_get_devname(dev);
+		if (verbose)
+			printf("enable %s\n", dev_name);
+		rc = accfg_device_enable(dev);
+		if (rc) {
+			fprintf(stderr, "Error enabling %s\n", dev_name);
+			continue;
+		}
+
+		/* Enable WQs */
+		accfg_wq_foreach(dev, wq) {
+			wq_name = accfg_wq_get_devname(wq);
+			if (verbose)
+				printf("enable %s\n", wq_name);
+
+			rc = accfg_wq_enable(wq);
+			if (rc) {
+				fprintf(stderr, "Error enabling %s\n", wq_name);
+				continue;
+			}
+		}
+	}
+}
+
+#define CONFIG_DEFAULT_WQ_PRIORITY		10
+#define CONFIG_DEFAULT_WQ_GROUP_ID		0
+#define CONFIG_DEFAULT_WQ_BLOCK_ON_FAULT	1
+#define CONFIG_DEFAULT_WQ_PRS_DISABLE		1
+#define CONFIG_DEFAULT_WQ_ATS_DISABLE		0
+#define CONFIG_DEFAULT_WQ_NAME			"user_default_wq"
+#define CONFIG_DEFAULT_WQ_TYPE			"user"
+#define CONFIG_DEFAULT_WQ_MODE			"shared"
+#define CONFIG_DEFAULT_WQ_DRV_NAME		"user"
+
+static void config_default(void *ctx)
+{
+	struct wq_parameters *p;
+	int i;
+
+	/*
+	 * Configure WQ parameters except:
+	 * 1. size and threshold will be configured when enabling WQs.
+	 * 2. max_buffer_size, max_batch_size, op_config will be default values
+	 *    which have been initialized by driver.
+	 */
+	for (i = 0; i < ACCFG_DEVICE_MAX; i++) {
+		p = &conf_def_wq_param[i].param;
+
+		p->priority = CONFIG_DEFAULT_WQ_PRIORITY;
+		p->group_id = CONFIG_DEFAULT_WQ_GROUP_ID;
+		p->block_on_fault = CONFIG_DEFAULT_WQ_BLOCK_ON_FAULT;
+		p->mode = strdup(CONFIG_DEFAULT_WQ_MODE);
+		p->type = strdup(CONFIG_DEFAULT_WQ_TYPE);
+		p->name = strdup(CONFIG_DEFAULT_WQ_NAME);
+		p->driver_name = strdup(CONFIG_DEFAULT_WQ_DRV_NAME);
+		p->prs_disable = CONFIG_DEFAULT_WQ_PRS_DISABLE;
+		p->ats_disable = CONFIG_DEFAULT_WQ_ATS_DISABLE;
+
+		conf_def_wq_param[i].configured = true;
+	}
+}
+
+static void config_default_param_free(void)
+{
+	struct wq_parameters *p;
+	int i;
+
+	for (i = 0; i < ACCFG_DEVICE_MAX; i++) {
+		if (!conf_def_wq_param[i].configured)
+			continue;
+
+		p = &conf_def_wq_param[i].param;
+
+		free((char *)p->name);
+		free((char *)p->type);
+		free((char *)p->mode);
+		free((char *)p->driver_name);
+	}
+}
+
+int cmd_config_default(int argc, const char **argv, void *ctx)
+{
+	const struct option options[] = {
+		OPT_BOOLEAN('v', "verbose", &verbose,
+			    "emit extra debug messages to stderr"),
+		OPT_END(),
+	};
+	const char *const u[] = {
+		"accfg config-default [<options>]", NULL
+	};
+	const char *prefix = "./";
+	int i;
+
+	argc = parse_options_prefix(argc, argv, prefix, options, u, 0);
+	for (i = 0; i < argc; i++)
+		error("unknown parameter \"%s\"\n", argv[i]);
+	if (argc)
+		usage_with_options(u, options);
+
+	config_default(ctx);
+	config_default_activate_devices(ctx);
+
+	config_default_param_free();
+
+	return 0;
+}
diff --git a/accfg/libaccel_config.h b/accfg/libaccel_config.h
index 3feb885..ca51b0a 100644
--- a/accfg/libaccel_config.h
+++ b/accfg/libaccel_config.h
@@ -36,6 +36,7 @@ enum accfg_device_version {
 enum accfg_device_type {
 	ACCFG_DEVICE_DSA = 0,
 	ACCFG_DEVICE_IAX = 1,
+	ACCFG_DEVICE_MAX = 2,
 	ACCFG_DEVICE_TYPE_UNKNOWN = -1,
 };
 
diff --git a/builtin.h b/builtin.h
index e1f0b83..96a9d61 100644
--- a/builtin.h
+++ b/builtin.h
@@ -30,6 +30,7 @@ int cmd_config_device(int argc, const char **argv, void *ctx);
 int cmd_config_group(int argc, const char **argv, void *ctx);
 int cmd_config_wq(int argc, const char **argv, void *ctx);
 int cmd_config_engine(int argc, const char **argv, void *ctx);
+int cmd_config_default(int argc, const char **argv, void *ctx);
 #ifdef ENABLE_TEST
 int cmd_test(int argc, const char **argv, void *ctx);
 #endif
-- 
2.31.1