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