Commit 0d384eec authored by Thomas Zimmermann's avatar Thomas Zimmermann

drm/ast: Keep cursor HW BOs mapped

Updating the image in a cursor's HW BO requires a mapping of the BO's
buffer in the kernel's address space. Cursor image updates can happen
frequently and create CPU overhead.

As cursor HW BOs are small and never move, they are now map exactly
once during the initialization and the mapping is used throughout the
driver's lifetime.

This change also removes a possible source of failures from
ast_cursor_show(). As the helper does not establish mappings, it cannot
fail. As a result, the cursor plane's atomic-update helper does not
call any failable interfaces. All failures are detected before trying
to update the cursor plane.
Signed-off-by: default avatarThomas Zimmermann <tzimmermann@suse.de>
Acked-by: default avatarSam Ravnborg <sam@ravnborg.org>
Link: https://patchwork.freedesktop.org/patch/msgid/20200702115029.5281-10-tzimmermann@suse.de
parent c91eadd1
...@@ -39,6 +39,7 @@ int ast_cursor_init(struct ast_private *ast) ...@@ -39,6 +39,7 @@ int ast_cursor_init(struct ast_private *ast)
struct drm_device *dev = ast->dev; struct drm_device *dev = ast->dev;
size_t size, i; size_t size, i;
struct drm_gem_vram_object *gbo; struct drm_gem_vram_object *gbo;
void __iomem *vaddr;
int ret; int ret;
size = roundup(AST_HWC_SIZE + AST_HWC_SIGNATURE_SIZE, PAGE_SIZE); size = roundup(AST_HWC_SIZE + AST_HWC_SIGNATURE_SIZE, PAGE_SIZE);
...@@ -55,8 +56,16 @@ int ast_cursor_init(struct ast_private *ast) ...@@ -55,8 +56,16 @@ int ast_cursor_init(struct ast_private *ast)
drm_gem_vram_put(gbo); drm_gem_vram_put(gbo);
goto err_drm_gem_vram_put; goto err_drm_gem_vram_put;
} }
vaddr = drm_gem_vram_vmap(gbo);
if (IS_ERR(vaddr)) {
ret = PTR_ERR(vaddr);
drm_gem_vram_unpin(gbo);
drm_gem_vram_put(gbo);
goto err_drm_gem_vram_put;
}
ast->cursor.gbo[i] = gbo; ast->cursor.gbo[i] = gbo;
ast->cursor.vaddr[i] = vaddr;
} }
return 0; return 0;
...@@ -65,9 +74,11 @@ int ast_cursor_init(struct ast_private *ast) ...@@ -65,9 +74,11 @@ int ast_cursor_init(struct ast_private *ast)
while (i) { while (i) {
--i; --i;
gbo = ast->cursor.gbo[i]; gbo = ast->cursor.gbo[i];
drm_gem_vram_vunmap(gbo, ast->cursor.vaddr[i]);
drm_gem_vram_unpin(gbo); drm_gem_vram_unpin(gbo);
drm_gem_vram_put(gbo); drm_gem_vram_put(gbo);
ast->cursor.gbo[i] = NULL; ast->cursor.gbo[i] = NULL;
ast->cursor.vaddr[i] = NULL;
} }
return ret; return ret;
} }
...@@ -79,6 +90,7 @@ void ast_cursor_fini(struct ast_private *ast) ...@@ -79,6 +90,7 @@ void ast_cursor_fini(struct ast_private *ast)
for (i = 0; i < ARRAY_SIZE(ast->cursor.gbo); ++i) { for (i = 0; i < ARRAY_SIZE(ast->cursor.gbo); ++i) {
gbo = ast->cursor.gbo[i]; gbo = ast->cursor.gbo[i];
drm_gem_vram_vunmap(gbo, ast->cursor.vaddr[i]);
drm_gem_vram_unpin(gbo); drm_gem_vram_unpin(gbo);
drm_gem_vram_put(gbo); drm_gem_vram_put(gbo);
} }
...@@ -154,7 +166,7 @@ int ast_cursor_blit(struct ast_private *ast, struct drm_framebuffer *fb) ...@@ -154,7 +166,7 @@ int ast_cursor_blit(struct ast_private *ast, struct drm_framebuffer *fb)
struct drm_gem_vram_object *gbo; struct drm_gem_vram_object *gbo;
int ret; int ret;
void *src; void *src;
void *dst; void __iomem *dst;
if (drm_WARN_ON_ONCE(dev, fb->width > AST_MAX_HWC_WIDTH) || if (drm_WARN_ON_ONCE(dev, fb->width > AST_MAX_HWC_WIDTH) ||
drm_WARN_ON_ONCE(dev, fb->height > AST_MAX_HWC_HEIGHT)) drm_WARN_ON_ONCE(dev, fb->height > AST_MAX_HWC_HEIGHT))
...@@ -171,28 +183,16 @@ int ast_cursor_blit(struct ast_private *ast, struct drm_framebuffer *fb) ...@@ -171,28 +183,16 @@ int ast_cursor_blit(struct ast_private *ast, struct drm_framebuffer *fb)
goto err_drm_gem_vram_unpin; goto err_drm_gem_vram_unpin;
} }
dst = drm_gem_vram_vmap(ast->cursor.gbo[ast->cursor.next_index]); dst = ast->cursor.vaddr[ast->cursor.next_index];
if (IS_ERR(dst)) {
ret = PTR_ERR(dst);
goto err_drm_gem_vram_vunmap_src;
}
/* do data transfer to cursor BO */ /* do data transfer to cursor BO */
update_cursor_image(dst, src, fb->width, fb->height); update_cursor_image(dst, src, fb->width, fb->height);
/*
* Always unmap buffers here. Destination buffers are
* perma-pinned while the driver is active. We're only
* changing ref-counters here.
*/
drm_gem_vram_vunmap(ast->cursor.gbo[ast->cursor.next_index], dst);
drm_gem_vram_vunmap(gbo, src); drm_gem_vram_vunmap(gbo, src);
drm_gem_vram_unpin(gbo); drm_gem_vram_unpin(gbo);
return 0; return 0;
err_drm_gem_vram_vunmap_src:
drm_gem_vram_vunmap(gbo, src);
err_drm_gem_vram_unpin: err_drm_gem_vram_unpin:
drm_gem_vram_unpin(gbo); drm_gem_vram_unpin(gbo);
return ret; return ret;
...@@ -243,18 +243,14 @@ static void ast_cursor_set_location(struct ast_private *ast, u16 x, u16 y, ...@@ -243,18 +243,14 @@ static void ast_cursor_set_location(struct ast_private *ast, u16 x, u16 y,
ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xc7, y1); ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xc7, y1);
} }
int ast_cursor_show(struct ast_private *ast, int x, int y, void ast_cursor_show(struct ast_private *ast, int x, int y,
unsigned int offset_x, unsigned int offset_y) unsigned int offset_x, unsigned int offset_y)
{ {
struct drm_gem_vram_object *gbo;
u8 x_offset, y_offset; u8 x_offset, y_offset;
u8 *dst, *sig; u8 __iomem *dst, __iomem *sig;
u8 jreg; u8 jreg;
gbo = ast->cursor.gbo[ast->cursor.next_index]; dst = ast->cursor.vaddr[ast->cursor.next_index];
dst = drm_gem_vram_vmap(gbo);
if (IS_ERR(dst))
return PTR_ERR(dst);
sig = dst + AST_HWC_SIZE; sig = dst + AST_HWC_SIZE;
writel(x, sig + AST_HWC_SIGNATURE_X); writel(x, sig + AST_HWC_SIGNATURE_X);
...@@ -279,10 +275,6 @@ int ast_cursor_show(struct ast_private *ast, int x, int y, ...@@ -279,10 +275,6 @@ int ast_cursor_show(struct ast_private *ast, int x, int y,
jreg = 0x02 | jreg = 0x02 |
0x01; /* enable ARGB4444 cursor */ 0x01; /* enable ARGB4444 cursor */
ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xcb, 0xfc, jreg); ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xcb, 0xfc, jreg);
drm_gem_vram_vunmap(gbo, dst);
return 0;
} }
void ast_cursor_hide(struct ast_private *ast) void ast_cursor_hide(struct ast_private *ast)
......
...@@ -116,6 +116,7 @@ struct ast_private { ...@@ -116,6 +116,7 @@ struct ast_private {
struct { struct {
struct drm_gem_vram_object *gbo[AST_DEFAULT_HWC_NUM]; struct drm_gem_vram_object *gbo[AST_DEFAULT_HWC_NUM];
void __iomem *vaddr[AST_DEFAULT_HWC_NUM];
unsigned int next_index; unsigned int next_index;
} cursor; } cursor;
...@@ -319,8 +320,8 @@ int ast_cursor_init(struct ast_private *ast); ...@@ -319,8 +320,8 @@ int ast_cursor_init(struct ast_private *ast);
void ast_cursor_fini(struct ast_private *ast); void ast_cursor_fini(struct ast_private *ast);
int ast_cursor_blit(struct ast_private *ast, struct drm_framebuffer *fb); int ast_cursor_blit(struct ast_private *ast, struct drm_framebuffer *fb);
void ast_cursor_page_flip(struct ast_private *ast); void ast_cursor_page_flip(struct ast_private *ast);
int ast_cursor_show(struct ast_private *ast, int x, int y, void ast_cursor_show(struct ast_private *ast, int x, int y,
unsigned int offset_x, unsigned int offset_y); unsigned int offset_x, unsigned int offset_y);
void ast_cursor_hide(struct ast_private *ast); void ast_cursor_hide(struct ast_private *ast);
#endif #endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment