xref: /dpdk/drivers/dma/idxd/idxd_bus.c (revision 83cfa2cbf3f3fb78e2f2dd228109adcb38e18a5c)
1e888bb12SKevin Laatz /* SPDX-License-Identifier: BSD-3-Clause
2e888bb12SKevin Laatz  * Copyright(c) 2021 Intel Corporation
3e888bb12SKevin Laatz  */
4e888bb12SKevin Laatz 
5e888bb12SKevin Laatz #include <dirent.h>
6e888bb12SKevin Laatz #include <fcntl.h>
7e888bb12SKevin Laatz #include <unistd.h>
8e888bb12SKevin Laatz #include <sys/mman.h>
9e888bb12SKevin Laatz #include <libgen.h>
10e888bb12SKevin Laatz 
11a04322f6SDavid Marchand #include <bus_driver.h>
121acb7f54SDavid Marchand #include <dev_driver.h>
13cecf5ed9SRadu Nicolau #include <rte_devargs.h>
14e888bb12SKevin Laatz #include <rte_eal.h>
157dcd73e3SOlivier Matz #include <rte_memory.h>
16e888bb12SKevin Laatz #include <rte_log.h>
17e888bb12SKevin Laatz #include <rte_dmadev_pmd.h>
18e888bb12SKevin Laatz #include <rte_string_fns.h>
19e888bb12SKevin Laatz 
20e888bb12SKevin Laatz #include "idxd_internal.h"
21e888bb12SKevin Laatz 
22e888bb12SKevin Laatz /* default value for DSA paths, but allow override in environment for testing */
23e888bb12SKevin Laatz #define DSA_DEV_PATH "/dev/dsa"
24e888bb12SKevin Laatz #define DSA_SYSFS_PATH "/sys/bus/dsa/devices"
25e888bb12SKevin Laatz 
26e888bb12SKevin Laatz static unsigned int devcount;
27e888bb12SKevin Laatz 
28e888bb12SKevin Laatz /** unique identifier for a DSA device/WQ instance */
29e888bb12SKevin Laatz struct dsa_wq_addr {
30e888bb12SKevin Laatz 	uint16_t device_id;
31e888bb12SKevin Laatz 	uint16_t wq_id;
32e888bb12SKevin Laatz };
33e888bb12SKevin Laatz 
34e888bb12SKevin Laatz /** a DSA device instance */
35e888bb12SKevin Laatz struct rte_dsa_device {
36e888bb12SKevin Laatz 	struct rte_device device;           /**< Inherit core device */
37e888bb12SKevin Laatz 	TAILQ_ENTRY(rte_dsa_device) next;   /**< next dev in list */
38e888bb12SKevin Laatz 
39e888bb12SKevin Laatz 	char wq_name[32];                   /**< the workqueue name/number e.g. wq0.1 */
40e888bb12SKevin Laatz 	struct dsa_wq_addr addr;            /**< Identifies the specific WQ */
41e888bb12SKevin Laatz };
42e888bb12SKevin Laatz 
43e888bb12SKevin Laatz /* forward prototypes */
44e888bb12SKevin Laatz struct dsa_bus;
45e888bb12SKevin Laatz static int dsa_scan(void);
46e888bb12SKevin Laatz static int dsa_probe(void);
47e888bb12SKevin Laatz static struct rte_device *dsa_find_device(const struct rte_device *start,
48e888bb12SKevin Laatz 		rte_dev_cmp_t cmp,  const void *data);
49e888bb12SKevin Laatz static enum rte_iova_mode dsa_get_iommu_class(void);
50e888bb12SKevin Laatz static int dsa_addr_parse(const char *name, void *addr);
51e888bb12SKevin Laatz 
52e888bb12SKevin Laatz /** List of devices */
53e888bb12SKevin Laatz TAILQ_HEAD(dsa_device_list, rte_dsa_device);
54e888bb12SKevin Laatz 
55e888bb12SKevin Laatz /**
56e888bb12SKevin Laatz  * Structure describing the DSA bus
57e888bb12SKevin Laatz  */
58e888bb12SKevin Laatz struct dsa_bus {
59e888bb12SKevin Laatz 	struct rte_bus bus;               /**< Inherit the generic class */
60e888bb12SKevin Laatz 	struct rte_driver driver;         /**< Driver struct for devices to point to */
61e888bb12SKevin Laatz 	struct dsa_device_list device_list;  /**< List of PCI devices */
62e888bb12SKevin Laatz };
63e888bb12SKevin Laatz 
64e888bb12SKevin Laatz struct dsa_bus dsa_bus = {
65e888bb12SKevin Laatz 	.bus = {
66e888bb12SKevin Laatz 		.scan = dsa_scan,
67e888bb12SKevin Laatz 		.probe = dsa_probe,
68e888bb12SKevin Laatz 		.find_device = dsa_find_device,
69e888bb12SKevin Laatz 		.get_iommu_class = dsa_get_iommu_class,
70e888bb12SKevin Laatz 		.parse = dsa_addr_parse,
71e888bb12SKevin Laatz 	},
72e888bb12SKevin Laatz 	.driver = {
73e888bb12SKevin Laatz 		.name = "dmadev_idxd"
74e888bb12SKevin Laatz 	},
75e888bb12SKevin Laatz 	.device_list = TAILQ_HEAD_INITIALIZER(dsa_bus.device_list),
76e888bb12SKevin Laatz };
77e888bb12SKevin Laatz 
78e888bb12SKevin Laatz static inline const char *
dsa_get_dev_path(void)79e888bb12SKevin Laatz dsa_get_dev_path(void)
80e888bb12SKevin Laatz {
81e888bb12SKevin Laatz 	const char *path = getenv("DSA_DEV_PATH");
82e888bb12SKevin Laatz 	return path ? path : DSA_DEV_PATH;
83e888bb12SKevin Laatz }
84e888bb12SKevin Laatz 
85e888bb12SKevin Laatz static inline const char *
dsa_get_sysfs_path(void)86e888bb12SKevin Laatz dsa_get_sysfs_path(void)
87e888bb12SKevin Laatz {
88e888bb12SKevin Laatz 	const char *path = getenv("DSA_SYSFS_PATH");
89e888bb12SKevin Laatz 	return path ? path : DSA_SYSFS_PATH;
90e888bb12SKevin Laatz }
91e888bb12SKevin Laatz 
9255dc0f60SKevin Laatz static int
idxd_dev_close(struct rte_dma_dev * dev)9355dc0f60SKevin Laatz idxd_dev_close(struct rte_dma_dev *dev)
9455dc0f60SKevin Laatz {
9555dc0f60SKevin Laatz 	struct idxd_dmadev *idxd = dev->data->dev_private;
9655dc0f60SKevin Laatz 	munmap(idxd->portal, 0x1000);
9755dc0f60SKevin Laatz 	return 0;
9855dc0f60SKevin Laatz }
9955dc0f60SKevin Laatz 
10055dc0f60SKevin Laatz static const struct rte_dma_dev_ops idxd_bus_ops = {
10155dc0f60SKevin Laatz 		.dev_close = idxd_dev_close,
10282147042SKevin Laatz 		.dev_dump = idxd_dump,
1032f7d42c6SKevin Laatz 		.dev_configure = idxd_configure,
1042f7d42c6SKevin Laatz 		.vchan_setup = idxd_vchan_setup,
1052f7d42c6SKevin Laatz 		.dev_info_get = idxd_info_get,
106280c3ca0SKevin Laatz 		.stats_get = idxd_stats_get,
107280c3ca0SKevin Laatz 		.stats_reset = idxd_stats_reset,
1085a23df34SKevin Laatz 		.vchan_status = idxd_vchan_status,
10955dc0f60SKevin Laatz };
11055dc0f60SKevin Laatz 
111e888bb12SKevin Laatz static void *
idxd_bus_mmap_wq(struct rte_dsa_device * dev)112e888bb12SKevin Laatz idxd_bus_mmap_wq(struct rte_dsa_device *dev)
113e888bb12SKevin Laatz {
114e888bb12SKevin Laatz 	void *addr;
115e888bb12SKevin Laatz 	char path[PATH_MAX];
116e888bb12SKevin Laatz 	int fd;
117e888bb12SKevin Laatz 
118e888bb12SKevin Laatz 	snprintf(path, sizeof(path), "%s/%s", dsa_get_dev_path(), dev->wq_name);
119e888bb12SKevin Laatz 	fd = open(path, O_RDWR);
120e888bb12SKevin Laatz 	if (fd < 0) {
121e888bb12SKevin Laatz 		IDXD_PMD_ERR("Failed to open device path: %s", path);
122e888bb12SKevin Laatz 		return NULL;
123e888bb12SKevin Laatz 	}
124e888bb12SKevin Laatz 
125e888bb12SKevin Laatz 	addr = mmap(NULL, 0x1000, PROT_WRITE, MAP_SHARED, fd, 0);
126e888bb12SKevin Laatz 	close(fd);
127e888bb12SKevin Laatz 	if (addr == MAP_FAILED) {
128e888bb12SKevin Laatz 		IDXD_PMD_ERR("Failed to mmap device %s", path);
129e888bb12SKevin Laatz 		return NULL;
130e888bb12SKevin Laatz 	}
131e888bb12SKevin Laatz 
132e888bb12SKevin Laatz 	return addr;
133e888bb12SKevin Laatz }
134e888bb12SKevin Laatz 
135e888bb12SKevin Laatz static int
read_wq_string(struct rte_dsa_device * dev,const char * filename,char * value,size_t valuelen)136e888bb12SKevin Laatz read_wq_string(struct rte_dsa_device *dev, const char *filename,
137e888bb12SKevin Laatz 		char *value, size_t valuelen)
138e888bb12SKevin Laatz {
139e888bb12SKevin Laatz 	char sysfs_node[PATH_MAX];
140e888bb12SKevin Laatz 	int len;
141e888bb12SKevin Laatz 	int fd;
142e888bb12SKevin Laatz 
143e888bb12SKevin Laatz 	snprintf(sysfs_node, sizeof(sysfs_node), "%s/%s/%s",
144e888bb12SKevin Laatz 			dsa_get_sysfs_path(), dev->wq_name, filename);
145e888bb12SKevin Laatz 	fd = open(sysfs_node, O_RDONLY);
146e888bb12SKevin Laatz 	if (fd < 0) {
147e888bb12SKevin Laatz 		IDXD_PMD_ERR("%s(): opening file '%s' failed: %s",
148e888bb12SKevin Laatz 				__func__, sysfs_node, strerror(errno));
149e888bb12SKevin Laatz 		return -1;
150e888bb12SKevin Laatz 	}
151e888bb12SKevin Laatz 
152e888bb12SKevin Laatz 	len = read(fd, value, valuelen - 1);
153e888bb12SKevin Laatz 	close(fd);
154e888bb12SKevin Laatz 	if (len < 0) {
155e888bb12SKevin Laatz 		IDXD_PMD_ERR("%s(): error reading file '%s': %s",
156e888bb12SKevin Laatz 				__func__, sysfs_node, strerror(errno));
157e888bb12SKevin Laatz 		return -1;
158e888bb12SKevin Laatz 	}
159e888bb12SKevin Laatz 	value[len] = '\0';
160e888bb12SKevin Laatz 	return 0;
161e888bb12SKevin Laatz }
162e888bb12SKevin Laatz 
163e888bb12SKevin Laatz static int
read_wq_int(struct rte_dsa_device * dev,const char * filename,int * value)164e888bb12SKevin Laatz read_wq_int(struct rte_dsa_device *dev, const char *filename,
165e888bb12SKevin Laatz 		int *value)
166e888bb12SKevin Laatz {
167e888bb12SKevin Laatz 	char sysfs_node[PATH_MAX];
168e888bb12SKevin Laatz 	FILE *f;
169e888bb12SKevin Laatz 	int ret = 0;
170e888bb12SKevin Laatz 
171e888bb12SKevin Laatz 	snprintf(sysfs_node, sizeof(sysfs_node), "%s/%s/%s",
172e888bb12SKevin Laatz 			dsa_get_sysfs_path(), dev->wq_name, filename);
173e888bb12SKevin Laatz 	f = fopen(sysfs_node, "r");
174e888bb12SKevin Laatz 	if (f == NULL) {
175e888bb12SKevin Laatz 		IDXD_PMD_ERR("%s(): opening file '%s' failed: %s",
176e888bb12SKevin Laatz 				__func__, sysfs_node, strerror(errno));
177e888bb12SKevin Laatz 		return -1;
178e888bb12SKevin Laatz 	}
179e888bb12SKevin Laatz 
180e888bb12SKevin Laatz 	if (fscanf(f, "%d", value) != 1) {
181e888bb12SKevin Laatz 		IDXD_PMD_ERR("%s(): error reading file '%s': %s",
182e888bb12SKevin Laatz 				__func__, sysfs_node, strerror(errno));
183e888bb12SKevin Laatz 		ret = -1;
184e888bb12SKevin Laatz 	}
185e888bb12SKevin Laatz 
186e888bb12SKevin Laatz 	fclose(f);
187e888bb12SKevin Laatz 	return ret;
188e888bb12SKevin Laatz }
189e888bb12SKevin Laatz 
190e888bb12SKevin Laatz static int
read_device_int(struct rte_dsa_device * dev,const char * filename,int * value)191e888bb12SKevin Laatz read_device_int(struct rte_dsa_device *dev, const char *filename,
192e888bb12SKevin Laatz 		int *value)
193e888bb12SKevin Laatz {
194e888bb12SKevin Laatz 	char sysfs_node[PATH_MAX];
195e888bb12SKevin Laatz 	FILE *f;
196e888bb12SKevin Laatz 	int ret = 0;
197e888bb12SKevin Laatz 
198e888bb12SKevin Laatz 	snprintf(sysfs_node, sizeof(sysfs_node), "%s/dsa%d/%s",
199e888bb12SKevin Laatz 			dsa_get_sysfs_path(), dev->addr.device_id, filename);
200e888bb12SKevin Laatz 	f = fopen(sysfs_node, "r");
201e888bb12SKevin Laatz 	if (f == NULL) {
202e888bb12SKevin Laatz 		IDXD_PMD_ERR("%s(): opening file '%s' failed: %s",
203e888bb12SKevin Laatz 				__func__, sysfs_node, strerror(errno));
204e888bb12SKevin Laatz 		return -1;
205e888bb12SKevin Laatz 	}
206e888bb12SKevin Laatz 
207e888bb12SKevin Laatz 	if (fscanf(f, "%d", value) != 1) {
208e888bb12SKevin Laatz 		IDXD_PMD_ERR("%s(): error reading file '%s': %s",
209e888bb12SKevin Laatz 				__func__, sysfs_node, strerror(errno));
210e888bb12SKevin Laatz 		ret = -1;
211e888bb12SKevin Laatz 	}
212e888bb12SKevin Laatz 
213e888bb12SKevin Laatz 	fclose(f);
214e888bb12SKevin Laatz 	return ret;
215e888bb12SKevin Laatz }
216e888bb12SKevin Laatz 
217e888bb12SKevin Laatz static int
idxd_probe_dsa(struct rte_dsa_device * dev)218e888bb12SKevin Laatz idxd_probe_dsa(struct rte_dsa_device *dev)
219e888bb12SKevin Laatz {
220e888bb12SKevin Laatz 	struct idxd_dmadev idxd = {0};
221e888bb12SKevin Laatz 	int ret = 0;
222e888bb12SKevin Laatz 
223e888bb12SKevin Laatz 	IDXD_PMD_INFO("Probing device %s on numa node %d",
224e888bb12SKevin Laatz 			dev->wq_name, dev->device.numa_node);
225e888bb12SKevin Laatz 	if (read_wq_int(dev, "size", &ret) < 0)
226e888bb12SKevin Laatz 		return -1;
227e888bb12SKevin Laatz 	idxd.max_batches = ret;
228e888bb12SKevin Laatz 	if (read_wq_int(dev, "max_batch_size", &ret) < 0)
229e888bb12SKevin Laatz 		return -1;
230e888bb12SKevin Laatz 	idxd.max_batch_size = ret;
231e888bb12SKevin Laatz 	idxd.qid = dev->addr.wq_id;
23255dc0f60SKevin Laatz 	idxd.u.bus.dsa_id = dev->addr.device_id;
233e888bb12SKevin Laatz 	idxd.sva_support = 1;
234e888bb12SKevin Laatz 
235e888bb12SKevin Laatz 	idxd.portal = idxd_bus_mmap_wq(dev);
236e888bb12SKevin Laatz 	if (idxd.portal == NULL) {
237e888bb12SKevin Laatz 		IDXD_PMD_ERR("WQ mmap failed");
238e888bb12SKevin Laatz 		return -ENOENT;
239e888bb12SKevin Laatz 	}
240e888bb12SKevin Laatz 
24155dc0f60SKevin Laatz 	ret = idxd_dmadev_create(dev->wq_name, &dev->device, &idxd, &idxd_bus_ops);
24255dc0f60SKevin Laatz 	if (ret) {
24355dc0f60SKevin Laatz 		IDXD_PMD_ERR("Failed to create dmadev %s", dev->wq_name);
24455dc0f60SKevin Laatz 		return ret;
24555dc0f60SKevin Laatz 	}
24655dc0f60SKevin Laatz 
247e888bb12SKevin Laatz 	return 0;
248e888bb12SKevin Laatz }
249e888bb12SKevin Laatz 
search_devargs(const char * name)250cecf5ed9SRadu Nicolau static int search_devargs(const char *name)
251cecf5ed9SRadu Nicolau {
252cecf5ed9SRadu Nicolau 	struct rte_devargs *devargs;
253cecf5ed9SRadu Nicolau 	RTE_EAL_DEVARGS_FOREACH(dsa_bus.bus.name, devargs) {
254cecf5ed9SRadu Nicolau 		if (strcmp(devargs->name, name) == 0)
255cecf5ed9SRadu Nicolau 			return 1;
256cecf5ed9SRadu Nicolau 	}
257cecf5ed9SRadu Nicolau 	return 0;
258cecf5ed9SRadu Nicolau }
259cecf5ed9SRadu Nicolau 
260e888bb12SKevin Laatz static int
is_for_this_process_use(struct rte_dsa_device * dev,const char * name)261cecf5ed9SRadu Nicolau is_for_this_process_use(struct rte_dsa_device *dev, const char *name)
262e888bb12SKevin Laatz {
263e888bb12SKevin Laatz 	char *runtime_dir = strdup(rte_eal_get_runtime_dir());
264e888bb12SKevin Laatz 	int retval = 0;
265*83cfa2cbSChengwen Feng 	int prefixlen;
266*83cfa2cbSChengwen Feng 	char *prefix;
267*83cfa2cbSChengwen Feng 
268*83cfa2cbSChengwen Feng 	if (runtime_dir == NULL)
269*83cfa2cbSChengwen Feng 		return retval;
270*83cfa2cbSChengwen Feng 
271*83cfa2cbSChengwen Feng 	prefix = basename(runtime_dir);
272*83cfa2cbSChengwen Feng 	prefixlen = strlen(prefix);
273e888bb12SKevin Laatz 
274e888bb12SKevin Laatz 	if (strncmp(name, "dpdk_", 5) == 0)
275e888bb12SKevin Laatz 		retval = 1;
276e888bb12SKevin Laatz 	if (strncmp(name, prefix, prefixlen) == 0 && name[prefixlen] == '_')
277e888bb12SKevin Laatz 		retval = 1;
278e888bb12SKevin Laatz 
279cecf5ed9SRadu Nicolau 	if (retval && dsa_bus.bus.conf.scan_mode != RTE_BUS_SCAN_UNDEFINED) {
280cecf5ed9SRadu Nicolau 		if (dsa_bus.bus.conf.scan_mode == RTE_BUS_SCAN_ALLOWLIST)
281cecf5ed9SRadu Nicolau 			retval = search_devargs(dev->device.name);
282cecf5ed9SRadu Nicolau 		else
283cecf5ed9SRadu Nicolau 			retval = !search_devargs(dev->device.name);
284cecf5ed9SRadu Nicolau 	}
285cecf5ed9SRadu Nicolau 
286e888bb12SKevin Laatz 	free(runtime_dir);
287e888bb12SKevin Laatz 	return retval;
288e888bb12SKevin Laatz }
289e888bb12SKevin Laatz 
290e888bb12SKevin Laatz static int
dsa_probe(void)291e888bb12SKevin Laatz dsa_probe(void)
292e888bb12SKevin Laatz {
293e888bb12SKevin Laatz 	struct rte_dsa_device *dev;
294e888bb12SKevin Laatz 
295e888bb12SKevin Laatz 	TAILQ_FOREACH(dev, &dsa_bus.device_list, next) {
296e888bb12SKevin Laatz 		char type[64], name[64];
297e888bb12SKevin Laatz 
298e888bb12SKevin Laatz 		if (read_wq_string(dev, "type", type, sizeof(type)) < 0 ||
299e888bb12SKevin Laatz 				read_wq_string(dev, "name", name, sizeof(name)) < 0)
300e888bb12SKevin Laatz 			continue;
301e888bb12SKevin Laatz 
302cecf5ed9SRadu Nicolau 		if (strncmp(type, "user", 4) == 0 &&
303cecf5ed9SRadu Nicolau 				is_for_this_process_use(dev, name)) {
304e888bb12SKevin Laatz 			dev->device.driver = &dsa_bus.driver;
305e888bb12SKevin Laatz 			idxd_probe_dsa(dev);
306e888bb12SKevin Laatz 			continue;
307e888bb12SKevin Laatz 		}
308e888bb12SKevin Laatz 		IDXD_PMD_DEBUG("WQ '%s', not allocated to DPDK", dev->wq_name);
309e888bb12SKevin Laatz 	}
310e888bb12SKevin Laatz 
311e888bb12SKevin Laatz 	return 0;
312e888bb12SKevin Laatz }
313e888bb12SKevin Laatz 
314e888bb12SKevin Laatz static int
dsa_scan(void)315e888bb12SKevin Laatz dsa_scan(void)
316e888bb12SKevin Laatz {
317e888bb12SKevin Laatz 	const char *path = dsa_get_dev_path();
318e888bb12SKevin Laatz 	struct dirent *wq;
319e888bb12SKevin Laatz 	DIR *dev_dir;
320e888bb12SKevin Laatz 
321e888bb12SKevin Laatz 	dev_dir = opendir(path);
322e888bb12SKevin Laatz 	if (dev_dir == NULL) {
323e888bb12SKevin Laatz 		if (errno == ENOENT)
324e888bb12SKevin Laatz 			return 0; /* no bus, return without error */
325e888bb12SKevin Laatz 		IDXD_PMD_ERR("%s(): opendir '%s' failed: %s",
326e888bb12SKevin Laatz 				__func__, path, strerror(errno));
327e888bb12SKevin Laatz 		return -1;
328e888bb12SKevin Laatz 	}
329e888bb12SKevin Laatz 
330e888bb12SKevin Laatz 	while ((wq = readdir(dev_dir)) != NULL) {
331e888bb12SKevin Laatz 		struct rte_dsa_device *dev;
3327dcd73e3SOlivier Matz 		int numa_node = SOCKET_ID_ANY;
333e888bb12SKevin Laatz 
334e888bb12SKevin Laatz 		if (strncmp(wq->d_name, "wq", 2) != 0)
335e888bb12SKevin Laatz 			continue;
336e888bb12SKevin Laatz 		if (strnlen(wq->d_name, sizeof(dev->wq_name)) == sizeof(dev->wq_name)) {
337e888bb12SKevin Laatz 			IDXD_PMD_ERR("%s(): wq name too long: '%s', skipping",
338e888bb12SKevin Laatz 					__func__, wq->d_name);
339e888bb12SKevin Laatz 			continue;
340e888bb12SKevin Laatz 		}
341e888bb12SKevin Laatz 		IDXD_PMD_DEBUG("%s(): found %s/%s", __func__, path, wq->d_name);
342e888bb12SKevin Laatz 
343e888bb12SKevin Laatz 		dev = malloc(sizeof(*dev));
344390c4822SShiqi Liu 		if (dev == NULL) {
345390c4822SShiqi Liu 			closedir(dev_dir);
346390c4822SShiqi Liu 			return -ENOMEM;
347390c4822SShiqi Liu 		}
348e888bb12SKevin Laatz 		if (dsa_addr_parse(wq->d_name, &dev->addr) < 0) {
349e888bb12SKevin Laatz 			IDXD_PMD_ERR("Error parsing WQ name: %s", wq->d_name);
350e888bb12SKevin Laatz 			free(dev);
351e888bb12SKevin Laatz 			continue;
352e888bb12SKevin Laatz 		}
353e888bb12SKevin Laatz 		dev->device.bus = &dsa_bus.bus;
354e888bb12SKevin Laatz 		strlcpy(dev->wq_name, wq->d_name, sizeof(dev->wq_name));
355e888bb12SKevin Laatz 		TAILQ_INSERT_TAIL(&dsa_bus.device_list, dev, next);
356e888bb12SKevin Laatz 		devcount++;
357e888bb12SKevin Laatz 
358e888bb12SKevin Laatz 		read_device_int(dev, "numa_node", &numa_node);
359e888bb12SKevin Laatz 		dev->device.numa_node = numa_node;
360e888bb12SKevin Laatz 		dev->device.name = dev->wq_name;
361e888bb12SKevin Laatz 	}
362e888bb12SKevin Laatz 
363e888bb12SKevin Laatz 	closedir(dev_dir);
364e888bb12SKevin Laatz 	return 0;
365e888bb12SKevin Laatz }
366e888bb12SKevin Laatz 
367e888bb12SKevin Laatz static struct rte_device *
dsa_find_device(const struct rte_device * start,rte_dev_cmp_t cmp,const void * data)368e888bb12SKevin Laatz dsa_find_device(const struct rte_device *start, rte_dev_cmp_t cmp,
369e888bb12SKevin Laatz 			 const void *data)
370e888bb12SKevin Laatz {
371e888bb12SKevin Laatz 	struct rte_dsa_device *dev = TAILQ_FIRST(&dsa_bus.device_list);
372e888bb12SKevin Laatz 
373e888bb12SKevin Laatz 	/* the rte_device struct must be at start of dsa structure */
374e888bb12SKevin Laatz 	RTE_BUILD_BUG_ON(offsetof(struct rte_dsa_device, device) != 0);
375e888bb12SKevin Laatz 
376e888bb12SKevin Laatz 	if (start != NULL) /* jump to start point if given */
377e888bb12SKevin Laatz 		dev = TAILQ_NEXT((const struct rte_dsa_device *)start, next);
378e888bb12SKevin Laatz 	while (dev != NULL) {
379e888bb12SKevin Laatz 		if (cmp(&dev->device, data) == 0)
380e888bb12SKevin Laatz 			return &dev->device;
381e888bb12SKevin Laatz 		dev = TAILQ_NEXT(dev, next);
382e888bb12SKevin Laatz 	}
383e888bb12SKevin Laatz 	return NULL;
384e888bb12SKevin Laatz }
385e888bb12SKevin Laatz 
386e888bb12SKevin Laatz static enum rte_iova_mode
dsa_get_iommu_class(void)387e888bb12SKevin Laatz dsa_get_iommu_class(void)
388e888bb12SKevin Laatz {
389e888bb12SKevin Laatz 	/* if there are no devices, report don't care, otherwise VA mode */
390e888bb12SKevin Laatz 	return devcount > 0 ? RTE_IOVA_VA : RTE_IOVA_DC;
391e888bb12SKevin Laatz }
392e888bb12SKevin Laatz 
393e888bb12SKevin Laatz static int
dsa_addr_parse(const char * name,void * addr)394e888bb12SKevin Laatz dsa_addr_parse(const char *name, void *addr)
395e888bb12SKevin Laatz {
396e888bb12SKevin Laatz 	struct dsa_wq_addr *wq = addr;
397e888bb12SKevin Laatz 	unsigned int device_id, wq_id;
398e888bb12SKevin Laatz 
399e888bb12SKevin Laatz 	if (sscanf(name, "wq%u.%u", &device_id, &wq_id) != 2) {
400e888bb12SKevin Laatz 		IDXD_PMD_DEBUG("Parsing WQ name failed: %s", name);
401e888bb12SKevin Laatz 		return -1;
402e888bb12SKevin Laatz 	}
403e888bb12SKevin Laatz 
404cecf5ed9SRadu Nicolau 	if (wq != NULL) {
405e888bb12SKevin Laatz 		wq->device_id = device_id;
406e888bb12SKevin Laatz 		wq->wq_id = wq_id;
407cecf5ed9SRadu Nicolau 	}
408cecf5ed9SRadu Nicolau 
409e888bb12SKevin Laatz 	return 0;
410e888bb12SKevin Laatz }
411e888bb12SKevin Laatz 
412e888bb12SKevin Laatz RTE_REGISTER_BUS(dsa, dsa_bus.bus);
413