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