Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright (C), 2025, Wuxi Stars Micro System Technologies Co., Ltd.
3 : : */
4 : :
5 : : #include <rte_version.h>
6 : : #include <rte_pci.h>
7 : : #include <rte_dev.h>
8 : : #include <rte_devargs.h>
9 : : #include <rte_class.h>
10 : : #include <rte_malloc.h>
11 : : #include <rte_errno.h>
12 : : #include <rte_fbarray.h>
13 : : #include <rte_eal.h>
14 : : #include <eal_private.h>
15 : : #include <eal_memcfg.h>
16 : : #include <bus_driver.h>
17 : : #include <bus_pci_driver.h>
18 : : #include <eal_export.h>
19 : : #include <pthread.h>
20 : :
21 : : #include "sxe2_common.h"
22 : : #include "sxe2_common_log.h"
23 : : #include "sxe2_ioctl_chnl_func.h"
24 : :
25 : : static TAILQ_HEAD(sxe2_class_drivers, sxe2_class_driver) sxe2_class_drivers_list =
26 : : TAILQ_HEAD_INITIALIZER(sxe2_class_drivers_list);
27 : :
28 : : static TAILQ_HEAD(sxe2_common_devices, sxe2_common_device) sxe2_common_devices_list =
29 : : TAILQ_HEAD_INITIALIZER(sxe2_common_devices_list);
30 : :
31 : : static pthread_mutex_t sxe2_common_devices_list_lock;
32 : :
33 : : static struct rte_pci_id *sxe2_common_pci_id_table;
34 : :
35 : : static const struct {
36 : : const char *name;
37 : : uint32_t class_type;
38 : : } sxe2_class_types[] = {
39 : : { .name = "eth", .class_type = SXE2_CLASS_TYPE_ETH },
40 : : { .name = "vdpa", .class_type = SXE2_CLASS_TYPE_VDPA },
41 : : };
42 : :
43 : 0 : static uint32_t sxe2_class_name_to_value(const char *class_name)
44 : : {
45 : : uint32_t class_type = SXE2_CLASS_TYPE_INVALID;
46 : : uint32_t i;
47 : :
48 [ # # ]: 0 : for (i = 0; i < RTE_DIM(sxe2_class_types); i++) {
49 [ # # ]: 0 : if (strcmp(class_name, sxe2_class_types[i].name) == 0)
50 : 0 : class_type = sxe2_class_types[i].class_type;
51 : : }
52 : :
53 : 0 : return class_type;
54 : : }
55 : :
56 : : static struct sxe2_common_device *sxe2_rtedev_to_cdev(struct rte_device *rte_dev)
57 : : {
58 : : struct sxe2_common_device *cdev = NULL;
59 : :
60 [ # # # # : 0 : TAILQ_FOREACH(cdev, &sxe2_common_devices_list, next) {
# # # # ]
61 [ # # # # : 0 : if (rte_dev == cdev->dev)
# # # # ]
62 : 0 : goto l_end;
63 : : }
64 : :
65 : : cdev = NULL;
66 : 0 : l_end:
67 : : return cdev;
68 : : }
69 : :
70 : : static struct sxe2_class_driver *sxe2_class_driver_get(uint32_t class_type)
71 : : {
72 : : struct sxe2_class_driver *cdrv = NULL;
73 : :
74 [ # # ]: 0 : TAILQ_FOREACH(cdrv, &sxe2_class_drivers_list, next) {
75 [ # # ]: 0 : if (cdrv->drv_class == class_type)
76 : 0 : goto l_end;
77 : : }
78 : :
79 : : cdrv = NULL;
80 : 0 : l_end:
81 : : return cdrv;
82 : : }
83 : :
84 : 0 : static int32_t sxe2_kvargs_preprocessing(struct sxe2_dev_kvargs_info *kv_info,
85 : : const struct rte_devargs *devargs)
86 : : {
87 : : const struct rte_kvargs_pair *pair;
88 : : struct rte_kvargs *kvlist;
89 : : int32_t ret = -1;
90 : : uint32_t i;
91 : :
92 : 0 : kvlist = rte_kvargs_parse(devargs->args, NULL);
93 [ # # ]: 0 : if (kvlist == NULL) {
94 : : ret = -EINVAL;
95 : 0 : goto l_end;
96 : : }
97 : :
98 [ # # ]: 0 : for (i = 0; i < kvlist->count; i++) {
99 : : pair = &kvlist->pairs[i];
100 [ # # # # ]: 0 : if (pair->value == NULL || *(pair->value) == '\0') {
101 : 0 : PMD_LOG_ERR(COM, "Key %s has no value.", pair->key);
102 : 0 : rte_kvargs_free(kvlist);
103 : : ret = -EINVAL;
104 : 0 : goto l_end;
105 : : }
106 : : }
107 : :
108 : 0 : kv_info->kvlist = kvlist;
109 : : ret = 0;
110 : 0 : PMD_LOG_DEBUG(COM, "kvargs %d preprocessing success.",
111 : : kv_info->kvlist->count);
112 : 0 : l_end:
113 : 0 : return ret;
114 : : }
115 : :
116 : : static void sxe2_kvargs_free(struct sxe2_dev_kvargs_info *kv_info)
117 : : {
118 [ # # # # ]: 0 : if ((kv_info != NULL) && (kv_info->kvlist != NULL)) {
119 : 0 : rte_kvargs_free(kv_info->kvlist);
120 : 0 : kv_info->kvlist = NULL;
121 : : }
122 : : }
123 : :
124 : : RTE_EXPORT_INTERNAL_SYMBOL(sxe2_kvargs_process)
125 : : int32_t
126 : 0 : sxe2_kvargs_process(struct sxe2_dev_kvargs_info *kv_info,
127 : : const char *const key_match, arg_handler_t handler, void *opaque_arg)
128 : : {
129 : : const struct rte_kvargs_pair *pair;
130 : : struct rte_kvargs *kvlist;
131 : : uint32_t i;
132 : : int32_t ret = 0;
133 : :
134 [ # # # # : 0 : if ((kv_info == NULL) || (kv_info->kvlist == NULL) ||
# # ]
135 : : (key_match == NULL)) {
136 : 0 : PMD_LOG_ERR(COM, "Failed to process kvargs, NULL parameter.");
137 : : ret = -EINVAL;
138 : 0 : goto l_end;
139 : : }
140 : : kvlist = kv_info->kvlist;
141 : :
142 [ # # ]: 0 : for (i = 0; i < kvlist->count; i++) {
143 : : pair = &kvlist->pairs[i];
144 [ # # ]: 0 : if (strcmp(pair->key, key_match) == 0) {
145 : 0 : ret = (*handler)(pair->key, pair->value, opaque_arg);
146 [ # # ]: 0 : if (ret)
147 : 0 : goto l_end;
148 : :
149 : 0 : kv_info->is_used[i] = true;
150 : 0 : break;
151 : : }
152 : : }
153 : :
154 : 0 : l_end:
155 : 0 : return ret;
156 : : }
157 : :
158 : 0 : static int32_t sxe2_parse_class_type(const char *key, const char *value, void *args)
159 : : {
160 : : uint32_t *class_type = (uint32_t *)args;
161 : : int32_t ret = 0;
162 : :
163 : 0 : *class_type = sxe2_class_name_to_value(value);
164 [ # # ]: 0 : if (*class_type == SXE2_CLASS_TYPE_INVALID) {
165 : : ret = -EINVAL;
166 : 0 : PMD_LOG_ERR(COM, "Unsupported %s type: %s", key, value);
167 : : }
168 : :
169 : 0 : return ret;
170 : : }
171 : :
172 : 0 : static int32_t sxe2_parse_driver(const char *key, const char *value, void *args)
173 : : {
174 : : int32_t ret = -EINVAL;
175 : :
176 [ # # ]: 0 : if (value == NULL || args == NULL) {
177 : : ret = 0;
178 : 0 : goto l_end;
179 : : }
180 : :
181 [ # # ]: 0 : if (strcmp(value, "sxe2") != 0) {
182 : 0 : PMD_LOG_ERR(COM, "%s: \"%s\" is not a valid driver.",
183 : : key, value);
184 : 0 : goto l_end;
185 : : }
186 : 0 : l_end:
187 : 0 : return ret;
188 : : }
189 : :
190 : 0 : static int32_t sxe2_parse_representor(const char *key, const char *value, void *args)
191 : : {
192 : : int32_t ret = 0;
193 : :
194 [ # # ]: 0 : if (value == NULL || args == NULL)
195 : 0 : goto l_end;
196 : :
197 : 0 : PMD_LOG_INFO(COM, "representor arg %s: \"%s\".", key, value);
198 : :
199 : 0 : l_end:
200 : 0 : return ret;
201 : : }
202 : 0 : static int32_t sxe2_dma_mem_map(struct sxe2_common_device *cdev,
203 : : const void *addr, size_t len, bool do_map)
204 : : {
205 : : struct rte_memseg_list *msl;
206 : : struct rte_memseg *ms;
207 : : size_t cur_len = 0;
208 : : int32_t ret = 0;
209 : :
210 : 0 : msl = rte_mem_virt2memseg_list(addr);
211 [ # # ]: 0 : if (msl == NULL) {
212 : : ret = -EINVAL;
213 : 0 : PMD_LOG_ERR(COM, "Invalid virt addr=%p.", addr);
214 : 0 : goto l_end;
215 : : }
216 : :
217 [ # # ]: 0 : if ((uintptr_t)addr != RTE_ALIGN((uintptr_t)addr, msl->page_sz) ||
218 [ # # ]: 0 : (len != RTE_ALIGN(len, msl->page_sz))) {
219 : : ret = -EINVAL;
220 : 0 : PMD_LOG_ERR(COM, "Addr=%p and len=%zu not align page size=%" PRIu64 ".",
221 : : addr, len, msl->page_sz);
222 : 0 : goto l_end;
223 : : }
224 : :
225 : : /* memsegs are contiguous in memory */
226 : 0 : ms = rte_mem_virt2memseg(addr, msl);
227 [ # # ]: 0 : while (cur_len < len) {
228 : : /* some memory segments may have invalid IOVA */
229 [ # # ]: 0 : if (ms->iova == RTE_BAD_IOVA) {
230 : 0 : PMD_LOG_WARN(COM, "Memory segment at %p has bad IOVA, skipping.",
231 : : ms->addr);
232 : 0 : goto next;
233 : : }
234 [ # # ]: 0 : if (do_map)
235 : 0 : sxe2_drv_dev_dma_map(cdev, ms->addr_64,
236 : : ms->iova, ms->len);
237 : : else
238 : 0 : sxe2_drv_dev_dma_unmap(cdev, ms->iova);
239 : :
240 : 0 : next:
241 : 0 : cur_len += ms->len;
242 : 0 : ++ms;
243 : : }
244 : :
245 : 0 : l_end:
246 : 0 : return ret;
247 : : }
248 : :
249 : : RTE_EXPORT_INTERNAL_SYMBOL(sxe2_common_mem_event_cb)
250 : : void
251 : 0 : sxe2_common_mem_event_cb(enum rte_mem_event type,
252 : : const void *addr, size_t size, void *arg __rte_unused)
253 : : {
254 : : struct sxe2_common_device *cdev = NULL;
255 : :
256 [ # # ]: 0 : if (rte_eal_process_type() != RTE_PROC_PRIMARY)
257 : 0 : goto l_end;
258 : :
259 : 0 : pthread_mutex_lock(&sxe2_common_devices_list_lock);
260 [ # # # ]: 0 : switch (type) {
261 : 0 : case RTE_MEM_EVENT_FREE:
262 [ # # ]: 0 : TAILQ_FOREACH(cdev, &sxe2_common_devices_list, next)
263 : 0 : (void)sxe2_dma_mem_map(cdev, addr, size, 0);
264 : : break;
265 : 0 : case RTE_MEM_EVENT_ALLOC:
266 [ # # ]: 0 : TAILQ_FOREACH(cdev, &sxe2_common_devices_list, next)
267 : 0 : (void)sxe2_dma_mem_map(cdev, addr, size, 1);
268 : : break;
269 : : default:
270 : : break;
271 : : }
272 : 0 : pthread_mutex_unlock(&sxe2_common_devices_list_lock);
273 : 0 : l_end:
274 : 0 : return;
275 : : }
276 : :
277 : 0 : static int32_t sxe2_memseg_walk_cb(const struct rte_memseg_list *msl,
278 : : const struct rte_memseg *ms, void *arg)
279 : : {
280 : : struct sxe2_common_device *cdev = arg;
281 : : int32_t ret = 0;
282 : :
283 [ # # # # ]: 0 : if (msl->external && !msl->heap)
284 : 0 : goto l_end;
285 : :
286 [ # # ]: 0 : if (ms->iova == RTE_BAD_IOVA)
287 : 0 : goto l_end;
288 : :
289 : 0 : ret = sxe2_drv_dev_dma_map(cdev, ms->addr_64, ms->iova, ms->len);
290 [ # # ]: 0 : if (ret != 0) {
291 : 0 : PMD_LOG_ERR(COM, "Fail to memseg dma map.");
292 : 0 : goto l_end;
293 : : }
294 : :
295 : 0 : l_end:
296 : 0 : return ret;
297 : : }
298 : :
299 : 0 : static int32_t sxe2_common_device_setup(struct sxe2_common_device *cdev)
300 : : {
301 : 0 : struct rte_pci_device *pci_dev = RTE_BUS_DEVICE(cdev->dev, *pci_dev);
302 : : int32_t ret = 0;
303 : :
304 [ # # ]: 0 : if (rte_eal_process_type() != RTE_PROC_PRIMARY)
305 : 0 : goto l_end;
306 : :
307 : 0 : ret = sxe2_drv_dev_open(cdev, pci_dev);
308 [ # # ]: 0 : if (ret != 0) {
309 : 0 : PMD_LOG_ERR(COM, "Open pmd chrdev failed, ret=%d", ret);
310 : 0 : goto l_end;
311 : : }
312 : :
313 : 0 : ret = sxe2_drv_dev_handshake(cdev);
314 [ # # ]: 0 : if (ret != 0) {
315 : 0 : PMD_LOG_ERR(COM, "Handshake failed, ret=%d", ret);
316 : 0 : goto l_close_dev;
317 : : }
318 : :
319 : 0 : rte_mcfg_mem_read_lock();
320 : 0 : ret = rte_memseg_walk_thread_unsafe(sxe2_memseg_walk_cb, cdev);
321 [ # # ]: 0 : if (ret) {
322 : 0 : PMD_LOG_ERR(COM, "Fail to walk memseg, ret=%d", ret);
323 : 0 : rte_mcfg_mem_read_unlock();
324 : 0 : goto l_close_dev;
325 : : }
326 : 0 : rte_mcfg_mem_read_unlock();
327 : :
328 : 0 : (void)rte_mem_event_callback_register("SXE2_MEM_EVENT_CB",
329 : : sxe2_common_mem_event_cb, NULL);
330 : :
331 : 0 : goto l_end;
332 : :
333 : 0 : l_close_dev:
334 : 0 : sxe2_drv_dev_close(cdev);
335 : 0 : l_end:
336 : 0 : return ret;
337 : : }
338 : :
339 : 0 : static void sxe2_common_device_cleanup(struct sxe2_common_device *cdev)
340 : : {
341 [ # # ]: 0 : if (rte_eal_process_type() != RTE_PROC_PRIMARY)
342 : : return;
343 : :
344 [ # # ]: 0 : if (TAILQ_EMPTY(&sxe2_common_devices_list))
345 : 0 : (void)rte_mem_event_callback_unregister("SXE2_MEM_ENVENT_CB", NULL);
346 : :
347 : 0 : sxe2_drv_dev_close(cdev);
348 : : }
349 : :
350 : 0 : static struct sxe2_common_device *sxe2_common_device_alloc(
351 : : struct rte_device *rte_dev, uint32_t class_type)
352 : : {
353 : : struct sxe2_common_device *cdev = NULL;
354 : :
355 : 0 : cdev = rte_zmalloc("sxe2_common_device", sizeof(*cdev), 0);
356 [ # # ]: 0 : if (cdev == NULL) {
357 : 0 : PMD_LOG_ERR(COM, "Fail to alloc sxe2 common device.");
358 : 0 : goto l_end;
359 : : }
360 : 0 : cdev->dev = rte_dev;
361 : 0 : cdev->class_type = class_type;
362 : 0 : cdev->config.cmd_fd = SXE2_CMD_FD_INVALID;
363 : 0 : cdev->config.kernel_reset = false;
364 : 0 : pthread_mutex_init(&cdev->config.lock, NULL);
365 : :
366 : 0 : pthread_mutex_lock(&sxe2_common_devices_list_lock);
367 : 0 : TAILQ_INSERT_TAIL(&sxe2_common_devices_list, cdev, next);
368 : 0 : pthread_mutex_unlock(&sxe2_common_devices_list_lock);
369 : :
370 : 0 : l_end:
371 : 0 : return cdev;
372 : : }
373 : :
374 : 0 : static void sxe2_common_device_free(struct sxe2_common_device *cdev)
375 : : {
376 : :
377 : 0 : pthread_mutex_lock(&sxe2_common_devices_list_lock);
378 [ # # ]: 0 : TAILQ_REMOVE(&sxe2_common_devices_list, cdev, next);
379 : 0 : pthread_mutex_unlock(&sxe2_common_devices_list_lock);
380 : :
381 : 0 : rte_free(cdev);
382 : 0 : }
383 : :
384 : : static bool sxe2_dev_is_pci(const struct rte_device *dev)
385 : : {
386 : 0 : return strcmp(dev->bus->name, "pci") == 0;
387 : : }
388 : :
389 : 0 : static bool sxe2_dev_pci_id_match(const struct sxe2_class_driver *cdrv,
390 : : const struct rte_device *dev)
391 : : {
392 : : const struct rte_pci_device *pci_dev;
393 : : const struct rte_pci_id *id_table;
394 : : bool ret = false;
395 : :
396 [ # # ]: 0 : if (!sxe2_dev_is_pci(dev)) {
397 : 0 : PMD_LOG_ERR(COM, "Device %s is not a PCI device", dev->name);
398 : 0 : goto l_end;
399 : : }
400 : :
401 : : pci_dev = RTE_BUS_DEVICE(dev, *pci_dev);
402 [ # # ]: 0 : for (id_table = cdrv->id_table; id_table->vendor_id != 0;
403 : 0 : id_table++) {
404 : :
405 [ # # # # ]: 0 : if (id_table->vendor_id != pci_dev->id.vendor_id &&
406 : : id_table->vendor_id != RTE_PCI_ANY_ID) {
407 : 0 : continue;
408 : : }
409 [ # # # # ]: 0 : if (id_table->device_id != pci_dev->id.device_id &&
410 : : id_table->device_id != RTE_PCI_ANY_ID) {
411 : 0 : continue;
412 : : }
413 : 0 : if (id_table->subsystem_vendor_id !=
414 [ # # # # ]: 0 : pci_dev->id.subsystem_vendor_id &&
415 : : id_table->subsystem_vendor_id != RTE_PCI_ANY_ID) {
416 : 0 : continue;
417 : : }
418 : 0 : if (id_table->subsystem_device_id !=
419 [ # # # # ]: 0 : pci_dev->id.subsystem_device_id &&
420 : : id_table->subsystem_device_id != RTE_PCI_ANY_ID) {
421 : :
422 : 0 : continue;
423 : : }
424 [ # # # # ]: 0 : if (id_table->class_id != pci_dev->id.class_id &&
425 : : id_table->class_id != RTE_CLASS_ANY_ID) {
426 : 0 : continue;
427 : : }
428 : : ret = true;
429 : : break;
430 : : }
431 : :
432 : 0 : l_end:
433 : 0 : return ret;
434 : : }
435 : :
436 : 0 : static int32_t sxe2_classes_driver_probe(struct sxe2_common_device *cdev,
437 : : struct sxe2_dev_kvargs_info *kv_info, uint32_t class_type)
438 : : {
439 : : struct sxe2_class_driver *cdrv = NULL;
440 : : int32_t ret = -1;
441 : :
442 : : cdrv = sxe2_class_driver_get(class_type);
443 [ # # ]: 0 : if (cdrv == NULL) {
444 : 0 : PMD_LOG_ERR(COM, "Fail to get class type[%u] driver.", class_type);
445 : 0 : goto l_end;
446 : : }
447 : :
448 [ # # ]: 0 : if (!sxe2_dev_pci_id_match(cdrv, cdev->dev)) {
449 : 0 : PMD_LOG_ERR(COM, "Fail to match pci id for driver:%s.", cdrv->name);
450 : 0 : goto l_end;
451 : : }
452 : :
453 : 0 : ret = cdrv->probe(cdev, kv_info);
454 [ # # ]: 0 : if (ret) {
455 : :
456 : 0 : PMD_LOG_DEBUG(COM, "Fail to probe driver:%s.", cdrv->name);
457 : 0 : goto l_end;
458 : : }
459 : :
460 : 0 : cdev->cdrv = cdrv;
461 : 0 : l_end:
462 : 0 : return ret;
463 : : }
464 : :
465 : : static int32_t sxe2_classes_driver_remove(struct sxe2_common_device *cdev)
466 : : {
467 : 0 : struct sxe2_class_driver *cdrv = cdev->cdrv;
468 : :
469 : 0 : return cdrv->remove(cdev);
470 : : }
471 : :
472 : 0 : static int32_t sxe2_kvargs_validate(struct sxe2_dev_kvargs_info *kv_info)
473 : : {
474 : : int32_t ret = 0;
475 : : uint32_t i;
476 : :
477 [ # # ]: 0 : if (rte_eal_process_type() != RTE_PROC_PRIMARY)
478 : 0 : goto l_end;
479 : :
480 [ # # ]: 0 : if (kv_info == NULL)
481 : 0 : goto l_end;
482 : :
483 [ # # ]: 0 : for (i = 0; i < kv_info->kvlist->count; i++) {
484 [ # # ]: 0 : if (kv_info->is_used[i] == 0) {
485 : 0 : PMD_LOG_ERR(COM, "Key \"%s\" is unsupported for the class driver.",
486 : : kv_info->kvlist->pairs[i].key);
487 : : ret = -EINVAL;
488 : 0 : goto l_end;
489 : : }
490 : : }
491 : :
492 : 0 : l_end:
493 : 0 : return ret;
494 : : }
495 : :
496 : 0 : static int32_t sxe2_common_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
497 : : struct rte_pci_device *pci_dev)
498 : : {
499 : 0 : struct rte_device *rte_dev = &pci_dev->device;
500 : : struct sxe2_common_device *cdev;
501 : : struct sxe2_dev_kvargs_info *kv_info_p = NULL;
502 : :
503 : 0 : uint32_t class_type = SXE2_CLASS_TYPE_ETH;
504 : : int32_t ret = -1;
505 : :
506 : 0 : PMD_LOG_INFO(COM, "Probe pci device: %s", pci_dev->name);
507 : :
508 : : cdev = sxe2_rtedev_to_cdev(rte_dev);
509 [ # # ]: 0 : if (cdev != NULL) {
510 : 0 : PMD_LOG_ERR(COM, "Device %s already probed.", rte_dev->name);
511 : : ret = -EBUSY;
512 : 0 : goto l_end;
513 : : }
514 : :
515 [ # # # # ]: 0 : if ((rte_dev->devargs != NULL) && (rte_dev->devargs->args != NULL)) {
516 : 0 : kv_info_p = calloc(1, sizeof(struct sxe2_dev_kvargs_info));
517 [ # # ]: 0 : if (!kv_info_p) {
518 : 0 : PMD_LOG_ERR(COM, "Failed to allocate memory for kv_info");
519 : 0 : goto l_end;
520 : : }
521 : :
522 : 0 : ret = sxe2_kvargs_preprocessing(kv_info_p, rte_dev->devargs);
523 [ # # ]: 0 : if (ret < 0) {
524 : 0 : PMD_LOG_ERR(COM, "Unsupported device args: %s",
525 : : rte_dev->devargs->args);
526 : 0 : goto l_free_kvargs;
527 : : }
528 : :
529 : 0 : ret = sxe2_kvargs_process(kv_info_p, SXE2_DEVARGS_KEY_CLASS,
530 : : sxe2_parse_class_type, &class_type);
531 [ # # ]: 0 : if (ret < 0) {
532 : 0 : PMD_LOG_ERR(COM, "Unsupported sxe2 driver class: %s",
533 : : rte_dev->devargs->args);
534 : 0 : goto l_free_args;
535 : : }
536 : :
537 : 0 : ret = sxe2_kvargs_process(kv_info_p, SXE2_DEVARGS_KEY_DRIVER,
538 : : sxe2_parse_driver, NULL);
539 [ # # ]: 0 : if (ret < 0) {
540 : 0 : PMD_LOG_ERR(COM, "Unsupported sxe2 driver name: %s",
541 : : rte_dev->devargs->args);
542 : 0 : goto l_free_args;
543 : : }
544 : :
545 : 0 : ret = sxe2_kvargs_process(kv_info_p, SXE2_DEVARGS_KEY_REPR,
546 : : sxe2_parse_representor, NULL);
547 [ # # ]: 0 : if (ret < 0) {
548 : 0 : PMD_LOG_ERR(COM, "Unsupported sxe2 driver representor: %s",
549 : : rte_dev->devargs->args);
550 : 0 : goto l_free_args;
551 : : }
552 : : }
553 : :
554 : 0 : cdev = sxe2_common_device_alloc(rte_dev, class_type);
555 [ # # ]: 0 : if (cdev == NULL) {
556 : : ret = -ENOMEM;
557 : 0 : goto l_free_args;
558 : : }
559 : :
560 : 0 : ret = sxe2_common_device_setup(cdev);
561 [ # # ]: 0 : if (ret != 0)
562 : 0 : goto l_err_setup;
563 : :
564 : 0 : ret = sxe2_classes_driver_probe(cdev, kv_info_p, class_type);
565 [ # # ]: 0 : if (ret != 0)
566 : 0 : goto l_err_probe;
567 : :
568 : 0 : ret = sxe2_kvargs_validate(kv_info_p);
569 [ # # ]: 0 : if (ret != 0) {
570 : 0 : PMD_LOG_ERR(COM, "Device args validate failed: %s",
571 : : rte_dev->devargs->args);
572 : 0 : goto l_err_valid;
573 : : }
574 : 0 : cdev->kvargs = kv_info_p;
575 : :
576 : 0 : goto l_end;
577 : : l_err_valid:
578 : : (void)sxe2_classes_driver_remove(cdev);
579 : 0 : l_err_probe:
580 : 0 : sxe2_common_device_cleanup(cdev);
581 : 0 : l_err_setup:
582 : 0 : sxe2_common_device_free(cdev);
583 [ # # ]: 0 : l_free_args:
584 : : sxe2_kvargs_free(kv_info_p);
585 : 0 : l_free_kvargs:
586 : 0 : free(kv_info_p);
587 : 0 : l_end:
588 : 0 : return ret;
589 : : }
590 : :
591 : 0 : static int32_t sxe2_common_pci_remove(struct rte_pci_device *pci_dev)
592 : : {
593 : : struct sxe2_common_device *cdev;
594 : : int32_t ret = -1;
595 : :
596 : 0 : PMD_LOG_INFO(COM, "Remove pci device: %s", pci_dev->name);
597 : 0 : cdev = sxe2_rtedev_to_cdev(&pci_dev->device);
598 [ # # ]: 0 : if (cdev == NULL) {
599 : : ret = -ENODEV;
600 : 0 : PMD_LOG_ERR(COM, "Fail to get device when remove.");
601 : 0 : goto l_end;
602 : : }
603 : :
604 : : ret = sxe2_classes_driver_remove(cdev);
605 [ # # ]: 0 : if (ret != 0) {
606 : 0 : PMD_LOG_ERR(COM, "Fail to remove device: %s", pci_dev->name);
607 : 0 : goto l_end;
608 : : }
609 : :
610 : 0 : sxe2_common_device_cleanup(cdev);
611 : :
612 [ # # ]: 0 : if (cdev->kvargs != NULL) {
613 : : sxe2_kvargs_free(cdev->kvargs);
614 : 0 : free(cdev->kvargs);
615 : 0 : cdev->kvargs = NULL;
616 : : }
617 : :
618 : 0 : sxe2_common_device_free(cdev);
619 : :
620 : 0 : l_end:
621 : 0 : return ret;
622 : : }
623 : :
624 : 0 : static int32_t sxe2_common_pci_dma_map(struct rte_pci_device *pci_dev,
625 : : void *addr, uint64_t iova, size_t len)
626 : : {
627 : : struct sxe2_common_device *cdev;
628 : : int32_t ret = -1;
629 : :
630 : 0 : cdev = sxe2_rtedev_to_cdev(&pci_dev->device);
631 [ # # ]: 0 : if (cdev == NULL) {
632 : : ret = -ENODEV;
633 : 0 : PMD_LOG_ERR(COM, "Fail to get device when dma map.");
634 : 0 : goto l_end;
635 : : }
636 : :
637 : 0 : ret = sxe2_drv_dev_dma_map(cdev, (uint64_t)(uintptr_t)addr, iova, len);
638 [ # # ]: 0 : if (ret) {
639 : 0 : PMD_LOG_ERR(COM, "Fail to map dma map, ret=%d", ret);
640 : 0 : goto l_end;
641 : : }
642 : :
643 : 0 : l_end:
644 : 0 : return ret;
645 : : }
646 : :
647 : 0 : static int32_t sxe2_common_pci_dma_unmap(struct rte_pci_device *pci_dev,
648 : : void *addr __rte_unused, uint64_t iova, size_t len __rte_unused)
649 : : {
650 : : struct sxe2_common_device *cdev;
651 : : int32_t ret = -1;
652 : :
653 : 0 : cdev = sxe2_rtedev_to_cdev(&pci_dev->device);
654 [ # # ]: 0 : if (cdev == NULL) {
655 : : ret = -ENODEV;
656 : 0 : PMD_LOG_ERR(COM, "Fail to get device when dma unmap.");
657 : 0 : goto l_end;
658 : : }
659 : :
660 : 0 : ret = sxe2_drv_dev_dma_unmap(cdev, iova);
661 [ # # ]: 0 : if (ret) {
662 : 0 : PMD_LOG_ERR(COM, "Fail to unmap dma map, ret=%d", ret);
663 : 0 : goto l_end;
664 : : }
665 : :
666 : 0 : l_end:
667 : 0 : return ret;
668 : : }
669 : :
670 : : static struct rte_pci_driver sxe2_common_pci_driver = {
671 : : .driver = {
672 : : .name = SXE2_COMMON_PCI_DRIVER_NAME,
673 : : },
674 : : .probe = sxe2_common_pci_probe,
675 : : .remove = sxe2_common_pci_remove,
676 : : .dma_map = sxe2_common_pci_dma_map,
677 : : .dma_unmap = sxe2_common_pci_dma_unmap,
678 : : };
679 : :
680 : : static uint32_t sxe2_common_pci_id_table_size_get(const struct rte_pci_id *id_table)
681 : : {
682 : : uint32_t table_size = 0;
683 : :
684 [ - + + + ]: 3030 : while (id_table->vendor_id != 0) {
685 : 2424 : table_size++;
686 : 2424 : id_table++;
687 : : }
688 : :
689 : : return table_size;
690 : : }
691 : :
692 : : static bool sxe2_common_pci_id_exists(const struct rte_pci_id *id,
693 : : const struct rte_pci_id *id_table, uint32_t next_idx)
694 : : {
695 : 2424 : int32_t current_size = next_idx - 1;
696 : : int32_t i;
697 : : bool exists = false;
698 : :
699 [ + + ]: 8787 : for (i = 0; i < current_size; i++) {
700 [ - + ]: 6363 : if ((id->device_id == id_table[i].device_id) &&
701 : : (id->vendor_id == id_table[i].vendor_id) &&
702 [ # # ]: 0 : (id->subsystem_vendor_id == id_table[i].subsystem_vendor_id) &&
703 : : (id->subsystem_device_id == id_table[i].subsystem_device_id)) {
704 : : exists = true;
705 : : break;
706 : : }
707 : : }
708 : :
709 : : return exists;
710 : : }
711 : :
712 : 303 : static void sxe2_common_pci_id_insert(struct rte_pci_id *id_table,
713 : : uint32_t *next_idx, const struct rte_pci_id *insert_table)
714 : : {
715 [ + + ]: 2727 : for (; insert_table->vendor_id != 0; insert_table++) {
716 [ + - ]: 4848 : if (!sxe2_common_pci_id_exists(insert_table, id_table, *next_idx)) {
717 : :
718 : 2424 : id_table[*next_idx] = *insert_table;
719 : 2424 : (*next_idx)++;
720 : : }
721 : : }
722 : 303 : }
723 : :
724 : 606 : static int32_t sxe2_common_pci_id_table_update(const struct rte_pci_id *id_table)
725 : : {
726 : : const struct rte_pci_id *id_iter;
727 : : struct rte_pci_id *updated_table;
728 : : struct rte_pci_id *old_table;
729 : : uint32_t num_ids = 0;
730 : 606 : uint32_t i = 0;
731 : : int32_t ret = 0;
732 : :
733 : 606 : old_table = sxe2_common_pci_id_table;
734 [ + + ]: 606 : if (old_table)
735 : : num_ids = sxe2_common_pci_id_table_size_get(old_table);
736 : :
737 : 606 : num_ids += sxe2_common_pci_id_table_size_get(id_table);
738 : :
739 : 606 : num_ids += 1;
740 : :
741 : 606 : updated_table = calloc(num_ids, sizeof(*updated_table));
742 [ - + ]: 606 : if (!updated_table) {
743 : : ret = -ENOMEM;
744 : 0 : PMD_LOG_ERR(COM, "Failed to allocate memory for PCI ID table");
745 : 0 : goto l_end;
746 : : }
747 : :
748 [ + + ]: 606 : if (old_table == NULL) {
749 : :
750 [ - + ]: 303 : for (id_iter = id_table; id_iter->vendor_id != 0;
751 : 0 : id_iter++, i++)
752 : 0 : updated_table[i] = *id_iter;
753 : : } else {
754 : :
755 [ - + ]: 303 : for (id_iter = old_table; id_iter->vendor_id != 0;
756 : 0 : id_iter++, i++)
757 : 0 : updated_table[i] = *id_iter;
758 : :
759 : 303 : sxe2_common_pci_id_insert(updated_table, &i, id_table);
760 : : }
761 : :
762 : 606 : updated_table[i].vendor_id = 0;
763 : 606 : sxe2_common_pci_driver.id_table = updated_table;
764 : 606 : sxe2_common_pci_id_table = updated_table;
765 : 606 : free(old_table);
766 : :
767 : 606 : l_end:
768 : 606 : return ret;
769 : : }
770 : :
771 : 303 : static void sxe2_common_driver_on_register_pci(struct sxe2_class_driver *driver)
772 : : {
773 [ + - ]: 303 : if (driver->id_table != NULL) {
774 [ + - ]: 303 : if (sxe2_common_pci_id_table_update(driver->id_table) != 0)
775 : : return;
776 : : }
777 : :
778 [ + - ]: 303 : if (driver->intr_lsc)
779 : 303 : sxe2_common_pci_driver.drv_flags |= RTE_PCI_DRV_INTR_LSC;
780 [ + - ]: 303 : if (driver->intr_rmv)
781 : 303 : sxe2_common_pci_driver.drv_flags |= RTE_PCI_DRV_INTR_RMV;
782 : : }
783 : :
784 : : RTE_EXPORT_INTERNAL_SYMBOL(sxe2_class_driver_register)
785 : : void
786 : 303 : sxe2_class_driver_register(struct sxe2_class_driver *driver)
787 : : {
788 : 303 : sxe2_common_driver_on_register_pci(driver);
789 : 303 : TAILQ_INSERT_TAIL(&sxe2_class_drivers_list, driver, next);
790 : 303 : }
791 : :
792 : 303 : static void sxe2_common_pci_init(void)
793 : : {
794 : 303 : const struct rte_pci_id empty_table[] = {
795 : : {
796 : : .vendor_id = 0
797 : : },
798 : : };
799 : : int32_t ret = -1;
800 : :
801 [ + - ]: 303 : if (sxe2_common_pci_id_table == NULL) {
802 : 303 : ret = sxe2_common_pci_id_table_update(empty_table);
803 [ - + ]: 303 : if (ret != 0)
804 : 0 : goto l_end;
805 : : }
806 : 303 : rte_pci_register(&sxe2_common_pci_driver);
807 : :
808 : 303 : l_end:
809 : 303 : return;
810 : : }
811 : :
812 : : static bool sxe2_common_inited;
813 : :
814 : : RTE_EXPORT_INTERNAL_SYMBOL(sxe2_common_init)
815 : : void
816 : 303 : sxe2_common_init(void)
817 : : {
818 [ - + ]: 303 : if (sxe2_common_inited)
819 : 0 : goto l_end;
820 : :
821 : 303 : pthread_mutex_init(&sxe2_common_devices_list_lock, NULL);
822 : 303 : sxe2_common_pci_init();
823 : 303 : sxe2_common_inited = true;
824 : :
825 : 303 : l_end:
826 : 303 : return;
827 : : }
828 : :
829 : 303 : RTE_FINI(sxe2_common_pci_finish)
830 : : {
831 [ + - ]: 303 : if (sxe2_common_pci_id_table != NULL) {
832 : 303 : rte_pci_unregister(&sxe2_common_pci_driver);
833 : 303 : free(sxe2_common_pci_id_table);
834 : : }
835 : 303 : }
836 : :
837 : : RTE_PMD_EXPORT_NAME(sxe2_common_pci);
838 : :
839 [ - + ]: 303 : RTE_LOG_REGISTER_SUFFIX(sxe2_common_log, com, NOTICE);
|