[v2,10/37] ml/cnxk: add functions to load and unload models

Message ID 20221208201806.21893-11-syalavarthi@marvell.com (mailing list archive)
State Superseded, archived
Delegated to: Thomas Monjalon
Headers
Series Implementation of ML CNXK driver |

Checks

Context Check Description
ci/checkpatch success coding style OK

Commit Message

Srikanth Yalavarthi Dec. 8, 2022, 8:17 p.m. UTC
  Added cnxk driver implementations to load and unload ML models.
Enabled support in configure stage to allocate model handles
array. Assign model ID and allocate resources per each model
during load stage and release resources during model unload.
Added internal structures to handle ML models.

Signed-off-by: Srikanth Yalavarthi <syalavarthi@marvell.com>
---
 drivers/ml/cnxk/cn10k_ml_dev.h   |   3 +
 drivers/ml/cnxk/cn10k_ml_model.c |   5 +
 drivers/ml/cnxk/cn10k_ml_model.h |  43 +++++++++
 drivers/ml/cnxk/cn10k_ml_ops.c   | 154 +++++++++++++++++++++++++++++++
 drivers/ml/cnxk/cn10k_ml_ops.h   |   5 +
 drivers/ml/cnxk/meson.build      |   2 +
 6 files changed, 212 insertions(+)
 create mode 100644 drivers/ml/cnxk/cn10k_ml_model.c
 create mode 100644 drivers/ml/cnxk/cn10k_ml_model.h
  

Patch

diff --git a/drivers/ml/cnxk/cn10k_ml_dev.h b/drivers/ml/cnxk/cn10k_ml_dev.h
index 30c2ea6471..c231cb23ed 100644
--- a/drivers/ml/cnxk/cn10k_ml_dev.h
+++ b/drivers/ml/cnxk/cn10k_ml_dev.h
@@ -214,6 +214,9 @@  struct cn10k_ml_dev {
 
 	/* ML Firmware */
 	struct cn10k_ml_fw fw;
+
+	/* Number of models loaded */
+	uint16_t nb_models_loaded;
 };
 
 uint64_t cn10k_ml_fw_flags_get(struct cn10k_ml_fw *fw);
diff --git a/drivers/ml/cnxk/cn10k_ml_model.c b/drivers/ml/cnxk/cn10k_ml_model.c
new file mode 100644
index 0000000000..39ed707396
--- /dev/null
+++ b/drivers/ml/cnxk/cn10k_ml_model.c
@@ -0,0 +1,5 @@ 
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (c) 2022 Marvell.
+ */
+
+#include "cn10k_ml_model.h"
diff --git a/drivers/ml/cnxk/cn10k_ml_model.h b/drivers/ml/cnxk/cn10k_ml_model.h
new file mode 100644
index 0000000000..f529374281
--- /dev/null
+++ b/drivers/ml/cnxk/cn10k_ml_model.h
@@ -0,0 +1,43 @@ 
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (c) 2022 Marvell.
+ */
+
+#ifndef _CN10K_ML_MODEL_H_
+#define _CN10K_ML_MODEL_H_
+
+#include <rte_mldev.h>
+
+#include <roc_api.h>
+
+#include "cn10k_ml_dev.h"
+
+/* Maximum number of models per device */
+#define ML_CN10K_MAX_MODELS 16
+
+/* Model state */
+enum cn10k_ml_model_state {
+	ML_CN10K_MODEL_STATE_LOADED,
+	ML_CN10K_MODEL_STATE_JOB_ACTIVE,
+	ML_CN10K_MODEL_STATE_STARTED,
+	ML_CN10K_MODEL_STATE_UNKNOWN,
+};
+
+/* ML Model Object */
+struct cn10k_ml_model {
+	/* Device reference */
+	struct cn10k_ml_dev *mldev;
+
+	/* Model name */
+	char name[RTE_ML_STR_MAX];
+
+	/* Model ID */
+	int16_t model_id;
+
+	/* Model lock, used to update model state */
+	plt_spinlock_t lock;
+
+	/* Model state */
+	enum cn10k_ml_model_state state;
+};
+
+#endif /* _CN10K_ML_MODEL_H_ */
diff --git a/drivers/ml/cnxk/cn10k_ml_ops.c b/drivers/ml/cnxk/cn10k_ml_ops.c
index 7c9c49ffda..30e7b0da35 100644
--- a/drivers/ml/cnxk/cn10k_ml_ops.c
+++ b/drivers/ml/cnxk/cn10k_ml_ops.c
@@ -6,8 +6,12 @@ 
 #include <rte_mldev_pmd.h>
 
 #include "cn10k_ml_dev.h"
+#include "cn10k_ml_model.h"
 #include "cn10k_ml_ops.h"
 
