drm/cirrus: Move vmap out of commit tail
Vmap operations may acquire the dmabuf reservation lock, which is not allowed within atomic commit-tail functions. Therefore move vmap and vunmap from the damage handler into prepare_fb and cleanup_fb callbacks. The mapping is provided as GEM shadow-buffered plane. The functions in the commit tail use the pre-established mapping for damage handling. Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Tested-by: Gerd Hoffmann <kraxel@redhat.com> Acked-by: Gerd Hoffmann <kraxel@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20210208115538.6430-6-tzimmermann@suse.de
This commit is contained in:
@@ -33,8 +33,9 @@
|
|||||||
#include <drm/drm_file.h>
|
#include <drm/drm_file.h>
|
||||||
#include <drm/drm_format_helper.h>
|
#include <drm/drm_format_helper.h>
|
||||||
#include <drm/drm_fourcc.h>
|
#include <drm/drm_fourcc.h>
|
||||||
#include <drm/drm_gem_shmem_helper.h>
|
#include <drm/drm_gem_atomic_helper.h>
|
||||||
#include <drm/drm_gem_framebuffer_helper.h>
|
#include <drm/drm_gem_framebuffer_helper.h>
|
||||||
|
#include <drm/drm_gem_shmem_helper.h>
|
||||||
#include <drm/drm_ioctl.h>
|
#include <drm/drm_ioctl.h>
|
||||||
#include <drm/drm_managed.h>
|
#include <drm/drm_managed.h>
|
||||||
#include <drm/drm_modeset_helper_vtables.h>
|
#include <drm/drm_modeset_helper_vtables.h>
|
||||||
@@ -311,22 +312,15 @@ static int cirrus_mode_set(struct cirrus_device *cirrus,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cirrus_fb_blit_rect(struct drm_framebuffer *fb,
|
static int cirrus_fb_blit_rect(struct drm_framebuffer *fb, const struct dma_buf_map *map,
|
||||||
struct drm_rect *rect)
|
struct drm_rect *rect)
|
||||||
{
|
{
|
||||||
struct cirrus_device *cirrus = to_cirrus(fb->dev);
|
struct cirrus_device *cirrus = to_cirrus(fb->dev);
|
||||||
struct dma_buf_map map;
|
void *vmap = map->vaddr; /* TODO: Use mapping abstraction properly */
|
||||||
void *vmap;
|
int idx;
|
||||||
int idx, ret;
|
|
||||||
|
|
||||||
ret = -ENODEV;
|
|
||||||
if (!drm_dev_enter(&cirrus->dev, &idx))
|
if (!drm_dev_enter(&cirrus->dev, &idx))
|
||||||
goto out;
|
return -ENODEV;
|
||||||
|
|
||||||
ret = drm_gem_shmem_vmap(fb->obj[0], &map);
|
|
||||||
if (ret)
|
|
||||||
goto out_dev_exit;
|
|
||||||
vmap = map.vaddr; /* TODO: Use mapping abstraction properly */
|
|
||||||
|
|
||||||
if (cirrus->cpp == fb->format->cpp[0])
|
if (cirrus->cpp == fb->format->cpp[0])
|
||||||
drm_fb_memcpy_dstclip(cirrus->vram,
|
drm_fb_memcpy_dstclip(cirrus->vram,
|
||||||
@@ -345,16 +339,12 @@ static int cirrus_fb_blit_rect(struct drm_framebuffer *fb,
|
|||||||
else
|
else
|
||||||
WARN_ON_ONCE("cpp mismatch");
|
WARN_ON_ONCE("cpp mismatch");
|
||||||
|
|
||||||
drm_gem_shmem_vunmap(fb->obj[0], &map);
|
|
||||||
ret = 0;
|
|
||||||
|
|
||||||
out_dev_exit:
|
|
||||||
drm_dev_exit(idx);
|
drm_dev_exit(idx);
|
||||||
out:
|
|
||||||
return ret;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cirrus_fb_blit_fullscreen(struct drm_framebuffer *fb)
|
static int cirrus_fb_blit_fullscreen(struct drm_framebuffer *fb, const struct dma_buf_map *map)
|
||||||
{
|
{
|
||||||
struct drm_rect fullscreen = {
|
struct drm_rect fullscreen = {
|
||||||
.x1 = 0,
|
.x1 = 0,
|
||||||
@@ -362,7 +352,7 @@ static int cirrus_fb_blit_fullscreen(struct drm_framebuffer *fb)
|
|||||||
.y1 = 0,
|
.y1 = 0,
|
||||||
.y2 = fb->height,
|
.y2 = fb->height,
|
||||||
};
|
};
|
||||||
return cirrus_fb_blit_rect(fb, &fullscreen);
|
return cirrus_fb_blit_rect(fb, map, &fullscreen);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cirrus_check_size(int width, int height,
|
static int cirrus_check_size(int width, int height,
|
||||||
@@ -441,9 +431,10 @@ static void cirrus_pipe_enable(struct drm_simple_display_pipe *pipe,
|
|||||||
struct drm_plane_state *plane_state)
|
struct drm_plane_state *plane_state)
|
||||||
{
|
{
|
||||||
struct cirrus_device *cirrus = to_cirrus(pipe->crtc.dev);
|
struct cirrus_device *cirrus = to_cirrus(pipe->crtc.dev);
|
||||||
|
struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
|
||||||
|
|
||||||
cirrus_mode_set(cirrus, &crtc_state->mode, plane_state->fb);
|
cirrus_mode_set(cirrus, &crtc_state->mode, plane_state->fb);
|
||||||
cirrus_fb_blit_fullscreen(plane_state->fb);
|
cirrus_fb_blit_fullscreen(plane_state->fb, &shadow_plane_state->map[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cirrus_pipe_update(struct drm_simple_display_pipe *pipe,
|
static void cirrus_pipe_update(struct drm_simple_display_pipe *pipe,
|
||||||
@@ -451,16 +442,15 @@ static void cirrus_pipe_update(struct drm_simple_display_pipe *pipe,
|
|||||||
{
|
{
|
||||||
struct cirrus_device *cirrus = to_cirrus(pipe->crtc.dev);
|
struct cirrus_device *cirrus = to_cirrus(pipe->crtc.dev);
|
||||||
struct drm_plane_state *state = pipe->plane.state;
|
struct drm_plane_state *state = pipe->plane.state;
|
||||||
|
struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(state);
|
||||||
struct drm_crtc *crtc = &pipe->crtc;
|
struct drm_crtc *crtc = &pipe->crtc;
|
||||||
struct drm_rect rect;
|
struct drm_rect rect;
|
||||||
|
|
||||||
if (pipe->plane.state->fb &&
|
if (state->fb && cirrus->cpp != cirrus_cpp(state->fb))
|
||||||
cirrus->cpp != cirrus_cpp(pipe->plane.state->fb))
|
cirrus_mode_set(cirrus, &crtc->mode, state->fb);
|
||||||
cirrus_mode_set(cirrus, &crtc->mode,
|
|
||||||
pipe->plane.state->fb);
|
|
||||||
|
|
||||||
if (drm_atomic_helper_damage_merged(old_state, state, &rect))
|
if (drm_atomic_helper_damage_merged(old_state, state, &rect))
|
||||||
cirrus_fb_blit_rect(pipe->plane.state->fb, &rect);
|
cirrus_fb_blit_rect(state->fb, &shadow_plane_state->map[0], &rect);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct drm_simple_display_pipe_funcs cirrus_pipe_funcs = {
|
static const struct drm_simple_display_pipe_funcs cirrus_pipe_funcs = {
|
||||||
@@ -468,6 +458,7 @@ static const struct drm_simple_display_pipe_funcs cirrus_pipe_funcs = {
|
|||||||
.check = cirrus_pipe_check,
|
.check = cirrus_pipe_check,
|
||||||
.enable = cirrus_pipe_enable,
|
.enable = cirrus_pipe_enable,
|
||||||
.update = cirrus_pipe_update,
|
.update = cirrus_pipe_update,
|
||||||
|
DRM_GEM_SIMPLE_DISPLAY_PIPE_SHADOW_PLANE_FUNCS,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const uint32_t cirrus_formats[] = {
|
static const uint32_t cirrus_formats[] = {
|
||||||
|
|||||||
Reference in New Issue
Block a user