Commit 37408cd8 authored by Thomas Zimmermann's avatar Thomas Zimmermann
Browse files

drm/gem: Provide drm_gem_fb_{begin,end}_cpu_access() helpers



Implement helpers drm_gem_fb_begin_cpu_access() and _end_cpu_access(),
which call the rsp dma-buf functions for all GEM BOs of the given
framebuffer.

Calls to dma_buf_end_cpu_access() can return an error code on failure,
while drm_gem_fb_end_cpu_access() does not. The latter runs during DRM's
atomic commit or during cleanup. Both cases don't allow for errors, so
leave out the return value.

v2:
	* fix typo in docs (Daniel)

Signed-off-by: default avatarThomas Zimmermann <tzimmermann@suse.de>
Reviewed-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
Reviewed-by: default avatarNoralf Trønnes <noralf@tronnes.org>
Link: https://patchwork.freedesktop.org/patch/msgid/20210716140801.1215-2-tzimmermann@suse.de
parent a791cde6
Loading
Loading
Loading
Loading
+89 −0
Original line number Diff line number Diff line
@@ -306,6 +306,95 @@ drm_gem_fb_create_with_dirty(struct drm_device *dev, struct drm_file *file,
}
EXPORT_SYMBOL_GPL(drm_gem_fb_create_with_dirty);

/**
 * drm_gem_fb_begin_cpu_access - prepares GEM buffer objects for CPU access
 * @fb: the framebuffer
 * @dir: access mode
 *
 * Prepares a framebuffer's GEM buffer objects for CPU access. This function
 * must be called before accessing the BO data within the kernel. For imported
 * BOs, the function calls dma_buf_begin_cpu_access().
 *
 * See drm_gem_fb_end_cpu_access() for signalling the end of CPU access.
 *
 * Returns:
 * 0 on success, or a negative errno code otherwise.
 */
int drm_gem_fb_begin_cpu_access(struct drm_framebuffer *fb, enum dma_data_direction dir)
{
	struct dma_buf_attachment *import_attach;
	struct drm_gem_object *obj;
	size_t i;
	int ret, ret2;

	for (i = 0; i < ARRAY_SIZE(fb->obj); ++i) {
		obj = drm_gem_fb_get_obj(fb, i);
		if (!obj)
			continue;
		import_attach = obj->import_attach;
		if (!import_attach)
			continue;
		ret = dma_buf_begin_cpu_access(import_attach->dmabuf, dir);
		if (ret)
			goto err_dma_buf_end_cpu_access;
	}

	return 0;

err_dma_buf_end_cpu_access:
	while (i) {
		--i;
		obj = drm_gem_fb_get_obj(fb, i);
		if (!obj)
			continue;
		import_attach = obj->import_attach;
		if (!import_attach)
			continue;
		ret2 = dma_buf_end_cpu_access(import_attach->dmabuf, dir);
		if (ret2) {
			drm_err(fb->dev,
				"dma_buf_end_cpu_access() failed during error handling: %d\n",
				ret2);
		}
	}

	return ret;
}
EXPORT_SYMBOL(drm_gem_fb_begin_cpu_access);

/**
 * drm_gem_fb_end_cpu_access - signals end of CPU access to GEM buffer objects
 * @fb: the framebuffer
 * @dir: access mode
 *
 * Signals the end of CPU access to the given framebuffer's GEM buffer objects. This
 * function must be paired with a corresponding call to drm_gem_fb_begin_cpu_access().
 * For imported BOs, the function calls dma_buf_end_cpu_access().
 *
 * See also drm_gem_fb_begin_cpu_access().
 */
void drm_gem_fb_end_cpu_access(struct drm_framebuffer *fb, enum dma_data_direction dir)
{
	size_t i = ARRAY_SIZE(fb->obj);
	struct dma_buf_attachment *import_attach;
	struct drm_gem_object *obj;
	int ret;

	while (i) {
		--i;
		obj = drm_gem_fb_get_obj(fb, i);
		if (!obj)
			continue;
		import_attach = obj->import_attach;
		if (!import_attach)
			continue;
		ret = dma_buf_end_cpu_access(import_attach->dmabuf, dir);
		if (ret)
			drm_err(fb->dev, "dma_buf_end_cpu_access() failed: %d\n", ret);
	}
}
EXPORT_SYMBOL(drm_gem_fb_end_cpu_access);

static __u32 drm_gem_afbc_get_bpp(struct drm_device *dev,
				  const struct drm_mode_fb_cmd2 *mode_cmd)
{
+6 −0
Original line number Diff line number Diff line
#ifndef __DRM_GEM_FB_HELPER_H__
#define __DRM_GEM_FB_HELPER_H__

#include <linux/dma-buf.h>
#include <linux/dma-buf-map.h>

struct drm_afbc_framebuffer;
struct drm_device;
struct drm_fb_helper_surface_size;
@@ -34,6 +37,9 @@ struct drm_framebuffer *
drm_gem_fb_create_with_dirty(struct drm_device *dev, struct drm_file *file,
			     const struct drm_mode_fb_cmd2 *mode_cmd);

int drm_gem_fb_begin_cpu_access(struct drm_framebuffer *fb, enum dma_data_direction dir);
void drm_gem_fb_end_cpu_access(struct drm_framebuffer *fb, enum dma_data_direction dir);

#define drm_is_afbc(modifier) \
	(((modifier) & AFBC_VENDOR_AND_TYPE_MASK) == DRM_FORMAT_MOD_ARM_AFBC(0))