/** * tinydrm_gem_cma_prime_import_sg_table - Produce a CMA GEM object from * another driver's scatter/gather table of pinned pages * @drm: DRM device to import into * @attach: DMA-BUF attachment * @sgt: Scatter/gather table of pinned pages * * This function imports a scatter/gather table exported via DMA-BUF by * another driver using drm_gem_cma_prime_import_sg_table(). It sets the * kernel virtual address on the CMA object. Drivers should use this as their * &drm_driver->gem_prime_import_sg_table callback if they need the virtual * address. tinydrm_gem_cma_free_object() should be used in combination with * this function. * * Returns: * A pointer to a newly created GEM object or an ERR_PTR-encoded negative * error code on failure. */ struct drm_gem_object * tinydrm_gem_cma_prime_import_sg_table(struct drm_device *drm, struct dma_buf_attachment *attach, struct sg_table *sgt) { struct drm_gem_cma_object *cma_obj; struct drm_gem_object *obj; void *vaddr; vaddr = dma_buf_vmap(attach->dmabuf); if (!vaddr) { DRM_ERROR("Failed to vmap PRIME buffer\n"); return ERR_PTR(-ENOMEM); } obj = drm_gem_cma_prime_import_sg_table(drm, attach, sgt); if (IS_ERR(obj)) { dma_buf_vunmap(attach->dmabuf, vaddr); return obj; } cma_obj = to_drm_gem_cma_obj(obj); cma_obj->vaddr = vaddr; return obj; }
void udl_gem_vunmap(struct udl_gem_object *obj) { if (obj->base.import_attach) { dma_buf_vunmap(obj->base.import_attach->dmabuf, obj->vmapping); return; } vunmap(obj->vmapping); udl_gem_put_pages(obj); }
/** * tinydrm_gem_cma_free_object - Free resources associated with a CMA GEM * object * @gem_obj: GEM object to free * * This function frees the backing memory of the CMA GEM object, cleans up the * GEM object state and frees the memory used to store the object itself using * drm_gem_cma_free_object(). It also handles PRIME buffers which has the kernel * virtual address set by tinydrm_gem_cma_prime_import_sg_table(). Drivers * can use this as their &drm_driver->gem_free_object callback. */ void tinydrm_gem_cma_free_object(struct drm_gem_object *gem_obj) { if (gem_obj->import_attach) { struct drm_gem_cma_object *cma_obj; cma_obj = to_drm_gem_cma_obj(gem_obj); dma_buf_vunmap(gem_obj->import_attach->dmabuf, cma_obj->vaddr); cma_obj->vaddr = NULL; } drm_gem_cma_free_object(gem_obj); }
void udl_gem_vunmap(struct udl_gem_object *obj) { if (obj->base.import_attach) { dma_buf_vunmap(obj->base.import_attach->dmabuf, obj->vmapping); dma_buf_end_cpu_access(obj->base.import_attach->dmabuf, 0, obj->base.size, DMA_BIDIRECTIONAL); return; } if (obj->vmapping) vunmap(obj->vmapping); udl_gem_put_pages(obj); }
static int igt_dmabuf_import_ownership(void *arg) { struct drm_i915_private *i915 = arg; struct drm_i915_gem_object *obj; struct dma_buf *dmabuf; void *ptr; int err; dmabuf = mock_dmabuf(1); if (IS_ERR(dmabuf)) return PTR_ERR(dmabuf); ptr = dma_buf_vmap(dmabuf); if (!ptr) { pr_err("dma_buf_vmap failed\n"); err = -ENOMEM; goto err_dmabuf; } memset(ptr, 0xc5, PAGE_SIZE); dma_buf_vunmap(dmabuf, ptr); obj = to_intel_bo(i915_gem_prime_import(&i915->drm, dmabuf)); if (IS_ERR(obj)) { pr_err("i915_gem_prime_import failed with err=%d\n", (int)PTR_ERR(obj)); err = PTR_ERR(obj); goto err_dmabuf; } dma_buf_put(dmabuf); err = i915_gem_object_pin_pages(obj); if (err) { pr_err("i915_gem_object_pin_pages failed with err=%d\n", err); goto out_obj; } err = 0; i915_gem_object_unpin_pages(obj); out_obj: i915_gem_object_put(obj); return err; err_dmabuf: dma_buf_put(dmabuf); return err; }
static int igt_dmabuf_export_vmap(void *arg) { struct drm_i915_private *i915 = arg; struct drm_i915_gem_object *obj; struct dma_buf *dmabuf; void *ptr; int err; obj = i915_gem_object_create(i915, PAGE_SIZE); if (IS_ERR(obj)) return PTR_ERR(obj); dmabuf = i915_gem_prime_export(&i915->drm, &obj->base, 0); if (IS_ERR(dmabuf)) { pr_err("i915_gem_prime_export failed with err=%d\n", (int)PTR_ERR(dmabuf)); err = PTR_ERR(dmabuf); goto err_obj; } i915_gem_object_put(obj); ptr = dma_buf_vmap(dmabuf); if (IS_ERR(ptr)) { err = PTR_ERR(ptr); pr_err("dma_buf_vmap failed with err=%d\n", err); goto out; } if (memchr_inv(ptr, 0, dmabuf->size)) { pr_err("Exported object not initialiased to zero!\n"); err = -EINVAL; goto out; } memset(ptr, 0xc5, dmabuf->size); err = 0; dma_buf_vunmap(dmabuf, ptr); out: dma_buf_put(dmabuf); return err; err_obj: i915_gem_object_put(obj); return err; }
void msm_gem_free_object(struct drm_gem_object *obj) { struct drm_device *dev = obj->dev; struct msm_drm_private *priv = obj->dev->dev_private; struct msm_gem_object *msm_obj = to_msm_bo(obj); int id; WARN_ON(!mutex_is_locked(&dev->struct_mutex)); /* object should not be on active list: */ WARN_ON(is_active(msm_obj)); list_del(&msm_obj->mm_list); for (id = 0; id < ARRAY_SIZE(msm_obj->domain); id++) { struct msm_mmu *mmu = priv->mmus[id]; if (mmu && msm_obj->domain[id].iova) { uint32_t offset = msm_obj->domain[id].iova; mmu->funcs->unmap(mmu, offset, msm_obj->sgt, obj->size); } } if (obj->import_attach) { if (msm_obj->vaddr) dma_buf_vunmap(obj->import_attach->dmabuf, msm_obj->vaddr); /* Don't drop the pages for imported dmabuf, as they are not * ours, just free the array we allocated: */ if (msm_obj->pages) drm_free_large(msm_obj->pages); drm_prime_gem_destroy(obj, msm_obj->sgt); } else { vunmap(msm_obj->vaddr); put_pages(obj); } if (msm_obj->resv == &msm_obj->_resv) reservation_object_fini(msm_obj->resv); drm_gem_object_release(obj); kfree(msm_obj); }
static void vb2_dma_sg_unmap_dmabuf(void *mem_priv) { struct vb2_dma_sg_buf *buf = mem_priv; struct sg_table *sgt = buf->dma_sgt; if (WARN_ON(!buf->db_attach)) { pr_err("trying to unpin a not attached buffer\n"); return; } if (WARN_ON(!sgt)) { pr_err("dmabuf buffer is already unpinned\n"); return; } if (buf->vaddr) { dma_buf_vunmap(buf->db_attach->dmabuf, buf->vaddr); buf->vaddr = NULL; } dma_buf_unmap_attachment(buf->db_attach, sgt, buf->dma_dir); buf->dma_sgt = NULL; }
void msm_gem_free_object(struct drm_gem_object *obj) { struct drm_device *dev = obj->dev; struct msm_gem_object *msm_obj = to_msm_bo(obj); WARN_ON(!mutex_is_locked(&dev->struct_mutex)); /* object should not be on active list: */ WARN_ON(is_active(msm_obj)); list_del(&msm_obj->mm_list); put_iova(obj); if (obj->import_attach) { if (msm_obj->vaddr) dma_buf_vunmap(obj->import_attach->dmabuf, msm_obj->vaddr); /* Don't drop the pages for imported dmabuf, as they are not * ours, just free the array we allocated: */ if (msm_obj->pages) drm_free_large(msm_obj->pages); drm_prime_gem_destroy(obj, msm_obj->sgt); } else { msm_gem_vunmap(obj); put_pages(obj); } if (msm_obj->resv == &msm_obj->_resv) reservation_object_fini(msm_obj->resv); drm_gem_object_release(obj); kfree(msm_obj); }
void nvhost_dmabuf_munmap(struct mem_handle *handle, void *addr) { dma_buf_vunmap(to_dmabuf(handle), addr); }
static int igt_dmabuf_import(void *arg) { struct drm_i915_private *i915 = arg; struct drm_i915_gem_object *obj; struct dma_buf *dmabuf; void *obj_map, *dma_map; u32 pattern[] = { 0, 0xaa, 0xcc, 0x55, 0xff }; int err, i; dmabuf = mock_dmabuf(1); if (IS_ERR(dmabuf)) return PTR_ERR(dmabuf); obj = to_intel_bo(i915_gem_prime_import(&i915->drm, dmabuf)); if (IS_ERR(obj)) { pr_err("i915_gem_prime_import failed with err=%d\n", (int)PTR_ERR(obj)); err = PTR_ERR(obj); goto out_dmabuf; } if (obj->base.dev != &i915->drm) { pr_err("i915_gem_prime_import created a non-i915 object!\n"); err = -EINVAL; goto out_obj; } if (obj->base.size != PAGE_SIZE) { pr_err("i915_gem_prime_import is wrong size found %lld, expected %ld\n", (long long)obj->base.size, PAGE_SIZE); err = -EINVAL; goto out_obj; } dma_map = dma_buf_vmap(dmabuf); if (!dma_map) { pr_err("dma_buf_vmap failed\n"); err = -ENOMEM; goto out_obj; } if (0) { /* Can not yet map dmabuf */ obj_map = i915_gem_object_pin_map(obj, I915_MAP_WB); if (IS_ERR(obj_map)) { err = PTR_ERR(obj_map); pr_err("i915_gem_object_pin_map failed with err=%d\n", err); goto out_dma_map; } for (i = 0; i < ARRAY_SIZE(pattern); i++) { memset(dma_map, pattern[i], PAGE_SIZE); if (memchr_inv(obj_map, pattern[i], PAGE_SIZE)) { err = -EINVAL; pr_err("imported vmap not all set to %x!\n", pattern[i]); i915_gem_object_unpin_map(obj); goto out_dma_map; } } for (i = 0; i < ARRAY_SIZE(pattern); i++) { memset(obj_map, pattern[i], PAGE_SIZE); if (memchr_inv(dma_map, pattern[i], PAGE_SIZE)) { err = -EINVAL; pr_err("exported vmap not all set to %x!\n", pattern[i]); i915_gem_object_unpin_map(obj); goto out_dma_map; } } i915_gem_object_unpin_map(obj); } err = 0; out_dma_map: dma_buf_vunmap(dmabuf, dma_map); out_obj: i915_gem_object_put(obj); out_dmabuf: dma_buf_put(dmabuf); return err; }
static void adf_fb_destroy(struct adf_fbdev *fbdev) { dma_buf_vunmap(fbdev->dma_buf, fbdev->vaddr); dma_buf_put(fbdev->dma_buf); }