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 cn10k_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 cn10k_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 : : struct cn10k_ml_layer_xstats *xstats;
292 : : char str[RTE_MEMZONE_NAMESIZE];
293 : : const struct plt_memzone *mz;
294 : : uint64_t isize = 0;
295 : : uint64_t osize = 0;
296 : : int ret = 0;
297 : :
298 : : /* Create input and output buffers. */
299 : 0 : isize = layer->info.total_input_sz_q;
300 : 0 : osize = layer->info.total_output_sz_q;
301 : :
302 : 0 : snprintf(str, RTE_MEMZONE_NAMESIZE, "%s_%u", "ml_dummy_io", layer->index);
303 : 0 : mz = plt_memzone_reserve_aligned(str, isize + osize, 0, ML_CN10K_ALIGN_SIZE);
304 [ # # ]: 0 : if (mz == NULL)
305 : : return -ENOMEM;
306 : 0 : memset(mz->addr, 0, isize + osize);
307 : :
308 : 0 : memset(layer->glow.req, 0, sizeof(struct cnxk_ml_req));
309 : 0 : ret = cn10k_ml_inference_sync(cnxk_mldev, layer->index, mz->addr,
310 : 0 : PLT_PTR_ADD(mz->addr, isize), 1);
311 : 0 : plt_memzone_free(mz);
312 : :
313 : : /* Reset sync xstats. */
314 : 0 : xstats = layer->glow.sync_xstats;
315 : 0 : xstats->hw_latency_tot = 0;
316 : 0 : xstats->hw_latency_min = UINT64_MAX;
317 : 0 : xstats->hw_latency_max = 0;
318 : 0 : xstats->fw_latency_tot = 0;
319 : 0 : xstats->fw_latency_min = UINT64_MAX;
320 : 0 : xstats->fw_latency_max = 0;
321 : 0 : xstats->dequeued_count = 0;
322 : :
323 : 0 : return ret;
324 : : }
325 : :
326 : : int
327 : 0 : cn10k_ml_dev_info_get(struct cnxk_ml_dev *cnxk_mldev, struct rte_ml_dev_info *dev_info)
328 : : {
329 : : struct cn10k_ml_dev *cn10k_mldev;
330 : :
331 : : cn10k_mldev = &cnxk_mldev->cn10k_mldev;
332 : :
333 [ # # ]: 0 : if (cn10k_mldev->hw_queue_lock)
334 : 0 : dev_info->max_queue_pairs = ML_CN10K_MAX_QP_PER_DEVICE_SL;
335 : : else
336 : 0 : dev_info->max_queue_pairs = ML_CN10K_MAX_QP_PER_DEVICE_LF;
337 : :
338 : 0 : dev_info->max_desc = ML_CN10K_MAX_DESC_PER_QP;
339 : 0 : dev_info->max_io = ML_CN10K_MAX_INPUT_OUTPUT;
340 : 0 : dev_info->max_segments = ML_CN10K_MAX_SEGMENTS;
341 : 0 : dev_info->align_size = ML_CN10K_ALIGN_SIZE;
342 : :
343 : 0 : return 0;
344 : : }
345 : :
346 : : int
347 : 0 : cn10k_ml_dev_configure(struct cnxk_ml_dev *cnxk_mldev, const struct rte_ml_dev_config *conf)
348 : : {
349 : : struct cn10k_ml_dev *cn10k_mldev;
350 : : struct cn10k_ml_ocm *ocm;
351 : : uint16_t tile_id;
352 : :
353 : : RTE_SET_USED(conf);
354 : :
355 : : cn10k_mldev = &cnxk_mldev->cn10k_mldev;
356 : :
357 : : ocm = &cn10k_mldev->ocm;
358 : 0 : ocm->num_tiles = ML_CN10K_OCM_NUMTILES;
359 : 0 : ocm->size_per_tile = ML_CN10K_OCM_TILESIZE;
360 : 0 : ocm->page_size = cn10k_mldev->ocm_page_size;
361 : 0 : ocm->num_pages = ocm->size_per_tile / ocm->page_size;
362 : 0 : ocm->mask_words = ocm->num_pages / (8 * sizeof(uint8_t));
363 : :
364 : : /* Allocate memory for ocm_mask */
365 : 0 : ocm->ocm_mask =
366 : 0 : rte_zmalloc("ocm_mask", ocm->mask_words * ocm->num_tiles, RTE_CACHE_LINE_SIZE);
367 [ # # ]: 0 : if (ocm->ocm_mask == NULL) {
368 : 0 : plt_err("Unable to allocate memory for OCM mask");
369 : 0 : return -ENOMEM;
370 : : }
371 : :
372 [ # # ]: 0 : for (tile_id = 0; tile_id < ocm->num_tiles; tile_id++) {
373 : 0 : ocm->tile_ocm_info[tile_id].ocm_mask = ocm->ocm_mask + tile_id * ocm->mask_words;
374 : 0 : ocm->tile_ocm_info[tile_id].last_wb_page = -1;
375 : : }
376 : :
377 : : rte_spinlock_init(&ocm->lock);
378 : :
379 : : /* Set JCMDQ enqueue function */
380 [ # # ]: 0 : if (cn10k_mldev->hw_queue_lock == 1)
381 : 0 : cn10k_mldev->ml_jcmdq_enqueue = roc_ml_jcmdq_enqueue_sl;
382 : : else
383 : 0 : cn10k_mldev->ml_jcmdq_enqueue = roc_ml_jcmdq_enqueue_lf;
384 : :
385 : : return 0;
386 : : }
387 : :
388 : : int
389 : 0 : cn10k_ml_dev_close(struct cnxk_ml_dev *cnxk_mldev)
390 : : {
391 : : struct cn10k_ml_dev *cn10k_mldev;
392 : :
393 : : cn10k_mldev = &cnxk_mldev->cn10k_mldev;
394 : :
395 : : /* Release ocm_mask memory */
396 : 0 : rte_free(cn10k_mldev->ocm.ocm_mask);
397 : :
398 : : /* Unload firmware */
399 : 0 : cn10k_ml_fw_unload(cnxk_mldev);
400 : :
401 : : /* Clear scratch registers */
402 : 0 : roc_ml_reg_write64(&cn10k_mldev->roc, 0, ML_SCRATCH_WORK_PTR);
403 : 0 : roc_ml_reg_write64(&cn10k_mldev->roc, 0, ML_SCRATCH_FW_CTRL);
404 : 0 : roc_ml_reg_write64(&cn10k_mldev->roc, 0, ML_SCRATCH_DBG_BUFFER_HEAD_C0);
405 : 0 : roc_ml_reg_write64(&cn10k_mldev->roc, 0, ML_SCRATCH_DBG_BUFFER_TAIL_C0);
406 : 0 : roc_ml_reg_write64(&cn10k_mldev->roc, 0, ML_SCRATCH_DBG_BUFFER_HEAD_C1);
407 : 0 : roc_ml_reg_write64(&cn10k_mldev->roc, 0, ML_SCRATCH_DBG_BUFFER_TAIL_C1);
408 : :
409 : : /* Reset ML_MLR_BASE */
410 : 0 : roc_ml_reg_write64(&cn10k_mldev->roc, 0, ML_MLR_BASE);
411 : 0 : plt_ml_dbg("ML_MLR_BASE = 0x%016lx", roc_ml_reg_read64(&cn10k_mldev->roc, ML_MLR_BASE));
412 : :
413 : 0 : return 0;
414 : : }
415 : :
416 : : int
417 : 0 : cn10k_ml_dev_start(struct cnxk_ml_dev *cnxk_mldev)
418 : : {
419 : : struct cn10k_ml_dev *cn10k_mldev;
420 : : uint64_t reg_val64;
421 : :
422 : : cn10k_mldev = &cnxk_mldev->cn10k_mldev;
423 : :
424 : 0 : reg_val64 = roc_ml_reg_read64(&cn10k_mldev->roc, ML_CFG);
425 : 0 : reg_val64 |= ROC_ML_CFG_ENA;
426 : 0 : roc_ml_reg_write64(&cn10k_mldev->roc, reg_val64, ML_CFG);
427 : 0 : plt_ml_dbg("ML_CFG => 0x%016lx", roc_ml_reg_read64(&cn10k_mldev->roc, ML_CFG));
428 : :
429 : 0 : return 0;
430 : : }
431 : :
432 : : int
433 : 0 : cn10k_ml_dev_stop(struct cnxk_ml_dev *cnxk_mldev)
434 : : {
435 : : struct cn10k_ml_dev *cn10k_mldev;
436 : : uint64_t reg_val64;
437 : :
438 : : cn10k_mldev = &cnxk_mldev->cn10k_mldev;
439 : :
440 : 0 : reg_val64 = roc_ml_reg_read64(&cn10k_mldev->roc, ML_CFG);
441 : 0 : reg_val64 &= ~ROC_ML_CFG_ENA;
442 : 0 : roc_ml_reg_write64(&cn10k_mldev->roc, reg_val64, ML_CFG);
443 : 0 : plt_ml_dbg("ML_CFG => 0x%016lx", roc_ml_reg_read64(&cn10k_mldev->roc, ML_CFG));
444 : :
445 : 0 : return 0;
446 : : }
447 : :
448 : : int
449 : 0 : cn10k_ml_dev_dump(struct cnxk_ml_dev *cnxk_mldev, FILE *fp)
450 : : {
451 : : struct cn10k_ml_dev *cn10k_mldev;
452 : : struct cn10k_ml_fw *fw;
453 : :
454 : : uint32_t head_loc;
455 : : uint32_t tail_loc;
456 : : uint32_t bufsize;
457 : : char *head_ptr;
458 : : int core_id;
459 : :
460 : : cn10k_mldev = &cnxk_mldev->cn10k_mldev;
461 : : fw = &cn10k_mldev->fw;
462 : :
463 : : /* Dump OCM state */
464 : 0 : cn10k_ml_ocm_print(cnxk_mldev, fp);
465 : :
466 [ # # ]: 0 : if (roc_env_is_asim())
467 : : return 0;
468 : :
469 : : /* Dump debug buffer */
470 [ # # ]: 0 : for (core_id = 0; core_id <= 1; core_id++) {
471 : 0 : bufsize = fw->req->cn10k_req.jd.fw_load.debug.debug_buffer_size;
472 [ # # ]: 0 : if (core_id == 0) {
473 : 0 : head_loc =
474 : 0 : roc_ml_reg_read64(&cn10k_mldev->roc, ML_SCRATCH_DBG_BUFFER_HEAD_C0);
475 : 0 : tail_loc =
476 : 0 : roc_ml_reg_read64(&cn10k_mldev->roc, ML_SCRATCH_DBG_BUFFER_TAIL_C0);
477 : 0 : head_ptr =
478 : 0 : PLT_PTR_CAST(fw->req->cn10k_req.jd.fw_load.debug.core0_debug_ptr);
479 : 0 : head_ptr = roc_ml_addr_mlip2ap(&cn10k_mldev->roc, head_ptr);
480 : : } else {
481 : 0 : head_loc =
482 : 0 : roc_ml_reg_read64(&cn10k_mldev->roc, ML_SCRATCH_DBG_BUFFER_HEAD_C1);
483 : 0 : tail_loc =
484 : 0 : roc_ml_reg_read64(&cn10k_mldev->roc, ML_SCRATCH_DBG_BUFFER_TAIL_C1);
485 : 0 : head_ptr =
486 : 0 : PLT_PTR_CAST(fw->req->cn10k_req.jd.fw_load.debug.core1_debug_ptr);
487 : 0 : head_ptr = roc_ml_addr_mlip2ap(&cn10k_mldev->roc, head_ptr);
488 : : }
489 [ # # ]: 0 : if (head_loc < tail_loc) {
490 : 0 : fprintf(fp, "%.*s\n", tail_loc - head_loc, &head_ptr[head_loc]);
491 [ # # ]: 0 : } else if (head_loc >= tail_loc + 1) {
492 : 0 : fprintf(fp, "%.*s\n", bufsize - tail_loc, &head_ptr[head_loc]);
493 : : fprintf(fp, "%.*s\n", tail_loc, &head_ptr[0]);
494 : : }
495 : : }
496 : :
497 : : /* Dump exception info */
498 [ # # ]: 0 : for (core_id = 0; core_id <= 1; core_id++) {
499 : 0 : bufsize = fw->req->cn10k_req.jd.fw_load.debug.exception_state_size;
500 [ # # # # ]: 0 : if ((core_id == 0) &&
501 : 0 : (roc_ml_reg_read64(&cn10k_mldev->roc, ML_SCRATCH_EXCEPTION_SP_C0) != 0)) {
502 : 0 : head_ptr = PLT_PTR_CAST(
503 : : fw->req->cn10k_req.jd.fw_load.debug.core0_exception_buffer);
504 : 0 : fprintf(fp, "ML_SCRATCH_EXCEPTION_SP_C0 = 0x%016lx",
505 : : roc_ml_reg_read64(&cn10k_mldev->roc, ML_SCRATCH_EXCEPTION_SP_C0));
506 : 0 : head_ptr = roc_ml_addr_mlip2ap(&cn10k_mldev->roc, head_ptr);
507 : : fprintf(fp, "%.*s", bufsize, head_ptr);
508 [ # # # # ]: 0 : } else if ((core_id == 1) && (roc_ml_reg_read64(&cn10k_mldev->roc,
509 : : ML_SCRATCH_EXCEPTION_SP_C1) != 0)) {
510 : 0 : head_ptr = PLT_PTR_CAST(
511 : : fw->req->cn10k_req.jd.fw_load.debug.core1_exception_buffer);
512 : 0 : fprintf(fp, "ML_SCRATCH_EXCEPTION_SP_C1 = 0x%016lx",
513 : : roc_ml_reg_read64(&cn10k_mldev->roc, ML_SCRATCH_EXCEPTION_SP_C1));
514 : 0 : head_ptr = roc_ml_addr_mlip2ap(&cn10k_mldev->roc, head_ptr);
515 : : fprintf(fp, "%.*s", bufsize, head_ptr);
516 : : }
517 : : }
518 : :
519 : : return 0;
520 : : }
521 : :
522 : : int
523 : 0 : cn10k_ml_dev_selftest(struct cnxk_ml_dev *cnxk_mldev)
524 : : {
525 : : struct cn10k_ml_dev *cn10k_mldev;
526 : : const struct plt_memzone *mz;
527 : : struct cnxk_ml_req *req;
528 : : uint64_t timeout_cycle;
529 : : bool timeout;
530 : : int ret;
531 : :
532 : : cn10k_mldev = &cnxk_mldev->cn10k_mldev;
533 : 0 : mz = plt_memzone_reserve_aligned("dev_selftest", sizeof(struct cnxk_ml_req), 0,
534 : : ML_CN10K_ALIGN_SIZE);
535 [ # # ]: 0 : if (mz == NULL) {
536 : 0 : plt_err("Could not allocate reserved memzone");
537 : 0 : return -ENOMEM;
538 : : }
539 : 0 : req = mz->addr;
540 : :
541 : : /* Prepare load completion structure */
542 : 0 : memset(&req->cn10k_req.jd, 0, sizeof(struct cn10k_ml_jd));
543 : 0 : req->cn10k_req.jd.hdr.jce.w1.u64 = PLT_U64_CAST(&req->cn10k_req.status);
544 : 0 : req->cn10k_req.jd.hdr.job_type = ML_CN10K_JOB_TYPE_FIRMWARE_SELFTEST;
545 : 0 : req->cn10k_req.jd.hdr.result =
546 : 0 : roc_ml_addr_ap2mlip(&cn10k_mldev->roc, &req->cn10k_req.result);
547 : 0 : req->cn10k_req.jd.fw_load.flags = cn10k_ml_fw_flags_get(&cn10k_mldev->fw);
548 : : plt_write64(ML_CNXK_POLL_JOB_START, &req->cn10k_req.status);
549 : : plt_wmb();
550 : :
551 : : /* Enqueue firmware selftest request through scratch registers */
552 : : timeout = true;
553 : 0 : timeout_cycle = plt_tsc_cycles() + ML_CNXK_CMD_TIMEOUT * plt_tsc_hz();
554 : 0 : roc_ml_scratch_enqueue(&cn10k_mldev->roc, &req->cn10k_req.jd);
555 : :
556 : : plt_rmb();
557 : : do {
558 [ # # # # ]: 0 : if (roc_ml_scratch_is_done_bit_set(&cn10k_mldev->roc) &&
559 : : (plt_read64(&req->cn10k_req.status) == ML_CNXK_POLL_JOB_FINISH)) {
560 : : timeout = false;
561 : : break;
562 : : }
563 [ # # ]: 0 : } while (plt_tsc_cycles() < timeout_cycle);
564 : :
565 : : /* Check firmware selftest status, clean-up and exit */
566 : : ret = 0;
567 [ # # ]: 0 : if (timeout) {
568 : : ret = -ETIME;
569 : : } else {
570 [ # # ]: 0 : if (req->cn10k_req.result.error_code != 0)
571 : : ret = -1;
572 : : }
573 : :
574 : 0 : plt_memzone_free(mz);
575 : :
576 : 0 : return ret;
577 : : }
578 : :
579 : : int
580 : 0 : cn10k_ml_layer_load(void *device, uint16_t model_id, const char *layer_name, uint8_t *buffer,
581 : : size_t size, uint16_t *index)
582 : : {
583 : : struct cn10k_ml_model_metadata *metadata;
584 : : struct cnxk_ml_dev *cnxk_mldev;
585 : : struct cnxk_ml_model *model;
586 : : struct cnxk_ml_layer *layer;
587 : :
588 : : char str[RTE_MEMZONE_NAMESIZE];
589 : : const struct plt_memzone *mz;
590 : : size_t layer_object_size = 0;
591 : : size_t layer_scratch_size;
592 : : size_t layer_xstats_size;
593 : : uint8_t *base_dma_addr;
594 : : uint16_t scratch_pages;
595 : : uint16_t layer_id;
596 : : uint16_t wb_pages;
597 : : uint64_t mz_size;
598 : : uint16_t idx;
599 : : int qp_id;
600 : : int ret;
601 : :
602 : : PLT_SET_USED(size);
603 : :
604 : : cnxk_mldev = (struct cnxk_ml_dev *)device;
605 [ # # ]: 0 : if (cnxk_mldev == NULL) {
606 : 0 : plt_err("Invalid device = %p", device);
607 : 0 : return -EINVAL;
608 : : }
609 : :
610 : 0 : model = cnxk_mldev->mldev->data->models[model_id];
611 [ # # ]: 0 : if (model == NULL) {
612 : 0 : plt_err("Invalid model_id = %u", model_id);
613 : 0 : return -EINVAL;
614 : : }
615 : :
616 : 0 : ret = cn10k_ml_model_get_layer_id(model, layer_name, &layer_id);
617 [ # # ]: 0 : if (ret != 0)
618 : : return ret;
619 : :
620 : 0 : layer = &model->layer[layer_id];
621 : :
622 : 0 : ret = cn10k_ml_model_metadata_check(buffer, size);
623 [ # # ]: 0 : if (ret != 0)
624 : : return ret;
625 : :
626 : : /* Get index */
627 [ # # ]: 0 : for (idx = 0; idx < cnxk_mldev->max_nb_layers; idx++) {
628 [ # # ]: 0 : if (!cnxk_mldev->index_map[idx].active) {
629 : 0 : layer->index = idx;
630 : 0 : break;
631 : : }
632 : : }
633 : :
634 [ # # ]: 0 : if (idx >= cnxk_mldev->max_nb_layers) {
635 : 0 : plt_err("No slots available for model layers, model_id = %u, layer_id = %u",
636 : : model->model_id, layer_id);
637 : 0 : return -1;
638 : : }
639 : :
640 : 0 : layer->model = model;
641 : :
642 : : /* Get WB and scratch pages, check if model can be loaded. */
643 : 0 : ret = cn10k_ml_model_ocm_pages_count(cnxk_mldev, layer, buffer, &wb_pages, &scratch_pages);
644 [ # # ]: 0 : if (ret < 0)
645 : : return ret;
646 : :
647 : : /* Compute layer memzone size */
648 : : metadata = (struct cn10k_ml_model_metadata *)buffer;
649 : 0 : layer_object_size = metadata->init_model.file_size + metadata->main_model.file_size +
650 : 0 : metadata->finish_model.file_size + metadata->weights_bias.file_size;
651 : 0 : layer_object_size = PLT_ALIGN_CEIL(layer_object_size, ML_CN10K_ALIGN_SIZE);
652 : 0 : layer_scratch_size = PLT_ALIGN_CEIL(metadata->model.ddr_scratch_range_end -
653 : : metadata->model.ddr_scratch_range_start + 1,
654 : : ML_CN10K_ALIGN_SIZE);
655 : 0 : layer_xstats_size = (cnxk_mldev->mldev->data->nb_queue_pairs + 1) *
656 : : sizeof(struct cn10k_ml_layer_xstats);
657 : :
658 : : /* Allocate memzone for model data */
659 : 0 : mz_size = layer_object_size + layer_scratch_size +
660 : 0 : PLT_ALIGN_CEIL(sizeof(struct cnxk_ml_req), ML_CN10K_ALIGN_SIZE) +
661 : : layer_xstats_size;
662 : 0 : snprintf(str, RTE_MEMZONE_NAMESIZE, "%s_%u_%u", CN10K_ML_LAYER_MEMZONE_NAME,
663 : 0 : model->model_id, layer_id);
664 : 0 : mz = plt_memzone_reserve_aligned(str, mz_size, 0, ML_CN10K_ALIGN_SIZE);
665 [ # # ]: 0 : if (!mz) {
666 : 0 : plt_err("plt_memzone_reserve failed : %s", str);
667 : 0 : return -ENOMEM;
668 : : }
669 : :
670 : : /* Copy metadata to internal buffer */
671 [ # # ]: 0 : rte_memcpy(&layer->glow.metadata, buffer, sizeof(struct cn10k_ml_model_metadata));
672 : 0 : cn10k_ml_model_metadata_update(&layer->glow.metadata);
673 : :
674 : : /* Set layer name */
675 [ # # ]: 0 : rte_memcpy(layer->name, layer->glow.metadata.model.name, MRVL_ML_MODEL_NAME_LEN);
676 : :
677 : : /* Enable support for batch_size of 256 */
678 [ # # ]: 0 : if (layer->glow.metadata.model.batch_size == 0)
679 : 0 : layer->batch_size = 256;
680 : : else
681 : 0 : layer->batch_size = layer->glow.metadata.model.batch_size;
682 : :
683 : : /* Set DMA base address */
684 : 0 : base_dma_addr = mz->addr;
685 : 0 : cn10k_ml_layer_addr_update(layer, buffer, base_dma_addr);
686 : :
687 : : /* Set scratch base address */
688 : 0 : layer->glow.addr.scratch_base_addr = PLT_PTR_ADD(base_dma_addr, layer_object_size);
689 : :
690 : : /* Update internal I/O data structure */
691 : 0 : cn10k_ml_layer_io_info_set(&layer->info, &layer->glow.metadata);
692 : :
693 : : /* Initialize model_mem_map */
694 : 0 : memset(&layer->glow.ocm_map, 0, sizeof(struct cn10k_ml_ocm_layer_map));
695 : 0 : layer->glow.ocm_map.ocm_reserved = false;
696 : 0 : layer->glow.ocm_map.tilemask = 0;
697 : 0 : layer->glow.ocm_map.wb_page_start = -1;
698 : 0 : layer->glow.ocm_map.wb_pages = wb_pages;
699 : 0 : layer->glow.ocm_map.scratch_pages = scratch_pages;
700 : :
701 : : /* Set slow-path request address and state */
702 : 0 : layer->glow.req = PLT_PTR_ADD(mz->addr, layer_object_size + layer_scratch_size);
703 : :
704 : : /* Reset burst and sync stats */
705 : 0 : layer->glow.burst_xstats = PLT_PTR_ADD(
706 : : layer->glow.req, PLT_ALIGN_CEIL(sizeof(struct cnxk_ml_req), ML_CN10K_ALIGN_SIZE));
707 [ # # ]: 0 : for (qp_id = 0; qp_id < cnxk_mldev->mldev->data->nb_queue_pairs + 1; qp_id++) {
708 : 0 : layer->glow.burst_xstats[qp_id].hw_latency_tot = 0;
709 : 0 : layer->glow.burst_xstats[qp_id].hw_latency_min = UINT64_MAX;
710 : 0 : layer->glow.burst_xstats[qp_id].hw_latency_max = 0;
711 : 0 : layer->glow.burst_xstats[qp_id].fw_latency_tot = 0;
712 : 0 : layer->glow.burst_xstats[qp_id].fw_latency_min = UINT64_MAX;
713 : 0 : layer->glow.burst_xstats[qp_id].fw_latency_max = 0;
714 : 0 : layer->glow.burst_xstats[qp_id].hw_reset_count = 0;
715 : 0 : layer->glow.burst_xstats[qp_id].fw_reset_count = 0;
716 : 0 : layer->glow.burst_xstats[qp_id].dequeued_count = 0;
717 : : }
718 : :
719 : 0 : layer->glow.sync_xstats =
720 : 0 : PLT_PTR_ADD(layer->glow.burst_xstats, cnxk_mldev->mldev->data->nb_queue_pairs *
721 : : sizeof(struct cn10k_ml_layer_xstats));
722 : :
723 : : /* Update xstats names */
724 : 0 : cn10k_ml_xstats_layer_name_update(cnxk_mldev, model_id, layer_id);
725 : :
726 : 0 : layer->state = ML_CNXK_LAYER_STATE_LOADED;
727 : 0 : cnxk_mldev->index_map[idx].model_id = model->model_id;
728 : 0 : cnxk_mldev->index_map[idx].layer_id = layer_id;
729 : 0 : cnxk_mldev->index_map[idx].active = true;
730 : 0 : *index = idx;
731 : :
732 : 0 : return 0;
733 : : }
734 : :
735 : : int
736 : 0 : cn10k_ml_model_load(struct cnxk_ml_dev *cnxk_mldev, struct rte_ml_model_params *params,
737 : : struct cnxk_ml_model *model)
738 : : {
739 : : struct cnxk_ml_layer *layer;
740 : : int ret;
741 : :
742 : : /* Metadata check */
743 : 0 : ret = cn10k_ml_model_metadata_check(params->addr, params->size);
744 [ # # ]: 0 : if (ret != 0)
745 : : return ret;
746 : :
747 : : /* Set model sub type */
748 : 0 : model->subtype = ML_CNXK_MODEL_SUBTYPE_GLOW_MRVL;
749 : :
750 : : /* Copy metadata to internal buffer */
751 [ # # ]: 0 : rte_memcpy(&model->glow.metadata, params->addr, sizeof(struct cn10k_ml_model_metadata));
752 : 0 : cn10k_ml_model_metadata_update(&model->glow.metadata);
753 : :
754 : : /* Set model name */
755 : : rte_memcpy(model->name, (char *)model->glow.metadata.model.name, 64);
756 : :
757 : : /* Enable support for batch_size of 256 */
758 [ # # ]: 0 : if (model->glow.metadata.model.batch_size == 0)
759 : 0 : model->batch_size = 256;
760 : : else
761 : 0 : model->batch_size = model->glow.metadata.model.batch_size;
762 : :
763 : : /* Since the number of layers that the driver would be handling for glow models is
764 : : * always 1. consider the entire model as a model with single layer. This would
765 : : * ignore the num_layers from metadata.
766 : : */
767 : 0 : model->nb_layers = 1;
768 : :
769 : : /* Load layer and get the index */
770 : : layer = &model->layer[0];
771 : 0 : layer->type = ML_CNXK_LAYER_TYPE_MRVL;
772 : 0 : ret = cn10k_ml_layer_load(cnxk_mldev, model->model_id, NULL, params->addr, params->size,
773 : : &layer->index);
774 [ # # ]: 0 : if (ret != 0) {
775 : 0 : plt_err("Model layer load failed: model_id = %u, layer_id = %u", model->model_id,
776 : : 0);
777 : 0 : return ret;
778 : : }
779 : :
780 : 0 : cn10k_ml_model_info_set(cnxk_mldev, model, &model->layer[0].info, &model->glow.metadata);
781 : :
782 : : /* Set fast-path functions */
783 : 0 : model->enqueue_single = cn10k_ml_enqueue_single;
784 : 0 : model->result_update = cn10k_ml_result_update;
785 : 0 : model->set_error_code = cn10k_ml_set_error_code;
786 : 0 : model->set_poll_addr = cn10k_ml_set_poll_addr;
787 : 0 : model->op_error_get = cn10k_ml_op_error_get;
788 : :
789 : 0 : return 0;
790 : : }
791 : :
792 : : int
793 : 0 : cn10k_ml_layer_unload(void *device, uint16_t model_id, const char *layer_name)
794 : : {
795 : : struct cnxk_ml_dev *cnxk_mldev;
796 : : struct cnxk_ml_model *model;
797 : : struct cnxk_ml_layer *layer;
798 : :
799 : : char str[RTE_MEMZONE_NAMESIZE];
800 : : uint16_t layer_id;
801 : : int ret;
802 : :
803 : : cnxk_mldev = (struct cnxk_ml_dev *)device;
804 [ # # ]: 0 : if (cnxk_mldev == NULL) {
805 : 0 : plt_err("Invalid device = %p", device);
806 : 0 : return -EINVAL;
807 : : }
808 : :
809 : 0 : model = cnxk_mldev->mldev->data->models[model_id];
810 [ # # ]: 0 : if (model == NULL) {
811 : 0 : plt_err("Invalid model_id = %u", model_id);
812 : 0 : return -EINVAL;
813 : : }
814 : :
815 : 0 : ret = cn10k_ml_model_get_layer_id(model, layer_name, &layer_id);
816 [ # # ]: 0 : if (ret != 0)
817 : : return ret;
818 : :
819 : 0 : layer = &model->layer[layer_id];
820 : :
821 : 0 : snprintf(str, RTE_MEMZONE_NAMESIZE, "%s_%u_%u", CN10K_ML_LAYER_MEMZONE_NAME,
822 : 0 : model->model_id, layer_id);
823 : 0 : ret = plt_memzone_free(plt_memzone_lookup(str));
824 : :
825 : 0 : layer->state = ML_CNXK_LAYER_STATE_UNKNOWN;
826 : 0 : cnxk_mldev->index_map[layer->index].active = false;
827 : :
828 : 0 : return ret;
829 : : }
830 : :
831 : : int
832 : 0 : cn10k_ml_model_unload(struct cnxk_ml_dev *cnxk_mldev, struct cnxk_ml_model *model)
833 : : {
834 : 0 : return cn10k_ml_layer_unload(cnxk_mldev, model->model_id, NULL);
835 : : }
836 : :
837 : : int
838 : 0 : cn10k_ml_layer_start(void *device, uint16_t model_id, const char *layer_name)
839 : : {
840 : : struct cn10k_ml_dev *cn10k_mldev;
841 : : struct cnxk_ml_dev *cnxk_mldev;
842 : : struct cnxk_ml_model *model;
843 : : struct cnxk_ml_layer *layer;
844 : : struct cn10k_ml_ocm *ocm;
845 : : struct cnxk_ml_req *req;
846 : :
847 : : uint16_t layer_id;
848 : : bool job_enqueued;
849 : : bool job_dequeued;
850 : : uint8_t num_tiles;
851 : : uint64_t tilemask;
852 : : int wb_page_start;
853 : : int tile_start;
854 : : int tile_end;
855 : : bool locked;
856 : : int ret = 0;
857 : :
858 : : cnxk_mldev = (struct cnxk_ml_dev *)device;
859 [ # # ]: 0 : if (cnxk_mldev == NULL) {
860 : 0 : plt_err("Invalid device = %p", device);
861 : 0 : return -EINVAL;
862 : : }
863 : :
864 : 0 : model = cnxk_mldev->mldev->data->models[model_id];
865 [ # # ]: 0 : if (model == NULL) {
866 : 0 : plt_err("Invalid model_id = %u", model_id);
867 : 0 : return -EINVAL;
868 : : }
869 : :
870 : 0 : ret = cn10k_ml_model_get_layer_id(model, layer_name, &layer_id);
871 [ # # ]: 0 : if (ret != 0)
872 : : return ret;
873 : :
874 : 0 : layer = &model->layer[layer_id];
875 : : cn10k_mldev = &cnxk_mldev->cn10k_mldev;
876 : : ocm = &cn10k_mldev->ocm;
877 : :
878 : : /* Prepare JD */
879 : 0 : req = layer->glow.req;
880 : 0 : cn10k_ml_prep_sp_job_descriptor(cnxk_mldev, layer, req, ML_CN10K_JOB_TYPE_MODEL_START);
881 : 0 : req->cn10k_req.result.error_code = 0x0;
882 : 0 : req->cn10k_req.result.user_ptr = NULL;
883 : :
884 : : plt_write64(ML_CNXK_POLL_JOB_START, &req->cn10k_req.status);
885 : : plt_wmb();
886 : :
887 : 0 : num_tiles = layer->glow.metadata.model.tile_end - layer->glow.metadata.model.tile_start + 1;
888 : :
889 : : locked = false;
890 : 0 : while (!locked) {
891 [ # # ]: 0 : if (plt_spinlock_trylock(&model->lock) != 0) {
892 [ # # ]: 0 : if (layer->state == ML_CNXK_LAYER_STATE_STARTED) {
893 : 0 : plt_ml_dbg("Layer already started, model_id = %u, layer_id = %u",
894 : : model->model_id, layer_id);
895 : : plt_spinlock_unlock(&model->lock);
896 : 0 : return 1;
897 : : }
898 : :
899 [ # # ]: 0 : if (layer->state == ML_CNXK_LAYER_STATE_JOB_ACTIVE) {
900 : 0 : plt_err("A slow-path job is active for the model_id = %u",
901 : : model->model_id);
902 : : plt_spinlock_unlock(&model->lock);
903 : 0 : return -EBUSY;
904 : : }
905 : :
906 : 0 : layer->state = ML_CNXK_LAYER_STATE_JOB_ACTIVE;
907 : : plt_spinlock_unlock(&model->lock);
908 : : locked = true;
909 : : }
910 : : }
911 : :
912 [ # # ]: 0 : while (!layer->glow.ocm_map.ocm_reserved) {
913 [ # # ]: 0 : if (plt_spinlock_trylock(&ocm->lock) != 0) {
914 : 0 : wb_page_start = cn10k_ml_ocm_tilemask_find(
915 : 0 : cnxk_mldev, num_tiles, layer->glow.ocm_map.wb_pages,
916 : 0 : layer->glow.ocm_map.scratch_pages, &tilemask);
917 : :
918 [ # # ]: 0 : if (wb_page_start == -1) {
919 : 0 : plt_err("Free pages not available on OCM tiles");
920 : 0 : plt_err("Failed to start layer, model_id = %u, layer_id = %u",
921 : : model->model_id, layer_id);
922 : : plt_spinlock_unlock(&ocm->lock);
923 : 0 : return -ENOMEM;
924 : : }
925 : :
926 : 0 : layer->glow.ocm_map.tilemask = tilemask;
927 : 0 : layer->glow.ocm_map.wb_page_start = wb_page_start;
928 : :
929 : 0 : cn10k_ml_ocm_reserve_pages(
930 : 0 : cnxk_mldev, model->model_id, layer_id, layer->glow.ocm_map.tilemask,
931 : 0 : layer->glow.ocm_map.wb_page_start, layer->glow.ocm_map.wb_pages,
932 : 0 : layer->glow.ocm_map.scratch_pages);
933 : 0 : layer->glow.ocm_map.ocm_reserved = true;
934 : : plt_spinlock_unlock(&ocm->lock);
935 : : }
936 : : }
937 : :
938 : : /* Update JD */
939 : 0 : cn10k_ml_ocm_tilecount(layer->glow.ocm_map.tilemask, &tile_start, &tile_end);
940 : 0 : req->cn10k_req.jd.model_start.tilemask = GENMASK_ULL(tile_end, tile_start);
941 : 0 : req->cn10k_req.jd.model_start.ocm_wb_base_address =
942 : 0 : layer->glow.ocm_map.wb_page_start * ocm->page_size;
943 : :
944 : : job_enqueued = false;
945 : : job_dequeued = false;
946 : : do {
947 [ # # ]: 0 : if (!job_enqueued) {
948 : 0 : req->timeout = plt_tsc_cycles() + ML_CNXK_CMD_TIMEOUT * plt_tsc_hz();
949 : : job_enqueued =
950 : 0 : roc_ml_scratch_enqueue(&cn10k_mldev->roc, &req->cn10k_req.jd);
951 : : }
952 : :
953 [ # # ]: 0 : if (job_enqueued && !job_dequeued)
954 : : job_dequeued =
955 : 0 : roc_ml_scratch_dequeue(&cn10k_mldev->roc, &req->cn10k_req.jd);
956 : :
957 [ # # ]: 0 : if (job_dequeued)
958 : : break;
959 [ # # ]: 0 : } while (plt_tsc_cycles() < req->timeout);
960 : :
961 [ # # ]: 0 : if (job_dequeued) {
962 [ # # ]: 0 : if (plt_read64(&req->cn10k_req.status) == ML_CNXK_POLL_JOB_FINISH) {
963 [ # # ]: 0 : if (req->cn10k_req.result.error_code == 0)
964 : : ret = 0;
965 : : else
966 : : ret = -1;
967 : : }
968 : : } else { /* Reset scratch registers */
969 : 0 : roc_ml_scratch_queue_reset(&cn10k_mldev->roc);
970 : : ret = -ETIME;
971 : : }
972 : :
973 : : locked = false;
974 : 0 : while (!locked) {
975 [ # # ]: 0 : if (plt_spinlock_trylock(&model->lock) != 0) {
976 [ # # ]: 0 : if (ret == 0)
977 : 0 : layer->state = ML_CNXK_LAYER_STATE_STARTED;
978 : : else
979 : 0 : layer->state = ML_CNXK_LAYER_STATE_UNKNOWN;
980 : :
981 : : plt_spinlock_unlock(&model->lock);
982 : : locked = true;
983 : : }
984 : : }
985 : :
986 [ # # ]: 0 : if (layer->state == ML_CNXK_LAYER_STATE_UNKNOWN) {
987 [ # # ]: 0 : while (layer->glow.ocm_map.ocm_reserved) {
988 [ # # ]: 0 : if (plt_spinlock_trylock(&ocm->lock) != 0) {
989 : 0 : cn10k_ml_ocm_free_pages(cnxk_mldev, model->model_id, layer_id);
990 : 0 : layer->glow.ocm_map.ocm_reserved = false;
991 : 0 : layer->glow.ocm_map.tilemask = 0x0;
992 : : plt_spinlock_unlock(&ocm->lock);
993 : : }
994 : : }
995 : : }
996 : :
997 [ # # ]: 0 : if (ret < 0) {
998 : 0 : cn10k_ml_layer_stop(device, model_id, layer_name);
999 : : } else {
1000 [ # # ]: 0 : if (cn10k_mldev->cache_model_data)
1001 : 0 : ret = cn10k_ml_cache_model_data(cnxk_mldev, layer);
1002 : : }
1003 : :
1004 : : return ret;
1005 : : }
1006 : :
1007 : : int
1008 : 0 : cn10k_ml_model_start(struct cnxk_ml_dev *cnxk_mldev, struct cnxk_ml_model *model)
1009 : : {
1010 : : struct cnxk_ml_layer *layer;
1011 : : int ret;
1012 : :
1013 : : layer = &model->layer[0];
1014 : 0 : ret = cn10k_ml_layer_start(cnxk_mldev, model->model_id, layer->name);
1015 [ # # ]: 0 : if (ret != 0) {
1016 : 0 : plt_err("CN10K Model start failed, model_id = %u, error = %d", model->model_id,
1017 : : ret);
1018 : 0 : return ret;
1019 : : }
1020 : :
1021 : 0 : cnxk_mldev->nb_models_started++;
1022 : 0 : model->state = ML_CNXK_MODEL_STATE_STARTED;
1023 : :
1024 : 0 : return 0;
1025 : : }
1026 : :
1027 : : int
1028 : 0 : cn10k_ml_layer_stop(void *device, uint16_t model_id, const char *layer_name)
1029 : : {
1030 : : struct cn10k_ml_dev *cn10k_mldev;
1031 : : struct cnxk_ml_dev *cnxk_mldev;
1032 : : struct cnxk_ml_model *model;
1033 : : struct cnxk_ml_layer *layer;
1034 : : struct cn10k_ml_ocm *ocm;
1035 : : struct cnxk_ml_req *req;
1036 : :
1037 : : uint16_t layer_id;
1038 : : bool job_enqueued;
1039 : : bool job_dequeued;
1040 : : bool locked;
1041 : : int ret = 0;
1042 : :
1043 : : cnxk_mldev = (struct cnxk_ml_dev *)device;
1044 [ # # ]: 0 : if (cnxk_mldev == NULL) {
1045 : 0 : plt_err("Invalid device = %p", device);
1046 : 0 : return -EINVAL;
1047 : : }
1048 : :
1049 : 0 : model = cnxk_mldev->mldev->data->models[model_id];
1050 [ # # ]: 0 : if (model == NULL) {
1051 : 0 : plt_err("Invalid model_id = %u", model_id);
1052 : 0 : return -EINVAL;
1053 : : }
1054 : :
1055 : 0 : ret = cn10k_ml_model_get_layer_id(model, layer_name, &layer_id);
1056 [ # # ]: 0 : if (ret != 0)
1057 : : return ret;
1058 : :
1059 : 0 : layer = &model->layer[layer_id];
1060 : : cn10k_mldev = &cnxk_mldev->cn10k_mldev;
1061 : : ocm = &cn10k_mldev->ocm;
1062 : :
1063 : : /* Prepare JD */
1064 : 0 : req = layer->glow.req;
1065 : 0 : cn10k_ml_prep_sp_job_descriptor(cnxk_mldev, layer, req, ML_CN10K_JOB_TYPE_MODEL_STOP);
1066 : 0 : req->cn10k_req.result.error_code = 0x0;
1067 : 0 : req->cn10k_req.result.user_ptr = NULL;
1068 : :
1069 : : plt_write64(ML_CNXK_POLL_JOB_START, &req->cn10k_req.status);
1070 : : plt_wmb();
1071 : :
1072 : : locked = false;
1073 : 0 : while (!locked) {
1074 [ # # ]: 0 : if (plt_spinlock_trylock(&model->lock) != 0) {
1075 [ # # ]: 0 : if (layer->state == ML_CNXK_LAYER_STATE_LOADED) {
1076 : 0 : plt_ml_dbg("Layer not started, model_id = %u, layer_id = %u",
1077 : : model->model_id, layer_id);
1078 : : plt_spinlock_unlock(&model->lock);
1079 : 0 : return 1;
1080 : : }
1081 : :
1082 [ # # ]: 0 : if (layer->state == ML_CNXK_LAYER_STATE_JOB_ACTIVE) {
1083 : 0 : plt_err("A slow-path job is active for the layer, model_id = %u, layer_id = %u",
1084 : : model->model_id, layer_id);
1085 : : plt_spinlock_unlock(&model->lock);
1086 : 0 : return -EBUSY;
1087 : : }
1088 : :
1089 : 0 : layer->state = ML_CNXK_LAYER_STATE_JOB_ACTIVE;
1090 : : plt_spinlock_unlock(&model->lock);
1091 : : locked = true;
1092 : : }
1093 : : }
1094 : :
1095 [ # # ]: 0 : while (layer->glow.ocm_map.ocm_reserved) {
1096 [ # # ]: 0 : if (plt_spinlock_trylock(&ocm->lock) != 0) {
1097 : 0 : cn10k_ml_ocm_free_pages(cnxk_mldev, model->model_id, layer_id);
1098 : 0 : layer->glow.ocm_map.ocm_reserved = false;
1099 : 0 : layer->glow.ocm_map.tilemask = 0x0;
1100 : : plt_spinlock_unlock(&ocm->lock);
1101 : : }
1102 : : }
1103 : :
1104 : : job_enqueued = false;
1105 : : job_dequeued = false;
1106 : : do {
1107 [ # # ]: 0 : if (!job_enqueued) {
1108 : 0 : req->timeout = plt_tsc_cycles() + ML_CNXK_CMD_TIMEOUT * plt_tsc_hz();
1109 : : job_enqueued =
1110 : 0 : roc_ml_scratch_enqueue(&cn10k_mldev->roc, &req->cn10k_req.jd);
1111 : : }
1112 : :
1113 [ # # ]: 0 : if (job_enqueued && !job_dequeued)
1114 : : job_dequeued =
1115 : 0 : roc_ml_scratch_dequeue(&cn10k_mldev->roc, &req->cn10k_req.jd);
1116 : :
1117 [ # # ]: 0 : if (job_dequeued)
1118 : : break;
1119 [ # # ]: 0 : } while (plt_tsc_cycles() < req->timeout);
1120 : :
1121 [ # # ]: 0 : if (job_dequeued) {
1122 [ # # ]: 0 : if (plt_read64(&req->cn10k_req.status) == ML_CNXK_POLL_JOB_FINISH) {
1123 [ # # ]: 0 : if (req->cn10k_req.result.error_code == 0x0)
1124 : : ret = 0;
1125 : : else
1126 : : ret = -1;
1127 : : }
1128 : : } else {
1129 : 0 : roc_ml_scratch_queue_reset(&cn10k_mldev->roc);
1130 : : ret = -ETIME;
1131 : : }
1132 : :
1133 : : locked = false;
1134 : 0 : while (!locked) {
1135 [ # # ]: 0 : if (plt_spinlock_trylock(&model->lock) != 0) {
1136 [ # # ]: 0 : if (ret == 0)
1137 : 0 : layer->state = ML_CNXK_LAYER_STATE_LOADED;
1138 : : else
1139 : 0 : layer->state = ML_CNXK_LAYER_STATE_UNKNOWN;
1140 : :
1141 : : plt_spinlock_unlock(&model->lock);
1142 : : locked = true;
1143 : : }
1144 : : }
1145 : :
1146 : : return ret;
1147 : : }
1148 : :
1149 : : int
1150 : 0 : cn10k_ml_model_stop(struct cnxk_ml_dev *cnxk_mldev, struct cnxk_ml_model *model)
1151 : : {
1152 : : struct cnxk_ml_layer *layer;
1153 : : int ret;
1154 : :
1155 : : layer = &model->layer[0];
1156 : 0 : ret = cn10k_ml_layer_stop(cnxk_mldev, model->model_id, layer->name);
1157 [ # # ]: 0 : if (ret != 0) {
1158 : 0 : plt_err("CN10K Model stop failed, model_id = %u, error = %d", model->model_id, ret);
1159 : 0 : return ret;
1160 : : }
1161 : :
1162 : 0 : cnxk_mldev->nb_models_stopped++;
1163 : 0 : model->state = ML_CNXK_MODEL_STATE_LOADED;
1164 : :
1165 : 0 : return 0;
1166 : : }
1167 : :
1168 : : int
1169 : 0 : cn10k_ml_model_params_update(struct cnxk_ml_dev *cnxk_mldev, struct cnxk_ml_model *model,
1170 : : void *buffer)
1171 : : {
1172 : : struct cnxk_ml_layer *layer;
1173 : :
1174 : : RTE_SET_USED(cnxk_mldev);
1175 : :
1176 [ # # ]: 0 : if (model->state == ML_CNXK_MODEL_STATE_UNKNOWN)
1177 : : return -1;
1178 [ # # ]: 0 : else if (model->state != ML_CNXK_MODEL_STATE_LOADED)
1179 : : return -EBUSY;
1180 : :
1181 : : layer = &model->layer[0];
1182 : :
1183 : : /* Update model weights & bias */
1184 : 0 : rte_memcpy(layer->glow.addr.wb_load_addr, buffer,
1185 [ # # ]: 0 : layer->glow.metadata.weights_bias.file_size);
1186 : :
1187 : : return 0;
1188 : : }
1189 : :
1190 : : __rte_hot void
1191 : 0 : cn10k_ml_result_update(struct cnxk_ml_dev *cnxk_mldev, int qp_id, void *request)
1192 : : {
1193 : : union cn10k_ml_error_code *error_code;
1194 : : struct cn10k_ml_layer_xstats *xstats;
1195 : : struct cn10k_ml_dev *cn10k_mldev;
1196 : : struct cn10k_ml_result *result;
1197 : : struct cnxk_ml_model *model;
1198 : : struct cnxk_ml_layer *layer;
1199 : : struct cnxk_ml_req *req;
1200 : : struct cnxk_ml_qp *qp;
1201 : : struct rte_ml_op *op;
1202 : : uint64_t hw_latency;
1203 : : uint64_t fw_latency;
1204 : : uint16_t model_id;
1205 : : uint16_t layer_id;
1206 : : uint16_t idx;
1207 : :
1208 : : req = (struct cnxk_ml_req *)request;
1209 : : result = &req->cn10k_req.result;
1210 : 0 : op = req->op;
1211 [ # # ]: 0 : if (likely(result->error_code == 0)) {
1212 : 0 : idx = req->cn10k_req.jd.hdr.model_id;
1213 : 0 : model_id = cnxk_mldev->index_map[idx].model_id;
1214 : 0 : layer_id = cnxk_mldev->index_map[idx].layer_id;
1215 : 0 : model = cnxk_mldev->mldev->data->models[model_id];
1216 : 0 : layer = &model->layer[layer_id];
1217 [ # # ]: 0 : if (likely(qp_id >= 0)) {
1218 : 0 : qp = cnxk_mldev->mldev->data->queue_pairs[qp_id];
1219 : 0 : qp->stats.dequeued_count++;
1220 : 0 : xstats = &layer->glow.burst_xstats[qp_id];
1221 : : } else {
1222 : 0 : xstats = layer->glow.sync_xstats;
1223 : : }
1224 : :
1225 [ # # ]: 0 : if (unlikely(xstats->dequeued_count == xstats->hw_reset_count)) {
1226 : 0 : xstats->hw_latency_min = UINT64_MAX;
1227 : 0 : xstats->hw_latency_max = 0;
1228 : : }
1229 : :
1230 [ # # ]: 0 : if (unlikely(xstats->dequeued_count == xstats->fw_reset_count)) {
1231 : 0 : xstats->fw_latency_min = UINT64_MAX;
1232 : 0 : xstats->fw_latency_max = 0;
1233 : : }
1234 : :
1235 : 0 : hw_latency = result->stats.hw_end - result->stats.hw_start;
1236 : 0 : fw_latency = result->stats.fw_end - result->stats.fw_start - hw_latency;
1237 : :
1238 : 0 : xstats->hw_latency_tot += hw_latency;
1239 : 0 : xstats->hw_latency_min = PLT_MIN(xstats->hw_latency_min, hw_latency);
1240 : 0 : xstats->hw_latency_max = PLT_MAX(xstats->hw_latency_max, hw_latency);
1241 : 0 : xstats->fw_latency_tot += fw_latency;
1242 : 0 : xstats->fw_latency_min = PLT_MIN(xstats->fw_latency_min, fw_latency);
1243 : 0 : xstats->fw_latency_max = PLT_MAX(xstats->fw_latency_max, fw_latency);
1244 : 0 : xstats->dequeued_count++;
1245 : :
1246 : 0 : op->impl_opaque = result->error_code;
1247 : 0 : op->status = RTE_ML_OP_STATUS_SUCCESS;
1248 : : } else {
1249 [ # # ]: 0 : if (likely(qp_id >= 0)) {
1250 : 0 : qp = cnxk_mldev->mldev->data->queue_pairs[qp_id];
1251 : 0 : qp->stats.dequeue_err_count++;
1252 : : }
1253 : :
1254 : : /* Handle driver error */
1255 : : error_code = (union cn10k_ml_error_code *)&result->error_code;
1256 [ # # ]: 0 : if (error_code->s.etype == ML_CN10K_ETYPE_DRIVER) {
1257 : : cn10k_mldev = &cnxk_mldev->cn10k_mldev;
1258 : :
1259 : : /* Check for exception */
1260 [ # # ]: 0 : if ((roc_ml_reg_read64(&cn10k_mldev->roc, ML_SCRATCH_EXCEPTION_SP_C0) !=
1261 [ # # ]: 0 : 0) ||
1262 : 0 : (roc_ml_reg_read64(&cn10k_mldev->roc, ML_SCRATCH_EXCEPTION_SP_C1) != 0))
1263 : 0 : error_code->s.stype = ML_CN10K_DRIVER_ERR_EXCEPTION;
1264 [ # # # # ]: 0 : else if ((roc_ml_reg_read64(&cn10k_mldev->roc, ML_CORE_INT_LO) != 0) ||
1265 : 0 : (roc_ml_reg_read64(&cn10k_mldev->roc, ML_CORE_INT_HI) != 0))
1266 : 0 : error_code->s.stype = ML_CN10K_DRIVER_ERR_FW_ERROR;
1267 : : else
1268 : 0 : error_code->s.stype = ML_CN10K_DRIVER_ERR_UNKNOWN;
1269 : : }
1270 : :
1271 : 0 : op->impl_opaque = result->error_code;
1272 : 0 : op->status = RTE_ML_OP_STATUS_ERROR;
1273 : : }
1274 : :
1275 : 0 : op->user_ptr = result->user_ptr;
1276 : 0 : }
1277 : :
1278 : : __rte_hot void
1279 : 0 : cn10k_ml_set_error_code(struct cnxk_ml_req *req, uint64_t etype, uint64_t stype)
1280 : : {
1281 : : union cn10k_ml_error_code *error_code;
1282 : :
1283 : : error_code = (union cn10k_ml_error_code *)&req->cn10k_req.result.error_code;
1284 : 0 : error_code->s.etype = etype;
1285 : 0 : error_code->s.stype = stype;
1286 : 0 : }
1287 : :
1288 : : __rte_hot bool
1289 : 0 : cn10k_ml_enqueue_single(struct cnxk_ml_dev *cnxk_mldev, struct rte_ml_op *op, uint16_t layer_id,
1290 : : struct cnxk_ml_qp *qp, uint64_t head)
1291 : : {
1292 : : union cn10k_ml_error_code *error_code;
1293 : : struct cn10k_ml_dev *cn10k_mldev;
1294 : : struct cnxk_ml_model *model;
1295 : : struct cnxk_ml_queue *queue;
1296 : : struct cnxk_ml_req *req;
1297 : :
1298 : : cn10k_mldev = &cnxk_mldev->cn10k_mldev;
1299 : : queue = &qp->queue;
1300 : 0 : req = &queue->reqs[head];
1301 : :
1302 : 0 : model = cnxk_mldev->mldev->data->models[op->model_id];
1303 : 0 : model->set_poll_addr(req);
1304 : 0 : cn10k_ml_prep_fp_job_descriptor(cnxk_mldev, req, model->layer[layer_id].index,
1305 : 0 : op->input[0]->addr, op->output[0]->addr, op->nb_batches);
1306 : :
1307 : : memset(&req->cn10k_req.result, 0, sizeof(struct cn10k_ml_result));
1308 : : error_code = (union cn10k_ml_error_code *)&req->cn10k_req.result.error_code;
1309 : 0 : error_code->s.etype = ML_CN10K_ETYPE_UNKNOWN;
1310 : 0 : req->cn10k_req.result.user_ptr = op->user_ptr;
1311 : :
1312 : 0 : cnxk_ml_set_poll_ptr(req);
1313 [ # # ]: 0 : if (unlikely(!cn10k_mldev->ml_jcmdq_enqueue(&cn10k_mldev->roc, &req->cn10k_req.jcmd)))
1314 : : return false;
1315 : :
1316 : 0 : req->timeout = plt_tsc_cycles() + queue->wait_cycles;
1317 : 0 : req->op = op;
1318 : :
1319 : 0 : return true;
1320 : : }
1321 : :
1322 : : __rte_hot int
1323 : 0 : cn10k_ml_op_error_get(struct cnxk_ml_dev *cnxk_mldev, struct rte_ml_op *op,
1324 : : struct rte_ml_op_error *error)
1325 : : {
1326 : : union cn10k_ml_error_code *error_code;
1327 : :
1328 : : PLT_SET_USED(cnxk_mldev);
1329 : :
1330 : : error_code = (union cn10k_ml_error_code *)&op->impl_opaque;
1331 : :
1332 : : /* Copy sub error message */
1333 [ # # ]: 0 : if (error_code->s.etype == ML_CN10K_ETYPE_HW_NONFATAL) {
1334 [ # # ]: 0 : if (error_code->s.stype < PLT_DIM(ml_stype_db_hw_nf))
1335 : 0 : snprintf(error->message, RTE_ML_STR_MAX, "%s : %s",
1336 : 0 : ml_etype_db[error_code->s.etype].str,
1337 : 0 : ml_stype_db_hw_nf[error_code->s.stype].str);
1338 : : else
1339 : 0 : snprintf(error->message, RTE_ML_STR_MAX, "%s : UNKNOWN ERROR",
1340 : 0 : ml_etype_db[error_code->s.etype].str);
1341 [ # # ]: 0 : } else if (error_code->s.etype == ML_CN10K_ETYPE_DRIVER) {
1342 : 0 : snprintf(error->message, RTE_ML_STR_MAX, "%s : %s",
1343 : 0 : ml_etype_db[error_code->s.etype].str,
1344 : 0 : ml_stype_db_driver[error_code->s.stype].str);
1345 : : } else {
1346 : 0 : snprintf(error->message, RTE_ML_STR_MAX, "%s",
1347 : 0 : ml_etype_db[error_code->s.etype].str);
1348 : : }
1349 : :
1350 : 0 : error->errcode = error_code->u64;
1351 : :
1352 : 0 : return 0;
1353 : : }
1354 : :
1355 : : __rte_hot int
1356 : 0 : cn10k_ml_inference_sync(void *device, uint16_t index, void *input, void *output,
1357 : : uint16_t nb_batches)
1358 : : {
1359 : : union cn10k_ml_error_code *error_code;
1360 : : struct cn10k_ml_dev *cn10k_mldev;
1361 : : struct cnxk_ml_dev *cnxk_mldev;
1362 : : struct cnxk_ml_model *model;
1363 : : struct cnxk_ml_layer *layer;
1364 : : struct cnxk_ml_req *req;
1365 : : struct rte_ml_op op;
1366 : : uint16_t model_id;
1367 : : uint16_t layer_id;
1368 : : bool timeout;
1369 : : int ret = 0;
1370 : :
1371 : : cnxk_mldev = (struct cnxk_ml_dev *)device;
1372 : : cn10k_mldev = &cnxk_mldev->cn10k_mldev;
1373 : 0 : model_id = cnxk_mldev->index_map[index].model_id;
1374 : 0 : layer_id = cnxk_mldev->index_map[index].layer_id;
1375 : 0 : model = cnxk_mldev->mldev->data->models[model_id];
1376 : 0 : layer = &model->layer[layer_id];
1377 : 0 : req = layer->glow.req;
1378 : :
1379 : 0 : op.model_id = index;
1380 : 0 : op.impl_opaque = 0;
1381 : :
1382 : 0 : cn10k_ml_set_poll_addr(req);
1383 : : cn10k_ml_prep_fp_job_descriptor(cnxk_mldev, req, index, input, output, nb_batches);
1384 : :
1385 : : memset(&req->cn10k_req.result, 0, sizeof(struct cn10k_ml_result));
1386 : : error_code = (union cn10k_ml_error_code *)&req->cn10k_req.result.error_code;
1387 : 0 : error_code->s.etype = ML_CN10K_ETYPE_UNKNOWN;
1388 : : req->cn10k_req.result.user_ptr = NULL;
1389 : :
1390 : 0 : cnxk_ml_set_poll_ptr(req);
1391 : 0 : req->cn10k_req.jcmd.w1.s.jobptr = PLT_U64_CAST(&req->cn10k_req.jd);
1392 : :
1393 : : timeout = true;
1394 : 0 : req->timeout = plt_tsc_cycles() + ML_CNXK_CMD_TIMEOUT * plt_tsc_hz();
1395 : : do {
1396 [ # # ]: 0 : if (cn10k_mldev->ml_jcmdq_enqueue(&cn10k_mldev->roc, &req->cn10k_req.jcmd)) {
1397 : 0 : req->op = &op;
1398 : : timeout = false;
1399 : : break;
1400 : : }
1401 [ # # ]: 0 : } while (plt_tsc_cycles() < req->timeout);
1402 : :
1403 : : if (timeout) {
1404 : : ret = -EBUSY;
1405 : 0 : goto error_enqueue;
1406 : : }
1407 : :
1408 : : timeout = true;
1409 : : do {
1410 [ # # ]: 0 : if (cnxk_ml_get_poll_ptr(req) == ML_CNXK_POLL_JOB_FINISH) {
1411 : : timeout = false;
1412 : : break;
1413 : : }
1414 [ # # ]: 0 : } while (plt_tsc_cycles() < req->timeout);
1415 : :
1416 [ # # ]: 0 : if (timeout)
1417 : : ret = -ETIME;
1418 : : else
1419 : 0 : cn10k_ml_result_update(cnxk_mldev, -1, req);
1420 : :
1421 : 0 : error_enqueue:
1422 : 0 : return ret;
1423 : : }
1424 : :
1425 : : int
1426 : 0 : cn10k_ml_io_alloc(void *device, uint16_t model_id, const char *layer_name, uint64_t **input_qbuffer,
1427 : : uint64_t **output_qbuffer)
1428 : : {
1429 : : struct cnxk_ml_dev *cnxk_mldev;
1430 : : struct cnxk_ml_model *model;
1431 : : struct cnxk_ml_layer *layer;
1432 : :
1433 : : char str[RTE_MEMZONE_NAMESIZE];
1434 : : const struct plt_memzone *mz;
1435 : : uint64_t output_size;
1436 : : uint64_t input_size;
1437 : : uint16_t layer_id;
1438 : : int ret;
1439 : :
1440 : : cnxk_mldev = (struct cnxk_ml_dev *)device;
1441 [ # # ]: 0 : if (cnxk_mldev == NULL) {
1442 : 0 : plt_err("Invalid device = %p", device);
1443 : 0 : return -EINVAL;
1444 : : }
1445 : :
1446 : 0 : model = cnxk_mldev->mldev->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 : ret = cn10k_ml_model_get_layer_id(model, layer_name, &layer_id);
1453 [ # # ]: 0 : if (ret != 0)
1454 : : return ret;
1455 : :
1456 : 0 : layer = &model->layer[layer_id];
1457 : 0 : input_size = PLT_ALIGN_CEIL(layer->info.total_input_sz_q, ML_CN10K_ALIGN_SIZE);
1458 : 0 : output_size = PLT_ALIGN_CEIL(layer->info.total_output_sz_q, ML_CN10K_ALIGN_SIZE);
1459 : :
1460 : 0 : sprintf(str, "cn10k_ml_io_mz_%u_%u", model_id, layer_id);
1461 : 0 : mz = plt_memzone_reserve_aligned(str, input_size + output_size, 0, ML_CN10K_ALIGN_SIZE);
1462 [ # # ]: 0 : if (mz == NULL) {
1463 : 0 : plt_err("io_alloc failed: Unable to allocate memory: model_id = %u, layer_name = %s",
1464 : : model_id, layer_name);
1465 : 0 : return -ENOMEM;
1466 : : }
1467 : :
1468 : 0 : *input_qbuffer = mz->addr;
1469 : 0 : *output_qbuffer = PLT_PTR_ADD(mz->addr, input_size);
1470 : :
1471 : 0 : return 0;
1472 : : }
1473 : :
1474 : : int
1475 : 0 : cn10k_ml_io_free(void *device, uint16_t model_id, const char *layer_name)
1476 : : {
1477 : : struct cnxk_ml_dev *cnxk_mldev;
1478 : : struct cnxk_ml_model *model;
1479 : :
1480 : : char str[RTE_MEMZONE_NAMESIZE];
1481 : : const struct plt_memzone *mz;
1482 : : uint16_t layer_id;
1483 : : int ret;
1484 : :
1485 : : cnxk_mldev = (struct cnxk_ml_dev *)device;
1486 [ # # ]: 0 : if (cnxk_mldev == NULL) {
1487 : 0 : plt_err("Invalid device = %p", device);
1488 : 0 : return -EINVAL;
1489 : : }
1490 : :
1491 : 0 : model = cnxk_mldev->mldev->data->models[model_id];
1492 [ # # ]: 0 : if (model == NULL) {
1493 : 0 : plt_err("Invalid model_id = %u", model_id);
1494 : 0 : return -EINVAL;
1495 : : }
1496 : :
1497 : 0 : ret = cn10k_ml_model_get_layer_id(model, layer_name, &layer_id);
1498 [ # # ]: 0 : if (ret != 0)
1499 : : return ret;
1500 : :
1501 : 0 : sprintf(str, "cn10k_ml_io_mz_%u_%u", model_id, layer_id);
1502 : 0 : mz = plt_memzone_lookup(str);
1503 [ # # ]: 0 : if (mz == NULL) {
1504 : 0 : plt_err("io_free failed: Memzone not found: model_id = %u, layer_name = %s",
1505 : : model_id, layer_name);
1506 : 0 : return -EINVAL;
1507 : : }
1508 : :
1509 : 0 : return plt_memzone_free(mz);
1510 : : }
1511 : :
1512 : : int
1513 : 0 : cn10k_ml_malloc(const char *name, size_t size, uint32_t align, void **addr)
1514 : : {
1515 : : const struct plt_memzone *mz;
1516 : :
1517 : 0 : mz = plt_memzone_reserve_aligned(name, size, 0, align);
1518 [ # # ]: 0 : if (mz == NULL) {
1519 : 0 : plt_err("ml_malloc failed: Unable to allocate memory: name = %s", name);
1520 : 0 : return -ENOMEM;
1521 : : }
1522 : :
1523 : 0 : *addr = mz->addr;
1524 : :
1525 : 0 : return 0;
1526 : : }
1527 : :
1528 : : int
1529 : 0 : cn10k_ml_free(const char *name)
1530 : : {
1531 : : const struct plt_memzone *mz;
1532 : :
1533 : 0 : mz = plt_memzone_lookup(name);
1534 [ # # ]: 0 : if (mz == NULL) {
1535 : 0 : plt_err("ml_free failed: Memzone not found: name = %s", name);
1536 : 0 : return -EINVAL;
1537 : : }
1538 : :
1539 : 0 : return plt_memzone_free(mz);
1540 : : }
|