1 /* exynos_drm_gem.c 2 * 3 * Copyright (c) 2011 Samsung Electronics Co., Ltd. 4 * Author: Inki Dae <inki.dae@samsung.com> 5 * 6 * This program is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License as published by the 8 * Free Software Foundation; either version 2 of the License, or (at your 9 * option) any later version. 10 */ 11 12 #include <drm/drmP.h> 13 #include <drm/drm_vma_manager.h> 14 15 #include <linux/shmem_fs.h> 16 #include <linux/dma-buf.h> 17 #include <linux/pfn_t.h> 18 #include <drm/exynos_drm.h> 19 20 #include "exynos_drm_drv.h" 21 #include "exynos_drm_gem.h" 22 #include "exynos_drm_iommu.h" 23 24 static int exynos_drm_alloc_buf(struct exynos_drm_gem *exynos_gem) 25 { 26 struct drm_device *dev = exynos_gem->base.dev; 27 unsigned long attr; 28 unsigned int nr_pages; 29 struct sg_table sgt; 30 int ret = -ENOMEM; 31 32 if (exynos_gem->dma_addr) { 33 DRM_DEBUG_KMS("already allocated.\n"); 34 return 0; 35 } 36 37 exynos_gem->dma_attrs = 0; 38 39 /* 40 * if EXYNOS_BO_CONTIG, fully physically contiguous memory 41 * region will be allocated else physically contiguous 42 * as possible. 43 */ 44 if (!(exynos_gem->flags & EXYNOS_BO_NONCONTIG)) 45 exynos_gem->dma_attrs |= DMA_ATTR_FORCE_CONTIGUOUS; 46 47 /* 48 * if EXYNOS_BO_WC or EXYNOS_BO_NONCACHABLE, writecombine mapping 49 * else cachable mapping. 50 */ 51 if (exynos_gem->flags & EXYNOS_BO_WC || 52 !(exynos_gem->flags & EXYNOS_BO_CACHABLE)) 53 attr = DMA_ATTR_WRITE_COMBINE; 54 else 55 attr = DMA_ATTR_NON_CONSISTENT; 56 57 exynos_gem->dma_attrs |= attr; 58 exynos_gem->dma_attrs |= DMA_ATTR_NO_KERNEL_MAPPING; 59 60 nr_pages = exynos_gem->size >> PAGE_SHIFT; 61 62 exynos_gem->pages = drm_calloc_large(nr_pages, sizeof(struct page *)); 63 if (!exynos_gem->pages) { 64 DRM_ERROR("failed to allocate pages.\n"); 65 return -ENOMEM; 66 } 67 68 exynos_gem->cookie = dma_alloc_attrs(to_dma_dev(dev), exynos_gem->size, 69 &exynos_gem->dma_addr, GFP_KERNEL, 70 exynos_gem->dma_attrs); 71 if (!exynos_gem->cookie) { 72 DRM_ERROR("failed to allocate buffer.\n"); 73 goto err_free; 74 } 75 76 ret = dma_get_sgtable_attrs(to_dma_dev(dev), &sgt, exynos_gem->cookie, 77 exynos_gem->dma_addr, exynos_gem->size, 78 exynos_gem->dma_attrs); 79 if (ret < 0) { 80 DRM_ERROR("failed to get sgtable.\n"); 81 goto err_dma_free; 82 } 83 84 if (drm_prime_sg_to_page_addr_arrays(&sgt, exynos_gem->pages, NULL, 85 nr_pages)) { 86 DRM_ERROR("invalid sgtable.\n"); 87 ret = -EINVAL; 88 goto err_sgt_free; 89 } 90 91 sg_free_table(&sgt); 92 93 DRM_DEBUG_KMS("dma_addr(0x%lx), size(0x%lx)\n", 94 (unsigned long)exynos_gem->dma_addr, exynos_gem->size); 95 96 return 0; 97 98 err_sgt_free: 99 sg_free_table(&sgt); 100 err_dma_free: 101 dma_free_attrs(to_dma_dev(dev), exynos_gem->size, exynos_gem->cookie, 102 exynos_gem->dma_addr, exynos_gem->dma_attrs); 103 err_free: 104 drm_free_large(exynos_gem->pages); 105 106 return ret; 107 } 108 109 static void exynos_drm_free_buf(struct exynos_drm_gem *exynos_gem) 110 { 111 struct drm_device *dev = exynos_gem->base.dev; 112 113 if (!exynos_gem->dma_addr) { 114 DRM_DEBUG_KMS("dma_addr is invalid.\n"); 115 return; 116 } 117 118 DRM_DEBUG_KMS("dma_addr(0x%lx), size(0x%lx)\n", 119 (unsigned long)exynos_gem->dma_addr, exynos_gem->size); 120 121 dma_free_attrs(to_dma_dev(dev), exynos_gem->size, exynos_gem->cookie, 122 (dma_addr_t)exynos_gem->dma_addr, 123 exynos_gem->dma_attrs); 124 125 drm_free_large(exynos_gem->pages); 126 } 127 128 static int exynos_drm_gem_handle_create(struct drm_gem_object *obj, 129 struct drm_file *file_priv, 130 unsigned int *handle) 131 { 132 int ret; 133 134 /* 135 * allocate a id of idr table where the obj is registered 136 * and handle has the id what user can see. 137 */ 138 ret = drm_gem_handle_create(file_priv, obj, handle); 139 if (ret) 140 return ret; 141 142 DRM_DEBUG_KMS("gem handle = 0x%x\n", *handle); 143 144 /* drop reference from allocate - handle holds it now. */ 145 drm_gem_object_unreference_unlocked(obj); 146 147 return 0; 148 } 149 150 void exynos_drm_gem_destroy(struct exynos_drm_gem *exynos_gem) 151 { 152 struct drm_gem_object *obj = &exynos_gem->base; 153 154 DRM_DEBUG_KMS("handle count = %d\n", obj->handle_count); 155 156 /* 157 * do not release memory region from exporter. 158 * 159 * the region will be released by exporter 160 * once dmabuf's refcount becomes 0. 161 */ 162 if (obj->import_attach) 163 drm_prime_gem_destroy(obj, exynos_gem->sgt); 164 else 165 exynos_drm_free_buf(exynos_gem); 166 167 /* release file pointer to gem object. */ 168 drm_gem_object_release(obj); 169 170 kfree(exynos_gem); 171 } 172 173 unsigned long exynos_drm_gem_get_size(struct drm_device *dev, 174 unsigned int gem_handle, 175 struct drm_file *file_priv) 176 { 177 struct exynos_drm_gem *exynos_gem; 178 struct drm_gem_object *obj; 179 180 obj = drm_gem_object_lookup(file_priv, gem_handle); 181 if (!obj) { 182 DRM_ERROR("failed to lookup gem object.\n"); 183 return 0; 184 } 185 186 exynos_gem = to_exynos_gem(obj); 187 188 drm_gem_object_unreference_unlocked(obj); 189 190 return exynos_gem->size; 191 } 192 193 static struct exynos_drm_gem *exynos_drm_gem_init(struct drm_device *dev, 194 unsigned long size) 195 { 196 struct exynos_drm_gem *exynos_gem; 197 struct drm_gem_object *obj; 198 int ret; 199 200 exynos_gem = kzalloc(sizeof(*exynos_gem), GFP_KERNEL); 201 if (!exynos_gem) 202 return ERR_PTR(-ENOMEM); 203 204 exynos_gem->size = size; 205 obj = &exynos_gem->base; 206 207 ret = drm_gem_object_init(dev, obj, size); 208 if (ret < 0) { 209 DRM_ERROR("failed to initialize gem object\n"); 210 kfree(exynos_gem); 211 return ERR_PTR(ret); 212 } 213 214 ret = drm_gem_create_mmap_offset(obj); 215 if (ret < 0) { 216 drm_gem_object_release(obj); 217 kfree(exynos_gem); 218 return ERR_PTR(ret); 219 } 220 221 DRM_DEBUG_KMS("created file object = %pK\n", obj->filp); 222 223 return exynos_gem; 224 } 225 226 struct exynos_drm_gem *exynos_drm_gem_create(struct drm_device *dev, 227 unsigned int flags, 228 unsigned long size) 229 { 230 struct exynos_drm_gem *exynos_gem; 231 int ret; 232 233 if (flags & ~(EXYNOS_BO_MASK)) { 234 DRM_ERROR("invalid GEM buffer flags: %u\n", flags); 235 return ERR_PTR(-EINVAL); 236 } 237 238 if (!size) { 239 DRM_ERROR("invalid GEM buffer size: %lu\n", size); 240 return ERR_PTR(-EINVAL); 241 } 242 243 size = roundup(size, PAGE_SIZE); 244 245 exynos_gem = exynos_drm_gem_init(dev, size); 246 if (IS_ERR(exynos_gem)) 247 return exynos_gem; 248 249 /* set memory type and cache attribute from user side. */ 250 exynos_gem->flags = flags; 251 252 ret = exynos_drm_alloc_buf(exynos_gem); 253 if (ret < 0) { 254 drm_gem_object_release(&exynos_gem->base); 255 kfree(exynos_gem); 256 return ERR_PTR(ret); 257 } 258 259 return exynos_gem; 260 } 261 262 int exynos_drm_gem_create_ioctl(struct drm_device *dev, void *data, 263 struct drm_file *file_priv) 264 { 265 struct drm_exynos_gem_create *args = data; 266 struct exynos_drm_gem *exynos_gem; 267 int ret; 268 269 exynos_gem = exynos_drm_gem_create(dev, args->flags, args->size); 270 if (IS_ERR(exynos_gem)) 271 return PTR_ERR(exynos_gem); 272 273 ret = exynos_drm_gem_handle_create(&exynos_gem->base, file_priv, 274 &args->handle); 275 if (ret) { 276 exynos_drm_gem_destroy(exynos_gem); 277 return ret; 278 } 279 280 return 0; 281 } 282 283 int exynos_drm_gem_map_ioctl(struct drm_device *dev, void *data, 284 struct drm_file *file_priv) 285 { 286 struct drm_exynos_gem_map *args = data; 287 288 return exynos_drm_gem_dumb_map_offset(file_priv, dev, args->handle, 289 &args->offset); 290 } 291 292 dma_addr_t *exynos_drm_gem_get_dma_addr(struct drm_device *dev, 293 unsigned int gem_handle, 294 struct drm_file *filp) 295 { 296 struct exynos_drm_gem *exynos_gem; 297 struct drm_gem_object *obj; 298 299 obj = drm_gem_object_lookup(filp, gem_handle); 300 if (!obj) { 301 DRM_ERROR("failed to lookup gem object.\n"); 302 return ERR_PTR(-EINVAL); 303 } 304 305 exynos_gem = to_exynos_gem(obj); 306 307 return &exynos_gem->dma_addr; 308 } 309 310 void exynos_drm_gem_put_dma_addr(struct drm_device *dev, 311 unsigned int gem_handle, 312 struct drm_file *filp) 313 { 314 struct drm_gem_object *obj; 315 316 obj = drm_gem_object_lookup(filp, gem_handle); 317 if (!obj) { 318 DRM_ERROR("failed to lookup gem object.\n"); 319 return; 320 } 321 322 drm_gem_object_unreference_unlocked(obj); 323 324 /* 325 * decrease obj->refcount one more time because we has already 326 * increased it at exynos_drm_gem_get_dma_addr(). 327 */ 328 drm_gem_object_unreference_unlocked(obj); 329 } 330 331 static int exynos_drm_gem_mmap_buffer(struct exynos_drm_gem *exynos_gem, 332 struct vm_area_struct *vma) 333 { 334 struct drm_device *drm_dev = exynos_gem->base.dev; 335 unsigned long vm_size; 336 int ret; 337 338 vma->vm_flags &= ~VM_PFNMAP; 339 vma->vm_pgoff = 0; 340 341 vm_size = vma->vm_end - vma->vm_start; 342 343 /* check if user-requested size is valid. */ 344 if (vm_size > exynos_gem->size) 345 return -EINVAL; 346 347 ret = dma_mmap_attrs(to_dma_dev(drm_dev), vma, exynos_gem->cookie, 348 exynos_gem->dma_addr, exynos_gem->size, 349 exynos_gem->dma_attrs); 350 if (ret < 0) { 351 DRM_ERROR("failed to mmap.\n"); 352 return ret; 353 } 354 355 return 0; 356 } 357 358 int exynos_drm_gem_get_ioctl(struct drm_device *dev, void *data, 359 struct drm_file *file_priv) 360 { 361 struct exynos_drm_gem *exynos_gem; 362 struct drm_exynos_gem_info *args = data; 363 struct drm_gem_object *obj; 364 365 obj = drm_gem_object_lookup(file_priv, args->handle); 366 if (!obj) { 367 DRM_ERROR("failed to lookup gem object.\n"); 368 return -EINVAL; 369 } 370 371 exynos_gem = to_exynos_gem(obj); 372 373 args->flags = exynos_gem->flags; 374 args->size = exynos_gem->size; 375 376 drm_gem_object_unreference_unlocked(obj); 377 378 return 0; 379 } 380 381 void exynos_drm_gem_free_object(struct drm_gem_object *obj) 382 { 383 exynos_drm_gem_destroy(to_exynos_gem(obj)); 384 } 385 386 int exynos_drm_gem_dumb_create(struct drm_file *file_priv, 387 struct drm_device *dev, 388 struct drm_mode_create_dumb *args) 389 { 390 struct exynos_drm_gem *exynos_gem; 391 unsigned int flags; 392 int ret; 393 394 /* 395 * allocate memory to be used for framebuffer. 396 * - this callback would be called by user application 397 * with DRM_IOCTL_MODE_CREATE_DUMB command. 398 */ 399 400 args->pitch = args->width * ((args->bpp + 7) / 8); 401 args->size = args->pitch * args->height; 402 403 if (is_drm_iommu_supported(dev)) 404 flags = EXYNOS_BO_NONCONTIG | EXYNOS_BO_WC; 405 else 406 flags = EXYNOS_BO_CONTIG | EXYNOS_BO_WC; 407 408 exynos_gem = exynos_drm_gem_create(dev, flags, args->size); 409 if (IS_ERR(exynos_gem)) { 410 dev_warn(dev->dev, "FB allocation failed.\n"); 411 return PTR_ERR(exynos_gem); 412 } 413 414 ret = exynos_drm_gem_handle_create(&exynos_gem->base, file_priv, 415 &args->handle); 416 if (ret) { 417 exynos_drm_gem_destroy(exynos_gem); 418 return ret; 419 } 420 421 return 0; 422 } 423 424 int exynos_drm_gem_dumb_map_offset(struct drm_file *file_priv, 425 struct drm_device *dev, uint32_t handle, 426 uint64_t *offset) 427 { 428 struct drm_gem_object *obj; 429 int ret = 0; 430 431 /* 432 * get offset of memory allocated for drm framebuffer. 433 * - this callback would be called by user application 434 * with DRM_IOCTL_MODE_MAP_DUMB command. 435 */ 436 437 obj = drm_gem_object_lookup(file_priv, handle); 438 if (!obj) { 439 DRM_ERROR("failed to lookup gem object.\n"); 440 return -EINVAL; 441 } 442 443 *offset = drm_vma_node_offset_addr(&obj->vma_node); 444 DRM_DEBUG_KMS("offset = 0x%lx\n", (unsigned long)*offset); 445 446 drm_gem_object_unreference_unlocked(obj); 447 return ret; 448 } 449 450 int exynos_drm_gem_fault(struct vm_fault *vmf) 451 { 452 struct vm_area_struct *vma = vmf->vma; 453 struct drm_gem_object *obj = vma->vm_private_data; 454 struct exynos_drm_gem *exynos_gem = to_exynos_gem(obj); 455 unsigned long pfn; 456 pgoff_t page_offset; 457 int ret; 458 459 page_offset = (vmf->address - vma->vm_start) >> PAGE_SHIFT; 460 461 if (page_offset >= (exynos_gem->size >> PAGE_SHIFT)) { 462 DRM_ERROR("invalid page offset\n"); 463 ret = -EINVAL; 464 goto out; 465 } 466 467 pfn = page_to_pfn(exynos_gem->pages[page_offset]); 468 ret = vm_insert_mixed(vma, vmf->address, __pfn_to_pfn_t(pfn, PFN_DEV)); 469 470 out: 471 switch (ret) { 472 case 0: 473 case -ERESTARTSYS: 474 case -EINTR: 475 return VM_FAULT_NOPAGE; 476 case -ENOMEM: 477 return VM_FAULT_OOM; 478 default: 479 return VM_FAULT_SIGBUS; 480 } 481 } 482 483 static int exynos_drm_gem_mmap_obj(struct drm_gem_object *obj, 484 struct vm_area_struct *vma) 485 { 486 struct exynos_drm_gem *exynos_gem = to_exynos_gem(obj); 487 int ret; 488 489 DRM_DEBUG_KMS("flags = 0x%x\n", exynos_gem->flags); 490 491 /* non-cachable as default. */ 492 if (exynos_gem->flags & EXYNOS_BO_CACHABLE) 493 vma->vm_page_prot = vm_get_page_prot(vma->vm_flags); 494 else if (exynos_gem->flags & EXYNOS_BO_WC) 495 vma->vm_page_prot = 496 pgprot_writecombine(vm_get_page_prot(vma->vm_flags)); 497 else 498 vma->vm_page_prot = 499 pgprot_noncached(vm_get_page_prot(vma->vm_flags)); 500 501 ret = exynos_drm_gem_mmap_buffer(exynos_gem, vma); 502 if (ret) 503 goto err_close_vm; 504 505 return ret; 506 507 err_close_vm: 508 drm_gem_vm_close(vma); 509 510 return ret; 511 } 512 513 int exynos_drm_gem_mmap(struct file *filp, struct vm_area_struct *vma) 514 { 515 struct drm_gem_object *obj; 516 int ret; 517 518 /* set vm_area_struct. */ 519 ret = drm_gem_mmap(filp, vma); 520 if (ret < 0) { 521 DRM_ERROR("failed to mmap.\n"); 522 return ret; 523 } 524 525 obj = vma->vm_private_data; 526 527 if (obj->import_attach) 528 return dma_buf_mmap(obj->dma_buf, vma, 0); 529 530 return exynos_drm_gem_mmap_obj(obj, vma); 531 } 532 533 /* low-level interface prime helpers */ 534 struct sg_table *exynos_drm_gem_prime_get_sg_table(struct drm_gem_object *obj) 535 { 536 struct exynos_drm_gem *exynos_gem = to_exynos_gem(obj); 537 int npages; 538 539 npages = exynos_gem->size >> PAGE_SHIFT; 540 541 return drm_prime_pages_to_sg(exynos_gem->pages, npages); 542 } 543 544 struct drm_gem_object * 545 exynos_drm_gem_prime_import_sg_table(struct drm_device *dev, 546 struct dma_buf_attachment *attach, 547 struct sg_table *sgt) 548 { 549 struct exynos_drm_gem *exynos_gem; 550 int npages; 551 int ret; 552 553 exynos_gem = exynos_drm_gem_init(dev, attach->dmabuf->size); 554 if (IS_ERR(exynos_gem)) { 555 ret = PTR_ERR(exynos_gem); 556 return ERR_PTR(ret); 557 } 558 559 exynos_gem->dma_addr = sg_dma_address(sgt->sgl); 560 561 npages = exynos_gem->size >> PAGE_SHIFT; 562 exynos_gem->pages = drm_malloc_ab(npages, sizeof(struct page *)); 563 if (!exynos_gem->pages) { 564 ret = -ENOMEM; 565 goto err; 566 } 567 568 ret = drm_prime_sg_to_page_addr_arrays(sgt, exynos_gem->pages, NULL, 569 npages); 570 if (ret < 0) 571 goto err_free_large; 572 573 exynos_gem->sgt = sgt; 574 575 if (sgt->nents == 1) { 576 /* always physically continuous memory if sgt->nents is 1. */ 577 exynos_gem->flags |= EXYNOS_BO_CONTIG; 578 } else { 579 /* 580 * this case could be CONTIG or NONCONTIG type but for now 581 * sets NONCONTIG. 582 * TODO. we have to find a way that exporter can notify 583 * the type of its own buffer to importer. 584 */ 585 exynos_gem->flags |= EXYNOS_BO_NONCONTIG; 586 } 587 588 return &exynos_gem->base; 589 590 err_free_large: 591 drm_free_large(exynos_gem->pages); 592 err: 593 drm_gem_object_release(&exynos_gem->base); 594 kfree(exynos_gem); 595 return ERR_PTR(ret); 596 } 597 598 void *exynos_drm_gem_prime_vmap(struct drm_gem_object *obj) 599 { 600 return NULL; 601 } 602 603 void exynos_drm_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr) 604 { 605 /* Nothing to do */ 606 } 607 608 int exynos_drm_gem_prime_mmap(struct drm_gem_object *obj, 609 struct vm_area_struct *vma) 610 { 611 int ret; 612 613 ret = drm_gem_mmap_obj(obj, obj->size, vma); 614 if (ret < 0) 615 return ret; 616 617 return exynos_drm_gem_mmap_obj(obj, vma); 618 } 619