+/* ML model macros */
+#define CN10K_ML_MODEL_MEMZONE_NAME "ml_cn10k_model_mz"
+
 static void
 qp_memzone_name_get(char *name, int size, int dev_id, int qp_id)
 {
@@ -120,9 +124,11 @@  static int
 cn10k_ml_dev_configure(struct rte_ml_dev *dev, const struct rte_ml_dev_config *conf)
 {
 	struct rte_ml_dev_info dev_info;
+	struct cn10k_ml_model *model;
 	struct cn10k_ml_dev *mldev;
 	struct cn10k_ml_qp *qp;
 	uint32_t mz_size;
+	int16_t model_id;
 	uint16_t qp_id;
 	int ret;
 
@@ -203,6 +209,48 @@  cn10k_ml_dev_configure(struct rte_ml_dev *dev, const struct rte_ml_dev_config *c
 	}
 	dev->data->nb_queue_pairs = conf->nb_queue_pairs;
 
+	/* Allocate ML models */
+	if (dev->data->models == NULL) {
+		mz_size = sizeof(dev->data->models[0]) * conf->nb_models;
+		dev->data->models = rte_zmalloc("cn10k_mldev_models", mz_size, RTE_CACHE_LINE_SIZE);
+		if (dev->data->models == NULL) {
+			dev->data->nb_models = 0;
+			plt_err("Failed to get memory for ml_models, nb_models %u",
+				conf->nb_models);
+			ret = -ENOMEM;
+			goto error;
+		}
+	} else {
+		/* Re-configure */
+		void **models;
+
+		/* Unload all models */
+		for (model_id = 0; model_id < dev->data->nb_models; model_id++) {
+			model = dev->data->models[model_id];
+			if (model != NULL) {
+				if (model->state == ML_CN10K_MODEL_STATE_LOADED) {
+					if (cn10k_ml_model_unload(dev, model_id) != 0)
+						plt_err("Could not unload model %d", model_id);
+				}
+				dev->data->models[model_id] = NULL;
+			}
+		}
+
+		models = dev->data->models;
+		models = rte_realloc(models, sizeof(models[0]) * conf->nb_models,
+				     RTE_CACHE_LINE_SIZE);
+		if (models == NULL) {
+			dev->data->nb_models = 0;
+			plt_err("Failed to realloc ml_models, nb_models = %u", conf->nb_models);
+			ret = -ENOMEM;
+			goto error;
+		}
+		memset(models, 0, sizeof(models[0]) * conf->nb_models);
+		dev->data->models = models;
+	}
+	dev->data->nb_models = conf->nb_models;
+
+	mldev->nb_models_loaded = 0;
 	mldev->state = ML_CN10K_DEV_STATE_CONFIGURED;
 
 	return 0;
@@ -211,14 +259,19 @@  cn10k_ml_dev_configure(struct rte_ml_dev *dev, const struct rte_ml_dev_config *c
 	if (dev->data->queue_pairs != NULL)
 		rte_free(dev->data->queue_pairs);
 
+	if (dev->data->models != NULL)
+		rte_free(dev->data->models);
+
 	return ret;
 }
 
 static int
 cn10k_ml_dev_close(struct rte_ml_dev *dev)
 {
+	struct cn10k_ml_model *model;
 	struct cn10k_ml_dev *mldev;
 	struct cn10k_ml_qp *qp;
+	int16_t model_id;
 	uint16_t qp_id;
 
 	if (dev == NULL)
@@ -226,6 +279,21 @@  cn10k_ml_dev_close(struct rte_ml_dev *dev)
 
 	mldev = dev->data->dev_private;
 
+	/* Unload all models */
+	for (model_id = 0; model_id < dev->data->nb_models; model_id++) {
+		model = dev->data->models[model_id];
+		if (model != NULL) {
+			if (model->state == ML_CN10K_MODEL_STATE_LOADED) {
+				if (cn10k_ml_model_unload(dev, model_id) != 0)
+					plt_err("Could not unload model %d", model_id);
+			}
+			dev->data->models[model_id] = NULL;
+		}
+	}
+
+	if (dev->data->models)
+		rte_free(dev->data->models);
+
 	/* Destroy all queue pairs */
 	for (qp_id = 0; qp_id < dev->data->nb_queue_pairs; qp_id++) {
 		qp = dev->data->queue_pairs[qp_id];
@@ -337,6 +405,88 @@  cn10k_ml_dev_queue_pair_setup(struct rte_ml_dev *dev, uint16_t queue_pair_id,
 	return 0;
 }
 
+int
+cn10k_ml_model_load(struct rte_ml_dev *dev, struct rte_ml_model_params *params, int16_t *model_id)
+{
+	struct cn10k_ml_model *model;
+	struct cn10k_ml_dev *mldev;
+
+	char str[RTE_MEMZONE_NAMESIZE];
+	const struct plt_memzone *mz;
+	uint64_t mz_size;
+	uint16_t idx;
+	bool found;
+
+	PLT_SET_USED(params);
+
+	mldev = dev->data->dev_private;
+
+	/* Find model ID */
+	found = false;
+	for (idx = 0; idx < dev->data->nb_models; idx++) {
+		if (dev->data->models[idx] == NULL) {
+			found = true;
+			break;
+		}
+	}
+
+	if (!found) {
+		plt_err("No slots available to load new model");
+		return -ENOMEM;
+	}
+
+	/* Get MZ size */
+	mz_size = PLT_ALIGN_CEIL(sizeof(struct cn10k_ml_model), ML_CN10K_ALIGN_SIZE);
+
+	/* Allocate memzone for model object and model data */
+	snprintf(str, RTE_MEMZONE_NAMESIZE, "%s_%u", CN10K_ML_MODEL_MEMZONE_NAME, idx);
+	mz = plt_memzone_reserve_aligned(str, mz_size, 0, ML_CN10K_ALIGN_SIZE);
+	if (!mz) {
+		plt_err("plt_memzone_reserve failed : %s", str);
+		return -ENOMEM;
+	}
+
+	model = mz->addr;
+	model->mldev = mldev;
+	model->model_id = idx;
+
+	plt_spinlock_init(&model->lock);
+	model->state = ML_CN10K_MODEL_STATE_LOADED;
+	dev->data->models[idx] = model;
+	mldev->nb_models_loaded++;
+
+	*model_id = idx;
+
+	return 0;
+}
+
+int
+cn10k_ml_model_unload(struct rte_ml_dev *dev, int16_t model_id)
+{
+	char str[RTE_MEMZONE_NAMESIZE];
+	struct cn10k_ml_model *model;
+	struct cn10k_ml_dev *mldev;
+
+	mldev = dev->data->dev_private;
+	model = dev->data->models[model_id];
+
+	if (model == NULL) {
+		plt_err("Invalid model_id = %d", model_id);
+		return -EINVAL;
+	}
+
+	if (model->state != ML_CN10K_MODEL_STATE_LOADED) {
+		plt_err("Cannot unload. Model in use.");
+		return -EBUSY;
+	}
+
+	dev->data->models[model_id] = NULL;
+	mldev->nb_models_loaded--;
+
+	snprintf(str, RTE_MEMZONE_NAMESIZE, "%s_%d", CN10K_ML_MODEL_MEMZONE_NAME, model_id);
+	return plt_memzone_free(plt_memzone_lookup(str));
+}
+
 struct rte_ml_dev_ops cn10k_ml_ops = {
 	/* Device control ops */
 	.dev_info_get = cn10k_ml_dev_info_get,
@@ -348,4 +498,8 @@  struct rte_ml_dev_ops cn10k_ml_ops = {
 	/* Queue-pair handling ops */
 	.dev_queue_pair_setup = cn10k_ml_dev_queue_pair_setup,
 	.dev_queue_pair_release = cn10k_ml_dev_queue_pair_release,
+
+	/* Model ops */
+	.model_load = cn10k_ml_model_load,
+	.model_unload = cn10k_ml_model_unload,
 };
diff --git a/drivers/ml/cnxk/cn10k_ml_ops.h b/drivers/ml/cnxk/cn10k_ml_ops.h
index 455109f10f..5caebde908 100644
--- a/drivers/ml/cnxk/cn10k_ml_ops.h
+++ b/drivers/ml/cnxk/cn10k_ml_ops.h
@@ -53,4 +53,9 @@  struct cn10k_ml_qp {
 /* CN10K device ops */
 extern struct rte_ml_dev_ops cn10k_ml_ops;
 
+/* Slow-path ops */
+int cn10k_ml_model_load(struct rte_ml_dev *dev, struct rte_ml_model_params *params,
+			int16_t *model_id);
+int cn10k_ml_model_unload(struct rte_ml_dev *dev, int16_t model_id);
+
 #endif /* _CN10K_ML_OPS_H_ */
diff --git a/drivers/ml/cnxk/meson.build b/drivers/ml/cnxk/meson.build
index 7c6fa5e906..1f1c923329 100644
--- a/drivers/ml/cnxk/meson.build
+++ b/drivers/ml/cnxk/meson.build
@@ -10,11 +10,13 @@  endif
 sources = files(
         'cn10k_ml_dev.c',
         'cn10k_ml_ops.c',
+        'cn10k_ml_model.c',
 )
 
 headers = files(
         'cn10k_ml_dev.h',
         'cn10k_ml_ops.h',
+        'cn10k_ml_model.h',
 )
 
 deps += ['mldev', 'common_ml', 'common_cnxk', 'kvargs']