Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 76f1be5f authored by Thomas Zimmermann's avatar Thomas Zimmermann Committed by Gerrit - the friendly Code Review server
Browse files

drm/client: Support unmapping of DRM client buffers

DRM clients, such as the fbdev emulation, have their buffer objects
mapped by default. Mapping a buffer implicitly prevents its relocation.
Hence, the buffer may permanently consume video memory while it's
allocated. This is a problem for drivers of low-memory devices, such as
ast, mgag200 or older framebuffer hardware, which will then not have
enough memory to display other content (e.g., X11).

This patch introduces drm_client_buffer_vmap() and _vunmap(). Internal
DRM clients can use these functions to unmap and remap buffer objects
as needed.

There's no reference counting for vmap operations. Callers are expected
to either keep buffers mapped (as it is now), or call vmap and vunmap
in pairs around code that accesses the mapped memory.

v2:
	* remove several duplicated NULL-pointer checks
v3:
	* style and typo fixes

Link: https://patchwork.freedesktop.org/patch/315831/


Signed-off-by: default avatarThomas Zimmermann <tzimmermann@suse.de>
Reviewed-by: default avatarNoralf Trønnes <noralf@tronnes.org>
Patch-mainline: 20190705092613.7621-2-tzimmermann@suse.de @ 05/07/19, 09:26 a.m.
[stalek@codeaurora.org: replace function name with function pointer
beacuse of comfict].

Change-Id: Ibb154a33375e48e9e34e5402c1f5472ae5cb6e1d
Signed-off-by: default avatarShubham Talekar <stalek@codeaurora.org>
parent 3631f099
Loading
Loading
Loading
Loading
+58 −10
Original line number Original line Diff line number Diff line
@@ -276,6 +276,43 @@ drm_client_buffer_create(struct drm_client_dev *client, u32 width, u32 height, u


	buffer->gem = obj;
	buffer->gem = obj;


	vaddr = drm_client_buffer_vmap(buffer);
	if (IS_ERR(vaddr)) {
		ret = PTR_ERR(vaddr);
		goto err_delete;
	}

	return buffer;

err_delete:
	drm_client_buffer_delete(buffer);

	return ERR_PTR(ret);
}

/**
 * drm_client_buffer_vmap - Map DRM client buffer into address space
 * @buffer: DRM client buffer
 *
 * This function maps a client buffer into kernel address space. If the
 * buffer is already mapped, it returns the mapping's address.
 *
 * Client buffer mappings are not ref'counted. Each call to
 * drm_client_buffer_vmap() should be followed by a call to
 * drm_client_buffer_vunmap(); or the client buffer should be mapped
 * throughout its lifetime. The latter is the default.
 *
 * Returns:
 *	The mapped memory's address
 */
void *drm_client_buffer_vmap(struct drm_client_buffer *buffer)
{
	struct drm_device *dev = buffer->client->dev;
	void *vaddr;

	if (buffer->vaddr)
		return buffer->vaddr;

	/*
	/*
	 * FIXME: The dependency on GEM here isn't required, we could
	 * FIXME: The dependency on GEM here isn't required, we could
	 * convert the driver handle to a dma-buf instead and use the
	 * convert the driver handle to a dma-buf instead and use the
@@ -284,21 +321,32 @@ 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
	 * fd_install step out of the driver backend hooks, to make that
	 * final step optional for internal users.
	 * final step optional for internal users.
	 */
	 */
	vaddr = dev->driver->gem_prime_vmap(obj);
	vaddr = dev->driver->gem_prime_vmap(buffer->gem);
	if (!vaddr) {
	if (IS_ERR(vaddr))
		ret = -ENOMEM;
		return vaddr;
		goto err_delete;
	}


	buffer->vaddr = vaddr;
	buffer->vaddr = vaddr;


	return buffer;
	return vaddr;

}
err_delete:
EXPORT_SYMBOL(drm_client_buffer_vmap);
	drm_client_buffer_delete(buffer);
/**
 * drm_client_buffer_vunmap - Unmap DRM client buffer
 * @buffer: DRM client buffer
 *
 * This function removes a client buffer's memory mapping. This
 * function is only required by clients that manage their buffers
 * by themselves. By default, DRM client buffers are mapped throughout
 * their entire lifetime.
 */
void drm_client_buffer_vunmap(struct drm_client_buffer *buffer)
{
	struct drm_device *dev = buffer->client->dev;


	return ERR_PTR(ret);
	dev->driver->gem_prime_vunmap(buffer->gem, buffer->vaddr);
	buffer->vaddr = NULL;
}
}
EXPORT_SYMBOL(drm_client_buffer_vunmap);


static void drm_client_buffer_rmfb(struct drm_client_buffer *buffer)
static void drm_client_buffer_rmfb(struct drm_client_buffer *buffer)
{
{
+2 −0
Original line number Original line Diff line number Diff line
@@ -147,6 +147,8 @@ struct drm_client_buffer {
struct drm_client_buffer *
struct drm_client_buffer *
drm_client_framebuffer_create(struct drm_client_dev *client, u32 width, u32 height, u32 format);
drm_client_framebuffer_create(struct drm_client_dev *client, u32 width, u32 height, u32 format);
void drm_client_framebuffer_delete(struct drm_client_buffer *buffer);
void drm_client_framebuffer_delete(struct drm_client_buffer *buffer);
void *drm_client_buffer_vmap(struct drm_client_buffer *buffer);
void drm_client_buffer_vunmap(struct drm_client_buffer *buffer);


int drm_client_modeset_create(struct drm_client_dev *client);
int drm_client_modeset_create(struct drm_client_dev *client);
void drm_client_modeset_free(struct drm_client_dev *client);
void drm_client_modeset_free(struct drm_client_dev *client);