1 // SPDX-License-Identifier: GPL-2.0-or-later 2 #include <linux/compat.h> 3 #include <linux/dma-mapping.h> 4 #include <linux/iommu.h> 5 #include <linux/module.h> 6 #include <linux/poll.h> 7 #include <linux/slab.h> 8 #include <linux/uacce.h> 9 10 static struct class *uacce_class; 11 static dev_t uacce_devt; 12 static DEFINE_MUTEX(uacce_mutex); 13 static DEFINE_XARRAY_ALLOC(uacce_xa); 14 15 static int uacce_start_queue(struct uacce_queue *q) 16 { 17 int ret = 0; 18 19 mutex_lock(&uacce_mutex); 20 21 if (q->state != UACCE_Q_INIT) { 22 ret = -EINVAL; 23 goto out_with_lock; 24 } 25 26 if (q->uacce->ops->start_queue) { 27 ret = q->uacce->ops->start_queue(q); 28 if (ret < 0) 29 goto out_with_lock; 30 } 31 32 q->state = UACCE_Q_STARTED; 33 34 out_with_lock: 35 mutex_unlock(&uacce_mutex); 36 37 return ret; 38 } 39 40 static int uacce_put_queue(struct uacce_queue *q) 41 { 42 struct uacce_device *uacce = q->uacce; 43 44 mutex_lock(&uacce_mutex); 45 46 if (q->state == UACCE_Q_ZOMBIE) 47 goto out; 48 49 if ((q->state == UACCE_Q_STARTED) && uacce->ops->stop_queue) 50 uacce->ops->stop_queue(q); 51 52 if ((q->state == UACCE_Q_INIT || q->state == UACCE_Q_STARTED) && 53 uacce->ops->put_queue) 54 uacce->ops->put_queue(q); 55 56 q->state = UACCE_Q_ZOMBIE; 57 out: 58 mutex_unlock(&uacce_mutex); 59 60 return 0; 61 } 62 63 static long uacce_fops_unl_ioctl(struct file *filep, 64 unsigned int cmd, unsigned long arg) 65 { 66 struct uacce_queue *q = filep->private_data; 67 struct uacce_device *uacce = q->uacce; 68 69 switch (cmd) { 70 case UACCE_CMD_START_Q: 71 return uacce_start_queue(q); 72 73 case UACCE_CMD_PUT_Q: 74 return uacce_put_queue(q); 75 76 default: 77 if (!uacce->ops->ioctl) 78 return -EINVAL; 79 80 return uacce->ops->ioctl(q, cmd, arg); 81 } 82 } 83 84 #ifdef CONFIG_COMPAT 85 static long uacce_fops_compat_ioctl(struct file *filep, 86 unsigned int cmd, unsigned long arg) 87 { 88 arg = (unsigned long)compat_ptr(arg); 89 90 return uacce_fops_unl_ioctl(filep, cmd, arg); 91 } 92 #endif 93 94 static int uacce_bind_queue(struct uacce_device *uacce, struct uacce_queue *q) 95 { 96 u32 pasid; 97 struct iommu_sva *handle; 98 99 if (!(uacce->flags & UACCE_DEV_SVA)) 100 return 0; 101 102 handle = iommu_sva_bind_device(uacce->parent, current->mm, NULL); 103 if (IS_ERR(handle)) 104 return PTR_ERR(handle); 105 106 pasid = iommu_sva_get_pasid(handle); 107 if (pasid == IOMMU_PASID_INVALID) { 108 iommu_sva_unbind_device(handle); 109 return -ENODEV; 110 } 111 112 q->handle = handle; 113 q->pasid = pasid; 114 return 0; 115 } 116 117 static void uacce_unbind_queue(struct uacce_queue *q) 118 { 119 if (!q->handle) 120 return; 121 iommu_sva_unbind_device(q->handle); 122 q->handle = NULL; 123 } 124 125 static int uacce_fops_open(struct inode *inode, struct file *filep) 126 { 127 struct uacce_device *uacce; 128 struct uacce_queue *q; 129 int ret = 0; 130 131 uacce = xa_load(&uacce_xa, iminor(inode)); 132 if (!uacce) 133 return -ENODEV; 134 135 q = kzalloc(sizeof(struct uacce_queue), GFP_KERNEL); 136 if (!q) 137 return -ENOMEM; 138 139 ret = uacce_bind_queue(uacce, q); 140 if (ret) 141 goto out_with_mem; 142 143 q->uacce = uacce; 144 145 if (uacce->ops->get_queue) { 146 ret = uacce->ops->get_queue(uacce, q->pasid, q); 147 if (ret < 0) 148 goto out_with_bond; 149 } 150 151 init_waitqueue_head(&q->wait); 152 filep->private_data = q; 153 uacce->inode = inode; 154 q->state = UACCE_Q_INIT; 155 156 mutex_lock(&uacce->queues_lock); 157 list_add(&q->list, &uacce->queues); 158 mutex_unlock(&uacce->queues_lock); 159 160 return 0; 161 162 out_with_bond: 163 uacce_unbind_queue(q); 164 out_with_mem: 165 kfree(q); 166 return ret; 167 } 168 169 static int uacce_fops_release(struct inode *inode, struct file *filep) 170 { 171 struct uacce_queue *q = filep->private_data; 172 173 mutex_lock(&q->uacce->queues_lock); 174 list_del(&q->list); 175 mutex_unlock(&q->uacce->queues_lock); 176 uacce_put_queue(q); 177 uacce_unbind_queue(q); 178 kfree(q); 179 180 return 0; 181 } 182 183 static void uacce_vma_close(struct vm_area_struct *vma) 184 { 185 struct uacce_queue *q = vma->vm_private_data; 186 struct uacce_qfile_region *qfr = NULL; 187 188 if (vma->vm_pgoff < UACCE_MAX_REGION) 189 qfr = q->qfrs[vma->vm_pgoff]; 190 191 kfree(qfr); 192 } 193 194 static const struct vm_operations_struct uacce_vm_ops = { 195 .close = uacce_vma_close, 196 }; 197 198 static int uacce_fops_mmap(struct file *filep, struct vm_area_struct *vma) 199 { 200 struct uacce_queue *q = filep->private_data; 201 struct uacce_device *uacce = q->uacce; 202 struct uacce_qfile_region *qfr; 203 enum uacce_qfrt type = UACCE_MAX_REGION; 204 int ret = 0; 205 206 if (vma->vm_pgoff < UACCE_MAX_REGION) 207 type = vma->vm_pgoff; 208 else 209 return -EINVAL; 210 211 qfr = kzalloc(sizeof(*qfr), GFP_KERNEL); 212 if (!qfr) 213 return -ENOMEM; 214 215 vma->vm_flags |= VM_DONTCOPY | VM_DONTEXPAND | VM_WIPEONFORK; 216 vma->vm_ops = &uacce_vm_ops; 217 vma->vm_private_data = q; 218 qfr->type = type; 219 220 mutex_lock(&uacce_mutex); 221 222 if (q->state != UACCE_Q_INIT && q->state != UACCE_Q_STARTED) { 223 ret = -EINVAL; 224 goto out_with_lock; 225 } 226 227 if (q->qfrs[type]) { 228 ret = -EEXIST; 229 goto out_with_lock; 230 } 231 232 switch (type) { 233 case UACCE_QFRT_MMIO: 234 case UACCE_QFRT_DUS: 235 if (!uacce->ops->mmap) { 236 ret = -EINVAL; 237 goto out_with_lock; 238 } 239 240 ret = uacce->ops->mmap(q, vma, qfr); 241 if (ret) 242 goto out_with_lock; 243 break; 244 245 default: 246 ret = -EINVAL; 247 goto out_with_lock; 248 } 249 250 q->qfrs[type] = qfr; 251 mutex_unlock(&uacce_mutex); 252 253 return ret; 254 255 out_with_lock: 256 mutex_unlock(&uacce_mutex); 257 kfree(qfr); 258 return ret; 259 } 260 261 static __poll_t uacce_fops_poll(struct file *file, poll_table *wait) 262 { 263 struct uacce_queue *q = file->private_data; 264 struct uacce_device *uacce = q->uacce; 265 266 poll_wait(file, &q->wait, wait); 267 if (uacce->ops->is_q_updated && uacce->ops->is_q_updated(q)) 268 return EPOLLIN | EPOLLRDNORM; 269 270 return 0; 271 } 272 273 static const struct file_operations uacce_fops = { 274 .owner = THIS_MODULE, 275 .open = uacce_fops_open, 276 .release = uacce_fops_release, 277 .unlocked_ioctl = uacce_fops_unl_ioctl, 278 #ifdef CONFIG_COMPAT 279 .compat_ioctl = uacce_fops_compat_ioctl, 280 #endif 281 .mmap = uacce_fops_mmap, 282 .poll = uacce_fops_poll, 283 }; 284 285 #define to_uacce_device(dev) container_of(dev, struct uacce_device, dev) 286 287 static ssize_t api_show(struct device *dev, 288 struct device_attribute *attr, char *buf) 289 { 290 struct uacce_device *uacce = to_uacce_device(dev); 291 292 return sprintf(buf, "%s\n", uacce->api_ver); 293 } 294 295 static ssize_t flags_show(struct device *dev, 296 struct device_attribute *attr, char *buf) 297 { 298 struct uacce_device *uacce = to_uacce_device(dev); 299 300 return sprintf(buf, "%u\n", uacce->flags); 301 } 302 303 static ssize_t available_instances_show(struct device *dev, 304 struct device_attribute *attr, 305 char *buf) 306 { 307 struct uacce_device *uacce = to_uacce_device(dev); 308 309 if (!uacce->ops->get_available_instances) 310 return -ENODEV; 311 312 return sprintf(buf, "%d\n", 313 uacce->ops->get_available_instances(uacce)); 314 } 315 316 static ssize_t algorithms_show(struct device *dev, 317 struct device_attribute *attr, char *buf) 318 { 319 struct uacce_device *uacce = to_uacce_device(dev); 320 321 return sprintf(buf, "%s\n", uacce->algs); 322 } 323 324 static ssize_t region_mmio_size_show(struct device *dev, 325 struct device_attribute *attr, char *buf) 326 { 327 struct uacce_device *uacce = to_uacce_device(dev); 328 329 return sprintf(buf, "%lu\n", 330 uacce->qf_pg_num[UACCE_QFRT_MMIO] << PAGE_SHIFT); 331 } 332 333 static ssize_t region_dus_size_show(struct device *dev, 334 struct device_attribute *attr, char *buf) 335 { 336 struct uacce_device *uacce = to_uacce_device(dev); 337 338 return sprintf(buf, "%lu\n", 339 uacce->qf_pg_num[UACCE_QFRT_DUS] << PAGE_SHIFT); 340 } 341 342 static DEVICE_ATTR_RO(api); 343 static DEVICE_ATTR_RO(flags); 344 static DEVICE_ATTR_RO(available_instances); 345 static DEVICE_ATTR_RO(algorithms); 346 static DEVICE_ATTR_RO(region_mmio_size); 347 static DEVICE_ATTR_RO(region_dus_size); 348 349 static struct attribute *uacce_dev_attrs[] = { 350 &dev_attr_api.attr, 351 &dev_attr_flags.attr, 352 &dev_attr_available_instances.attr, 353 &dev_attr_algorithms.attr, 354 &dev_attr_region_mmio_size.attr, 355 &dev_attr_region_dus_size.attr, 356 NULL, 357 }; 358 359 static umode_t uacce_dev_is_visible(struct kobject *kobj, 360 struct attribute *attr, int n) 361 { 362 struct device *dev = kobj_to_dev(kobj); 363 struct uacce_device *uacce = to_uacce_device(dev); 364 365 if (((attr == &dev_attr_region_mmio_size.attr) && 366 (!uacce->qf_pg_num[UACCE_QFRT_MMIO])) || 367 ((attr == &dev_attr_region_dus_size.attr) && 368 (!uacce->qf_pg_num[UACCE_QFRT_DUS]))) 369 return 0; 370 371 return attr->mode; 372 } 373 374 static struct attribute_group uacce_dev_group = { 375 .is_visible = uacce_dev_is_visible, 376 .attrs = uacce_dev_attrs, 377 }; 378 379 __ATTRIBUTE_GROUPS(uacce_dev); 380 381 static void uacce_release(struct device *dev) 382 { 383 struct uacce_device *uacce = to_uacce_device(dev); 384 385 kfree(uacce); 386 } 387 388 /** 389 * uacce_alloc() - alloc an accelerator 390 * @parent: pointer of uacce parent device 391 * @interface: pointer of uacce_interface for register 392 * 393 * Returns uacce pointer if success and ERR_PTR if not 394 * Need check returned negotiated uacce->flags 395 */ 396 struct uacce_device *uacce_alloc(struct device *parent, 397 struct uacce_interface *interface) 398 { 399 unsigned int flags = interface->flags; 400 struct uacce_device *uacce; 401 int ret; 402 403 uacce = kzalloc(sizeof(struct uacce_device), GFP_KERNEL); 404 if (!uacce) 405 return ERR_PTR(-ENOMEM); 406 407 if (flags & UACCE_DEV_SVA) { 408 ret = iommu_dev_enable_feature(parent, IOMMU_DEV_FEAT_SVA); 409 if (ret) 410 flags &= ~UACCE_DEV_SVA; 411 } 412 413 uacce->parent = parent; 414 uacce->flags = flags; 415 uacce->ops = interface->ops; 416 417 ret = xa_alloc(&uacce_xa, &uacce->dev_id, uacce, xa_limit_32b, 418 GFP_KERNEL); 419 if (ret < 0) 420 goto err_with_uacce; 421 422 INIT_LIST_HEAD(&uacce->queues); 423 mutex_init(&uacce->queues_lock); 424 device_initialize(&uacce->dev); 425 uacce->dev.devt = MKDEV(MAJOR(uacce_devt), uacce->dev_id); 426 uacce->dev.class = uacce_class; 427 uacce->dev.groups = uacce_dev_groups; 428 uacce->dev.parent = uacce->parent; 429 uacce->dev.release = uacce_release; 430 dev_set_name(&uacce->dev, "%s-%d", interface->name, uacce->dev_id); 431 432 return uacce; 433 434 err_with_uacce: 435 if (flags & UACCE_DEV_SVA) 436 iommu_dev_disable_feature(uacce->parent, IOMMU_DEV_FEAT_SVA); 437 kfree(uacce); 438 return ERR_PTR(ret); 439 } 440 EXPORT_SYMBOL_GPL(uacce_alloc); 441 442 /** 443 * uacce_register() - add the accelerator to cdev and export to user space 444 * @uacce: The initialized uacce device 445 * 446 * Return 0 if register succeeded, or an error. 447 */ 448 int uacce_register(struct uacce_device *uacce) 449 { 450 if (!uacce) 451 return -ENODEV; 452 453 uacce->cdev = cdev_alloc(); 454 if (!uacce->cdev) 455 return -ENOMEM; 456 457 uacce->cdev->ops = &uacce_fops; 458 uacce->cdev->owner = THIS_MODULE; 459 460 return cdev_device_add(uacce->cdev, &uacce->dev); 461 } 462 EXPORT_SYMBOL_GPL(uacce_register); 463 464 /** 465 * uacce_remove() - remove the accelerator 466 * @uacce: the accelerator to remove 467 */ 468 void uacce_remove(struct uacce_device *uacce) 469 { 470 struct uacce_queue *q, *next_q; 471 472 if (!uacce) 473 return; 474 /* 475 * unmap remaining mapping from user space, preventing user still 476 * access the mmaped area while parent device is already removed 477 */ 478 if (uacce->inode) 479 unmap_mapping_range(uacce->inode->i_mapping, 0, 0, 1); 480 481 /* ensure no open queue remains */ 482 mutex_lock(&uacce->queues_lock); 483 list_for_each_entry_safe(q, next_q, &uacce->queues, list) { 484 uacce_put_queue(q); 485 uacce_unbind_queue(q); 486 } 487 mutex_unlock(&uacce->queues_lock); 488 489 /* disable sva now since no opened queues */ 490 if (uacce->flags & UACCE_DEV_SVA) 491 iommu_dev_disable_feature(uacce->parent, IOMMU_DEV_FEAT_SVA); 492 493 if (uacce->cdev) 494 cdev_device_del(uacce->cdev, &uacce->dev); 495 xa_erase(&uacce_xa, uacce->dev_id); 496 put_device(&uacce->dev); 497 } 498 EXPORT_SYMBOL_GPL(uacce_remove); 499 500 static int __init uacce_init(void) 501 { 502 int ret; 503 504 uacce_class = class_create(THIS_MODULE, UACCE_NAME); 505 if (IS_ERR(uacce_class)) 506 return PTR_ERR(uacce_class); 507 508 ret = alloc_chrdev_region(&uacce_devt, 0, MINORMASK, UACCE_NAME); 509 if (ret) 510 class_destroy(uacce_class); 511 512 return ret; 513 } 514 515 static __exit void uacce_exit(void) 516 { 517 unregister_chrdev_region(uacce_devt, MINORMASK); 518 class_destroy(uacce_class); 519 } 520 521 subsys_initcall(uacce_init); 522 module_exit(uacce_exit); 523 524 MODULE_LICENSE("GPL"); 525 MODULE_AUTHOR("HiSilicon Tech. Co., Ltd."); 526 MODULE_DESCRIPTION("Accelerator interface for Userland applications"); 527