Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright (c) 2022 Marvell.
3 : : */
4 : :
5 : : #include <rte_mldev.h>
6 : : #include <rte_mldev_pmd.h>
7 : :
8 : : #include <mldev_utils.h>
9 : :
10 : : #include "cnxk_ml_dev.h"
11 : : #include "cnxk_ml_model.h"
12 : : #include "cnxk_ml_ops.h"
13 : : #include "cnxk_ml_xstats.h"
14 : :
15 : : /* ML model macros */
16 : : #define CN10K_ML_MODEL_MEMZONE_NAME "ml_cn10k_model_mz"
17 : :
18 : : /* ML layer macros */
19 : : #define CN10K_ML_LAYER_MEMZONE_NAME "ml_cn10k_layer_mz"
20 : :
21 : : /* ML Job descriptor flags */
22 : : #define ML_FLAGS_POLL_COMPL BIT(0)
23 : : #define ML_FLAGS_SSO_COMPL BIT(1)
24 : :
25 : : /* Hardware non-fatal error subtype database */
26 : : static struct cnxk_ml_error_db ml_stype_db_hw_nf[] = {
27 : : {ML_CN10K_FW_ERR_NOERR, "NO ERROR"},
28 : : {ML_CN10K_FW_ERR_UNLOAD_ID_NOT_FOUND, "UNLOAD MODEL ID NOT FOUND"},
29 : : {ML_CN10K_FW_ERR_LOAD_LUT_OVERFLOW, "LOAD LUT OVERFLOW"},
30 : : {ML_CN10K_FW_ERR_ID_IN_USE, "MODEL ID IN USE"},
31 : : {ML_CN10K_FW_ERR_INVALID_TILEMASK, "INVALID TILEMASK"},
32 : : {ML_CN10K_FW_ERR_RUN_LUT_OVERFLOW, "RUN LUT OVERFLOW"},
33 : : {ML_CN10K_FW_ERR_RUN_ID_NOT_FOUND, "RUN MODEL ID NOT FOUND"},
34 : : {ML_CN10K_FW_ERR_COMMAND_NOTSUP, "COMMAND NOT SUPPORTED"},
35 : : {ML_CN10K_FW_ERR_DDR_ADDR_RANGE, "DDR ADDRESS OUT OF RANGE"},
36 : : {ML_CN10K_FW_ERR_NUM_BATCHES_INVALID, "INVALID BATCHES"},
37 : : {ML_CN10K_FW_ERR_INSSYNC_TIMEOUT, "INSSYNC TIMEOUT"},
38 : : };
39 : :
40 : : /* Driver error subtype database */
41 : : static struct cnxk_ml_error_db ml_stype_db_driver[] = {
42 : : {ML_CN10K_DRIVER_ERR_NOERR, "NO ERROR"},
43 : : {ML_CN10K_DRIVER_ERR_UNKNOWN, "UNKNOWN ERROR"},
44 : : {ML_CN10K_DRIVER_ERR_EXCEPTION, "FW EXCEPTION"},
45 : : {ML_CN10K_DRIVER_ERR_FW_ERROR, "UNKNOWN FIRMWARE ERROR"},
46 : : };
47 : :
48 : : __rte_hot void
49 : 0 : cn10k_ml_set_poll_addr(struct cnxk_ml_req *req)
50 : : {
51 : 0 : req->status = &req->cn10k_req.status;
52 : 0 : }
53 : :
54 : : void
55 : 0 : cn10k_ml_qp_initialize(struct cnxk_ml_dev *cnxk_mldev, struct cnxk_ml_qp *qp)
56 : : {
57 : : uint64_t i;
58 : :
59 : : RTE_SET_USED(cnxk_mldev);
60 : :
61 : : /* Initialize job command */
62 [ # # ]: 0 : for (i = 0; i < qp->nb_desc; i++) {
63 : 0 : memset(&qp->queue.reqs[i].cn10k_req.jd, 0, sizeof(struct cn10k_ml_jd));
64 : 0 : qp->queue.reqs[i].cn10k_req.jcmd.w1.s.jobptr =
65 : 0 : PLT_U64_CAST(&qp->queue.reqs[i].cn10k_req.jd);
66 : : }
67 : 0 : }
68 : :
69 : : static void
70 : 0 : cn10k_ml_prep_sp_job_descriptor(struct cnxk_ml_dev *cnxk_mldev, struct cnxk_ml_layer *layer,
71 : : struct cnxk_ml_req *req, enum cn10k_ml_job_type job_type)
72 : : {
73 : : struct cn10k_ml_model_metadata *metadata;
74 : : struct cn10k_ml_layer_addr *addr;
75 : : struct cn10k_ml_dev *cn10k_mldev;
76 : :
77 : : cn10k_mldev = &cnxk_mldev->cn10k_mldev;
78 : : metadata = &layer->glow.metadata;
79 : : addr = &layer->glow.addr;
80 : :
81 : 0 : memset(&req->cn10k_req.jd, 0, sizeof(struct cn10k_ml_jd));
82 : : req->cn10k_req.jd.hdr.jce.w0.u64 = 0;
83 : 0 : req->cn10k_req.jd.hdr.jce.w1.u64 = PLT_U64_CAST(&req->cn10k_req.status);
84 : 0 : req->cn10k_req.jd.hdr.model_id = layer->index;
85 : 0 : req->cn10k_req.jd.hdr.job_type = job_type;
86 : : req->cn10k_req.jd.hdr.fp_flags = 0x0;
87 : 0 : req->cn10k_req.jd.hdr.result =
88 : 0 : roc_ml_addr_ap2mlip(&cn10k_mldev->roc, &req->cn10k_req.result);
89 : :
90 [ # # ]: 0 : if (job_type == ML_CN10K_JOB_TYPE_MODEL_START) {
91 [ # # ]: 0 : if (!layer->glow.metadata.model.ocm_relocatable)
92 : 0 : req->cn10k_req.jd.hdr.sp_flags = ML_CN10K_SP_FLAGS_OCM_NONRELOCATABLE;
93 : : else
94 : 0 : req->cn10k_req.jd.hdr.sp_flags = 0x0;
95 : :
96 : 0 : req->cn10k_req.jd.hdr.sp_flags |= ML_CN10K_SP_FLAGS_EXTENDED_LOAD_JD;
97 : 0 : req->cn10k_req.jd.model_start.extended_args = PLT_U64_CAST(
98 : : roc_ml_addr_ap2mlip(&cn10k_mldev->roc, &req->cn10k_req.extended_args));
99 : 0 : req->cn10k_req.jd.model_start.model_dst_ddr_addr =
100 : 0 : PLT_U64_CAST(roc_ml_addr_ap2mlip(&cn10k_mldev->roc, addr->init_load_addr));
101 : 0 : req->cn10k_req.jd.model_start.model_init_offset = 0x0;
102 : 0 : req->cn10k_req.jd.model_start.model_main_offset = metadata->init_model.file_size;
103 : 0 : req->cn10k_req.jd.model_start.model_finish_offset =
104 : 0 : metadata->init_model.file_size + metadata->main_model.file_size;
105 : 0 : req->cn10k_req.jd.model_start.model_init_size = metadata->init_model.file_size;
106 : 0 : req->cn10k_req.jd.model_start.model_main_size = metadata->main_model.file_size;
107 : 0 : req->cn10k_req.jd.model_start.model_finish_size = metadata->finish_model.file_size;
108 : 0 : req->cn10k_req.jd.model_start.model_wb_offset = metadata->init_model.file_size +
109 : 0 : metadata->main_model.file_size +
110 : : metadata->finish_model.file_size;
111 : 0 : req->cn10k_req.jd.model_start.num_layers = metadata->model.num_layers;
112 : 0 : req->cn10k_req.jd.model_start.num_gather_entries = 0;
113 : 0 : req->cn10k_req.jd.model_start.num_scatter_entries = 0;
114 : 0 : req->cn10k_req.jd.model_start.tilemask = 0; /* Updated after reserving pages */
115 : 0 : req->cn10k_req.jd.model_start.batch_size = layer->batch_size;
116 : 0 : req->cn10k_req.jd.model_start.ocm_wb_base_address =
117 : : 0; /* Updated after reserving pages */
118 : 0 : req->cn10k_req.jd.model_start.ocm_wb_range_start =
119 : 0 : metadata->model.ocm_wb_range_start;
120 : 0 : req->cn10k_req.jd.model_start.ocm_wb_range_end = metadata->model.ocm_wb_range_end;
121 : 0 : req->cn10k_req.jd.model_start.ddr_wb_base_address =
122 : 0 : PLT_U64_CAST(roc_ml_addr_ap2mlip(
123 : : &cn10k_mldev->roc, PLT_PTR_ADD(addr->finish_load_addr,
124 : : metadata->finish_model.file_size)));
125 : 0 : req->cn10k_req.jd.model_start.ddr_wb_range_start =
126 : 0 : metadata->model.ddr_wb_range_start;
127 : 0 : req->cn10k_req.jd.model_start.ddr_wb_range_end = metadata->model.ddr_wb_range_end;
128 : 0 : req->cn10k_req.jd.model_start.input.s.ddr_range_start =
129 : 0 : metadata->model.ddr_input_range_start;
130 : 0 : req->cn10k_req.jd.model_start.input.s.ddr_range_end =
131 : 0 : metadata->model.ddr_input_range_end;
132 : 0 : req->cn10k_req.jd.model_start.output.s.ddr_range_start =
133 : 0 : metadata->model.ddr_output_range_start;
134 : 0 : req->cn10k_req.jd.model_start.output.s.ddr_range_end =
135 : 0 : metadata->model.ddr_output_range_end;
136 : :
137 : 0 : req->cn10k_req.extended_args.start.ddr_scratch_base_address = PLT_U64_CAST(
138 : : roc_ml_addr_ap2mlip(&cn10k_mldev->roc, addr->scratch_base_addr));
139 : 0 : req->cn10k_req.extended_args.start.ddr_scratch_range_start =
140 : 0 : metadata->model.ddr_scratch_range_start;
141 : 0 : req->cn10k_req.extended_args.start.ddr_scratch_range_end =
142 : 0 : metadata->model.ddr_scratch_range_end;
143 : : }
144 : 0 : }
145 : :
146 : : static __rte_always_inline void
147 : : cn10k_ml_prep_fp_job_descriptor(struct cnxk_ml_dev *cnxk_mldev, struct cnxk_ml_req *req,
148 : : uint16_t index, void *input, void *output, uint16_t nb_batches)
149 : : {
150 : : struct cn10k_ml_dev *cn10k_mldev;
151 : :
152 : : cn10k_mldev = &cnxk_mldev->cn10k_mldev;
153 : :
154 : 0 : req->cn10k_req.jd.hdr.jce.w0.u64 = 0;
155 : 0 : req->cn10k_req.jd.hdr.jce.w1.u64 = PLT_U64_CAST(req->status);
156 : 0 : req->cn10k_req.jd.hdr.model_id = index;
157 : 0 : req->cn10k_req.jd.hdr.job_type = ML_CN10K_JOB_TYPE_MODEL_RUN;
158 : 0 : req->cn10k_req.jd.hdr.fp_flags = ML_FLAGS_POLL_COMPL;
159 : 0 : req->cn10k_req.jd.hdr.sp_flags = 0x0;
160 : 0 : req->cn10k_req.jd.hdr.result =
161 : 0 : roc_ml_addr_ap2mlip(&cn10k_mldev->roc, &req->cn10k_req.result);
162 : 0 : req->cn10k_req.jd.model_run.input_ddr_addr =
163 : 0 : PLT_U64_CAST(roc_ml_addr_ap2mlip(&cn10k_mldev->roc, input));
164 : 0 : req->cn10k_req.jd.model_run.output_ddr_addr =
165 : 0 : PLT_U64_CAST(roc_ml_addr_ap2mlip(&cn10k_mldev->roc, output));
166 : 0 : req->cn10k_req.jd.model_run.num_batches = nb_batches;
167 : : }
168 : :
169 : : static void
170 : 0 : cn10k_ml_xstats_layer_name_update(struct cnxk_ml_dev *cnxk_mldev, uint16_t model_id,
171 : : uint16_t layer_id)
172 : : {
173 : : struct cnxk_ml_model *model;
174 : : struct cnxk_ml_layer *layer;
175 : : uint16_t rclk_freq;
176 : : uint16_t sclk_freq;
177 : : uint16_t stat_id;
178 : : char suffix[8];
179 : : uint16_t i;
180 : :
181 : 0 : model = cnxk_mldev->mldev->data->models[model_id];
182 : 0 : layer = &model->layer[layer_id];
183 : 0 : stat_id = cnxk_mldev->xstats.offset_for_layer[model_id][layer_id];
184 : :
185 : 0 : roc_clk_freq_get(&rclk_freq, &sclk_freq);
186 [ # # ]: 0 : if (sclk_freq == 0)
187 : : strcpy(suffix, "cycles");
188 : : else
189 : : strcpy(suffix, "ns");
190 : :
191 : : /* Update xstat name based on layer name and sclk availability */
192 [ # # ]: 0 : for (i = 0; i < RTE_DIM(layer_xstats); i++) {
193 : 0 : snprintf(cnxk_mldev->xstats.entries[stat_id].map.name,
194 : : sizeof(cnxk_mldev->xstats.entries[stat_id].map.name), "%s-%s-%s",
195 : 0 : layer->glow.metadata.model.name, layer_xstats[i].name, suffix);
196 : 0 : stat_id++;
197 : : }
198 : 0 : }
199 : :
200 : : void
201 : 0 : cn10k_ml_xstat_model_name_set(struct cnxk_ml_dev *cnxk_mldev, struct cnxk_ml_model *model,
202 : : uint16_t stat_id, uint16_t entry, char *suffix)
203 : : {
204 : 0 : snprintf(cnxk_mldev->xstats.entries[stat_id].map.name,
205 : : sizeof(cnxk_mldev->xstats.entries[stat_id].map.name), "%s-%s-%s",
206 : 0 : model->glow.metadata.model.name, model_xstats[entry].name, suffix);
207 : 0 : }
208 : :
209 : : #define ML_AVG_FOREACH_QP(cnxk_mldev, layer, qp_id, str, value, count) \
210 : : do { \
211 : : value = 0; \
212 : : for (qp_id = 0; qp_id < cnxk_mldev->mldev->data->nb_queue_pairs; qp_id++) { \
213 : : value += layer->glow.burst_xstats[qp_id].str##_latency_tot; \
214 : : count += layer->glow.burst_xstats[qp_id].dequeued_count - \
215 : : layer->glow.burst_xstats[qp_id].str##_reset_count; \
216 : : } \
217 : : value += layer->glow.sync_xstats->str##_latency_tot; \
218 : : count += layer->glow.sync_xstats->dequeued_count - \
219 : : layer->glow.sync_xstats->str##_reset_count; \
220 : : if (count != 0) \
221 : : value = value / count; \
222 : : } while (0)
223 : :
224 : : #define ML_MIN_FOREACH_QP(cnxk_mldev, layer, qp_id, str, value, count) \
225 : : do { \
226 : : value = UINT64_MAX; \
227 : : for (qp_id = 0; qp_id < cnxk_mldev->mldev->data->nb_queue_pairs; qp_id++) { \
228 : : value = PLT_MIN(value, layer->glow.burst_xstats[qp_id].str##_latency_min); \
229 : : count += layer->glow.burst_xstats[qp_id].dequeued_count - \
230 : : layer->glow.burst_xstats[qp_id].str##_reset_count; \
231 : : } \
232 : : value = PLT_MIN(value, layer->glow.sync_xstats->str##_latency_min); \
233 : : count += layer->glow.sync_xstats->dequeued_count - \
234 : : layer->glow.sync_xstats->str##_reset_count; \
235 : : if (count == 0) \
236 : : value = 0; \
237 : : } while (0)
238 : :
239 : : #define ML_MAX_FOREACH_QP(cnxk_mldev, layer, qp_id, str, value, count) \
240 : : do { \
241 : : value = 0; \
242 : : for (qp_id = 0; qp_id < cnxk_mldev->mldev->data->nb_queue_pairs; qp_id++) { \
243 : : value = PLT_MAX(value, layer->glow.burst_xstats[qp_id].str##_latency_max); \
244 : : count += layer->glow.burst_xstats[qp_id].dequeued_count - \
245 : : layer->glow.burst_xstats[qp_id].str##_reset_count; \
246 : : } \
247 : : value = PLT_MAX(value, layer->glow.sync_xstats->str##_latency_max); \
248 : : count += layer->glow.sync_xstats->dequeued_count - \
249 : : layer->glow.sync_xstats->str##_reset_count; \
250 : : if (count == 0) \
251 : : value = 0; \
252 : : } while (0)
253 : :
254 : : uint64_t
255 : 0 : cn10k_ml_model_xstat_get(struct cnxk_ml_dev *cnxk_mldev, struct cnxk_ml_layer *layer,
256 : : enum cnxk_ml_xstats_type type)
257 : : {
258 : : uint64_t count = 0;
259 : : uint64_t value = 0;
260 : : uint32_t qp_id;
261 : :
262 [ # # # # : 0 : switch (type) {
# # # ]
263 : : case avg_hw_latency:
264 [ # # # # ]: 0 : ML_AVG_FOREACH_QP(cnxk_mldev, layer, qp_id, hw, value, count);
265 : : break;
266 : : case min_hw_latency:
267 [ # # # # ]: 0 : ML_MIN_FOREACH_QP(cnxk_mldev, layer, qp_id, hw, value, count);
268 : : break;
269 : : case max_hw_latency:
270 [ # # # # ]: 0 : ML_MAX_FOREACH_QP(cnxk_mldev, layer, qp_id, hw, value, count);
271 : : break;
272 : : case avg_fw_latency:
273 [ # # # # ]: 0 : ML_AVG_FOREACH_QP(cnxk_mldev, layer, qp_id, fw, value, count);
274 : : break;
275 : : case min_fw_latency:
276 [ # # # # ]: 0 : ML_MIN_FOREACH_QP(cnxk_mldev, layer, qp_id, fw, value, count);
277 : : break;
278 : : case max_fw_latency:
279 [ # # # # ]: 0 : ML_MAX_FOREACH_QP(cnxk_mldev, layer, qp_id, fw, value, count);
280 : : break;
281 : : default:
282 : : value = 0;
283 : : }
284 : :
285 : 0 : return value;
286 : : }
287 : :
288 : : static int
289 : 0 : cn10k_ml_cache_model_data(struct cnxk_ml_dev *cnxk_mldev, struct cnxk_ml_layer *layer)
290 : : {
291 : : 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 [ # # ]: 0 : 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 : :
788 : 0 : return 0;
789 : : }
790 : :
791 : : int
792 : 0 : cn10k_ml_layer_unload(void *device, uint16_t model_id, const char *layer_name)
793 : : {
794 : : struct cnxk_ml_dev *cnxk_mldev;
795 : : struct cnxk_ml_model *model;
796 : : struct cnxk_ml_layer *layer;
797 : :
798 : : char str[RTE_MEMZONE_NAMESIZE];
799 : : uint16_t layer_id;
800 : : int ret;
801 : :
802 : : cnxk_mldev = (struct cnxk_ml_dev *)device;
803 [ # # ]: 0 : if (cnxk_mldev == NULL) {
804 : 0 : plt_err("Invalid device = %p", device);
805 : 0 : return -EINVAL;
806 : : }
807 : :
808 : 0 : model = cnxk_mldev->mldev->data->models[model_id];
809 [ # # ]: 0 : if (model == NULL) {
810 : 0 : plt_err("Invalid model_id = %u", model_id);
811 : 0 : return -EINVAL;
812 : : }
813 : :
814 : 0 : ret = cn10k_ml_model_get_layer_id(model, layer_name, &layer_id);
815 [ # # ]: 0 : if (ret != 0)
816 : : return ret;
817 : :
818 : 0 : layer = &model->layer[layer_id];
819 : :
820 : 0 : snprintf(str, RTE_MEMZONE_NAMESIZE, "%s_%u_%u", CN10K_ML_LAYER_MEMZONE_NAME,
821 : 0 : model->model_id, layer_id);
822 : 0 : ret = plt_memzone_free(plt_memzone_lookup(str));
823 : :
824 : 0 : layer->state = ML_CNXK_LAYER_STATE_UNKNOWN;
825 : 0 : cnxk_mldev->index_map[layer->index].active = false;
826 : :
827 : 0 : return ret;
828 : : }
829 : :
830 : : int
831 : 0 : cn10k_ml_model_unload(struct cnxk_ml_dev *cnxk_mldev, struct cnxk_ml_model *model)
832 : : {
833 : 0 : return cn10k_ml_layer_unload(cnxk_mldev, model->model_id, NULL);
834 : : }
835 : :
836 : : int
837 : 0 : cn10k_ml_layer_start(void *device, uint16_t model_id, const char *layer_name)
838 : : {
839 : : struct cn10k_ml_dev *cn10k_mldev;
840 : : struct cnxk_ml_dev *cnxk_mldev;
841 : : struct cnxk_ml_model *model;
842 : : struct cnxk_ml_layer *layer;
843 : : struct cn10k_ml_ocm *ocm;
844 : : struct cnxk_ml_req *req;
845 : :
846 : : uint16_t layer_id;
847 : : bool job_enqueued;
848 : : bool job_dequeued;
849 : : uint8_t num_tiles;
850 : : uint64_t tilemask;
851 : : int wb_page_start;
852 : : int tile_start;
853 : : int tile_end;
854 : : bool locked;
855 : : int ret = 0;
856 : :
857 : : cnxk_mldev = (struct cnxk_ml_dev *)device;
858 [ # # ]: 0 : if (cnxk_mldev == NULL) {
859 : 0 : plt_err("Invalid device = %p", device);
860 : 0 : return -EINVAL;
861 : : }
862 : :
863 : 0 : model = cnxk_mldev->mldev->data->models[model_id];
864 [ # # ]: 0 : if (model == NULL) {
865 : 0 : plt_err("Invalid model_id = %u", model_id);
866 : 0 : return -EINVAL;
867 : : }
868 : :
869 : 0 : ret = cn10k_ml_model_get_layer_id(model, layer_name, &layer_id);
870 [ # # ]: 0 : if (ret != 0)
871 : : return ret;
872 : :
873 : 0 : layer = &model->layer[layer_id];
874 : : cn10k_mldev = &cnxk_mldev->cn10k_mldev;
875 : : ocm = &cn10k_mldev->ocm;
876 : :
877 : : /* Prepare JD */
878 : 0 : req = layer->glow.req;
879 : 0 : cn10k_ml_prep_sp_job_descriptor(cnxk_mldev, layer, req, ML_CN10K_JOB_TYPE_MODEL_START);
880 : 0 : req->cn10k_req.result.error_code = 0x0;
881 : 0 : req->cn10k_req.result.user_ptr = NULL;
882 : :
883 : : plt_write64(ML_CNXK_POLL_JOB_START, &req->cn10k_req.status);
884 : : plt_wmb();
885 : :
886 : 0 : num_tiles = layer->glow.metadata.model.tile_end - layer->glow.metadata.model.tile_start + 1;
887 : :
888 : : locked = false;
889 : 0 : while (!locked) {
890 [ # # ]: 0 : if (plt_spinlock_trylock(&model->lock) != 0) {
891 [ # # ]: 0 : if (layer->state == ML_CNXK_LAYER_STATE_STARTED) {
892 : 0 : plt_ml_dbg("Layer already started, model_id = %u, layer_id = %u",
893 : : model->model_id, layer_id);
894 : : plt_spinlock_unlock(&model->lock);
895 : 0 : return 1;
896 : : }
897 : :
898 [ # # ]: 0 : if (layer->state == ML_CNXK_LAYER_STATE_JOB_ACTIVE) {
899 : 0 : plt_err("A slow-path job is active for the model_id = %u",
900 : : model->model_id);
901 : : plt_spinlock_unlock(&model->lock);
902 : 0 : return -EBUSY;
903 : : }
904 : :
905 : 0 : layer->state = ML_CNXK_LAYER_STATE_JOB_ACTIVE;
906 : : plt_spinlock_unlock(&model->lock);
907 : : locked = true;
908 : : }
909 : : }
910 : :
911 [ # # ]: 0 : while (!layer->glow.ocm_map.ocm_reserved) {
912 [ # # ]: 0 : if (plt_spinlock_trylock(&ocm->lock) != 0) {
913 : 0 : wb_page_start = cn10k_ml_ocm_tilemask_find(
914 : 0 : cnxk_mldev, num_tiles, layer->glow.ocm_map.wb_pages,
915 : 0 : layer->glow.ocm_map.scratch_pages, &tilemask);
916 : :
917 [ # # ]: 0 : if (wb_page_start == -1) {
918 : 0 : plt_err("Free pages not available on OCM tiles");
919 : 0 : plt_err("Failed to start layer, model_id = %u, layer_id = %u",
920 : : model->model_id, layer_id);
921 : : plt_spinlock_unlock(&ocm->lock);
922 : 0 : return -ENOMEM;
923 : : }
924 : :
925 : 0 : layer->glow.ocm_map.tilemask = tilemask;
926 : 0 : layer->glow.ocm_map.wb_page_start = wb_page_start;
927 : :
928 : 0 : cn10k_ml_ocm_reserve_pages(
929 : 0 : cnxk_mldev, model->model_id, layer_id, layer->glow.ocm_map.tilemask,
930 : 0 : layer->glow.ocm_map.wb_page_start, layer->glow.ocm_map.wb_pages,
931 : 0 : layer->glow.ocm_map.scratch_pages);
932 : 0 : layer->glow.ocm_map.ocm_reserved = true;
933 : : plt_spinlock_unlock(&ocm->lock);
934 : : }
935 : : }
936 : :
937 : : /* Update JD */
938 : 0 : cn10k_ml_ocm_tilecount(layer->glow.ocm_map.tilemask, &tile_start, &tile_end);
939 : 0 : req->cn10k_req.jd.model_start.tilemask = GENMASK_ULL(tile_end, tile_start);
940 : 0 : req->cn10k_req.jd.model_start.ocm_wb_base_address =
941 : 0 : layer->glow.ocm_map.wb_page_start * ocm->page_size;
942 : :
943 : : job_enqueued = false;
944 : : job_dequeued = false;
945 : : do {
946 [ # # ]: 0 : if (!job_enqueued) {
947 : 0 : req->timeout = plt_tsc_cycles() + ML_CNXK_CMD_TIMEOUT * plt_tsc_hz();
948 : : job_enqueued =
949 : 0 : roc_ml_scratch_enqueue(&cn10k_mldev->roc, &req->cn10k_req.jd);
950 : : }
951 : :
952 [ # # ]: 0 : if (job_enqueued && !job_dequeued)
953 : : job_dequeued =
954 : 0 : roc_ml_scratch_dequeue(&cn10k_mldev->roc, &req->cn10k_req.jd);
955 : :
956 [ # # ]: 0 : if (job_dequeued)
957 : : break;
958 [ # # ]: 0 : } while (plt_tsc_cycles() < req->timeout);
959 : :
960 [ # # ]: 0 : if (job_dequeued) {
961 [ # # ]: 0 : if (plt_read64(&req->cn10k_req.status) == ML_CNXK_POLL_JOB_FINISH) {
962 [ # # ]: 0 : if (req->cn10k_req.result.error_code == 0)
963 : : ret = 0;
964 : : else
965 : : ret = -1;
966 : : }
967 : : } else { /* Reset scratch registers */
968 : 0 : roc_ml_scratch_queue_reset(&cn10k_mldev->roc);
969 : : ret = -ETIME;
970 : : }
971 : :
972 : : locked = false;
973 : 0 : while (!locked) {
974 [ # # ]: 0 : if (plt_spinlock_trylock(&model->lock) != 0) {
975 [ # # ]: 0 : if (ret == 0)
976 : 0 : layer->state = ML_CNXK_LAYER_STATE_STARTED;
977 : : else
978 : 0 : layer->state = ML_CNXK_LAYER_STATE_UNKNOWN;
979 : :
980 : : plt_spinlock_unlock(&model->lock);
981 : : locked = true;
982 : : }
983 : : }
984 : :
985 [ # # ]: 0 : if (layer->state == ML_CNXK_LAYER_STATE_UNKNOWN) {
986 [ # # ]: 0 : while (layer->glow.ocm_map.ocm_reserved) {
987 [ # # ]: 0 : if (plt_spinlock_trylock(&ocm->lock) != 0) {
988 : 0 : cn10k_ml_ocm_free_pages(cnxk_mldev, model->model_id, layer_id);
989 : 0 : layer->glow.ocm_map.ocm_reserved = false;
990 : 0 : layer->glow.ocm_map.tilemask = 0x0;
991 : : plt_spinlock_unlock(&ocm->lock);
992 : : }
993 : : }
994 : : }
995 : :
996 [ # # ]: 0 : if (ret < 0) {
997 : 0 : cn10k_ml_layer_stop(device, model_id, layer_name);
998 : : } else {
999 [ # # ]: 0 : if (cn10k_mldev->cache_model_data) {
1000 : 0 : if ((model->type == ML_CNXK_MODEL_TYPE_GLOW &&
1001 [ # # ]: 0 : model->subtype == ML_CNXK_MODEL_SUBTYPE_GLOW_MRVL) ||
1002 : : (model->type == ML_CNXK_MODEL_TYPE_TVM &&
1003 : : model->subtype == ML_CNXK_MODEL_SUBTYPE_TVM_MRVL))
1004 : 0 : ret = cn10k_ml_cache_model_data(cnxk_mldev, layer);
1005 : : }
1006 : : }
1007 : :
1008 : : return ret;
1009 : : }
1010 : :
1011 : : int
1012 : 0 : cn10k_ml_model_start(struct cnxk_ml_dev *cnxk_mldev, struct cnxk_ml_model *model)
1013 : : {
1014 : : struct cnxk_ml_layer *layer;
1015 : : int ret;
1016 : :
1017 : : layer = &model->layer[0];
1018 : 0 : ret = cn10k_ml_layer_start(cnxk_mldev, model->model_id, layer->name);
1019 [ # # ]: 0 : if (ret != 0) {
1020 : 0 : plt_err("CN10K Model start failed, model_id = %u, error = %d", model->model_id,
1021 : : ret);
1022 : 0 : return ret;
1023 : : }
1024 : :
1025 : 0 : cnxk_mldev->nb_models_started++;
1026 : 0 : model->state = ML_CNXK_MODEL_STATE_STARTED;
1027 : :
1028 : 0 : return 0;
1029 : : }
1030 : :
1031 : : int
1032 : 0 : cn10k_ml_layer_stop(void *device, uint16_t model_id, const char *layer_name)
1033 : : {
1034 : : struct cn10k_ml_dev *cn10k_mldev;
1035 : : struct cnxk_ml_dev *cnxk_mldev;
1036 : : struct cnxk_ml_model *model;
1037 : : struct cnxk_ml_layer *layer;
1038 : : struct cn10k_ml_ocm *ocm;
1039 : : struct cnxk_ml_req *req;
1040 : :
1041 : : uint16_t layer_id;
1042 : : bool job_enqueued;
1043 : : bool job_dequeued;
1044 : : bool locked;
1045 : : int ret = 0;
1046 : :
1047 : : cnxk_mldev = (struct cnxk_ml_dev *)device;
1048 [ # # ]: 0 : if (cnxk_mldev == NULL) {
1049 : 0 : plt_err("Invalid device = %p", device);
1050 : 0 : return -EINVAL;
1051 : : }
1052 : :
1053 : 0 : model = cnxk_mldev->mldev->data->models[model_id];
1054 [ # # ]: 0 : if (model == NULL) {
1055 : 0 : plt_err("Invalid model_id = %u", model_id);
1056 : 0 : return -EINVAL;
1057 : : }
1058 : :
1059 : 0 : ret = cn10k_ml_model_get_layer_id(model, layer_name, &layer_id);
1060 [ # # ]: 0 : if (ret != 0)
1061 : : return ret;
1062 : :
1063 : 0 : layer = &model->layer[layer_id];
1064 : : cn10k_mldev = &cnxk_mldev->cn10k_mldev;
1065 : : ocm = &cn10k_mldev->ocm;
1066 : :
1067 : : /* Prepare JD */
1068 : 0 : req = layer->glow.req;
1069 : 0 : cn10k_ml_prep_sp_job_descriptor(cnxk_mldev, layer, req, ML_CN10K_JOB_TYPE_MODEL_STOP);
1070 : 0 : req->cn10k_req.result.error_code = 0x0;
1071 : 0 : req->cn10k_req.result.user_ptr = NULL;
1072 : :
1073 : : plt_write64(ML_CNXK_POLL_JOB_START, &req->cn10k_req.status);
1074 : : plt_wmb();
1075 : :
1076 : : locked = false;
1077 : 0 : while (!locked) {
1078 [ # # ]: 0 : if (plt_spinlock_trylock(&model->lock) != 0) {
1079 [ # # ]: 0 : if (layer->state == ML_CNXK_LAYER_STATE_LOADED) {
1080 : 0 : plt_ml_dbg("Layer not started, model_id = %u, layer_id = %u",
1081 : : model->model_id, layer_id);
1082 : : plt_spinlock_unlock(&model->lock);
1083 : 0 : return 1;
1084 : : }
1085 : :
1086 [ # # ]: 0 : if (layer->state == ML_CNXK_LAYER_STATE_JOB_ACTIVE) {
1087 : 0 : plt_err("A slow-path job is active for the layer, model_id = %u, layer_id = %u",
1088 : : model->model_id, layer_id);
1089 : : plt_spinlock_unlock(&model->lock);
1090 : 0 : return -EBUSY;
1091 : : }
1092 : :
1093 : 0 : layer->state = ML_CNXK_LAYER_STATE_JOB_ACTIVE;
1094 : : plt_spinlock_unlock(&model->lock);
1095 : : locked = true;
1096 : : }
1097 : : }
1098 : :
1099 [ # # ]: 0 : while (layer->glow.ocm_map.ocm_reserved) {
1100 [ # # ]: 0 : if (plt_spinlock_trylock(&ocm->lock) != 0) {
1101 : 0 : cn10k_ml_ocm_free_pages(cnxk_mldev, model->model_id, layer_id);
1102 : 0 : layer->glow.ocm_map.ocm_reserved = false;
1103 : 0 : layer->glow.ocm_map.tilemask = 0x0;
1104 : : plt_spinlock_unlock(&ocm->lock);
1105 : : }
1106 : : }
1107 : :
1108 : : job_enqueued = false;
1109 : : job_dequeued = false;
1110 : : do {
1111 [ # # ]: 0 : if (!job_enqueued) {
1112 : 0 : req->timeout = plt_tsc_cycles() + ML_CNXK_CMD_TIMEOUT * plt_tsc_hz();
1113 : : job_enqueued =
1114 : 0 : roc_ml_scratch_enqueue(&cn10k_mldev->roc, &req->cn10k_req.jd);
1115 : : }
1116 : :
1117 [ # # ]: 0 : if (job_enqueued && !job_dequeued)
1118 : : job_dequeued =
1119 : 0 : roc_ml_scratch_dequeue(&cn10k_mldev->roc, &req->cn10k_req.jd);
1120 : :
1121 [ # # ]: 0 : if (job_dequeued)
1122 : : break;
1123 [ # # ]: 0 : } while (plt_tsc_cycles() < req->timeout);
1124 : :
1125 [ # # ]: 0 : if (job_dequeued) {
1126 [ # # ]: 0 : if (plt_read64(&req->cn10k_req.status) == ML_CNXK_POLL_JOB_FINISH) {
1127 [ # # ]: 0 : if (req->cn10k_req.result.error_code == 0x0)
1128 : : ret = 0;
1129 : : else
1130 : : ret = -1;
1131 : : }
1132 : : } else {
1133 : 0 : roc_ml_scratch_queue_reset(&cn10k_mldev->roc);
1134 : : ret = -ETIME;
1135 : : }
1136 : :
1137 : : locked = false;
1138 : 0 : while (!locked) {
1139 [ # # ]: 0 : if (plt_spinlock_trylock(&model->lock) != 0) {
1140 [ # # ]: 0 : if (ret == 0)
1141 : 0 : layer->state = ML_CNXK_LAYER_STATE_LOADED;
1142 : : else
1143 : 0 : layer->state = ML_CNXK_LAYER_STATE_UNKNOWN;
1144 : :
1145 : : plt_spinlock_unlock(&model->lock);
1146 : : locked = true;
1147 : : }
1148 : : }
1149 : :
1150 : : return ret;
1151 : : }
1152 : :
1153 : : int
1154 : 0 : cn10k_ml_model_stop(struct cnxk_ml_dev *cnxk_mldev, struct cnxk_ml_model *model)
1155 : : {
1156 : : struct cnxk_ml_layer *layer;
1157 : : int ret;
1158 : :
1159 : : layer = &model->layer[0];
1160 : 0 : ret = cn10k_ml_layer_stop(cnxk_mldev, model->model_id, layer->name);
1161 [ # # ]: 0 : if (ret != 0) {
1162 : 0 : plt_err("CN10K Model stop failed, model_id = %u, error = %d", model->model_id, ret);
1163 : 0 : return ret;
1164 : : }
1165 : :
1166 : 0 : cnxk_mldev->nb_models_stopped++;
1167 : 0 : model->state = ML_CNXK_MODEL_STATE_LOADED;
1168 : :
1169 : 0 : return 0;
1170 : : }
1171 : :
1172 : : int
1173 : 0 : cn10k_ml_model_params_update(struct cnxk_ml_dev *cnxk_mldev, struct cnxk_ml_model *model,
1174 : : void *buffer)
1175 : : {
1176 : : struct cnxk_ml_layer *layer;
1177 : :
1178 : : RTE_SET_USED(cnxk_mldev);
1179 : :
1180 [ # # ]: 0 : if (model->state == ML_CNXK_MODEL_STATE_UNKNOWN)
1181 : : return -1;
1182 [ # # ]: 0 : else if (model->state != ML_CNXK_MODEL_STATE_LOADED)
1183 : : return -EBUSY;
1184 : :
1185 : : layer = &model->layer[0];
1186 : :
1187 : : /* Update model weights & bias */
1188 : 0 : rte_memcpy(layer->glow.addr.wb_load_addr, buffer,
1189 [ # # ]: 0 : layer->glow.metadata.weights_bias.file_size);
1190 : :
1191 : : return 0;
1192 : : }
1193 : :
1194 : : __rte_hot void
1195 : 0 : cn10k_ml_result_update(struct cnxk_ml_dev *cnxk_mldev, int qp_id, void *request)
1196 : : {
1197 : : union cn10k_ml_error_code *error_code;
1198 : : struct cn10k_ml_layer_xstats *xstats;
1199 : : struct cn10k_ml_dev *cn10k_mldev;
1200 : : struct cn10k_ml_result *result;
1201 : : struct cnxk_ml_model *model;
1202 : : struct cnxk_ml_layer *layer;
1203 : : struct cnxk_ml_req *req;
1204 : : struct cnxk_ml_qp *qp;
1205 : : struct rte_ml_op *op;
1206 : : uint64_t hw_latency;
1207 : : uint64_t fw_latency;
1208 : : uint16_t model_id;
1209 : : uint16_t layer_id;
1210 : : uint16_t idx;
1211 : :
1212 : : req = (struct cnxk_ml_req *)request;
1213 : : result = &req->cn10k_req.result;
1214 : 0 : op = req->op;
1215 [ # # ]: 0 : if (likely(result->error_code == 0)) {
1216 : 0 : idx = req->cn10k_req.jd.hdr.model_id;
1217 : 0 : model_id = cnxk_mldev->index_map[idx].model_id;
1218 : 0 : layer_id = cnxk_mldev->index_map[idx].layer_id;
1219 : 0 : model = cnxk_mldev->mldev->data->models[model_id];
1220 : 0 : layer = &model->layer[layer_id];
1221 [ # # ]: 0 : if (likely(qp_id >= 0)) {
1222 : 0 : qp = cnxk_mldev->mldev->data->queue_pairs[qp_id];
1223 : 0 : qp->stats.dequeued_count++;
1224 : 0 : xstats = &layer->glow.burst_xstats[qp_id];
1225 : : } else {
1226 : 0 : xstats = layer->glow.sync_xstats;
1227 : : }
1228 : :
1229 [ # # ]: 0 : if (unlikely(xstats->dequeued_count == xstats->hw_reset_count)) {
1230 : 0 : xstats->hw_latency_min = UINT64_MAX;
1231 : 0 : xstats->hw_latency_max = 0;
1232 : : }
1233 : :
1234 [ # # ]: 0 : if (unlikely(xstats->dequeued_count == xstats->fw_reset_count)) {
1235 : 0 : xstats->fw_latency_min = UINT64_MAX;
1236 : 0 : xstats->fw_latency_max = 0;
1237 : : }
1238 : :
1239 : 0 : hw_latency = result->stats.hw_end - result->stats.hw_start;
1240 : 0 : fw_latency = result->stats.fw_end - result->stats.fw_start - hw_latency;
1241 : :
1242 : 0 : xstats->hw_latency_tot += hw_latency;
1243 : 0 : xstats->hw_latency_min = PLT_MIN(xstats->hw_latency_min, hw_latency);
1244 : 0 : xstats->hw_latency_max = PLT_MAX(xstats->hw_latency_max, hw_latency);
1245 : 0 : xstats->fw_latency_tot += fw_latency;
1246 : 0 : xstats->fw_latency_min = PLT_MIN(xstats->fw_latency_min, fw_latency);
1247 : 0 : xstats->fw_latency_max = PLT_MAX(xstats->fw_latency_max, fw_latency);
1248 : 0 : xstats->dequeued_count++;
1249 : :
1250 : 0 : op->impl_opaque = result->error_code;
1251 : 0 : op->status = RTE_ML_OP_STATUS_SUCCESS;
1252 : : } else {
1253 [ # # ]: 0 : if (likely(qp_id >= 0)) {
1254 : 0 : qp = cnxk_mldev->mldev->data->queue_pairs[qp_id];
1255 : 0 : qp->stats.dequeue_err_count++;
1256 : : }
1257 : :
1258 : : /* Handle driver error */
1259 : : error_code = (union cn10k_ml_error_code *)&result->error_code;
1260 [ # # ]: 0 : if (error_code->s.etype == ML_CNXK_ETYPE_DRIVER) {
1261 : : cn10k_mldev = &cnxk_mldev->cn10k_mldev;
1262 : :
1263 : : /* Check for exception */
1264 [ # # ]: 0 : if ((roc_ml_reg_read64(&cn10k_mldev->roc, ML_SCRATCH_EXCEPTION_SP_C0) !=
1265 [ # # ]: 0 : 0) ||
1266 : 0 : (roc_ml_reg_read64(&cn10k_mldev->roc, ML_SCRATCH_EXCEPTION_SP_C1) != 0))
1267 : 0 : error_code->s.stype = ML_CN10K_DRIVER_ERR_EXCEPTION;
1268 [ # # # # ]: 0 : else if ((roc_ml_reg_read64(&cn10k_mldev->roc, ML_CORE_INT_LO) != 0) ||
1269 : 0 : (roc_ml_reg_read64(&cn10k_mldev->roc, ML_CORE_INT_HI) != 0))
1270 : 0 : error_code->s.stype = ML_CN10K_DRIVER_ERR_FW_ERROR;
1271 : : else
1272 : 0 : error_code->s.stype = ML_CN10K_DRIVER_ERR_UNKNOWN;
1273 : : }
1274 : :
1275 : 0 : op->impl_opaque = result->error_code;
1276 : 0 : op->status = RTE_ML_OP_STATUS_ERROR;
1277 : : }
1278 : :
1279 : 0 : op->user_ptr = result->user_ptr;
1280 : 0 : }
1281 : :
1282 : : __rte_hot void
1283 : 0 : cn10k_ml_set_error_code(struct cnxk_ml_req *req, uint64_t etype, uint64_t stype)
1284 : : {
1285 : : union cn10k_ml_error_code *error_code;
1286 : :
1287 : : error_code = (union cn10k_ml_error_code *)&req->cn10k_req.result.error_code;
1288 : 0 : error_code->s.etype = etype;
1289 : 0 : error_code->s.stype = stype;
1290 : 0 : }
1291 : :
1292 : : __rte_hot bool
1293 : 0 : cn10k_ml_enqueue_single(struct cnxk_ml_dev *cnxk_mldev, struct rte_ml_op *op, uint16_t layer_id,
1294 : : struct cnxk_ml_qp *qp, uint64_t head)
1295 : : {
1296 : : union cn10k_ml_error_code *error_code;
1297 : : struct cn10k_ml_dev *cn10k_mldev;
1298 : : struct cnxk_ml_model *model;
1299 : : struct cnxk_ml_queue *queue;
1300 : : struct cnxk_ml_req *req;
1301 : :
1302 : : cn10k_mldev = &cnxk_mldev->cn10k_mldev;
1303 : : queue = &qp->queue;
1304 : 0 : req = &queue->reqs[head];
1305 : :
1306 : 0 : model = cnxk_mldev->mldev->data->models[op->model_id];
1307 : 0 : model->set_poll_addr(req);
1308 : 0 : cn10k_ml_prep_fp_job_descriptor(cnxk_mldev, req, model->layer[layer_id].index,
1309 : 0 : op->input[0]->addr, op->output[0]->addr, op->nb_batches);
1310 : :
1311 : : memset(&req->cn10k_req.result, 0, sizeof(struct cn10k_ml_result));
1312 : : error_code = (union cn10k_ml_error_code *)&req->cn10k_req.result.error_code;
1313 : 0 : error_code->s.etype = ML_CNXK_ETYPE_UNKNOWN;
1314 : 0 : req->cn10k_req.result.user_ptr = op->user_ptr;
1315 : :
1316 : 0 : cnxk_ml_set_poll_ptr(req);
1317 [ # # ]: 0 : if (unlikely(!cn10k_mldev->ml_jcmdq_enqueue(&cn10k_mldev->roc, &req->cn10k_req.jcmd)))
1318 : : return false;
1319 : :
1320 : 0 : req->timeout = plt_tsc_cycles() + queue->wait_cycles;
1321 : 0 : req->op = op;
1322 : :
1323 : 0 : return true;
1324 : : }
1325 : :
1326 : : __rte_hot int
1327 : 0 : cn10k_ml_op_error_get(struct rte_ml_dev *dev, struct rte_ml_op *op, struct rte_ml_op_error *error)
1328 : : {
1329 : : union cn10k_ml_error_code *error_code;
1330 : :
1331 : : PLT_SET_USED(dev);
1332 : :
1333 : : error_code = (union cn10k_ml_error_code *)&op->impl_opaque;
1334 : :
1335 : : /* Copy sub error message */
1336 [ # # ]: 0 : if (error_code->s.etype == ML_CNXK_ETYPE_HW_NONFATAL) {
1337 [ # # ]: 0 : if (error_code->s.stype < PLT_DIM(ml_stype_db_hw_nf))
1338 : 0 : snprintf(error->message, RTE_ML_STR_MAX, "%s : %s",
1339 : 0 : ml_etype_db[error_code->s.etype].str,
1340 : 0 : ml_stype_db_hw_nf[error_code->s.stype].str);
1341 : : else
1342 : 0 : snprintf(error->message, RTE_ML_STR_MAX, "%s : UNKNOWN ERROR",
1343 : 0 : ml_etype_db[error_code->s.etype].str);
1344 [ # # ]: 0 : } else if (error_code->s.etype == ML_CNXK_ETYPE_DRIVER) {
1345 : 0 : snprintf(error->message, RTE_ML_STR_MAX, "%s : %s",
1346 : 0 : ml_etype_db[error_code->s.etype].str,
1347 : 0 : ml_stype_db_driver[error_code->s.stype].str);
1348 : : } else {
1349 : 0 : snprintf(error->message, RTE_ML_STR_MAX, "%s",
1350 : 0 : ml_etype_db[error_code->s.etype].str);
1351 : : }
1352 : :
1353 : 0 : error->errcode = error_code->u64;
1354 : :
1355 : 0 : return 0;
1356 : : }
1357 : :
1358 : : __rte_hot int
1359 : 0 : cn10k_ml_inference_sync(void *device, uint16_t index, void *input, void *output,
1360 : : uint16_t nb_batches)
1361 : : {
1362 : : union cn10k_ml_error_code *error_code;
1363 : : struct cn10k_ml_dev *cn10k_mldev;
1364 : : struct cnxk_ml_dev *cnxk_mldev;
1365 : : struct cnxk_ml_model *model;
1366 : : struct cnxk_ml_layer *layer;
1367 : : struct cnxk_ml_req *req;
1368 : : struct rte_ml_op op;
1369 : : uint16_t model_id;
1370 : : uint16_t layer_id;
1371 : : bool timeout;
1372 : : int ret = 0;
1373 : :
1374 : : cnxk_mldev = (struct cnxk_ml_dev *)device;
1375 : : cn10k_mldev = &cnxk_mldev->cn10k_mldev;
1376 : 0 : model_id = cnxk_mldev->index_map[index].model_id;
1377 : 0 : layer_id = cnxk_mldev->index_map[index].layer_id;
1378 : 0 : model = cnxk_mldev->mldev->data->models[model_id];
1379 : 0 : layer = &model->layer[layer_id];
1380 : 0 : req = layer->glow.req;
1381 : :
1382 : 0 : op.model_id = index;
1383 : 0 : op.impl_opaque = 0;
1384 : :
1385 : 0 : cn10k_ml_set_poll_addr(req);
1386 : : cn10k_ml_prep_fp_job_descriptor(cnxk_mldev, req, index, input, output, nb_batches);
1387 : :
1388 : : memset(&req->cn10k_req.result, 0, sizeof(struct cn10k_ml_result));
1389 : : error_code = (union cn10k_ml_error_code *)&req->cn10k_req.result.error_code;
1390 : 0 : error_code->s.etype = ML_CNXK_ETYPE_UNKNOWN;
1391 : : req->cn10k_req.result.user_ptr = NULL;
1392 : :
1393 : 0 : cnxk_ml_set_poll_ptr(req);
1394 : 0 : req->cn10k_req.jcmd.w1.s.jobptr = PLT_U64_CAST(&req->cn10k_req.jd);
1395 : :
1396 : : timeout = true;
1397 : 0 : req->timeout = plt_tsc_cycles() + ML_CNXK_CMD_TIMEOUT * plt_tsc_hz();
1398 : : do {
1399 [ # # ]: 0 : if (cn10k_mldev->ml_jcmdq_enqueue(&cn10k_mldev->roc, &req->cn10k_req.jcmd)) {
1400 : 0 : req->op = &op;
1401 : : timeout = false;
1402 : : break;
1403 : : }
1404 [ # # ]: 0 : } while (plt_tsc_cycles() < req->timeout);
1405 : :
1406 : : if (timeout) {
1407 : : ret = -EBUSY;
1408 : 0 : goto error_enqueue;
1409 : : }
1410 : :
1411 : : timeout = true;
1412 : : do {
1413 [ # # ]: 0 : if (cnxk_ml_get_poll_ptr(req) == ML_CNXK_POLL_JOB_FINISH) {
1414 : : timeout = false;
1415 : : break;
1416 : : }
1417 [ # # ]: 0 : } while (plt_tsc_cycles() < req->timeout);
1418 : :
1419 [ # # ]: 0 : if (timeout)
1420 : : ret = -ETIME;
1421 : : else
1422 : 0 : cn10k_ml_result_update(cnxk_mldev, -1, req);
1423 : :
1424 : 0 : error_enqueue:
1425 : 0 : return ret;
1426 : : }
1427 : :
1428 : : int
1429 : 0 : cn10k_ml_io_alloc(void *device, uint16_t model_id, const char *layer_name, uint64_t **input_qbuffer,
1430 : : uint64_t **output_qbuffer)
1431 : : {
1432 : : struct cnxk_ml_dev *cnxk_mldev;
1433 : : struct cnxk_ml_model *model;
1434 : : struct cnxk_ml_layer *layer;
1435 : :
1436 : : char str[RTE_MEMZONE_NAMESIZE];
1437 : : const struct plt_memzone *mz;
1438 : : uint64_t output_size;
1439 : : uint64_t input_size;
1440 : : uint16_t layer_id;
1441 : : int ret;
1442 : :
1443 : : cnxk_mldev = (struct cnxk_ml_dev *)device;
1444 [ # # ]: 0 : if (cnxk_mldev == NULL) {
1445 : 0 : plt_err("Invalid device = %p", device);
1446 : 0 : return -EINVAL;
1447 : : }
1448 : :
1449 : 0 : model = cnxk_mldev->mldev->data->models[model_id];
1450 [ # # ]: 0 : if (model == NULL) {
1451 : 0 : plt_err("Invalid model_id = %u", model_id);
1452 : 0 : return -EINVAL;
1453 : : }
1454 : :
1455 : 0 : ret = cn10k_ml_model_get_layer_id(model, layer_name, &layer_id);
1456 [ # # ]: 0 : if (ret != 0)
1457 : : return ret;
1458 : :
1459 : 0 : layer = &model->layer[layer_id];
1460 : 0 : input_size = PLT_ALIGN_CEIL(layer->info.total_input_sz_q, ML_CN10K_ALIGN_SIZE);
1461 : 0 : output_size = PLT_ALIGN_CEIL(layer->info.total_output_sz_q, ML_CN10K_ALIGN_SIZE);
1462 : :
1463 : 0 : sprintf(str, "cn10k_ml_io_mz_%u_%u", model_id, layer_id);
1464 : 0 : mz = plt_memzone_reserve_aligned(str, input_size + output_size, 0, ML_CN10K_ALIGN_SIZE);
1465 [ # # ]: 0 : if (mz == NULL) {
1466 : 0 : plt_err("io_alloc failed: Unable to allocate memory: model_id = %u, layer_name = %s",
1467 : : model_id, layer_name);
1468 : 0 : return -ENOMEM;
1469 : : }
1470 : :
1471 : 0 : *input_qbuffer = mz->addr;
1472 : 0 : *output_qbuffer = PLT_PTR_ADD(mz->addr, input_size);
1473 : :
1474 : 0 : return 0;
1475 : : }
1476 : :
1477 : : int
1478 : 0 : cn10k_ml_io_free(void *device, uint16_t model_id, const char *layer_name)
1479 : : {
1480 : : struct cnxk_ml_dev *cnxk_mldev;
1481 : : struct cnxk_ml_model *model;
1482 : :
1483 : : char str[RTE_MEMZONE_NAMESIZE];
1484 : : const struct plt_memzone *mz;
1485 : : uint16_t layer_id;
1486 : : int ret;
1487 : :
1488 : : cnxk_mldev = (struct cnxk_ml_dev *)device;
1489 [ # # ]: 0 : if (cnxk_mldev == NULL) {
1490 : 0 : plt_err("Invalid device = %p", device);
1491 : 0 : return -EINVAL;
1492 : : }
1493 : :
1494 : 0 : model = cnxk_mldev->mldev->data->models[model_id];
1495 [ # # ]: 0 : if (model == NULL) {
1496 : 0 : plt_err("Invalid model_id = %u", model_id);
1497 : 0 : return -EINVAL;
1498 : : }
1499 : :
1500 : 0 : ret = cn10k_ml_model_get_layer_id(model, layer_name, &layer_id);
1501 [ # # ]: 0 : if (ret != 0)
1502 : : return ret;
1503 : :
1504 : 0 : sprintf(str, "cn10k_ml_io_mz_%u_%u", model_id, layer_id);
1505 : 0 : mz = plt_memzone_lookup(str);
1506 [ # # ]: 0 : if (mz == NULL) {
1507 : 0 : plt_err("io_free failed: Memzone not found: model_id = %u, layer_name = %s",
1508 : : model_id, layer_name);
1509 : 0 : return -EINVAL;
1510 : : }
1511 : :
1512 : 0 : return plt_memzone_free(mz);
1513 : : }
1514 : :
1515 : : int
1516 : 0 : cn10k_ml_malloc(const char *name, size_t size, uint32_t align, void **addr)
1517 : : {
1518 : : const struct plt_memzone *mz;
1519 : :
1520 : 0 : mz = plt_memzone_reserve_aligned(name, size, 0, align);
1521 [ # # ]: 0 : if (mz == NULL) {
1522 : 0 : plt_err("ml_malloc failed: Unable to allocate memory: name = %s", name);
1523 : 0 : return -ENOMEM;
1524 : : }
1525 : :
1526 : 0 : *addr = mz->addr;
1527 : :
1528 : 0 : return 0;
1529 : : }
1530 : :
1531 : : int
1532 : 0 : cn10k_ml_free(const char *name)
1533 : : {
1534 : : const struct plt_memzone *mz;
1535 : :
1536 : 0 : mz = plt_memzone_lookup(name);
1537 [ # # ]: 0 : if (mz == NULL) {
1538 : 0 : plt_err("ml_free failed: Memzone not found: name = %s", name);
1539 : 0 : return -EINVAL;
1540 : : }
1541 : :
1542 : 0 : return plt_memzone_free(mz);
1543 : : }
|