11afce308SXueming Li /* SPDX-License-Identifier: BSD-3-Clause
21afce308SXueming Li * Copyright (c) 2021 NVIDIA Corporation & Affiliates
31afce308SXueming Li */
41afce308SXueming Li
51afce308SXueming Li #include <string.h>
61afce308SXueming Li #include <dirent.h>
71afce308SXueming Li
81afce308SXueming Li #include <rte_log.h>
91afce308SXueming Li #include <rte_malloc.h>
101afce308SXueming Li #include <rte_devargs.h>
111afce308SXueming Li #include <rte_memcpy.h>
121afce308SXueming Li #include <eal_filesystem.h>
131afce308SXueming Li
141afce308SXueming Li #include "../private.h"
151afce308SXueming Li
161afce308SXueming Li #define AUXILIARY_SYSFS_PATH "/sys/bus/auxiliary/devices"
171afce308SXueming Li
181afce308SXueming Li /* Scan one auxiliary sysfs entry, and fill the devices list from it. */
191afce308SXueming Li static int
auxiliary_scan_one(const char * dirname,const char * name)201afce308SXueming Li auxiliary_scan_one(const char *dirname, const char *name)
211afce308SXueming Li {
221afce308SXueming Li struct rte_auxiliary_device *dev;
231afce308SXueming Li struct rte_auxiliary_device *dev2;
241afce308SXueming Li char filename[PATH_MAX];
251afce308SXueming Li unsigned long tmp;
261afce308SXueming Li int ret;
271afce308SXueming Li
281afce308SXueming Li dev = malloc(sizeof(*dev));
291afce308SXueming Li if (dev == NULL)
301afce308SXueming Li return -1;
311afce308SXueming Li
321afce308SXueming Li memset(dev, 0, sizeof(*dev));
331afce308SXueming Li if (rte_strscpy(dev->name, name, sizeof(dev->name)) < 0) {
341afce308SXueming Li free(dev);
351afce308SXueming Li return -1;
361afce308SXueming Li }
371afce308SXueming Li dev->device.name = dev->name;
381afce308SXueming Li dev->device.bus = &auxiliary_bus.bus;
391afce308SXueming Li
401afce308SXueming Li /* Get NUMA node, default to 0 if not present */
411afce308SXueming Li snprintf(filename, sizeof(filename), "%s/%s/numa_node",
421afce308SXueming Li dirname, name);
43*7dcd73e3SOlivier Matz if (access(filename, F_OK) == 0 &&
44*7dcd73e3SOlivier Matz eal_parse_sysfs_value(filename, &tmp) == 0)
451afce308SXueming Li dev->device.numa_node = tmp;
461afce308SXueming Li else
47*7dcd73e3SOlivier Matz dev->device.numa_node = SOCKET_ID_ANY;
481afce308SXueming Li
491afce308SXueming Li auxiliary_on_scan(dev);
501afce308SXueming Li
511afce308SXueming Li /* Device is valid, add in list (sorted) */
521afce308SXueming Li TAILQ_FOREACH(dev2, &auxiliary_bus.device_list, next) {
531afce308SXueming Li ret = strcmp(dev->name, dev2->name);
541afce308SXueming Li if (ret > 0)
551afce308SXueming Li continue;
561afce308SXueming Li if (ret < 0) {
571afce308SXueming Li auxiliary_insert_device(dev2, dev);
581afce308SXueming Li } else { /* already registered */
591afce308SXueming Li if (rte_dev_is_probed(&dev2->device) &&
601afce308SXueming Li dev2->device.devargs != dev->device.devargs) {
611afce308SXueming Li /* To probe device with new devargs. */
621afce308SXueming Li rte_devargs_remove(dev2->device.devargs);
631afce308SXueming Li auxiliary_on_scan(dev2);
641afce308SXueming Li }
651afce308SXueming Li free(dev);
661afce308SXueming Li }
671afce308SXueming Li return 0;
681afce308SXueming Li }
691afce308SXueming Li auxiliary_add_device(dev);
701afce308SXueming Li return 0;
711afce308SXueming Li }
721afce308SXueming Li
731afce308SXueming Li /*
741afce308SXueming Li * Test whether the auxiliary device exist.
751afce308SXueming Li */
761afce308SXueming Li bool
auxiliary_dev_exists(const char * name)771afce308SXueming Li auxiliary_dev_exists(const char *name)
781afce308SXueming Li {
791afce308SXueming Li DIR *dir;
801afce308SXueming Li char dirname[PATH_MAX];
811afce308SXueming Li
821afce308SXueming Li snprintf(dirname, sizeof(dirname), "%s/%s",
831afce308SXueming Li AUXILIARY_SYSFS_PATH, name);
841afce308SXueming Li dir = opendir(dirname);
851afce308SXueming Li if (dir == NULL)
861afce308SXueming Li return false;
871afce308SXueming Li closedir(dir);
881afce308SXueming Li return true;
891afce308SXueming Li }
901afce308SXueming Li
911afce308SXueming Li /*
921afce308SXueming Li * Scan the devices in the auxiliary bus.
931afce308SXueming Li */
941afce308SXueming Li int
auxiliary_scan(void)951afce308SXueming Li auxiliary_scan(void)
961afce308SXueming Li {
971afce308SXueming Li struct dirent *e;
981afce308SXueming Li DIR *dir;
991afce308SXueming Li char dirname[PATH_MAX];
1001afce308SXueming Li struct rte_auxiliary_driver *drv;
1011afce308SXueming Li
1021afce308SXueming Li dir = opendir(AUXILIARY_SYSFS_PATH);
1031afce308SXueming Li if (dir == NULL) {
1041afce308SXueming Li AUXILIARY_LOG(INFO, "%s not found, is auxiliary module loaded?",
1051afce308SXueming Li AUXILIARY_SYSFS_PATH);
1061afce308SXueming Li return 0;
1071afce308SXueming Li }
1081afce308SXueming Li
1091afce308SXueming Li while ((e = readdir(dir)) != NULL) {
1101afce308SXueming Li if (e->d_name[0] == '.')
1111afce308SXueming Li continue;
1121afce308SXueming Li
1131afce308SXueming Li if (auxiliary_is_ignored_device(e->d_name))
1141afce308SXueming Li continue;
1151afce308SXueming Li
1161afce308SXueming Li snprintf(dirname, sizeof(dirname), "%s/%s",
1171afce308SXueming Li AUXILIARY_SYSFS_PATH, e->d_name);
1181afce308SXueming Li
1191afce308SXueming Li /* Ignore if no driver can handle. */
1201afce308SXueming Li FOREACH_DRIVER_ON_AUXILIARY_BUS(drv) {
1211afce308SXueming Li if (drv->match(e->d_name))
1221afce308SXueming Li break;
1231afce308SXueming Li }
1241afce308SXueming Li if (drv == NULL)
1251afce308SXueming Li continue;
1261afce308SXueming Li
1271afce308SXueming Li if (auxiliary_scan_one(dirname, e->d_name) < 0)
1281afce308SXueming Li goto error;
1291afce308SXueming Li }
1301afce308SXueming Li closedir(dir);
1311afce308SXueming Li return 0;
1321afce308SXueming Li
1331afce308SXueming Li error:
1341afce308SXueming Li closedir(dir);
1351afce308SXueming Li return -1;
1361afce308SXueming Li }
137