1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright 2020 Mellanox Technologies Ltd 3 */ 4 5 #include <stdlib.h> 6 #include <dirent.h> 7 #include <libgen.h> 8 9 #include <rte_malloc.h> 10 #include <rte_errno.h> 11 #include <rte_bus_auxiliary.h> 12 #include <rte_common.h> 13 #include "eal_filesystem.h" 14 15 #include "mlx5_common_utils.h" 16 #include "mlx5_common_private.h" 17 18 #define AUXILIARY_SYSFS_PATH "/sys/bus/auxiliary/devices" 19 #define MLX5_AUXILIARY_PREFIX "mlx5_core.sf." 20 21 int 22 mlx5_auxiliary_get_child_name(const char *dev, const char *node, 23 char *child, size_t size) 24 { 25 DIR *dir; 26 struct dirent *dent; 27 MKSTR(path, "%s/%s%s", AUXILIARY_SYSFS_PATH, dev, node); 28 29 dir = opendir(path); 30 if (dir == NULL) { 31 rte_errno = errno; 32 return -rte_errno; 33 } 34 /* Get the first file name. */ 35 while ((dent = readdir(dir)) != NULL) { 36 if (dent->d_name[0] != '.') 37 break; 38 } 39 closedir(dir); 40 if (dent == NULL) { 41 rte_errno = ENOENT; 42 return -rte_errno; 43 } 44 if (rte_strscpy(child, dent->d_name, size) < 0) 45 return -rte_errno; 46 return 0; 47 } 48 49 static int 50 mlx5_auxiliary_get_pci_path(const struct rte_auxiliary_device *dev, 51 char *sysfs_pci, size_t size) 52 { 53 char sysfs_real[PATH_MAX] = { 0 }; 54 MKSTR(sysfs_aux, "%s/%s", AUXILIARY_SYSFS_PATH, dev->name); 55 char *dir; 56 57 if (realpath(sysfs_aux, sysfs_real) == NULL) { 58 rte_errno = errno; 59 return -rte_errno; 60 } 61 dir = dirname(sysfs_real); 62 if (dir == NULL) { 63 rte_errno = errno; 64 return -rte_errno; 65 } 66 if (rte_strscpy(sysfs_pci, dir, size) < 0) 67 return -rte_errno; 68 return 0; 69 } 70 71 int 72 mlx5_auxiliary_get_pci_str(const struct rte_auxiliary_device *dev, 73 char *addr, size_t size) 74 { 75 char sysfs_pci[PATH_MAX]; 76 char *base; 77 78 if (mlx5_auxiliary_get_pci_path(dev, sysfs_pci, sizeof(sysfs_pci)) != 0) 79 return -ENODEV; 80 base = basename(sysfs_pci); 81 if (base == NULL) 82 return -errno; 83 if (rte_strscpy(addr, base, size) < 0) 84 return -rte_errno; 85 return 0; 86 } 87 88 static int 89 mlx5_auxiliary_get_numa(const struct rte_auxiliary_device *dev) 90 { 91 unsigned long numa; 92 char numa_path[PATH_MAX]; 93 94 if (mlx5_auxiliary_get_pci_path(dev, numa_path, sizeof(numa_path)) != 0) 95 return SOCKET_ID_ANY; 96 if (strcat(numa_path, "/numa_node") == NULL) { 97 rte_errno = ENAMETOOLONG; 98 return SOCKET_ID_ANY; 99 } 100 if (eal_parse_sysfs_value(numa_path, &numa) != 0) { 101 rte_errno = EINVAL; 102 return SOCKET_ID_ANY; 103 } 104 return (int)numa; 105 } 106 107 struct ibv_device * 108 mlx5_get_aux_ibv_device(const struct rte_auxiliary_device *dev) 109 { 110 int n; 111 char ib_name[64] = { 0 }; 112 struct ibv_device **ibv_list = mlx5_glue->get_device_list(&n); 113 struct ibv_device *ibv_match = NULL; 114 115 if (!ibv_list) { 116 rte_errno = ENOSYS; 117 return NULL; 118 } 119 if (mlx5_auxiliary_get_child_name(dev->name, "/infiniband", 120 ib_name, sizeof(ib_name)) != 0) 121 goto out; 122 while (n-- > 0) { 123 if (strcmp(ibv_list[n]->name, ib_name) != 0) 124 continue; 125 ibv_match = ibv_list[n]; 126 break; 127 } 128 if (ibv_match == NULL) 129 rte_errno = ENOENT; 130 out: 131 mlx5_glue->free_device_list(ibv_list); 132 return ibv_match; 133 } 134 135 static bool 136 mlx5_common_auxiliary_match(const char *name) 137 { 138 return strncmp(name, MLX5_AUXILIARY_PREFIX, 139 strlen(MLX5_AUXILIARY_PREFIX)) == 0; 140 } 141 142 static int 143 mlx5_common_auxiliary_probe(struct rte_auxiliary_driver *drv __rte_unused, 144 struct rte_auxiliary_device *dev) 145 { 146 dev->device.numa_node = mlx5_auxiliary_get_numa(dev); 147 return mlx5_common_dev_probe(&dev->device); 148 } 149 150 static int 151 mlx5_common_auxiliary_remove(struct rte_auxiliary_device *auxiliary_dev) 152 { 153 return mlx5_common_dev_remove(&auxiliary_dev->device); 154 } 155 156 static int 157 mlx5_common_auxiliary_dma_map(struct rte_auxiliary_device *auxiliary_dev, 158 void *addr, uint64_t iova, size_t len) 159 { 160 return mlx5_common_dev_dma_map(&auxiliary_dev->device, addr, iova, len); 161 } 162 163 static int 164 mlx5_common_auxiliary_dma_unmap(struct rte_auxiliary_device *auxiliary_dev, 165 void *addr, uint64_t iova, size_t len) 166 { 167 return mlx5_common_dev_dma_unmap(&auxiliary_dev->device, addr, iova, 168 len); 169 } 170 171 static struct rte_auxiliary_driver mlx5_auxiliary_driver = { 172 .driver = { 173 .name = MLX5_AUXILIARY_DRIVER_NAME, 174 }, 175 .match = mlx5_common_auxiliary_match, 176 .probe = mlx5_common_auxiliary_probe, 177 .remove = mlx5_common_auxiliary_remove, 178 .dma_map = mlx5_common_auxiliary_dma_map, 179 .dma_unmap = mlx5_common_auxiliary_dma_unmap, 180 }; 181 182 void mlx5_common_auxiliary_init(void) 183 { 184 if (mlx5_auxiliary_driver.bus == NULL) 185 rte_auxiliary_register(&mlx5_auxiliary_driver); 186 } 187 188 RTE_FINI(mlx5_common_auxiliary_driver_finish) 189 { 190 if (mlx5_auxiliary_driver.bus != NULL) 191 rte_auxiliary_unregister(&mlx5_auxiliary_driver); 192 } 193