mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-11 05:17:10 +09:00
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:
121
drivers/amlogic/drm/am_meson_gem.c
Normal file → Executable file
121
drivers/amlogic/drm/am_meson_gem.c
Normal file → Executable 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
25
drivers/amlogic/drm/am_meson_gem.h
Normal file → Executable 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
16
drivers/amlogic/drm/meson_drv.c
Normal file → Executable 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,
|
||||
|
||||
Reference in New Issue
Block a user