Skip to content

Commit

Permalink
drm/gem: Add drm_gem_object_funcs
Browse files Browse the repository at this point in the history
This adds an optional function table on GEM objects.
The main benefit is for drivers that support more than one type of
memory (shmem,vram,cma) for their buffers depending on the hardware it
runs on. With the callbacks attached to the GEM object itself, it is
easier to have core helpers for the the various buffer types. The driver
only has to make the decision about buffer type on GEM object creation
and all other callbacks can be handled by the chosen helper.

drm_driver->gem_prime_res_obj has not been added since there's a todo to
put a reservation_object into drm_gem_object.

v3: Add todo entry

v2: Drop drm_gem_object_funcs->prime_mmap in favour of
drm_gem_prime_mmap() (Daniel Vetter)

v1:
- drm_gem_object_funcs.map -> .prime_map let it only do PRIME mmap like
  the function it superseeds (Daniel Vetter)
- Flip around the if ladders and make obj->funcs the first choice
  highlighting the fact that this the new default way of doing it
  (Daniel Vetter)

Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Acked-by: Christian König <christian.koenig@amd.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20181110145647.17580-4-noralf@tronnes.org
  • Loading branch information
Noralf Trønnes committed Nov 20, 2018
1 parent 7698799 commit b39b539
Show file tree
Hide file tree
Showing 5 changed files with 258 additions and 34 deletions.
6 changes: 6 additions & 0 deletions Documentation/gpu/todo.rst
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,12 @@ Most drivers don't need to set drm_driver->gem_prime_import and
->gem_prime_export now that drm_gem_prime_import() and drm_gem_prime_export()
are the default.

struct drm_gem_object_funcs
---------------------------

GEM objects can now have a function table instead of having the callbacks on the
DRM driver struct. This is now the preferred way and drivers can be moved over.

Core refactorings
=================

