1 // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB 2 /* 3 * Copyright (c) 2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved 4 */ 5 6 #include <linux/kref.h> 7 #include <linux/cdev.h> 8 #include <linux/mutex.h> 9 #include <linux/file.h> 10 #include <linux/fs.h> 11 #include <rdma/ib_ucaps.h> 12 13 #define RDMA_UCAP_FIRST RDMA_UCAP_MLX5_CTRL_LOCAL 14 15 static DEFINE_MUTEX(ucaps_mutex); 16 static struct ib_ucap *ucaps_list[RDMA_UCAP_MAX]; 17 static bool ucaps_class_is_registered; 18 static dev_t ucaps_base_dev; 19 20 struct ib_ucap { 21 struct cdev cdev; 22 struct device dev; 23 struct kref ref; 24 }; 25 26 static const char *ucap_names[RDMA_UCAP_MAX] = { 27 [RDMA_UCAP_MLX5_CTRL_LOCAL] = "mlx5_perm_ctrl_local", 28 [RDMA_UCAP_MLX5_CTRL_OTHER_VHCA] = "mlx5_perm_ctrl_other_vhca" 29 }; 30 31 static char *ucaps_devnode(const struct device *dev, umode_t *mode) 32 { 33 if (mode) 34 *mode = 0600; 35 36 return kasprintf(GFP_KERNEL, "infiniband/%s", dev_name(dev)); 37 } 38 39 static const struct class ucaps_class = { 40 .name = "infiniband_ucaps", 41 .devnode = ucaps_devnode, 42 }; 43 44 static const struct file_operations ucaps_cdev_fops = { 45 .owner = THIS_MODULE, 46 .open = simple_open, 47 }; 48 49 /** 50 * ib_cleanup_ucaps - cleanup all API resources and class. 51 * 52 * This is called once, when removing the ib_uverbs module. 53 */ 54 void ib_cleanup_ucaps(void) 55 { 56 mutex_lock(&ucaps_mutex); 57 if (!ucaps_class_is_registered) { 58 mutex_unlock(&ucaps_mutex); 59 return; 60 } 61 62 for (int i = RDMA_UCAP_FIRST; i < RDMA_UCAP_MAX; i++) 63 WARN_ON(ucaps_list[i]); 64 65 class_unregister(&ucaps_class); 66 ucaps_class_is_registered = false; 67 unregister_chrdev_region(ucaps_base_dev, RDMA_UCAP_MAX); 68 mutex_unlock(&ucaps_mutex); 69 } 70 71 static int get_ucap_from_devt(dev_t devt, u64 *idx_mask) 72 { 73 for (int type = RDMA_UCAP_FIRST; type < RDMA_UCAP_MAX; type++) { 74 if (ucaps_list[type] && ucaps_list[type]->dev.devt == devt) { 75 *idx_mask |= 1 << type; 76 return 0; 77 } 78 } 79 80 return -EINVAL; 81 } 82 83 static int get_devt_from_fd(unsigned int fd, dev_t *ret_dev) 84 { 85 CLASS(fd, f)(fd); 86 87 if (fd_empty(f) || fd_file(f)->f_op != &ucaps_cdev_fops) 88 return -EBADF; 89 90 *ret_dev = file_inode(fd_file(f))->i_rdev; 91 return 0; 92 } 93 94 /** 95 * ib_ucaps_init - Initialization required before ucap creation. 96 * 97 * Return: 0 on success, or a negative errno value on failure 98 */ 99 static int ib_ucaps_init(void) 100 { 101 int ret = 0; 102 103 if (ucaps_class_is_registered) 104 return ret; 105 106 ret = class_register(&ucaps_class); 107 if (ret) 108 return ret; 109 110 ret = alloc_chrdev_region(&ucaps_base_dev, 0, RDMA_UCAP_MAX, 111 ucaps_class.name); 112 if (ret < 0) { 113 class_unregister(&ucaps_class); 114 return ret; 115 } 116 117 ucaps_class_is_registered = true; 118 119 return 0; 120 } 121 122 static void ucap_dev_release(struct device *device) 123 { 124 struct ib_ucap *ucap = container_of(device, struct ib_ucap, dev); 125 126 kfree(ucap); 127 } 128 129 /** 130 * ib_create_ucap - Add a ucap character device 131 * @type: UCAP type 132 * 133 * Creates a ucap character device in the /dev/infiniband directory. By default, 134 * the device has root-only read-write access. 135 * 136 * A driver may call this multiple times with the same UCAP type. A reference 137 * count tracks creations and deletions. 138 * 139 * Return: 0 on success, or a negative errno value on failure 140 */ 141 int ib_create_ucap(enum rdma_user_cap type) 142 { 143 struct ib_ucap *ucap; 144 int ret; 145 146 if (type >= RDMA_UCAP_MAX) 147 return -EINVAL; 148 149 mutex_lock(&ucaps_mutex); 150 ret = ib_ucaps_init(); 151 if (ret) 152 goto unlock; 153 154 ucap = ucaps_list[type]; 155 if (ucap) { 156 kref_get(&ucap->ref); 157 mutex_unlock(&ucaps_mutex); 158 return 0; 159 } 160 161 ucap = kzalloc_obj(*ucap); 162 if (!ucap) { 163 ret = -ENOMEM; 164 goto unlock; 165 } 166 167 device_initialize(&ucap->dev); 168 ucap->dev.class = &ucaps_class; 169 ucap->dev.devt = MKDEV(MAJOR(ucaps_base_dev), type); 170 ucap->dev.release = ucap_dev_release; 171 ret = dev_set_name(&ucap->dev, "%s", ucap_names[type]); 172 if (ret) 173 goto err_device; 174 175 cdev_init(&ucap->cdev, &ucaps_cdev_fops); 176 ucap->cdev.owner = THIS_MODULE; 177 178 ret = cdev_device_add(&ucap->cdev, &ucap->dev); 179 if (ret) 180 goto err_device; 181 182 kref_init(&ucap->ref); 183 ucaps_list[type] = ucap; 184 mutex_unlock(&ucaps_mutex); 185 186 return 0; 187 188 err_device: 189 put_device(&ucap->dev); 190 unlock: 191 mutex_unlock(&ucaps_mutex); 192 return ret; 193 } 194 EXPORT_SYMBOL(ib_create_ucap); 195 196 static void ib_release_ucap(struct kref *ref) 197 { 198 struct ib_ucap *ucap = container_of(ref, struct ib_ucap, ref); 199 enum rdma_user_cap type; 200 201 for (type = RDMA_UCAP_FIRST; type < RDMA_UCAP_MAX; type++) { 202 if (ucaps_list[type] == ucap) 203 break; 204 } 205 WARN_ON(type == RDMA_UCAP_MAX); 206 207 ucaps_list[type] = NULL; 208 cdev_device_del(&ucap->cdev, &ucap->dev); 209 put_device(&ucap->dev); 210 } 211 212 /** 213 * ib_remove_ucap - Remove a ucap character device 214 * @type: User cap type 215 * 216 * Removes the ucap character device according to type. The device is completely 217 * removed from the filesystem when its reference count reaches 0. 218 */ 219 void ib_remove_ucap(enum rdma_user_cap type) 220 { 221 struct ib_ucap *ucap; 222 223 mutex_lock(&ucaps_mutex); 224 ucap = ucaps_list[type]; 225 if (WARN_ON(!ucap)) 226 goto end; 227 228 kref_put(&ucap->ref, ib_release_ucap); 229 end: 230 mutex_unlock(&ucaps_mutex); 231 } 232 EXPORT_SYMBOL(ib_remove_ucap); 233 234 /** 235 * ib_get_ucaps - Get bitmask of ucap types from file descriptors 236 * @fds: Array of file descriptors 237 * @fd_count: Number of file descriptors in the array 238 * @idx_mask: Bitmask to be updated based on the ucaps in the fd list 239 * 240 * Given an array of file descriptors, this function returns a bitmask of 241 * the ucaps where a bit is set if an FD for that ucap type was in the array. 242 * 243 * Return: 0 on success, or a negative errno value on failure 244 */ 245 int ib_get_ucaps(int *fds, int fd_count, uint64_t *idx_mask) 246 { 247 int ret = 0; 248 dev_t dev; 249 250 *idx_mask = 0; 251 mutex_lock(&ucaps_mutex); 252 for (int i = 0; i < fd_count; i++) { 253 ret = get_devt_from_fd(fds[i], &dev); 254 if (ret) 255 goto end; 256 257 ret = get_ucap_from_devt(dev, idx_mask); 258 if (ret) 259 goto end; 260 } 261 262 end: 263 mutex_unlock(&ucaps_mutex); 264 return ret; 265 } 266