DRM: fix gem object leak in PRIME_EXPORT operation.

PD#158474: fixed exported fd leaked.

Exported fd didnot bind correct release function,
use core gem-prime function to re-write export function.
The import function is not provded, for now we only import
the buffer created from meson driver.

Change-Id: I15fad65741631ee2b367d088e733f20af8b0cf5a
Signed-off-by: sky zhou <sky.zhou@amlogic.com>
This commit is contained in:
sky zhou
2018-01-17 12:12:59 +08:00
committed by Jianxin Pan
parent 4f75f1bd8b
commit 05a1bf9ad2
3 changed files with 44 additions and 118 deletions

121
drivers/amlogic/drm/am_meson_gem.c Normal file → Executable file
View File

@@ -125,10 +125,10 @@ void am_meson_gem_object_free(struct drm_gem_object *obj)
DRM_DEBUG("am_meson_gem_object_free %p handle count = %d\n",
meson_gem_obj, obj->handle_count);
if (obj->import_attach)
drm_prime_gem_destroy(obj, meson_gem_obj->sgt);
else
if (obj->import_attach == false)
am_meson_gem_free_ion_buf(obj->dev, meson_gem_obj);
else
DRM_ERROR("Not support import buffer from other driver.\n");
drm_gem_free_mmap_offset(obj);
@@ -154,15 +154,8 @@ int am_meson_gem_object_mmap(
vma->vm_flags &= ~VM_PFNMAP;
vma->vm_pgoff = 0;
if (obj->sgt) {
DRM_ERROR("am_meson_gem_object_mmap imported buffer.\n");
/*should NOT run to here.*/
#if 0
ret = dma_mmap_wc(obj->base.dev->dev, vma,
page_address(sg_page(obj->sgt->sgl)),
sg_dma_address(obj->sgt->sgl),
vma->vm_end - vma->vm_start);
#endif
if (obj->base.import_attach) {
DRM_ERROR("Not support import buffer from other driver.\n");
} else {
buffer = obj->handle->buffer;
@@ -342,102 +335,20 @@ void am_meson_gem_cleanup(struct meson_drm *drmdrv)
}
}
/* PRIME operations */
struct dma_buf *am_meson_gem_prime_export(
struct drm_device *drm_dev,
struct drm_gem_object *obj,
int flags)
struct sg_table *am_meson_gem_prime_get_sg_table(
struct drm_gem_object *obj)
{
struct am_meson_gem_object *meson_gem_obj;
struct ion_handle *handle;
meson_gem_obj = to_am_meson_gem_obj(obj);
handle = meson_gem_obj->handle;
if (!handle)
return ERR_PTR(-EINVAL);
return ion_share_dma_buf(handle->client, handle);
}
struct drm_gem_object *am_meson_gem_prime_import(
struct drm_device *drm_dev,
struct dma_buf *dma_buf)
{
struct dma_buf_attachment *attach;
struct sg_table *sgt;
struct am_meson_gem_object *meson_gem_obj = NULL;
int ret;
attach = dma_buf_attach(dma_buf, drm_dev->dev);
if (IS_ERR(attach))
return ERR_PTR(-EINVAL);
get_dma_buf(dma_buf);
sgt = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL);
if (IS_ERR_OR_NULL(sgt)) {
ret = PTR_ERR(sgt);
goto err_buf_detach;
}
meson_gem_obj = kzalloc(sizeof(*meson_gem_obj), GFP_KERNEL);
if (!meson_gem_obj) {
ret = -ENOMEM;
goto err_unmap_attach;
}
ret = drm_gem_object_init(drm_dev, &meson_gem_obj->base, dma_buf->size);
if (ret < 0) {
DRM_ERROR("failed to initialize gem object\n");
ret = -ENOMEM;
goto err_unmap_attach;
}
meson_gem_obj->sgt = sgt;
meson_gem_obj->base.import_attach = attach;
return &meson_gem_obj->base;
err_unmap_attach:
dma_buf_unmap_attachment(attach, sgt, DMA_BIDIRECTIONAL);
err_buf_detach:
dma_buf_detach(dma_buf, attach);
dma_buf_put(dma_buf);
kfree(meson_gem_obj);
return ERR_PTR(ret);
}
#if 0
struct sg_table *am_meson_gem_prime_get_sg_table(struct drm_gem_object *obj)
{
struct am_meson_gem_object *meson_gem_obj;
struct sg_table *src_sgt;
struct sg_table *sgt;
int ret;
meson_gem_obj = to_am_meson_gem_obj(obj);
DRM_DEBUG("am_meson_gem_prime_get_sg_table %p.\n", meson_gem_obj);
if (meson_gem_obj->sgt)
src_sgt = meson_gem_obj->sgt;
else
src_sgt = meson_gem_obj->handle->buffer->sg_table;
sgt = kzalloc(sizeof(*sgt), GFP_KERNEL);
if (!sgt)
return NULL;
ret = dma_get_sgtable(obj->dev->dev, sgt,
page_address(sg_page(src_sgt->sgl)),
sg_dma_address(src_sgt->sgl), obj->size);
if (ret < 0) {
kfree(sgt);
if (meson_gem_obj->base.import_attach == false)
return meson_gem_obj->handle->buffer->sg_table;
else {
DRM_ERROR("Not support import buffer from other driver.\n");
return NULL;
}
return sgt;
}
struct drm_gem_object *am_meson_gem_prime_import_sg_table(
@@ -462,18 +373,15 @@ struct drm_gem_object *am_meson_gem_prime_import_sg_table(
}
DRM_DEBUG("%s: %p, sg_table %p\n", __func__, meson_gem_obj, sgt);
meson_gem_obj->sgt = sgt;
/*meson_gem_obj->sgt = sgt;*/
return &meson_gem_obj->base;
}
void *am_meson_gem_prime_vmap(struct drm_gem_object *obj)
{
struct am_meson_gem_object *meson_gem_obj;
DRM_DEBUG("am_meson_gem_prime_vmap %p.\n", obj);
meson_gem_obj = to_am_meson_gem_obj(obj);
DRM_DEBUG("am_meson_gem_prime_vmap %p.\n", meson_gem_obj);
return meson_gem_obj->handle->buffer->vaddr;
return NULL;
}
void am_meson_gem_prime_vunmap(
@@ -499,4 +407,3 @@ int am_meson_gem_prime_mmap(
return am_meson_gem_object_mmap(meson_gem_obj, vma);
}
#endif

25
drivers/amlogic/drm/am_meson_gem.h Normal file → Executable file
View File

@@ -28,9 +28,6 @@ struct am_meson_gem_object {
/*for buffer create from ion heap */
struct ion_handle *handle;
bool bscatter;
/*for buffer imported. */
struct sg_table *sgt;
};
/* GEM MANAGER CREATE*/
@@ -75,13 +72,23 @@ int am_meson_gem_object_get_phyaddr(
struct am_meson_gem_object *meson_gem);
/* GEM PRIME OPERATIONS */
struct drm_gem_object *am_meson_gem_prime_import(
struct drm_device *drm_dev,
struct dma_buf *dma_buf);
struct sg_table *am_meson_gem_prime_get_sg_table(
struct drm_gem_object *obj);
struct dma_buf *am_meson_gem_prime_export(
struct drm_device *drm_dev,
struct drm_gem_object *am_meson_gem_prime_import_sg_table(
struct drm_device *dev,
struct dma_buf_attachment *attach,
struct sg_table *sgt);
void *am_meson_gem_prime_vmap(
struct drm_gem_object *obj);
void am_meson_gem_prime_vunmap(
struct drm_gem_object *obj,
int flags);
void *vaddr);
int am_meson_gem_prime_mmap(
struct drm_gem_object *obj,
struct vm_area_struct *vma);
#endif /* __AM_MESON_GEM_H */

16
drivers/amlogic/drm/meson_drv.c Normal file → Executable file
View File

@@ -160,8 +160,20 @@ static struct drm_driver meson_driver = {
/* PRIME Ops */
.prime_handle_to_fd = drm_gem_prime_handle_to_fd,
.prime_fd_to_handle = drm_gem_prime_fd_to_handle,
.gem_prime_import = am_meson_gem_prime_import,
.gem_prime_export = am_meson_gem_prime_export,
.gem_prime_export = drm_gem_prime_export,
.gem_prime_get_sg_table = am_meson_gem_prime_get_sg_table,
.gem_prime_import = drm_gem_prime_import,
/*
* If gem_prime_import_sg_table is NULL,only buffer created
* by meson driver can be imported ok.
*/
/*.gem_prime_import_sg_table = am_meson_gem_prime_import_sg_table,*/
.gem_prime_vmap = am_meson_gem_prime_vmap,
.gem_prime_vunmap = am_meson_gem_prime_vunmap,
.gem_prime_mmap = am_meson_gem_prime_mmap,
/* GEM Ops */
.dumb_create = am_meson_gem_dumb_create,