Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright (c) 2023 Marvell.
3 : : */
4 : :
5 : : #include <rte_mldev.h>
6 : : #include <rte_mldev_pmd.h>
7 : :
8 : : #include <mldev_utils.h>
9 : :
10 : : #include "cnxk_ml_dev.h"
11 : : #include "cnxk_ml_io.h"
12 : : #include "cnxk_ml_model.h"
13 : : #include "cnxk_ml_ops.h"
14 : :
15 : : /* ML model macros */
16 : : #define CNXK_ML_MODEL_MEMZONE_NAME "ml_cnxk_model_mz"
17 : :
18 : : __rte_hot void
19 : 0 : cnxk_ml_set_poll_ptr(struct cnxk_ml_req *req)
20 : : {
21 : 0 : plt_write64(ML_CNXK_POLL_JOB_START, req->status);
22 : 0 : }
23 : :
24 : : __rte_hot uint64_t
25 : 0 : cnxk_ml_get_poll_ptr(struct cnxk_ml_req *req)
26 : : {
27 : 0 : return plt_read64(req->status);
28 : : }
29 : :
30 : : static void
31 : : qp_memzone_name_get(char *name, int size, int dev_id, int qp_id)
32 : : {
33 : : snprintf(name, size, "cnxk_ml_qp_mem_%u:%u", dev_id, qp_id);
34 : : }
35 : :
36 : : static int
37 : 0 : cnxk_ml_qp_destroy(const struct rte_ml_dev *dev, struct cnxk_ml_qp *qp)
38 : : {
39 : : const struct rte_memzone *qp_mem;
40 : : char name[RTE_MEMZONE_NAMESIZE];
41 : : int ret;
42 : :
43 : 0 : qp_memzone_name_get(name, RTE_MEMZONE_NAMESIZE, dev->data->dev_id, qp->id);
44 : 0 : qp_mem = rte_memzone_lookup(name);
45 : 0 : ret = rte_memzone_free(qp_mem);
46 [ # # ]: 0 : if (ret)
47 : : return ret;
48 : :
49 : 0 : rte_free(qp);
50 : :
51 : 0 : return 0;
52 : : }
53 : :
54 : : static int
55 : 0 : cnxk_ml_dev_queue_pair_release(struct rte_ml_dev *dev, uint16_t queue_pair_id)
56 : : {
57 : : struct cnxk_ml_qp *qp;
58 : : int ret;
59 : :
60 : 0 : qp = dev->data->queue_pairs[queue_pair_id];
61 [ # # ]: 0 : if (qp == NULL)
62 : : return -EINVAL;
63 : :
64 : 0 : ret = cnxk_ml_qp_destroy(dev, qp);
65 [ # # ]: 0 : if (ret) {
66 : 0 : plt_err("Could not destroy queue pair %u", queue_pair_id);
67 : 0 : return ret;
68 : : }
69 : :
70 : 0 : dev->data->queue_pairs[queue_pair_id] = NULL;
71 : :
72 : 0 : return 0;
73 : : }
74 : :
75 : : static struct cnxk_ml_qp *
76 : 0 : cnxk_ml_qp_create(const struct rte_ml_dev *dev, uint16_t qp_id, uint32_t nb_desc, int socket_id)
77 : : {
78 : : const struct rte_memzone *qp_mem;
79 : : char name[RTE_MEMZONE_NAMESIZE];
80 : : struct cnxk_ml_dev *cnxk_mldev;
81 : : struct cnxk_ml_qp *qp;
82 : : uint32_t len;
83 : : uint8_t *va;
84 : :
85 : 0 : cnxk_mldev = dev->data->dev_private;
86 : :
87 : : /* Allocate queue pair */
88 : 0 : qp = rte_zmalloc_socket("cnxk_ml_pmd_queue_pair", sizeof(struct cnxk_ml_qp), ROC_ALIGN,
89 : : socket_id);
90 [ # # ]: 0 : if (qp == NULL) {
91 : 0 : plt_err("Could not allocate queue pair");
92 : 0 : return NULL;
93 : : }
94 : :
95 : : /* For request queue */
96 : 0 : len = nb_desc * sizeof(struct cnxk_ml_req);
97 : 0 : qp_memzone_name_get(name, RTE_MEMZONE_NAMESIZE, dev->data->dev_id, qp_id);
98 : 0 : qp_mem = rte_memzone_reserve_aligned(
99 : : name, len, socket_id, RTE_MEMZONE_SIZE_HINT_ONLY | RTE_MEMZONE_256MB, ROC_ALIGN);
100 [ # # ]: 0 : if (qp_mem == NULL) {
101 : 0 : plt_err("Could not reserve memzone: %s", name);
102 : 0 : goto qp_free;
103 : : }
104 : :
105 : 0 : va = qp_mem->addr;
106 : : memset(va, 0, len);
107 : :
108 : : /* Initialize Request queue */
109 : 0 : qp->id = qp_id;
110 : 0 : qp->queue.reqs = (struct cnxk_ml_req *)va;
111 : 0 : qp->queue.head = 0;
112 : 0 : qp->queue.tail = 0;
113 : 0 : qp->queue.wait_cycles = ML_CNXK_CMD_TIMEOUT * plt_tsc_hz();
114 : 0 : qp->nb_desc = nb_desc;
115 : 0 : qp->stats.enqueued_count = 0;
116 : 0 : qp->stats.dequeued_count = 0;
117 : 0 : qp->stats.enqueue_err_count = 0;
118 : 0 : qp->stats.dequeue_err_count = 0;
119 : :
120 [ # # ]: 0 : if (cnxk_mldev->type == CNXK_ML_DEV_TYPE_PCI)
121 : 0 : cn10k_ml_qp_initialize(cnxk_mldev, qp);
122 : :
123 : : return qp;
124 : :
125 : : qp_free:
126 : 0 : rte_free(qp);
127 : :
128 : 0 : return NULL;
129 : : }
130 : :
131 : : static int
132 : 0 : cnxk_ml_xstats_init(struct cnxk_ml_dev *cnxk_mldev)
133 : : {
134 : : uint16_t nb_stats;
135 : : uint16_t stat_id;
136 : : uint16_t model;
137 : : uint16_t layer;
138 : : uint16_t i;
139 : :
140 : : /* Allocate memory for xstats entries. Don't allocate during reconfigure */
141 : : nb_stats = RTE_DIM(device_xstats) +
142 : : RTE_DIM(layer_xstats) * ML_CNXK_MAX_MODELS * ML_CNXK_MODEL_MAX_LAYERS +
143 : : RTE_DIM(model_xstats) * ML_CNXK_MAX_MODELS;
144 [ # # ]: 0 : if (cnxk_mldev->xstats.entries == NULL)
145 : 0 : cnxk_mldev->xstats.entries = rte_zmalloc(
146 : : "cnxk_ml_xstats", sizeof(struct cnxk_ml_xstats_entry) * nb_stats,
147 : : PLT_CACHE_LINE_SIZE);
148 : :
149 [ # # ]: 0 : if (cnxk_mldev->xstats.entries == NULL)
150 : : return -ENOMEM;
151 : :
152 : : /* Initialize device xstats */
153 : : stat_id = 0;
154 [ # # ]: 0 : for (i = 0; i < RTE_DIM(device_xstats); i++) {
155 : 0 : cnxk_mldev->xstats.entries[stat_id].map.id = stat_id;
156 : 0 : snprintf(cnxk_mldev->xstats.entries[stat_id].map.name,
157 : : sizeof(cnxk_mldev->xstats.entries[stat_id].map.name), "%s",
158 : 0 : device_xstats[i].name);
159 : :
160 : 0 : cnxk_mldev->xstats.entries[stat_id].mode = RTE_ML_DEV_XSTATS_DEVICE;
161 : 0 : cnxk_mldev->xstats.entries[stat_id].group = CNXK_ML_XSTATS_GROUP_DEVICE;
162 : 0 : cnxk_mldev->xstats.entries[stat_id].type = device_xstats[i].type;
163 : 0 : cnxk_mldev->xstats.entries[stat_id].fn_id = CNXK_ML_XSTATS_FN_DEVICE;
164 : 0 : cnxk_mldev->xstats.entries[stat_id].obj_idx = 0;
165 : 0 : cnxk_mldev->xstats.entries[stat_id].reset_allowed = device_xstats[i].reset_allowed;
166 : 0 : stat_id++;
167 : : }
168 : 0 : cnxk_mldev->xstats.count_mode_device = stat_id;
169 : :
170 : : /* Initialize model xstats */
171 [ # # ]: 0 : for (model = 0; model < ML_CNXK_MAX_MODELS; model++) {
172 : 0 : cnxk_mldev->xstats.offset_for_model[model] = stat_id;
173 : :
174 [ # # ]: 0 : for (i = 0; i < RTE_DIM(model_xstats); i++) {
175 : 0 : cnxk_mldev->xstats.entries[stat_id].map.id = stat_id;
176 : 0 : cnxk_mldev->xstats.entries[stat_id].mode = RTE_ML_DEV_XSTATS_MODEL;
177 : 0 : cnxk_mldev->xstats.entries[stat_id].group = CNXK_ML_XSTATS_GROUP_MODEL;
178 : 0 : cnxk_mldev->xstats.entries[stat_id].type = model_xstats[i].type;
179 : 0 : cnxk_mldev->xstats.entries[stat_id].fn_id = CNXK_ML_XSTATS_FN_MODEL;
180 : 0 : cnxk_mldev->xstats.entries[stat_id].obj_idx = model;
181 : 0 : cnxk_mldev->xstats.entries[stat_id].layer_id = -1;
182 : 0 : cnxk_mldev->xstats.entries[stat_id].reset_allowed =
183 : 0 : model_xstats[i].reset_allowed;
184 : :
185 : : /* Name of xstat is updated during model load */
186 : 0 : snprintf(cnxk_mldev->xstats.entries[stat_id].map.name,
187 : : sizeof(cnxk_mldev->xstats.entries[stat_id].map.name),
188 : 0 : "Model-%u-%s", model, model_xstats[i].name);
189 : :
190 : 0 : stat_id++;
191 : : }
192 : :
193 [ # # ]: 0 : for (layer = 0; layer < ML_CNXK_MODEL_MAX_LAYERS; layer++) {
194 : 0 : cnxk_mldev->xstats.offset_for_layer[model][layer] = stat_id;
195 : :
196 [ # # ]: 0 : for (i = 0; i < RTE_DIM(layer_xstats); i++) {
197 : 0 : cnxk_mldev->xstats.entries[stat_id].map.id = stat_id;
198 : 0 : cnxk_mldev->xstats.entries[stat_id].mode = RTE_ML_DEV_XSTATS_MODEL;
199 : 0 : cnxk_mldev->xstats.entries[stat_id].group =
200 : : CNXK_ML_XSTATS_GROUP_LAYER;
201 : 0 : cnxk_mldev->xstats.entries[stat_id].type = layer_xstats[i].type;
202 : 0 : cnxk_mldev->xstats.entries[stat_id].fn_id = CNXK_ML_XSTATS_FN_MODEL;
203 : 0 : cnxk_mldev->xstats.entries[stat_id].obj_idx = model;
204 : 0 : cnxk_mldev->xstats.entries[stat_id].layer_id = layer;
205 : 0 : cnxk_mldev->xstats.entries[stat_id].reset_allowed =
206 : 0 : layer_xstats[i].reset_allowed;
207 : :
208 : : /* Name of xstat is updated during model load */
209 : 0 : snprintf(cnxk_mldev->xstats.entries[stat_id].map.name,
210 : : sizeof(cnxk_mldev->xstats.entries[stat_id].map.name),
211 : 0 : "Layer-%u-%u-%s", model, layer, layer_xstats[i].name);
212 : :
213 : 0 : stat_id++;
214 : : }
215 : :
216 : 0 : cnxk_mldev->xstats.count_per_layer[model][layer] = RTE_DIM(layer_xstats);
217 : : }
218 : :
219 : 0 : cnxk_mldev->xstats.count_per_model[model] =
220 : : RTE_DIM(layer_xstats) + ML_CNXK_MODEL_MAX_LAYERS * RTE_DIM(model_xstats);
221 : : }
222 : :
223 : 0 : cnxk_mldev->xstats.count_mode_model = stat_id - cnxk_mldev->xstats.count_mode_device;
224 : 0 : cnxk_mldev->xstats.count = stat_id;
225 : :
226 : 0 : return 0;
227 : : }
228 : :
229 : : void
230 : 0 : cnxk_ml_xstats_model_name_update(struct cnxk_ml_dev *cnxk_mldev, uint16_t model_id)
231 : : {
232 : : struct cnxk_ml_model *model;
233 : : uint16_t rclk_freq;
234 : : uint16_t sclk_freq;
235 : : uint16_t stat_id;
236 : : char suffix[8];
237 : : uint16_t i;
238 : :
239 : 0 : model = cnxk_mldev->mldev->data->models[model_id];
240 : 0 : stat_id = cnxk_mldev->xstats.offset_for_model[model_id];
241 : :
242 : 0 : roc_clk_freq_get(&rclk_freq, &sclk_freq);
243 [ # # ]: 0 : if (sclk_freq == 0)
244 : 0 : rte_strscpy(suffix, "cycles", 7);
245 : : else
246 : 0 : rte_strscpy(suffix, "ns", 3);
247 : :
248 : : /* Update xstat name based on layer name and sclk availability */
249 [ # # ]: 0 : for (i = 0; i < RTE_DIM(model_xstats); i++) {
250 [ # # ]: 0 : if (model->type == ML_CNXK_MODEL_TYPE_GLOW)
251 : 0 : cn10k_ml_xstat_model_name_set(cnxk_mldev, model, stat_id, i, suffix);
252 : : else
253 : 0 : mvtvm_ml_model_xstat_name_set(cnxk_mldev, model, stat_id, i, suffix);
254 : :
255 : 0 : stat_id++;
256 : : }
257 : 0 : }
258 : :
259 : : static void
260 : : cnxk_ml_xstats_uninit(struct cnxk_ml_dev *cnxk_mldev)
261 : : {
262 : 0 : rte_free(cnxk_mldev->xstats.entries);
263 : 0 : cnxk_mldev->xstats.entries = NULL;
264 : :
265 : 0 : cnxk_mldev->xstats.count = 0;
266 : : }
267 : :
268 : : static uint64_t
269 : 0 : cnxk_ml_dev_xstat_get(struct cnxk_ml_dev *cnxk_mldev, uint16_t obj_idx __rte_unused,
270 : : int32_t layer_id __rte_unused, enum cnxk_ml_xstats_type type)
271 : : {
272 [ # # # # : 0 : switch (type) {
# ]
273 : 0 : case nb_models_loaded:
274 : 0 : return cnxk_mldev->nb_models_loaded;
275 : 0 : case nb_models_unloaded:
276 : 0 : return cnxk_mldev->nb_models_unloaded;
277 : 0 : case nb_models_started:
278 : 0 : return cnxk_mldev->nb_models_started;
279 : 0 : case nb_models_stopped:
280 : 0 : return cnxk_mldev->nb_models_stopped;
281 : : default:
282 : : return -1;
283 : : }
284 : :
285 : : return 0;
286 : : }
287 : :
288 : : static uint64_t
289 : 0 : cnxk_ml_model_xstat_get(struct cnxk_ml_dev *cnxk_mldev, uint16_t obj_idx, int32_t layer_id,
290 : : enum cnxk_ml_xstats_type type)
291 : : {
292 : : struct cnxk_ml_model *model;
293 : : struct cnxk_ml_layer *layer;
294 : : uint16_t rclk_freq; /* MHz */
295 : : uint16_t sclk_freq; /* MHz */
296 : : uint64_t value = 0;
297 : :
298 : 0 : model = cnxk_mldev->mldev->data->models[obj_idx];
299 [ # # ]: 0 : if (model == NULL)
300 : : return 0;
301 : :
302 [ # # ]: 0 : if (layer_id >= 0) {
303 : 0 : layer = &model->layer[layer_id];
304 : 0 : goto layer_xstats;
305 : : } else {
306 : : layer = NULL;
307 : 0 : goto model_xstats;
308 : : }
309 : :
310 : : layer_xstats:
311 : 0 : value = cn10k_ml_model_xstat_get(cnxk_mldev, layer, type);
312 : 0 : goto exit_xstats;
313 : :
314 : : model_xstats:
315 : 0 : value = mvtvm_ml_model_xstat_get(cnxk_mldev, model, type);
316 : :
317 : 0 : exit_xstats:
318 : 0 : roc_clk_freq_get(&rclk_freq, &sclk_freq);
319 [ # # ]: 0 : if (sclk_freq != 0) /* return in ns */
320 : 0 : value = (value * 1000ULL) / sclk_freq;
321 : :
322 : : return value;
323 : : }
324 : :
325 : : static int
326 : 0 : cnxk_ml_device_xstats_reset(struct cnxk_ml_dev *cnxk_mldev, const uint16_t stat_ids[],
327 : : uint16_t nb_ids)
328 : : {
329 : : struct cnxk_ml_xstats_entry *xs;
330 : : uint16_t nb_stats;
331 : : uint16_t stat_id;
332 : : uint32_t i;
333 : :
334 [ # # ]: 0 : if (stat_ids == NULL)
335 : 0 : nb_stats = cnxk_mldev->xstats.count_mode_device;
336 : : else
337 : : nb_stats = nb_ids;
338 : :
339 [ # # ]: 0 : for (i = 0; i < nb_stats; i++) {
340 [ # # ]: 0 : if (stat_ids == NULL)
341 : 0 : stat_id = i;
342 : : else
343 : 0 : stat_id = stat_ids[i];
344 : :
345 [ # # ]: 0 : if (stat_id >= cnxk_mldev->xstats.count_mode_device)
346 : : return -EINVAL;
347 : :
348 : 0 : xs = &cnxk_mldev->xstats.entries[stat_id];
349 [ # # ]: 0 : if (!xs->reset_allowed)
350 : 0 : continue;
351 : :
352 : 0 : xs->reset_value =
353 [ # # # # : 0 : cnxk_ml_dev_xstat_get(cnxk_mldev, xs->obj_idx, xs->layer_id, xs->type);
# ]
354 : : }
355 : :
356 : : return 0;
357 : : }
358 : :
359 : : #define ML_AVG_RESET_FOREACH_QP(cnxk_mldev, layer, qp_id, str) \
360 : : do { \
361 : : for (qp_id = 0; qp_id < cnxk_mldev->mldev->data->nb_queue_pairs; qp_id++) { \
362 : : layer->glow.burst_xstats[qp_id].str##_latency_tot = 0; \
363 : : layer->glow.burst_xstats[qp_id].str##_reset_count = \
364 : : layer->glow.burst_xstats[qp_id].dequeued_count; \
365 : : } \
366 : : } while (0)
367 : :
368 : : #define ML_MIN_RESET_FOREACH_QP(cnxk_mldev, layer, qp_id, str) \
369 : : do { \
370 : : for (qp_id = 0; qp_id < cnxk_mldev->mldev->data->nb_queue_pairs; qp_id++) \
371 : : layer->glow.burst_xstats[qp_id].str##_latency_min = UINT64_MAX; \
372 : : } while (0)
373 : :
374 : : #define ML_MAX_RESET_FOREACH_QP(cnxk_mldev, layer, qp_id, str) \
375 : : do { \
376 : : for (qp_id = 0; qp_id < cnxk_mldev->mldev->data->nb_queue_pairs; qp_id++) \
377 : : layer->glow.burst_xstats[qp_id].str##_latency_max = 0; \
378 : : } while (0)
379 : :
380 : : static void
381 : 0 : cnxk_ml_reset_model_stat(struct cnxk_ml_dev *cnxk_mldev, uint16_t model_id,
382 : : enum cnxk_ml_xstats_type type)
383 : : {
384 : : struct cnxk_ml_model *model;
385 : : struct cnxk_ml_layer *layer;
386 : : uint16_t layer_id = 0;
387 : : uint32_t qp_id;
388 : :
389 : 0 : model = cnxk_mldev->mldev->data->models[model_id];
390 : : layer = &model->layer[layer_id];
391 : :
392 [ # # # # : 0 : switch (type) {
# # # ]
393 : : case avg_hw_latency:
394 [ # # ]: 0 : ML_AVG_RESET_FOREACH_QP(cnxk_mldev, layer, qp_id, hw);
395 : : break;
396 : : case min_hw_latency:
397 [ # # ]: 0 : ML_MIN_RESET_FOREACH_QP(cnxk_mldev, layer, qp_id, hw);
398 : : break;
399 : : case max_hw_latency:
400 [ # # ]: 0 : ML_MAX_RESET_FOREACH_QP(cnxk_mldev, layer, qp_id, hw);
401 : : break;
402 : : case avg_fw_latency:
403 [ # # ]: 0 : ML_AVG_RESET_FOREACH_QP(cnxk_mldev, layer, qp_id, fw);
404 : : break;
405 : : case min_fw_latency:
406 [ # # ]: 0 : ML_MIN_RESET_FOREACH_QP(cnxk_mldev, layer, qp_id, fw);
407 : : break;
408 : : case max_fw_latency:
409 [ # # ]: 0 : ML_MAX_RESET_FOREACH_QP(cnxk_mldev, layer, qp_id, fw);
410 : : break;
411 : : default:
412 : : return;
413 : : }
414 : : }
415 : :
416 : : static int
417 : 0 : cnxk_ml_model_xstats_reset(struct cnxk_ml_dev *cnxk_mldev, int32_t model_id,
418 : : const uint16_t stat_ids[], uint16_t nb_ids)
419 : : {
420 : : struct cnxk_ml_xstats_entry *xs;
421 : : struct cnxk_ml_model *model;
422 : : int32_t lcl_model_id = 0;
423 : : uint16_t layer_id = 0;
424 : : uint16_t start_id;
425 : : uint16_t end_id;
426 : : int32_t i;
427 : : int32_t j;
428 : :
429 [ # # ]: 0 : for (i = 0; i < ML_CNXK_MAX_MODELS; i++) {
430 [ # # ]: 0 : if (model_id == -1) {
431 : 0 : model = cnxk_mldev->mldev->data->models[i];
432 [ # # ]: 0 : if (model == NULL) /* skip inactive models */
433 : 0 : continue;
434 : : } else {
435 [ # # ]: 0 : if (model_id != i)
436 : 0 : continue;
437 : :
438 : 0 : model = cnxk_mldev->mldev->data->models[model_id];
439 [ # # ]: 0 : if (model == NULL) {
440 : 0 : plt_err("Invalid model_id = %d", model_id);
441 : 0 : return -EINVAL;
442 : : }
443 : : }
444 : :
445 : 0 : start_id = cnxk_mldev->xstats.offset_for_layer[i][layer_id];
446 : 0 : end_id = cnxk_mldev->xstats.offset_for_layer[i][layer_id] +
447 : 0 : cnxk_mldev->xstats.count_per_layer[i][layer_id] - 1;
448 : :
449 [ # # ]: 0 : if (stat_ids == NULL) {
450 [ # # ]: 0 : for (j = start_id; j <= end_id; j++) {
451 : 0 : xs = &cnxk_mldev->xstats.entries[j];
452 : 0 : cnxk_ml_reset_model_stat(cnxk_mldev, i, xs->type);
453 : : }
454 : : } else {
455 [ # # ]: 0 : for (j = 0; j < nb_ids; j++) {
456 [ # # # # ]: 0 : if (stat_ids[j] < start_id || stat_ids[j] > end_id) {
457 : 0 : plt_err("Invalid stat_ids[%d] = %d for model_id = %d", j,
458 : : stat_ids[j], lcl_model_id);
459 : 0 : return -EINVAL;
460 : : }
461 : 0 : xs = &cnxk_mldev->xstats.entries[stat_ids[j]];
462 : 0 : cnxk_ml_reset_model_stat(cnxk_mldev, i, xs->type);
463 : : }
464 : : }
465 : : }
466 : :
467 : : return 0;
468 : : }
469 : :
470 : : static int
471 : 0 : cnxk_ml_dev_info_get(struct rte_ml_dev *dev, struct rte_ml_dev_info *dev_info)
472 : : {
473 : : struct cnxk_ml_dev *cnxk_mldev;
474 : :
475 [ # # ]: 0 : if (dev == NULL || dev_info == NULL)
476 : : return -EINVAL;
477 : :
478 [ # # ]: 0 : cnxk_mldev = dev->data->dev_private;
479 : :
480 : : memset(dev_info, 0, sizeof(struct rte_ml_dev_info));
481 : 0 : dev_info->driver_name = dev->device->driver->name;
482 : 0 : dev_info->max_models = ML_CNXK_MAX_MODELS;
483 : :
484 [ # # ]: 0 : if (cnxk_mldev->type == CNXK_ML_DEV_TYPE_PCI)
485 : 0 : return cn10k_ml_dev_info_get(cnxk_mldev, dev_info);
486 : : else
487 : 0 : return mvtvm_ml_dev_info_get(cnxk_mldev, dev_info);
488 : :
489 : : return 0;
490 : : }
491 : :
492 : : static int
493 : 0 : cnxk_ml_dev_configure(struct rte_ml_dev *dev, const struct rte_ml_dev_config *conf)
494 : : {
495 : : struct rte_ml_dev_info dev_info;
496 : : struct cnxk_ml_dev *cnxk_mldev;
497 : : struct cnxk_ml_model *model;
498 : : struct cnxk_ml_qp *qp;
499 : : uint16_t model_id;
500 : : uint32_t mz_size;
501 : : uint16_t qp_id;
502 : : uint64_t i;
503 : : int ret;
504 : :
505 [ # # ]: 0 : if (dev == NULL)
506 : : return -EINVAL;
507 : :
508 : : /* Get CNXK device handle */
509 : 0 : cnxk_mldev = dev->data->dev_private;
510 : :
511 : 0 : cnxk_ml_dev_info_get(dev, &dev_info);
512 [ # # ]: 0 : if (conf->nb_models > dev_info.max_models) {
513 : 0 : plt_err("Invalid device config, nb_models > %u", dev_info.max_models);
514 : 0 : return -EINVAL;
515 : : }
516 : :
517 [ # # ]: 0 : if (conf->nb_queue_pairs > dev_info.max_queue_pairs) {
518 : 0 : plt_err("Invalid device config, nb_queue_pairs > %u", dev_info.max_queue_pairs);
519 : 0 : return -EINVAL;
520 : : }
521 : :
522 [ # # ]: 0 : if (cnxk_mldev->state == ML_CNXK_DEV_STATE_PROBED) {
523 : 0 : plt_ml_dbg("Configuring ML device, nb_queue_pairs = %u, nb_models = %u",
524 : : conf->nb_queue_pairs, conf->nb_models);
525 : :
526 : : /* Load firmware */
527 [ # # ]: 0 : if (cnxk_mldev->type == CNXK_ML_DEV_TYPE_PCI) {
528 : 0 : ret = cn10k_ml_fw_load(cnxk_mldev);
529 [ # # ]: 0 : if (ret != 0)
530 : : return ret;
531 : : }
532 [ # # ]: 0 : } else if (cnxk_mldev->state == ML_CNXK_DEV_STATE_CONFIGURED) {
533 : 0 : plt_ml_dbg("Re-configuring ML device, nb_queue_pairs = %u, nb_models = %u",
534 : : conf->nb_queue_pairs, conf->nb_models);
535 [ # # ]: 0 : } else if (cnxk_mldev->state == ML_CNXK_DEV_STATE_STARTED) {
536 : 0 : plt_err("Device can't be reconfigured in started state");
537 : 0 : return -ENOTSUP;
538 [ # # ]: 0 : } else if (cnxk_mldev->state == ML_CNXK_DEV_STATE_CLOSED) {
539 : 0 : plt_err("Device can't be reconfigured after close");
540 : 0 : return -ENOTSUP;
541 : : }
542 : :
543 : : /* Configure queue-pairs */
544 [ # # ]: 0 : if (dev->data->queue_pairs == NULL) {
545 : 0 : mz_size = sizeof(dev->data->queue_pairs[0]) * conf->nb_queue_pairs;
546 : 0 : dev->data->queue_pairs =
547 : 0 : rte_zmalloc("cnxk_mldev_queue_pairs", mz_size, RTE_CACHE_LINE_SIZE);
548 [ # # ]: 0 : if (dev->data->queue_pairs == NULL) {
549 : 0 : dev->data->nb_queue_pairs = 0;
550 : 0 : plt_err("Failed to get memory for queue_pairs, nb_queue_pairs %u",
551 : : conf->nb_queue_pairs);
552 : 0 : return -ENOMEM;
553 : : }
554 : : } else { /* Re-configure */
555 : : void **queue_pairs;
556 : :
557 : : /* Release all queue pairs as ML spec doesn't support queue_pair_destroy. */
558 [ # # ]: 0 : for (qp_id = 0; qp_id < dev->data->nb_queue_pairs; qp_id++) {
559 : 0 : qp = dev->data->queue_pairs[qp_id];
560 [ # # ]: 0 : if (qp != NULL) {
561 : 0 : ret = cnxk_ml_dev_queue_pair_release(dev, qp_id);
562 [ # # ]: 0 : if (ret < 0)
563 : 0 : return ret;
564 : : }
565 : : }
566 : :
567 : 0 : queue_pairs = dev->data->queue_pairs;
568 : : queue_pairs =
569 : 0 : rte_realloc(queue_pairs, sizeof(queue_pairs[0]) * conf->nb_queue_pairs,
570 : : RTE_CACHE_LINE_SIZE);
571 [ # # ]: 0 : if (queue_pairs == NULL) {
572 : 0 : dev->data->nb_queue_pairs = 0;
573 : 0 : plt_err("Failed to realloc queue_pairs, nb_queue_pairs = %u",
574 : : conf->nb_queue_pairs);
575 : : ret = -ENOMEM;
576 : 0 : goto error;
577 : : }
578 : :
579 : 0 : memset(queue_pairs, 0, sizeof(queue_pairs[0]) * conf->nb_queue_pairs);
580 : 0 : dev->data->queue_pairs = queue_pairs;
581 : : }
582 : 0 : dev->data->nb_queue_pairs = conf->nb_queue_pairs;
583 : :
584 : : /* Allocate ML models */
585 [ # # ]: 0 : if (dev->data->models == NULL) {
586 : 0 : mz_size = sizeof(dev->data->models[0]) * conf->nb_models;
587 : 0 : dev->data->models = rte_zmalloc("cnxk_mldev_models", mz_size, RTE_CACHE_LINE_SIZE);
588 [ # # ]: 0 : if (dev->data->models == NULL) {
589 : 0 : dev->data->nb_models = 0;
590 : 0 : plt_err("Failed to get memory for ml_models, nb_models %u",
591 : : conf->nb_models);
592 : : ret = -ENOMEM;
593 : 0 : goto error;
594 : : }
595 : : } else {
596 : : /* Re-configure */
597 : : void **models;
598 : :
599 : : /* Stop and unload all models */
600 [ # # ]: 0 : for (model_id = 0; model_id < dev->data->nb_models; model_id++) {
601 : 0 : model = dev->data->models[model_id];
602 [ # # ]: 0 : if (model != NULL) {
603 [ # # ]: 0 : if (model->state == ML_CNXK_MODEL_STATE_STARTED) {
604 [ # # ]: 0 : if (cnxk_ml_model_stop(dev, model_id) != 0)
605 : 0 : plt_err("Could not stop model %u", model_id);
606 : : }
607 [ # # ]: 0 : if (model->state == ML_CNXK_MODEL_STATE_LOADED) {
608 [ # # ]: 0 : if (cnxk_ml_model_unload(dev, model_id) != 0)
609 : 0 : plt_err("Could not unload model %u", model_id);
610 : : }
611 : 0 : dev->data->models[model_id] = NULL;
612 : : }
613 : : }
614 : :
615 : 0 : models = dev->data->models;
616 : 0 : models = rte_realloc(models, sizeof(models[0]) * conf->nb_models,
617 : : RTE_CACHE_LINE_SIZE);
618 [ # # ]: 0 : if (models == NULL) {
619 : 0 : dev->data->nb_models = 0;
620 : 0 : plt_err("Failed to realloc ml_models, nb_models = %u", conf->nb_models);
621 : : ret = -ENOMEM;
622 : 0 : goto error;
623 : : }
624 : 0 : memset(models, 0, sizeof(models[0]) * conf->nb_models);
625 : 0 : dev->data->models = models;
626 : : }
627 : 0 : dev->data->nb_models = conf->nb_models;
628 : :
629 [ # # ]: 0 : if (cnxk_mldev->type == CNXK_ML_DEV_TYPE_PCI) {
630 : 0 : ret = cn10k_ml_dev_configure(cnxk_mldev, conf);
631 [ # # ]: 0 : if (ret != 0) {
632 : 0 : plt_err("Failed to configure CN10K ML Device");
633 : 0 : goto error;
634 : : }
635 : : }
636 : :
637 : 0 : ret = mvtvm_ml_dev_configure(cnxk_mldev, conf);
638 [ # # ]: 0 : if (ret != 0)
639 : 0 : goto error;
640 : :
641 : : /* Set device capabilities */
642 [ # # ]: 0 : if (cnxk_mldev->type == CNXK_ML_DEV_TYPE_PCI)
643 : 0 : cnxk_mldev->max_nb_layers =
644 : 0 : cnxk_mldev->cn10k_mldev.fw.req->cn10k_req.jd.fw_load.cap.s.max_models;
645 : : else
646 : 0 : cnxk_mldev->max_nb_layers = ML_CNXK_MAX_MODELS;
647 : :
648 : 0 : cnxk_mldev->mldev->enqueue_burst = cnxk_ml_enqueue_burst;
649 : 0 : cnxk_mldev->mldev->dequeue_burst = cnxk_ml_dequeue_burst;
650 : 0 : cnxk_mldev->mldev->op_error_get = cnxk_ml_op_error_get;
651 : :
652 : : /* Allocate and initialize index_map */
653 [ # # ]: 0 : if (cnxk_mldev->index_map == NULL) {
654 : 0 : cnxk_mldev->index_map =
655 : 0 : rte_zmalloc("cnxk_ml_index_map",
656 : 0 : sizeof(struct cnxk_ml_index_map) * cnxk_mldev->max_nb_layers,
657 : : RTE_CACHE_LINE_SIZE);
658 [ # # ]: 0 : if (cnxk_mldev->index_map == NULL) {
659 : 0 : plt_err("Failed to get memory for index_map, nb_layers %" PRIu64,
660 : : cnxk_mldev->max_nb_layers);
661 : : ret = -ENOMEM;
662 : 0 : goto error;
663 : : }
664 : : }
665 : :
666 [ # # ]: 0 : for (i = 0; i < cnxk_mldev->max_nb_layers; i++)
667 : 0 : cnxk_mldev->index_map[i].active = false;
668 : :
669 : : /* Initialize xstats */
670 : 0 : ret = cnxk_ml_xstats_init(cnxk_mldev);
671 [ # # ]: 0 : if (ret != 0) {
672 : 0 : plt_err("Failed to initialize xstats");
673 : 0 : goto error;
674 : : }
675 : :
676 : 0 : cnxk_mldev->nb_models_loaded = 0;
677 : 0 : cnxk_mldev->nb_models_started = 0;
678 : 0 : cnxk_mldev->nb_models_stopped = 0;
679 : 0 : cnxk_mldev->nb_models_unloaded = 0;
680 : 0 : cnxk_mldev->state = ML_CNXK_DEV_STATE_CONFIGURED;
681 : :
682 : 0 : return 0;
683 : :
684 : 0 : error:
685 : 0 : rte_free(dev->data->queue_pairs);
686 : 0 : rte_free(dev->data->models);
687 : :
688 : 0 : return ret;
689 : : }
690 : :
691 : : static int
692 : 0 : cnxk_ml_dev_close(struct rte_ml_dev *dev)
693 : : {
694 : : struct cnxk_ml_dev *cnxk_mldev;
695 : : struct cnxk_ml_model *model;
696 : : struct cnxk_ml_qp *qp;
697 : : uint16_t model_id;
698 : : uint16_t qp_id;
699 : :
700 [ # # ]: 0 : if (dev == NULL)
701 : : return -EINVAL;
702 : :
703 : 0 : cnxk_mldev = dev->data->dev_private;
704 : :
705 : : /* Un-initialize xstats */
706 : : cnxk_ml_xstats_uninit(cnxk_mldev);
707 : :
708 [ # # ]: 0 : if (mvtvm_ml_dev_close(cnxk_mldev) != 0)
709 : 0 : plt_err("Failed to close MVTVM ML Device");
710 : :
711 [ # # ]: 0 : if (cnxk_mldev->type == CNXK_ML_DEV_TYPE_PCI) {
712 [ # # ]: 0 : if (cn10k_ml_dev_close(cnxk_mldev) != 0)
713 : 0 : plt_err("Failed to close CN10K ML Device");
714 : : }
715 : :
716 : 0 : rte_free(cnxk_mldev->index_map);
717 : :
718 : : /* Stop and unload all models */
719 [ # # ]: 0 : for (model_id = 0; model_id < dev->data->nb_models; model_id++) {
720 : 0 : model = dev->data->models[model_id];
721 [ # # ]: 0 : if (model != NULL) {
722 [ # # ]: 0 : if (model->state == ML_CNXK_MODEL_STATE_STARTED) {
723 [ # # ]: 0 : if (cnxk_ml_model_stop(dev, model_id) != 0)
724 : 0 : plt_err("Could not stop model %u", model_id);
725 : : }
726 [ # # ]: 0 : if (model->state == ML_CNXK_MODEL_STATE_LOADED) {
727 [ # # ]: 0 : if (cnxk_ml_model_unload(dev, model_id) != 0)
728 : 0 : plt_err("Could not unload model %u", model_id);
729 : : }
730 : 0 : dev->data->models[model_id] = NULL;
731 : : }
732 : : }
733 : :
734 : 0 : rte_free(dev->data->models);
735 : :
736 : : /* Destroy all queue pairs */
737 [ # # ]: 0 : for (qp_id = 0; qp_id < dev->data->nb_queue_pairs; qp_id++) {
738 : 0 : qp = dev->data->queue_pairs[qp_id];
739 [ # # ]: 0 : if (qp != NULL) {
740 [ # # ]: 0 : if (cnxk_ml_qp_destroy(dev, qp) != 0)
741 : 0 : plt_err("Could not destroy queue pair %u", qp_id);
742 : 0 : dev->data->queue_pairs[qp_id] = NULL;
743 : : }
744 : : }
745 : :
746 : 0 : rte_free(dev->data->queue_pairs);
747 : :
748 : 0 : cnxk_mldev->state = ML_CNXK_DEV_STATE_CLOSED;
749 : :
750 : : /* Remove PCI device */
751 : 0 : return rte_dev_remove(dev->device);
752 : : }
753 : :
754 : : static int
755 : 0 : cnxk_ml_dev_start(struct rte_ml_dev *dev)
756 : : {
757 : : struct cnxk_ml_dev *cnxk_mldev;
758 : : int ret;
759 : :
760 [ # # ]: 0 : if (dev == NULL)
761 : : return -EINVAL;
762 : :
763 : 0 : cnxk_mldev = dev->data->dev_private;
764 : :
765 [ # # ]: 0 : if (cnxk_mldev->type == CNXK_ML_DEV_TYPE_PCI) {
766 : 0 : ret = cn10k_ml_dev_start(cnxk_mldev);
767 [ # # ]: 0 : if (ret != 0) {
768 : 0 : plt_err("Failed to start CN10K ML Device");
769 : 0 : return ret;
770 : : }
771 : : }
772 : :
773 : 0 : cnxk_mldev->state = ML_CNXK_DEV_STATE_STARTED;
774 : :
775 : 0 : return 0;
776 : : }
777 : :
778 : : static int
779 : 0 : cnxk_ml_dev_stop(struct rte_ml_dev *dev)
780 : : {
781 : : struct cnxk_ml_dev *cnxk_mldev;
782 : : int ret;
783 : :
784 [ # # ]: 0 : if (dev == NULL)
785 : : return -EINVAL;
786 : :
787 : 0 : cnxk_mldev = dev->data->dev_private;
788 : :
789 [ # # ]: 0 : if (cnxk_mldev->type == CNXK_ML_DEV_TYPE_PCI) {
790 : 0 : ret = cn10k_ml_dev_stop(cnxk_mldev);
791 [ # # ]: 0 : if (ret != 0) {
792 : 0 : plt_err("Failed to stop CN10K ML Device");
793 : 0 : return ret;
794 : : }
795 : : }
796 : :
797 : 0 : cnxk_mldev->state = ML_CNXK_DEV_STATE_CONFIGURED;
798 : :
799 : 0 : return 0;
800 : : }
801 : :
802 : : static int
803 : 0 : cnxk_ml_dev_dump(struct rte_ml_dev *dev, FILE *fp)
804 : : {
805 : : struct cnxk_ml_dev *cnxk_mldev;
806 : : struct cnxk_ml_model *model;
807 : : uint16_t model_id;
808 : :
809 [ # # ]: 0 : if ((dev == NULL) || (fp == NULL))
810 : : return -EINVAL;
811 : :
812 : 0 : cnxk_mldev = dev->data->dev_private;
813 : :
814 : : /* Dump model info */
815 [ # # ]: 0 : for (model_id = 0; model_id < cnxk_mldev->mldev->data->nb_models; model_id++) {
816 : 0 : model = cnxk_mldev->mldev->data->models[model_id];
817 [ # # ]: 0 : if (model != NULL)
818 : 0 : cnxk_ml_model_dump(cnxk_mldev, model, fp);
819 : : }
820 : :
821 [ # # ]: 0 : if (cnxk_mldev->type == CNXK_ML_DEV_TYPE_PCI)
822 : 0 : return cn10k_ml_dev_dump(cnxk_mldev, fp);
823 : : else
824 : 0 : return mvtvm_ml_dev_dump(cnxk_mldev, fp);
825 : :
826 : : return 0;
827 : : }
828 : :
829 : : static int
830 : 0 : cnxk_ml_dev_selftest(struct rte_ml_dev *dev)
831 : : {
832 : : struct cnxk_ml_dev *cnxk_mldev;
833 : :
834 [ # # ]: 0 : if (dev == NULL)
835 : : return -EINVAL;
836 : :
837 : 0 : cnxk_mldev = dev->data->dev_private;
838 : :
839 [ # # ]: 0 : if (cnxk_mldev->type == CNXK_ML_DEV_TYPE_VDEV)
840 : : return -ENOTSUP;
841 : :
842 : 0 : return cn10k_ml_dev_selftest(cnxk_mldev);
843 : : }
844 : :
845 : : static int
846 : 0 : cnxk_ml_dev_queue_pair_setup(struct rte_ml_dev *dev, uint16_t queue_pair_id,
847 : : const struct rte_ml_dev_qp_conf *qp_conf, int socket_id)
848 : : {
849 : : struct rte_ml_dev_info dev_info;
850 : : struct cnxk_ml_qp *qp;
851 : : uint32_t nb_desc;
852 : :
853 [ # # ]: 0 : if (queue_pair_id >= dev->data->nb_queue_pairs) {
854 : 0 : plt_err("Queue-pair id = %u (>= max queue pairs supported, %u)", queue_pair_id,
855 : : dev->data->nb_queue_pairs);
856 : 0 : return -EINVAL;
857 : : }
858 : :
859 [ # # ]: 0 : if (dev->data->queue_pairs[queue_pair_id] != NULL)
860 : 0 : cnxk_ml_dev_queue_pair_release(dev, queue_pair_id);
861 : :
862 : 0 : cnxk_ml_dev_info_get(dev, &dev_info);
863 [ # # ]: 0 : if (qp_conf->nb_desc == 0) {
864 : 0 : plt_err("Could not setup queue pair for %u descriptors", qp_conf->nb_desc);
865 : 0 : return -EINVAL;
866 [ # # ]: 0 : } else if (qp_conf->nb_desc > dev_info.max_desc) {
867 : 0 : plt_err("Could not setup queue pair for %u descriptors (> %u)", qp_conf->nb_desc,
868 : : dev_info.max_desc);
869 : 0 : return -EINVAL;
870 : : }
871 : 0 : plt_ml_dbg("Creating queue-pair, queue_pair_id = %u, nb_desc = %u", queue_pair_id,
872 : : qp_conf->nb_desc);
873 : :
874 : : /* As the number of usable descriptors is 1 less than the queue size being created, we
875 : : * increment the size of queue by 1 than the requested size, except when the requested size
876 : : * is equal to the maximum possible size.
877 : : */
878 : : nb_desc =
879 [ # # ]: 0 : (qp_conf->nb_desc == dev_info.max_desc) ? dev_info.max_desc : qp_conf->nb_desc + 1;
880 : 0 : qp = cnxk_ml_qp_create(dev, queue_pair_id, nb_desc, socket_id);
881 [ # # ]: 0 : if (qp == NULL) {
882 : 0 : plt_err("Could not create queue pair %u", queue_pair_id);
883 : 0 : return -ENOMEM;
884 : : }
885 : 0 : dev->data->queue_pairs[queue_pair_id] = qp;
886 : :
887 : 0 : return 0;
888 : : }
889 : :
890 : : static int
891 : 0 : cnxk_ml_dev_stats_get(struct rte_ml_dev *dev, struct rte_ml_dev_stats *stats)
892 : : {
893 : : struct cnxk_ml_qp *qp;
894 : : int qp_id;
895 : :
896 [ # # ]: 0 : for (qp_id = 0; qp_id < dev->data->nb_queue_pairs; qp_id++) {
897 : 0 : qp = dev->data->queue_pairs[qp_id];
898 : 0 : stats->enqueued_count += qp->stats.enqueued_count;
899 : 0 : stats->dequeued_count += qp->stats.dequeued_count;
900 : 0 : stats->enqueue_err_count += qp->stats.enqueue_err_count;
901 : 0 : stats->dequeue_err_count += qp->stats.dequeue_err_count;
902 : : }
903 : :
904 : 0 : return 0;
905 : : }
906 : :
907 : : static void
908 : 0 : cnxk_ml_dev_stats_reset(struct rte_ml_dev *dev)
909 : : {
910 : : struct cnxk_ml_qp *qp;
911 : : int qp_id;
912 : :
913 [ # # ]: 0 : for (qp_id = 0; qp_id < dev->data->nb_queue_pairs; qp_id++) {
914 : 0 : qp = dev->data->queue_pairs[qp_id];
915 : 0 : qp->stats.enqueued_count = 0;
916 : 0 : qp->stats.dequeued_count = 0;
917 : 0 : qp->stats.enqueue_err_count = 0;
918 : 0 : qp->stats.dequeue_err_count = 0;
919 : : }
920 : 0 : }
921 : :
922 : : static int
923 : 0 : cnxk_ml_dev_xstats_names_get(struct rte_ml_dev *dev, enum rte_ml_dev_xstats_mode mode,
924 : : int32_t model_id, struct rte_ml_dev_xstats_map *xstats_map,
925 : : uint32_t size)
926 : : {
927 : : struct cnxk_ml_xstats_entry *xs;
928 : : struct cnxk_ml_dev *cnxk_mldev;
929 : : struct cnxk_ml_model *model;
930 : : uint32_t xstats_mode_count;
931 : : uint16_t layer_id;
932 : : uint32_t idx = 0;
933 : : uint32_t i;
934 : :
935 [ # # ]: 0 : if (dev == NULL)
936 : : return -EINVAL;
937 : :
938 : 0 : cnxk_mldev = dev->data->dev_private;
939 : : xstats_mode_count = 0;
940 : :
941 [ # # # ]: 0 : switch (mode) {
942 : 0 : case RTE_ML_DEV_XSTATS_DEVICE:
943 : 0 : xstats_mode_count = cnxk_mldev->xstats.count_mode_device;
944 : 0 : break;
945 : 0 : case RTE_ML_DEV_XSTATS_MODEL:
946 [ # # ]: 0 : if (model_id >= ML_CNXK_MAX_MODELS)
947 : : break;
948 : :
949 : 0 : model = cnxk_mldev->mldev->data->models[model_id];
950 [ # # ]: 0 : for (layer_id = 0; layer_id < model->nb_layers; layer_id++) {
951 [ # # ]: 0 : if (model->layer[layer_id].type == ML_CNXK_LAYER_TYPE_MRVL)
952 : 0 : xstats_mode_count +=
953 : 0 : cnxk_mldev->xstats.count_per_layer[model_id][layer_id];
954 : : }
955 : :
956 [ # # ]: 0 : if ((model->type == ML_CNXK_MODEL_TYPE_TVM) &&
957 [ # # ]: 0 : (model->subtype != ML_CNXK_MODEL_SUBTYPE_TVM_MRVL))
958 : 0 : xstats_mode_count += RTE_DIM(model_xstats);
959 : : break;
960 : : default:
961 : : return -EINVAL;
962 : : };
963 : :
964 [ # # ]: 0 : if (xstats_mode_count > size || xstats_map == NULL)
965 : 0 : return xstats_mode_count;
966 : :
967 [ # # # # ]: 0 : for (i = 0; i < cnxk_mldev->xstats.count && idx < size; i++) {
968 : 0 : xs = &cnxk_mldev->xstats.entries[i];
969 [ # # ]: 0 : if (xs->mode != mode)
970 : 0 : continue;
971 : :
972 [ # # ]: 0 : if (mode == RTE_ML_DEV_XSTATS_MODEL) {
973 [ # # ]: 0 : if (model_id != xs->obj_idx)
974 : 0 : continue;
975 : :
976 : 0 : model = cnxk_mldev->mldev->data->models[model_id];
977 [ # # ]: 0 : if ((model->type == ML_CNXK_MODEL_TYPE_GLOW ||
978 [ # # ]: 0 : model->subtype == ML_CNXK_MODEL_SUBTYPE_TVM_MRVL) &&
979 [ # # ]: 0 : xs->group == CNXK_ML_XSTATS_GROUP_MODEL)
980 : 0 : continue;
981 : :
982 [ # # ]: 0 : if (model->type == ML_CNXK_MODEL_TYPE_TVM &&
983 [ # # ]: 0 : model->layer[xs->layer_id].type == ML_CNXK_LAYER_TYPE_LLVM)
984 : 0 : continue;
985 : : }
986 : :
987 : 0 : rte_strscpy(xstats_map[idx].name, xs->map.name, RTE_ML_STR_MAX);
988 : 0 : xstats_map[idx].id = xs->map.id;
989 : 0 : idx++;
990 : : }
991 : :
992 : 0 : return idx;
993 : : }
994 : :
995 : : static int
996 : 0 : cnxk_ml_dev_xstats_by_name_get(struct rte_ml_dev *dev, const char *name, uint16_t *stat_id,
997 : : uint64_t *value)
998 : : {
999 : : struct cnxk_ml_xstats_entry *xs;
1000 : : struct cnxk_ml_dev *cnxk_mldev;
1001 : : cnxk_ml_xstats_fn fn;
1002 : : uint32_t i;
1003 : :
1004 [ # # ]: 0 : if (dev == NULL)
1005 : : return -EINVAL;
1006 : :
1007 : 0 : cnxk_mldev = dev->data->dev_private;
1008 : :
1009 [ # # ]: 0 : for (i = 0; i < cnxk_mldev->xstats.count; i++) {
1010 : 0 : xs = &cnxk_mldev->xstats.entries[i];
1011 [ # # ]: 0 : if (strncmp(xs->map.name, name, RTE_ML_STR_MAX) == 0) {
1012 [ # # ]: 0 : if (stat_id != NULL)
1013 : 0 : *stat_id = xs->map.id;
1014 : :
1015 [ # # # ]: 0 : switch (xs->fn_id) {
1016 : : case CNXK_ML_XSTATS_FN_DEVICE:
1017 : : fn = cnxk_ml_dev_xstat_get;
1018 : : break;
1019 : 0 : case CNXK_ML_XSTATS_FN_MODEL:
1020 : : fn = cnxk_ml_model_xstat_get;
1021 : 0 : break;
1022 : 0 : default:
1023 : 0 : plt_err("Unexpected xstat fn_id = %d", xs->fn_id);
1024 : 0 : return -EINVAL;
1025 : : }
1026 : :
1027 : 0 : *value = fn(cnxk_mldev, xs->obj_idx, xs->layer_id, xs->type) -
1028 : 0 : xs->reset_value;
1029 : :
1030 : 0 : return 0;
1031 : : }
1032 : : }
1033 : :
1034 [ # # ]: 0 : if (stat_id != NULL)
1035 : 0 : *stat_id = (uint16_t)-1;
1036 : :
1037 : : return -EINVAL;
1038 : : }
1039 : :
1040 : : static int
1041 : 0 : cnxk_ml_dev_xstats_get(struct rte_ml_dev *dev, enum rte_ml_dev_xstats_mode mode, int32_t model_id,
1042 : : const uint16_t stat_ids[], uint64_t values[], uint16_t nb_ids)
1043 : : {
1044 : : struct cnxk_ml_xstats_entry *xs;
1045 : : struct cnxk_ml_dev *cnxk_mldev;
1046 : : struct cnxk_ml_model *model;
1047 : : uint32_t xstats_mode_count;
1048 : : cnxk_ml_xstats_fn fn;
1049 : : uint16_t layer_id;
1050 : : uint64_t val;
1051 : : uint32_t idx;
1052 : : uint32_t i;
1053 : :
1054 [ # # ]: 0 : if (dev == NULL)
1055 : : return -EINVAL;
1056 : :
1057 : 0 : cnxk_mldev = dev->data->dev_private;
1058 : : xstats_mode_count = 0;
1059 : :
1060 [ # # # ]: 0 : switch (mode) {
1061 : 0 : case RTE_ML_DEV_XSTATS_DEVICE:
1062 : 0 : xstats_mode_count = cnxk_mldev->xstats.count_mode_device;
1063 : 0 : break;
1064 : 0 : case RTE_ML_DEV_XSTATS_MODEL:
1065 [ # # ]: 0 : if (model_id >= ML_CNXK_MAX_MODELS)
1066 : : return -EINVAL;
1067 : :
1068 : 0 : model = cnxk_mldev->mldev->data->models[model_id];
1069 [ # # ]: 0 : for (layer_id = 0; layer_id < model->nb_layers; layer_id++)
1070 : 0 : xstats_mode_count += cnxk_mldev->xstats.count_per_layer[model_id][layer_id];
1071 : :
1072 [ # # ]: 0 : if ((model->type == ML_CNXK_MODEL_TYPE_TVM) &&
1073 [ # # ]: 0 : (model->subtype != ML_CNXK_MODEL_SUBTYPE_TVM_MRVL))
1074 : 0 : xstats_mode_count += RTE_DIM(model_xstats);
1075 : : break;
1076 : : default:
1077 : : return -EINVAL;
1078 : : };
1079 : :
1080 : : idx = 0;
1081 [ # # # # ]: 0 : for (i = 0; i < nb_ids && idx < xstats_mode_count; i++) {
1082 : 0 : xs = &cnxk_mldev->xstats.entries[stat_ids[i]];
1083 [ # # # # ]: 0 : if (stat_ids[i] > cnxk_mldev->xstats.count || xs->mode != mode)
1084 : 0 : continue;
1085 : :
1086 [ # # ]: 0 : if (mode == RTE_ML_DEV_XSTATS_MODEL) {
1087 [ # # ]: 0 : if (model_id != xs->obj_idx)
1088 : 0 : continue;
1089 : :
1090 : 0 : model = cnxk_mldev->mldev->data->models[xs->obj_idx];
1091 [ # # ]: 0 : if ((model->type == ML_CNXK_MODEL_TYPE_GLOW ||
1092 [ # # ]: 0 : model->subtype == ML_CNXK_MODEL_SUBTYPE_TVM_MRVL) &&
1093 [ # # ]: 0 : xs->group == CNXK_ML_XSTATS_GROUP_MODEL)
1094 : 0 : continue;
1095 : :
1096 [ # # # # ]: 0 : if (xs->layer_id == -1 && xs->group == CNXK_ML_XSTATS_GROUP_LAYER)
1097 : 0 : continue;
1098 : : }
1099 : :
1100 [ # # # ]: 0 : switch (xs->fn_id) {
1101 : : case CNXK_ML_XSTATS_FN_DEVICE:
1102 : : fn = cnxk_ml_dev_xstat_get;
1103 : : break;
1104 : 0 : case CNXK_ML_XSTATS_FN_MODEL:
1105 : : fn = cnxk_ml_model_xstat_get;
1106 : 0 : break;
1107 : 0 : default:
1108 : 0 : plt_err("Unexpected xstat fn_id = %d", xs->fn_id);
1109 : 0 : return -EINVAL;
1110 : : }
1111 : :
1112 : 0 : val = fn(cnxk_mldev, xs->obj_idx, xs->layer_id, xs->type);
1113 [ # # ]: 0 : if (values)
1114 : 0 : values[idx] = val;
1115 : :
1116 : 0 : idx++;
1117 : : }
1118 : :
1119 : 0 : return idx;
1120 : : }
1121 : :
1122 : : static int
1123 : 0 : cnxk_ml_dev_xstats_reset(struct rte_ml_dev *dev, enum rte_ml_dev_xstats_mode mode, int32_t model_id,
1124 : : const uint16_t stat_ids[], uint16_t nb_ids)
1125 : : {
1126 : : struct cnxk_ml_dev *cnxk_mldev;
1127 : :
1128 [ # # ]: 0 : if (dev == NULL)
1129 : : return -EINVAL;
1130 : :
1131 : 0 : cnxk_mldev = dev->data->dev_private;
1132 : :
1133 [ # # # ]: 0 : switch (mode) {
1134 : 0 : case RTE_ML_DEV_XSTATS_DEVICE:
1135 : 0 : return cnxk_ml_device_xstats_reset(cnxk_mldev, stat_ids, nb_ids);
1136 : 0 : case RTE_ML_DEV_XSTATS_MODEL:
1137 : 0 : return cnxk_ml_model_xstats_reset(cnxk_mldev, model_id, stat_ids, nb_ids);
1138 : : };
1139 : :
1140 : : return 0;
1141 : : }
1142 : :
1143 : : static int
1144 : 0 : cnxk_ml_model_load(struct rte_ml_dev *dev, struct rte_ml_model_params *params, uint16_t *model_id)
1145 : : {
1146 : : struct rte_ml_dev_info dev_info;
1147 : : struct cnxk_ml_dev *cnxk_mldev;
1148 : : enum cnxk_ml_model_type type;
1149 : : struct cnxk_ml_model *model;
1150 : :
1151 : : char str[RTE_MEMZONE_NAMESIZE];
1152 : : const struct plt_memzone *mz;
1153 : : uint16_t max_scratch_pages;
1154 : : struct cn10k_ml_ocm *ocm;
1155 : : uint64_t model_info_size;
1156 : : uint16_t total_wb_pages;
1157 : : uint16_t lcl_model_id;
1158 : : uint16_t layer_id;
1159 : : uint64_t mz_size;
1160 : : bool found;
1161 : : int ret;
1162 : :
1163 [ # # ]: 0 : if (dev == NULL)
1164 : : return -EINVAL;
1165 : :
1166 : 0 : cnxk_mldev = dev->data->dev_private;
1167 : :
1168 : 0 : type = cnxk_ml_model_get_type(params);
1169 [ # # ]: 0 : if (type == ML_CNXK_MODEL_TYPE_INVALID) {
1170 : 0 : plt_err("Invalid / unsupported model type");
1171 : 0 : return -EINVAL;
1172 : : }
1173 : :
1174 [ # # # # ]: 0 : if (cnxk_mldev->type == CNXK_ML_DEV_TYPE_VDEV && type != ML_CNXK_MODEL_TYPE_TVM) {
1175 : 0 : plt_err("Unsupported model type");
1176 : 0 : return -ENOTSUP;
1177 : : }
1178 : :
1179 : : /* Find model ID */
1180 : : found = false;
1181 [ # # ]: 0 : for (lcl_model_id = 0; lcl_model_id < dev->data->nb_models; lcl_model_id++) {
1182 [ # # ]: 0 : if (dev->data->models[lcl_model_id] == NULL) {
1183 : : found = true;
1184 : : break;
1185 : : }
1186 : : }
1187 : :
1188 [ # # ]: 0 : if (!found) {
1189 : 0 : plt_err("No slots available to load new model");
1190 : 0 : return -ENOMEM;
1191 : : }
1192 : :
1193 : : /* Compute memzone size */
1194 : 0 : cnxk_ml_dev_info_get(dev, &dev_info);
1195 : 0 : mz_size = PLT_ALIGN_CEIL(sizeof(struct cnxk_ml_model), dev_info.align_size);
1196 : : model_info_size = sizeof(struct rte_ml_model_info) +
1197 : : ML_CNXK_MODEL_MAX_INPUT_OUTPUT * sizeof(struct rte_ml_io_info) +
1198 : : ML_CNXK_MODEL_MAX_INPUT_OUTPUT * sizeof(struct rte_ml_io_info);
1199 : 0 : model_info_size = PLT_ALIGN_CEIL(model_info_size, dev_info.align_size);
1200 : 0 : mz_size += model_info_size;
1201 : :
1202 : : /* Allocate memzone for model object */
1203 : 0 : snprintf(str, RTE_MEMZONE_NAMESIZE, "%s_%u", CNXK_ML_MODEL_MEMZONE_NAME, lcl_model_id);
1204 : 0 : mz = plt_memzone_reserve_aligned(str, mz_size, 0, dev_info.align_size);
1205 [ # # ]: 0 : if (!mz) {
1206 : 0 : plt_err("Failed to allocate memory for cnxk_ml_model: %s", str);
1207 : 0 : return -ENOMEM;
1208 : : }
1209 : :
1210 : 0 : model = mz->addr;
1211 : 0 : model->cnxk_mldev = cnxk_mldev;
1212 : 0 : model->type = type;
1213 : 0 : model->model_id = lcl_model_id;
1214 : 0 : model->info = PLT_PTR_ADD(
1215 : : model, PLT_ALIGN_CEIL(sizeof(struct cnxk_ml_model), dev_info.align_size));
1216 : 0 : dev->data->models[lcl_model_id] = model;
1217 : :
1218 [ # # ]: 0 : if (type == ML_CNXK_MODEL_TYPE_GLOW)
1219 : 0 : ret = cn10k_ml_model_load(cnxk_mldev, params, model);
1220 : : else
1221 : 0 : ret = mvtvm_ml_model_load(cnxk_mldev, params, model);
1222 [ # # ]: 0 : if (ret != 0)
1223 : 0 : goto error;
1224 : :
1225 : : max_scratch_pages = 0;
1226 : : total_wb_pages = 0;
1227 : : layer_id = 0;
1228 : :
1229 : : ocm = &cnxk_mldev->cn10k_mldev.ocm;
1230 : :
1231 [ # # ]: 0 : if (model->type == ML_CNXK_MODEL_TYPE_GLOW) {
1232 : 0 : total_wb_pages = total_wb_pages + model->layer[layer_id].glow.ocm_map.wb_pages;
1233 : 0 : max_scratch_pages = PLT_MAX(max_scratch_pages,
1234 : : model->layer[layer_id].glow.ocm_map.scratch_pages);
1235 : : #ifdef RTE_MLDEV_CNXK_ENABLE_MVTVM
1236 : : } else {
1237 : : for (layer_id = 0; layer_id < model->mvtvm.metadata.model.nb_layers; layer_id++) {
1238 : : if (model->layer[layer_id].type == ML_CNXK_LAYER_TYPE_MRVL) {
1239 : : total_wb_pages = total_wb_pages +
1240 : : model->layer[layer_id].glow.ocm_map.wb_pages;
1241 : : max_scratch_pages =
1242 : : PLT_MAX(max_scratch_pages,
1243 : : model->layer[layer_id].glow.ocm_map.scratch_pages);
1244 : : }
1245 : : }
1246 : : #endif
1247 : : }
1248 : :
1249 [ # # ]: 0 : if ((total_wb_pages + max_scratch_pages) > ocm->num_pages) {
1250 : 0 : plt_err("model_id = %u: total_wb_pages (%u) + scratch_pages (%u) > %u",
1251 : : lcl_model_id, total_wb_pages, max_scratch_pages, ocm->num_pages);
1252 : :
1253 [ # # ]: 0 : if (model->type == ML_CNXK_MODEL_TYPE_GLOW) {
1254 : 0 : plt_ml_dbg("layer_id = %u: wb_pages = %u, scratch_pages = %u", layer_id,
1255 : : model->layer[layer_id].glow.ocm_map.wb_pages,
1256 : : model->layer[layer_id].glow.ocm_map.scratch_pages);
1257 : : #ifdef RTE_MLDEV_CNXK_ENABLE_MVTVM
1258 : : } else {
1259 : : for (layer_id = 0; layer_id < model->mvtvm.metadata.model.nb_layers;
1260 : : layer_id++) {
1261 : : if (model->layer[layer_id].type == ML_CNXK_LAYER_TYPE_MRVL) {
1262 : : plt_ml_dbg(
1263 : : "layer_id = %u: wb_pages = %u, scratch_pages = %u",
1264 : : layer_id,
1265 : : model->layer[layer_id].glow.ocm_map.wb_pages,
1266 : : model->layer[layer_id].glow.ocm_map.scratch_pages);
1267 : : }
1268 : : }
1269 : : #endif
1270 : : }
1271 : :
1272 [ # # ]: 0 : if (model->type == ML_CNXK_MODEL_TYPE_GLOW)
1273 : 0 : cn10k_ml_model_unload(cnxk_mldev, model);
1274 : : #ifdef RTE_MLDEV_CNXK_ENABLE_MVTVM
1275 : : else {
1276 : : mvtvm_ml_model_unload(cnxk_mldev, model);
1277 : : return -ENOMEM;
1278 : : }
1279 : : #endif
1280 : : }
1281 : : plt_spinlock_init(&model->lock);
1282 : 0 : model->state = ML_CNXK_MODEL_STATE_LOADED;
1283 : 0 : cnxk_mldev->nb_models_loaded++;
1284 : :
1285 : 0 : *model_id = lcl_model_id;
1286 : :
1287 : 0 : return 0;
1288 : :
1289 : : error:
1290 : 0 : rte_memzone_free(mz);
1291 : :
1292 : 0 : return ret;
1293 : : }
1294 : :
1295 : : int
1296 : 0 : cnxk_ml_model_unload(struct rte_ml_dev *dev, uint16_t model_id)
1297 : : {
1298 : : struct cnxk_ml_dev *cnxk_mldev;
1299 : : struct cnxk_ml_model *model;
1300 : :
1301 : : char str[RTE_MEMZONE_NAMESIZE];
1302 : : int ret = 0;
1303 : :
1304 [ # # ]: 0 : if (dev == NULL)
1305 : : return -EINVAL;
1306 : :
1307 : 0 : cnxk_mldev = dev->data->dev_private;
1308 : :
1309 : 0 : model = dev->data->models[model_id];
1310 [ # # ]: 0 : if (model == NULL) {
1311 : 0 : plt_err("Invalid model_id = %u", model_id);
1312 : 0 : return -EINVAL;
1313 : : }
1314 : :
1315 [ # # ]: 0 : if (model->state != ML_CNXK_MODEL_STATE_LOADED) {
1316 : 0 : plt_err("Cannot unload. Model in use.");
1317 : 0 : return -EBUSY;
1318 : : }
1319 : :
1320 [ # # ]: 0 : if (model->type == ML_CNXK_MODEL_TYPE_GLOW)
1321 : 0 : ret = cn10k_ml_model_unload(cnxk_mldev, model);
1322 : : else
1323 : 0 : ret = mvtvm_ml_model_unload(cnxk_mldev, model);
1324 [ # # ]: 0 : if (ret != 0)
1325 : : return ret;
1326 : :
1327 : 0 : dev->data->models[model_id] = NULL;
1328 : 0 : cnxk_mldev->nb_models_unloaded++;
1329 : :
1330 : 0 : snprintf(str, RTE_MEMZONE_NAMESIZE, "%s_%u", CNXK_ML_MODEL_MEMZONE_NAME, model_id);
1331 : 0 : return plt_memzone_free(plt_memzone_lookup(str));
1332 : : }
1333 : :
1334 : : static int
1335 : 0 : cnxk_ml_model_start(struct rte_ml_dev *dev, uint16_t model_id)
1336 : : {
1337 : : struct cnxk_ml_dev *cnxk_mldev;
1338 : : struct cnxk_ml_model *model;
1339 : :
1340 [ # # ]: 0 : if (dev == NULL)
1341 : : return -EINVAL;
1342 : :
1343 : 0 : cnxk_mldev = dev->data->dev_private;
1344 : :
1345 : 0 : model = dev->data->models[model_id];
1346 [ # # ]: 0 : if (model == NULL) {
1347 : 0 : plt_err("Invalid model_id = %u", model_id);
1348 : 0 : return -EINVAL;
1349 : : }
1350 : :
1351 [ # # ]: 0 : if (model->type == ML_CNXK_MODEL_TYPE_GLOW)
1352 : 0 : return cn10k_ml_model_start(cnxk_mldev, model);
1353 : : else
1354 : 0 : return mvtvm_ml_model_start(cnxk_mldev, model);
1355 : :
1356 : : return 0;
1357 : : }
1358 : :
1359 : : int
1360 : 0 : cnxk_ml_model_stop(struct rte_ml_dev *dev, uint16_t model_id)
1361 : : {
1362 : : struct cnxk_ml_dev *cnxk_mldev;
1363 : : struct cnxk_ml_model *model;
1364 : :
1365 [ # # ]: 0 : if (dev == NULL)
1366 : : return -EINVAL;
1367 : :
1368 : 0 : cnxk_mldev = dev->data->dev_private;
1369 : :
1370 : 0 : model = dev->data->models[model_id];
1371 [ # # ]: 0 : if (model == NULL) {
1372 : 0 : plt_err("Invalid model_id = %u", model_id);
1373 : 0 : return -EINVAL;
1374 : : }
1375 : :
1376 [ # # ]: 0 : if (model->type == ML_CNXK_MODEL_TYPE_GLOW)
1377 : 0 : return cn10k_ml_model_stop(cnxk_mldev, model);
1378 : : else
1379 : 0 : return mvtvm_ml_model_stop(cnxk_mldev, model);
1380 : :
1381 : : return 0;
1382 : : }
1383 : :
1384 : : static int
1385 : 0 : cnxk_ml_model_info_get(struct rte_ml_dev *dev, uint16_t model_id,
1386 : : struct rte_ml_model_info *model_info)
1387 : : {
1388 : : struct rte_ml_model_info *info;
1389 : : struct cnxk_ml_model *model;
1390 : :
1391 [ # # ]: 0 : if ((dev == NULL) || (model_info == NULL))
1392 : : return -EINVAL;
1393 : :
1394 : 0 : model = dev->data->models[model_id];
1395 [ # # ]: 0 : if (model == NULL) {
1396 : 0 : plt_err("Invalid model_id = %u", model_id);
1397 : 0 : return -EINVAL;
1398 : : }
1399 : :
1400 [ # # ]: 0 : info = (struct rte_ml_model_info *)model->info;
1401 : : rte_memcpy(model_info, info, sizeof(struct rte_ml_model_info));
1402 : 0 : model_info->input_info = info->input_info;
1403 : 0 : model_info->output_info = info->output_info;
1404 : :
1405 : 0 : return 0;
1406 : : }
1407 : :
1408 : : static int
1409 : 0 : cnxk_ml_model_params_update(struct rte_ml_dev *dev, uint16_t model_id, void *buffer)
1410 : : {
1411 : : struct cnxk_ml_dev *cnxk_mldev;
1412 : : struct cnxk_ml_model *model;
1413 : :
1414 [ # # ]: 0 : if ((dev == NULL) || (buffer == NULL))
1415 : : return -EINVAL;
1416 : :
1417 : 0 : cnxk_mldev = dev->data->dev_private;
1418 [ # # ]: 0 : if (cnxk_mldev->type == CNXK_ML_DEV_TYPE_VDEV)
1419 : : return -ENOTSUP;
1420 : :
1421 : 0 : model = dev->data->models[model_id];
1422 [ # # ]: 0 : if (model == NULL) {
1423 : 0 : plt_err("Invalid model_id = %u", model_id);
1424 : 0 : return -EINVAL;
1425 : : }
1426 : :
1427 : 0 : return cn10k_ml_model_params_update(cnxk_mldev, model, buffer);
1428 : : }
1429 : :
1430 : : static int
1431 : 0 : cnxk_ml_io_quantize(struct rte_ml_dev *dev, uint16_t model_id, struct rte_ml_buff_seg **dbuffer,
1432 : : struct rte_ml_buff_seg **qbuffer)
1433 : : {
1434 : : struct cnxk_ml_io_info *info = NULL;
1435 : : struct cnxk_ml_model *model;
1436 : : uint8_t *lcl_dbuffer;
1437 : : uint8_t *lcl_qbuffer;
1438 : : uint64_t d_offset;
1439 : : uint64_t q_offset;
1440 : : uint32_t i;
1441 : : int ret;
1442 : :
1443 [ # # # # ]: 0 : if ((dev == NULL) || (dbuffer == NULL) || (qbuffer == NULL))
1444 : : return -EINVAL;
1445 : :
1446 : 0 : model = dev->data->models[model_id];
1447 [ # # ]: 0 : if (model == NULL) {
1448 : 0 : plt_err("Invalid model_id = %u", model_id);
1449 : 0 : return -EINVAL;
1450 : : }
1451 : :
1452 [ # # ]: 0 : if (model->type == ML_CNXK_MODEL_TYPE_GLOW)
1453 : 0 : info = cn10k_ml_model_io_info_get(model, 0);
1454 : : else
1455 : 0 : info = mvtvm_ml_model_io_info_get(model, 0);
1456 : :
1457 [ # # ]: 0 : if (info == NULL)
1458 : : return -EINVAL;
1459 : :
1460 : : d_offset = 0;
1461 : : q_offset = 0;
1462 [ # # ]: 0 : for (i = 0; i < info->nb_inputs; i++) {
1463 [ # # ]: 0 : if (model->type == ML_CNXK_MODEL_TYPE_TVM &&
1464 [ # # ]: 0 : model->subtype != ML_CNXK_MODEL_SUBTYPE_TVM_MRVL) {
1465 : 0 : lcl_dbuffer = dbuffer[i]->addr;
1466 : 0 : lcl_qbuffer = qbuffer[i]->addr;
1467 : : } else {
1468 : 0 : lcl_dbuffer = RTE_PTR_ADD(dbuffer[0]->addr, d_offset);
1469 : 0 : lcl_qbuffer = RTE_PTR_ADD(qbuffer[0]->addr, q_offset);
1470 : : }
1471 : :
1472 : 0 : ret = cnxk_ml_io_quantize_single(&info->input[i], lcl_dbuffer, lcl_qbuffer);
1473 [ # # ]: 0 : if (ret < 0)
1474 : 0 : return ret;
1475 : :
1476 [ # # ]: 0 : if ((model->type == ML_CNXK_MODEL_TYPE_GLOW) ||
1477 [ # # ]: 0 : (model->subtype == ML_CNXK_MODEL_SUBTYPE_TVM_MRVL)) {
1478 : 0 : d_offset += info->input[i].sz_d;
1479 : 0 : q_offset += info->input[i].sz_q;
1480 : : }
1481 : : }
1482 : :
1483 : : return 0;
1484 : : }
1485 : :
1486 : : static int
1487 : 0 : cnxk_ml_io_dequantize(struct rte_ml_dev *dev, uint16_t model_id, struct rte_ml_buff_seg **qbuffer,
1488 : : struct rte_ml_buff_seg **dbuffer)
1489 : : {
1490 : : struct cnxk_ml_io_info *info = NULL;
1491 : : struct cnxk_ml_model *model;
1492 : : uint8_t *lcl_qbuffer;
1493 : : uint8_t *lcl_dbuffer;
1494 : : uint64_t q_offset;
1495 : : uint64_t d_offset;
1496 : : uint32_t i;
1497 : : int ret;
1498 : :
1499 [ # # # # ]: 0 : if ((dev == NULL) || (qbuffer == NULL) || (dbuffer == NULL))
1500 : : return -EINVAL;
1501 : :
1502 : 0 : model = dev->data->models[model_id];
1503 [ # # ]: 0 : if (model == NULL) {
1504 : 0 : plt_err("Invalid model_id = %u", model_id);
1505 : 0 : return -EINVAL;
1506 : : }
1507 : :
1508 [ # # ]: 0 : if (model->type == ML_CNXK_MODEL_TYPE_GLOW)
1509 : 0 : info = cn10k_ml_model_io_info_get(model, model->nb_layers - 1);
1510 : : else
1511 : 0 : info = mvtvm_ml_model_io_info_get(model, model->nb_layers - 1);
1512 : :
1513 [ # # ]: 0 : if (info == NULL)
1514 : : return -EINVAL;
1515 : :
1516 : : q_offset = 0;
1517 : : d_offset = 0;
1518 [ # # ]: 0 : for (i = 0; i < info->nb_outputs; i++) {
1519 [ # # ]: 0 : if (model->type == ML_CNXK_MODEL_TYPE_TVM &&
1520 [ # # ]: 0 : model->subtype != ML_CNXK_MODEL_SUBTYPE_TVM_MRVL) {
1521 : 0 : lcl_qbuffer = qbuffer[i]->addr;
1522 : 0 : lcl_dbuffer = dbuffer[i]->addr;
1523 : : } else {
1524 : 0 : lcl_qbuffer = RTE_PTR_ADD(qbuffer[0]->addr, q_offset);
1525 : 0 : lcl_dbuffer = RTE_PTR_ADD(dbuffer[0]->addr, d_offset);
1526 : : }
1527 : :
1528 : 0 : ret = cnxk_ml_io_dequantize_single(&info->output[i], lcl_qbuffer, lcl_dbuffer);
1529 [ # # ]: 0 : if (ret < 0)
1530 : 0 : return ret;
1531 : :
1532 [ # # ]: 0 : if ((model->type == ML_CNXK_MODEL_TYPE_GLOW) ||
1533 [ # # ]: 0 : (model->subtype == ML_CNXK_MODEL_SUBTYPE_TVM_MRVL)) {
1534 : 0 : q_offset += info->output[i].sz_q;
1535 : 0 : d_offset += info->output[i].sz_d;
1536 : : }
1537 : : }
1538 : :
1539 : : return 0;
1540 : : }
1541 : :
1542 : : static __rte_always_inline void
1543 : : queue_index_advance(uint64_t *index, uint64_t nb_desc)
1544 : : {
1545 : 0 : *index = (*index + 1) % nb_desc;
1546 : : }
1547 : :
1548 : : static __rte_always_inline uint64_t
1549 : : queue_pending_count(uint64_t head, uint64_t tail, uint64_t nb_desc)
1550 : : {
1551 : 0 : return (nb_desc + head - tail) % nb_desc;
1552 : : }
1553 : :
1554 : : static __rte_always_inline uint64_t
1555 : : queue_free_count(uint64_t head, uint64_t tail, uint64_t nb_desc)
1556 : : {
1557 : 0 : return nb_desc - queue_pending_count(head, tail, nb_desc) - 1;
1558 : : }
1559 : :
1560 : : __rte_hot uint16_t
1561 : 0 : cnxk_ml_enqueue_burst(struct rte_ml_dev *dev, uint16_t qp_id, struct rte_ml_op **ops,
1562 : : uint16_t nb_ops)
1563 : : {
1564 : : struct cnxk_ml_dev *cnxk_mldev;
1565 : : struct cnxk_ml_model *model;
1566 : : struct cnxk_ml_queue *queue;
1567 : : struct cnxk_ml_qp *qp;
1568 : : struct rte_ml_op *op;
1569 : :
1570 : : uint16_t layer_id = 0;
1571 : : uint16_t count;
1572 : : uint64_t head;
1573 : :
1574 : 0 : cnxk_mldev = dev->data->dev_private;
1575 : 0 : qp = dev->data->queue_pairs[qp_id];
1576 : : queue = &qp->queue;
1577 : :
1578 : 0 : head = queue->head;
1579 : 0 : nb_ops = PLT_MIN(nb_ops, queue_free_count(head, queue->tail, qp->nb_desc));
1580 : : count = 0;
1581 : :
1582 [ # # ]: 0 : if (unlikely(nb_ops == 0))
1583 : : return 0;
1584 : :
1585 : 0 : enqueue_req:
1586 : 0 : op = ops[count];
1587 : 0 : model = cnxk_mldev->mldev->data->models[op->model_id];
1588 : :
1589 [ # # ]: 0 : if (unlikely(!model->enqueue_single(cnxk_mldev, op, layer_id, qp, head)))
1590 : 0 : goto jcmdq_full;
1591 : :
1592 : 0 : queue_index_advance(&head, qp->nb_desc);
1593 : 0 : count++;
1594 : :
1595 [ # # ]: 0 : if (count < nb_ops)
1596 : 0 : goto enqueue_req;
1597 : :
1598 : 0 : jcmdq_full:
1599 : 0 : queue->head = head;
1600 : 0 : qp->stats.enqueued_count += count;
1601 : : rte_wmb();
1602 : :
1603 : 0 : return count;
1604 : : }
1605 : :
1606 : : __rte_hot uint16_t
1607 : 0 : cnxk_ml_dequeue_burst(struct rte_ml_dev *dev, uint16_t qp_id, struct rte_ml_op **ops,
1608 : : uint16_t nb_ops)
1609 : : {
1610 : : struct cnxk_ml_dev *cnxk_mldev;
1611 : : struct cnxk_ml_queue *queue;
1612 : : struct cnxk_ml_model *model;
1613 : : struct cnxk_ml_req *req;
1614 : : struct cnxk_ml_qp *qp;
1615 : :
1616 : : uint64_t status;
1617 : : uint16_t count;
1618 : : uint64_t tail;
1619 : :
1620 : 0 : cnxk_mldev = dev->data->dev_private;
1621 : 0 : qp = dev->data->queue_pairs[qp_id];
1622 : : queue = &qp->queue;
1623 : :
1624 : 0 : tail = queue->tail;
1625 : 0 : nb_ops = PLT_MIN(nb_ops, queue_pending_count(queue->head, tail, qp->nb_desc));
1626 : : count = 0;
1627 : :
1628 [ # # ]: 0 : if (unlikely(nb_ops == 0))
1629 : 0 : goto empty_or_active;
1630 : :
1631 : 0 : dequeue_req:
1632 : :
1633 : 0 : req = &queue->reqs[tail];
1634 : 0 : model = cnxk_mldev->mldev->data->models[req->op->model_id];
1635 : :
1636 : 0 : status = cnxk_ml_get_poll_ptr(req);
1637 [ # # ]: 0 : if (unlikely(status != ML_CNXK_POLL_JOB_FINISH)) {
1638 [ # # ]: 0 : if (plt_tsc_cycles() < req->timeout)
1639 : 0 : goto empty_or_active;
1640 : : else /* Timeout, set indication of driver error */
1641 : 0 : model->set_error_code(req, ML_CN10K_ETYPE_DRIVER, 0);
1642 : : }
1643 : :
1644 : 0 : model->result_update(cnxk_mldev, qp->id, req);
1645 : :
1646 : 0 : ops[count] = req->op;
1647 : 0 : queue_index_advance(&tail, qp->nb_desc);
1648 : 0 : count++;
1649 : :
1650 [ # # ]: 0 : if (count < nb_ops)
1651 : 0 : goto dequeue_req;
1652 : :
1653 : 0 : empty_or_active:
1654 : 0 : queue->tail = tail;
1655 : :
1656 : 0 : return count;
1657 : : }
1658 : :
1659 : : __rte_hot int
1660 : 0 : cnxk_ml_op_error_get(struct rte_ml_dev *dev, struct rte_ml_op *op, struct rte_ml_op_error *error)
1661 : : {
1662 : : struct cnxk_ml_dev *cnxk_mldev;
1663 : : struct cnxk_ml_model *model;
1664 : :
1665 : 0 : cnxk_mldev = dev->data->dev_private;
1666 : 0 : model = cnxk_mldev->mldev->data->models[op->model_id];
1667 : :
1668 : 0 : return model->op_error_get(cnxk_mldev, op, error);
1669 : : }
1670 : :
1671 : : struct rte_ml_dev_ops cnxk_ml_ops = {
1672 : : /* Device control ops */
1673 : : .dev_info_get = cnxk_ml_dev_info_get,
1674 : : .dev_configure = cnxk_ml_dev_configure,
1675 : : .dev_close = cnxk_ml_dev_close,
1676 : : .dev_start = cnxk_ml_dev_start,
1677 : : .dev_stop = cnxk_ml_dev_stop,
1678 : : .dev_dump = cnxk_ml_dev_dump,
1679 : : .dev_selftest = cnxk_ml_dev_selftest,
1680 : :
1681 : : /* Queue-pair handling ops */
1682 : : .dev_queue_pair_setup = cnxk_ml_dev_queue_pair_setup,
1683 : : .dev_queue_pair_release = cnxk_ml_dev_queue_pair_release,
1684 : :
1685 : : /* Stats ops */
1686 : : .dev_stats_get = cnxk_ml_dev_stats_get,
1687 : : .dev_stats_reset = cnxk_ml_dev_stats_reset,
1688 : : .dev_xstats_names_get = cnxk_ml_dev_xstats_names_get,
1689 : : .dev_xstats_by_name_get = cnxk_ml_dev_xstats_by_name_get,
1690 : : .dev_xstats_get = cnxk_ml_dev_xstats_get,
1691 : : .dev_xstats_reset = cnxk_ml_dev_xstats_reset,
1692 : :
1693 : : /* Model ops */
1694 : : .model_load = cnxk_ml_model_load,
1695 : : .model_unload = cnxk_ml_model_unload,
1696 : : .model_start = cnxk_ml_model_start,
1697 : : .model_stop = cnxk_ml_model_stop,
1698 : : .model_info_get = cnxk_ml_model_info_get,
1699 : : .model_params_update = cnxk_ml_model_params_update,
1700 : :
1701 : : /* I/O ops */
1702 : : .io_quantize = cnxk_ml_io_quantize,
1703 : : .io_dequantize = cnxk_ml_io_dequantize,
1704 : : };
|