xref: /dpdk/drivers/common/mlx5/mlx5_common_pci.c (revision ad435d3204736e8110cd3ecdf5363ae20f68e66f)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright 2020 Mellanox Technologies Ltd
3  */
4 
5 #include <stdlib.h>
6 
7 #include <rte_malloc.h>
8 #include <rte_devargs.h>
9 #include <rte_errno.h>
10 #include <rte_class.h>
11 
12 #include "mlx5_common_log.h"
13 #include "mlx5_common_pci.h"
14 #include "mlx5_common_private.h"
15 
16 static struct rte_pci_driver mlx5_common_pci_driver;
17 
18 /********** Legacy PCI bus driver, to be removed ********/
19 
20 struct mlx5_pci_device {
21 	struct rte_pci_device *pci_dev;
22 	TAILQ_ENTRY(mlx5_pci_device) next;
23 	uint32_t classes_loaded;
24 };
25 
26 /* Head of list of drivers. */
27 static TAILQ_HEAD(mlx5_pci_bus_drv_head, mlx5_pci_driver) drv_list =
28 				TAILQ_HEAD_INITIALIZER(drv_list);
29 
30 /* Head of mlx5 pci devices. */
31 static TAILQ_HEAD(mlx5_pci_devices_head, mlx5_pci_device) devices_list =
32 				TAILQ_HEAD_INITIALIZER(devices_list);
33 
34 static const struct {
35 	const char *name;
36 	unsigned int driver_class;
37 } mlx5_classes[] = {
38 	{ .name = "vdpa", .driver_class = MLX5_CLASS_VDPA },
39 	{ .name = "eth", .driver_class = MLX5_CLASS_ETH },
40 	/* Keep name "net" for backward compatibility. */
41 	{ .name = "net", .driver_class = MLX5_CLASS_ETH },
42 	{ .name = "regex", .driver_class = MLX5_CLASS_REGEX },
43 	{ .name = "compress", .driver_class = MLX5_CLASS_COMPRESS },
44 	{ .name = "crypto", .driver_class = MLX5_CLASS_CRYPTO },
45 };
46 
47 static const unsigned int mlx5_class_combinations[] = {
48 	MLX5_CLASS_ETH,
49 	MLX5_CLASS_VDPA,
50 	MLX5_CLASS_REGEX,
51 	MLX5_CLASS_COMPRESS,
52 	MLX5_CLASS_CRYPTO,
53 	MLX5_CLASS_ETH | MLX5_CLASS_REGEX,
54 	MLX5_CLASS_VDPA | MLX5_CLASS_REGEX,
55 	MLX5_CLASS_ETH | MLX5_CLASS_COMPRESS,
56 	MLX5_CLASS_VDPA | MLX5_CLASS_COMPRESS,
57 	MLX5_CLASS_REGEX | MLX5_CLASS_COMPRESS,
58 	MLX5_CLASS_ETH | MLX5_CLASS_CRYPTO,
59 	MLX5_CLASS_ETH | MLX5_CLASS_REGEX | MLX5_CLASS_COMPRESS,
60 	MLX5_CLASS_VDPA | MLX5_CLASS_CRYPTO,
61 	MLX5_CLASS_REGEX | MLX5_CLASS_CRYPTO,
62 	MLX5_CLASS_COMPRESS | MLX5_CLASS_CRYPTO,
63 	MLX5_CLASS_VDPA | MLX5_CLASS_REGEX | MLX5_CLASS_COMPRESS,
64 	MLX5_CLASS_ETH | MLX5_CLASS_REGEX | MLX5_CLASS_CRYPTO,
65 	MLX5_CLASS_VDPA | MLX5_CLASS_REGEX | MLX5_CLASS_CRYPTO,
66 	MLX5_CLASS_ETH | MLX5_CLASS_COMPRESS | MLX5_CLASS_CRYPTO,
67 	MLX5_CLASS_VDPA | MLX5_CLASS_COMPRESS | MLX5_CLASS_CRYPTO,
68 	MLX5_CLASS_ETH | MLX5_CLASS_REGEX | MLX5_CLASS_COMPRESS |
69 	MLX5_CLASS_CRYPTO,
70 	MLX5_CLASS_VDPA | MLX5_CLASS_REGEX | MLX5_CLASS_COMPRESS |
71 	MLX5_CLASS_CRYPTO,
72 	/* New class combination should be added here. */
73 };
74 
75 static int
76 class_name_to_value(const char *class_name)
77 {
78 	unsigned int i;
79 
80 	for (i = 0; i < RTE_DIM(mlx5_classes); i++) {
81 		if (strcmp(class_name, mlx5_classes[i].name) == 0)
82 			return mlx5_classes[i].driver_class;
83 	}
84 	return -EINVAL;
85 }
86 
87 static struct mlx5_pci_driver *
88 driver_get(uint32_t class)
89 {
90 	struct mlx5_pci_driver *driver;
91 
92 	TAILQ_FOREACH(driver, &drv_list, next) {
93 		if (driver->driver_class == class)
94 			return driver;
95 	}
96 	return NULL;
97 }
98 
99 static int
100 bus_cmdline_options_handler(__rte_unused const char *key,
101 			    const char *class_names, void *opaque)
102 {
103 	int *ret = opaque;
104 	char *nstr_org;
105 	int class_val;
106 	char *found;
107 	char *nstr;
108 	char *refstr = NULL;
109 
110 	*ret = 0;
111 	nstr = strdup(class_names);
112 	if (!nstr) {
113 		*ret = -ENOMEM;
114 		return *ret;
115 	}
116 	nstr_org = nstr;
117 	found = strtok_r(nstr, ":", &refstr);
118 	if (!found)
119 		goto err;
120 	do {
121 		/* Extract each individual class name. Multiple
122 		 * class key,value is supplied as class=net:vdpa:foo:bar.
123 		 */
124 		class_val = class_name_to_value(found);
125 		/* Check if its a valid class. */
126 		if (class_val < 0) {
127 			*ret = -EINVAL;
128 			goto err;
129 		}
130 		*ret |= class_val;
131 		found = strtok_r(NULL, ":", &refstr);
132 	} while (found);
133 err:
134 	free(nstr_org);
135 	if (*ret < 0)
136 		DRV_LOG(ERR, "Invalid mlx5 class options %s."
137 			" Maybe typo in device class argument setting?",
138 			class_names);
139 	return *ret;
140 }
141 
142 static int
143 parse_class_options(const struct rte_devargs *devargs)
144 {
145 	const char *key = RTE_DEVARGS_KEY_CLASS;
146 	struct rte_kvargs *kvlist;
147 	int ret = 0;
148 
149 	if (devargs == NULL)
150 		return 0;
151 	kvlist = rte_kvargs_parse(devargs->args, NULL);
152 	if (kvlist == NULL)
153 		return 0;
154 	if (rte_kvargs_count(kvlist, key))
155 		rte_kvargs_process(kvlist, key, bus_cmdline_options_handler,
156 				   &ret);
157 	rte_kvargs_free(kvlist);
158 	return ret;
159 }
160 
161 static bool
162 mlx5_bus_match(const struct mlx5_pci_driver *drv,
163 	       const struct rte_pci_device *pci_dev)
164 {
165 	const struct rte_pci_id *id_table;
166 
167 	for (id_table = drv->pci_driver.id_table; id_table->vendor_id != 0;
168 	     id_table++) {
169 		/* Check if device's ids match the class driver's ids. */
170 		if (id_table->vendor_id != pci_dev->id.vendor_id &&
171 		    id_table->vendor_id != RTE_PCI_ANY_ID)
172 			continue;
173 		if (id_table->device_id != pci_dev->id.device_id &&
174 		    id_table->device_id != RTE_PCI_ANY_ID)
175 			continue;
176 		if (id_table->subsystem_vendor_id !=
177 		    pci_dev->id.subsystem_vendor_id &&
178 		    id_table->subsystem_vendor_id != RTE_PCI_ANY_ID)
179 			continue;
180 		if (id_table->subsystem_device_id !=
181 		    pci_dev->id.subsystem_device_id &&
182 		    id_table->subsystem_device_id != RTE_PCI_ANY_ID)
183 			continue;
184 		if (id_table->class_id != pci_dev->id.class_id &&
185 		    id_table->class_id != RTE_CLASS_ANY_ID)
186 			continue;
187 		return true;
188 	}
189 	return false;
190 }
191 
192 static int
193 is_valid_class_combination(uint32_t user_classes)
194 {
195 	unsigned int i;
196 
197 	/* Verify if user specified valid supported combination. */
198 	for (i = 0; i < RTE_DIM(mlx5_class_combinations); i++) {
199 		if (mlx5_class_combinations[i] == user_classes)
200 			return 0;
201 	}
202 	/* Not found any valid class combination. */
203 	return -EINVAL;
204 }
205 
206 static struct mlx5_pci_device *
207 pci_to_mlx5_device(const struct rte_pci_device *pci_dev)
208 {
209 	struct mlx5_pci_device *dev;
210 
211 	TAILQ_FOREACH(dev, &devices_list, next) {
212 		if (dev->pci_dev == pci_dev)
213 			return dev;
214 	}
215 	return NULL;
216 }
217 
218 static bool
219 device_class_enabled(const struct mlx5_pci_device *device, uint32_t class)
220 {
221 	return (device->classes_loaded & class) ? true : false;
222 }
223 
224 static void
225 dev_release(struct mlx5_pci_device *dev)
226 {
227 	TAILQ_REMOVE(&devices_list, dev, next);
228 	rte_free(dev);
229 }
230 
231 static int
232 drivers_remove(struct mlx5_pci_device *dev, uint32_t enabled_classes)
233 {
234 	struct mlx5_pci_driver *driver;
235 	int local_ret = -ENODEV;
236 	unsigned int i = 0;
237 	int ret = 0;
238 
239 	enabled_classes &= dev->classes_loaded;
240 	while (enabled_classes) {
241 		driver = driver_get(RTE_BIT64(i));
242 		if (driver) {
243 			local_ret = driver->pci_driver.remove(dev->pci_dev);
244 			if (!local_ret)
245 				dev->classes_loaded &= ~RTE_BIT64(i);
246 			else if (ret == 0)
247 				ret = local_ret;
248 		}
249 		enabled_classes &= ~RTE_BIT64(i);
250 		i++;
251 	}
252 	if (local_ret)
253 		ret = local_ret;
254 	return ret;
255 }
256 
257 static int
258 drivers_probe(struct mlx5_pci_device *dev, struct rte_pci_driver *pci_drv,
259 	      struct rte_pci_device *pci_dev, uint32_t user_classes)
260 {
261 	struct mlx5_pci_driver *driver;
262 	uint32_t enabled_classes = 0;
263 	bool already_loaded;
264 	int ret;
265 
266 	TAILQ_FOREACH(driver, &drv_list, next) {
267 		if ((driver->driver_class & user_classes) == 0)
268 			continue;
269 		if (!mlx5_bus_match(driver, pci_dev))
270 			continue;
271 		already_loaded = dev->classes_loaded & driver->driver_class;
272 		if (already_loaded &&
273 		    !(driver->pci_driver.drv_flags & RTE_PCI_DRV_PROBE_AGAIN)) {
274 			DRV_LOG(ERR, "Device %s is already probed",
275 				pci_dev->device.name);
276 			ret = -EEXIST;
277 			goto probe_err;
278 		}
279 		ret = driver->pci_driver.probe(pci_drv, pci_dev);
280 		if (ret < 0) {
281 			DRV_LOG(ERR, "Failed to load driver %s",
282 				driver->pci_driver.driver.name);
283 			goto probe_err;
284 		}
285 		enabled_classes |= driver->driver_class;
286 	}
287 	dev->classes_loaded |= enabled_classes;
288 	return 0;
289 probe_err:
290 	/* Only unload drivers which are enabled which were enabled
291 	 * in this probe instance.
292 	 */
293 	drivers_remove(dev, enabled_classes);
294 	return ret;
295 }
296 
297 /**
298  * DPDK callback to register to probe multiple drivers for a PCI device.
299  *
300  * @param[in] pci_drv
301  *   PCI driver structure.
302  * @param[in] dev
303  *   PCI device information.
304  *
305  * @return
306  *   0 on success, a negative errno value otherwise and rte_errno is set.
307  */
308 static int
309 mlx5_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
310 	       struct rte_pci_device *pci_dev)
311 {
312 	struct mlx5_pci_device *dev;
313 	uint32_t user_classes = 0;
314 	bool new_device = false;
315 	int ret;
316 
317 	ret = parse_class_options(pci_dev->device.devargs);
318 	if (ret < 0)
319 		return ret;
320 	user_classes = ret;
321 	if (user_classes) {
322 		/* Validate combination here. */
323 		ret = is_valid_class_combination(user_classes);
324 		if (ret) {
325 			DRV_LOG(ERR, "Unsupported mlx5 classes supplied.");
326 			return ret;
327 		}
328 	} else {
329 		/* Default to net class. */
330 		user_classes = MLX5_CLASS_ETH;
331 	}
332 	dev = pci_to_mlx5_device(pci_dev);
333 	if (!dev) {
334 		dev = rte_zmalloc("mlx5_pci_device", sizeof(*dev), 0);
335 		if (!dev)
336 			return -ENOMEM;
337 		dev->pci_dev = pci_dev;
338 		TAILQ_INSERT_HEAD(&devices_list, dev, next);
339 		new_device = true;
340 	}
341 	ret = drivers_probe(dev, pci_drv, pci_dev, user_classes);
342 	if (ret)
343 		goto class_err;
344 	return 0;
345 class_err:
346 	if (new_device)
347 		dev_release(dev);
348 	return ret;
349 }
350 
351 /**
352  * DPDK callback to remove one or more drivers for a PCI device.
353  *
354  * This function removes all drivers probed for a given PCI device.
355  *
356  * @param[in] pci_dev
357  *   Pointer to the PCI device.
358  *
359  * @return
360  *   0 on success, the function cannot fail.
361  */
362 static int
363 mlx5_pci_remove(struct rte_pci_device *pci_dev)
364 {
365 	struct mlx5_pci_device *dev;
366 	int ret;
367 
368 	dev = pci_to_mlx5_device(pci_dev);
369 	if (!dev)
370 		return -ENODEV;
371 	/* Matching device found, cleanup and unload drivers. */
372 	ret = drivers_remove(dev, dev->classes_loaded);
373 	if (!ret)
374 		dev_release(dev);
375 	return ret;
376 }
377 
378 static int
379 mlx5_pci_dma_map(struct rte_pci_device *pci_dev, void *addr,
380 		 uint64_t iova, size_t len)
381 {
382 	struct mlx5_pci_driver *driver = NULL;
383 	struct mlx5_pci_driver *temp;
384 	struct mlx5_pci_device *dev;
385 	int ret = -EINVAL;
386 
387 	dev = pci_to_mlx5_device(pci_dev);
388 	if (!dev)
389 		return -ENODEV;
390 	TAILQ_FOREACH(driver, &drv_list, next) {
391 		if (device_class_enabled(dev, driver->driver_class) &&
392 		    driver->pci_driver.dma_map) {
393 			ret = driver->pci_driver.dma_map(pci_dev, addr,
394 							 iova, len);
395 			if (ret)
396 				goto map_err;
397 		}
398 	}
399 	return ret;
400 map_err:
401 	TAILQ_FOREACH(temp, &drv_list, next) {
402 		if (temp == driver)
403 			break;
404 		if (device_class_enabled(dev, temp->driver_class) &&
405 		    temp->pci_driver.dma_map && temp->pci_driver.dma_unmap)
406 			temp->pci_driver.dma_unmap(pci_dev, addr, iova, len);
407 	}
408 	return ret;
409 }
410 
411 static int
412 mlx5_pci_dma_unmap(struct rte_pci_device *pci_dev, void *addr,
413 		   uint64_t iova, size_t len)
414 {
415 	struct mlx5_pci_driver *driver;
416 	struct mlx5_pci_device *dev;
417 	int local_ret = -EINVAL;
418 	int ret;
419 
420 	dev = pci_to_mlx5_device(pci_dev);
421 	if (!dev)
422 		return -ENODEV;
423 	ret = 0;
424 	/* There is no unmap error recovery in current implementation. */
425 	TAILQ_FOREACH_REVERSE(driver, &drv_list, mlx5_pci_bus_drv_head, next) {
426 		if (device_class_enabled(dev, driver->driver_class) &&
427 		    driver->pci_driver.dma_unmap) {
428 			local_ret = driver->pci_driver.dma_unmap(pci_dev, addr,
429 								 iova, len);
430 			if (local_ret && (ret == 0))
431 				ret = local_ret;
432 		}
433 	}
434 	if (local_ret)
435 		ret = local_ret;
436 	return ret;
437 }
438 
439 /* PCI ID table is build dynamically based on registered mlx5 drivers. */
440 static struct rte_pci_id *mlx5_pci_id_table;
441 
442 static struct rte_pci_driver mlx5_pci_driver = {
443 	.driver = {
444 		.name = MLX5_PCI_DRIVER_NAME,
445 	},
446 	.probe = mlx5_pci_probe,
447 	.remove = mlx5_pci_remove,
448 	.dma_map = mlx5_pci_dma_map,
449 	.dma_unmap = mlx5_pci_dma_unmap,
450 };
451 
452 static int
453 pci_id_table_size_get(const struct rte_pci_id *id_table)
454 {
455 	int table_size = 0;
456 
457 	for (; id_table->vendor_id != 0; id_table++)
458 		table_size++;
459 	return table_size;
460 }
461 
462 static bool
463 pci_id_exists(const struct rte_pci_id *id, const struct rte_pci_id *table,
464 	      int next_idx)
465 {
466 	int current_size = next_idx - 1;
467 	int i;
468 
469 	for (i = 0; i < current_size; i++) {
470 		if (id->device_id == table[i].device_id &&
471 		    id->vendor_id == table[i].vendor_id &&
472 		    id->subsystem_vendor_id == table[i].subsystem_vendor_id &&
473 		    id->subsystem_device_id == table[i].subsystem_device_id)
474 			return true;
475 	}
476 	return false;
477 }
478 
479 static void
480 pci_id_insert(struct rte_pci_id *new_table, int *next_idx,
481 	      const struct rte_pci_id *id_table)
482 {
483 	/* Traverse the id_table, check if entry exists in new_table;
484 	 * Add non duplicate entries to new table.
485 	 */
486 	for (; id_table->vendor_id != 0; id_table++) {
487 		if (!pci_id_exists(id_table, new_table, *next_idx)) {
488 			/* New entry; add to the table. */
489 			new_table[*next_idx] = *id_table;
490 			(*next_idx)++;
491 		}
492 	}
493 }
494 
495 static int
496 pci_ids_table_update(const struct rte_pci_id *driver_id_table)
497 {
498 	const struct rte_pci_id *id_iter;
499 	struct rte_pci_id *updated_table;
500 	struct rte_pci_id *old_table;
501 	int num_ids = 0;
502 	int i = 0;
503 
504 	old_table = mlx5_pci_id_table;
505 	if (old_table)
506 		num_ids = pci_id_table_size_get(old_table);
507 	num_ids += pci_id_table_size_get(driver_id_table);
508 	/* Increase size by one for the termination entry of vendor_id = 0. */
509 	num_ids += 1;
510 	updated_table = calloc(num_ids, sizeof(*updated_table));
511 	if (!updated_table)
512 		return -ENOMEM;
513 	if (old_table == NULL) {
514 		/* Copy the first driver's ID table. */
515 		for (id_iter = driver_id_table; id_iter->vendor_id != 0;
516 		     id_iter++, i++)
517 			updated_table[i] = *id_iter;
518 	} else {
519 		/* First copy existing table entries. */
520 		for (id_iter = old_table; id_iter->vendor_id != 0;
521 		     id_iter++, i++)
522 			updated_table[i] = *id_iter;
523 		/* New id to be added at the end of current ID table. */
524 		pci_id_insert(updated_table, &i, driver_id_table);
525 	}
526 	/* Terminate table with empty entry. */
527 	updated_table[i].vendor_id = 0;
528 	mlx5_pci_driver.id_table = updated_table;
529 	mlx5_common_pci_driver.id_table = updated_table;
530 	mlx5_pci_id_table = updated_table;
531 	if (old_table)
532 		free(old_table);
533 	return 0;
534 }
535 
536 void
537 mlx5_pci_driver_register(struct mlx5_pci_driver *driver)
538 {
539 	int ret;
540 
541 	ret = pci_ids_table_update(driver->pci_driver.id_table);
542 	if (ret)
543 		return;
544 	mlx5_pci_driver.drv_flags |= driver->pci_driver.drv_flags;
545 	TAILQ_INSERT_TAIL(&drv_list, driver, next);
546 }
547 
548 /********** New common PCI bus driver ********/
549 
550 bool
551 mlx5_dev_is_pci(const struct rte_device *dev)
552 {
553 	return strcmp(dev->bus->name, "pci") == 0;
554 }
555 
556 bool
557 mlx5_dev_pci_match(const struct mlx5_class_driver *drv,
558 		   const struct rte_device *dev)
559 {
560 	const struct rte_pci_device *pci_dev;
561 	const struct rte_pci_id *id_table;
562 
563 	if (!mlx5_dev_is_pci(dev))
564 		return false;
565 	pci_dev = RTE_DEV_TO_PCI_CONST(dev);
566 	for (id_table = drv->id_table; id_table->vendor_id != 0;
567 	     id_table++) {
568 		/* Check if device's ids match the class driver's ids. */
569 		if (id_table->vendor_id != pci_dev->id.vendor_id &&
570 		    id_table->vendor_id != RTE_PCI_ANY_ID)
571 			continue;
572 		if (id_table->device_id != pci_dev->id.device_id &&
573 		    id_table->device_id != RTE_PCI_ANY_ID)
574 			continue;
575 		if (id_table->subsystem_vendor_id !=
576 		    pci_dev->id.subsystem_vendor_id &&
577 		    id_table->subsystem_vendor_id != RTE_PCI_ANY_ID)
578 			continue;
579 		if (id_table->subsystem_device_id !=
580 		    pci_dev->id.subsystem_device_id &&
581 		    id_table->subsystem_device_id != RTE_PCI_ANY_ID)
582 			continue;
583 		if (id_table->class_id != pci_dev->id.class_id &&
584 		    id_table->class_id != RTE_CLASS_ANY_ID)
585 			continue;
586 		return true;
587 	}
588 	return false;
589 }
590 
591 static int
592 mlx5_common_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
593 		      struct rte_pci_device *pci_dev)
594 {
595 	return mlx5_common_dev_probe(&pci_dev->device);
596 }
597 
598 static int
599 mlx5_common_pci_remove(struct rte_pci_device *pci_dev)
600 {
601 	return mlx5_common_dev_remove(&pci_dev->device);
602 }
603 
604 static int
605 mlx5_common_pci_dma_map(struct rte_pci_device *pci_dev, void *addr,
606 			uint64_t iova, size_t len)
607 {
608 	return mlx5_common_dev_dma_map(&pci_dev->device, addr, iova, len);
609 }
610 
611 static int
612 mlx5_common_pci_dma_unmap(struct rte_pci_device *pci_dev, void *addr,
613 			  uint64_t iova, size_t len)
614 {
615 	return mlx5_common_dev_dma_unmap(&pci_dev->device, addr, iova, len);
616 }
617 
618 void
619 mlx5_common_driver_on_register_pci(struct mlx5_class_driver *driver)
620 {
621 	if (driver->id_table != NULL) {
622 		if (pci_ids_table_update(driver->id_table) != 0)
623 			return;
624 	}
625 	if (driver->probe_again)
626 		mlx5_common_pci_driver.drv_flags |= RTE_PCI_DRV_PROBE_AGAIN;
627 	if (driver->intr_lsc)
628 		mlx5_common_pci_driver.drv_flags |= RTE_PCI_DRV_INTR_LSC;
629 	if (driver->intr_rmv)
630 		mlx5_common_pci_driver.drv_flags |= RTE_PCI_DRV_INTR_RMV;
631 }
632 
633 static struct rte_pci_driver mlx5_common_pci_driver = {
634 	.driver = {
635 		   .name = MLX5_PCI_DRIVER_NAME,
636 	},
637 	.probe = mlx5_common_pci_probe,
638 	.remove = mlx5_common_pci_remove,
639 	.dma_map = mlx5_common_pci_dma_map,
640 	.dma_unmap = mlx5_common_pci_dma_unmap,
641 };
642 
643 void mlx5_common_pci_init(void)
644 {
645 	const struct rte_pci_id empty_table[] = {
646 		{
647 			.vendor_id = 0
648 		},
649 	};
650 
651 	/* All mlx5 PMDs constructor runs at same priority. So any of the PMD
652 	 * including this one can register the PCI table first. If any other
653 	 * PMD(s) have registered the PCI ID table, No need to register an empty
654 	 * default one.
655 	 */
656 	if (mlx5_pci_id_table == NULL && pci_ids_table_update(empty_table))
657 		return;
658 	rte_pci_register(&mlx5_common_pci_driver);
659 }
660 
661 RTE_FINI(mlx5_common_pci_finish)
662 {
663 	if (mlx5_pci_id_table != NULL) {
664 		/* Constructor doesn't register with PCI bus if it failed
665 		 * to build the table.
666 		 */
667 		rte_pci_unregister(&mlx5_common_pci_driver);
668 		free(mlx5_pci_id_table);
669 	}
670 }
671 
672 RTE_PMD_EXPORT_NAME(mlx5_common_pci, __COUNTER__);
673