/* SPDX-License-Identifier: BSD-3-Clause * Copyright (c) 2022 Marvell. */ #include #include #include #include #include "test_model_ops.h" #include "test_stats.h" static bool test_model_ops_cap_check(struct ml_options *opt) { if (!ml_test_cap_check(opt)) return false; return true; } static int test_model_ops_opt_check(struct ml_options *opt) { uint32_t i; int ret; /* check common opts */ ret = ml_test_opt_check(opt); if (ret != 0) return ret; /* check for at least one model */ if (opt->nb_filelist == 0) { ml_err("Models list empty, need at least one model to run the test\n"); return -EINVAL; } /* check model file availability */ for (i = 0; i < opt->nb_filelist; i++) { if (access(opt->filelist[i].model, F_OK) == -1) { ml_err("Model file not available: id = %u, file = %s", i, opt->filelist[i].model); return -ENOENT; } } return 0; } static void test_model_ops_opt_dump(struct ml_options *opt) { uint32_t i; /* dump common opts */ ml_test_opt_dump(opt); /* dump test specific opts */ ml_dump_begin("models"); for (i = 0; i < opt->nb_filelist; i++) ml_dump_list("model", i, opt->filelist[i].model); ml_dump_end; } static int test_model_ops_setup(struct ml_test *test, struct ml_options *opt) { struct test_model_ops *t; void *test_model_ops; int ret = 0; uint32_t i; /* allocate model ops test structure */ test_model_ops = rte_zmalloc_socket(test->name, sizeof(struct test_model_ops), RTE_CACHE_LINE_SIZE, opt->socket_id); if (test_model_ops == NULL) { ml_err("Failed to allocate memory for test_model"); ret = -ENOMEM; goto error; } test->test_priv = test_model_ops; t = ml_test_priv(test); t->cmn.result = ML_TEST_FAILED; t->cmn.opt = opt; /* get device info */ ret = rte_ml_dev_info_get(opt->dev_id, &t->cmn.dev_info); if (ret < 0) { ml_err("Failed to get device info"); goto error; } /* set model initial state */ for (i = 0; i < opt->nb_filelist; i++) t->model[i].state = MODEL_INITIAL; return 0; error: rte_free(test_model_ops); return ret; } static void test_model_ops_destroy(struct ml_test *test, struct ml_options *opt) { struct test_model_ops *t; RTE_SET_USED(opt); t = ml_test_priv(test); rte_free(t); } static int test_model_ops_mldev_setup(struct ml_test *test, struct ml_options *opt) { int ret; ret = ml_test_device_configure(test, opt); if (ret != 0) return ret; ret = ml_test_device_start(test, opt); if (ret != 0) goto error; return 0; error: ml_test_device_close(test, opt); return ret; } static int test_model_ops_mldev_destroy(struct ml_test *test, struct ml_options *opt) { int ret; ret = ml_test_device_stop(test, opt); if (ret != 0) goto error; ret = ml_test_device_close(test, opt); if (ret != 0) return ret; return 0; error: ml_test_device_close(test, opt); return ret; } /* Sub-test A: (load -> start -> stop -> unload) x n */ static int test_model_ops_subtest_a(struct ml_test *test, struct ml_options *opt) { struct test_model_ops *t; int ret = 0; uint32_t i; t = ml_test_priv(test); /* load + start + stop + unload */ for (i = 0; i < opt->nb_filelist; i++) { ret = ml_model_load(test, opt, &t->model[i], i); if (ret != 0) goto error; ret = ml_model_start(test, opt, &t->model[i], i); if (ret != 0) goto error; ret = ml_model_stop(test, opt, &t->model[i], i); if (ret != 0) goto error; ret = ml_model_unload(test, opt, &t->model[i], i); if (ret != 0) goto error; } error: for (i = 0; i < opt->nb_filelist; i++) ml_model_stop(test, opt, &t->model[i], i); for (i = 0; i < opt->nb_filelist; i++) ml_model_unload(test, opt, &t->model[i], i); return ret; } /* Sub-test B: load x n -> start x n -> stop x n -> unload x n */ static int test_model_ops_subtest_b(struct ml_test *test, struct ml_options *opt) { struct test_model_ops *t; int ret = 0; uint32_t i; t = ml_test_priv(test); /* load */ for (i = 0; i < opt->nb_filelist; i++) { ret = ml_model_load(test, opt, &t->model[i], i); if (ret != 0) goto error; } /* start */ for (i = 0; i < opt->nb_filelist; i++) { ret = ml_model_start(test, opt, &t->model[i], i); if (ret != 0) goto error; } /* stop */ for (i = 0; i < opt->nb_filelist; i++) { ret = ml_model_stop(test, opt, &t->model[i], i); if (ret != 0) goto error; } /* unload */ for (i = 0; i < opt->nb_filelist; i++) { ret = ml_model_unload(test, opt, &t->model[i], i); if (ret != 0) goto error; } return 0; error: for (i = 0; i < opt->nb_filelist; i++) ml_model_stop(test, opt, &t->model[i], i); for (i = 0; i < opt->nb_filelist; i++) ml_model_unload(test, opt, &t->model[i], i); return ret; } /* Sub-test C: load x n + (start + stop) x n + unload x n */ static int test_model_ops_subtest_c(struct ml_test *test, struct ml_options *opt) { struct test_model_ops *t; int ret = 0; uint32_t i; t = ml_test_priv(test); /* load */ for (i = 0; i < opt->nb_filelist; i++) { ret = ml_model_load(test, opt, &t->model[i], i); if (ret != 0) goto error; } /* start + stop */ for (i = 0; i < opt->nb_filelist; i++) { ret = ml_model_start(test, opt, &t->model[i], i); if (ret != 0) goto error; ret = ml_model_stop(test, opt, &t->model[i], i); if (ret != 0) goto error; } /* unload */ for (i = 0; i < opt->nb_filelist; i++) { ret = ml_model_unload(test, opt, &t->model[i], i); if (ret != 0) goto error; } return 0; error: for (i = 0; i < opt->nb_filelist; i++) ml_model_stop(test, opt, &t->model[i], i); for (i = 0; i < opt->nb_filelist; i++) ml_model_unload(test, opt, &t->model[i], i); return ret; } /* Sub-test D: (load + start) x n -> (stop + unload) x n */ static int test_model_ops_subtest_d(struct ml_test *test, struct ml_options *opt) { struct test_model_ops *t; int ret = 0; uint32_t i; t = ml_test_priv(test); /* load + start */ for (i = 0; i < opt->nb_filelist; i++) { ret = ml_model_load(test, opt, &t->model[i], i); if (ret != 0) goto error; ret = ml_model_start(test, opt, &t->model[i], i); if (ret != 0) goto error; } /* stop + unload */ for (i = 0; i < opt->nb_filelist; i++) { ret = ml_model_stop(test, opt, &t->model[i], i); if (ret != 0) goto error; ret = ml_model_unload(test, opt, &t->model[i], i); if (ret != 0) goto error; } return 0; error: for (i = 0; i < opt->nb_filelist; i++) ml_model_stop(test, opt, &t->model[i], i); for (i = 0; i < opt->nb_filelist; i++) ml_model_unload(test, opt, &t->model[i], i); return ret; } static int test_model_ops_driver(struct ml_test *test, struct ml_options *opt) { struct test_model_ops *t; int ret = 0; t = ml_test_priv(test); /* device setup */ ret = test_model_ops_mldev_setup(test, opt); if (ret != 0) return ret; printf("\n"); /* sub-test A */ ret = test_model_ops_subtest_a(test, opt); if (ret != 0) { printf("Model Ops Sub-test A: " CLRED "%s" CLNRM "\n", "Failed"); goto error; } else { printf("Model Ops Sub-test A: " CLYEL "%s" CLNRM "\n", "Passed"); } /* sub-test B */ ret = test_model_ops_subtest_b(test, opt); if (ret != 0) { printf("Model Ops Sub-test B: " CLRED "%s" CLNRM "\n", "Failed"); goto error; } else { printf("Model Ops Sub-test B: " CLYEL "%s" CLNRM "\n", "Passed"); } /* sub-test C */ ret = test_model_ops_subtest_c(test, opt); if (ret != 0) { printf("Model Ops Sub-test C: " CLRED "%s" CLNRM "\n", "Failed"); goto error; } else { printf("Model Ops Sub-test C: " CLYEL "%s" CLNRM "\n", "Passed"); } /* sub-test D */ ret = test_model_ops_subtest_d(test, opt); if (ret != 0) { printf("Model Ops Sub-test D: " CLRED "%s" CLNRM "\n", "Failed"); goto error; } else { printf("Model Ops Sub-test D: " CLYEL "%s" CLNRM "\n", "Passed"); } printf("\n"); ml_stats_get(test, opt, RTE_ML_DEV_XSTATS_DEVICE, -1); /* device destroy */ ret = test_model_ops_mldev_destroy(test, opt); if (ret != 0) return ret; t->cmn.result = ML_TEST_SUCCESS; return 0; error: test_model_ops_mldev_destroy(test, opt); t->cmn.result = ML_TEST_FAILED; return ret; } static int test_model_ops_result(struct ml_test *test, struct ml_options *opt) { struct test_model_ops *t; RTE_SET_USED(opt); t = ml_test_priv(test); return t->cmn.result; } static const struct ml_test_ops model_ops = { .cap_check = test_model_ops_cap_check, .opt_check = test_model_ops_opt_check, .opt_dump = test_model_ops_opt_dump, .test_setup = test_model_ops_setup, .test_destroy = test_model_ops_destroy, .test_driver = test_model_ops_driver, .test_result = test_model_ops_result, }; ML_TEST_REGISTER(model_ops);