summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c
diff options
context:
space:
mode:
authorThomas Hellstrom <thellstrom@vmware.com>2018-03-22 10:19:01 +0100
committerThomas Hellstrom <thellstrom@vmware.com>2018-03-22 12:08:23 +0100
commitbf833fd36f9bdc2c86e1fdc90318e4c99b452472 (patch)
tree58de8089e9a4951fe1fc65836499263117d25d2c /drivers/gpu/drm/vmwgfx/vmwgfx_fb.c
parentdc366364c4ef809dccd063919314301f8ba01ac2 (diff)
drm/vmwgfx: Avoid pinning fbdev framebuffers
fbdev framebuffers were previously pinned to be able to keep them mapped across updates. This commit introduces a mechanism that instead revalidates the map on each update, keeping the map cached across updates. The cached map is torn down if the underlying pages change. Typically on buffer object moves and swapouts. This should be nicer to the system when we have resource contention. Testing done: Basic fbdev functionality under Fedora 27. Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com> Signed-off-by: Sinclair Yeh <syeh@vmware.com> Reviewed-by: Brian Paul <brianp@vmware.com> Reviewed-by: Deepak Rawat <drawat@vmware.com>
Diffstat (limited to 'drivers/gpu/drm/vmwgfx/vmwgfx_fb.c')
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_fb.c67
1 files changed, 18 insertions, 49 deletions
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c
index d23a18aae476..fb4e59ee26c7 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c
@@ -43,8 +43,6 @@ struct vmw_fb_par {
struct mutex bo_mutex;
struct vmw_dma_buffer *vmw_bo;
- struct ttm_bo_kmap_obj map;
- void *bo_ptr;
unsigned bo_size;
struct drm_framebuffer *set_fb;
struct drm_display_mode *set_mode;
@@ -174,11 +172,13 @@ static void vmw_fb_dirty_flush(struct work_struct *work)
struct vmw_private *vmw_priv = par->vmw_priv;
struct fb_info *info = vmw_priv->fb_info;
unsigned long irq_flags;
- s32 dst_x1, dst_x2, dst_y1, dst_y2, w, h;
+ s32 dst_x1, dst_x2, dst_y1, dst_y2, w = 0, h = 0;
u32 cpp, max_x, max_y;
struct drm_clip_rect clip;
struct drm_framebuffer *cur_fb;
u8 *src_ptr, *dst_ptr;
+ struct vmw_dma_buffer *vbo = par->vmw_bo;
+ void *virtual;
if (vmw_priv->suspended)
return;
@@ -188,10 +188,16 @@ static void vmw_fb_dirty_flush(struct work_struct *work)
if (!cur_fb)
goto out_unlock;
+ (void) ttm_read_lock(&vmw_priv->reservation_sem, false);
+ (void) ttm_bo_reserve(&vbo->base, false, false, NULL);
+ virtual = vmw_dma_buffer_map_and_cache(vbo);
+ if (!virtual)
+ goto out_unreserve;
+
spin_lock_irqsave(&par->dirty.lock, irq_flags);
if (!par->dirty.active) {
spin_unlock_irqrestore(&par->dirty.lock, irq_flags);
- goto out_unlock;
+ goto out_unreserve;
}
/*
@@ -221,7 +227,7 @@ static void vmw_fb_dirty_flush(struct work_struct *work)
spin_unlock_irqrestore(&par->dirty.lock, irq_flags);
if (w && h) {
- dst_ptr = (u8 *)par->bo_ptr +
+ dst_ptr = (u8 *)virtual +
(dst_y1 * par->set_fb->pitches[0] + dst_x1 * cpp);
src_ptr = (u8 *)par->vmalloc +
((dst_y1 + par->fb_y) * info->fix.line_length +
@@ -237,7 +243,12 @@ static void vmw_fb_dirty_flush(struct work_struct *work)
clip.x2 = dst_x2;
clip.y1 = dst_y1;
clip.y2 = dst_y2;
+ }
+out_unreserve:
+ ttm_bo_unreserve(&vbo->base);
+ ttm_read_unlock(&vmw_priv->reservation_sem);
+ if (w && h) {
WARN_ON_ONCE(par->set_fb->funcs->dirty(cur_fb, NULL, 0, 0,
&clip, 1));
vmw_fifo_flush(vmw_priv, false);
@@ -504,18 +515,8 @@ static int vmw_fb_kms_detach(struct vmw_fb_par *par,
par->set_fb = NULL;
}
- if (par->vmw_bo && detach_bo) {
- struct vmw_private *vmw_priv = par->vmw_priv;
-
- if (par->bo_ptr) {
- ttm_bo_kunmap(&par->map);
- par->bo_ptr = NULL;
- }
- if (unref_bo)
- vmw_dmabuf_unreference(&par->vmw_bo);
- else if (vmw_priv->active_display_unit != vmw_du_legacy)
- vmw_dmabuf_unpin(par->vmw_priv, par->vmw_bo, false);
- }
+ if (par->vmw_bo && detach_bo && unref_bo)
+ vmw_dmabuf_unreference(&par->vmw_bo);
return 0;
}
@@ -636,38 +637,6 @@ static int vmw_fb_set_par(struct fb_info *info)
if (ret)
goto out_unlock;
- if (!par->bo_ptr) {
- struct vmw_framebuffer *vfb = vmw_framebuffer_to_vfb(set.fb);
-
- /*
- * Pin before mapping. Since we don't know in what placement
- * to pin, call into KMS to do it for us. LDU doesn't require
- * additional pinning because set_config() would've pinned
- * it already
- */
- if (vmw_priv->active_display_unit != vmw_du_legacy) {
- ret = vfb->pin(vfb);
- if (ret) {
- DRM_ERROR("Could not pin the fbdev "
- "framebuffer.\n");
- goto out_unlock;
- }
- }
-
- ret = ttm_bo_kmap(&par->vmw_bo->base, 0,
- par->vmw_bo->base.num_pages, &par->map);
- if (ret) {
- if (vmw_priv->active_display_unit != vmw_du_legacy)
- vfb->unpin(vfb);
-
- DRM_ERROR("Could not map the fbdev framebuffer.\n");
- goto out_unlock;
- }
-
- par->bo_ptr = ttm_kmap_obj_virtual(&par->map, &par->bo_iowrite);
- }
-
-
vmw_fb_dirty_mark(par, par->fb_x, par->fb_y,
par->set_fb->width, par->set_fb->height);