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_mrvl_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_mrvl_layers) {
635 : 0 : plt_err("No slots available for model MRVL 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 : : /* Enable support for batch_size of 256 */
675 [ # # ]: 0 : if (layer->glow.metadata.model.batch_size == 0)
676 : 0 : layer->batch_size = 256;
677 : : else
678 : 0 : layer->batch_size = layer->glow.metadata.model.batch_size;
679 : :
680 : : /* Set DMA base address */
681 : 0 : base_dma_addr = mz->addr;
682 : 0 : cn10k_ml_layer_addr_update(layer, buffer, base_dma_addr);
683 : :
684 : : /* Set scratch base address */
685 : 0 : layer->glow.addr.scratch_base_addr = PLT_PTR_ADD(base_dma_addr, layer_object_size);
686 : :
687 : : /* Update internal I/O data structure */
688 : 0 : cn10k_ml_layer_io_info_set(&layer->info, &layer->glow.metadata);
689 : :
690 : : /* Initialize model_mem_map */
691 : 0 : memset(&layer->glow.ocm_map, 0, sizeof(struct cn10k_ml_ocm_layer_map));
692 : 0 : layer->glow.ocm_map.ocm_reserved = false;
693 : 0 : layer->glow.ocm_map.tilemask = 0;
694 : 0 : layer->glow.ocm_map.wb_page_start = -1;
695 : 0 : layer->glow.ocm_map.wb_pages = wb_pages;
696 : 0 : layer->glow.ocm_map.scratch_pages = scratch_pages;
697 : :
698 : : /* Set slow-path request address and state */
699 : 0 : layer->glow.req = PLT_PTR_ADD(mz->addr, layer_object_size + layer_scratch_size);
700 : :
701 : : /* Reset burst and sync stats */
702 : 0 : layer->glow.burst_xstats = PLT_PTR_ADD(
703 : : layer->glow.req, PLT_ALIGN_CEIL(sizeof(struct cnxk_ml_req), ML_CN10K_ALIGN_SIZE));
704 [ # # ]: 0 : for (qp_id = 0; qp_id < cnxk_mldev->mldev->data->nb_queue_pairs + 1; qp_id++) {
705 : 0 : layer->glow.burst_xstats[qp_id].hw_latency_tot = 0;
706 : 0 : layer->glow.burst_xstats[qp_id].hw_latency_min = UINT64_MAX;
707 : 0 : layer->glow.burst_xstats[qp_id].hw_latency_max = 0;
708 : 0 : layer->glow.burst_xstats[qp_id].fw_latency_tot = 0;
709 : 0 : layer->glow.burst_xstats[qp_id].fw_latency_min = UINT64_MAX;
710 : 0 : layer->glow.burst_xstats[qp_id].fw_latency_max = 0;
711 : 0 : layer->glow.burst_xstats[qp_id].hw_reset_count = 0;
712 : 0 : layer->glow.burst_xstats[qp_id].fw_reset_count = 0;
713 : 0 : layer->glow.burst_xstats[qp_id].dequeued_count = 0;
714 : : }
715 : :
716 : 0 : layer->glow.sync_xstats =
717 : 0 : PLT_PTR_ADD(layer->glow.burst_xstats, cnxk_mldev->mldev->data->nb_queue_pairs *
718 : : sizeof(struct cn10k_ml_layer_xstats));
719 : :
720 : : /* Update xstats names */
721 : 0 : cn10k_ml_xstats_layer_name_update(cnxk_mldev, model_id, layer_id);
722 : :
723 : 0 : layer->state = ML_CNXK_LAYER_STATE_LOADED;
724 : 0 : cnxk_mldev->index_map[idx].model_id = model->model_id;
725 : 0 : cnxk_mldev->index_map[idx].layer_id = layer_id;
726 : 0 : cnxk_mldev->index_map[idx].active = true;
727 : 0 : *index = idx;
728 : :
729 : 0 : return 0;
730 : : }
731 : :
732 : : int
733 : 0 : cn10k_ml_model_load(struct cnxk_ml_dev *cnxk_mldev, struct rte_ml_model_params *params,
734 : : struct cnxk_ml_model *model)
735 : : {
736 : : struct cnxk_ml_layer *layer;
737 : : int ret;
738 : :
739 : : /* Metadata check */
740 : 0 : ret = cn10k_ml_model_metadata_check(params->addr, params->size);
741 [ # # ]: 0 : if (ret != 0)
742 : : return ret;
743 : :
744 : : /* Set model sub type */
745 : 0 : model->subtype = ML_CNXK_MODEL_SUBTYPE_GLOW_MRVL;
746 : :
747 : : /* Copy metadata to internal buffer */
748 [ # # ]: 0 : rte_memcpy(&model->glow.metadata, params->addr, sizeof(struct cn10k_ml_model_metadata));
749 : 0 : cn10k_ml_model_metadata_update(&model->glow.metadata);
750 : :
751 : : /* Set model name */
752 : : rte_memcpy(model->name, (char *)model->glow.metadata.model.name, 64);
753 : :
754 : : /* Enable support for batch_size of 256 */
755 [ # # ]: 0 : if (model->glow.metadata.model.batch_size == 0)
756 : 0 : model->batch_size = 256;
757 : : else
758 : 0 : model->batch_size = model->glow.metadata.model.batch_size;
759 : :
760 : : /* Since the number of layers that the driver would be handling for glow models is
761 : : * always 1. consider the entire model as a model with single layer. This would
762 : : * ignore the num_layers from metadata.
763 : : */
764 : 0 : model->nb_layers = 1;
765 : :
766 : : /* Load layer and get the index */
767 : : layer = &model->layer[0];
768 : 0 : layer->type = ML_CNXK_LAYER_TYPE_MRVL;
769 : 0 : ret = cn10k_ml_layer_load(cnxk_mldev, model->model_id, NULL, params->addr, params->size,
770 : : &layer->index);
771 [ # # ]: 0 : if (ret != 0) {
772 : 0 : plt_err("Model layer load failed: model_id = %u, layer_id = %u", model->model_id,
773 : : 0);
774 : 0 : return ret;
775 : : }
776 : :
777 : 0 : cn10k_ml_model_info_set(cnxk_mldev, model, &model->layer[0].info, &model->glow.metadata);
778 : :
779 : : /* Set fast-path functions */
780 : 0 : model->enqueue_single = cn10k_ml_enqueue_single;
781 : 0 : model->result_update = cn10k_ml_result_update;
782 : 0 : model->set_error_code = cn10k_ml_set_error_code;
783 : 0 : model->set_poll_addr = cn10k_ml_set_poll_addr;
784 : 0 : model->op_error_get = cn10k_ml_op_error_get;
785 : :
786 : 0 : return 0;
787 : : }
788 : :
789 : : int
790 : 0 : cn10k_ml_layer_unload(void *device, uint16_t model_id, const char *layer_name)
791 : : {
792 : : struct cnxk_ml_dev *cnxk_mldev;
793 : : struct cnxk_ml_model *model;
794 : : struct cnxk_ml_layer *layer;
795 : :
796 : : char str[RTE_MEMZONE_NAMESIZE];
797 : : uint16_t layer_id;
798 : : int ret;
799 : :
800 : : cnxk_mldev = (struct cnxk_ml_dev *)device;
801 [ # # ]: 0 : if (cnxk_mldev == NULL) {
802 : 0 : plt_err("Invalid device = %p", device);
803 : 0 : return -EINVAL;
804 : : }
805 : :
806 : 0 : model = cnxk_mldev->mldev->data->models[model_id];
807 [ # # ]: 0 : if (model == NULL) {
808 : 0 : plt_err("Invalid model_id = %u", model_id);
809 : 0 : return -EINVAL;
810 : : }
811 : :
812 : 0 : ret = cn10k_ml_model_get_layer_id(model, layer_name, &layer_id);
813 [ # # ]: 0 : if (ret != 0)
814 : : return ret;
815 : :
816 : 0 : layer = &model->layer[layer_id];
817 : :
818 : 0 : snprintf(str, RTE_MEMZONE_NAMESIZE, "%s_%u_%u", CN10K_ML_LAYER_MEMZONE_NAME,
819 : 0 : model->model_id, layer_id);
820 : 0 : ret = plt_memzone_free(plt_memzone_lookup(str));
821 : :
822 : 0 : layer->state = ML_CNXK_LAYER_STATE_UNKNOWN;
823 : 0 : cnxk_mldev->index_map[layer->index].active = false;
824 : :
825 : 0 : return ret;
826 : : }
827 : :
828 : : int
829 : 0 : cn10k_ml_model_unload(struct cnxk_ml_dev *cnxk_mldev, struct cnxk_ml_model *model)
830 : : {
831 : 0 : return cn10k_ml_layer_unload(cnxk_mldev, model->model_id, NULL);
832 : : }
833 : :
834 : : int
835 : 0 : cn10k_ml_layer_start(void *device, uint16_t model_id, const char *layer_name)
836 : : {
837 : : struct cn10k_ml_dev *cn10k_mldev;
838 : : struct cnxk_ml_dev *cnxk_mldev;
839 : : struct cnxk_ml_model *model;
840 : : struct cnxk_ml_layer *layer;
841 : : struct cn10k_ml_ocm *ocm;
842 : : struct cnxk_ml_req *req;
843 : :
844 : : uint16_t layer_id;
845 : : bool job_enqueued;
846 : : bool job_dequeued;
847 : : uint8_t num_tiles;
848 : : uint64_t tilemask;
849 : : int wb_page_start;
850 : : int tile_start;
851 : : int tile_end;
852 : : bool locked;
853 : : int ret = 0;
854 : :
855 : : cnxk_mldev = (struct cnxk_ml_dev *)device;
856 [ # # ]: 0 : if (cnxk_mldev == NULL) {
857 : 0 : plt_err("Invalid device = %p", device);
858 : 0 : return -EINVAL;
859 : : }
860 : :
861 : 0 : model = cnxk_mldev->mldev->data->models[model_id];
862 [ # # ]: 0 : if (model == NULL) {
863 : 0 : plt_err("Invalid model_id = %u", model_id);
864 : 0 : return -EINVAL;
865 : : }
866 : :
867 : 0 : ret = cn10k_ml_model_get_layer_id(model, layer_name, &layer_id);
868 [ # # ]: 0 : if (ret != 0)
869 : : return ret;
870 : :
871 : 0 : layer = &model->layer[layer_id];
872 : : cn10k_mldev = &cnxk_mldev->cn10k_mldev;
873 : : ocm = &cn10k_mldev->ocm;
874 : :
875 : : /* Prepare JD */
876 : 0 : req = layer->glow.req;
877 : 0 : cn10k_ml_prep_sp_job_descriptor(cnxk_mldev, layer, req, ML_CN10K_JOB_TYPE_MODEL_START);
878 : 0 : req->cn10k_req.result.error_code = 0x0;
879 : 0 : req->cn10k_req.result.user_ptr = NULL;
880 : :
881 : : plt_write64(ML_CNXK_POLL_JOB_START, &req->cn10k_req.status);
882 : : plt_wmb();
883 : :
884 : 0 : num_tiles = layer->glow.metadata.model.tile_end - layer->glow.metadata.model.tile_start + 1;
885 : :
886 : : locked = false;
887 : 0 : while (!locked) {
888 [ # # ]: 0 : if (plt_spinlock_trylock(&model->lock) != 0) {
889 [ # # ]: 0 : if (layer->state == ML_CNXK_LAYER_STATE_STARTED) {
890 : 0 : plt_ml_dbg("Layer already started, model_id = %u, layer_id = %u",
891 : : model->model_id, layer_id);
892 : : plt_spinlock_unlock(&model->lock);
893 : 0 : return 1;
894 : : }
895 : :
896 [ # # ]: 0 : if (layer->state == ML_CNXK_LAYER_STATE_JOB_ACTIVE) {
897 : 0 : plt_err("A slow-path job is active for the model_id = %u",
898 : : model->model_id);
899 : : plt_spinlock_unlock(&model->lock);
900 : 0 : return -EBUSY;
901 : : }
902 : :
903 : 0 : layer->state = ML_CNXK_LAYER_STATE_JOB_ACTIVE;
904 : : plt_spinlock_unlock(&model->lock);
905 : : locked = true;
906 : : }
907 : : }
908 : :
909 [ # # ]: 0 : while (!layer->glow.ocm_map.ocm_reserved) {
910 [ # # ]: 0 : if (plt_spinlock_trylock(&ocm->lock) != 0) {
911 : 0 : wb_page_start = cn10k_ml_ocm_tilemask_find(
912 : 0 : cnxk_mldev, num_tiles, layer->glow.ocm_map.wb_pages,
913 : 0 : layer->glow.ocm_map.scratch_pages, &tilemask);
914 : :
915 [ # # ]: 0 : if (wb_page_start == -1) {
916 : 0 : plt_err("Free pages not available on OCM tiles");
917 : 0 : plt_err("Failed to start layer, model_id = %u, layer_id = %u",
918 : : model->model_id, layer_id);
919 : : plt_spinlock_unlock(&ocm->lock);
920 : 0 : return -ENOMEM;
921 : : }
922 : :
923 : 0 : layer->glow.ocm_map.tilemask = tilemask;
924 : 0 : layer->glow.ocm_map.wb_page_start = wb_page_start;
925 : :
926 : 0 : cn10k_ml_ocm_reserve_pages(
927 : 0 : cnxk_mldev, model->model_id, layer_id, layer->glow.ocm_map.tilemask,
928 : 0 : layer->glow.ocm_map.wb_page_start, layer->glow.ocm_map.wb_pages,
929 : 0 : layer->glow.ocm_map.scratch_pages);
930 : 0 : layer->glow.ocm_map.ocm_reserved = true;
931 : : plt_spinlock_unlock(&ocm->lock);
932 : : }
933 : : }
934 : :
935 : : /* Update JD */
936 : 0 : cn10k_ml_ocm_tilecount(layer->glow.ocm_map.tilemask, &tile_start, &tile_end);
937 : 0 : req->cn10k_req.jd.model_start.tilemask = GENMASK_ULL(tile_end, tile_start);
938 : 0 : req->cn10k_req.jd.model_start.ocm_wb_base_address =
939 : 0 : layer->glow.ocm_map.wb_page_start * ocm->page_size;
940 : :
941 : : job_enqueued = false;
942 : : job_dequeued = false;
943 : : do {
944 [ # # ]: 0 : if (!job_enqueued) {
945 : 0 : req->timeout = plt_tsc_cycles() + ML_CNXK_CMD_TIMEOUT * plt_tsc_hz();
946 : : job_enqueued =
947 : 0 : roc_ml_scratch_enqueue(&cn10k_mldev->roc, &req->cn10k_req.jd);
948 : : }
949 : :
950 [ # # ]: 0 : if (job_enqueued && !job_dequeued)
951 : : job_dequeued =
952 : 0 : roc_ml_scratch_dequeue(&cn10k_mldev->roc, &req->cn10k_req.jd);
953 : :
954 [ # # ]: 0 : if (job_dequeued)
955 : : break;
956 [ # # ]: 0 : } while (plt_tsc_cycles() < req->timeout);
957 : :
958 [ # # ]: 0 : if (job_dequeued) {
959 [ # # ]: 0 : if (plt_read64(&req->cn10k_req.status) == ML_CNXK_POLL_JOB_FINISH) {
960 [ # # ]: 0 : if (req->cn10k_req.result.error_code == 0)
961 : : ret = 0;
962 : : else
963 : : ret = -1;
964 : : }
965 : : } else { /* Reset scratch registers */
966 : 0 : roc_ml_scratch_queue_reset(&cn10k_mldev->roc);
967 : : ret = -ETIME;
968 : : }
969 : :
970 : : locked = false;
971 : 0 : while (!locked) {
972 [ # # ]: 0 : if (plt_spinlock_trylock(&model->lock) != 0) {
973 [ # # ]: 0 : if (ret == 0)
974 : 0 : layer->state = ML_CNXK_LAYER_STATE_STARTED;
975 : : else
976 : 0 : layer->state = ML_CNXK_LAYER_STATE_UNKNOWN;
977 : :
978 : : plt_spinlock_unlock(&model->lock);
979 : : locked = true;
980 : : }
981 : : }
982 : :
983 [ # # ]: 0 : if (layer->state == ML_CNXK_LAYER_STATE_UNKNOWN) {
984 [ # # ]: 0 : while (layer->glow.ocm_map.ocm_reserved) {
985 [ # # ]: 0 : if (plt_spinlock_trylock(&ocm->lock) != 0) {
986 : 0 : cn10k_ml_ocm_free_pages(cnxk_mldev, model->model_id, layer_id);
987 : 0 : layer->glow.ocm_map.ocm_reserved = false;
988 : 0 : layer->glow.ocm_map.tilemask = 0x0;
989 : : plt_spinlock_unlock(&ocm->lock);
990 : : }
991 : : }
992 : : }
993 : :
994 [ # # ]: 0 : if (ret < 0) {
995 : 0 : cn10k_ml_layer_stop(device, model_id, layer_name);
996 : : } else {
997 [ # # ]: 0 : if (cn10k_mldev->cache_model_data)
998 : 0 : ret = cn10k_ml_cache_model_data(cnxk_mldev, layer);
999 : : }
1000 : :
1001 : : return ret;
1002 : : }
1003 : :
1004 : : int
1005 : 0 : cn10k_ml_model_start(struct cnxk_ml_dev *cnxk_mldev, struct cnxk_ml_model *model)
1006 : : {
1007 : : struct cnxk_ml_layer *layer;
1008 : : int ret;
1009 : :
1010 : : layer = &model->layer[0];
1011 : 0 : ret = cn10k_ml_layer_start(cnxk_mldev, model->model_id, layer->name);
1012 [ # # ]: 0 : if (ret != 0) {
1013 : 0 : plt_err("CN10K Model start failed, model_id = %u, error = %d", model->model_id,
1014 : : ret);
1015 : 0 : return ret;
1016 : : }
1017 : :
1018 : 0 : cnxk_mldev->nb_models_started++;
1019 : 0 : model->state = ML_CNXK_MODEL_STATE_STARTED;
1020 : :
1021 : 0 : return 0;
1022 : : }
1023 : :
1024 : : int
1025 : 0 : cn10k_ml_layer_stop(void *device, uint16_t model_id, const char *layer_name)
1026 : : {
1027 : : struct cn10k_ml_dev *cn10k_mldev;
1028 : : struct cnxk_ml_dev *cnxk_mldev;
1029 : : struct cnxk_ml_model *model;
1030 : : struct cnxk_ml_layer *layer;
1031 : : struct cn10k_ml_ocm *ocm;
1032 : : struct cnxk_ml_req *req;
1033 : :
1034 : : uint16_t layer_id;
1035 : : bool job_enqueued;
1036 : : bool job_dequeued;
1037 : : bool locked;
1038 : : int ret = 0;
1039 : :
1040 : : cnxk_mldev = (struct cnxk_ml_dev *)device;
1041 [ # # ]: 0 : if (cnxk_mldev == NULL) {
1042 : 0 : plt_err("Invalid device = %p", device);
1043 : 0 : return -EINVAL;
1044 : : }
1045 : :
1046 : 0 : model = cnxk_mldev->mldev->data->models[model_id];
1047 [ # # ]: 0 : if (model == NULL) {
1048 : 0 : plt_err("Invalid model_id = %u", model_id);
1049 : 0 : return -EINVAL;
1050 : : }
1051 : :
1052 : 0 : ret = cn10k_ml_model_get_layer_id(model, layer_name, &layer_id);
1053 [ # # ]: 0 : if (ret != 0)
1054 : : return ret;
1055 : :
1056 : 0 : layer = &model->layer[layer_id];
1057 : : cn10k_mldev = &cnxk_mldev->cn10k_mldev;
1058 : : ocm = &cn10k_mldev->ocm;
1059 : :
1060 : : /* Prepare JD */
1061 : 0 : req = layer->glow.req;
1062 : 0 : cn10k_ml_prep_sp_job_descriptor(cnxk_mldev, layer, req, ML_CN10K_JOB_TYPE_MODEL_STOP);
1063 : 0 : req->cn10k_req.result.error_code = 0x0;
1064 : 0 : req->cn10k_req.result.user_ptr = NULL;
1065 : :
1066 : : plt_write64(ML_CNXK_POLL_JOB_START, &req->cn10k_req.status);
1067 : : plt_wmb();
1068 : :
1069 : : locked = false;
1070 : 0 : while (!locked) {
1071 [ # # ]: 0 : if (plt_spinlock_trylock(&model->lock) != 0) {
1072 [ # # ]: 0 : if (layer->state == ML_CNXK_LAYER_STATE_LOADED) {
1073 : 0 : plt_ml_dbg("Layer not started, model_id = %u, layer_id = %u",
1074 : : model->model_id, layer_id);
1075 : : plt_spinlock_unlock(&model->lock);
1076 : 0 : return 1;
1077 : : }
1078 : :
1079 [ # # ]: 0 : if (layer->state == ML_CNXK_LAYER_STATE_JOB_ACTIVE) {
1080 : 0 : plt_err("A slow-path job is active for the layer, model_id = %u, layer_id = %u",
1081 : : model->model_id, layer_id);
1082 : : plt_spinlock_unlock(&model->lock);
1083 : 0 : return -EBUSY;
1084 : : }
1085 : :
1086 : 0 : layer->state = ML_CNXK_LAYER_STATE_JOB_ACTIVE;
1087 : : plt_spinlock_unlock(&model->lock);
1088 : : locked = true;
1089 : : }
1090 : : }
1091 : :
1092 [ # # ]: 0 : while (layer->glow.ocm_map.ocm_reserved) {
1093 [ # # ]: 0 : if (plt_spinlock_trylock(&ocm->lock) != 0) {
1094 : 0 : cn10k_ml_ocm_free_pages(cnxk_mldev, model->model_id, layer_id);
1095 : 0 : layer->glow.ocm_map.ocm_reserved = false;
1096 : 0 : layer->glow.ocm_map.tilemask = 0x0;
1097 : : plt_spinlock_unlock(&ocm->lock);
1098 : : }
1099 : : }
1100 : :
1101 : : job_enqueued = false;
1102 : : job_dequeued = false;
1103 : : do {
1104 [ # # ]: 0 : if (!job_enqueued) {
1105 : 0 : req->timeout = plt_tsc_cycles() + ML_CNXK_CMD_TIMEOUT * plt_tsc_hz();
1106 : : job_enqueued =
1107 : 0 : roc_ml_scratch_enqueue(&cn10k_mldev->roc, &req->cn10k_req.jd);
1108 : : }
1109 : :
1110 [ # # ]: 0 : if (job_enqueued && !job_dequeued)
1111 : : job_dequeued =
1112 : 0 : roc_ml_scratch_dequeue(&cn10k_mldev->roc, &req->cn10k_req.jd);
1113 : :
1114 [ # # ]: 0 : if (job_dequeued)
1115 : : break;
1116 [ # # ]: 0 : } while (plt_tsc_cycles() < req->timeout);
1117 : :
1118 [ # # ]: 0 : if (job_dequeued) {
1119 [ # # ]: 0 : if (plt_read64(&req->cn10k_req.status) == ML_CNXK_POLL_JOB_FINISH) {
1120 [ # # ]: 0 : if (req->cn10k_req.result.error_code == 0x0)
1121 : : ret = 0;
1122 : : else
1123 : : ret = -1;
1124 : : }
1125 : : } else {
1126 : 0 : roc_ml_scratch_queue_reset(&cn10k_mldev->roc);
1127 : : ret = -ETIME;
1128 : : }
1129 : :
1130 : : locked = false;
1131 : 0 : while (!locked) {
1132 [ # # ]: 0 : if (plt_spinlock_trylock(&model->lock) != 0) {
1133 [ # # ]: 0 : if (ret == 0)
1134 : 0 : layer->state = ML_CNXK_LAYER_STATE_LOADED;
1135 : : else
1136 : 0 : layer->state = ML_CNXK_LAYER_STATE_UNKNOWN;
1137 : :
1138 : : plt_spinlock_unlock(&model->lock);
1139 : : locked = true;
1140 : : }
1141 : : }
1142 : :
1143 : : return ret;
1144 : : }
1145 : :
1146 : : int
1147 : 0 : cn10k_ml_model_stop(struct cnxk_ml_dev *cnxk_mldev, struct cnxk_ml_model *model)
1148 : : {
1149 : : struct cnxk_ml_layer *layer;
1150 : : int ret;
1151 : :
1152 : : layer = &model->layer[0];
1153 : 0 : ret = cn10k_ml_layer_stop(cnxk_mldev, model->model_id, layer->name);
1154 [ # # ]: 0 : if (ret != 0) {
1155 : 0 : plt_err("CN10K Model stop failed, model_id = %u, error = %d", model->model_id, ret);
1156 : 0 : return ret;
1157 : : }
1158 : :
1159 : 0 : cnxk_mldev->nb_models_stopped++;
1160 : 0 : model->state = ML_CNXK_MODEL_STATE_LOADED;
1161 : :
1162 : 0 : return 0;
1163 : : }
1164 : :
1165 : : int
1166 : 0 : cn10k_ml_model_params_update(struct cnxk_ml_dev *cnxk_mldev, struct cnxk_ml_model *model,
1167 : : void *buffer)
1168 : : {
1169 : : struct cnxk_ml_layer *layer;
1170 : :
1171 : : RTE_SET_USED(cnxk_mldev);
1172 : :
1173 [ # # ]: 0 : if (model->state == ML_CNXK_MODEL_STATE_UNKNOWN)
1174 : : return -1;
1175 [ # # ]: 0 : else if (model->state != ML_CNXK_MODEL_STATE_LOADED)
1176 : : return -EBUSY;
1177 : :
1178 : : layer = &model->layer[0];
1179 : :
1180 : : /* Update model weights & bias */
1181 : 0 : rte_memcpy(layer->glow.addr.wb_load_addr, buffer,
1182 [ # # ]: 0 : layer->glow.metadata.weights_bias.file_size);
1183 : :
1184 : : return 0;
1185 : : }
1186 : :
1187 : : __rte_hot void
1188 : 0 : cn10k_ml_result_update(struct cnxk_ml_dev *cnxk_mldev, int qp_id, void *request)
1189 : : {
1190 : : union cn10k_ml_error_code *error_code;
1191 : : struct cn10k_ml_layer_xstats *xstats;
1192 : : struct cn10k_ml_dev *cn10k_mldev;
1193 : : struct cn10k_ml_result *result;
1194 : : struct cnxk_ml_model *model;
1195 : : struct cnxk_ml_layer *layer;
1196 : : struct cnxk_ml_req *req;
1197 : : struct cnxk_ml_qp *qp;
1198 : : struct rte_ml_op *op;
1199 : : uint64_t hw_latency;
1200 : : uint64_t fw_latency;
1201 : : uint16_t model_id;
1202 : : uint16_t layer_id;
1203 : : uint16_t idx;
1204 : :
1205 : : req = (struct cnxk_ml_req *)request;
1206 : : result = &req->cn10k_req.result;
1207 : 0 : op = req->op;
1208 [ # # ]: 0 : if (likely(result->error_code == 0)) {
1209 : 0 : idx = req->cn10k_req.jd.hdr.model_id;
1210 : 0 : model_id = cnxk_mldev->index_map[idx].model_id;
1211 : 0 : layer_id = cnxk_mldev->index_map[idx].layer_id;
1212 : 0 : model = cnxk_mldev->mldev->data->models[model_id];
1213 : 0 : layer = &model->layer[layer_id];
1214 [ # # ]: 0 : if (likely(qp_id >= 0)) {
1215 : 0 : qp = cnxk_mldev->mldev->data->queue_pairs[qp_id];
1216 : 0 : qp->stats.dequeued_count++;
1217 : 0 : xstats = &layer->glow.burst_xstats[qp_id];
1218 : : } else {
1219 : 0 : xstats = layer->glow.sync_xstats;
1220 : : }
1221 : :
1222 [ # # ]: 0 : if (unlikely(xstats->dequeued_count == xstats->hw_reset_count)) {
1223 : 0 : xstats->hw_latency_min = UINT64_MAX;
1224 : 0 : xstats->hw_latency_max = 0;
1225 : : }
1226 : :
1227 [ # # ]: 0 : if (unlikely(xstats->dequeued_count == xstats->fw_reset_count)) {
1228 : 0 : xstats->fw_latency_min = UINT64_MAX;
1229 : 0 : xstats->fw_latency_max = 0;
1230 : : }
1231 : :
1232 : 0 : hw_latency = result->stats.hw_end - result->stats.hw_start;
1233 : 0 : fw_latency = result->stats.fw_end - result->stats.fw_start - hw_latency;
1234 : :
1235 : 0 : xstats->hw_latency_tot += hw_latency;
1236 : 0 : xstats->hw_latency_min = PLT_MIN(xstats->hw_latency_min, hw_latency);
1237 : 0 : xstats->hw_latency_max = PLT_MAX(xstats->hw_latency_max, hw_latency);
1238 : 0 : xstats->fw_latency_tot += fw_latency;
1239 : 0 : xstats->fw_latency_min = PLT_MIN(xstats->fw_latency_min, fw_latency);
1240 : 0 : xstats->fw_latency_max = PLT_MAX(xstats->fw_latency_max, fw_latency);
1241 : 0 : xstats->dequeued_count++;
1242 : :
1243 : 0 : op->impl_opaque = result->error_code;
1244 : 0 : op->status = RTE_ML_OP_STATUS_SUCCESS;
1245 : : } else {
1246 [ # # ]: 0 : if (likely(qp_id >= 0)) {
1247 : 0 : qp = cnxk_mldev->mldev->data->queue_pairs[qp_id];
1248 : 0 : qp->stats.dequeue_err_count++;
1249 : : }
1250 : :
1251 : : /* Handle driver error */
1252 : : error_code = (union cn10k_ml_error_code *)&result->error_code;
1253 [ # # ]: 0 : if (error_code->s.etype == ML_CN10K_ETYPE_DRIVER) {
1254 : : cn10k_mldev = &cnxk_mldev->cn10k_mldev;
1255 : :
1256 : : /* Check for exception */
1257 [ # # ]: 0 : if ((roc_ml_reg_read64(&cn10k_mldev->roc, ML_SCRATCH_EXCEPTION_SP_C0) !=
1258 [ # # ]: 0 : 0) ||
1259 : 0 : (roc_ml_reg_read64(&cn10k_mldev->roc, ML_SCRATCH_EXCEPTION_SP_C1) != 0))
1260 : 0 : error_code->s.stype = ML_CN10K_DRIVER_ERR_EXCEPTION;
1261 [ # # # # ]: 0 : else if ((roc_ml_reg_read64(&cn10k_mldev->roc, ML_CORE_INT_LO) != 0) ||
1262 : 0 : (roc_ml_reg_read64(&cn10k_mldev->roc, ML_CORE_INT_HI) != 0))
1263 : 0 : error_code->s.stype = ML_CN10K_DRIVER_ERR_FW_ERROR;
1264 : : else
1265 : 0 : error_code->s.stype = ML_CN10K_DRIVER_ERR_UNKNOWN;
1266 : : }
1267 : :
1268 : 0 : op->impl_opaque = result->error_code;
1269 : 0 : op->status = RTE_ML_OP_STATUS_ERROR;
1270 : : }
1271 : :
1272 : 0 : op->user_ptr = result->user_ptr;
1273 : 0 : }
1274 : :
1275 : : __rte_hot void
1276 : 0 : cn10k_ml_set_error_code(struct cnxk_ml_req *req, uint64_t etype, uint64_t stype)
1277 : : {
1278 : : union cn10k_ml_error_code *error_code;
1279 : :
1280 : : error_code = (union cn10k_ml_error_code *)&req->cn10k_req.result.error_code;
1281 : 0 : error_code->s.etype = etype;
1282 : 0 : error_code->s.stype = stype;
1283 : 0 : }
1284 : :
1285 : : __rte_hot bool
1286 : 0 : cn10k_ml_enqueue_single(struct cnxk_ml_dev *cnxk_mldev, struct rte_ml_op *op, uint16_t layer_id,
1287 : : struct cnxk_ml_qp *qp, uint64_t head)
1288 : : {
1289 : : union cn10k_ml_error_code *error_code;
1290 : : struct cn10k_ml_dev *cn10k_mldev;
1291 : : struct cnxk_ml_model *model;
1292 : : struct cnxk_ml_queue *queue;
1293 : : struct cnxk_ml_req *req;
1294 : :
1295 : : cn10k_mldev = &cnxk_mldev->cn10k_mldev;
1296 : : queue = &qp->queue;
1297 : 0 : req = &queue->reqs[head];
1298 : :
1299 : 0 : model = cnxk_mldev->mldev->data->models[op->model_id];
1300 : 0 : model->set_poll_addr(req);
1301 : 0 : cn10k_ml_prep_fp_job_descriptor(cnxk_mldev, req, model->layer[layer_id].index,
1302 : 0 : op->input[0]->addr, op->output[0]->addr, op->nb_batches);
1303 : :
1304 : : memset(&req->cn10k_req.result, 0, sizeof(struct cn10k_ml_result));
1305 : : error_code = (union cn10k_ml_error_code *)&req->cn10k_req.result.error_code;
1306 : 0 : error_code->s.etype = ML_CN10K_ETYPE_UNKNOWN;
1307 : 0 : req->cn10k_req.result.user_ptr = op->user_ptr;
1308 : :
1309 : 0 : cnxk_ml_set_poll_ptr(req);
1310 [ # # ]: 0 : if (unlikely(!cn10k_mldev->ml_jcmdq_enqueue(&cn10k_mldev->roc, &req->cn10k_req.jcmd)))
1311 : : return false;
1312 : :
1313 : 0 : req->timeout = plt_tsc_cycles() + queue->wait_cycles;
1314 : 0 : req->op = op;
1315 : :
1316 : 0 : return true;
1317 : : }
1318 : :
1319 : : __rte_hot int
1320 : 0 : cn10k_ml_op_error_get(struct cnxk_ml_dev *cnxk_mldev, struct rte_ml_op *op,
1321 : : struct rte_ml_op_error *error)
1322 : : {
1323 : : union cn10k_ml_error_code *error_code;
1324 : :
1325 : : PLT_SET_USED(cnxk_mldev);
1326 : :
1327 : : error_code = (union cn10k_ml_error_code *)&op->impl_opaque;
1328 : :
1329 : : /* Copy sub error message */
1330 [ # # ]: 0 : if (error_code->s.etype == ML_CN10K_ETYPE_HW_NONFATAL) {
1331 [ # # ]: 0 : if (error_code->s.stype < PLT_DIM(ml_stype_db_hw_nf))
1332 : 0 : snprintf(error->message, RTE_ML_STR_MAX, "%s : %s",
1333 : 0 : ml_etype_db[error_code->s.etype].str,
1334 : 0 : ml_stype_db_hw_nf[error_code->s.stype].str);
1335 : : else
1336 : 0 : snprintf(error->message, RTE_ML_STR_MAX, "%s : UNKNOWN ERROR",
1337 : 0 : ml_etype_db[error_code->s.etype].str);
1338 [ # # ]: 0 : } else if (error_code->s.etype == ML_CN10K_ETYPE_DRIVER) {
1339 : 0 : snprintf(error->message, RTE_ML_STR_MAX, "%s : %s",
1340 : 0 : ml_etype_db[error_code->s.etype].str,
1341 : 0 : ml_stype_db_driver[error_code->s.stype].str);
1342 : : } else {
1343 : 0 : snprintf(error->message, RTE_ML_STR_MAX, "%s",
1344 : 0 : ml_etype_db[error_code->s.etype].str);
1345 : : }
1346 : :
1347 : 0 : error->errcode = error_code->u64;
1348 : :
1349 : 0 : return 0;
1350 : : }
1351 : :
1352 : : __rte_hot int
1353 : 0 : cn10k_ml_inference_sync(void *device, uint16_t index, void *input, void *output,
1354 : : uint16_t nb_batches)
1355 : : {
1356 : : union cn10k_ml_error_code *error_code;
1357 : : struct cn10k_ml_dev *cn10k_mldev;
1358 : : struct cnxk_ml_dev *cnxk_mldev;
1359 : : struct cnxk_ml_model *model;
1360 : : struct cnxk_ml_layer *layer;
1361 : : struct cnxk_ml_req *req;
1362 : : struct rte_ml_op op;
1363 : : uint16_t model_id;
1364 : : uint16_t layer_id;
1365 : : bool timeout;
1366 : : int ret = 0;
1367 : :
1368 : : cnxk_mldev = (struct cnxk_ml_dev *)device;
1369 : : cn10k_mldev = &cnxk_mldev->cn10k_mldev;
1370 : 0 : model_id = cnxk_mldev->index_map[index].model_id;
1371 : 0 : layer_id = cnxk_mldev->index_map[index].layer_id;
1372 : 0 : model = cnxk_mldev->mldev->data->models[model_id];
1373 : 0 : layer = &model->layer[layer_id];
1374 : 0 : req = layer->glow.req;
1375 : :
1376 : 0 : op.model_id = index;
1377 : 0 : op.impl_opaque = 0;
1378 : :
1379 : 0 : cn10k_ml_set_poll_addr(req);
1380 : : cn10k_ml_prep_fp_job_descriptor(cnxk_mldev, req, index, input, output, nb_batches);
1381 : :
1382 : : memset(&req->cn10k_req.result, 0, sizeof(struct cn10k_ml_result));
1383 : : error_code = (union cn10k_ml_error_code *)&req->cn10k_req.result.error_code;
1384 : 0 : error_code->s.etype = ML_CN10K_ETYPE_UNKNOWN;
1385 : : req->cn10k_req.result.user_ptr = NULL;
1386 : :
1387 : 0 : cnxk_ml_set_poll_ptr(req);
1388 : 0 : req->cn10k_req.jcmd.w1.s.jobptr = PLT_U64_CAST(&req->cn10k_req.jd);
1389 : :
1390 : : timeout = true;
1391 : 0 : req->timeout = plt_tsc_cycles() + ML_CNXK_CMD_TIMEOUT * plt_tsc_hz();
1392 : : do {
1393 [ # # ]: 0 : if (cn10k_mldev->ml_jcmdq_enqueue(&cn10k_mldev->roc, &req->cn10k_req.jcmd)) {
1394 : 0 : req->op = &op;
1395 : : timeout = false;
1396 : : break;
1397 : : }
1398 [ # # ]: 0 : } while (plt_tsc_cycles() < req->timeout);
1399 : :
1400 : : if (timeout) {
1401 : : ret = -EBUSY;
1402 : 0 : goto error_enqueue;
1403 : : }
1404 : :
1405 : : timeout = true;
1406 : : do {
1407 [ # # ]: 0 : if (cnxk_ml_get_poll_ptr(req) == ML_CNXK_POLL_JOB_FINISH) {
1408 : : timeout = false;
1409 : : break;
1410 : : }
1411 [ # # ]: 0 : } while (plt_tsc_cycles() < req->timeout);
1412 : :
1413 [ # # ]: 0 : if (timeout)
1414 : : ret = -ETIME;
1415 : : else
1416 : 0 : cn10k_ml_result_update(cnxk_mldev, -1, req);
1417 : :
1418 : 0 : error_enqueue:
1419 : 0 : return ret;
1420 : : }
1421 : :
1422 : : int
1423 : 0 : cn10k_ml_io_alloc(void *device, uint16_t model_id, const char *layer_name, uint64_t **input_qbuffer,
1424 : : uint64_t **output_qbuffer)
1425 : : {
1426 : : struct cnxk_ml_dev *cnxk_mldev;
1427 : : struct cnxk_ml_model *model;
1428 : : struct cnxk_ml_layer *layer;
1429 : :
1430 : : char str[RTE_MEMZONE_NAMESIZE];
1431 : : const struct plt_memzone *mz;
1432 : : uint64_t output_size;
1433 : : uint64_t input_size;
1434 : : uint16_t layer_id;
1435 : : int ret;
1436 : :
1437 : : cnxk_mldev = (struct cnxk_ml_dev *)device;
1438 [ # # ]: 0 : if (cnxk_mldev == NULL) {
1439 : 0 : plt_err("Invalid device = %p", device);
1440 : 0 : return -EINVAL;
1441 : : }
1442 : :
1443 : 0 : model = cnxk_mldev->mldev->data->models[model_id];
1444 [ # # ]: 0 : if (model == NULL) {
1445 : 0 : plt_err("Invalid model_id = %u", model_id);
1446 : 0 : return -EINVAL;
1447 : : }
1448 : :
1449 : 0 : ret = cn10k_ml_model_get_layer_id(model, layer_name, &layer_id);
1450 [ # # ]: 0 : if (ret != 0)
1451 : : return ret;
1452 : :
1453 : 0 : layer = &model->layer[layer_id];
1454 : 0 : input_size = PLT_ALIGN_CEIL(layer->info.total_input_sz_q, ML_CN10K_ALIGN_SIZE);
1455 : 0 : output_size = PLT_ALIGN_CEIL(layer->info.total_output_sz_q, ML_CN10K_ALIGN_SIZE);
1456 : :
1457 : 0 : sprintf(str, "cn10k_ml_io_mz_%u_%u", model_id, layer_id);
1458 : 0 : mz = plt_memzone_reserve_aligned(str, input_size + output_size, 0, ML_CN10K_ALIGN_SIZE);
1459 [ # # ]: 0 : if (mz == NULL) {
1460 : 0 : plt_err("io_alloc failed: Unable to allocate memory: model_id = %u, layer_name = %s",
1461 : : model_id, layer_name);
1462 : 0 : return -ENOMEM;
1463 : : }
1464 : :
1465 : 0 : *input_qbuffer = mz->addr;
1466 : 0 : *output_qbuffer = PLT_PTR_ADD(mz->addr, input_size);
1467 : :
1468 : 0 : return 0;
1469 : : }
1470 : :
1471 : : int
1472 : 0 : cn10k_ml_io_free(void *device, uint16_t model_id, const char *layer_name)
1473 : : {
1474 : : struct cnxk_ml_dev *cnxk_mldev;
1475 : : struct cnxk_ml_model *model;
1476 : :
1477 : : char str[RTE_MEMZONE_NAMESIZE];
1478 : : const struct plt_memzone *mz;
1479 : : uint16_t layer_id;
1480 : : int ret;
1481 : :
1482 : : cnxk_mldev = (struct cnxk_ml_dev *)device;
1483 [ # # ]: 0 : if (cnxk_mldev == NULL) {
1484 : 0 : plt_err("Invalid device = %p", device);
1485 : 0 : return -EINVAL;
1486 : : }
1487 : :
1488 : 0 : model = cnxk_mldev->mldev->data->models[model_id];
1489 [ # # ]: 0 : if (model == NULL) {
1490 : 0 : plt_err("Invalid model_id = %u", model_id);
1491 : 0 : return -EINVAL;
1492 : : }
1493 : :
1494 : 0 : ret = cn10k_ml_model_get_layer_id(model, layer_name, &layer_id);
1495 [ # # ]: 0 : if (ret != 0)
1496 : : return ret;
1497 : :
1498 : 0 : sprintf(str, "cn10k_ml_io_mz_%u_%u", model_id, layer_id);
1499 : 0 : mz = plt_memzone_lookup(str);
1500 [ # # ]: 0 : if (mz == NULL) {
1501 : 0 : plt_err("io_free failed: Memzone not found: model_id = %u, layer_name = %s",
1502 : : model_id, layer_name);
1503 : 0 : return -EINVAL;
1504 : : }
1505 : :
1506 : 0 : return plt_memzone_free(mz);
1507 : : }
1508 : :
1509 : : int
1510 : 0 : cn10k_ml_malloc(const char *name, size_t size, uint32_t align, void **addr)
1511 : : {
1512 : : const struct plt_memzone *mz;
1513 : :
1514 : 0 : mz = plt_memzone_reserve_aligned(name, size, 0, align);
1515 [ # # ]: 0 : if (mz == NULL) {
1516 : 0 : plt_err("ml_malloc failed: Unable to allocate memory: name = %s", name);
1517 : 0 : return -ENOMEM;
1518 : : }
1519 : :
1520 : 0 : *addr = mz->addr;
1521 : :
1522 : 0 : return 0;
1523 : : }
1524 : :
1525 : : int
1526 : 0 : cn10k_ml_free(const char *name)
1527 : : {
1528 : : const struct plt_memzone *mz;
1529 : :
1530 : 0 : mz = plt_memzone_lookup(name);
1531 [ # # ]: 0 : if (mz == NULL) {
1532 : 0 : plt_err("ml_free failed: Memzone not found: name = %s", name);
1533 : 0 : return -EINVAL;
1534 : : }
1535 : :
1536 : 0 : return plt_memzone_free(mz);
1537 : : }
|