Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright (c) 2022 Marvell.
3 : : */
4 : :
5 : : #include <rte_common.h>
6 : : #include <rte_dev.h>
7 : : #include <rte_devargs.h>
8 : : #include <rte_kvargs.h>
9 : : #include <rte_mldev.h>
10 : : #include <rte_mldev_pmd.h>
11 : : #include <rte_pci.h>
12 : :
13 : : #include <eal_firmware.h>
14 : :
15 : : #include <roc_api.h>
16 : :
17 : : #include "cnxk_ml_dev.h"
18 : : #include "cnxk_ml_ops.h"
19 : :
20 : : #define CN10K_ML_FW_PATH "fw_path"
21 : : #define CN10K_ML_FW_ENABLE_DPE_WARNINGS "enable_dpe_warnings"
22 : : #define CN10K_ML_FW_REPORT_DPE_WARNINGS "report_dpe_warnings"
23 : : #define CN10K_ML_DEV_CACHE_MODEL_DATA "cache_model_data"
24 : : #define CN10K_ML_OCM_ALLOC_MODE "ocm_alloc_mode"
25 : : #define CN10K_ML_DEV_HW_QUEUE_LOCK "hw_queue_lock"
26 : : #define CN10K_ML_OCM_PAGE_SIZE "ocm_page_size"
27 : :
28 : : #define CN10K_ML_FW_PATH_DEFAULT "/lib/firmware/mlip-fw.bin"
29 : : #define CN10K_ML_FW_ENABLE_DPE_WARNINGS_DEFAULT 1
30 : : #define CN10K_ML_FW_REPORT_DPE_WARNINGS_DEFAULT 0
31 : : #define CN10K_ML_DEV_CACHE_MODEL_DATA_DEFAULT 1
32 : : #define CN10K_ML_OCM_ALLOC_MODE_DEFAULT "lowest"
33 : : #define CN10K_ML_DEV_HW_QUEUE_LOCK_DEFAULT 1
34 : : #define CN10K_ML_OCM_PAGE_SIZE_DEFAULT 16384
35 : :
36 : : /* ML firmware macros */
37 : : #define FW_MEMZONE_NAME "ml_cn10k_fw_mz"
38 : : #define FW_STACK_BUFFER_SIZE 0x40000
39 : : #define FW_DEBUG_BUFFER_SIZE (2 * 0x20000)
40 : : #define FW_EXCEPTION_BUFFER_SIZE 0x400
41 : : #define FW_LINKER_OFFSET 0x80000
42 : : #define FW_WAIT_CYCLES 100
43 : :
44 : : /* Firmware flags */
45 : : #define FW_ENABLE_DPE_WARNING_BITMASK BIT(0)
46 : : #define FW_REPORT_DPE_WARNING_BITMASK BIT(1)
47 : : #define FW_USE_DDR_POLL_ADDR_FP BIT(2)
48 : :
49 : : static const char *const valid_args[] = {CN10K_ML_FW_PATH,
50 : : CN10K_ML_FW_ENABLE_DPE_WARNINGS,
51 : : CN10K_ML_FW_REPORT_DPE_WARNINGS,
52 : : CN10K_ML_DEV_CACHE_MODEL_DATA,
53 : : CN10K_ML_OCM_ALLOC_MODE,
54 : : CN10K_ML_DEV_HW_QUEUE_LOCK,
55 : : CN10K_ML_OCM_PAGE_SIZE,
56 : : NULL};
57 : :
58 : : /* Supported OCM page sizes: 1KB, 2KB, 4KB, 8KB and 16KB */
59 : : static const int valid_ocm_page_size[] = {1024, 2048, 4096, 8192, 16384};
60 : :
61 : : static int
62 : 0 : parse_string_arg(const char *key __rte_unused, const char *value, void *extra_args)
63 : : {
64 [ # # ]: 0 : if (value == NULL || extra_args == NULL)
65 : : return -EINVAL;
66 : :
67 : 0 : *(char **)extra_args = strdup(value);
68 : :
69 [ # # ]: 0 : if (!*(char **)extra_args)
70 : 0 : return -ENOMEM;
71 : :
72 : : return 0;
73 : : }
74 : :
75 : : static int
76 : 0 : parse_integer_arg(const char *key __rte_unused, const char *value, void *extra_args)
77 : : {
78 : : int *i = (int *)extra_args;
79 : :
80 : 0 : *i = atoi(value);
81 [ # # ]: 0 : if (*i < 0) {
82 : 0 : plt_err("Argument has to be positive.");
83 : 0 : return -EINVAL;
84 : : }
85 : :
86 : : return 0;
87 : : }
88 : :
89 : : static int
90 : 0 : cn10k_mldev_parse_devargs(struct rte_devargs *devargs, struct cn10k_ml_dev *cn10k_mldev)
91 : : {
92 : : bool enable_dpe_warnings_set = false;
93 : : bool report_dpe_warnings_set = false;
94 : : bool cache_model_data_set = false;
95 : : struct rte_kvargs *kvlist = NULL;
96 : : bool ocm_alloc_mode_set = false;
97 : : bool hw_queue_lock_set = false;
98 : : bool ocm_page_size_set = false;
99 : 0 : char *ocm_alloc_mode = NULL;
100 : : bool fw_path_set = false;
101 : 0 : char *fw_path = NULL;
102 : : int ret = 0;
103 : : bool found;
104 : : uint8_t i;
105 : :
106 [ # # ]: 0 : if (devargs == NULL)
107 : 0 : goto check_args;
108 : :
109 : 0 : kvlist = rte_kvargs_parse(devargs->args, valid_args);
110 [ # # ]: 0 : if (kvlist == NULL) {
111 : 0 : plt_err("Error parsing devargs\n");
112 : 0 : return -EINVAL;
113 : : }
114 : :
115 [ # # ]: 0 : if (rte_kvargs_count(kvlist, CN10K_ML_FW_PATH) == 1) {
116 : 0 : ret = rte_kvargs_process(kvlist, CN10K_ML_FW_PATH, &parse_string_arg, &fw_path);
117 [ # # ]: 0 : if (ret < 0) {
118 : 0 : plt_err("Error processing arguments, key = %s\n", CN10K_ML_FW_PATH);
119 : : ret = -EINVAL;
120 : 0 : goto exit;
121 : : }
122 : : fw_path_set = true;
123 : : }
124 : :
125 [ # # ]: 0 : if (rte_kvargs_count(kvlist, CN10K_ML_FW_ENABLE_DPE_WARNINGS) == 1) {
126 : 0 : ret = rte_kvargs_process(kvlist, CN10K_ML_FW_ENABLE_DPE_WARNINGS,
127 : 0 : &parse_integer_arg, &cn10k_mldev->fw.enable_dpe_warnings);
128 [ # # ]: 0 : if (ret < 0) {
129 : 0 : plt_err("Error processing arguments, key = %s\n",
130 : : CN10K_ML_FW_ENABLE_DPE_WARNINGS);
131 : : ret = -EINVAL;
132 : 0 : goto exit;
133 : : }
134 : : enable_dpe_warnings_set = true;
135 : : }
136 : :
137 [ # # ]: 0 : if (rte_kvargs_count(kvlist, CN10K_ML_FW_REPORT_DPE_WARNINGS) == 1) {
138 : 0 : ret = rte_kvargs_process(kvlist, CN10K_ML_FW_REPORT_DPE_WARNINGS,
139 : 0 : &parse_integer_arg, &cn10k_mldev->fw.report_dpe_warnings);
140 [ # # ]: 0 : if (ret < 0) {
141 : 0 : plt_err("Error processing arguments, key = %s\n",
142 : : CN10K_ML_FW_REPORT_DPE_WARNINGS);
143 : : ret = -EINVAL;
144 : 0 : goto exit;
145 : : }
146 : : report_dpe_warnings_set = true;
147 : : }
148 : :
149 [ # # ]: 0 : if (rte_kvargs_count(kvlist, CN10K_ML_DEV_CACHE_MODEL_DATA) == 1) {
150 : 0 : ret = rte_kvargs_process(kvlist, CN10K_ML_DEV_CACHE_MODEL_DATA, &parse_integer_arg,
151 : 0 : &cn10k_mldev->cache_model_data);
152 [ # # ]: 0 : if (ret < 0) {
153 : 0 : plt_err("Error processing arguments, key = %s\n",
154 : : CN10K_ML_DEV_CACHE_MODEL_DATA);
155 : : ret = -EINVAL;
156 : 0 : goto exit;
157 : : }
158 : : cache_model_data_set = true;
159 : : }
160 : :
161 [ # # ]: 0 : if (rte_kvargs_count(kvlist, CN10K_ML_OCM_ALLOC_MODE) == 1) {
162 : 0 : ret = rte_kvargs_process(kvlist, CN10K_ML_OCM_ALLOC_MODE, &parse_string_arg,
163 : : &ocm_alloc_mode);
164 [ # # ]: 0 : if (ret < 0) {
165 : 0 : plt_err("Error processing arguments, key = %s\n", CN10K_ML_OCM_ALLOC_MODE);
166 : : ret = -EINVAL;
167 : 0 : goto exit;
168 : : }
169 : : ocm_alloc_mode_set = true;
170 : : }
171 : :
172 [ # # ]: 0 : if (rte_kvargs_count(kvlist, CN10K_ML_DEV_HW_QUEUE_LOCK) == 1) {
173 : 0 : ret = rte_kvargs_process(kvlist, CN10K_ML_DEV_HW_QUEUE_LOCK, &parse_integer_arg,
174 : 0 : &cn10k_mldev->hw_queue_lock);
175 [ # # ]: 0 : if (ret < 0) {
176 : 0 : plt_err("Error processing arguments, key = %s\n",
177 : : CN10K_ML_DEV_HW_QUEUE_LOCK);
178 : : ret = -EINVAL;
179 : 0 : goto exit;
180 : : }
181 : : hw_queue_lock_set = true;
182 : : }
183 : :
184 [ # # ]: 0 : if (rte_kvargs_count(kvlist, CN10K_ML_OCM_PAGE_SIZE) == 1) {
185 : 0 : ret = rte_kvargs_process(kvlist, CN10K_ML_OCM_PAGE_SIZE, &parse_integer_arg,
186 : 0 : &cn10k_mldev->ocm_page_size);
187 [ # # ]: 0 : if (ret < 0) {
188 : 0 : plt_err("Error processing arguments, key = %s\n", CN10K_ML_OCM_PAGE_SIZE);
189 : : ret = -EINVAL;
190 : 0 : goto exit;
191 : : }
192 : : ocm_page_size_set = true;
193 : : }
194 : :
195 : 0 : check_args:
196 [ # # ]: 0 : if (!fw_path_set)
197 : 0 : cn10k_mldev->fw.path = CN10K_ML_FW_PATH_DEFAULT;
198 : : else
199 : 0 : cn10k_mldev->fw.path = fw_path;
200 : 0 : plt_info("ML: %s = %s", CN10K_ML_FW_PATH, cn10k_mldev->fw.path);
201 : :
202 [ # # ]: 0 : if (!enable_dpe_warnings_set) {
203 : 0 : cn10k_mldev->fw.enable_dpe_warnings = CN10K_ML_FW_ENABLE_DPE_WARNINGS_DEFAULT;
204 : : } else {
205 [ # # ]: 0 : if ((cn10k_mldev->fw.enable_dpe_warnings < 0) ||
206 : : (cn10k_mldev->fw.enable_dpe_warnings > 1)) {
207 : 0 : plt_err("Invalid argument, %s = %d\n", CN10K_ML_FW_ENABLE_DPE_WARNINGS,
208 : : cn10k_mldev->fw.enable_dpe_warnings);
209 : : ret = -EINVAL;
210 : 0 : goto exit;
211 : : }
212 : : }
213 : 0 : plt_info("ML: %s = %d", CN10K_ML_FW_ENABLE_DPE_WARNINGS,
214 : : cn10k_mldev->fw.enable_dpe_warnings);
215 : :
216 [ # # ]: 0 : if (!report_dpe_warnings_set) {
217 : 0 : cn10k_mldev->fw.report_dpe_warnings = CN10K_ML_FW_REPORT_DPE_WARNINGS_DEFAULT;
218 : : } else {
219 [ # # ]: 0 : if ((cn10k_mldev->fw.report_dpe_warnings < 0) ||
220 : : (cn10k_mldev->fw.report_dpe_warnings > 1)) {
221 : 0 : plt_err("Invalid argument, %s = %d\n", CN10K_ML_FW_REPORT_DPE_WARNINGS,
222 : : cn10k_mldev->fw.report_dpe_warnings);
223 : : ret = -EINVAL;
224 : 0 : goto exit;
225 : : }
226 : : }
227 : 0 : plt_info("ML: %s = %d", CN10K_ML_FW_REPORT_DPE_WARNINGS,
228 : : cn10k_mldev->fw.report_dpe_warnings);
229 : :
230 [ # # ]: 0 : if (!cache_model_data_set) {
231 : 0 : cn10k_mldev->cache_model_data = CN10K_ML_DEV_CACHE_MODEL_DATA_DEFAULT;
232 : : } else {
233 [ # # ]: 0 : if ((cn10k_mldev->cache_model_data < 0) || (cn10k_mldev->cache_model_data > 1)) {
234 : 0 : plt_err("Invalid argument, %s = %d\n", CN10K_ML_DEV_CACHE_MODEL_DATA,
235 : : cn10k_mldev->cache_model_data);
236 : : ret = -EINVAL;
237 : 0 : goto exit;
238 : : }
239 : : }
240 : 0 : plt_info("ML: %s = %d", CN10K_ML_DEV_CACHE_MODEL_DATA, cn10k_mldev->cache_model_data);
241 : :
242 [ # # ]: 0 : if (!ocm_alloc_mode_set) {
243 : 0 : cn10k_mldev->ocm.alloc_mode = CN10K_ML_OCM_ALLOC_MODE_DEFAULT;
244 : : } else {
245 [ # # ]: 0 : if (!((strcmp(ocm_alloc_mode, "lowest") == 0) ||
246 [ # # ]: 0 : (strcmp(ocm_alloc_mode, "largest") == 0))) {
247 : 0 : plt_err("Invalid argument, %s = %s\n", CN10K_ML_OCM_ALLOC_MODE,
248 : : ocm_alloc_mode);
249 : : ret = -EINVAL;
250 : 0 : goto exit;
251 : : }
252 : 0 : cn10k_mldev->ocm.alloc_mode = ocm_alloc_mode;
253 : : }
254 : 0 : plt_info("ML: %s = %s", CN10K_ML_OCM_ALLOC_MODE, cn10k_mldev->ocm.alloc_mode);
255 : :
256 [ # # ]: 0 : if (!hw_queue_lock_set) {
257 : 0 : cn10k_mldev->hw_queue_lock = CN10K_ML_DEV_HW_QUEUE_LOCK_DEFAULT;
258 : : } else {
259 [ # # ]: 0 : if ((cn10k_mldev->hw_queue_lock < 0) || (cn10k_mldev->hw_queue_lock > 1)) {
260 : 0 : plt_err("Invalid argument, %s = %d\n", CN10K_ML_DEV_HW_QUEUE_LOCK,
261 : : cn10k_mldev->hw_queue_lock);
262 : : ret = -EINVAL;
263 : 0 : goto exit;
264 : : }
265 : : }
266 : 0 : plt_info("ML: %s = %d", CN10K_ML_DEV_HW_QUEUE_LOCK, cn10k_mldev->hw_queue_lock);
267 : :
268 [ # # ]: 0 : if (!ocm_page_size_set) {
269 : 0 : cn10k_mldev->ocm_page_size = CN10K_ML_OCM_PAGE_SIZE_DEFAULT;
270 : : } else {
271 [ # # ]: 0 : if (cn10k_mldev->ocm_page_size < 0) {
272 : 0 : plt_err("Invalid argument, %s = %d\n", CN10K_ML_OCM_PAGE_SIZE,
273 : : cn10k_mldev->ocm_page_size);
274 : : ret = -EINVAL;
275 : 0 : goto exit;
276 : : }
277 : :
278 : : found = false;
279 [ # # ]: 0 : for (i = 0; i < PLT_DIM(valid_ocm_page_size); i++) {
280 [ # # ]: 0 : if (cn10k_mldev->ocm_page_size == valid_ocm_page_size[i]) {
281 : : found = true;
282 : : break;
283 : : }
284 : : }
285 : :
286 [ # # ]: 0 : if (!found) {
287 : 0 : plt_err("Unsupported ocm_page_size = %d\n", cn10k_mldev->ocm_page_size);
288 : : ret = -EINVAL;
289 : 0 : goto exit;
290 : : }
291 : : }
292 : 0 : plt_info("ML: %s = %d", CN10K_ML_OCM_PAGE_SIZE, cn10k_mldev->ocm_page_size);
293 : :
294 : 0 : exit:
295 : 0 : rte_kvargs_free(kvlist);
296 : :
297 : 0 : return ret;
298 : : }
299 : :
300 : : static int
301 : 0 : cn10k_ml_pci_probe(struct rte_pci_driver *pci_drv, struct rte_pci_device *pci_dev)
302 : : {
303 : : struct rte_ml_dev_pmd_init_params init_params;
304 : : struct cn10k_ml_dev *cn10k_mldev;
305 : : struct cnxk_ml_dev *cnxk_mldev;
306 : : char name[RTE_ML_STR_MAX];
307 : : struct rte_ml_dev *dev;
308 : : int ret;
309 : :
310 : : PLT_SET_USED(pci_drv);
311 : :
312 [ # # ]: 0 : if (cnxk_ml_dev_initialized == 1) {
313 : 0 : plt_err("ML CNXK device already initialized!");
314 : 0 : plt_err("Cannot initialize CN10K PCI dev");
315 : 0 : return -EINVAL;
316 : : }
317 : :
318 : 0 : init_params = (struct rte_ml_dev_pmd_init_params){
319 : 0 : .socket_id = rte_socket_id(), .private_data_size = sizeof(struct cnxk_ml_dev)};
320 : :
321 : 0 : ret = roc_plt_init();
322 [ # # ]: 0 : if (ret < 0) {
323 : 0 : plt_err("Failed to initialize platform model");
324 : 0 : return ret;
325 : : }
326 : :
327 : 0 : rte_pci_device_name(&pci_dev->addr, name, sizeof(name));
328 : 0 : dev = rte_ml_dev_pmd_create(name, &pci_dev->device, &init_params);
329 [ # # ]: 0 : if (dev == NULL) {
330 : : ret = -ENODEV;
331 : 0 : goto error_exit;
332 : : }
333 : :
334 : : /* Get private data space allocated */
335 : 0 : cnxk_mldev = dev->data->dev_private;
336 : 0 : cnxk_mldev->mldev = dev;
337 : 0 : cn10k_mldev = &cnxk_mldev->cn10k_mldev;
338 : :
339 [ # # ]: 0 : if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
340 : 0 : cn10k_mldev->roc.pci_dev = pci_dev;
341 : :
342 : 0 : ret = cn10k_mldev_parse_devargs(dev->device->devargs, cn10k_mldev);
343 [ # # ]: 0 : if (ret) {
344 : 0 : plt_err("Failed to parse devargs ret = %d", ret);
345 : 0 : goto pmd_destroy;
346 : : }
347 : :
348 : 0 : ret = roc_ml_dev_init(&cn10k_mldev->roc);
349 [ # # ]: 0 : if (ret) {
350 : 0 : plt_err("Failed to initialize ML ROC, ret = %d", ret);
351 : 0 : goto pmd_destroy;
352 : : }
353 : :
354 : 0 : dev->dev_ops = &cnxk_ml_ops;
355 : : } else {
356 : 0 : plt_err("CN10K ML Ops are not supported on secondary process");
357 : 0 : dev->dev_ops = &ml_dev_dummy_ops;
358 : : }
359 : :
360 : 0 : dev->enqueue_burst = NULL;
361 : 0 : dev->dequeue_burst = NULL;
362 : 0 : dev->op_error_get = NULL;
363 : :
364 : 0 : cnxk_ml_dev_initialized = 1;
365 : 0 : cnxk_mldev->type = CNXK_ML_DEV_TYPE_PCI;
366 : 0 : cnxk_mldev->state = ML_CNXK_DEV_STATE_PROBED;
367 : :
368 : 0 : return 0;
369 : :
370 : 0 : pmd_destroy:
371 : 0 : rte_ml_dev_pmd_destroy(dev);
372 : :
373 : 0 : error_exit:
374 : 0 : plt_err("Could not create device (vendor_id: 0x%x device_id: 0x%x)", pci_dev->id.vendor_id,
375 : : pci_dev->id.device_id);
376 : :
377 : 0 : return ret;
378 : : }
379 : :
380 : : static int
381 : 0 : cn10k_ml_pci_remove(struct rte_pci_device *pci_dev)
382 : : {
383 : : struct cnxk_ml_dev *cnxk_mldev;
384 : : char name[RTE_ML_STR_MAX];
385 : : struct rte_ml_dev *dev;
386 : : int ret;
387 : :
388 [ # # ]: 0 : if (pci_dev == NULL)
389 : : return -EINVAL;
390 : :
391 : 0 : rte_pci_device_name(&pci_dev->addr, name, sizeof(name));
392 : :
393 : 0 : dev = rte_ml_dev_pmd_get_named_dev(name);
394 [ # # ]: 0 : if (dev == NULL)
395 : : return -ENODEV;
396 : :
397 [ # # ]: 0 : if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
398 : 0 : cnxk_mldev = dev->data->dev_private;
399 : 0 : ret = roc_ml_dev_fini(&cnxk_mldev->cn10k_mldev.roc);
400 [ # # ]: 0 : if (ret)
401 : : return ret;
402 : : }
403 : :
404 : 0 : return rte_ml_dev_pmd_destroy(dev);
405 : : }
406 : :
407 : : static void
408 : 0 : cn10k_ml_fw_print_info(struct cn10k_ml_fw *fw)
409 : : {
410 : 0 : plt_info("ML Firmware Version = %s", fw->req->cn10k_req.jd.fw_load.version);
411 : :
412 : 0 : plt_ml_dbg("Firmware capabilities = 0x%016lx", fw->req->cn10k_req.jd.fw_load.cap.u64);
413 : 0 : plt_ml_dbg("Version = %s", fw->req->cn10k_req.jd.fw_load.version);
414 : 0 : plt_ml_dbg("core0_debug_ptr = 0x%016lx",
415 : : fw->req->cn10k_req.jd.fw_load.debug.core0_debug_ptr);
416 : 0 : plt_ml_dbg("core1_debug_ptr = 0x%016lx",
417 : : fw->req->cn10k_req.jd.fw_load.debug.core1_debug_ptr);
418 : 0 : plt_ml_dbg("debug_buffer_size = %u bytes",
419 : : fw->req->cn10k_req.jd.fw_load.debug.debug_buffer_size);
420 : 0 : plt_ml_dbg("core0_exception_buffer = 0x%016lx",
421 : : fw->req->cn10k_req.jd.fw_load.debug.core0_exception_buffer);
422 : 0 : plt_ml_dbg("core1_exception_buffer = 0x%016lx",
423 : : fw->req->cn10k_req.jd.fw_load.debug.core1_exception_buffer);
424 : 0 : plt_ml_dbg("exception_state_size = %u bytes",
425 : : fw->req->cn10k_req.jd.fw_load.debug.exception_state_size);
426 : 0 : plt_ml_dbg("flags = 0x%016lx", fw->req->cn10k_req.jd.fw_load.flags);
427 : 0 : }
428 : :
429 : : uint64_t
430 : 0 : cn10k_ml_fw_flags_get(struct cn10k_ml_fw *fw)
431 : : {
432 : : uint64_t flags = 0x0;
433 : :
434 [ # # ]: 0 : if (fw->enable_dpe_warnings)
435 : : flags = flags | FW_ENABLE_DPE_WARNING_BITMASK;
436 : :
437 [ # # ]: 0 : if (fw->report_dpe_warnings)
438 : 0 : flags = flags | FW_REPORT_DPE_WARNING_BITMASK;
439 : :
440 : 0 : flags = flags | FW_USE_DDR_POLL_ADDR_FP;
441 : :
442 : 0 : return flags;
443 : : }
444 : :
445 : : static int
446 : 0 : cn10k_ml_fw_load_asim(struct cn10k_ml_fw *fw)
447 : : {
448 : : struct cn10k_ml_dev *cn10k_mldev;
449 : : uint64_t timeout_cycle;
450 : : uint64_t reg_val64;
451 : : bool timeout;
452 : : int ret = 0;
453 : :
454 : 0 : cn10k_mldev = fw->cn10k_mldev;
455 : :
456 : : /* Reset HEAD and TAIL debug pointer registers */
457 : 0 : roc_ml_reg_write64(&cn10k_mldev->roc, 0, ML_SCRATCH_DBG_BUFFER_HEAD_C0);
458 : 0 : roc_ml_reg_write64(&cn10k_mldev->roc, 0, ML_SCRATCH_DBG_BUFFER_TAIL_C0);
459 : 0 : roc_ml_reg_write64(&cn10k_mldev->roc, 0, ML_SCRATCH_DBG_BUFFER_HEAD_C1);
460 : 0 : roc_ml_reg_write64(&cn10k_mldev->roc, 0, ML_SCRATCH_DBG_BUFFER_TAIL_C1);
461 : 0 : roc_ml_reg_write64(&cn10k_mldev->roc, 0, ML_SCRATCH_EXCEPTION_SP_C0);
462 : 0 : roc_ml_reg_write64(&cn10k_mldev->roc, 0, ML_SCRATCH_EXCEPTION_SP_C1);
463 : :
464 : : /* Set ML_MLR_BASE to base IOVA of the ML region in LLC/DRAM. */
465 : 0 : reg_val64 = rte_eal_get_baseaddr();
466 : 0 : roc_ml_reg_write64(&cn10k_mldev->roc, reg_val64, ML_MLR_BASE);
467 : 0 : plt_ml_dbg("ML_MLR_BASE = 0x%016lx", roc_ml_reg_read64(&cn10k_mldev->roc, ML_MLR_BASE));
468 : 0 : roc_ml_reg_save(&cn10k_mldev->roc, ML_MLR_BASE);
469 : :
470 : : /* Update FW load completion structure */
471 : 0 : fw->req->cn10k_req.jd.hdr.jce.w1.u64 = PLT_U64_CAST(&fw->req->cn10k_req.status);
472 : 0 : fw->req->cn10k_req.jd.hdr.job_type = ML_CN10K_JOB_TYPE_FIRMWARE_LOAD;
473 : 0 : fw->req->cn10k_req.jd.hdr.result =
474 : 0 : roc_ml_addr_ap2mlip(&cn10k_mldev->roc, &fw->req->cn10k_req.result);
475 : 0 : fw->req->cn10k_req.jd.fw_load.flags = cn10k_ml_fw_flags_get(fw);
476 : 0 : plt_write64(ML_CNXK_POLL_JOB_START, &fw->req->cn10k_req.status);
477 : : plt_wmb();
478 : :
479 : : /* Enqueue FW load through scratch registers */
480 : : timeout = true;
481 : 0 : timeout_cycle = plt_tsc_cycles() + ML_CNXK_CMD_TIMEOUT * plt_tsc_hz();
482 : 0 : roc_ml_scratch_enqueue(&cn10k_mldev->roc, &fw->req->cn10k_req.jd);
483 : :
484 : : plt_rmb();
485 : : do {
486 [ # # # # ]: 0 : if (roc_ml_scratch_is_done_bit_set(&cn10k_mldev->roc) &&
487 [ # # ]: 0 : (plt_read64(&fw->req->cn10k_req.status) == ML_CNXK_POLL_JOB_FINISH)) {
488 : : timeout = false;
489 : : break;
490 : : }
491 [ # # ]: 0 : } while (plt_tsc_cycles() < timeout_cycle);
492 : :
493 : : /* Check firmware load status, clean-up and exit on failure. */
494 [ # # # # ]: 0 : if ((!timeout) && (fw->req->cn10k_req.result.error_code == 0)) {
495 : 0 : cn10k_ml_fw_print_info(fw);
496 : : } else {
497 : : /* Set ML to disable new jobs */
498 : : reg_val64 = (ROC_ML_CFG_JD_SIZE | ROC_ML_CFG_MLIP_ENA);
499 : 0 : roc_ml_reg_write64(&cn10k_mldev->roc, reg_val64, ML_CFG);
500 : :
501 : : /* Clear scratch registers */
502 : 0 : roc_ml_reg_write64(&cn10k_mldev->roc, 0, ML_SCRATCH_WORK_PTR);
503 : 0 : roc_ml_reg_write64(&cn10k_mldev->roc, 0, ML_SCRATCH_FW_CTRL);
504 : :
505 [ # # ]: 0 : if (timeout) {
506 : 0 : plt_err("Firmware load timeout");
507 : : ret = -ETIME;
508 : : } else {
509 : 0 : plt_err("Firmware load failed");
510 : : ret = -1;
511 : : }
512 : :
513 : 0 : return ret;
514 : : }
515 : :
516 : : /* Reset scratch registers */
517 : 0 : roc_ml_reg_write64(&cn10k_mldev->roc, 0, ML_SCRATCH_FW_CTRL);
518 : 0 : roc_ml_reg_write64(&cn10k_mldev->roc, 0, ML_SCRATCH_WORK_PTR);
519 : :
520 : : /* Disable job execution, to be enabled in start */
521 : 0 : reg_val64 = roc_ml_reg_read64(&cn10k_mldev->roc, ML_CFG);
522 : 0 : reg_val64 &= ~ROC_ML_CFG_ENA;
523 : 0 : roc_ml_reg_write64(&cn10k_mldev->roc, reg_val64, ML_CFG);
524 : 0 : plt_ml_dbg("ML_CFG => 0x%016lx", roc_ml_reg_read64(&cn10k_mldev->roc, ML_CFG));
525 : :
526 : 0 : return ret;
527 : : }
528 : :
529 : : static int
530 : 0 : cn10k_ml_fw_load_cn10ka(struct cn10k_ml_fw *fw, void *buffer, uint64_t size)
531 : : {
532 : : union ml_a35_0_rst_vector_base_s a35_0_rst_vector_base;
533 : : union ml_a35_0_rst_vector_base_s a35_1_rst_vector_base;
534 : : struct cn10k_ml_dev *cn10k_mldev;
535 : : uint64_t timeout_cycle;
536 : : uint64_t reg_val64;
537 : : uint32_t reg_val32;
538 : : uint64_t offset;
539 : : bool timeout;
540 : : int ret = 0;
541 : : uint8_t i;
542 : :
543 : 0 : cn10k_mldev = fw->cn10k_mldev;
544 : :
545 : : /* Reset HEAD and TAIL debug pointer registers */
546 : 0 : roc_ml_reg_write64(&cn10k_mldev->roc, 0, ML_SCRATCH_DBG_BUFFER_HEAD_C0);
547 : 0 : roc_ml_reg_write64(&cn10k_mldev->roc, 0, ML_SCRATCH_DBG_BUFFER_TAIL_C0);
548 : 0 : roc_ml_reg_write64(&cn10k_mldev->roc, 0, ML_SCRATCH_DBG_BUFFER_HEAD_C1);
549 : 0 : roc_ml_reg_write64(&cn10k_mldev->roc, 0, ML_SCRATCH_DBG_BUFFER_TAIL_C1);
550 : 0 : roc_ml_reg_write64(&cn10k_mldev->roc, 0, ML_SCRATCH_EXCEPTION_SP_C0);
551 : 0 : roc_ml_reg_write64(&cn10k_mldev->roc, 0, ML_SCRATCH_EXCEPTION_SP_C1);
552 : :
553 : : /* (1) Write firmware images for ACC's two A35 cores to the ML region in LLC / DRAM. */
554 [ # # ]: 0 : rte_memcpy(PLT_PTR_ADD(fw->data, FW_LINKER_OFFSET), buffer, size);
555 : :
556 : : /* (2) Set ML(0)_MLR_BASE = Base IOVA of the ML region in LLC/DRAM. */
557 : 0 : reg_val64 = PLT_PTR_SUB_U64_CAST(fw->data, rte_eal_get_baseaddr());
558 : 0 : roc_ml_reg_write64(&cn10k_mldev->roc, reg_val64, ML_MLR_BASE);
559 : 0 : plt_ml_dbg("ML_MLR_BASE => 0x%016lx", roc_ml_reg_read64(&cn10k_mldev->roc, ML_MLR_BASE));
560 : 0 : roc_ml_reg_save(&cn10k_mldev->roc, ML_MLR_BASE);
561 : :
562 : : /* (3) Set ML(0)_AXI_BRIDGE_CTRL(1) = 0x184003 to remove back-pressure check on DMA AXI
563 : : * bridge.
564 : : */
565 : : reg_val64 = (ROC_ML_AXI_BRIDGE_CTRL_AXI_RESP_CTRL |
566 : : ROC_ML_AXI_BRIDGE_CTRL_BRIDGE_CTRL_MODE | ROC_ML_AXI_BRIDGE_CTRL_NCB_WR_BLK |
567 : : ROC_ML_AXI_BRIDGE_CTRL_FORCE_WRESP_OK | ROC_ML_AXI_BRIDGE_CTRL_FORCE_RRESP_OK);
568 : 0 : roc_ml_reg_write64(&cn10k_mldev->roc, reg_val64, ML_AXI_BRIDGE_CTRL(1));
569 : 0 : plt_ml_dbg("ML_AXI_BRIDGE_CTRL(1) => 0x%016lx",
570 : : roc_ml_reg_read64(&cn10k_mldev->roc, ML_AXI_BRIDGE_CTRL(1)));
571 : :
572 : : /* (4) Set ML(0)_ANB(0..2)_BACKP_DISABLE = 0x3 to remove back-pressure on the AXI to NCB
573 : : * bridges.
574 : : */
575 [ # # ]: 0 : for (i = 0; i < ML_ANBX_NR; i++) {
576 : : reg_val64 = (ROC_ML_ANBX_BACKP_DISABLE_EXTMSTR_B_BACKP_DISABLE |
577 : : ROC_ML_ANBX_BACKP_DISABLE_EXTMSTR_R_BACKP_DISABLE);
578 : 0 : roc_ml_reg_write64(&cn10k_mldev->roc, reg_val64, ML_ANBX_BACKP_DISABLE(i));
579 : 0 : plt_ml_dbg("ML_ANBX_BACKP_DISABLE(%u) => 0x%016lx", i,
580 : : roc_ml_reg_read64(&cn10k_mldev->roc, ML_ANBX_BACKP_DISABLE(i)));
581 : : }
582 : :
583 : : /* (5) Set ML(0)_ANB(0..2)_NCBI_P_OVR = 0x3000 and ML(0)_ANB(0..2)_NCBI_NP_OVR = 0x3000 to
584 : : * signal all ML transactions as non-secure.
585 : : */
586 [ # # ]: 0 : for (i = 0; i < ML_ANBX_NR; i++) {
587 : : reg_val64 = (ML_ANBX_NCBI_P_OVR_ANB_NCBI_P_NS_OVR |
588 : : ML_ANBX_NCBI_P_OVR_ANB_NCBI_P_NS_OVR_VLD);
589 : 0 : roc_ml_reg_write64(&cn10k_mldev->roc, reg_val64, ML_ANBX_NCBI_P_OVR(i));
590 : 0 : plt_ml_dbg("ML_ANBX_NCBI_P_OVR(%u) => 0x%016lx", i,
591 : : roc_ml_reg_read64(&cn10k_mldev->roc, ML_ANBX_NCBI_P_OVR(i)));
592 : :
593 : : reg_val64 |= (ML_ANBX_NCBI_NP_OVR_ANB_NCBI_NP_NS_OVR |
594 : : ML_ANBX_NCBI_NP_OVR_ANB_NCBI_NP_NS_OVR_VLD);
595 : 0 : roc_ml_reg_write64(&cn10k_mldev->roc, reg_val64, ML_ANBX_NCBI_NP_OVR(i));
596 : 0 : plt_ml_dbg("ML_ANBX_NCBI_NP_OVR(%u) => 0x%016lx", i,
597 : : roc_ml_reg_read64(&cn10k_mldev->roc, ML_ANBX_NCBI_NP_OVR(i)));
598 : : }
599 : :
600 : : /* (6) Set ML(0)_CFG[MLIP_CLK_FORCE] = 1, to force turning on the MLIP clock. */
601 : 0 : reg_val64 = roc_ml_reg_read64(&cn10k_mldev->roc, ML_CFG);
602 : 0 : reg_val64 |= ROC_ML_CFG_MLIP_CLK_FORCE;
603 : 0 : roc_ml_reg_write64(&cn10k_mldev->roc, reg_val64, ML_CFG);
604 : 0 : plt_ml_dbg("ML_CFG => 0x%016lx", roc_ml_reg_read64(&cn10k_mldev->roc, ML_CFG));
605 : :
606 : : /* (7) Set ML(0)_JOB_MGR_CTRL[STALL_ON_IDLE] = 0, to make sure the boot request is accepted
607 : : * when there is no job in the command queue.
608 : : */
609 : 0 : reg_val64 = roc_ml_reg_read64(&cn10k_mldev->roc, ML_JOB_MGR_CTRL);
610 : 0 : reg_val64 &= ~ROC_ML_JOB_MGR_CTRL_STALL_ON_IDLE;
611 : 0 : roc_ml_reg_write64(&cn10k_mldev->roc, reg_val64, ML_JOB_MGR_CTRL);
612 : 0 : plt_ml_dbg("ML_JOB_MGR_CTRL => 0x%016lx",
613 : : roc_ml_reg_read64(&cn10k_mldev->roc, ML_JOB_MGR_CTRL));
614 : :
615 : : /* (8) Set ML(0)_CFG[ENA] = 0 and ML(0)_CFG[MLIP_ENA] = 1 to bring MLIP out of reset while
616 : : * keeping the job manager disabled.
617 : : */
618 : 0 : reg_val64 = roc_ml_reg_read64(&cn10k_mldev->roc, ML_CFG);
619 : : reg_val64 |= ROC_ML_CFG_MLIP_ENA;
620 : 0 : reg_val64 &= ~ROC_ML_CFG_ENA;
621 : 0 : roc_ml_reg_write64(&cn10k_mldev->roc, reg_val64, ML_CFG);
622 : 0 : plt_ml_dbg("ML_CFG => 0x%016lx", roc_ml_reg_read64(&cn10k_mldev->roc, ML_CFG));
623 : :
624 : : /* (9) Wait at least 70 coprocessor clock cycles. */
625 : 0 : plt_delay_us(FW_WAIT_CYCLES);
626 : :
627 : : /* (10) Write ML outbound addresses pointing to the firmware images written in step 1 to the
628 : : * following registers: ML(0)_A35_0_RST_VECTOR_BASE_W(0..1) for core 0,
629 : : * ML(0)_A35_1_RST_VECTOR_BASE_W(0..1) for core 1. The value written to each register is the
630 : : * AXI outbound address divided by 4. Read after write.
631 : : */
632 : 0 : offset = PLT_PTR_ADD_U64_CAST(
633 : : fw->data, FW_LINKER_OFFSET - roc_ml_reg_read64(&cn10k_mldev->roc, ML_MLR_BASE));
634 : 0 : a35_0_rst_vector_base.s.addr = (offset + ML_AXI_START_ADDR) / 4;
635 : 0 : a35_1_rst_vector_base.s.addr = (offset + ML_AXI_START_ADDR) / 4;
636 : :
637 : 0 : roc_ml_reg_write32(&cn10k_mldev->roc, a35_0_rst_vector_base.w.w0,
638 : : ML_A35_0_RST_VECTOR_BASE_W(0));
639 : 0 : reg_val32 = roc_ml_reg_read32(&cn10k_mldev->roc, ML_A35_0_RST_VECTOR_BASE_W(0));
640 : 0 : plt_ml_dbg("ML_A35_0_RST_VECTOR_BASE_W(0) => 0x%08x", reg_val32);
641 : :
642 : 0 : roc_ml_reg_write32(&cn10k_mldev->roc, a35_0_rst_vector_base.w.w1,
643 : : ML_A35_0_RST_VECTOR_BASE_W(1));
644 : 0 : reg_val32 = roc_ml_reg_read32(&cn10k_mldev->roc, ML_A35_0_RST_VECTOR_BASE_W(1));
645 : 0 : plt_ml_dbg("ML_A35_0_RST_VECTOR_BASE_W(1) => 0x%08x", reg_val32);
646 : :
647 : 0 : roc_ml_reg_write32(&cn10k_mldev->roc, a35_1_rst_vector_base.w.w0,
648 : : ML_A35_1_RST_VECTOR_BASE_W(0));
649 : 0 : reg_val32 = roc_ml_reg_read32(&cn10k_mldev->roc, ML_A35_1_RST_VECTOR_BASE_W(0));
650 : 0 : plt_ml_dbg("ML_A35_1_RST_VECTOR_BASE_W(0) => 0x%08x", reg_val32);
651 : :
652 : 0 : roc_ml_reg_write32(&cn10k_mldev->roc, a35_1_rst_vector_base.w.w1,
653 : : ML_A35_1_RST_VECTOR_BASE_W(1));
654 : 0 : reg_val32 = roc_ml_reg_read32(&cn10k_mldev->roc, ML_A35_1_RST_VECTOR_BASE_W(1));
655 : 0 : plt_ml_dbg("ML_A35_1_RST_VECTOR_BASE_W(1) => 0x%08x", reg_val32);
656 : :
657 : : /* (11) Clear MLIP's ML(0)_SW_RST_CTRL[ACC_RST]. This will bring the ACC cores and other
658 : : * MLIP components out of reset. The cores will execute firmware from the ML region as
659 : : * written in step 1.
660 : : */
661 : 0 : reg_val32 = roc_ml_reg_read32(&cn10k_mldev->roc, ML_SW_RST_CTRL);
662 : 0 : reg_val32 &= ~ROC_ML_SW_RST_CTRL_ACC_RST;
663 : 0 : roc_ml_reg_write32(&cn10k_mldev->roc, reg_val32, ML_SW_RST_CTRL);
664 : 0 : reg_val32 = roc_ml_reg_read32(&cn10k_mldev->roc, ML_SW_RST_CTRL);
665 : 0 : plt_ml_dbg("ML_SW_RST_CTRL => 0x%08x", reg_val32);
666 : :
667 : : /* (12) Wait for notification from firmware that ML is ready for job execution. */
668 : 0 : fw->req->cn10k_req.jd.hdr.jce.w1.u64 = PLT_U64_CAST(&fw->req->cn10k_req.status);
669 : 0 : fw->req->cn10k_req.jd.hdr.job_type = ML_CN10K_JOB_TYPE_FIRMWARE_LOAD;
670 : 0 : fw->req->cn10k_req.jd.hdr.result =
671 : 0 : roc_ml_addr_ap2mlip(&cn10k_mldev->roc, &fw->req->cn10k_req.result);
672 : 0 : fw->req->cn10k_req.jd.fw_load.flags = cn10k_ml_fw_flags_get(fw);
673 : 0 : plt_write64(ML_CNXK_POLL_JOB_START, &fw->req->cn10k_req.status);
674 : : plt_wmb();
675 : :
676 : : /* Enqueue FW load through scratch registers */
677 : : timeout = true;
678 : 0 : timeout_cycle = plt_tsc_cycles() + ML_CNXK_CMD_TIMEOUT * plt_tsc_hz();
679 : 0 : roc_ml_scratch_enqueue(&cn10k_mldev->roc, &fw->req->cn10k_req.jd);
680 : :
681 : : plt_rmb();
682 : : do {
683 [ # # # # ]: 0 : if (roc_ml_scratch_is_done_bit_set(&cn10k_mldev->roc) &&
684 [ # # ]: 0 : (plt_read64(&fw->req->cn10k_req.status) == ML_CNXK_POLL_JOB_FINISH)) {
685 : : timeout = false;
686 : : break;
687 : : }
688 [ # # ]: 0 : } while (plt_tsc_cycles() < timeout_cycle);
689 : :
690 : : /* Check firmware load status, clean-up and exit on failure. */
691 [ # # # # ]: 0 : if ((!timeout) && (fw->req->cn10k_req.result.error_code == 0)) {
692 : 0 : cn10k_ml_fw_print_info(fw);
693 : : } else {
694 : : /* Set ML to disable new jobs */
695 : : reg_val64 = (ROC_ML_CFG_JD_SIZE | ROC_ML_CFG_MLIP_ENA);
696 : 0 : roc_ml_reg_write64(&cn10k_mldev->roc, reg_val64, ML_CFG);
697 : :
698 : : /* Clear scratch registers */
699 : 0 : roc_ml_reg_write64(&cn10k_mldev->roc, 0, ML_SCRATCH_WORK_PTR);
700 : 0 : roc_ml_reg_write64(&cn10k_mldev->roc, 0, ML_SCRATCH_FW_CTRL);
701 : :
702 [ # # ]: 0 : if (timeout) {
703 : 0 : plt_err("Firmware load timeout");
704 : : ret = -ETIME;
705 : : } else {
706 : 0 : plt_err("Firmware load failed");
707 : : ret = -1;
708 : : }
709 : :
710 : 0 : return ret;
711 : : }
712 : :
713 : : /* (13) Set ML(0)_JOB_MGR_CTRL[STALL_ON_IDLE] = 0x1; this is needed to shut down the MLIP
714 : : * clock when there are no more jobs to process.
715 : : */
716 : 0 : reg_val64 = roc_ml_reg_read64(&cn10k_mldev->roc, ML_JOB_MGR_CTRL);
717 : 0 : reg_val64 |= ROC_ML_JOB_MGR_CTRL_STALL_ON_IDLE;
718 : 0 : roc_ml_reg_write64(&cn10k_mldev->roc, reg_val64, ML_JOB_MGR_CTRL);
719 : 0 : plt_ml_dbg("ML_JOB_MGR_CTRL => 0x%016lx",
720 : : roc_ml_reg_read64(&cn10k_mldev->roc, ML_JOB_MGR_CTRL));
721 : :
722 : : /* (14) Set ML(0)_CFG[MLIP_CLK_FORCE] = 0; the MLIP clock will be turned on/off based on job
723 : : * activities.
724 : : */
725 : 0 : reg_val64 = roc_ml_reg_read64(&cn10k_mldev->roc, ML_CFG);
726 : 0 : reg_val64 &= ~ROC_ML_CFG_MLIP_CLK_FORCE;
727 : 0 : roc_ml_reg_write64(&cn10k_mldev->roc, reg_val64, ML_CFG);
728 : 0 : plt_ml_dbg("ML_CFG => 0x%016lx", roc_ml_reg_read64(&cn10k_mldev->roc, ML_CFG));
729 : :
730 : : /* (15) Set ML(0)_CFG[ENA] to enable ML job execution. */
731 : 0 : reg_val64 = roc_ml_reg_read64(&cn10k_mldev->roc, ML_CFG);
732 : 0 : reg_val64 |= ROC_ML_CFG_ENA;
733 : 0 : roc_ml_reg_write64(&cn10k_mldev->roc, reg_val64, ML_CFG);
734 : 0 : plt_ml_dbg("ML_CFG => 0x%016lx", roc_ml_reg_read64(&cn10k_mldev->roc, ML_CFG));
735 : :
736 : : /* Reset scratch registers */
737 : 0 : roc_ml_reg_write64(&cn10k_mldev->roc, 0, ML_SCRATCH_FW_CTRL);
738 : 0 : roc_ml_reg_write64(&cn10k_mldev->roc, 0, ML_SCRATCH_WORK_PTR);
739 : :
740 : : /* Disable job execution, to be enabled in start */
741 : 0 : reg_val64 = roc_ml_reg_read64(&cn10k_mldev->roc, ML_CFG);
742 : 0 : reg_val64 &= ~ROC_ML_CFG_ENA;
743 : 0 : roc_ml_reg_write64(&cn10k_mldev->roc, reg_val64, ML_CFG);
744 : 0 : plt_ml_dbg("ML_CFG => 0x%016lx", roc_ml_reg_read64(&cn10k_mldev->roc, ML_CFG));
745 : :
746 : : /* Additional fixes: Set RO bit to fix O2D DMA bandwidth issue on cn10ka */
747 [ # # ]: 0 : for (i = 0; i < ML_ANBX_NR; i++) {
748 : 0 : reg_val64 = roc_ml_reg_read64(&cn10k_mldev->roc, ML_ANBX_NCBI_P_OVR(i));
749 : 0 : reg_val64 |= (ML_ANBX_NCBI_P_OVR_ANB_NCBI_P_RO_OVR |
750 : : ML_ANBX_NCBI_P_OVR_ANB_NCBI_P_RO_OVR_VLD);
751 : 0 : roc_ml_reg_write64(&cn10k_mldev->roc, reg_val64, ML_ANBX_NCBI_P_OVR(i));
752 : : }
753 : :
754 : : return ret;
755 : : }
756 : :
757 : : int
758 : 0 : cn10k_ml_fw_load(struct cnxk_ml_dev *cnxk_mldev)
759 : : {
760 : : struct cn10k_ml_dev *cn10k_mldev;
761 : : const struct plt_memzone *mz;
762 : : struct cn10k_ml_fw *fw;
763 : 0 : void *fw_buffer = NULL;
764 : : uint64_t mz_size = 0;
765 : 0 : uint64_t fw_size = 0;
766 : : int ret = 0;
767 : :
768 : 0 : cn10k_mldev = &cnxk_mldev->cn10k_mldev;
769 : 0 : fw = &cn10k_mldev->fw;
770 [ # # ]: 0 : fw->cn10k_mldev = cn10k_mldev;
771 : :
772 [ # # # # ]: 0 : if (roc_env_is_emulator() || roc_env_is_hw()) {
773 : : /* Read firmware image to a buffer */
774 : 0 : ret = rte_firmware_read(fw->path, &fw_buffer, &fw_size);
775 [ # # # # ]: 0 : if ((ret < 0) || (fw_buffer == NULL)) {
776 : 0 : plt_err("Unable to read firmware data: %s\n", fw->path);
777 : 0 : return ret;
778 : : }
779 : :
780 : : /* Reserve memzone for firmware load completion and data */
781 : 0 : mz_size = sizeof(struct cnxk_ml_req) + fw_size + FW_STACK_BUFFER_SIZE +
782 : 0 : FW_DEBUG_BUFFER_SIZE + FW_EXCEPTION_BUFFER_SIZE;
783 [ # # ]: 0 : } else if (roc_env_is_asim()) {
784 : : /* Reserve memzone for firmware load completion */
785 : : mz_size = sizeof(struct cnxk_ml_req);
786 : : }
787 : :
788 : 0 : mz = plt_memzone_reserve_aligned(FW_MEMZONE_NAME, mz_size, 0, ML_CN10K_ALIGN_SIZE);
789 [ # # ]: 0 : if (mz == NULL) {
790 : 0 : plt_err("plt_memzone_reserve failed : %s", FW_MEMZONE_NAME);
791 : 0 : free(fw_buffer);
792 : 0 : return -ENOMEM;
793 : : }
794 : 0 : fw->req = mz->addr;
795 : :
796 : : /* Reset firmware load completion structure */
797 : 0 : memset(&fw->req->cn10k_req.jd, 0, sizeof(struct cn10k_ml_jd));
798 : 0 : memset(&fw->req->cn10k_req.jd.fw_load.version[0], '\0', MLDEV_FIRMWARE_VERSION_LENGTH);
799 : :
800 : : /* Reset device, if in active state */
801 [ # # ]: 0 : if (roc_ml_mlip_is_enabled(&cn10k_mldev->roc))
802 : 0 : roc_ml_mlip_reset(&cn10k_mldev->roc, true);
803 : :
804 : : /* Load firmware */
805 [ # # # # ]: 0 : if (roc_env_is_emulator() || roc_env_is_hw()) {
806 : 0 : fw->data = PLT_PTR_ADD(mz->addr, sizeof(struct cnxk_ml_req));
807 : 0 : ret = cn10k_ml_fw_load_cn10ka(fw, fw_buffer, fw_size);
808 : 0 : free(fw_buffer);
809 [ # # ]: 0 : } else if (roc_env_is_asim()) {
810 : 0 : fw->data = NULL;
811 : 0 : ret = cn10k_ml_fw_load_asim(fw);
812 : : }
813 : :
814 [ # # ]: 0 : if (ret < 0)
815 : 0 : cn10k_ml_fw_unload(cnxk_mldev);
816 : :
817 : : return ret;
818 : : }
819 : :
820 : : void
821 : 0 : cn10k_ml_fw_unload(struct cnxk_ml_dev *cnxk_mldev)
822 : : {
823 : : struct cn10k_ml_dev *cn10k_mldev;
824 : : const struct plt_memzone *mz;
825 : : uint64_t reg_val;
826 : :
827 : : cn10k_mldev = &cnxk_mldev->cn10k_mldev;
828 : :
829 : : /* Disable and reset device */
830 : 0 : reg_val = roc_ml_reg_read64(&cn10k_mldev->roc, ML_CFG);
831 : 0 : reg_val &= ~ROC_ML_CFG_MLIP_ENA;
832 : 0 : roc_ml_reg_write64(&cn10k_mldev->roc, reg_val, ML_CFG);
833 : 0 : roc_ml_mlip_reset(&cn10k_mldev->roc, true);
834 : :
835 : 0 : mz = plt_memzone_lookup(FW_MEMZONE_NAME);
836 [ # # ]: 0 : if (mz != NULL)
837 : 0 : plt_memzone_free(mz);
838 : 0 : }
839 : :
840 : : static struct rte_pci_id pci_id_ml_table[] = {
841 : : {RTE_PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, PCI_DEVID_CN10K_ML_PF)},
842 : : /* sentinel */
843 : : {},
844 : : };
845 : :
846 : : static struct rte_pci_driver cn10k_mldev_pmd = {
847 : : .id_table = pci_id_ml_table,
848 : : .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_NEED_IOVA_AS_VA,
849 : : .probe = cn10k_ml_pci_probe,
850 : : .remove = cn10k_ml_pci_remove,
851 : : };
852 : :
853 : 238 : RTE_PMD_REGISTER_PCI(MLDEV_NAME_CN10K_PMD, cn10k_mldev_pmd);
854 : : RTE_PMD_REGISTER_PCI_TABLE(MLDEV_NAME_CN10K_PMD, pci_id_ml_table);
855 : : RTE_PMD_REGISTER_KMOD_DEP(MLDEV_NAME_CN10K_PMD, "vfio-pci");
856 : :
857 : : RTE_PMD_REGISTER_PARAM_STRING(MLDEV_NAME_CN10K_PMD, CN10K_ML_FW_PATH
858 : : "=<path>" CN10K_ML_FW_ENABLE_DPE_WARNINGS
859 : : "=<0|1>" CN10K_ML_FW_REPORT_DPE_WARNINGS
860 : : "=<0|1>" CN10K_ML_DEV_CACHE_MODEL_DATA
861 : : "=<0|1>" CN10K_ML_OCM_ALLOC_MODE
862 : : "=<lowest|largest>" CN10K_ML_DEV_HW_QUEUE_LOCK
863 : : "=<0|1>" CN10K_ML_OCM_PAGE_SIZE "=<1024|2048|4096|8192|16384>");
|