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 struct file *file; 86 87 file = fget(fd); 88 if (!file) 89 return -EBADF; 90 91 *ret_dev = file_inode(file)->i_rdev; 92 fput(file); 93 return 0; 94 } 95 96 /** 97 * ib_ucaps_init - Initialization required before ucap creation. 98 * 99 * Return: 0 on success, or a negative errno value on failure 100 */ 101 static int ib_ucaps_init(void) 102 { 103 int ret = 0; 104 105 if (ucaps_class_is_registered) 106 return ret; 107 108 ret = class_register(&ucaps_class); 109 if (ret) 110 return ret; 111 112 ret = alloc_chrdev_region(&ucaps_base_dev, 0, RDMA_UCAP_MAX, 113 ucaps_class.name); 114 if (ret < 0) { 115 class_unregister(&ucaps_class); 116 return ret; 117 } 118 119 ucaps_class_is_registered = true; 120 121 return 0; 122 } 123 124 static void ucap_dev_release(struct device *device) 125 { 126 struct ib_ucap *ucap = container_of(device, struct ib_ucap, dev); 127 128 kfree(ucap); 129 } 130 131 /** 132 * ib_create_ucap - Add a ucap character device 133 * @type: UCAP type 134 * 135 * Creates a ucap character device in the /dev/infiniband directory. By default, 136 * the device has root-only read-write access. 137 * 138 * A driver may call this multiple times with the same UCAP type. A reference 139 * count tracks creations and deletions. 140 * 141 * Return: 0 on success, or a negative errno value on failure 142 */ 143 int ib_create_ucap(enum rdma_user_cap type) 144 { 145 struct ib_ucap *ucap; 146 int ret; 147 148 if (type >= RDMA_UCAP_MAX) 149 return -EINVAL; 150 151 mutex_lock(&ucaps_mutex); 152 ret = ib_ucaps_init(); 153 if (ret) 154 goto unlock; 155 156 ucap = ucaps_list[type]; 157 if (ucap) { 158 kref_get(&ucap->ref); 159 mutex_unlock(&ucaps_mutex); 160 return 0; 161 } 162 163 ucap = kzalloc(sizeof(*ucap), GFP_KERNEL); 164 if (!ucap) { 165 ret = -ENOMEM; 166 goto unlock; 167 } 168 169 device_initialize(&ucap->dev); 170 ucap->dev.class = &ucaps_class; 171 ucap->dev.devt = MKDEV(MAJOR(ucaps_base_dev), type); 172 ucap->dev.release = ucap_dev_release; 173 ret = dev_set_name(&ucap->dev, "%s", ucap_names[type]); 174 if (ret) 175 goto err_device; 176 177 cdev_init(&ucap->cdev, &ucaps_cdev_fops); 178 ucap->cdev.owner = THIS_MODULE; 179 180 ret = cdev_device_add(&ucap->cdev, &ucap->dev); 181 if (ret) 182 goto err_device; 183 184 kref_init(&ucap->ref); 185 ucaps_list[type] = ucap; 186 mutex_unlock(&ucaps_mutex); 187 188 return 0; 189 190 err_device: 191 put_device(&ucap->dev); 192 unlock: 193 mutex_unlock(&ucaps_mutex); 194 return ret; 195 } 196 EXPORT_SYMBOL(ib_create_ucap); 197 198 static void ib_release_ucap(struct kref *ref) 199 { 200 struct ib_ucap *ucap = container_of(ref, struct ib_ucap, ref); 201 enum rdma_user_cap type; 202 203 for (type = RDMA_UCAP_FIRST; type < RDMA_UCAP_MAX; type++) { 204 if (ucaps_list[type] == ucap) 205 break; 206 } 207 WARN_ON(type == RDMA_UCAP_MAX); 208 209 ucaps_list[type] = NULL; 210 cdev_device_del(&ucap->cdev, &ucap->dev); 211 put_device(&ucap->dev); 212 } 213 214 /** 215 * ib_remove_ucap - Remove a ucap character device 216 * @type: User cap type 217 * 218 * Removes the ucap character device according to type. The device is completely 219 * removed from the filesystem when its reference count reaches 0. 220 */ 221 void ib_remove_ucap(enum rdma_user_cap type) 222 { 223 struct ib_ucap *ucap; 224 225 mutex_lock(&ucaps_mutex); 226 ucap = ucaps_list[type]; 227 if (WARN_ON(!ucap)) 228 goto end; 229 230 kref_put(&ucap->ref, ib_release_ucap); 231 end: 232 mutex_unlock(&ucaps_mutex); 233 } 234 EXPORT_SYMBOL(ib_remove_ucap); 235 236 /** 237 * ib_get_ucaps - Get bitmask of ucap types from file descriptors 238 * @fds: Array of file descriptors 239 * @fd_count: Number of file descriptors in the array 240 * @idx_mask: Bitmask to be updated based on the ucaps in the fd list 241 * 242 * Given an array of file descriptors, this function returns a bitmask of 243 * the ucaps where a bit is set if an FD for that ucap type was in the array. 244 * 245 * Return: 0 on success, or a negative errno value on failure 246 */ 247 int ib_get_ucaps(int *fds, int fd_count, uint64_t *idx_mask) 248 { 249 int ret = 0; 250 dev_t dev; 251 252 *idx_mask = 0; 253 mutex_lock(&ucaps_mutex); 254 for (int i = 0; i < fd_count; i++) { 255 ret = get_devt_from_fd(fds[i], &dev); 256 if (ret) 257 goto end; 258 259 ret = get_ucap_from_devt(dev, idx_mask); 260 if (ret) 261 goto end; 262 } 263 264 end: 265 mutex_unlock(&ucaps_mutex); 266 return ret; 267 } 268