xref: /dpdk/drivers/bus/auxiliary/linux/auxiliary.c (revision daa02b5cddbb8e11b31d41e2bf7bb1ae64dcae2f)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright (c) 2021 NVIDIA Corporation & Affiliates
3  */
4 
5 #include <string.h>
6 #include <dirent.h>
7 
8 #include <rte_log.h>
9 #include <rte_bus.h>
10 #include <rte_malloc.h>
11 #include <rte_devargs.h>
12 #include <rte_memcpy.h>
13 #include <eal_filesystem.h>
14 
15 #include "../rte_bus_auxiliary.h"
16 #include "../private.h"
17 
18 #define AUXILIARY_SYSFS_PATH "/sys/bus/auxiliary/devices"
19 
20 /* Scan one auxiliary sysfs entry, and fill the devices list from it. */
21 static int
22 auxiliary_scan_one(const char *dirname, const char *name)
23 {
24 	struct rte_auxiliary_device *dev;
25 	struct rte_auxiliary_device *dev2;
26 	char filename[PATH_MAX];
27 	unsigned long tmp;
28 	int ret;
29 
30 	dev = malloc(sizeof(*dev));
31 	if (dev == NULL)
32 		return -1;
33 
34 	memset(dev, 0, sizeof(*dev));
35 	if (rte_strscpy(dev->name, name, sizeof(dev->name)) < 0) {
36 		free(dev);
37 		return -1;
38 	}
39 	dev->device.name = dev->name;
40 	dev->device.bus = &auxiliary_bus.bus;
41 
42 	/* Get NUMA node, default to 0 if not present */
43 	snprintf(filename, sizeof(filename), "%s/%s/numa_node",
44 		 dirname, name);
45 	if (access(filename, F_OK) != -1) {
46 		if (eal_parse_sysfs_value(filename, &tmp) == 0)
47 			dev->device.numa_node = tmp;
48 		else
49 			dev->device.numa_node = -1;
50 	} else {
51 		dev->device.numa_node = 0;
52 	}
53 
54 	auxiliary_on_scan(dev);
55 
56 	/* Device is valid, add in list (sorted) */
57 	TAILQ_FOREACH(dev2, &auxiliary_bus.device_list, next) {
58 		ret = strcmp(dev->name, dev2->name);
59 		if (ret > 0)
60 			continue;
61 		if (ret < 0) {
62 			auxiliary_insert_device(dev2, dev);
63 		} else { /* already registered */
64 			if (rte_dev_is_probed(&dev2->device) &&
65 			    dev2->device.devargs != dev->device.devargs) {
66 				/* To probe device with new devargs. */
67 				rte_devargs_remove(dev2->device.devargs);
68 				auxiliary_on_scan(dev2);
69 			}
70 			free(dev);
71 		}
72 		return 0;
73 	}
74 	auxiliary_add_device(dev);
75 	return 0;
76 }
77 
78 /*
79  * Test whether the auxiliary device exist.
80  */
81 bool
82 auxiliary_dev_exists(const char *name)
83 {
84 	DIR *dir;
85 	char dirname[PATH_MAX];
86 
87 	snprintf(dirname, sizeof(dirname), "%s/%s",
88 		 AUXILIARY_SYSFS_PATH, name);
89 	dir = opendir(dirname);
90 	if (dir == NULL)
91 		return false;
92 	closedir(dir);
93 	return true;
94 }
95 
96 /*
97  * Scan the devices in the auxiliary bus.
98  */
99 int
100 auxiliary_scan(void)
101 {
102 	struct dirent *e;
103 	DIR *dir;
104 	char dirname[PATH_MAX];
105 	struct rte_auxiliary_driver *drv;
106 
107 	dir = opendir(AUXILIARY_SYSFS_PATH);
108 	if (dir == NULL) {
109 		AUXILIARY_LOG(INFO, "%s not found, is auxiliary module loaded?",
110 			      AUXILIARY_SYSFS_PATH);
111 		return 0;
112 	}
113 
114 	while ((e = readdir(dir)) != NULL) {
115 		if (e->d_name[0] == '.')
116 			continue;
117 
118 		if (auxiliary_is_ignored_device(e->d_name))
119 			continue;
120 
121 		snprintf(dirname, sizeof(dirname), "%s/%s",
122 			 AUXILIARY_SYSFS_PATH, e->d_name);
123 
124 		/* Ignore if no driver can handle. */
125 		FOREACH_DRIVER_ON_AUXILIARY_BUS(drv) {
126 			if (drv->match(e->d_name))
127 				break;
128 		}
129 		if (drv == NULL)
130 			continue;
131 
132 		if (auxiliary_scan_one(dirname, e->d_name) < 0)
133 			goto error;
134 	}
135 	closedir(dir);
136 	return 0;
137 
138 error:
139 	closedir(dir);
140 	return -1;
141 }
142