Expand Down
12 changes: 5 additions & 7 deletions drivers/gpu/drm/drm_client.c
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,7 @@ int drm_client_init(struct drm_device *dev, struct drm_client_dev *client,
{
int ret;

if (!drm_core_check_feature(dev, DRIVER_MODESET) ||
!dev->driver->dumb_create || !dev->driver->gem_prime_vmap)
if (!drm_core_check_feature(dev, DRIVER_MODESET) || !dev->driver->dumb_create)
return -EOPNOTSUPP;

if (funcs && !try_module_get(funcs->owner))
Expand Down Expand Up @@ -229,8 +228,7 @@ static void drm_client_buffer_delete(struct drm_client_buffer *buffer)
{
struct drm_device *dev = buffer->client->dev;

if (buffer->vaddr && dev->driver->gem_prime_vunmap)
dev->driver->gem_prime_vunmap(buffer->gem, buffer->vaddr);
drm_gem_vunmap(buffer->gem, buffer->vaddr);

if (buffer->gem)
drm_gem_object_put_unlocked(buffer->gem);
Expand Down Expand Up @@ -283,9 +281,9 @@ drm_client_buffer_create(struct drm_client_dev *client, u32 width, u32 height, u
* fd_install step out of the driver backend hooks, to make that
* final step optional for internal users.
*/
vaddr = dev->driver->gem_prime_vmap(obj);
if (!vaddr) {
ret = -ENOMEM;
vaddr = drm_gem_vmap(obj);
if (IS_ERR(vaddr)) {
ret = PTR_ERR(vaddr);
goto err_delete;
}

Expand Down
109 changes: 100 additions & 9 deletions drivers/gpu/drm/drm_gem.c
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,9 @@ drm_gem_object_release_handle(int id, void *ptr, void *data)
struct drm_gem_object *obj = ptr;
struct drm_device *dev = obj->dev;

if (dev->driver->gem_close_object)
if (obj->funcs && obj->funcs->close)
obj->funcs->close(obj, file_priv);
else if (dev->driver->gem_close_object)
dev->driver->gem_close_object(obj, file_priv);

if (drm_core_check_feature(dev, DRIVER_PRIME))
Expand Down Expand Up @@ -410,7 +412,11 @@ drm_gem_handle_create_tail(struct drm_file *file_priv,
if (ret)
goto err_remove;

if (dev->driver->gem_open_object) {
if (obj->funcs && obj->funcs->open) {
ret = obj->funcs->open(obj, file_priv);
if (ret)
goto err_revoke;
} else if (dev->driver->gem_open_object) {
ret = dev->driver->gem_open_object(obj, file_priv);
if (ret)
goto err_revoke;
Expand Down Expand Up @@ -835,7 +841,9 @@ drm_gem_object_free(struct kref *kref)
container_of(kref, struct drm_gem_object, refcount);
struct drm_device *dev = obj->dev;

if (dev->driver->gem_free_object_unlocked) {
if (obj->funcs) {
obj->funcs->free(obj);
} else if (dev->driver->gem_free_object_unlocked) {
dev->driver->gem_free_object_unlocked(obj);
} else if (dev->driver->gem_free_object) {
WARN_ON(!mutex_is_locked(&dev->struct_mutex));
Expand Down Expand Up @@ -864,13 +872,13 @@ drm_gem_object_put_unlocked(struct drm_gem_object *obj)

dev = obj->dev;

if (dev->driver->gem_free_object_unlocked) {
kref_put(&obj->refcount, drm_gem_object_free);
} else {
if (dev->driver->gem_free_object) {
might_lock(&dev->struct_mutex);
if (kref_put_mutex(&obj->refcount, drm_gem_object_free,
&dev->struct_mutex))
mutex_unlock(&dev->struct_mutex);
} else {
kref_put(&obj->refcount, drm_gem_object_free);
}
}
EXPORT_SYMBOL(drm_gem_object_put_unlocked);
Expand Down Expand Up @@ -960,11 +968,14 @@ int drm_gem_mmap_obj(struct drm_gem_object *obj, unsigned long obj_size,
if (obj_size < vma->vm_end - vma->vm_start)
return -EINVAL;

if (!dev->driver->gem_vm_ops)
if (obj->funcs && obj->funcs->vm_ops)
vma->vm_ops = obj->funcs->vm_ops;
else if (dev->driver->gem_vm_ops)
vma->vm_ops = dev->driver->gem_vm_ops;
else
return -EINVAL;

vma->vm_flags |= VM_IO | VM_PFNMAP | VM_DONTEXPAND | VM_DONTDUMP;
vma->vm_ops = dev->driver->gem_vm_ops;
vma->vm_private_data = obj;
vma->vm_page_prot = pgprot_writecombine(vm_get_page_prot(vma->vm_flags));
vma->vm_page_prot = pgprot_decrypted(vma->vm_page_prot);
Expand Down Expand Up @@ -1066,6 +1077,86 @@ void drm_gem_print_info(struct drm_printer *p, unsigned int indent,
drm_printf_indent(p, indent, "imported=%s\n",
obj->import_attach ? "yes" : "no");

if (obj->dev->driver->gem_print_info)
if (obj->funcs && obj->funcs->print_info)
obj->funcs->print_info(p, indent, obj);
else if (obj->dev->driver->gem_print_info)
obj->dev->driver->gem_print_info(p, indent, obj);
}

/**
* drm_gem_pin - Pin backing buffer in memory
* @obj: GEM object
*
* Make sure the backing buffer is pinned in memory.
*
* Returns:
* 0 on success or a negative error code on failure.
*/
int drm_gem_pin(struct drm_gem_object *obj)
{
if (obj->funcs && obj->funcs->pin)
return obj->funcs->pin(obj);
else if (obj->dev->driver->gem_prime_pin)
return obj->dev->driver->gem_prime_pin(obj);
else
return 0;
}
EXPORT_SYMBOL(drm_gem_pin);

/**
* drm_gem_unpin - Unpin backing buffer from memory
* @obj: GEM object
*
* Relax the requirement that the backing buffer is pinned in memory.
*/
void drm_gem_unpin(struct drm_gem_object *obj)
{
if (obj->funcs && obj->funcs->unpin)
obj->funcs->unpin(obj);
else if (obj->dev->driver->gem_prime_unpin)
obj->dev->driver->gem_prime_unpin(obj);
}
EXPORT_SYMBOL(drm_gem_unpin);

/**
* drm_gem_vmap - Map buffer into kernel virtual address space
* @obj: GEM object
*
* Returns:
* A virtual pointer to a newly created GEM object or an ERR_PTR-encoded negative
* error code on failure.
*/
void *drm_gem_vmap(struct drm_gem_object *obj)
{
void *vaddr;

if (obj->funcs && obj->funcs->vmap)
vaddr = obj->funcs->vmap(obj);
else if (obj->dev->driver->gem_prime_vmap)
vaddr = obj->dev->driver->gem_prime_vmap(obj);
else
vaddr = ERR_PTR(-EOPNOTSUPP);

if (!vaddr)
vaddr = ERR_PTR(-ENOMEM);

return vaddr;
}
EXPORT_SYMBOL(drm_gem_vmap);

/**
* drm_gem_vunmap - Remove buffer mapping from kernel virtual address space
* @obj: GEM object
* @vaddr: Virtual address (can be NULL)
*/
void drm_gem_vunmap(struct drm_gem_object *obj, void *vaddr)
{
if (!vaddr)
return;

if (obj->funcs && obj->funcs->vunmap)
obj->funcs->vunmap(obj, vaddr);
else if (obj->dev->driver->gem_prime_vunmap)
obj->dev->driver->gem_prime_vunmap(obj, vaddr);
}
EXPORT_SYMBOL(drm_gem_vunmap);
34 changes: 16 additions & 18 deletions drivers/gpu/drm/drm_prime.c
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,6 @@ int drm_gem_map_attach(struct dma_buf *dma_buf,
{
struct drm_prime_attachment *prime_attach;
struct drm_gem_object *obj = dma_buf->priv;
struct drm_device *dev = obj->dev;

prime_attach = kzalloc(sizeof(*prime_attach), GFP_KERNEL);
if (!prime_attach)
Expand All @@ -208,10 +207,7 @@ int drm_gem_map_attach(struct dma_buf *dma_buf,
prime_attach->dir = DMA_NONE;
attach->priv = prime_attach;

if (!dev->driver->gem_prime_pin)
return 0;

return dev->driver->gem_prime_pin(obj);
return drm_gem_pin(obj);
}
EXPORT_SYMBOL(drm_gem_map_attach);

Expand All @@ -228,7 +224,6 @@ void drm_gem_map_detach(struct dma_buf *dma_buf,
{
struct drm_prime_attachment *prime_attach = attach->priv;
struct drm_gem_object *obj = dma_buf->priv;
struct drm_device *dev = obj->dev;

if (prime_attach) {
struct sg_table *sgt = prime_attach->sgt;
Expand All @@ -247,8 +242,7 @@ void drm_gem_map_detach(struct dma_buf *dma_buf,
attach->priv = NULL;
}

if (dev->driver->gem_prime_unpin)
dev->driver->gem_prime_unpin(obj);
drm_gem_unpin(obj);
}
EXPORT_SYMBOL(drm_gem_map_detach);

Expand Down Expand Up @@ -310,7 +304,10 @@ struct sg_table *drm_gem_map_dma_buf(struct dma_buf_attachment *attach,
if (WARN_ON(prime_attach->dir != DMA_NONE))
return ERR_PTR(-EBUSY);

sgt = obj->dev->driver->gem_prime_get_sg_table(obj);
if (obj->funcs)
sgt = obj->funcs->get_sg_table(obj);
else
sgt = obj->dev->driver->gem_prime_get_sg_table(obj);

if (!IS_ERR(sgt)) {
if (!dma_map_sg_attrs(attach->dev, sgt->sgl, sgt->nents, dir,
Expand Down Expand Up @@ -406,12 +403,13 @@ EXPORT_SYMBOL(drm_gem_dmabuf_release);
void *drm_gem_dmabuf_vmap(struct dma_buf *dma_buf)
{
struct drm_gem_object *obj = dma_buf->priv;
struct drm_device *dev = obj->dev;
void *vaddr;

if (dev->driver->gem_prime_vmap)
return dev->driver->gem_prime_vmap(obj);
else
return NULL;
vaddr = drm_gem_vmap(obj);
if (IS_ERR(vaddr))
vaddr = NULL;

return vaddr;
}
EXPORT_SYMBOL(drm_gem_dmabuf_vmap);

Expand All @@ -426,10 +424,8 @@ EXPORT_SYMBOL(drm_gem_dmabuf_vmap);
void drm_gem_dmabuf_vunmap(struct dma_buf *dma_buf, void *vaddr)
{
struct drm_gem_object *obj = dma_buf->priv;
struct drm_device *dev = obj->dev;

if (dev->driver->gem_prime_vunmap)
dev->driver->gem_prime_vunmap(obj, vaddr);
drm_gem_vunmap(obj, vaddr);
}
EXPORT_SYMBOL(drm_gem_dmabuf_vunmap);

Expand Down Expand Up @@ -529,7 +525,9 @@ static struct dma_buf *export_and_register_object(struct drm_device *dev,
return dmabuf;
}

if (dev->driver->gem_prime_export)
if (obj->funcs && obj->funcs->export)
dmabuf = obj->funcs->export(obj, flags);
else if (dev->driver->gem_prime_export)
dmabuf = dev->driver->gem_prime_export(dev, obj, flags);
else
dmabuf = drm_gem_prime_export(dev, obj, flags);
Expand Down
Loading

0 comments on commit b39b539

Please sign in to comment.