Lines Matching +full:cpu +full:- +full:release +full:- +full:addr
1 // SPDX-License-Identifier: GPL-2.0-only
6 #include <linux/dma-buf.h>
7 #include <linux/dma-mapping.h>
20 struct drm_gem_object *gobj = vmf->vma->vm_private_data; in armada_gem_vm_fault()
22 unsigned long pfn = obj->phys_addr >> PAGE_SHIFT; in armada_gem_vm_fault()
24 pfn += (vmf->address - vmf->vma->vm_start) >> PAGE_SHIFT; in armada_gem_vm_fault()
25 return vmf_insert_pfn(vmf->vma, vmf->address, pfn); in armada_gem_vm_fault()
42 struct armada_private *priv = drm_to_armada_dev(obj->dev); in armada_gem_free_object()
44 DRM_DEBUG_DRIVER("release obj %p\n", dobj); in armada_gem_free_object()
46 drm_gem_free_mmap_offset(&dobj->obj); in armada_gem_free_object()
48 might_lock(&priv->linear_lock); in armada_gem_free_object()
50 if (dobj->page) { in armada_gem_free_object()
52 unsigned int order = get_order(dobj->obj.size); in armada_gem_free_object()
53 __free_pages(dobj->page, order); in armada_gem_free_object()
54 } else if (dobj->linear) { in armada_gem_free_object()
56 mutex_lock(&priv->linear_lock); in armada_gem_free_object()
57 drm_mm_remove_node(dobj->linear); in armada_gem_free_object()
58 mutex_unlock(&priv->linear_lock); in armada_gem_free_object()
59 kfree(dobj->linear); in armada_gem_free_object()
60 if (dobj->addr) in armada_gem_free_object()
61 iounmap(dobj->addr); in armada_gem_free_object()
64 if (dobj->obj.import_attach) { in armada_gem_free_object()
66 if (dobj->sgt) in armada_gem_free_object()
67 dma_buf_unmap_attachment(dobj->obj.import_attach, in armada_gem_free_object()
68 dobj->sgt, DMA_TO_DEVICE); in armada_gem_free_object()
69 drm_prime_gem_destroy(&dobj->obj, NULL); in armada_gem_free_object()
72 drm_gem_object_release(&dobj->obj); in armada_gem_free_object()
81 size_t size = obj->obj.size; in armada_gem_linear_back()
83 if (obj->page || obj->linear) in armada_gem_linear_back()
91 * only accessed by the CPU so we don't need any special handing in armada_gem_linear_back()
99 obj->addr = page_address(p); in armada_gem_linear_back()
100 obj->phys_addr = page_to_phys(p); in armada_gem_linear_back()
101 obj->page = p; in armada_gem_linear_back()
103 memset(obj->addr, 0, PAGE_ALIGN(size)); in armada_gem_linear_back()
112 * with an CPU virtual address and a device address. in armada_gem_linear_back()
114 * The CPU virtual address may be either an address in the kernel in armada_gem_linear_back()
124 * unsafe to re-use as a physical address. in armada_gem_linear_back()
131 if (!obj->page) { in armada_gem_linear_back()
139 return -ENOSPC; in armada_gem_linear_back()
141 mutex_lock(&priv->linear_lock); in armada_gem_linear_back()
142 ret = drm_mm_insert_node_generic(&priv->linear, node, in armada_gem_linear_back()
144 mutex_unlock(&priv->linear_lock); in armada_gem_linear_back()
150 obj->linear = node; in armada_gem_linear_back()
153 ptr = ioremap_wc(obj->linear->start, size); in armada_gem_linear_back()
155 mutex_lock(&priv->linear_lock); in armada_gem_linear_back()
156 drm_mm_remove_node(obj->linear); in armada_gem_linear_back()
157 mutex_unlock(&priv->linear_lock); in armada_gem_linear_back()
158 kfree(obj->linear); in armada_gem_linear_back()
159 obj->linear = NULL; in armada_gem_linear_back()
160 return -ENOMEM; in armada_gem_linear_back()
166 obj->phys_addr = obj->linear->start; in armada_gem_linear_back()
167 obj->dev_addr = obj->linear->start; in armada_gem_linear_back()
168 obj->mapped = true; in armada_gem_linear_back()
172 (unsigned long long)obj->phys_addr, in armada_gem_linear_back()
173 (unsigned long long)obj->dev_addr); in armada_gem_linear_back()
182 if (!dobj->addr && dobj->linear) in armada_gem_map_object()
183 dobj->addr = ioremap_wc(dobj->phys_addr, dobj->obj.size); in armada_gem_map_object()
184 return dobj->addr; in armada_gem_map_object()
198 drm_gem_private_object_init(dev, &obj->obj, size); in armada_gem_alloc_private_object()
217 if (drm_gem_object_init(dev, &obj->obj, size)) { in armada_gem_alloc_object()
222 mapping = obj->obj.filp->f_mapping; in armada_gem_alloc_object()
239 args->pitch = armada_pitch(args->width, args->bpp); in armada_gem_dumb_create()
240 args->size = size = args->pitch * args->height; in armada_gem_dumb_create()
244 return -ENOMEM; in armada_gem_dumb_create()
250 ret = drm_gem_handle_create(file, &dobj->obj, &handle); in armada_gem_dumb_create()
254 args->handle = handle; in armada_gem_dumb_create()
256 /* drop reference from allocate - handle holds it now */ in armada_gem_dumb_create()
259 drm_gem_object_put(&dobj->obj); in armada_gem_dumb_create()
273 if (args->size == 0) in armada_gem_create_ioctl()
274 return -ENOMEM; in armada_gem_create_ioctl()
276 size = args->size; in armada_gem_create_ioctl()
280 return -ENOMEM; in armada_gem_create_ioctl()
282 ret = drm_gem_handle_create(file, &dobj->obj, &handle); in armada_gem_create_ioctl()
286 args->handle = handle; in armada_gem_create_ioctl()
288 /* drop reference from allocate - handle holds it now */ in armada_gem_create_ioctl()
291 drm_gem_object_put(&dobj->obj); in armada_gem_create_ioctl()
295 /* Map a shmem-backed object into process memory space */
301 unsigned long addr; in armada_gem_mmap_ioctl() local
303 dobj = armada_gem_object_lookup(file, args->handle); in armada_gem_mmap_ioctl()
305 return -ENOENT; in armada_gem_mmap_ioctl()
307 if (!dobj->obj.filp) { in armada_gem_mmap_ioctl()
308 drm_gem_object_put(&dobj->obj); in armada_gem_mmap_ioctl()
309 return -EINVAL; in armada_gem_mmap_ioctl()
312 addr = vm_mmap(dobj->obj.filp, 0, args->size, PROT_READ | PROT_WRITE, in armada_gem_mmap_ioctl()
313 MAP_SHARED, args->offset); in armada_gem_mmap_ioctl()
314 drm_gem_object_put(&dobj->obj); in armada_gem_mmap_ioctl()
315 if (IS_ERR_VALUE(addr)) in armada_gem_mmap_ioctl()
316 return addr; in armada_gem_mmap_ioctl()
318 args->addr = addr; in armada_gem_mmap_ioctl()
332 args->handle, args->offset, args->size, args->ptr); in armada_gem_pwrite_ioctl()
334 if (args->size == 0) in armada_gem_pwrite_ioctl()
337 ptr = (char __user *)(uintptr_t)args->ptr; in armada_gem_pwrite_ioctl()
339 if (!access_ok(ptr, args->size)) in armada_gem_pwrite_ioctl()
340 return -EFAULT; in armada_gem_pwrite_ioctl()
342 ret = fault_in_pages_readable(ptr, args->size); in armada_gem_pwrite_ioctl()
346 dobj = armada_gem_object_lookup(file, args->handle); in armada_gem_pwrite_ioctl()
348 return -ENOENT; in armada_gem_pwrite_ioctl()
350 /* Must be a kernel-mapped object */ in armada_gem_pwrite_ioctl()
351 if (!dobj->addr) in armada_gem_pwrite_ioctl()
352 return -EINVAL; in armada_gem_pwrite_ioctl()
354 if (args->offset > dobj->obj.size || in armada_gem_pwrite_ioctl()
355 args->size > dobj->obj.size - args->offset) { in armada_gem_pwrite_ioctl()
356 DRM_ERROR("invalid size: object size %u\n", dobj->obj.size); in armada_gem_pwrite_ioctl()
357 ret = -EINVAL; in armada_gem_pwrite_ioctl()
361 if (copy_from_user(dobj->addr + args->offset, ptr, args->size)) { in armada_gem_pwrite_ioctl()
362 ret = -EFAULT; in armada_gem_pwrite_ioctl()
363 } else if (dobj->update) { in armada_gem_pwrite_ioctl()
364 dobj->update(dobj->update_data); in armada_gem_pwrite_ioctl()
369 drm_gem_object_put(&dobj->obj); in armada_gem_pwrite_ioctl()
378 struct drm_gem_object *obj = attach->dmabuf->priv; in armada_gem_prime_map_dma_buf()
388 if (dobj->obj.filp) { in armada_gem_prime_map_dma_buf()
392 count = dobj->obj.size / PAGE_SIZE; in armada_gem_prime_map_dma_buf()
396 mapping = dobj->obj.filp->f_mapping; in armada_gem_prime_map_dma_buf()
403 goto release; in armada_gem_prime_map_dma_buf()
408 if (dma_map_sgtable(attach->dev, sgt, dir, 0)) in armada_gem_prime_map_dma_buf()
409 goto release; in armada_gem_prime_map_dma_buf()
410 } else if (dobj->page) { in armada_gem_prime_map_dma_buf()
415 sg_set_page(sgt->sgl, dobj->page, dobj->obj.size, 0); in armada_gem_prime_map_dma_buf()
417 if (dma_map_sgtable(attach->dev, sgt, dir, 0)) in armada_gem_prime_map_dma_buf()
419 } else if (dobj->linear) { in armada_gem_prime_map_dma_buf()
420 /* Single contiguous physical region - no struct page */ in armada_gem_prime_map_dma_buf()
423 sg_dma_address(sgt->sgl) = dobj->dev_addr; in armada_gem_prime_map_dma_buf()
424 sg_dma_len(sgt->sgl) = dobj->obj.size; in armada_gem_prime_map_dma_buf()
430 release: in armada_gem_prime_map_dma_buf()
444 struct drm_gem_object *obj = attach->dmabuf->priv; in armada_gem_prime_unmap_dma_buf()
448 if (!dobj->linear) in armada_gem_prime_unmap_dma_buf()
449 dma_unmap_sgtable(attach->dev, sgt, dir, 0); in armada_gem_prime_unmap_dma_buf()
451 if (dobj->obj.filp) { in armada_gem_prime_unmap_dma_buf()
465 return -EINVAL; in armada_gem_dmabuf_mmap()
471 .release = drm_gem_dmabuf_release,
481 exp_info.size = obj->size; in armada_gem_prime_export()
485 return drm_gem_dmabuf_export(obj->dev, &exp_info); in armada_gem_prime_export()
494 if (buf->ops == &armada_gem_prime_dmabuf_ops) { in armada_gem_prime_import()
495 struct drm_gem_object *obj = buf->priv; in armada_gem_prime_import()
496 if (obj->dev == dev) { in armada_gem_prime_import()
506 attach = dma_buf_attach(buf, dev->dev); in armada_gem_prime_import()
510 dobj = armada_gem_alloc_private_object(dev, buf->size); in armada_gem_prime_import()
513 return ERR_PTR(-ENOMEM); in armada_gem_prime_import()
516 dobj->obj.import_attach = attach; in armada_gem_prime_import()
520 * Don't call dma_buf_map_attachment() here - it maps the in armada_gem_prime_import()
524 return &dobj->obj; in armada_gem_prime_import()
531 dobj->sgt = dma_buf_map_attachment(dobj->obj.import_attach, in armada_gem_map_import()
533 if (IS_ERR(dobj->sgt)) { in armada_gem_map_import()
534 ret = PTR_ERR(dobj->sgt); in armada_gem_map_import()
535 dobj->sgt = NULL; in armada_gem_map_import()
539 if (dobj->sgt->nents > 1) { in armada_gem_map_import()
541 return -EINVAL; in armada_gem_map_import()
543 if (sg_dma_len(dobj->sgt->sgl) < dobj->obj.size) { in armada_gem_map_import()
545 return -EINVAL; in armada_gem_map_import()
547 dobj->dev_addr = sg_dma_address(dobj->sgt->sgl); in armada_gem_map_import()
548 dobj->mapped = true; in armada_gem_map_import()