struct dma_buf *omap_gem_prime_export(struct drm_device *dev, struct drm_gem_object *obj, int flags) { DEFINE_DMA_BUF_EXPORT_INFO(exp_info); exp_info.ops = &omap_dmabuf_ops; exp_info.size = obj->size; exp_info.flags = flags; exp_info.priv = obj; return drm_gem_dmabuf_export(dev, &exp_info); }
struct dma_buf *tegra_gem_prime_export(struct drm_device *drm, struct drm_gem_object *gem, int flags) { DEFINE_DMA_BUF_EXPORT_INFO(exp_info); exp_info.ops = &tegra_gem_prime_dmabuf_ops; exp_info.size = gem->size; exp_info.flags = flags; exp_info.priv = gem; return dma_buf_export(&exp_info); }
struct dma_buf *i915_gem_prime_export(struct drm_device *dev, struct drm_gem_object *gem_obj, int flags) { struct drm_i915_gem_object *obj = to_intel_bo(gem_obj); DEFINE_DMA_BUF_EXPORT_INFO(exp_info); exp_info.ops = &i915_dmabuf_ops; exp_info.size = gem_obj->size; exp_info.flags = flags; exp_info.priv = gem_obj; if (obj->ops->dmabuf_export) { int ret = obj->ops->dmabuf_export(obj); if (ret) return ERR_PTR(ret); } return dma_buf_export(&exp_info); }
static struct dma_buf *vb2_dma_sg_get_dmabuf(void *buf_priv, unsigned long flags) { struct vb2_dma_sg_buf *buf = buf_priv; struct dma_buf *dbuf; DEFINE_DMA_BUF_EXPORT_INFO(exp_info); exp_info.ops = &vb2_dma_sg_dmabuf_ops; exp_info.size = buf->size; exp_info.flags = flags; exp_info.priv = buf; if (WARN_ON(!buf->dma_sgt)) return NULL; dbuf = dma_buf_export(&exp_info); if (IS_ERR(dbuf)) return NULL; /* dmabuf keeps reference to vb2 buffer */ atomic_inc(&buf->refcount); return dbuf; }
static struct dma_buf *mock_dmabuf(int npages) { struct mock_dmabuf *mock; DEFINE_DMA_BUF_EXPORT_INFO(exp_info); struct dma_buf *dmabuf; int i; mock = kmalloc(sizeof(*mock) + npages * sizeof(struct page *), GFP_KERNEL); if (!mock) return ERR_PTR(-ENOMEM); mock->npages = npages; for (i = 0; i < npages; i++) { mock->pages[i] = alloc_page(GFP_KERNEL); if (!mock->pages[i]) goto err; } exp_info.ops = &mock_dmabuf_ops; exp_info.size = npages * PAGE_SIZE; exp_info.flags = O_CLOEXEC; exp_info.priv = mock; dmabuf = dma_buf_export(&exp_info); if (IS_ERR(dmabuf)) goto err; return dmabuf; err: while (i--) put_page(mock->pages[i]); kfree(mock); return ERR_PTR(-ENOMEM); }
struct tee_shm *tee_shm_register(struct tee_context *ctx, unsigned long addr, size_t length, u32 flags) { struct tee_device *teedev = ctx->teedev; const u32 req_flags = TEE_SHM_DMA_BUF | TEE_SHM_USER_MAPPED; struct tee_shm *shm; void *ret; int rc; int num_pages; unsigned long start; if (flags != req_flags) return ERR_PTR(-ENOTSUPP); if (!tee_device_get(teedev)) return ERR_PTR(-EINVAL); if (!teedev->desc->ops->shm_register || !teedev->desc->ops->shm_unregister) { tee_device_put(teedev); return ERR_PTR(-ENOTSUPP); } teedev_ctx_get(ctx); shm = kzalloc(sizeof(*shm), GFP_KERNEL); if (!shm) { ret = ERR_PTR(-ENOMEM); goto err; } shm->flags = flags | TEE_SHM_REGISTER; shm->teedev = teedev; shm->ctx = ctx; shm->id = -1; start = rounddown(addr, PAGE_SIZE); shm->offset = addr - start; shm->size = length; num_pages = (roundup(addr + length, PAGE_SIZE) - start) / PAGE_SIZE; shm->pages = kcalloc(num_pages, sizeof(*shm->pages), GFP_KERNEL); if (!shm->pages) { ret = ERR_PTR(-ENOMEM); goto err; } rc = get_user_pages_fast(start, num_pages, 1, shm->pages); if (rc > 0) shm->num_pages = rc; if (rc != num_pages) { if (rc >= 0) rc = -ENOMEM; ret = ERR_PTR(rc); goto err; } mutex_lock(&teedev->mutex); shm->id = idr_alloc(&teedev->idr, shm, 1, 0, GFP_KERNEL); mutex_unlock(&teedev->mutex); if (shm->id < 0) { ret = ERR_PTR(shm->id); goto err; } rc = teedev->desc->ops->shm_register(ctx, shm, shm->pages, shm->num_pages, start); if (rc) { ret = ERR_PTR(rc); goto err; } if (flags & TEE_SHM_DMA_BUF) { DEFINE_DMA_BUF_EXPORT_INFO(exp_info); exp_info.ops = &tee_shm_dma_buf_ops; exp_info.size = shm->size; exp_info.flags = O_RDWR; exp_info.priv = shm; shm->dmabuf = dma_buf_export(&exp_info); if (IS_ERR(shm->dmabuf)) { ret = ERR_CAST(shm->dmabuf); teedev->desc->ops->shm_unregister(ctx, shm); goto err; } } mutex_lock(&teedev->mutex); list_add_tail(&shm->link, &ctx->list_shm); mutex_unlock(&teedev->mutex); return shm; err: if (shm) { size_t n; if (shm->id >= 0) { mutex_lock(&teedev->mutex); idr_remove(&teedev->idr, shm->id); mutex_unlock(&teedev->mutex); } if (shm->pages) { for (n = 0; n < shm->num_pages; n++) put_page(shm->pages[n]); kfree(shm->pages); } } kfree(shm); teedev_ctx_put(ctx); tee_device_put(teedev); return ret; }
static struct tee_shm *__tee_shm_alloc(struct tee_context *ctx, struct tee_device *teedev, size_t size, u32 flags) { struct tee_shm_pool_mgr *poolm = NULL; struct tee_shm *shm; void *ret; int rc; if (ctx && ctx->teedev != teedev) { dev_err(teedev->dev.parent, "ctx and teedev mismatch\n"); return ERR_PTR(-EINVAL); } if (!(flags & TEE_SHM_MAPPED)) { dev_err(teedev->dev.parent, "only mapped allocations supported\n"); return ERR_PTR(-EINVAL); } if ((flags & ~(TEE_SHM_MAPPED | TEE_SHM_DMA_BUF))) { dev_err(teedev->dev.parent, "invalid shm flags 0x%x", flags); return ERR_PTR(-EINVAL); } if (!tee_device_get(teedev)) return ERR_PTR(-EINVAL); if (!teedev->pool) { /* teedev has been detached from driver */ ret = ERR_PTR(-EINVAL); goto err_dev_put; } shm = kzalloc(sizeof(*shm), GFP_KERNEL); if (!shm) { ret = ERR_PTR(-ENOMEM); goto err_dev_put; } shm->flags = flags | TEE_SHM_POOL; shm->teedev = teedev; shm->ctx = ctx; if (flags & TEE_SHM_DMA_BUF) poolm = teedev->pool->dma_buf_mgr; else poolm = teedev->pool->private_mgr; rc = poolm->ops->alloc(poolm, shm, size); if (rc) { ret = ERR_PTR(rc); goto err_kfree; } mutex_lock(&teedev->mutex); shm->id = idr_alloc(&teedev->idr, shm, 1, 0, GFP_KERNEL); mutex_unlock(&teedev->mutex); if (shm->id < 0) { ret = ERR_PTR(shm->id); goto err_pool_free; } if (flags & TEE_SHM_DMA_BUF) { DEFINE_DMA_BUF_EXPORT_INFO(exp_info); exp_info.ops = &tee_shm_dma_buf_ops; exp_info.size = shm->size; exp_info.flags = O_RDWR; exp_info.priv = shm; shm->dmabuf = dma_buf_export(&exp_info); if (IS_ERR(shm->dmabuf)) { ret = ERR_CAST(shm->dmabuf); goto err_rem; } } if (ctx) { teedev_ctx_get(ctx); mutex_lock(&teedev->mutex); list_add_tail(&shm->link, &ctx->list_shm); mutex_unlock(&teedev->mutex); } return shm; err_rem: mutex_lock(&teedev->mutex); idr_remove(&teedev->idr, shm->id); mutex_unlock(&teedev->mutex); err_pool_free: poolm->ops->free(poolm, shm); err_kfree: kfree(shm); err_dev_put: tee_device_put(teedev); return ret; }