From: Mark Yao Date: Mon, 20 Mar 2017 02:31:02 +0000 (+0800) Subject: drm/drm-prime: cache dma_buf import context X-Git-Tag: firefly_0821_release~254 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=5a90381e5acc2cf32be03099a14d05d4362b3348;p=firefly-linux-kernel-4.4.55.git drm/drm-prime: cache dma_buf import context Change-Id: Ia39a3d4691f0b545039efb880c999a35886178a0 Signed-off-by: Mark Yao --- diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c index 4675bd3b050b..3331c5647d18 100644 --- a/drivers/gpu/drm/drm_prime.c +++ b/drivers/gpu/drm/drm_prime.c @@ -71,6 +71,11 @@ struct drm_prime_attachment { enum dma_data_direction dir; }; +struct drm_prime_callback_data { + struct drm_gem_object *obj; + struct sg_table *sgt; +}; + static int drm_prime_add_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf, uint32_t handle) { @@ -491,6 +496,23 @@ out_unlock: } EXPORT_SYMBOL(drm_gem_prime_handle_to_fd); +static void drm_gem_prime_dmabuf_release_callback(void *data) +{ + struct drm_prime_callback_data *cb_data = data; + + if (cb_data && cb_data->obj && cb_data->obj->import_attach) { + struct dma_buf_attachment *attach = cb_data->obj->import_attach; + struct sg_table *sgt = cb_data->sgt; + + if (sgt) + dma_buf_unmap_attachment(attach, sgt, + DMA_BIDIRECTIONAL); + dma_buf_detach(attach->dmabuf, attach); + drm_gem_object_unreference_unlocked(cb_data->obj); + kfree(cb_data); + } +} + /** * drm_gem_prime_import - helper library implementation of the import callback * @dev: drm_device to import into @@ -505,6 +527,7 @@ struct drm_gem_object *drm_gem_prime_import(struct drm_device *dev, struct dma_buf_attachment *attach; struct sg_table *sgt; struct drm_gem_object *obj; + struct drm_prime_callback_data *cb_data; int ret; if (dma_buf->ops == &drm_gem_prime_dmabuf_ops) { @@ -519,6 +542,13 @@ struct drm_gem_object *drm_gem_prime_import(struct drm_device *dev, } } + cb_data = dma_buf_get_release_callback_data(dma_buf, + drm_gem_prime_dmabuf_release_callback); + if (cb_data && cb_data->obj && cb_data->obj->dev == dev) { + drm_gem_object_reference(cb_data->obj); + return cb_data->obj; + } + if (!dev->driver->gem_prime_import_sg_table) return ERR_PTR(-EINVAL); @@ -527,11 +557,16 @@ struct drm_gem_object *drm_gem_prime_import(struct drm_device *dev, return ERR_CAST(attach); get_dma_buf(dma_buf); + cb_data = kmalloc(sizeof(*cb_data), GFP_KERNEL); + if (!cb_data) { + ret = -ENOMEM; + goto fail_detach; + } sgt = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL); if (IS_ERR(sgt)) { ret = PTR_ERR(sgt); - goto fail_detach; + goto fail_free; } obj = dev->driver->gem_prime_import_sg_table(dev, attach, sgt); @@ -539,13 +574,20 @@ struct drm_gem_object *drm_gem_prime_import(struct drm_device *dev, ret = PTR_ERR(obj); goto fail_unmap; } - obj->import_attach = attach; + cb_data->obj = obj; + cb_data->sgt = sgt; + dma_buf_set_release_callback(dma_buf, + drm_gem_prime_dmabuf_release_callback, cb_data); + dma_buf_put(dma_buf); + drm_gem_object_reference(obj); return obj; fail_unmap: dma_buf_unmap_attachment(attach, sgt, DMA_BIDIRECTIONAL); +fail_free: + kfree(cb_data); fail_detach: dma_buf_detach(dma_buf, attach); dma_buf_put(dma_buf); diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_gem.c b/drivers/gpu/drm/rockchip/rockchip_drm_gem.c index 30d8efcb5132..12bc70d44257 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_gem.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_gem.c @@ -493,7 +493,6 @@ void rockchip_gem_free_object(struct drm_gem_object *obj) dma_unmap_sg(drm->dev, rk_obj->sgt->sgl, rk_obj->sgt->nents, DMA_BIDIRECTIONAL); } - drm_prime_gem_destroy(obj, rk_obj->sgt); } else { rockchip_gem_free_buf(rk_obj); }