--- /dev/null
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright 2020 Mellanox Technologies Ltd
+ */
+
+#include <stdlib.h>
+#include <dirent.h>
+#include <libgen.h>
+
+#include <rte_malloc.h>
+#include <rte_errno.h>
+#include <rte_bus_auxiliary.h>
+#include <rte_common.h>
+#include "eal_filesystem.h"
+
+#include "mlx5_common_utils.h"
+#include "mlx5_common_private.h"
+
+#define AUXILIARY_SYSFS_PATH "/sys/bus/auxiliary/devices"
+#define MLX5_AUXILIARY_PREFIX "mlx5_core.sf."
+
+int
+mlx5_auxiliary_get_child_name(const char *dev, const char *node,
+ char *child, size_t size)
+{
+ DIR *dir;
+ struct dirent *dent;
+ MKSTR(path, "%s/%s%s", AUXILIARY_SYSFS_PATH, dev, node);
+
+ dir = opendir(path);
+ if (dir == NULL) {
+ rte_errno = errno;
+ return -rte_errno;
+ }
+ /* Get the first file name. */
+ while ((dent = readdir(dir)) != NULL) {
+ if (dent->d_name[0] != '.')
+ break;
+ }
+ closedir(dir);
+ if (dent == NULL) {
+ rte_errno = ENOENT;
+ return -rte_errno;
+ }
+ if (rte_strscpy(child, dent->d_name, size) < 0)
+ return -rte_errno;
+ return 0;
+}
+
+static int
+mlx5_auxiliary_get_pci_path(const struct rte_auxiliary_device *dev,
+ char *sysfs_pci, size_t size)
+{
+ char sysfs_real[PATH_MAX] = { 0 };
+ MKSTR(sysfs_aux, "%s/%s", AUXILIARY_SYSFS_PATH, dev->name);
+ char *dir;
+
+ if (realpath(sysfs_aux, sysfs_real) == NULL) {
+ rte_errno = errno;
+ return -rte_errno;
+ }
+ dir = dirname(sysfs_real);
+ if (dir == NULL) {
+ rte_errno = errno;
+ return -rte_errno;
+ }
+ if (rte_strscpy(sysfs_pci, dir, size) < 0)
+ return -rte_errno;
+ return 0;
+}
+
+static int
+mlx5_auxiliary_get_numa(const struct rte_auxiliary_device *dev)
+{
+ unsigned long numa;
+ char numa_path[PATH_MAX];
+
+ if (mlx5_auxiliary_get_pci_path(dev, numa_path, sizeof(numa_path)) != 0)
+ return SOCKET_ID_ANY;
+ if (strcat(numa_path, "/numa_node") == NULL) {
+ rte_errno = ENAMETOOLONG;
+ return SOCKET_ID_ANY;
+ }
+ if (eal_parse_sysfs_value(numa_path, &numa) != 0) {
+ rte_errno = EINVAL;
+ return SOCKET_ID_ANY;
+ }
+ return (int)numa;
+}
+
+struct ibv_device *
+mlx5_get_aux_ibv_device(const struct rte_auxiliary_device *dev)
+{
+ int n;
+ char ib_name[64] = { 0 };
+ struct ibv_device **ibv_list = mlx5_glue->get_device_list(&n);
+ struct ibv_device *ibv_match = NULL;
+
+ if (!ibv_list) {
+ rte_errno = ENOSYS;
+ return NULL;
+ }
+ if (mlx5_auxiliary_get_child_name(dev->name, "/infiniband",
+ ib_name, sizeof(ib_name)) != 0)
+ goto out;
+ while (n-- > 0) {
+ if (strcmp(ibv_list[n]->name, ib_name) != 0)
+ continue;
+ ibv_match = ibv_list[n];
+ break;
+ }
+ if (ibv_match == NULL)
+ rte_errno = ENOENT;
+out:
+ mlx5_glue->free_device_list(ibv_list);
+ return ibv_match;
+}
+
+static bool
+mlx5_common_auxiliary_match(const char *name)
+{
+ return strncmp(name, MLX5_AUXILIARY_PREFIX,
+ strlen(MLX5_AUXILIARY_PREFIX)) == 0;
+}
+
+static int
+mlx5_common_auxiliary_probe(struct rte_auxiliary_driver *drv __rte_unused,
+ struct rte_auxiliary_device *dev)
+{
+ dev->device.numa_node = mlx5_auxiliary_get_numa(dev);
+ return mlx5_common_dev_probe(&dev->device);
+}
+
+static int
+mlx5_common_auxiliary_remove(struct rte_auxiliary_device *auxiliary_dev)
+{
+ return mlx5_common_dev_remove(&auxiliary_dev->device);
+}
+
+static int
+mlx5_common_auxiliary_dma_map(struct rte_auxiliary_device *auxiliary_dev,
+ void *addr, uint64_t iova, size_t len)
+{
+ return mlx5_common_dev_dma_map(&auxiliary_dev->device, addr, iova, len);
+}
+
+static int
+mlx5_common_auxiliary_dma_unmap(struct rte_auxiliary_device *auxiliary_dev,
+ void *addr, uint64_t iova, size_t len)
+{
+ return mlx5_common_dev_dma_unmap(&auxiliary_dev->device, addr, iova,
+ len);
+}
+
+static struct rte_auxiliary_driver mlx5_auxiliary_driver = {
+ .driver = {
+ .name = MLX5_AUXILIARY_DRIVER_NAME,
+ },
+ .match = mlx5_common_auxiliary_match,
+ .probe = mlx5_common_auxiliary_probe,
+ .remove = mlx5_common_auxiliary_remove,
+ .dma_map = mlx5_common_auxiliary_dma_map,
+ .dma_unmap = mlx5_common_auxiliary_dma_unmap,
+};
+
+void mlx5_common_auxiliary_init(void)
+{
+ if (mlx5_auxiliary_driver.bus == NULL)
+ rte_auxiliary_register(&mlx5_auxiliary_driver);
+}
+
+RTE_FINI(mlx5_common_auxiliary_driver_finish)
+{
+ if (mlx5_auxiliary_driver.bus != NULL)
+ rte_auxiliary_unregister(&mlx5_auxiliary_driver);
+}
/* Reported driver name. */
#define MLX5_PCI_DRIVER_NAME "mlx5_pci"
+#define MLX5_AUXILIARY_DRIVER_NAME "mlx5_auxiliary"
/* Bit-field manipulation. */
#define BITFIELD_DECLARE(bf, type, size) \
int mkstr_size_##name = snprintf(NULL, 0, "" __VA_ARGS__); \
char name[mkstr_size_##name + 1]; \
\
+ memset(name, 0, mkstr_size_##name + 1); \
snprintf(name, sizeof(name), "" __VA_ARGS__)
enum {
__rte_internal
int mlx5_get_ifname_sysfs(const char *ibdev_path, char *ifname);
+__rte_internal
+int mlx5_auxiliary_get_child_name(const char *dev, const char *node,
+ char *child, size_t size);
enum mlx5_class {
MLX5_CLASS_INVALID,