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 int 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 if (!uacce->ops->mmap) { 235 ret = -EINVAL; 236 goto out_with_lock; 237 } 238 239 ret = uacce->ops->mmap(q, vma, qfr); 240 if (ret) 241 goto out_with_lock; 242 243 break; 244 245 case UACCE_QFRT_DUS: 246 if (!uacce->ops->mmap) { 247 ret = -EINVAL; 248 goto out_with_lock; 249 } 250 251 ret = uacce->ops->mmap(q, vma, qfr); 252 if (ret) 253 goto out_with_lock; 254 break; 255 256 default: 257 ret = -EINVAL; 258 goto out_with_lock; 259 } 260 261 q->qfrs[type] = qfr; 262 mutex_unlock(&uacce_mutex); 263 264 return ret; 265 266 out_with_lock: 267 mutex_unlock(&uacce_mutex); 268 kfree(qfr); 269 return ret; 270 } 271 272 static __poll_t uacce_fops_poll(struct file *file, poll_table *wait) 273 { 274 struct uacce_queue *q = file->private_data; 275 struct uacce_device *uacce = q->uacce; 276 277 poll_wait(file, &q->wait, wait); 278 if (uacce->ops->is_q_updated && uacce->ops->is_q_updated(q)) 279 return EPOLLIN | EPOLLRDNORM; 280 281 return 0; 282 } 283 284 static const struct file_operations uacce_fops = { 285 .owner = THIS_MODULE, 286 .open = uacce_fops_open, 287 .release = uacce_fops_release, 288 .unlocked_ioctl = uacce_fops_unl_ioctl, 289 #ifdef CONFIG_COMPAT 290 .compat_ioctl = uacce_fops_compat_ioctl, 291 #endif 292 .mmap = uacce_fops_mmap, 293 .poll = uacce_fops_poll, 294 }; 295 296 #define to_uacce_device(dev) container_of(dev, struct uacce_device, dev) 297 298 static ssize_t api_show(struct device *dev, 299 struct device_attribute *attr, char *buf) 300 { 301 struct uacce_device *uacce = to_uacce_device(dev); 302 303 return sprintf(buf, "%s\n", uacce->api_ver); 304 } 305 306 static ssize_t flags_show(struct device *dev, 307 struct device_attribute *attr, char *buf) 308 { 309 struct uacce_device *uacce = to_uacce_device(dev); 310 311 return sprintf(buf, "%u\n", uacce->flags); 312 } 313 314 static ssize_t available_instances_show(struct device *dev, 315 struct device_attribute *attr, 316 char *buf) 317 { 318 struct uacce_device *uacce = to_uacce_device(dev); 319 320 if (!uacce->ops->get_available_instances) 321 return -ENODEV; 322 323 return sprintf(buf, "%d\n", 324 uacce->ops->get_available_instances(uacce)); 325 } 326 327 static ssize_t algorithms_show(struct device *dev, 328 struct device_attribute *attr, char *buf) 329 { 330 struct uacce_device *uacce = to_uacce_device(dev); 331 332 return sprintf(buf, "%s\n", uacce->algs); 333 } 334 335 static ssize_t region_mmio_size_show(struct device *dev, 336 struct device_attribute *attr, char *buf) 337 { 338 struct uacce_device *uacce = to_uacce_device(dev); 339 340 return sprintf(buf, "%lu\n", 341 uacce->qf_pg_num[UACCE_QFRT_MMIO] << PAGE_SHIFT); 342 } 343 344 static ssize_t region_dus_size_show(struct device *dev, 345 struct device_attribute *attr, char *buf) 346 { 347 struct uacce_device *uacce = to_uacce_device(dev); 348 349 return sprintf(buf, "%lu\n", 350 uacce->qf_pg_num[UACCE_QFRT_DUS] << PAGE_SHIFT); 351 } 352 353 static DEVICE_ATTR_RO(api); 354 static DEVICE_ATTR_RO(flags); 355 static DEVICE_ATTR_RO(available_instances); 356 static DEVICE_ATTR_RO(algorithms); 357 static DEVICE_ATTR_RO(region_mmio_size); 358 static DEVICE_ATTR_RO(region_dus_size); 359 360 static struct attribute *uacce_dev_attrs[] = { 361 &dev_attr_api.attr, 362 &dev_attr_flags.attr, 363 &dev_attr_available_instances.attr, 364 &dev_attr_algorithms.attr, 365 &dev_attr_region_mmio_size.attr, 366 &dev_attr_region_dus_size.attr, 367 NULL, 368 }; 369 370 static umode_t uacce_dev_is_visible(struct kobject *kobj, 371 struct attribute *attr, int n) 372 { 373 struct device *dev = container_of(kobj, struct device, kobj); 374 struct uacce_device *uacce = to_uacce_device(dev); 375 376 if (((attr == &dev_attr_region_mmio_size.attr) && 377 (!uacce->qf_pg_num[UACCE_QFRT_MMIO])) || 378 ((attr == &dev_attr_region_dus_size.attr) && 379 (!uacce->qf_pg_num[UACCE_QFRT_DUS]))) 380 return 0; 381 382 return attr->mode; 383 } 384 385 static struct attribute_group uacce_dev_group = { 386 .is_visible = uacce_dev_is_visible, 387 .attrs = uacce_dev_attrs, 388 }; 389 390 __ATTRIBUTE_GROUPS(uacce_dev); 391 392 static void uacce_release(struct device *dev) 393 { 394 struct uacce_device *uacce = to_uacce_device(dev); 395 396 kfree(uacce); 397 } 398 399 /** 400 * uacce_alloc() - alloc an accelerator 401 * @parent: pointer of uacce parent device 402 * @interface: pointer of uacce_interface for register 403 * 404 * Returns uacce pointer if success and ERR_PTR if not 405 * Need check returned negotiated uacce->flags 406 */ 407 struct uacce_device *uacce_alloc(struct device *parent, 408 struct uacce_interface *interface) 409 { 410 unsigned int flags = interface->flags; 411 struct uacce_device *uacce; 412 int ret; 413 414 uacce = kzalloc(sizeof(struct uacce_device), GFP_KERNEL); 415 if (!uacce) 416 return ERR_PTR(-ENOMEM); 417 418 if (flags & UACCE_DEV_SVA) { 419 ret = iommu_dev_enable_feature(parent, IOMMU_DEV_FEAT_SVA); 420 if (ret) 421 flags &= ~UACCE_DEV_SVA; 422 } 423 424 uacce->parent = parent; 425 uacce->flags = flags; 426 uacce->ops = interface->ops; 427 428 ret = xa_alloc(&uacce_xa, &uacce->dev_id, uacce, xa_limit_32b, 429 GFP_KERNEL); 430 if (ret < 0) 431 goto err_with_uacce; 432 433 INIT_LIST_HEAD(&uacce->queues); 434 mutex_init(&uacce->queues_lock); 435 device_initialize(&uacce->dev); 436 uacce->dev.devt = MKDEV(MAJOR(uacce_devt), uacce->dev_id); 437 uacce->dev.class = uacce_class; 438 uacce->dev.groups = uacce_dev_groups; 439 uacce->dev.parent = uacce->parent; 440 uacce->dev.release = uacce_release; 441 dev_set_name(&uacce->dev, "%s-%d", interface->name, uacce->dev_id); 442 443 return uacce; 444 445 err_with_uacce: 446 if (flags & UACCE_DEV_SVA) 447 iommu_dev_disable_feature(uacce->parent, IOMMU_DEV_FEAT_SVA); 448 kfree(uacce); 449 return ERR_PTR(ret); 450 } 451 EXPORT_SYMBOL_GPL(uacce_alloc); 452 453 /** 454 * uacce_register() - add the accelerator to cdev and export to user space 455 * @uacce: The initialized uacce device 456 * 457 * Return 0 if register succeeded, or an error. 458 */ 459 int uacce_register(struct uacce_device *uacce) 460 { 461 if (!uacce) 462 return -ENODEV; 463 464 uacce->cdev = cdev_alloc(); 465 if (!uacce->cdev) 466 return -ENOMEM; 467 468 uacce->cdev->ops = &uacce_fops; 469 uacce->cdev->owner = THIS_MODULE; 470 471 return cdev_device_add(uacce->cdev, &uacce->dev); 472 } 473 EXPORT_SYMBOL_GPL(uacce_register); 474 475 /** 476 * uacce_remove() - remove the accelerator 477 * @uacce: the accelerator to remove 478 */ 479 void uacce_remove(struct uacce_device *uacce) 480 { 481 struct uacce_queue *q, *next_q; 482 483 if (!uacce) 484 return; 485 /* 486 * unmap remaining mapping from user space, preventing user still 487 * access the mmaped area while parent device is already removed 488 */ 489 if (uacce->inode) 490 unmap_mapping_range(uacce->inode->i_mapping, 0, 0, 1); 491 492 /* ensure no open queue remains */ 493 mutex_lock(&uacce->queues_lock); 494 list_for_each_entry_safe(q, next_q, &uacce->queues, list) { 495 uacce_put_queue(q); 496 uacce_unbind_queue(q); 497 } 498 mutex_unlock(&uacce->queues_lock); 499 500 /* disable sva now since no opened queues */ 501 if (uacce->flags & UACCE_DEV_SVA) 502 iommu_dev_disable_feature(uacce->parent, IOMMU_DEV_FEAT_SVA); 503 504 if (uacce->cdev) 505 cdev_device_del(uacce->cdev, &uacce->dev); 506 xa_erase(&uacce_xa, uacce->dev_id); 507 put_device(&uacce->dev); 508 } 509 EXPORT_SYMBOL_GPL(uacce_remove); 510 511 static int __init uacce_init(void) 512 { 513 int ret; 514 515 uacce_class = class_create(THIS_MODULE, UACCE_NAME); 516 if (IS_ERR(uacce_class)) 517 return PTR_ERR(uacce_class); 518 519 ret = alloc_chrdev_region(&uacce_devt, 0, MINORMASK, UACCE_NAME); 520 if (ret) 521 class_destroy(uacce_class); 522 523 return ret; 524 } 525 526 static __exit void uacce_exit(void) 527 { 528 unregister_chrdev_region(uacce_devt, MINORMASK); 529 class_destroy(uacce_class); 530 } 531 532 subsys_initcall(uacce_init); 533 module_exit(uacce_exit); 534 535 MODULE_LICENSE("GPL"); 536 MODULE_AUTHOR("Hisilicon Tech. Co., Ltd."); 537 MODULE_DESCRIPTION("Accelerator interface for Userland applications"); 538