xref: /dpdk/drivers/bus/pci/pci_params.c (revision 849f773b7645216954022a47e466043a23125af9)
146521ca2SGaetan Rivet /* SPDX-License-Identifier: BSD-3-Clause
246521ca2SGaetan Rivet  * Copyright 2018 Gaëtan Rivet
346521ca2SGaetan Rivet  */
446521ca2SGaetan Rivet 
5f1f6ebc0SWilliam Tu #include <sys/queue.h>
6f1f6ebc0SWilliam Tu 
7a04322f6SDavid Marchand #include <bus_driver.h>
84410c1b0SGaetan Rivet #include <rte_bus_pci.h>
91acb7f54SDavid Marchand #include <dev_driver.h>
1046521ca2SGaetan Rivet #include <rte_errno.h>
1146521ca2SGaetan Rivet #include <rte_kvargs.h>
12d2a66ad7SXueming Li #include <rte_devargs.h>
1346521ca2SGaetan Rivet #include <rte_pci.h>
14d2a66ad7SXueming Li #include <rte_debug.h>
1546521ca2SGaetan Rivet 
1646521ca2SGaetan Rivet #include "private.h"
1746521ca2SGaetan Rivet 
1846521ca2SGaetan Rivet enum pci_params {
193f7a40c6SThomas Monjalon 	RTE_PCI_PARAM_ADDR,
203f7a40c6SThomas Monjalon 	RTE_PCI_PARAM_MAX,
2146521ca2SGaetan Rivet };
2246521ca2SGaetan Rivet 
2346521ca2SGaetan Rivet static const char * const pci_params_keys[] = {
243f7a40c6SThomas Monjalon 	[RTE_PCI_PARAM_ADDR] = "addr",
253f7a40c6SThomas Monjalon 	[RTE_PCI_PARAM_MAX] = NULL,
2646521ca2SGaetan Rivet };
2746521ca2SGaetan Rivet 
2846521ca2SGaetan Rivet static int
pci_addr_kv_cmp(const char * key __rte_unused,const char * value,void * _addr2)294410c1b0SGaetan Rivet pci_addr_kv_cmp(const char *key __rte_unused,
304410c1b0SGaetan Rivet 		const char *value,
314410c1b0SGaetan Rivet 		void *_addr2)
324410c1b0SGaetan Rivet {
334410c1b0SGaetan Rivet 	struct rte_pci_addr _addr1;
344410c1b0SGaetan Rivet 	struct rte_pci_addr *addr1 = &_addr1;
354410c1b0SGaetan Rivet 	struct rte_pci_addr *addr2 = _addr2;
364410c1b0SGaetan Rivet 
374410c1b0SGaetan Rivet 	if (rte_pci_addr_parse(value, addr1))
384410c1b0SGaetan Rivet 		return -1;
394410c1b0SGaetan Rivet 	return -abs(rte_pci_addr_cmp(addr1, addr2));
404410c1b0SGaetan Rivet }
414410c1b0SGaetan Rivet 
424410c1b0SGaetan Rivet static int
pci_dev_match(const struct rte_device * dev,const void * _kvlist)4346521ca2SGaetan Rivet pci_dev_match(const struct rte_device *dev,
4446521ca2SGaetan Rivet 	      const void *_kvlist)
4546521ca2SGaetan Rivet {
4646521ca2SGaetan Rivet 	const struct rte_kvargs *kvlist = _kvlist;
474410c1b0SGaetan Rivet 	const struct rte_pci_device *pdev;
4846521ca2SGaetan Rivet 
494410c1b0SGaetan Rivet 	if (kvlist == NULL)
504410c1b0SGaetan Rivet 		/* Empty string matches everything. */
514410c1b0SGaetan Rivet 		return 0;
524410c1b0SGaetan Rivet 	pdev = RTE_DEV_TO_PCI_CONST(dev);
534410c1b0SGaetan Rivet 	/* if any field does not match. */
543f7a40c6SThomas Monjalon 	if (rte_kvargs_process(kvlist, pci_params_keys[RTE_PCI_PARAM_ADDR],
554410c1b0SGaetan Rivet 			       &pci_addr_kv_cmp,
564410c1b0SGaetan Rivet 			       (void *)(intptr_t)&pdev->addr))
574410c1b0SGaetan Rivet 		return 1;
5846521ca2SGaetan Rivet 	return 0;
5946521ca2SGaetan Rivet }
6046521ca2SGaetan Rivet 
6146521ca2SGaetan Rivet void *
rte_pci_dev_iterate(const void * start,const char * str,const struct rte_dev_iterator * it __rte_unused)6246521ca2SGaetan Rivet rte_pci_dev_iterate(const void *start,
6346521ca2SGaetan Rivet 		    const char *str,
6446521ca2SGaetan Rivet 		    const struct rte_dev_iterator *it __rte_unused)
6546521ca2SGaetan Rivet {
6646521ca2SGaetan Rivet 	rte_bus_find_device_t find_device;
6746521ca2SGaetan Rivet 	struct rte_kvargs *kvargs = NULL;
6846521ca2SGaetan Rivet 	struct rte_device *dev;
6946521ca2SGaetan Rivet 
7046521ca2SGaetan Rivet 	if (str != NULL) {
7146521ca2SGaetan Rivet 		kvargs = rte_kvargs_parse(str, pci_params_keys);
7246521ca2SGaetan Rivet 		if (kvargs == NULL) {
73*849f773bSDavid Marchand 			PCI_LOG(ERR, "cannot parse argument list");
7446521ca2SGaetan Rivet 			rte_errno = EINVAL;
7546521ca2SGaetan Rivet 			return NULL;
7646521ca2SGaetan Rivet 		}
7746521ca2SGaetan Rivet 	}
7846521ca2SGaetan Rivet 	find_device = rte_pci_bus.bus.find_device;
7946521ca2SGaetan Rivet 	dev = find_device(start, pci_dev_match, kvargs);
8046521ca2SGaetan Rivet 	rte_kvargs_free(kvargs);
8146521ca2SGaetan Rivet 	return dev;
8246521ca2SGaetan Rivet }
83d2a66ad7SXueming Li 
84d2a66ad7SXueming Li int
rte_pci_devargs_parse(struct rte_devargs * da)85d2a66ad7SXueming Li rte_pci_devargs_parse(struct rte_devargs *da)
86d2a66ad7SXueming Li {
87d2a66ad7SXueming Li 	struct rte_kvargs *kvargs;
88d2a66ad7SXueming Li 	const char *addr_str;
89d2a66ad7SXueming Li 	struct rte_pci_addr addr;
905adef306SXueming Li 	int ret = 0;
91d2a66ad7SXueming Li 
925adef306SXueming Li 	if (da == NULL || da->bus_str == NULL)
93d2a66ad7SXueming Li 		return 0;
94d2a66ad7SXueming Li 
95d2a66ad7SXueming Li 	kvargs = rte_kvargs_parse(da->bus_str, NULL);
96d2a66ad7SXueming Li 	if (kvargs == NULL) {
97*849f773bSDavid Marchand 		PCI_LOG(ERR, "cannot parse argument list: %s", da->bus_str);
98d2a66ad7SXueming Li 		ret = -ENODEV;
99d2a66ad7SXueming Li 		goto out;
100d2a66ad7SXueming Li 	}
101d2a66ad7SXueming Li 
102d2a66ad7SXueming Li 	addr_str = rte_kvargs_get(kvargs, pci_params_keys[RTE_PCI_PARAM_ADDR]);
103d2a66ad7SXueming Li 	if (addr_str == NULL) {
104*849f773bSDavid Marchand 		PCI_LOG(DEBUG, "No PCI address specified using '%s=<id>' in: %s",
105d2a66ad7SXueming Li 			pci_params_keys[RTE_PCI_PARAM_ADDR], da->bus_str);
106d2a66ad7SXueming Li 		goto out;
107d2a66ad7SXueming Li 	}
108d2a66ad7SXueming Li 
109d2a66ad7SXueming Li 	ret = rte_pci_addr_parse(addr_str, &addr);
110d2a66ad7SXueming Li 	if (ret != 0) {
111*849f773bSDavid Marchand 		PCI_LOG(ERR, "PCI address invalid: %s", da->bus_str);
112d2a66ad7SXueming Li 		ret = -EINVAL;
113d2a66ad7SXueming Li 		goto out;
114d2a66ad7SXueming Li 	}
115d2a66ad7SXueming Li 
116d2a66ad7SXueming Li 	rte_pci_device_name(&addr, da->name, sizeof(da->name));
117d2a66ad7SXueming Li 
118d2a66ad7SXueming Li out:
119d2a66ad7SXueming Li 	rte_kvargs_free(kvargs);
120d2a66ad7SXueming Li 	if (ret != 0)
121d2a66ad7SXueming Li 		rte_errno = -ret;
122d2a66ad7SXueming Li 	return ret;
123d2a66ad7SXueming Li }
124