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_common_device_setup(struct sxe2_common_device *cdev)
173 : : {
174 : 0 : struct rte_pci_device *pci_dev = RTE_DEV_TO_PCI(cdev->dev);
175 : : int32_t ret = 0;
176 : :
177 [ # # ]: 0 : if (rte_eal_process_type() != RTE_PROC_PRIMARY)
178 : 0 : goto l_end;
179 : :
180 : 0 : ret = sxe2_drv_dev_open(cdev, pci_dev);
181 [ # # ]: 0 : if (ret != 0) {
182 : 0 : PMD_LOG_ERR(COM, "Open pmd chrdev failed, ret=%d", ret);
183 : 0 : goto l_end;
184 : : }
185 : :
186 : 0 : ret = sxe2_drv_dev_handshake(cdev);
187 [ # # ]: 0 : if (ret != 0) {
188 : 0 : PMD_LOG_ERR(COM, "Handshake failed, ret=%d", ret);
189 : 0 : goto l_close_dev;
190 : : }
191 : :
192 : 0 : goto l_end;
193 : :
194 : : l_close_dev:
195 : 0 : sxe2_drv_dev_close(cdev);
196 : 0 : l_end:
197 : 0 : return ret;
198 : : }
199 : :
200 : 0 : static void sxe2_common_device_cleanup(struct sxe2_common_device *cdev)
201 : : {
202 [ # # ]: 0 : if (rte_eal_process_type() != RTE_PROC_PRIMARY)
203 : : return;
204 : :
205 [ # # ]: 0 : if (TAILQ_EMPTY(&sxe2_common_devices_list))
206 : 0 : (void)rte_mem_event_callback_unregister("SXE2_MEM_ENVENT_CB", NULL);
207 : :
208 : 0 : sxe2_drv_dev_close(cdev);
209 : : }
210 : :
211 : 0 : static struct sxe2_common_device *sxe2_common_device_alloc(
212 : : struct rte_device *rte_dev, uint32_t class_type)
213 : : {
214 : : struct sxe2_common_device *cdev = NULL;
215 : :
216 : 0 : cdev = rte_zmalloc("sxe2_common_device", sizeof(*cdev), 0);
217 [ # # ]: 0 : if (cdev == NULL) {
218 : 0 : PMD_LOG_ERR(COM, "Fail to alloc sxe2 common device.");
219 : 0 : goto l_end;
220 : : }
221 : 0 : cdev->dev = rte_dev;
222 : 0 : cdev->class_type = class_type;
223 : 0 : cdev->config.kernel_reset = false;
224 : 0 : pthread_mutex_init(&cdev->config.lock, NULL);
225 : :
226 : 0 : pthread_mutex_lock(&sxe2_common_devices_list_lock);
227 : 0 : TAILQ_INSERT_TAIL(&sxe2_common_devices_list, cdev, next);
228 : 0 : pthread_mutex_unlock(&sxe2_common_devices_list_lock);
229 : :
230 : 0 : l_end:
231 : 0 : return cdev;
232 : : }
233 : :
234 : 0 : static void sxe2_common_device_free(struct sxe2_common_device *cdev)
235 : : {
236 : :
237 : 0 : pthread_mutex_lock(&sxe2_common_devices_list_lock);
238 [ # # ]: 0 : TAILQ_REMOVE(&sxe2_common_devices_list, cdev, next);
239 : 0 : pthread_mutex_unlock(&sxe2_common_devices_list_lock);
240 : :
241 : 0 : rte_free(cdev);
242 : 0 : }
243 : :
244 : : static bool sxe2_dev_is_pci(const struct rte_device *dev)
245 : : {
246 : 0 : return strcmp(dev->bus->name, "pci") == 0;
247 : : }
248 : :
249 : 0 : static bool sxe2_dev_pci_id_match(const struct sxe2_class_driver *cdrv,
250 : : const struct rte_device *dev)
251 : : {
252 : : const struct rte_pci_device *pci_dev;
253 : : const struct rte_pci_id *id_table;
254 : : bool ret = false;
255 : :
256 [ # # ]: 0 : if (!sxe2_dev_is_pci(dev)) {
257 : 0 : PMD_LOG_ERR(COM, "Device %s is not a PCI device", dev->name);
258 : 0 : goto l_end;
259 : : }
260 : :
261 : 0 : pci_dev = RTE_DEV_TO_PCI_CONST(dev);
262 [ # # ]: 0 : for (id_table = cdrv->id_table; id_table->vendor_id != 0;
263 : 0 : id_table++) {
264 : :
265 [ # # # # ]: 0 : if (id_table->vendor_id != pci_dev->id.vendor_id &&
266 : : id_table->vendor_id != RTE_PCI_ANY_ID) {
267 : 0 : continue;
268 : : }
269 [ # # # # ]: 0 : if (id_table->device_id != pci_dev->id.device_id &&
270 : : id_table->device_id != RTE_PCI_ANY_ID) {
271 : 0 : continue;
272 : : }
273 : 0 : if (id_table->subsystem_vendor_id !=
274 [ # # # # ]: 0 : pci_dev->id.subsystem_vendor_id &&
275 : : id_table->subsystem_vendor_id != RTE_PCI_ANY_ID) {
276 : 0 : continue;
277 : : }
278 : 0 : if (id_table->subsystem_device_id !=
279 [ # # # # ]: 0 : pci_dev->id.subsystem_device_id &&
280 : : id_table->subsystem_device_id != RTE_PCI_ANY_ID) {
281 : :
282 : 0 : continue;
283 : : }
284 [ # # # # ]: 0 : if (id_table->class_id != pci_dev->id.class_id &&
285 : : id_table->class_id != RTE_CLASS_ANY_ID) {
286 : 0 : continue;
287 : : }
288 : : ret = true;
289 : : break;
290 : : }
291 : :
292 : 0 : l_end:
293 : 0 : return ret;
294 : : }
295 : :
296 : 0 : static int32_t sxe2_classes_driver_probe(struct sxe2_common_device *cdev,
297 : : struct sxe2_dev_kvargs_info *kv_info, uint32_t class_type)
298 : : {
299 : : struct sxe2_class_driver *cdrv = NULL;
300 : : int32_t ret = -1;
301 : :
302 : : cdrv = sxe2_class_driver_get(class_type);
303 [ # # ]: 0 : if (cdrv == NULL) {
304 : 0 : PMD_LOG_ERR(COM, "Fail to get class type[%u] driver.", class_type);
305 : 0 : goto l_end;
306 : : }
307 : :
308 [ # # ]: 0 : if (!sxe2_dev_pci_id_match(cdrv, cdev->dev)) {
309 : 0 : PMD_LOG_ERR(COM, "Fail to match pci id for driver:%s.", cdrv->name);
310 : 0 : goto l_end;
311 : : }
312 : :
313 : 0 : ret = cdrv->probe(cdev, kv_info);
314 [ # # ]: 0 : if (ret) {
315 : :
316 : 0 : PMD_LOG_DEBUG(COM, "Fail to probe driver:%s.", cdrv->name);
317 : 0 : goto l_end;
318 : : }
319 : :
320 : 0 : cdev->cdrv = cdrv;
321 : 0 : l_end:
322 : 0 : return ret;
323 : : }
324 : :
325 : : static int32_t sxe2_classes_driver_remove(struct sxe2_common_device *cdev)
326 : : {
327 : 0 : struct sxe2_class_driver *cdrv = cdev->cdrv;
328 : :
329 : 0 : return cdrv->remove(cdev);
330 : : }
331 : :
332 : 0 : static int32_t sxe2_kvargs_validate(struct sxe2_dev_kvargs_info *kv_info)
333 : : {
334 : : int32_t ret = 0;
335 : : uint32_t i;
336 : :
337 [ # # ]: 0 : if (rte_eal_process_type() != RTE_PROC_PRIMARY)
338 : 0 : goto l_end;
339 : :
340 [ # # ]: 0 : if (kv_info == NULL)
341 : 0 : goto l_end;
342 : :
343 [ # # ]: 0 : for (i = 0; i < kv_info->kvlist->count; i++) {
344 [ # # ]: 0 : if (kv_info->is_used[i] == 0) {
345 : 0 : PMD_LOG_ERR(COM, "Key \"%s\" is unsupported for the class driver.",
346 : : kv_info->kvlist->pairs[i].key);
347 : : ret = -EINVAL;
348 : 0 : goto l_end;
349 : : }
350 : : }
351 : :
352 : 0 : l_end:
353 : 0 : return ret;
354 : : }
355 : :
356 : 0 : static int32_t sxe2_common_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
357 : : struct rte_pci_device *pci_dev)
358 : : {
359 : 0 : struct rte_device *rte_dev = &pci_dev->device;
360 : : struct sxe2_common_device *cdev;
361 : : struct sxe2_dev_kvargs_info *kv_info_p = NULL;
362 : :
363 : 0 : uint32_t class_type = SXE2_CLASS_TYPE_ETH;
364 : : int32_t ret = -1;
365 : :
366 : 0 : PMD_LOG_INFO(COM, "Probe pci device: %s", pci_dev->name);
367 : :
368 : : cdev = sxe2_rtedev_to_cdev(rte_dev);
369 [ # # ]: 0 : if (cdev != NULL) {
370 : 0 : PMD_LOG_ERR(COM, "Device %s already probed.", rte_dev->name);
371 : : ret = -EBUSY;
372 : 0 : goto l_end;
373 : : }
374 : :
375 [ # # # # ]: 0 : if ((rte_dev->devargs != NULL) && (rte_dev->devargs->args != NULL)) {
376 : 0 : kv_info_p = calloc(1, sizeof(struct sxe2_dev_kvargs_info));
377 [ # # ]: 0 : if (!kv_info_p) {
378 : 0 : PMD_LOG_ERR(COM, "Failed to allocate memory for kv_info");
379 : 0 : goto l_end;
380 : : }
381 : :
382 : 0 : ret = sxe2_kvargs_preprocessing(kv_info_p, rte_dev->devargs);
383 [ # # ]: 0 : if (ret < 0) {
384 : 0 : PMD_LOG_ERR(COM, "Unsupported device args: %s",
385 : : rte_dev->devargs->args);
386 : 0 : goto l_free_kvargs;
387 : : }
388 : :
389 : 0 : ret = sxe2_kvargs_process(kv_info_p, SXE2_DEVARGS_KEY_CLASS,
390 : : sxe2_parse_class_type, &class_type);
391 [ # # ]: 0 : if (ret < 0) {
392 : 0 : PMD_LOG_ERR(COM, "Unsupported sxe2 driver class: %s",
393 : : rte_dev->devargs->args);
394 : 0 : goto l_free_args;
395 : : }
396 : :
397 : : }
398 : :
399 : 0 : cdev = sxe2_common_device_alloc(rte_dev, class_type);
400 [ # # ]: 0 : if (cdev == NULL) {
401 : : ret = -ENOMEM;
402 : 0 : goto l_free_args;
403 : : }
404 : :
405 : 0 : ret = sxe2_common_device_setup(cdev);
406 [ # # ]: 0 : if (ret != 0)
407 : 0 : goto l_err_setup;
408 : :
409 : 0 : ret = sxe2_classes_driver_probe(cdev, kv_info_p, class_type);
410 [ # # ]: 0 : if (ret != 0)
411 : 0 : goto l_err_probe;
412 : :
413 : 0 : ret = sxe2_kvargs_validate(kv_info_p);
414 [ # # ]: 0 : if (ret != 0) {
415 : 0 : PMD_LOG_ERR(COM, "Device args validate failed: %s",
416 : : rte_dev->devargs->args);
417 : 0 : goto l_err_valid;
418 : : }
419 : 0 : cdev->kvargs = kv_info_p;
420 : :
421 : 0 : goto l_end;
422 : : l_err_valid:
423 : : (void)sxe2_classes_driver_remove(cdev);
424 : 0 : l_err_probe:
425 : 0 : sxe2_common_device_cleanup(cdev);
426 : 0 : l_err_setup:
427 : 0 : sxe2_common_device_free(cdev);
428 [ # # ]: 0 : l_free_args:
429 : : sxe2_kvargs_free(kv_info_p);
430 : 0 : l_free_kvargs:
431 : 0 : free(kv_info_p);
432 : 0 : l_end:
433 : 0 : return ret;
434 : : }
435 : :
436 : 0 : static int32_t sxe2_common_pci_remove(struct rte_pci_device *pci_dev)
437 : : {
438 : : struct sxe2_common_device *cdev;
439 : : int32_t ret = -1;
440 : :
441 : 0 : PMD_LOG_INFO(COM, "Remove pci device: %s", pci_dev->name);
442 : 0 : cdev = sxe2_rtedev_to_cdev(&pci_dev->device);
443 [ # # ]: 0 : if (cdev == NULL) {
444 : : ret = -ENODEV;
445 : 0 : PMD_LOG_ERR(COM, "Fail to get device when remove.");
446 : 0 : goto l_end;
447 : : }
448 : :
449 : : ret = sxe2_classes_driver_remove(cdev);
450 [ # # ]: 0 : if (ret != 0) {
451 : 0 : PMD_LOG_ERR(COM, "Fail to remove device: %s", pci_dev->name);
452 : 0 : goto l_end;
453 : : }
454 : :
455 : 0 : sxe2_common_device_cleanup(cdev);
456 : :
457 [ # # ]: 0 : if (cdev->kvargs != NULL) {
458 : : sxe2_kvargs_free(cdev->kvargs);
459 : 0 : free(cdev->kvargs);
460 : 0 : cdev->kvargs = NULL;
461 : : }
462 : :
463 : 0 : sxe2_common_device_free(cdev);
464 : :
465 : 0 : l_end:
466 : 0 : return ret;
467 : : }
468 : :
469 : 0 : static int32_t sxe2_common_pci_dma_map(struct rte_pci_device *pci_dev,
470 : : void *addr, uint64_t iova, size_t len)
471 : : {
472 : : struct sxe2_common_device *cdev;
473 : : int32_t ret = -1;
474 : :
475 : 0 : cdev = sxe2_rtedev_to_cdev(&pci_dev->device);
476 [ # # ]: 0 : if (cdev == NULL) {
477 : : ret = -ENODEV;
478 : 0 : PMD_LOG_ERR(COM, "Fail to get device when dma map.");
479 : 0 : goto l_end;
480 : : }
481 : :
482 : 0 : ret = sxe2_drv_dev_dma_map(cdev, (uint64_t)(uintptr_t)addr, iova, len);
483 [ # # ]: 0 : if (ret) {
484 : 0 : PMD_LOG_ERR(COM, "Fail to map dma map, ret=%d", ret);
485 : 0 : goto l_end;
486 : : }
487 : :
488 : 0 : l_end:
489 : 0 : return ret;
490 : : }
491 : :
492 : 0 : static int32_t sxe2_common_pci_dma_unmap(struct rte_pci_device *pci_dev,
493 : : void *addr __rte_unused, uint64_t iova, size_t len __rte_unused)
494 : : {
495 : : struct sxe2_common_device *cdev;
496 : : int32_t ret = -1;
497 : :
498 : 0 : cdev = sxe2_rtedev_to_cdev(&pci_dev->device);
499 [ # # ]: 0 : if (cdev == NULL) {
500 : : ret = -ENODEV;
501 : 0 : PMD_LOG_ERR(COM, "Fail to get device when dma unmap.");
502 : 0 : goto l_end;
503 : : }
504 : :
505 : 0 : ret = sxe2_drv_dev_dma_unmap(cdev, iova);
506 [ # # ]: 0 : if (ret) {
507 : 0 : PMD_LOG_ERR(COM, "Fail to unmap dma map, ret=%d", ret);
508 : 0 : goto l_end;
509 : : }
510 : :
511 : 0 : l_end:
512 : 0 : return ret;
513 : : }
514 : :
515 : : static struct rte_pci_driver sxe2_common_pci_driver = {
516 : : .driver = {
517 : : .name = SXE2_COMMON_PCI_DRIVER_NAME,
518 : : },
519 : : .probe = sxe2_common_pci_probe,
520 : : .remove = sxe2_common_pci_remove,
521 : : .dma_map = sxe2_common_pci_dma_map,
522 : : .dma_unmap = sxe2_common_pci_dma_unmap,
523 : : };
524 : :
525 : : static uint32_t sxe2_common_pci_id_table_size_get(const struct rte_pci_id *id_table)
526 : : {
527 : : uint32_t table_size = 0;
528 : :
529 [ - + + + ]: 2860 : while (id_table->vendor_id != 0) {
530 : 2288 : table_size++;
531 : 2288 : id_table++;
532 : : }
533 : :
534 : : return table_size;
535 : : }
536 : :
537 : : static bool sxe2_common_pci_id_exists(const struct rte_pci_id *id,
538 : : const struct rte_pci_id *id_table, uint32_t next_idx)
539 : : {
540 : 2288 : int32_t current_size = next_idx - 1;
541 : : int32_t i;
542 : : bool exists = false;
543 : :
544 [ + + ]: 8294 : for (i = 0; i < current_size; i++) {
545 [ - + ]: 6006 : if ((id->device_id == id_table[i].device_id) &&
546 : : (id->vendor_id == id_table[i].vendor_id) &&
547 [ # # ]: 0 : (id->subsystem_vendor_id == id_table[i].subsystem_vendor_id) &&
548 : : (id->subsystem_device_id == id_table[i].subsystem_device_id)) {
549 : : exists = true;
550 : : break;
551 : : }
552 : : }
553 : :
554 : : return exists;
555 : : }
556 : :
557 : 286 : static void sxe2_common_pci_id_insert(struct rte_pci_id *id_table,
558 : : uint32_t *next_idx, const struct rte_pci_id *insert_table)
559 : : {
560 [ + + ]: 2574 : for (; insert_table->vendor_id != 0; insert_table++) {
561 [ + - ]: 4576 : if (!sxe2_common_pci_id_exists(insert_table, id_table, *next_idx)) {
562 : :
563 : 2288 : id_table[*next_idx] = *insert_table;
564 : 2288 : (*next_idx)++;
565 : : }
566 : : }
567 : 286 : }
568 : :
569 : 572 : static int32_t sxe2_common_pci_id_table_update(const struct rte_pci_id *id_table)
570 : : {
571 : : const struct rte_pci_id *id_iter;
572 : : struct rte_pci_id *updated_table;
573 : : struct rte_pci_id *old_table;
574 : : uint32_t num_ids = 0;
575 : 572 : uint32_t i = 0;
576 : : int32_t ret = 0;
577 : :
578 : 572 : old_table = sxe2_common_pci_id_table;
579 [ + + ]: 572 : if (old_table)
580 : : num_ids = sxe2_common_pci_id_table_size_get(old_table);
581 : :
582 : 572 : num_ids += sxe2_common_pci_id_table_size_get(id_table);
583 : :
584 : 572 : num_ids += 1;
585 : :
586 : 572 : updated_table = calloc(num_ids, sizeof(*updated_table));
587 [ - + ]: 572 : if (!updated_table) {
588 : 0 : PMD_LOG_ERR(COM, "Failed to allocate memory for PCI ID table");
589 : 0 : goto l_end;
590 : : }
591 : :
592 [ + + ]: 572 : if (old_table == NULL) {
593 : :
594 [ - + ]: 286 : for (id_iter = id_table; id_iter->vendor_id != 0;
595 : 0 : id_iter++, i++)
596 : 0 : updated_table[i] = *id_iter;
597 : : } else {
598 : :
599 [ - + ]: 286 : for (id_iter = old_table; id_iter->vendor_id != 0;
600 : 0 : id_iter++, i++)
601 : 0 : updated_table[i] = *id_iter;
602 : :
603 : 286 : sxe2_common_pci_id_insert(updated_table, &i, id_table);
604 : : }
605 : :
606 : 572 : updated_table[i].vendor_id = 0;
607 : 572 : sxe2_common_pci_driver.id_table = updated_table;
608 : 572 : sxe2_common_pci_id_table = updated_table;
609 : 572 : free(old_table);
610 : :
611 : 572 : l_end:
612 : 572 : return ret;
613 : : }
614 : :
615 : 286 : static void sxe2_common_driver_on_register_pci(struct sxe2_class_driver *driver)
616 : : {
617 [ + - ]: 286 : if (driver->id_table != NULL) {
618 [ + - ]: 286 : if (sxe2_common_pci_id_table_update(driver->id_table) != 0)
619 : : return;
620 : : }
621 : :
622 [ + - ]: 286 : if (driver->intr_lsc)
623 : 286 : sxe2_common_pci_driver.drv_flags |= RTE_PCI_DRV_INTR_LSC;
624 [ + - ]: 286 : if (driver->intr_rmv)
625 : 286 : sxe2_common_pci_driver.drv_flags |= RTE_PCI_DRV_INTR_RMV;
626 : : }
627 : :
628 : : RTE_EXPORT_INTERNAL_SYMBOL(sxe2_class_driver_register)
629 : : void
630 : 286 : sxe2_class_driver_register(struct sxe2_class_driver *driver)
631 : : {
632 : 286 : sxe2_common_driver_on_register_pci(driver);
633 : 286 : TAILQ_INSERT_TAIL(&sxe2_class_drivers_list, driver, next);
634 : 286 : }
635 : :
636 : 286 : static void sxe2_common_pci_init(void)
637 : : {
638 : 286 : const struct rte_pci_id empty_table[] = {
639 : : {
640 : : .vendor_id = 0
641 : : },
642 : : };
643 : : int32_t ret = -1;
644 : :
645 [ + - ]: 286 : if (sxe2_common_pci_id_table == NULL) {
646 : 286 : ret = sxe2_common_pci_id_table_update(empty_table);
647 [ - + ]: 286 : if (ret != 0)
648 : 0 : goto l_end;
649 : : }
650 : 286 : rte_pci_register(&sxe2_common_pci_driver);
651 : :
652 : 286 : l_end:
653 : 286 : return;
654 : : }
655 : :
656 : : static bool sxe2_common_inited;
657 : :
658 : : RTE_EXPORT_INTERNAL_SYMBOL(sxe2_common_init)
659 : : void
660 : 286 : sxe2_common_init(void)
661 : : {
662 [ - + ]: 286 : if (sxe2_common_inited)
663 : 0 : goto l_end;
664 : :
665 : 286 : pthread_mutex_init(&sxe2_common_devices_list_lock, NULL);
666 : 286 : sxe2_common_pci_init();
667 : 286 : sxe2_common_inited = true;
668 : :
669 : 286 : l_end:
670 : 286 : return;
671 : : }
672 : :
673 : 286 : RTE_FINI(sxe2_common_pci_finish)
674 : : {
675 [ + - ]: 286 : if (sxe2_common_pci_id_table != NULL) {
676 : 286 : rte_pci_unregister(&sxe2_common_pci_driver);
677 : 286 : free(sxe2_common_pci_id_table);
678 : : }
679 : 286 : }
680 : :
681 : : RTE_PMD_EXPORT_NAME(sxe2_common_pci);
682 : :
683 [ - + ]: 286 : RTE_LOG_REGISTER_SUFFIX(sxe2_common_log, com, NOTICE);
|