Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright (c) 2022 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_model.h"
12 : : #include "cnxk_ml_ops.h"
13 : : #include "cnxk_ml_xstats.h"
14 : :
15 : : /* ML model macros */
16 : : #define CN10K_ML_MODEL_MEMZONE_NAME "ml_cn10k_model_mz"
17 : :
18 : : /* ML layer macros */
19 : : #define CN10K_ML_LAYER_MEMZONE_NAME "ml_cn10k_layer_mz"
20 : :
21 : : /* ML Job descriptor flags */
22 : : #define ML_FLAGS_POLL_COMPL BIT(0)
23 : : #define ML_FLAGS_SSO_COMPL BIT(1)
24 : :
25 : : /* Hardware non-fatal error subtype database */
26 : : static struct cnxk_ml_error_db ml_stype_db_hw_nf[] = {
27 : : {ML_CN10K_FW_ERR_NOERR, "NO ERROR"},
28 : : {ML_CN10K_FW_ERR_UNLOAD_ID_NOT_FOUND, "UNLOAD MODEL ID NOT FOUND"},
29 : : {ML_CN10K_FW_ERR_LOAD_LUT_OVERFLOW, "LOAD LUT OVERFLOW"},
30 : : {ML_CN10K_FW_ERR_ID_IN_USE, "MODEL ID IN USE"},
31 : : {ML_CN10K_FW_ERR_INVALID_TILEMASK, "INVALID TILEMASK"},
32 : : {ML_CN10K_FW_ERR_RUN_LUT_OVERFLOW, "RUN LUT OVERFLOW"},
33 : : {ML_CN10K_FW_ERR_RUN_ID_NOT_FOUND, "RUN MODEL ID NOT FOUND"},
34 : : {ML_CN10K_FW_ERR_COMMAND_NOTSUP, "COMMAND NOT SUPPORTED"},
35 : : {ML_CN10K_FW_ERR_DDR_ADDR_RANGE, "DDR ADDRESS OUT OF RANGE"},
36 : : {ML_CN10K_FW_ERR_NUM_BATCHES_INVALID, "INVALID BATCHES"},
37 : : {ML_CN10K_FW_ERR_INSSYNC_TIMEOUT, "INSSYNC TIMEOUT"},
38 : : };
39 : :
40 : : /* Driver error subtype database */
41 : : static struct cnxk_ml_error_db ml_stype_db_driver[] = {
42 : : {ML_CN10K_DRIVER_ERR_NOERR, "NO ERROR"},
43 : : {ML_CN10K_DRIVER_ERR_UNKNOWN, "UNKNOWN ERROR"},
44 : : {ML_CN10K_DRIVER_ERR_EXCEPTION, "FW EXCEPTION"},
45 : : {ML_CN10K_DRIVER_ERR_FW_ERROR, "UNKNOWN FIRMWARE ERROR"},
46 : : };
47 : :
48 : : __rte_hot void
49 : 0 : cn10k_ml_set_poll_addr(struct cnxk_ml_req *req)
50 : : {
51 : 0 : req->status = &req->cn10k_req.status;
52 : 0 : }
53 : :
54 : : void
55 : 0 : cn10k_ml_qp_initialize(struct cnxk_ml_dev *cnxk_mldev, struct cnxk_ml_qp *qp)
56 : : {
57 : : uint64_t i;
58 : :
59 : : RTE_SET_USED(cnxk_mldev);
60 : :
61 : : /* Initialize job command */
62 [ # # ]: 0 : for (i = 0; i < qp->nb_desc; i++) {
63 : 0 : memset(&qp->queue.reqs[i].cn10k_req.jd, 0, sizeof(struct cn10k_ml_jd));
64 : 0 : qp->queue.reqs[i].cn10k_req.jcmd.w1.s.jobptr =
65 : 0 : PLT_U64_CAST(&qp->queue.reqs[i].cn10k_req.jd);
66 : : }
67 : 0 : }
68 : :
69 : : static void
70 : 0 : cn10k_ml_prep_sp_job_descriptor(struct cnxk_ml_dev *cnxk_mldev, struct cnxk_ml_layer *layer,
71 : : struct cnxk_ml_req *req, enum cn10k_ml_job_type job_type)
72 : : {
73 : : struct cn10k_ml_model_metadata *metadata;
74 : : struct cn10k_ml_layer_addr *addr;
75 : : struct cn10k_ml_dev *cn10k_mldev;
76 : :
77 : : cn10k_mldev = &cnxk_mldev->cn10k_mldev;
78 : : metadata = &layer->glow.metadata;
79 : : addr = &layer->glow.addr;
80 : :
81 : 0 : memset(&req->cn10k_req.jd, 0, sizeof(struct cn10k_ml_jd));
82 : : req->cn10k_req.jd.hdr.jce.w0.u64 = 0;
83 : 0 : req->cn10k_req.jd.hdr.jce.w1.u64 = PLT_U64_CAST(&req->cn10k_req.status);
84 : 0 : req->cn10k_req.jd.hdr.model_id = layer->index;
85 : 0 : req->cn10k_req.jd.hdr.job_type = job_type;
86 : : req->cn10k_req.jd.hdr.fp_flags = 0x0;
87 : 0 : req->cn10k_req.jd.hdr.result =
88 : 0 : roc_ml_addr_ap2mlip(&cn10k_mldev->roc, &req->cn10k_req.result);
89 : :
90 [ # # ]: 0 : if (job_type == ML_CN10K_JOB_TYPE_MODEL_START) {
91 [ # # ]: 0 : if (!layer->glow.metadata.model.ocm_relocatable)
92 : 0 : req->cn10k_req.jd.hdr.sp_flags = ML_CN10K_SP_FLAGS_OCM_NONRELOCATABLE;
93 : : else
94 : 0 : req->cn10k_req.jd.hdr.sp_flags = 0x0;
95 : :
96 : 0 : req->cn10k_req.jd.hdr.sp_flags |= ML_CN10K_SP_FLAGS_EXTENDED_LOAD_JD;
97 : 0 : req->cn10k_req.jd.model_start.extended_args = PLT_U64_CAST(
98 : : roc_ml_addr_ap2mlip(&cn10k_mldev->roc, &req->cn10k_req.extended_args));
99 : 0 : req->cn10k_req.jd.model_start.model_dst_ddr_addr =
100 : 0 : PLT_U64_CAST(roc_ml_addr_ap2mlip(&cn10k_mldev->roc, addr->init_load_addr));
101 : 0 : req->cn10k_req.jd.model_start.model_init_offset = 0x0;
102 : 0 : req->cn10k_req.jd.model_start.model_main_offset = metadata->init_model.file_size;
103 : 0 : req->cn10k_req.jd.model_start.model_finish_offset =
104 : 0 : metadata->init_model.file_size + metadata->main_model.file_size;
105 : 0 : req->cn10k_req.jd.model_start.model_init_size = metadata->init_model.file_size;
106 : 0 : req->cn10k_req.jd.model_start.model_main_size = metadata->main_model.file_size;
107 : 0 : req->cn10k_req.jd.model_start.model_finish_size = metadata->finish_model.file_size;
108 : 0 : req->cn10k_req.jd.model_start.model_wb_offset = metadata->init_model.file_size +
109 : 0 : metadata->main_model.file_size +
110 : : metadata->finish_model.file_size;
111 : 0 : req->cn10k_req.jd.model_start.num_layers = metadata->model.num_layers;
112 : 0 : req->cn10k_req.jd.model_start.num_gather_entries = 0;
113 : 0 : req->cn10k_req.jd.model_start.num_scatter_entries = 0;
114 : 0 : req->cn10k_req.jd.model_start.tilemask = 0; /* Updated after reserving pages */
115 : 0 : req->cn10k_req.jd.model_start.batch_size = layer->batch_size;
116 : 0 : req->cn10k_req.jd.model_start.ocm_wb_base_address =
117 : : 0; /* Updated after reserving pages */
118 : 0 : req->cn10k_req.jd.model_start.ocm_wb_range_start =
119 : 0 : metadata->model.ocm_wb_range_start;
120 : 0 : req->cn10k_req.jd.model_start.ocm_wb_range_end = metadata->model.ocm_wb_range_end;
121 : 0 : req->cn10k_req.jd.model_start.ddr_wb_base_address =
122 : 0 : PLT_U64_CAST(roc_ml_addr_ap2mlip(
123 : : &cn10k_mldev->roc, PLT_PTR_ADD(addr->finish_load_addr,
124 : : metadata->finish_model.file_size)));
125 : 0 : req->cn10k_req.jd.model_start.ddr_wb_range_start =
126 : 0 : metadata->model.ddr_wb_range_start;
127 : 0 : req->cn10k_req.jd.model_start.ddr_wb_range_end = metadata->model.ddr_wb_range_end;
128 : 0 : req->cn10k_req.jd.model_start.input.s.ddr_range_start =
129 : 0 : metadata->model.ddr_input_range_start;
130 : 0 : req->cn10k_req.jd.model_start.input.s.ddr_range_end =
131 : 0 : metadata->model.ddr_input_range_end;
132 : 0 : req->cn10k_req.jd.model_start.output.s.ddr_range_start =
133 : 0 : metadata->model.ddr_output_range_start;
134 : 0 : req->cn10k_req.jd.model_start.output.s.ddr_range_end =
135 : 0 : metadata->model.ddr_output_range_end;
136 : :
137 : 0 : req->cn10k_req.extended_args.start.ddr_scratch_base_address = PLT_U64_CAST(
138 : : roc_ml_addr_ap2mlip(&cn10k_mldev->roc, addr->scratch_base_addr));
139 : 0 : req->cn10k_req.extended_args.start.ddr_scratch_range_start =
140 : 0 : metadata->model.ddr_scratch_range_start;
141 : 0 : req->cn10k_req.extended_args.start.ddr_scratch_range_end =
142 : 0 : metadata->model.ddr_scratch_range_end;
143 : : }
144 : 0 : }
145 : :
146 : : static __rte_always_inline void
147 : : cn10k_ml_prep_fp_job_descriptor(struct cnxk_ml_dev *cnxk_mldev, struct cnxk_ml_req *req,
148 : : uint16_t index, void *input, void *output, uint16_t nb_batches)
149 : : {
150 : : struct cn10k_ml_dev *cn10k_mldev;
151 : :
152 : : cn10k_mldev = &cnxk_mldev->cn10k_mldev;
153 : :
154 : 0 : req->cn10k_req.jd.hdr.jce.w0.u64 = 0;
155 : 0 : req->cn10k_req.jd.hdr.jce.w1.u64 = PLT_U64_CAST(req->status);
156 : 0 : req->cn10k_req.jd.hdr.model_id = index;
157 : 0 : req->cn10k_req.jd.hdr.job_type = ML_CN10K_JOB_TYPE_MODEL_RUN;
158 : 0 : req->cn10k_req.jd.hdr.fp_flags = ML_FLAGS_POLL_COMPL;
159 : 0 : req->cn10k_req.jd.hdr.sp_flags = 0x0;
160 : 0 : req->cn10k_req.jd.hdr.result =
161 : 0 : roc_ml_addr_ap2mlip(&cn10k_mldev->roc, &req->cn10k_req.result);
162 : 0 : req->cn10k_req.jd.model_run.input_ddr_addr =
163 : 0 : PLT_U64_CAST(roc_ml_addr_ap2mlip(&cn10k_mldev->roc, input));
164 : 0 : req->cn10k_req.jd.model_run.output_ddr_addr =
165 : 0 : PLT_U64_CAST(roc_ml_addr_ap2mlip(&cn10k_mldev->roc, output));
166 : 0 : req->cn10k_req.jd.model_run.num_batches = nb_batches;
167 : : }
168 : :
169 : : static void
170 : 0 : cn10k_ml_xstats_layer_name_update(struct cnxk_ml_dev *cnxk_mldev, uint16_t model_id,
171 : : uint16_t layer_id)
172 : : {
173 : : struct cnxk_ml_model *model;
174 : : struct cnxk_ml_layer *layer;
175 : : uint16_t rclk_freq;
176 : : uint16_t sclk_freq;
177 : : uint16_t stat_id;
178 : : char suffix[8];
179 : : uint16_t i;
180 : :
181 : 0 : model = cnxk_mldev->mldev->data->models[model_id];
182 : 0 : layer = &model->layer[layer_id];
183 : 0 : stat_id = cnxk_mldev->xstats.offset_for_layer[model_id][layer_id];
184 : :
185 : 0 : roc_clk_freq_get(&rclk_freq, &sclk_freq);
186 [ # # ]: 0 : if (sclk_freq == 0)
187 : : strcpy(suffix, "cycles");
188 : : else
189 : : strcpy(suffix, "ns");
190 : :
191 : : /* Update xstat name based on layer name and sclk availability */
192 [ # # ]: 0 : for (i = 0; i < RTE_DIM(layer_xstats); i++) {
193 : 0 : snprintf(cnxk_mldev->xstats.entries[stat_id].map.name,
194 : : sizeof(cnxk_mldev->xstats.entries[stat_id].map.name), "%s-%s-%s",
195 : 0 : layer->glow.metadata.model.name, layer_xstats[i].name, suffix);
196 : 0 : stat_id++;
197 : : }
198 : 0 : }
199 : :
200 : : void
201 : 0 : cn10k_ml_xstat_model_name_set(struct cnxk_ml_dev *cnxk_mldev, struct cnxk_ml_model *model,
202 : : uint16_t stat_id, uint16_t entry, char *suffix)
203 : : {
204 : 0 : snprintf(cnxk_mldev->xstats.entries[stat_id].map.name,
205 : : sizeof(cnxk_mldev->xstats.entries[stat_id].map.name), "%s-%s-%s",
206 : 0 : model->glow.metadata.model.name, model_xstats[entry].name, suffix);
207 : 0 : }
208 : :
209 : : #define ML_AVG_FOREACH_QP(cnxk_mldev, layer, qp_id, str, value, count) \
210 : : do { \
211 : : value = 0; \
212 : : for (qp_id = 0; qp_id < cnxk_mldev->mldev->data->nb_queue_pairs; qp_id++) { \
213 : : value += layer->glow.burst_xstats[qp_id].str##_latency_tot; \
214 : : count += layer->glow.burst_xstats[qp_id].dequeued_count - \
215 : : layer->glow.burst_xstats[qp_id].str##_reset_count; \
216 : : } \
217 : : value += layer->glow.sync_xstats->str##_latency_tot; \
218 : : count += layer->glow.sync_xstats->dequeued_count - \
219 : : layer->glow.sync_xstats->str##_reset_count; \
220 : : if (count != 0) \
221 : : value = value / count; \
222 : : } while (0)
223 : :
224 : : #define ML_MIN_FOREACH_QP(cnxk_mldev, layer, qp_id, str, value, count) \
225 : : do { \
226 : : value = UINT64_MAX; \
227 : : for (qp_id = 0; qp_id < cnxk_mldev->mldev->data->nb_queue_pairs; qp_id++) { \
228 : : value = PLT_MIN(value, layer->glow.burst_xstats[qp_id].str##_latency_min); \
229 : : count += layer->glow.burst_xstats[qp_id].dequeued_count - \
230 : : layer->glow.burst_xstats[qp_id].str##_reset_count; \
231 : : } \
232 : : value = PLT_MIN(value, layer->glow.sync_xstats->str##_latency_min); \
233 : : count += layer->glow.sync_xstats->dequeued_count - \
234 : : layer->glow.sync_xstats->str##_reset_count; \
235 : : if (count == 0) \
236 : : value = 0; \
237 : : } while (0)
238 : :
239 : : #define ML_MAX_FOREACH_QP(cnxk_mldev, layer, qp_id, str, value, count) \
240 : : do { \
241 : : value = 0; \
242 : : for (qp_id = 0; qp_id < cnxk_mldev->mldev->data->nb_queue_pairs; qp_id++) { \
243 : : value = PLT_MAX(value, layer->glow.burst_xstats[qp_id].str##_latency_max); \
244 : : count += layer->glow.burst_xstats[qp_id].dequeued_count - \
245 : : layer->glow.burst_xstats[qp_id].str##_reset_count; \
246 : : } \
247 : : value = PLT_MAX(value, layer->glow.sync_xstats->str##_latency_max); \
248 : : count += layer->glow.sync_xstats->dequeued_count - \
249 : : layer->glow.sync_xstats->str##_reset_count; \
250 : : if (count == 0) \
251 : : value = 0; \
252 : : } while (0)
253 : :
254 : : uint64_t
255 : 0 : cn10k_ml_model_xstat_get(struct cnxk_ml_dev *cnxk_mldev, struct cnxk_ml_layer *layer,
256 : : enum cnxk_ml_xstats_type type)
257 : : {
258 : : uint64_t count = 0;
259 : : uint64_t value = 0;
260 : : uint32_t qp_id;
261 : :
262 [ # # # # : 0 : switch (type) {
# # # ]
263 : : case avg_hw_latency:
264 [ # # # # ]: 0 : ML_AVG_FOREACH_QP(cnxk_mldev, layer, qp_id, hw, value, count);
265 : : break;
266 : : case min_hw_latency:
267 [ # # # # ]: 0 : ML_MIN_FOREACH_QP(cnxk_mldev, layer, qp_id, hw, value, count);
268 : : break;
269 : : case max_hw_latency:
270 [ # # # # ]: 0 : ML_MAX_FOREACH_QP(cnxk_mldev, layer, qp_id, hw, value, count);
271 : : break;
272 : : case avg_fw_latency:
273 [ # # # # ]: 0 : ML_AVG_FOREACH_QP(cnxk_mldev, layer, qp_id, fw, value, count);
274 : : break;
275 : : case min_fw_latency:
276 [ # # # # ]: 0 : ML_MIN_FOREACH_QP(cnxk_mldev, layer, qp_id, fw, value, count);
277 : : break;
278 : : case max_fw_latency:
279 [ # # # # ]: 0 : ML_MAX_FOREACH_QP(cnxk_mldev, layer, qp_id, fw, value, count);
280 : : break;
281 : : default:
282 : : value = 0;
283 : : }
284 : :
285 : 0 : return value;
286 : : }
287 : :
288 : : static int
289 : 0 : cn10k_ml_cache_model_data(struct cnxk_ml_dev *cnxk_mldev, struct cnxk_ml_layer *layer)
290 : : {
291 : : char str[RTE_MEMZONE_NAMESIZE];
292 : : const struct plt_memzone *mz;
293 : : uint64_t isize = 0;
294 : : uint64_t osize = 0;
295 : : int ret = 0;
296 : :
297 : : /* Create input and output buffers. */
298 : 0 : isize = layer->info.total_input_sz_q;
299 : 0 : osize = layer->info.total_output_sz_q;
300 : :
301 : 0 : snprintf(str, RTE_MEMZONE_NAMESIZE, "%s_%u", "ml_dummy_io", layer->index);
302 : 0 : mz = plt_memzone_reserve_aligned(str, isize + osize, 0, ML_CN10K_ALIGN_SIZE);
303 [ # # ]: 0 : if (mz == NULL)
304 : : return -ENOMEM;
305 : 0 : memset(mz->addr, 0, isize + osize);
306 : :
307 : 0 : memset(layer->glow.req, 0, sizeof(struct cnxk_ml_req));
308 : 0 : ret = cn10k_ml_inference_sync(cnxk_mldev, layer->index, mz->addr,
309 : 0 : PLT_PTR_ADD(mz->addr, isize), 1);
310 : 0 : plt_memzone_free(mz);
311 : :
312 : 0 : return ret;
313 : : }
314 : :
315 : : int
316 : 0 : cn10k_ml_dev_info_get(struct cnxk_ml_dev *cnxk_mldev, struct rte_ml_dev_info *dev_info)
317 : : {
318 : : struct cn10k_ml_dev *cn10k_mldev;
319 : :
320 : : cn10k_mldev = &cnxk_mldev->cn10k_mldev;
321 : :
322 [ # # ]: 0 : if (cn10k_mldev->hw_queue_lock)
323 : 0 : dev_info->max_queue_pairs = ML_CN10K_MAX_QP_PER_DEVICE_SL;
324 : : else
325 : 0 : dev_info->max_queue_pairs = ML_CN10K_MAX_QP_PER_DEVICE_LF;
326 : :
327 : 0 : dev_info->max_desc = ML_CN10K_MAX_DESC_PER_QP;
328 : 0 : dev_info->max_io = ML_CN10K_MAX_INPUT_OUTPUT;
329 : 0 : dev_info->max_segments = ML_CN10K_MAX_SEGMENTS;
330 : 0 : dev_info->align_size = ML_CN10K_ALIGN_SIZE;
331 : :
332 : 0 : return 0;
333 : : }
334 : :
335 : : int
336 : 0 : cn10k_ml_dev_configure(struct cnxk_ml_dev *cnxk_mldev, const struct rte_ml_dev_config *conf)
337 : : {
338 : : struct cn10k_ml_dev *cn10k_mldev;
339 : : struct cn10k_ml_ocm *ocm;
340 : : uint16_t tile_id;
341 : :
342 : : RTE_SET_USED(conf);
343 : :
344 : : cn10k_mldev = &cnxk_mldev->cn10k_mldev;
345 : :
346 : : ocm = &cn10k_mldev->ocm;
347 : 0 : ocm->num_tiles = ML_CN10K_OCM_NUMTILES;
348 : 0 : ocm->size_per_tile = ML_CN10K_OCM_TILESIZE;
349 : 0 : ocm->page_size = cn10k_mldev->ocm_page_size;
350 : 0 : ocm->num_pages = ocm->size_per_tile / ocm->page_size;
351 : 0 : ocm->mask_words = ocm->num_pages / (8 * sizeof(uint8_t));
352 : :
353 : : /* Allocate memory for ocm_mask */
354 : 0 : ocm->ocm_mask =
355 : 0 : rte_zmalloc("ocm_mask", ocm->mask_words * ocm->num_tiles, RTE_CACHE_LINE_SIZE);
356 [ # # ]: 0 : if (ocm->ocm_mask == NULL) {
357 : 0 : plt_err("Unable to allocate memory for OCM mask");
358 : 0 : return -ENOMEM;
359 : : }
360 : :
361 [ # # ]: 0 : for (tile_id = 0; tile_id < ocm->num_tiles; tile_id++) {
362 : 0 : ocm->tile_ocm_info[tile_id].ocm_mask = ocm->ocm_mask + tile_id * ocm->mask_words;
363 : 0 : ocm->tile_ocm_info[tile_id].last_wb_page = -1;
364 : : }
365 : :
366 : : rte_spinlock_init(&ocm->lock);
367 : :
368 : : /* Set JCMDQ enqueue function */
369 [ # # ]: 0 : if (cn10k_mldev->hw_queue_lock == 1)
370 : 0 : cn10k_mldev->ml_jcmdq_enqueue = roc_ml_jcmdq_enqueue_sl;
371 : : else
372 : 0 : cn10k_mldev->ml_jcmdq_enqueue = roc_ml_jcmdq_enqueue_lf;
373 : :
374 : : return 0;
375 : : }
376 : :
377 : : int
378 : 0 : cn10k_ml_dev_close(struct cnxk_ml_dev *cnxk_mldev)
379 : : {
380 : : struct cn10k_ml_dev *cn10k_mldev;
381 : :
382 : : cn10k_mldev = &cnxk_mldev->cn10k_mldev;
383 : :
384 : : /* Release ocm_mask memory */
385 : 0 : rte_free(cn10k_mldev->ocm.ocm_mask);
386 : :
387 : : /* Unload firmware */
388 : 0 : cn10k_ml_fw_unload(cnxk_mldev);
389 : :
390 : : /* Clear scratch registers */
391 : 0 : roc_ml_reg_write64(&cn10k_mldev->roc, 0, ML_SCRATCH_WORK_PTR);
392 : 0 : roc_ml_reg_write64(&cn10k_mldev->roc, 0, ML_SCRATCH_FW_CTRL);
393 : 0 : roc_ml_reg_write64(&cn10k_mldev->roc, 0, ML_SCRATCH_DBG_BUFFER_HEAD_C0);
394 : 0 : roc_ml_reg_write64(&cn10k_mldev->roc, 0, ML_SCRATCH_DBG_BUFFER_TAIL_C0);
395 : 0 : roc_ml_reg_write64(&cn10k_mldev->roc, 0, ML_SCRATCH_DBG_BUFFER_HEAD_C1);
396 : 0 : roc_ml_reg_write64(&cn10k_mldev->roc, 0, ML_SCRATCH_DBG_BUFFER_TAIL_C1);
397 : :
398 : : /* Reset ML_MLR_BASE */
399 : 0 : roc_ml_reg_write64(&cn10k_mldev->roc, 0, ML_MLR_BASE);
400 : 0 : plt_ml_dbg("ML_MLR_BASE = 0x%016lx", roc_ml_reg_read64(&cn10k_mldev->roc, ML_MLR_BASE));
401 : :
402 : 0 : return 0;
403 : : }
404 : :
405 : : int
406 : 0 : cn10k_ml_dev_start(struct cnxk_ml_dev *cnxk_mldev)
407 : : {
408 : : struct cn10k_ml_dev *cn10k_mldev;
409 : : uint64_t reg_val64;
410 : :
411 : : cn10k_mldev = &cnxk_mldev->cn10k_mldev;
412 : :
413 : 0 : reg_val64 = roc_ml_reg_read64(&cn10k_mldev->roc, ML_CFG);
414 : 0 : reg_val64 |= ROC_ML_CFG_ENA;
415 : 0 : roc_ml_reg_write64(&cn10k_mldev->roc, reg_val64, ML_CFG);
416 : 0 : plt_ml_dbg("ML_CFG => 0x%016lx", roc_ml_reg_read64(&cn10k_mldev->roc, ML_CFG));
417 : :
418 : 0 : return 0;
419 : : }
420 : :
421 : : int
422 : 0 : cn10k_ml_dev_stop(struct cnxk_ml_dev *cnxk_mldev)
423 : : {
424 : : struct cn10k_ml_dev *cn10k_mldev;
425 : : uint64_t reg_val64;
426 : :
427 : : cn10k_mldev = &cnxk_mldev->cn10k_mldev;
428 : :
429 : 0 : reg_val64 = roc_ml_reg_read64(&cn10k_mldev->roc, ML_CFG);
430 : 0 : reg_val64 &= ~ROC_ML_CFG_ENA;
431 : 0 : roc_ml_reg_write64(&cn10k_mldev->roc, reg_val64, ML_CFG);
432 : 0 : plt_ml_dbg("ML_CFG => 0x%016lx", roc_ml_reg_read64(&cn10k_mldev->roc, ML_CFG));
433 : :
434 : 0 : return 0;
435 : : }
436 : :
437 : : int
438 : 0 : cn10k_ml_dev_dump(struct cnxk_ml_dev *cnxk_mldev, FILE *fp)
439 : : {
440 : : struct cn10k_ml_dev *cn10k_mldev;
441 : : struct cn10k_ml_fw *fw;
442 : :
443 : : uint32_t head_loc;
444 : : uint32_t tail_loc;
445 : : uint32_t bufsize;
446 : : char *head_ptr;
447 : : int core_id;
448 : :
449 : : cn10k_mldev = &cnxk_mldev->cn10k_mldev;
450 : : fw = &cn10k_mldev->fw;
451 : :
452 : : /* Dump OCM state */
453 : 0 : cn10k_ml_ocm_print(cnxk_mldev, fp);
454 : :
455 [ # # ]: 0 : if (roc_env_is_asim())
456 : : return 0;
457 : :
458 : : /* Dump debug buffer */
459 [ # # ]: 0 : for (core_id = 0; core_id <= 1; core_id++) {
460 : 0 : bufsize = fw->req->cn10k_req.jd.fw_load.debug.debug_buffer_size;
461 [ # # ]: 0 : if (core_id == 0) {
462 : 0 : head_loc =
463 : 0 : roc_ml_reg_read64(&cn10k_mldev->roc, ML_SCRATCH_DBG_BUFFER_HEAD_C0);
464 : 0 : tail_loc =
465 : 0 : roc_ml_reg_read64(&cn10k_mldev->roc, ML_SCRATCH_DBG_BUFFER_TAIL_C0);
466 : 0 : head_ptr =
467 : 0 : PLT_PTR_CAST(fw->req->cn10k_req.jd.fw_load.debug.core0_debug_ptr);
468 : 0 : head_ptr = roc_ml_addr_mlip2ap(&cn10k_mldev->roc, head_ptr);
469 : : } else {
470 : 0 : head_loc =
471 : 0 : roc_ml_reg_read64(&cn10k_mldev->roc, ML_SCRATCH_DBG_BUFFER_HEAD_C1);
472 : 0 : tail_loc =
473 : 0 : roc_ml_reg_read64(&cn10k_mldev->roc, ML_SCRATCH_DBG_BUFFER_TAIL_C1);
474 : 0 : head_ptr =
475 : 0 : PLT_PTR_CAST(fw->req->cn10k_req.jd.fw_load.debug.core1_debug_ptr);
476 : 0 : head_ptr = roc_ml_addr_mlip2ap(&cn10k_mldev->roc, head_ptr);
477 : : }
478 [ # # ]: 0 : if (head_loc < tail_loc) {
479 : 0 : fprintf(fp, "%.*s\n", tail_loc - head_loc, &head_ptr[head_loc]);
480 [ # # ]: 0 : } else if (head_loc >= tail_loc + 1) {
481 : 0 : fprintf(fp, "%.*s\n", bufsize - tail_loc, &head_ptr[head_loc]);
482 : : fprintf(fp, "%.*s\n", tail_loc, &head_ptr[0]);
483 : : }
484 : : }
485 : :
486 : : /* Dump exception info */
487 [ # # ]: 0 : for (core_id = 0; core_id <= 1; core_id++) {
488 : 0 : bufsize = fw->req->cn10k_req.jd.fw_load.debug.exception_state_size;
489 [ # # # # ]: 0 : if ((core_id == 0) &&
490 : 0 : (roc_ml_reg_read64(&cn10k_mldev->roc, ML_SCRATCH_EXCEPTION_SP_C0) != 0)) {
491 : 0 : head_ptr = PLT_PTR_CAST(
492 : : fw->req->cn10k_req.jd.fw_load.debug.core0_exception_buffer);
493 : 0 : fprintf(fp, "ML_SCRATCH_EXCEPTION_SP_C0 = 0x%016lx",
494 : : roc_ml_reg_read64(&cn10k_mldev->roc, ML_SCRATCH_EXCEPTION_SP_C0));
495 : 0 : head_ptr = roc_ml_addr_mlip2ap(&cn10k_mldev->roc, head_ptr);
496 : : fprintf(fp, "%.*s", bufsize, head_ptr);
497 [ # # # # ]: 0 : } else if ((core_id == 1) && (roc_ml_reg_read64(&cn10k_mldev->roc,
498 : : ML_SCRATCH_EXCEPTION_SP_C1) != 0)) {
499 : 0 : head_ptr = PLT_PTR_CAST(
500 : : fw->req->cn10k_req.jd.fw_load.debug.core1_exception_buffer);
501 : 0 : fprintf(fp, "ML_SCRATCH_EXCEPTION_SP_C1 = 0x%016lx",
502 : : roc_ml_reg_read64(&cn10k_mldev->roc, ML_SCRATCH_EXCEPTION_SP_C1));
503 : 0 : head_ptr = roc_ml_addr_mlip2ap(&cn10k_mldev->roc, head_ptr);
504 : : fprintf(fp, "%.*s", bufsize, head_ptr);
505 : : }
506 : : }
507 : :
508 : : return 0;
509 : : }
510 : :
511 : : int
512 : 0 : cn10k_ml_dev_selftest(struct cnxk_ml_dev *cnxk_mldev)
513 : : {
514 : : struct cn10k_ml_dev *cn10k_mldev;
515 : : const struct plt_memzone *mz;
516 : : struct cnxk_ml_req *req;
517 : : uint64_t timeout_cycle;
518 : : bool timeout;
519 : : int ret;
520 : :
521 : : cn10k_mldev = &cnxk_mldev->cn10k_mldev;
522 : 0 : mz = plt_memzone_reserve_aligned("dev_selftest", sizeof(struct cnxk_ml_req), 0,
523 : : ML_CN10K_ALIGN_SIZE);
524 [ # # ]: 0 : if (mz == NULL) {
525 : 0 : plt_err("Could not allocate reserved memzone");
526 : 0 : return -ENOMEM;
527 : : }
528 : 0 : req = mz->addr;
529 : :
530 : : /* Prepare load completion structure */
531 : 0 : memset(&req->cn10k_req.jd, 0, sizeof(struct cn10k_ml_jd));
532 : 0 : req->cn10k_req.jd.hdr.jce.w1.u64 = PLT_U64_CAST(&req->cn10k_req.status);
533 : 0 : req->cn10k_req.jd.hdr.job_type = ML_CN10K_JOB_TYPE_FIRMWARE_SELFTEST;
534 : 0 : req->cn10k_req.jd.hdr.result =
535 : 0 : roc_ml_addr_ap2mlip(&cn10k_mldev->roc, &req->cn10k_req.result);
536 : 0 : req->cn10k_req.jd.fw_load.flags = cn10k_ml_fw_flags_get(&cn10k_mldev->fw);
537 : : plt_write64(ML_CNXK_POLL_JOB_START, &req->cn10k_req.status);
538 : : plt_wmb();
539 : :
540 : : /* Enqueue firmware selftest request through scratch registers */
541 : : timeout = true;
542 : 0 : timeout_cycle = plt_tsc_cycles() + ML_CNXK_CMD_TIMEOUT * plt_tsc_hz();
543 : 0 : roc_ml_scratch_enqueue(&cn10k_mldev->roc, &req->cn10k_req.jd);
544 : :
545 : : plt_rmb();
546 : : do {
547 [ # # # # ]: 0 : if (roc_ml_scratch_is_done_bit_set(&cn10k_mldev->roc) &&
548 : : (plt_read64(&req->cn10k_req.status) == ML_CNXK_POLL_JOB_FINISH)) {
549 : : timeout = false;
550 : : break;
551 : : }
552 [ # # ]: 0 : } while (plt_tsc_cycles() < timeout_cycle);
553 : :
554 : : /* Check firmware selftest status, clean-up and exit */
555 : : ret = 0;
556 [ # # ]: 0 : if (timeout) {
557 : : ret = -ETIME;
558 : : } else {
559 [ # # ]: 0 : if (req->cn10k_req.result.error_code != 0)
560 : : ret = -1;
561 : : }
562 : :
563 : 0 : plt_memzone_free(mz);
564 : :
565 : 0 : return ret;
566 : : }
567 : :
568 : : int
569 : 0 : cn10k_ml_layer_load(void *device, uint16_t model_id, const char *layer_name, uint8_t *buffer,
570 : : size_t size, uint16_t *index)
571 : : {
572 : : struct cn10k_ml_model_metadata *metadata;
573 : : struct cnxk_ml_dev *cnxk_mldev;
574 : : struct cnxk_ml_model *model;
575 : : struct cnxk_ml_layer *layer;
576 : :
577 : : char str[RTE_MEMZONE_NAMESIZE];
578 : : const struct plt_memzone *mz;
579 : : size_t layer_object_size = 0;
580 : : size_t layer_scratch_size;
581 : : size_t layer_xstats_size;
582 : : uint8_t *base_dma_addr;
583 : : uint16_t scratch_pages;
584 : : uint16_t layer_id;
585 : : uint16_t wb_pages;
586 : : uint64_t mz_size;
587 : : uint16_t idx;
588 : : int qp_id;
589 : : int ret;
590 : :
591 : : PLT_SET_USED(size);
592 : :
593 : : cnxk_mldev = (struct cnxk_ml_dev *)device;
594 [ # # ]: 0 : if (cnxk_mldev == NULL) {
595 : 0 : plt_err("Invalid device = %p", device);
596 : 0 : return -EINVAL;
597 : : }
598 : :
599 : 0 : model = cnxk_mldev->mldev->data->models[model_id];
600 [ # # ]: 0 : if (model == NULL) {
601 : 0 : plt_err("Invalid model_id = %u", model_id);
602 : 0 : return -EINVAL;
603 : : }
604 : :
605 : 0 : ret = cn10k_ml_model_get_layer_id(model, layer_name, &layer_id);
606 [ # # ]: 0 : if (ret != 0)
607 : : return ret;
608 : :
609 : 0 : layer = &model->layer[layer_id];
610 : :
611 : 0 : ret = cn10k_ml_model_metadata_check(buffer, size);
612 [ # # ]: 0 : if (ret != 0)
613 : : return ret;
614 : :
615 : : /* Get index */
616 [ # # ]: 0 : for (idx = 0; idx < cnxk_mldev->max_nb_layers; idx++) {
617 [ # # ]: 0 : if (!cnxk_mldev->index_map[idx].active) {
618 : 0 : layer->index = idx;
619 : 0 : break;
620 : : }
621 : : }
622 : :
623 [ # # ]: 0 : if (idx >= cnxk_mldev->max_nb_layers) {
624 : 0 : plt_err("No slots available for model layers, model_id = %u, layer_id = %u",
625 : : model->model_id, layer_id);
626 : 0 : return -1;
627 : : }
628 : :
629 : 0 : layer->model = model;
630 : :
631 : : /* Get WB and scratch pages, check if model can be loaded. */
632 : 0 : ret = cn10k_ml_model_ocm_pages_count(cnxk_mldev, layer, buffer, &wb_pages, &scratch_pages);
633 [ # # ]: 0 : if (ret < 0)
634 : : return ret;
635 : :
636 : : /* Compute layer memzone size */
637 : : metadata = (struct cn10k_ml_model_metadata *)buffer;
638 : 0 : layer_object_size = metadata->init_model.file_size + metadata->main_model.file_size +
639 : 0 : metadata->finish_model.file_size + metadata->weights_bias.file_size;
640 : 0 : layer_object_size = PLT_ALIGN_CEIL(layer_object_size, ML_CN10K_ALIGN_SIZE);
641 : 0 : layer_scratch_size = PLT_ALIGN_CEIL(metadata->model.ddr_scratch_range_end -
642 : : metadata->model.ddr_scratch_range_start + 1,
643 : : ML_CN10K_ALIGN_SIZE);
644 : 0 : layer_xstats_size = (cnxk_mldev->mldev->data->nb_queue_pairs + 1) *
645 : : sizeof(struct cn10k_ml_layer_xstats);
646 : :
647 : : /* Allocate memzone for model data */
648 : 0 : mz_size = layer_object_size + layer_scratch_size +
649 : 0 : PLT_ALIGN_CEIL(sizeof(struct cnxk_ml_req), ML_CN10K_ALIGN_SIZE) +
650 : : layer_xstats_size;
651 : 0 : snprintf(str, RTE_MEMZONE_NAMESIZE, "%s_%u_%u", CN10K_ML_LAYER_MEMZONE_NAME,
652 : 0 : model->model_id, layer_id);
653 : 0 : mz = plt_memzone_reserve_aligned(str, mz_size, 0, ML_CN10K_ALIGN_SIZE);
654 [ # # ]: 0 : if (!mz) {
655 : 0 : plt_err("plt_memzone_reserve failed : %s", str);
656 : 0 : return -ENOMEM;
657 : : }
658 : :
659 : : /* Copy metadata to internal buffer */
660 [ # # ]: 0 : rte_memcpy(&layer->glow.metadata, buffer, sizeof(struct cn10k_ml_model_metadata));
661 : 0 : cn10k_ml_model_metadata_update(&layer->glow.metadata);
662 : :
663 : : /* Set layer name */
664 [ # # ]: 0 : rte_memcpy(layer->name, layer->glow.metadata.model.name, MRVL_ML_MODEL_NAME_LEN);
665 : :
666 : : /* Enable support for batch_size of 256 */
667 [ # # ]: 0 : if (layer->glow.metadata.model.batch_size == 0)
668 : 0 : layer->batch_size = 256;
669 : : else
670 : 0 : layer->batch_size = layer->glow.metadata.model.batch_size;
671 : :
672 : : /* Set DMA base address */
673 : 0 : base_dma_addr = mz->addr;
674 : 0 : cn10k_ml_layer_addr_update(layer, buffer, base_dma_addr);
675 : :
676 : : /* Set scratch base address */
677 : 0 : layer->glow.addr.scratch_base_addr = PLT_PTR_ADD(base_dma_addr, layer_object_size);
678 : :
679 : : /* Update internal I/O data structure */
680 : 0 : cn10k_ml_layer_io_info_set(&layer->info, &layer->glow.metadata);
681 : :
682 : : /* Initialize model_mem_map */
683 : 0 : memset(&layer->glow.ocm_map, 0, sizeof(struct cn10k_ml_ocm_layer_map));
684 : 0 : layer->glow.ocm_map.ocm_reserved = false;
685 : 0 : layer->glow.ocm_map.tilemask = 0;
686 : 0 : layer->glow.ocm_map.wb_page_start = -1;
687 : 0 : layer->glow.ocm_map.wb_pages = wb_pages;
688 : 0 : layer->glow.ocm_map.scratch_pages = scratch_pages;
689 : :
690 : : /* Set slow-path request address and state */
691 : 0 : layer->glow.req = PLT_PTR_ADD(mz->addr, layer_object_size + layer_scratch_size);
692 : :
693 : : /* Reset burst and sync stats */
694 : 0 : layer->glow.burst_xstats = PLT_PTR_ADD(
695 : : layer->glow.req, PLT_ALIGN_CEIL(sizeof(struct cnxk_ml_req), ML_CN10K_ALIGN_SIZE));
696 [ # # ]: 0 : for (qp_id = 0; qp_id < cnxk_mldev->mldev->data->nb_queue_pairs + 1; qp_id++) {
697 : 0 : layer->glow.burst_xstats[qp_id].hw_latency_tot = 0;
698 : 0 : layer->glow.burst_xstats[qp_id].hw_latency_min = UINT64_MAX;
699 : 0 : layer->glow.burst_xstats[qp_id].hw_latency_max = 0;
700 : 0 : layer->glow.burst_xstats[qp_id].fw_latency_tot = 0;
701 : 0 : layer->glow.burst_xstats[qp_id].fw_latency_min = UINT64_MAX;
702 : 0 : layer->glow.burst_xstats[qp_id].fw_latency_max = 0;
703 : 0 : layer->glow.burst_xstats[qp_id].hw_reset_count = 0;
704 : 0 : layer->glow.burst_xstats[qp_id].fw_reset_count = 0;
705 : 0 : layer->glow.burst_xstats[qp_id].dequeued_count = 0;
706 : : }
707 : :
708 : 0 : layer->glow.sync_xstats =
709 : 0 : PLT_PTR_ADD(layer->glow.burst_xstats, cnxk_mldev->mldev->data->nb_queue_pairs *
710 : : sizeof(struct cn10k_ml_layer_xstats));
711 : :
712 : : /* Update xstats names */
713 : 0 : cn10k_ml_xstats_layer_name_update(cnxk_mldev, model_id, layer_id);
714 : :
715 : 0 : layer->state = ML_CNXK_LAYER_STATE_LOADED;
716 : 0 : cnxk_mldev->index_map[idx].model_id = model->model_id;
717 : 0 : cnxk_mldev->index_map[idx].layer_id = layer_id;
718 : 0 : cnxk_mldev->index_map[idx].active = true;
719 : 0 : *index = idx;
720 : :
721 : 0 : return 0;
722 : : }
723 : :
724 : : int
725 : 0 : cn10k_ml_model_load(struct cnxk_ml_dev *cnxk_mldev, struct rte_ml_model_params *params,
726 : : struct cnxk_ml_model *model)
727 : : {
728 : : struct cnxk_ml_layer *layer;
729 : : int ret;
730 : :
731 : : /* Metadata check */
732 : 0 : ret = cn10k_ml_model_metadata_check(params->addr, params->size);
733 [ # # ]: 0 : if (ret != 0)
734 : : return ret;
735 : :
736 : : /* Set model sub type */
737 : 0 : model->subtype = ML_CNXK_MODEL_SUBTYPE_GLOW_MRVL;
738 : :
739 : : /* Copy metadata to internal buffer */
740 [ # # ]: 0 : rte_memcpy(&model->glow.metadata, params->addr, sizeof(struct cn10k_ml_model_metadata));
741 : 0 : cn10k_ml_model_metadata_update(&model->glow.metadata);
742 : :
743 : : /* Set model name */
744 [ # # ]: 0 : rte_memcpy(model->name, (char *)model->glow.metadata.model.name, 64);
745 : :
746 : : /* Enable support for batch_size of 256 */
747 [ # # ]: 0 : if (model->glow.metadata.model.batch_size == 0)
748 : 0 : model->batch_size = 256;
749 : : else
750 : 0 : model->batch_size = model->glow.metadata.model.batch_size;
751 : :
752 : : /* Since the number of layers that the driver would be handling for glow models is
753 : : * always 1. consider the entire model as a model with single layer. This would
754 : : * ignore the num_layers from metadata.
755 : : */
756 : 0 : model->nb_layers = 1;
757 : :
758 : : /* Load layer and get the index */
759 : : layer = &model->layer[0];
760 : 0 : layer->type = ML_CNXK_LAYER_TYPE_MRVL;
761 : 0 : ret = cn10k_ml_layer_load(cnxk_mldev, model->model_id, NULL, params->addr, params->size,
762 : : &layer->index);
763 [ # # ]: 0 : if (ret != 0) {
764 : 0 : plt_err("Model layer load failed: model_id = %u, layer_id = %u", model->model_id,
765 : : 0);
766 : 0 : return ret;
767 : : }
768 : :
769 : 0 : cn10k_ml_model_info_set(cnxk_mldev, model, &model->layer[0].info, &model->glow.metadata);
770 : :
771 : : /* Set fast-path functions */
772 : 0 : model->enqueue_single = cn10k_ml_enqueue_single;
773 : 0 : model->result_update = cn10k_ml_result_update;
774 : 0 : model->set_error_code = cn10k_ml_set_error_code;
775 : 0 : model->set_poll_addr = cn10k_ml_set_poll_addr;
776 : :
777 : 0 : return 0;
778 : : }
779 : :
780 : : int
781 : 0 : cn10k_ml_layer_unload(void *device, uint16_t model_id, const char *layer_name)
782 : : {
783 : : struct cnxk_ml_dev *cnxk_mldev;
784 : : struct cnxk_ml_model *model;
785 : : struct cnxk_ml_layer *layer;
786 : :
787 : : char str[RTE_MEMZONE_NAMESIZE];
788 : : uint16_t layer_id;
789 : : int ret;
790 : :
791 : : cnxk_mldev = (struct cnxk_ml_dev *)device;
792 [ # # ]: 0 : if (cnxk_mldev == NULL) {
793 : 0 : plt_err("Invalid device = %p", device);
794 : 0 : return -EINVAL;
795 : : }
796 : :
797 : 0 : model = cnxk_mldev->mldev->data->models[model_id];
798 [ # # ]: 0 : if (model == NULL) {
799 : 0 : plt_err("Invalid model_id = %u", model_id);
800 : 0 : return -EINVAL;
801 : : }
802 : :
803 : 0 : ret = cn10k_ml_model_get_layer_id(model, layer_name, &layer_id);
804 [ # # ]: 0 : if (ret != 0)
805 : : return ret;
806 : :
807 : 0 : layer = &model->layer[layer_id];
808 : :
809 : 0 : snprintf(str, RTE_MEMZONE_NAMESIZE, "%s_%u_%u", CN10K_ML_LAYER_MEMZONE_NAME,
810 : 0 : model->model_id, layer_id);
811 : 0 : ret = plt_memzone_free(plt_memzone_lookup(str));
812 : :
813 : 0 : layer->state = ML_CNXK_LAYER_STATE_UNKNOWN;
814 : 0 : cnxk_mldev->index_map[layer->index].active = false;
815 : :
816 : 0 : return ret;
817 : : }
818 : :
819 : : int
820 : 0 : cn10k_ml_model_unload(struct cnxk_ml_dev *cnxk_mldev, struct cnxk_ml_model *model)
821 : : {
822 : 0 : return cn10k_ml_layer_unload(cnxk_mldev, model->model_id, NULL);
823 : : }
824 : :
825 : : int
826 : 0 : cn10k_ml_layer_start(void *device, uint16_t model_id, const char *layer_name)
827 : : {
828 : : struct cn10k_ml_dev *cn10k_mldev;
829 : : struct cnxk_ml_dev *cnxk_mldev;
830 : : struct cnxk_ml_model *model;
831 : : struct cnxk_ml_layer *layer;
832 : : struct cn10k_ml_ocm *ocm;
833 : : struct cnxk_ml_req *req;
834 : :
835 : : uint16_t layer_id;
836 : : bool job_enqueued;
837 : : bool job_dequeued;
838 : : uint8_t num_tiles;
839 : : uint64_t tilemask;
840 : : int wb_page_start;
841 : : int tile_start;
842 : : int tile_end;
843 : : bool locked;
844 : : int ret = 0;
845 : :
846 : : cnxk_mldev = (struct cnxk_ml_dev *)device;
847 [ # # ]: 0 : if (cnxk_mldev == NULL) {
848 : 0 : plt_err("Invalid device = %p", device);
849 : 0 : return -EINVAL;
850 : : }
851 : :
852 : 0 : model = cnxk_mldev->mldev->data->models[model_id];
853 [ # # ]: 0 : if (model == NULL) {
854 : 0 : plt_err("Invalid model_id = %u", model_id);
855 : 0 : return -EINVAL;
856 : : }
857 : :
858 : 0 : ret = cn10k_ml_model_get_layer_id(model, layer_name, &layer_id);
859 [ # # ]: 0 : if (ret != 0)
860 : : return ret;
861 : :
862 : 0 : layer = &model->layer[layer_id];
863 : : cn10k_mldev = &cnxk_mldev->cn10k_mldev;
864 : : ocm = &cn10k_mldev->ocm;
865 : :
866 : : /* Prepare JD */
867 : 0 : req = layer->glow.req;
868 : 0 : cn10k_ml_prep_sp_job_descriptor(cnxk_mldev, layer, req, ML_CN10K_JOB_TYPE_MODEL_START);
869 : 0 : req->cn10k_req.result.error_code = 0x0;
870 : 0 : req->cn10k_req.result.user_ptr = NULL;
871 : :
872 : : plt_write64(ML_CNXK_POLL_JOB_START, &req->cn10k_req.status);
873 : : plt_wmb();
874 : :
875 : 0 : num_tiles = layer->glow.metadata.model.tile_end - layer->glow.metadata.model.tile_start + 1;
876 : :
877 : : locked = false;
878 : 0 : while (!locked) {
879 [ # # ]: 0 : if (plt_spinlock_trylock(&model->lock) != 0) {
880 [ # # ]: 0 : if (layer->state == ML_CNXK_LAYER_STATE_STARTED) {
881 : 0 : plt_ml_dbg("Layer already started, model_id = %u, layer_id = %u",
882 : : model->model_id, layer_id);
883 : : plt_spinlock_unlock(&model->lock);
884 : 0 : return 1;
885 : : }
886 : :
887 [ # # ]: 0 : if (layer->state == ML_CNXK_LAYER_STATE_JOB_ACTIVE) {
888 : 0 : plt_err("A slow-path job is active for the model_id = %u",
889 : : model->model_id);
890 : : plt_spinlock_unlock(&model->lock);
891 : 0 : return -EBUSY;
892 : : }
893 : :
894 : 0 : layer->state = ML_CNXK_LAYER_STATE_JOB_ACTIVE;
895 : : plt_spinlock_unlock(&model->lock);
896 : : locked = true;
897 : : }
898 : : }
899 : :
900 [ # # ]: 0 : while (!layer->glow.ocm_map.ocm_reserved) {
901 [ # # ]: 0 : if (plt_spinlock_trylock(&ocm->lock) != 0) {
902 : 0 : wb_page_start = cn10k_ml_ocm_tilemask_find(
903 : 0 : cnxk_mldev, num_tiles, layer->glow.ocm_map.wb_pages,
904 : 0 : layer->glow.ocm_map.scratch_pages, &tilemask);
905 : :
906 [ # # ]: 0 : if (wb_page_start == -1) {
907 : 0 : plt_err("Free pages not available on OCM tiles");
908 : 0 : plt_err("Failed to start layer, model_id = %u, layer_id = %u",
909 : : model->model_id, layer_id);
910 : : plt_spinlock_unlock(&ocm->lock);
911 : 0 : return -ENOMEM;
912 : : }
913 : :
914 : 0 : layer->glow.ocm_map.tilemask = tilemask;
915 : 0 : layer->glow.ocm_map.wb_page_start = wb_page_start;
916 : :
917 : 0 : cn10k_ml_ocm_reserve_pages(
918 : 0 : cnxk_mldev, model->model_id, layer_id, layer->glow.ocm_map.tilemask,
919 : 0 : layer->glow.ocm_map.wb_page_start, layer->glow.ocm_map.wb_pages,
920 : 0 : layer->glow.ocm_map.scratch_pages);
921 : 0 : layer->glow.ocm_map.ocm_reserved = true;
922 : : plt_spinlock_unlock(&ocm->lock);
923 : : }
924 : : }
925 : :
926 : : /* Update JD */
927 : 0 : cn10k_ml_ocm_tilecount(layer->glow.ocm_map.tilemask, &tile_start, &tile_end);
928 : 0 : req->cn10k_req.jd.model_start.tilemask = GENMASK_ULL(tile_end, tile_start);
929 : 0 : req->cn10k_req.jd.model_start.ocm_wb_base_address =
930 : 0 : layer->glow.ocm_map.wb_page_start * ocm->page_size;
931 : :
932 : : job_enqueued = false;
933 : : job_dequeued = false;
934 : : do {
935 [ # # ]: 0 : if (!job_enqueued) {
936 : 0 : req->timeout = plt_tsc_cycles() + ML_CNXK_CMD_TIMEOUT * plt_tsc_hz();
937 : : job_enqueued =
938 : 0 : roc_ml_scratch_enqueue(&cn10k_mldev->roc, &req->cn10k_req.jd);
939 : : }
940 : :
941 [ # # ]: 0 : if (job_enqueued && !job_dequeued)
942 : : job_dequeued =
943 : 0 : roc_ml_scratch_dequeue(&cn10k_mldev->roc, &req->cn10k_req.jd);
944 : :
945 [ # # ]: 0 : if (job_dequeued)
946 : : break;
947 [ # # ]: 0 : } while (plt_tsc_cycles() < req->timeout);
948 : :
949 [ # # ]: 0 : if (job_dequeued) {
950 [ # # ]: 0 : if (plt_read64(&req->cn10k_req.status) == ML_CNXK_POLL_JOB_FINISH) {
951 [ # # ]: 0 : if (req->cn10k_req.result.error_code == 0)
952 : : ret = 0;
953 : : else
954 : : ret = -1;
955 : : }
956 : : } else { /* Reset scratch registers */
957 : 0 : roc_ml_scratch_queue_reset(&cn10k_mldev->roc);
958 : : ret = -ETIME;
959 : : }
960 : :
961 : : locked = false;
962 : 0 : while (!locked) {
963 [ # # ]: 0 : if (plt_spinlock_trylock(&model->lock) != 0) {
964 [ # # ]: 0 : if (ret == 0)
965 : 0 : layer->state = ML_CNXK_LAYER_STATE_STARTED;
966 : : else
967 : 0 : layer->state = ML_CNXK_LAYER_STATE_UNKNOWN;
968 : :
969 : : plt_spinlock_unlock(&model->lock);
970 : : locked = true;
971 : : }
972 : : }
973 : :
974 [ # # ]: 0 : if (layer->state == ML_CNXK_LAYER_STATE_UNKNOWN) {
975 [ # # ]: 0 : while (layer->glow.ocm_map.ocm_reserved) {
976 [ # # ]: 0 : if (plt_spinlock_trylock(&ocm->lock) != 0) {
977 : 0 : cn10k_ml_ocm_free_pages(cnxk_mldev, model->model_id, layer_id);
978 : 0 : layer->glow.ocm_map.ocm_reserved = false;
979 : 0 : layer->glow.ocm_map.tilemask = 0x0;
980 : : plt_spinlock_unlock(&ocm->lock);
981 : : }
982 : : }
983 : : }
984 : :
985 [ # # ]: 0 : if (ret < 0) {
986 : 0 : cn10k_ml_layer_stop(device, model_id, layer_name);
987 : : } else {
988 [ # # # # ]: 0 : if (cn10k_mldev->cache_model_data && model->type == ML_CNXK_MODEL_TYPE_GLOW)
989 : 0 : ret = cn10k_ml_cache_model_data(cnxk_mldev, layer);
990 : : }
991 : :
992 : : return ret;
993 : : }
994 : :
995 : : int
996 : 0 : cn10k_ml_model_start(struct cnxk_ml_dev *cnxk_mldev, struct cnxk_ml_model *model)
997 : : {
998 : : struct cnxk_ml_layer *layer;
999 : : int ret;
1000 : :
1001 : : layer = &model->layer[0];
1002 : 0 : ret = cn10k_ml_layer_start(cnxk_mldev, model->model_id, layer->name);
1003 [ # # ]: 0 : if (ret != 0) {
1004 : 0 : plt_err("CN10K Model start failed, model_id = %u, error = %d", model->model_id,
1005 : : ret);
1006 : 0 : return ret;
1007 : : }
1008 : :
1009 : 0 : cnxk_mldev->nb_models_started++;
1010 : 0 : model->state = ML_CNXK_MODEL_STATE_STARTED;
1011 : :
1012 : 0 : return 0;
1013 : : }
1014 : :
1015 : : int
1016 : 0 : cn10k_ml_layer_stop(void *device, uint16_t model_id, const char *layer_name)
1017 : : {
1018 : : struct cn10k_ml_dev *cn10k_mldev;
1019 : : struct cnxk_ml_dev *cnxk_mldev;
1020 : : struct cnxk_ml_model *model;
1021 : : struct cnxk_ml_layer *layer;
1022 : : struct cn10k_ml_ocm *ocm;
1023 : : struct cnxk_ml_req *req;
1024 : :
1025 : : uint16_t layer_id;
1026 : : bool job_enqueued;
1027 : : bool job_dequeued;
1028 : : bool locked;
1029 : : int ret = 0;
1030 : :
1031 : : cnxk_mldev = (struct cnxk_ml_dev *)device;
1032 [ # # ]: 0 : if (cnxk_mldev == NULL) {
1033 : 0 : plt_err("Invalid device = %p", device);
1034 : 0 : return -EINVAL;
1035 : : }
1036 : :
1037 : 0 : model = cnxk_mldev->mldev->data->models[model_id];
1038 [ # # ]: 0 : if (model == NULL) {
1039 : 0 : plt_err("Invalid model_id = %u", model_id);
1040 : 0 : return -EINVAL;
1041 : : }
1042 : :
1043 : 0 : ret = cn10k_ml_model_get_layer_id(model, layer_name, &layer_id);
1044 [ # # ]: 0 : if (ret != 0)
1045 : : return ret;
1046 : :
1047 : 0 : layer = &model->layer[layer_id];
1048 : : cn10k_mldev = &cnxk_mldev->cn10k_mldev;
1049 : : ocm = &cn10k_mldev->ocm;
1050 : :
1051 : : /* Prepare JD */
1052 : 0 : req = layer->glow.req;
1053 : 0 : cn10k_ml_prep_sp_job_descriptor(cnxk_mldev, layer, req, ML_CN10K_JOB_TYPE_MODEL_STOP);
1054 : 0 : req->cn10k_req.result.error_code = 0x0;
1055 : 0 : req->cn10k_req.result.user_ptr = NULL;
1056 : :
1057 : : plt_write64(ML_CNXK_POLL_JOB_START, &req->cn10k_req.status);
1058 : : plt_wmb();
1059 : :
1060 : : locked = false;
1061 : 0 : while (!locked) {
1062 [ # # ]: 0 : if (plt_spinlock_trylock(&model->lock) != 0) {
1063 [ # # ]: 0 : if (layer->state == ML_CNXK_LAYER_STATE_LOADED) {
1064 : 0 : plt_ml_dbg("Layer not started, model_id = %u, layer_id = %u",
1065 : : model->model_id, layer_id);
1066 : : plt_spinlock_unlock(&model->lock);
1067 : 0 : return 1;
1068 : : }
1069 : :
1070 [ # # ]: 0 : if (layer->state == ML_CNXK_LAYER_STATE_JOB_ACTIVE) {
1071 : 0 : plt_err("A slow-path job is active for the layer, model_id = %u, layer_id = %u",
1072 : : model->model_id, layer_id);
1073 : : plt_spinlock_unlock(&model->lock);
1074 : 0 : return -EBUSY;
1075 : : }
1076 : :
1077 : 0 : layer->state = ML_CNXK_LAYER_STATE_JOB_ACTIVE;
1078 : : plt_spinlock_unlock(&model->lock);
1079 : : locked = true;
1080 : : }
1081 : : }
1082 : :
1083 [ # # ]: 0 : while (layer->glow.ocm_map.ocm_reserved) {
1084 [ # # ]: 0 : if (plt_spinlock_trylock(&ocm->lock) != 0) {
1085 : 0 : cn10k_ml_ocm_free_pages(cnxk_mldev, model->model_id, layer_id);
1086 : 0 : layer->glow.ocm_map.ocm_reserved = false;
1087 : 0 : layer->glow.ocm_map.tilemask = 0x0;
1088 : : plt_spinlock_unlock(&ocm->lock);
1089 : : }
1090 : : }
1091 : :
1092 : : job_enqueued = false;
1093 : : job_dequeued = false;
1094 : : do {
1095 [ # # ]: 0 : if (!job_enqueued) {
1096 : 0 : req->timeout = plt_tsc_cycles() + ML_CNXK_CMD_TIMEOUT * plt_tsc_hz();
1097 : : job_enqueued =
1098 : 0 : roc_ml_scratch_enqueue(&cn10k_mldev->roc, &req->cn10k_req.jd);
1099 : : }
1100 : :
1101 [ # # ]: 0 : if (job_enqueued && !job_dequeued)
1102 : : job_dequeued =
1103 : 0 : roc_ml_scratch_dequeue(&cn10k_mldev->roc, &req->cn10k_req.jd);
1104 : :
1105 [ # # ]: 0 : if (job_dequeued)
1106 : : break;
1107 [ # # ]: 0 : } while (plt_tsc_cycles() < req->timeout);
1108 : :
1109 [ # # ]: 0 : if (job_dequeued) {
1110 [ # # ]: 0 : if (plt_read64(&req->cn10k_req.status) == ML_CNXK_POLL_JOB_FINISH) {
1111 [ # # ]: 0 : if (req->cn10k_req.result.error_code == 0x0)
1112 : : ret = 0;
1113 : : else
1114 : : ret = -1;
1115 : : }
1116 : : } else {
1117 : 0 : roc_ml_scratch_queue_reset(&cn10k_mldev->roc);
1118 : : ret = -ETIME;
1119 : : }
1120 : :
1121 : : locked = false;
1122 : 0 : while (!locked) {
1123 [ # # ]: 0 : if (plt_spinlock_trylock(&model->lock) != 0) {
1124 [ # # ]: 0 : if (ret == 0)
1125 : 0 : layer->state = ML_CNXK_LAYER_STATE_LOADED;
1126 : : else
1127 : 0 : layer->state = ML_CNXK_LAYER_STATE_UNKNOWN;
1128 : :
1129 : : plt_spinlock_unlock(&model->lock);
1130 : : locked = true;
1131 : : }
1132 : : }
1133 : :
1134 : : return ret;
1135 : : }
1136 : :
1137 : : int
1138 : 0 : cn10k_ml_model_stop(struct cnxk_ml_dev *cnxk_mldev, struct cnxk_ml_model *model)
1139 : : {
1140 : : struct cnxk_ml_layer *layer;
1141 : : int ret;
1142 : :
1143 : : layer = &model->layer[0];
1144 : 0 : ret = cn10k_ml_layer_stop(cnxk_mldev, model->model_id, layer->name);
1145 [ # # ]: 0 : if (ret != 0) {
1146 : 0 : plt_err("CN10K Model stop failed, model_id = %u, error = %d", model->model_id, ret);
1147 : 0 : return ret;
1148 : : }
1149 : :
1150 : 0 : cnxk_mldev->nb_models_stopped++;
1151 : 0 : model->state = ML_CNXK_MODEL_STATE_LOADED;
1152 : :
1153 : 0 : return 0;
1154 : : }
1155 : :
1156 : : int
1157 : 0 : cn10k_ml_model_params_update(struct cnxk_ml_dev *cnxk_mldev, struct cnxk_ml_model *model,
1158 : : void *buffer)
1159 : : {
1160 : : struct cnxk_ml_layer *layer;
1161 : :
1162 : : RTE_SET_USED(cnxk_mldev);
1163 : :
1164 [ # # ]: 0 : if (model->state == ML_CNXK_MODEL_STATE_UNKNOWN)
1165 : : return -1;
1166 [ # # ]: 0 : else if (model->state != ML_CNXK_MODEL_STATE_LOADED)
1167 : : return -EBUSY;
1168 : :
1169 : : layer = &model->layer[0];
1170 : :
1171 : : /* Update model weights & bias */
1172 : 0 : rte_memcpy(layer->glow.addr.wb_load_addr, buffer,
1173 [ # # ]: 0 : layer->glow.metadata.weights_bias.file_size);
1174 : :
1175 : : return 0;
1176 : : }
1177 : :
1178 : : __rte_hot void
1179 : 0 : cn10k_ml_result_update(struct cnxk_ml_dev *cnxk_mldev, int qp_id, void *request)
1180 : : {
1181 : : union cn10k_ml_error_code *error_code;
1182 : : struct cn10k_ml_layer_xstats *xstats;
1183 : : struct cn10k_ml_dev *cn10k_mldev;
1184 : : struct cn10k_ml_result *result;
1185 : : struct cnxk_ml_model *model;
1186 : : struct cnxk_ml_layer *layer;
1187 : : struct cnxk_ml_req *req;
1188 : : struct cnxk_ml_qp *qp;
1189 : : struct rte_ml_op *op;
1190 : : uint64_t hw_latency;
1191 : : uint64_t fw_latency;
1192 : : uint16_t model_id;
1193 : : uint16_t layer_id;
1194 : : uint16_t idx;
1195 : :
1196 : : req = (struct cnxk_ml_req *)request;
1197 : : result = &req->cn10k_req.result;
1198 : 0 : op = req->op;
1199 [ # # ]: 0 : if (likely(result->error_code == 0)) {
1200 : 0 : idx = req->cn10k_req.jd.hdr.model_id;
1201 : 0 : model_id = cnxk_mldev->index_map[idx].model_id;
1202 : 0 : layer_id = cnxk_mldev->index_map[idx].layer_id;
1203 : 0 : model = cnxk_mldev->mldev->data->models[model_id];
1204 : 0 : layer = &model->layer[layer_id];
1205 [ # # ]: 0 : if (likely(qp_id >= 0)) {
1206 : 0 : qp = cnxk_mldev->mldev->data->queue_pairs[qp_id];
1207 : 0 : qp->stats.dequeued_count++;
1208 : 0 : xstats = &layer->glow.burst_xstats[qp_id];
1209 : : } else {
1210 : 0 : xstats = layer->glow.sync_xstats;
1211 : : }
1212 : :
1213 [ # # ]: 0 : if (unlikely(xstats->dequeued_count == xstats->hw_reset_count)) {
1214 : 0 : xstats->hw_latency_min = UINT64_MAX;
1215 : 0 : xstats->hw_latency_max = 0;
1216 : : }
1217 : :
1218 [ # # ]: 0 : if (unlikely(xstats->dequeued_count == xstats->fw_reset_count)) {
1219 : 0 : xstats->fw_latency_min = UINT64_MAX;
1220 : 0 : xstats->fw_latency_max = 0;
1221 : : }
1222 : :
1223 : 0 : hw_latency = result->stats.hw_end - result->stats.hw_start;
1224 : 0 : fw_latency = result->stats.fw_end - result->stats.fw_start - hw_latency;
1225 : :
1226 : 0 : xstats->hw_latency_tot += hw_latency;
1227 : 0 : xstats->hw_latency_min = PLT_MIN(xstats->hw_latency_min, hw_latency);
1228 : 0 : xstats->hw_latency_max = PLT_MAX(xstats->hw_latency_max, hw_latency);
1229 : 0 : xstats->fw_latency_tot += fw_latency;
1230 : 0 : xstats->fw_latency_min = PLT_MIN(xstats->fw_latency_min, fw_latency);
1231 : 0 : xstats->fw_latency_max = PLT_MAX(xstats->fw_latency_max, fw_latency);
1232 : 0 : xstats->dequeued_count++;
1233 : :
1234 : 0 : op->impl_opaque = result->error_code;
1235 : 0 : op->status = RTE_ML_OP_STATUS_SUCCESS;
1236 : : } else {
1237 [ # # ]: 0 : if (likely(qp_id >= 0)) {
1238 : 0 : qp = cnxk_mldev->mldev->data->queue_pairs[qp_id];
1239 : 0 : qp->stats.dequeue_err_count++;
1240 : : }
1241 : :
1242 : : /* Handle driver error */
1243 : : error_code = (union cn10k_ml_error_code *)&result->error_code;
1244 [ # # ]: 0 : if (error_code->s.etype == ML_CNXK_ETYPE_DRIVER) {
1245 : : cn10k_mldev = &cnxk_mldev->cn10k_mldev;
1246 : :
1247 : : /* Check for exception */
1248 [ # # ]: 0 : if ((roc_ml_reg_read64(&cn10k_mldev->roc, ML_SCRATCH_EXCEPTION_SP_C0) !=
1249 [ # # ]: 0 : 0) ||
1250 : 0 : (roc_ml_reg_read64(&cn10k_mldev->roc, ML_SCRATCH_EXCEPTION_SP_C1) != 0))
1251 : 0 : error_code->s.stype = ML_CN10K_DRIVER_ERR_EXCEPTION;
1252 [ # # # # ]: 0 : else if ((roc_ml_reg_read64(&cn10k_mldev->roc, ML_CORE_INT_LO) != 0) ||
1253 : 0 : (roc_ml_reg_read64(&cn10k_mldev->roc, ML_CORE_INT_HI) != 0))
1254 : 0 : error_code->s.stype = ML_CN10K_DRIVER_ERR_FW_ERROR;
1255 : : else
1256 : 0 : error_code->s.stype = ML_CN10K_DRIVER_ERR_UNKNOWN;
1257 : : }
1258 : :
1259 : 0 : op->impl_opaque = result->error_code;
1260 : 0 : op->status = RTE_ML_OP_STATUS_ERROR;
1261 : : }
1262 : :
1263 : 0 : op->user_ptr = result->user_ptr;
1264 : 0 : }
1265 : :
1266 : : __rte_hot void
1267 : 0 : cn10k_ml_set_error_code(struct cnxk_ml_req *req, uint64_t etype, uint64_t stype)
1268 : : {
1269 : : union cn10k_ml_error_code *error_code;
1270 : :
1271 : : error_code = (union cn10k_ml_error_code *)&req->cn10k_req.result.error_code;
1272 : 0 : error_code->s.etype = etype;
1273 : 0 : error_code->s.stype = stype;
1274 : 0 : }
1275 : :
1276 : : __rte_hot bool
1277 : 0 : cn10k_ml_enqueue_single(struct cnxk_ml_dev *cnxk_mldev, struct rte_ml_op *op, uint16_t layer_id,
1278 : : struct cnxk_ml_qp *qp, uint64_t head)
1279 : : {
1280 : : union cn10k_ml_error_code *error_code;
1281 : : struct cn10k_ml_dev *cn10k_mldev;
1282 : : struct cnxk_ml_model *model;
1283 : : struct cnxk_ml_queue *queue;
1284 : : struct cnxk_ml_req *req;
1285 : :
1286 : : cn10k_mldev = &cnxk_mldev->cn10k_mldev;
1287 : : queue = &qp->queue;
1288 : 0 : req = &queue->reqs[head];
1289 : :
1290 : 0 : model = cnxk_mldev->mldev->data->models[op->model_id];
1291 : 0 : model->set_poll_addr(req);
1292 : 0 : cn10k_ml_prep_fp_job_descriptor(cnxk_mldev, req, model->layer[layer_id].index,
1293 : 0 : op->input[0]->addr, op->output[0]->addr, op->nb_batches);
1294 : :
1295 : : memset(&req->cn10k_req.result, 0, sizeof(struct cn10k_ml_result));
1296 : : error_code = (union cn10k_ml_error_code *)&req->cn10k_req.result.error_code;
1297 : 0 : error_code->s.etype = ML_CNXK_ETYPE_UNKNOWN;
1298 : 0 : req->cn10k_req.result.user_ptr = op->user_ptr;
1299 : :
1300 : 0 : cnxk_ml_set_poll_ptr(req);
1301 [ # # ]: 0 : if (unlikely(!cn10k_mldev->ml_jcmdq_enqueue(&cn10k_mldev->roc, &req->cn10k_req.jcmd)))
1302 : : return false;
1303 : :
1304 : 0 : req->timeout = plt_tsc_cycles() + queue->wait_cycles;
1305 : 0 : req->op = op;
1306 : :
1307 : 0 : return true;
1308 : : }
1309 : :
1310 : : __rte_hot int
1311 : 0 : cn10k_ml_op_error_get(struct rte_ml_dev *dev, struct rte_ml_op *op, struct rte_ml_op_error *error)
1312 : : {
1313 : : union cn10k_ml_error_code *error_code;
1314 : :
1315 : : PLT_SET_USED(dev);
1316 : :
1317 : : error_code = (union cn10k_ml_error_code *)&op->impl_opaque;
1318 : :
1319 : : /* Copy sub error message */
1320 [ # # ]: 0 : if (error_code->s.etype == ML_CNXK_ETYPE_HW_NONFATAL) {
1321 [ # # ]: 0 : if (error_code->s.stype < PLT_DIM(ml_stype_db_hw_nf))
1322 : 0 : snprintf(error->message, RTE_ML_STR_MAX, "%s : %s",
1323 : 0 : ml_etype_db[error_code->s.etype].str,
1324 : 0 : ml_stype_db_hw_nf[error_code->s.stype].str);
1325 : : else
1326 : 0 : snprintf(error->message, RTE_ML_STR_MAX, "%s : UNKNOWN ERROR",
1327 : 0 : ml_etype_db[error_code->s.etype].str);
1328 [ # # ]: 0 : } else if (error_code->s.etype == ML_CNXK_ETYPE_DRIVER) {
1329 : 0 : snprintf(error->message, RTE_ML_STR_MAX, "%s : %s",
1330 : 0 : ml_etype_db[error_code->s.etype].str,
1331 : 0 : ml_stype_db_driver[error_code->s.stype].str);
1332 : : } else {
1333 : 0 : snprintf(error->message, RTE_ML_STR_MAX, "%s",
1334 : 0 : ml_etype_db[error_code->s.etype].str);
1335 : : }
1336 : :
1337 : 0 : error->errcode = error_code->u64;
1338 : :
1339 : 0 : return 0;
1340 : : }
1341 : :
1342 : : __rte_hot int
1343 : 0 : cn10k_ml_inference_sync(void *device, uint16_t index, void *input, void *output,
1344 : : uint16_t nb_batches)
1345 : : {
1346 : : union cn10k_ml_error_code *error_code;
1347 : : struct cn10k_ml_dev *cn10k_mldev;
1348 : : struct cnxk_ml_dev *cnxk_mldev;
1349 : : struct cnxk_ml_model *model;
1350 : : struct cnxk_ml_layer *layer;
1351 : : struct cnxk_ml_req *req;
1352 : : struct rte_ml_op op;
1353 : : uint16_t model_id;
1354 : : uint16_t layer_id;
1355 : : bool timeout;
1356 : : int ret = 0;
1357 : :
1358 : : cnxk_mldev = (struct cnxk_ml_dev *)device;
1359 : : cn10k_mldev = &cnxk_mldev->cn10k_mldev;
1360 : 0 : model_id = cnxk_mldev->index_map[index].model_id;
1361 : 0 : layer_id = cnxk_mldev->index_map[index].layer_id;
1362 : 0 : model = cnxk_mldev->mldev->data->models[model_id];
1363 : 0 : layer = &model->layer[layer_id];
1364 : 0 : req = layer->glow.req;
1365 : :
1366 : 0 : op.model_id = index;
1367 : 0 : op.impl_opaque = 0;
1368 : :
1369 : 0 : cn10k_ml_set_poll_addr(req);
1370 : : cn10k_ml_prep_fp_job_descriptor(cnxk_mldev, req, index, input, output, nb_batches);
1371 : :
1372 : : memset(&req->cn10k_req.result, 0, sizeof(struct cn10k_ml_result));
1373 : : error_code = (union cn10k_ml_error_code *)&req->cn10k_req.result.error_code;
1374 : 0 : error_code->s.etype = ML_CNXK_ETYPE_UNKNOWN;
1375 : : req->cn10k_req.result.user_ptr = NULL;
1376 : :
1377 : 0 : cnxk_ml_set_poll_ptr(req);
1378 : 0 : req->cn10k_req.jcmd.w1.s.jobptr = PLT_U64_CAST(&req->cn10k_req.jd);
1379 : :
1380 : : timeout = true;
1381 : 0 : req->timeout = plt_tsc_cycles() + ML_CNXK_CMD_TIMEOUT * plt_tsc_hz();
1382 : : do {
1383 [ # # ]: 0 : if (cn10k_mldev->ml_jcmdq_enqueue(&cn10k_mldev->roc, &req->cn10k_req.jcmd)) {
1384 : 0 : req->op = &op;
1385 : : timeout = false;
1386 : : break;
1387 : : }
1388 [ # # ]: 0 : } while (plt_tsc_cycles() < req->timeout);
1389 : :
1390 : : if (timeout) {
1391 : : ret = -EBUSY;
1392 : 0 : goto error_enqueue;
1393 : : }
1394 : :
1395 : : timeout = true;
1396 : : do {
1397 [ # # ]: 0 : if (cnxk_ml_get_poll_ptr(req) == ML_CNXK_POLL_JOB_FINISH) {
1398 : : timeout = false;
1399 : : break;
1400 : : }
1401 [ # # ]: 0 : } while (plt_tsc_cycles() < req->timeout);
1402 : :
1403 [ # # ]: 0 : if (timeout)
1404 : : ret = -ETIME;
1405 : : else
1406 : 0 : cn10k_ml_result_update(cnxk_mldev, -1, req);
1407 : :
1408 : 0 : error_enqueue:
1409 : 0 : return ret;
1410 : : }
1411 : :
1412 : : int
1413 : 0 : cn10k_ml_io_alloc(void *device, uint16_t model_id, const char *layer_name, uint64_t **input_qbuffer,
1414 : : uint64_t **output_qbuffer)
1415 : : {
1416 : : struct cnxk_ml_dev *cnxk_mldev;
1417 : : struct cnxk_ml_model *model;
1418 : : struct cnxk_ml_layer *layer;
1419 : :
1420 : : char str[RTE_MEMZONE_NAMESIZE];
1421 : : const struct plt_memzone *mz;
1422 : : uint64_t output_size;
1423 : : uint64_t input_size;
1424 : : uint16_t layer_id;
1425 : : int ret;
1426 : :
1427 : : cnxk_mldev = (struct cnxk_ml_dev *)device;
1428 [ # # ]: 0 : if (cnxk_mldev == NULL) {
1429 : 0 : plt_err("Invalid device = %p", device);
1430 : 0 : return -EINVAL;
1431 : : }
1432 : :
1433 : 0 : model = cnxk_mldev->mldev->data->models[model_id];
1434 [ # # ]: 0 : if (model == NULL) {
1435 : 0 : plt_err("Invalid model_id = %u", model_id);
1436 : 0 : return -EINVAL;
1437 : : }
1438 : :
1439 : 0 : ret = cn10k_ml_model_get_layer_id(model, layer_name, &layer_id);
1440 [ # # ]: 0 : if (ret != 0)
1441 : : return ret;
1442 : :
1443 : 0 : layer = &model->layer[layer_id];
1444 : 0 : input_size = PLT_ALIGN_CEIL(layer->info.total_input_sz_q, ML_CN10K_ALIGN_SIZE);
1445 : 0 : output_size = PLT_ALIGN_CEIL(layer->info.total_output_sz_q, ML_CN10K_ALIGN_SIZE);
1446 : :
1447 : 0 : sprintf(str, "cn10k_ml_io_mz_%u_%u", model_id, layer_id);
1448 : 0 : mz = plt_memzone_reserve_aligned(str, input_size + output_size, 0, ML_CN10K_ALIGN_SIZE);
1449 [ # # ]: 0 : if (mz == NULL) {
1450 : 0 : plt_err("io_alloc failed: Unable to allocate memory: model_id = %u, layer_name = %s",
1451 : : model_id, layer_name);
1452 : 0 : return -ENOMEM;
1453 : : }
1454 : :
1455 : 0 : *input_qbuffer = mz->addr;
1456 : 0 : *output_qbuffer = PLT_PTR_ADD(mz->addr, input_size);
1457 : :
1458 : 0 : return 0;
1459 : : }
1460 : :
1461 : : int
1462 : 0 : cn10k_ml_io_free(void *device, uint16_t model_id, const char *layer_name)
1463 : : {
1464 : : struct cnxk_ml_dev *cnxk_mldev;
1465 : : struct cnxk_ml_model *model;
1466 : :
1467 : : char str[RTE_MEMZONE_NAMESIZE];
1468 : : const struct plt_memzone *mz;
1469 : : uint16_t layer_id;
1470 : : int ret;
1471 : :
1472 : : cnxk_mldev = (struct cnxk_ml_dev *)device;
1473 [ # # ]: 0 : if (cnxk_mldev == NULL) {
1474 : 0 : plt_err("Invalid device = %p", device);
1475 : 0 : return -EINVAL;
1476 : : }
1477 : :
1478 : 0 : model = cnxk_mldev->mldev->data->models[model_id];
1479 [ # # ]: 0 : if (model == NULL) {
1480 : 0 : plt_err("Invalid model_id = %u", model_id);
1481 : 0 : return -EINVAL;
1482 : : }
1483 : :
1484 : 0 : ret = cn10k_ml_model_get_layer_id(model, layer_name, &layer_id);
1485 [ # # ]: 0 : if (ret != 0)
1486 : : return ret;
1487 : :
1488 : 0 : sprintf(str, "cn10k_ml_io_mz_%u_%u", model_id, layer_id);
1489 : 0 : mz = plt_memzone_lookup(str);
1490 [ # # ]: 0 : if (mz == NULL) {
1491 : 0 : plt_err("io_free failed: Memzone not found: model_id = %u, layer_name = %s",
1492 : : model_id, layer_name);
1493 : 0 : return -EINVAL;
1494 : : }
1495 : :
1496 : 0 : return plt_memzone_free(mz);
1497 : : }
1498 : :
1499 : : int
1500 : 0 : cn10k_ml_malloc(const char *name, size_t size, uint32_t align, void **addr)
1501 : : {
1502 : : const struct plt_memzone *mz;
1503 : :
1504 : 0 : mz = plt_memzone_reserve_aligned(name, size, 0, align);
1505 [ # # ]: 0 : if (mz == NULL) {
1506 : 0 : plt_err("ml_malloc failed: Unable to allocate memory: name = %s", name);
1507 : 0 : return -ENOMEM;
1508 : : }
1509 : :
1510 : 0 : *addr = mz->addr;
1511 : :
1512 : 0 : return 0;
1513 : : }
1514 : :
1515 : : int
1516 : 0 : cn10k_ml_free(const char *name)
1517 : : {
1518 : : const struct plt_memzone *mz;
1519 : :
1520 : 0 : mz = plt_memzone_lookup(name);
1521 [ # # ]: 0 : if (mz == NULL) {
1522 : 0 : plt_err("ml_free failed: Memzone not found: name = %s", name);
1523 : 0 : return -EINVAL;
1524 : : }
1525 : :
1526 : 0 : return plt_memzone_free(mz);
1527 : : }
|