This patch series basically brings vmwgfx up to date with the standalone repo. Mostly bug-fixes but some new features as well. Most notably the in-kernel time-based throttling support which is advertized by a minor version bump.
From: Jakob Bornecrantz jakob@vmware.com
Signed-off-by: Jakob Bornecrantz jakob@vmware.com Signed-off-by: Thomas Hellstrom thellstrom@vmware.com --- drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 5 +++-- 1 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index 31f9afe..146792e 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c @@ -771,8 +771,9 @@ int vmw_kms_init(struct vmw_private *dev_priv) dev->mode_config.funcs = &vmw_kms_funcs; dev->mode_config.min_width = 1; dev->mode_config.min_height = 1; - dev->mode_config.max_width = dev_priv->fb_max_width; - dev->mode_config.max_height = dev_priv->fb_max_height; + /* assumed largest fb size */ + dev->mode_config.max_width = 8192; + dev->mode_config.max_height = 8192;
ret = vmw_kms_init_legacy_display_system(dev_priv);
From: Jakob Bornecrantz jakob@vmware.com
Signed-off-by: Jakob Bornecrantz jakob@vmware.com Signed-off-by: Thomas Hellstrom thellstrom@vmware.com --- drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c | 3 +++ 1 files changed, 3 insertions(+), 0 deletions(-)
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c index 9089159..be88fc6 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c @@ -130,6 +130,7 @@ static int vmw_ldu_del_active(struct vmw_private *vmw_priv, if (list_empty(&ldu->active)) return 0;
+ /* must init otherwise list_empty(&ldu->active) well not work */ list_del_init(&ldu->active); if (--(ld->num_active) == 0) { BUG_ON(!ld->fb); @@ -208,6 +209,8 @@ static int vmw_ldu_crtc_set_config(struct drm_mode_set *set)
/* ldu only supports one fb active at the time */ if (dev_priv->ldu_priv->fb && vfb && + !(dev_priv->ldu_priv->num_active == 1 && + !list_empty(&ldu->active)) && dev_priv->ldu_priv->fb != vfb) { DRM_ERROR("Multiple framebuffers not supported\n"); return -EINVAL;
From: Jakob Bornecrantz jakob@vmware.com
Signed-off-by: Jakob Bornecrantz jakob@vmware.com Signed-off-by: Thomas Hellstrom thellstrom@vmware.com --- drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c | 17 +++++++++++------ 1 files changed, 11 insertions(+), 6 deletions(-)
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c index be88fc6..93dd9be 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c @@ -150,6 +150,15 @@ static int vmw_ldu_add_active(struct vmw_private *vmw_priv, struct vmw_legacy_display_unit *entry; struct list_head *at;
+ BUG_ON(!ld->num_active && ld->fb); + if (vfb != ld->fb) { + if (ld->fb && ld->fb->unpin) + ld->fb->unpin(ld->fb); + if (vfb->pin) + vfb->pin(vfb); + ld->fb = vfb; + } + if (!list_empty(&ldu->active)) return 0;
@@ -162,12 +171,8 @@ static int vmw_ldu_add_active(struct vmw_private *vmw_priv, }
list_add(&ldu->active, at); - if (ld->num_active++ == 0) { - BUG_ON(ld->fb); - if (vfb->pin) - vfb->pin(vfb); - ld->fb = vfb; - } + + ld->num_active++;
return 0; }
The throttle_us member in the execbuf argument is now honored. If the member is 0, no waiting for lag will occur, which guarantees backwards compatibility with well-behaved clients.
Signed-off-by: Thomas Hellstrom thellstrom@vmware.com --- drivers/gpu/drm/vmwgfx/Makefile | 2 +- drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | 27 +++++- drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c | 9 ++ drivers/gpu/drm/vmwgfx/vmwgfx_fence.c | 173 +++++++++++++++++++++++++++++++ drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c | 5 +- drivers/gpu/drm/vmwgfx/vmwgfx_irq.c | 17 +++- 6 files changed, 227 insertions(+), 6 deletions(-) create mode 100644 drivers/gpu/drm/vmwgfx/vmwgfx_fence.c
diff --git a/drivers/gpu/drm/vmwgfx/Makefile b/drivers/gpu/drm/vmwgfx/Makefile index 1a3cb68..4505e17 100644 --- a/drivers/gpu/drm/vmwgfx/Makefile +++ b/drivers/gpu/drm/vmwgfx/Makefile @@ -4,6 +4,6 @@ ccflags-y := -Iinclude/drm vmwgfx-y := vmwgfx_execbuf.o vmwgfx_gmr.o vmwgfx_kms.o vmwgfx_drv.o \ vmwgfx_fb.o vmwgfx_ioctl.o vmwgfx_resource.o vmwgfx_buffer.o \ vmwgfx_fifo.o vmwgfx_irq.o vmwgfx_ldu.o vmwgfx_ttm_glue.o \ - vmwgfx_overlay.o + vmwgfx_overlay.o vmwgfx_fence.o
obj-$(CONFIG_DRM_VMWGFX) := vmwgfx.o diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h index 356dc93..9a0a82b 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h @@ -41,7 +41,7 @@
#define VMWGFX_DRIVER_DATE "20100209" #define VMWGFX_DRIVER_MAJOR 1 -#define VMWGFX_DRIVER_MINOR 0 +#define VMWGFX_DRIVER_MINOR 1 #define VMWGFX_DRIVER_PATCHLEVEL 0 #define VMWGFX_FILE_PAGE_OFFSET 0x00100000 #define VMWGFX_FIFO_STATIC_SIZE (1024*1024) @@ -102,6 +102,13 @@ struct vmw_surface { struct vmw_cursor_snooper snooper; };
+struct vmw_fence_queue { + struct list_head head; + struct timespec lag; + struct timespec lag_time; + spinlock_t lock; +}; + struct vmw_fifo_state { unsigned long reserved_size; __le32 *dynamic_buffer; @@ -115,6 +122,7 @@ struct vmw_fifo_state { uint32_t capabilities; struct mutex fifo_mutex; struct rw_semaphore rwsem; + struct vmw_fence_queue fence_queue; };
struct vmw_relocation { @@ -441,6 +449,23 @@ extern int vmw_fallback_wait(struct vmw_private *dev_priv, uint32_t sequence, bool interruptible, unsigned long timeout); +extern void vmw_update_sequence(struct vmw_private *dev_priv, + struct vmw_fifo_state *fifo_state); + + +/** + * Rudimentary fence objects currently used only for throttling - + * vmwgfx_fence.c + */ + +extern void vmw_fence_queue_init(struct vmw_fence_queue *queue); +extern void vmw_fence_queue_takedown(struct vmw_fence_queue *queue); +extern int vmw_fence_push(struct vmw_fence_queue *queue, + uint32_t sequence); +extern int vmw_fence_pull(struct vmw_fence_queue *queue, + uint32_t signaled_sequence); +extern int vmw_wait_lag(struct vmw_private *dev_priv, + struct vmw_fence_queue *queue, uint32_t us);
/** * Kernel framebuffer - vmwgfx_fb.c diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c index 0897359..0e425a4 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c @@ -669,6 +669,15 @@ int vmw_execbuf_ioctl(struct drm_device *dev, void *data, goto out_err;
vmw_apply_relocations(sw_context); + + if (arg->throttle_us) { + ret = vmw_wait_lag(dev_priv, &dev_priv->fifo.fence_queue, + arg->throttle_us); + + if (unlikely(ret != 0)) + goto out_err; + } + vmw_fifo_commit(dev_priv, arg->command_size);
ret = vmw_fifo_send_fence(dev_priv, &sequence); diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c new file mode 100644 index 0000000..61eacc1 --- /dev/null +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c @@ -0,0 +1,173 @@ +/************************************************************************** + * + * Copyright (C) 2010 VMware, Inc., Palo Alto, CA., USA + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + + +#include "vmwgfx_drv.h" + +struct vmw_fence { + struct list_head head; + uint32_t sequence; + struct timespec submitted; +}; + +void vmw_fence_queue_init(struct vmw_fence_queue *queue) +{ + INIT_LIST_HEAD(&queue->head); + queue->lag = ns_to_timespec(0); + getrawmonotonic(&queue->lag_time); + spin_lock_init(&queue->lock); +} + +void vmw_fence_queue_takedown(struct vmw_fence_queue *queue) +{ + struct vmw_fence *fence, *next; + + spin_lock(&queue->lock); + list_for_each_entry_safe(fence, next, &queue->head, head) { + kfree(fence); + } + spin_unlock(&queue->lock); +} + +int vmw_fence_push(struct vmw_fence_queue *queue, + uint32_t sequence) +{ + struct vmw_fence *fence = kmalloc(sizeof(*fence), GFP_KERNEL); + + if (unlikely(!fence)) + return -ENOMEM; + + fence->sequence = sequence; + getrawmonotonic(&fence->submitted); + spin_lock(&queue->lock); + list_add_tail(&fence->head, &queue->head); + spin_unlock(&queue->lock); + + return 0; +} + +int vmw_fence_pull(struct vmw_fence_queue *queue, + uint32_t signaled_sequence) +{ + struct vmw_fence *fence, *next; + struct timespec now; + bool updated = false; + + spin_lock(&queue->lock); + getrawmonotonic(&now); + + if (list_empty(&queue->head)) { + queue->lag = ns_to_timespec(0); + queue->lag_time = now; + updated = true; + goto out_unlock; + } + + list_for_each_entry_safe(fence, next, &queue->head, head) { + if (signaled_sequence - fence->sequence > (1 << 30)) + continue; + + queue->lag = timespec_sub(now, fence->submitted); + queue->lag_time = now; + updated = true; + list_del(&fence->head); + kfree(fence); + } + +out_unlock: + spin_unlock(&queue->lock); + + return (updated) ? 0 : -EBUSY; +} + +static struct timespec vmw_timespec_add(struct timespec t1, + struct timespec t2) +{ + t1.tv_sec += t2.tv_sec; + t1.tv_nsec += t2.tv_nsec; + if (t1.tv_nsec >= 1000000000L) { + t1.tv_sec += 1; + t1.tv_nsec -= 1000000000L; + } + + return t1; +} + +static struct timespec vmw_fifo_lag(struct vmw_fence_queue *queue) +{ + struct timespec now; + + spin_lock(&queue->lock); + getrawmonotonic(&now); + queue->lag = vmw_timespec_add(queue->lag, + timespec_sub(now, queue->lag_time)); + queue->lag_time = now; + spin_unlock(&queue->lock); + return queue->lag; +} + + +static bool vmw_lag_lt(struct vmw_fence_queue *queue, + uint32_t us) +{ + struct timespec lag, cond; + + cond = ns_to_timespec((s64) us * 1000); + lag = vmw_fifo_lag(queue); + return (timespec_compare(&lag, &cond) < 1); +} + +int vmw_wait_lag(struct vmw_private *dev_priv, + struct vmw_fence_queue *queue, uint32_t us) +{ + struct vmw_fence *fence; + uint32_t sequence; + int ret; + + while (!vmw_lag_lt(queue, us)) { + spin_lock(&queue->lock); + if (list_empty(&queue->head)) + sequence = atomic_read(&dev_priv->fence_seq); + else { + fence = list_first_entry(&queue->head, + struct vmw_fence, head); + sequence = fence->sequence; + } + spin_unlock(&queue->lock); + + ret = vmw_wait_fence(dev_priv, false, sequence, true, + 3*HZ); + + if (unlikely(ret != 0)) + return ret; + + (void) vmw_fence_pull(queue, sequence); + } + return 0; +} + + diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c index 39d43a0..a8e5445 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c @@ -120,7 +120,7 @@ int vmw_fifo_init(struct vmw_private *dev_priv, struct vmw_fifo_state *fifo)
atomic_set(&dev_priv->fence_seq, dev_priv->last_read_sequence); iowrite32(dev_priv->last_read_sequence, fifo_mem + SVGA_FIFO_FENCE); - + vmw_fence_queue_init(&fifo->fence_queue); return vmw_fifo_send_fence(dev_priv, &dummy); out_err: vfree(fifo->static_buffer); @@ -159,6 +159,7 @@ void vmw_fifo_release(struct vmw_private *dev_priv, struct vmw_fifo_state *fifo) dev_priv->enable_state);
mutex_unlock(&dev_priv->hw_mutex); + vmw_fence_queue_takedown(&fifo->fence_queue);
if (likely(fifo->last_buffer != NULL)) { vfree(fifo->last_buffer); @@ -484,6 +485,8 @@ int vmw_fifo_send_fence(struct vmw_private *dev_priv, uint32_t *sequence) fifo_state->last_buffer_add = true; vmw_fifo_commit(dev_priv, bytes); fifo_state->last_buffer_add = false; + (void) vmw_fence_push(&fifo_state->fence_queue, *sequence); + vmw_update_sequence(dev_priv, fifo_state);
out_err: return ret; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c b/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c index 4d7cb53..e92298a 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c @@ -64,22 +64,33 @@ static bool vmw_fifo_idle(struct vmw_private *dev_priv, uint32_t sequence) return (busy == 0); }
+void vmw_update_sequence(struct vmw_private *dev_priv, + struct vmw_fifo_state *fifo_state) +{ + __le32 __iomem *fifo_mem = dev_priv->mmio_virt; + + uint32_t sequence = ioread32(fifo_mem + SVGA_FIFO_FENCE); + + if (dev_priv->last_read_sequence != sequence) { + dev_priv->last_read_sequence = sequence; + vmw_fence_pull(&fifo_state->fence_queue, sequence); + } +}
bool vmw_fence_signaled(struct vmw_private *dev_priv, uint32_t sequence) { - __le32 __iomem *fifo_mem = dev_priv->mmio_virt; struct vmw_fifo_state *fifo_state; bool ret;
if (likely(dev_priv->last_read_sequence - sequence < VMW_FENCE_WRAP)) return true;
- dev_priv->last_read_sequence = ioread32(fifo_mem + SVGA_FIFO_FENCE); + fifo_state = &dev_priv->fifo; + vmw_update_sequence(dev_priv, fifo_state); if (likely(dev_priv->last_read_sequence - sequence < VMW_FENCE_WRAP)) return true;
- fifo_state = &dev_priv->fifo; if (!(fifo_state->capabilities & SVGA_FIFO_CAP_FENCE) && vmw_fifo_idle(dev_priv, sequence)) return true;
From: Jakob Bornecrantz jakob@vmware.com
Also make sure the ldu::active member is properly initialized. Part of fix by Michel Daenzer daenzer@vmware.com.
Signed-off-by: Jakob Bornecrantz jakob@vmware.com Signed-off-by: Michel Daenzer daenzer@vmware.com Signed-off-by: Thomas Hellstrom thellstrom@vmware.com --- drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c | 10 +++------- 1 files changed, 3 insertions(+), 7 deletions(-)
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c index 93dd9be..06618a3 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c @@ -456,13 +456,11 @@ static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit) encoder = &ldu->base.encoder; connector = &ldu->base.connector;
+ INIT_LIST_HEAD(&ldu->active); + drm_connector_init(dev, connector, &vmw_legacy_connector_funcs, DRM_MODE_CONNECTOR_LVDS); - /* Initial status */ - if (unit == 0) - connector->status = connector_status_connected; - else - connector->status = connector_status_disconnected; + connector->status = vmw_ldu_connector_detect(connector);
drm_encoder_init(dev, encoder, &vmw_legacy_encoder_funcs, DRM_MODE_ENCODER_LVDS); @@ -470,8 +468,6 @@ static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit) encoder->possible_crtcs = (1 << unit); encoder->possible_clones = 0;
- INIT_LIST_HEAD(&ldu->active); - drm_crtc_init(dev, crtc, &vmw_legacy_crtc_funcs);
drm_connector_attach_property(connector,
From: Jakob Bornecrantz jakob@vmware.com
Signed-off-by: Jakob Bornecrantz jakob@vmware.com Signed-off-by: Thomas Hellstrom thellstrom@vmware.com --- drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 9 ++++ drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | 5 ++ drivers/gpu/drm/vmwgfx/vmwgfx_fb.c | 81 ++++++++++++---------------------- drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c | 18 ++++++++ drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 72 +++++++++++++----------------- drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c | 70 ++++++++++++++++++++++++----- 6 files changed, 148 insertions(+), 107 deletions(-)
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index 0c9c081..6241255 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c @@ -318,6 +318,15 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset) goto out_err3; }
+ /* need mmio memory to check for fifo pitchlock cap */ + if (!(dev_priv->capabilities & SVGA_CAP_DISPLAY_TOPOLOGY) && + !(dev_priv->capabilities & SVGA_CAP_PITCHLOCK) && + !vmw_fifo_have_pitchlock(dev_priv)) { + ret = -ENOSYS; + DRM_ERROR("Hardware has no pitchlock\n"); + goto out_err4; + } + dev_priv->tdev = ttm_object_device_init (dev_priv->mem_global_ref.object, 12);
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h index 9a0a82b..1341ade 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h @@ -187,6 +187,7 @@ struct vmw_private { uint32_t vga_red_mask; uint32_t vga_blue_mask; uint32_t vga_green_mask; + uint32_t vga_pitchlock;
/* * Framebuffer info. @@ -401,6 +402,7 @@ extern int vmw_fifo_send_fence(struct vmw_private *dev_priv, extern void vmw_fifo_ping_host(struct vmw_private *dev_priv, uint32_t reason); extern int vmw_fifo_mmap(struct file *filp, struct vm_area_struct *vma); extern bool vmw_fifo_have_3d(struct vmw_private *dev_priv); +extern bool vmw_fifo_have_pitchlock(struct vmw_private *dev_priv);
/** * TTM glue - vmwgfx_ttm_glue.c @@ -491,6 +493,9 @@ void vmw_kms_cursor_snoop(struct vmw_surface *srf, struct ttm_object_file *tfile, struct ttm_buffer_object *bo, SVGA3dCmdHeader *header); +void vmw_kms_write_svga(struct vmw_private *vmw_priv, + unsigned width, unsigned height, unsigned pitch, + unsigned bbp, unsigned depth);
/** * Overlay control - vmwgfx_overlay.c diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c index a933670..897ece5 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c @@ -132,16 +132,14 @@ static int vmw_fb_check_var(struct fb_var_screeninfo *var, return -EINVAL; }
- /* without multimon its hard to resize */ - if (!(vmw_priv->capabilities & SVGA_CAP_MULTIMON) && - (var->xres != par->max_width || - var->yres != par->max_height)) { - DRM_ERROR("Tried to resize, but we don't have multimon\n"); + if (!(vmw_priv->capabilities & SVGA_CAP_DISPLAY_TOPOLOGY) && + (var->xoffset != 0 || var->yoffset != 0)) { + DRM_ERROR("Can not handle panning without display topology\n"); return -EINVAL; }
- if (var->xres > par->max_width || - var->yres > par->max_height) { + if ((var->xoffset + var->xres) > par->max_width || + (var->yoffset + var->yres) > par->max_height) { DRM_ERROR("Requested geom can not fit in framebuffer\n"); return -EINVAL; } @@ -154,8 +152,8 @@ static int vmw_fb_set_par(struct fb_info *info) struct vmw_fb_par *par = info->par; struct vmw_private *vmw_priv = par->vmw_priv;
- if (vmw_priv->capabilities & SVGA_CAP_MULTIMON) { - vmw_write(vmw_priv, SVGA_REG_NUM_GUEST_DISPLAYS, 1); + if (vmw_priv->capabilities & SVGA_CAP_DISPLAY_TOPOLOGY) { + vmw_write(vmw_priv, SVGA_REG_ENABLE, 0); vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, 0); vmw_write(vmw_priv, SVGA_REG_DISPLAY_IS_PRIMARY, true); vmw_write(vmw_priv, SVGA_REG_DISPLAY_POSITION_X, 0); @@ -164,18 +162,11 @@ static int vmw_fb_set_par(struct fb_info *info) vmw_write(vmw_priv, SVGA_REG_DISPLAY_HEIGHT, 0); vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, SVGA_ID_INVALID);
- vmw_write(vmw_priv, SVGA_REG_ENABLE, 1); - vmw_write(vmw_priv, SVGA_REG_WIDTH, par->max_width); - vmw_write(vmw_priv, SVGA_REG_HEIGHT, par->max_height); - vmw_write(vmw_priv, SVGA_REG_BITS_PER_PIXEL, par->bpp); - vmw_write(vmw_priv, SVGA_REG_DEPTH, par->depth); - vmw_write(vmw_priv, SVGA_REG_RED_MASK, 0x00ff0000); - vmw_write(vmw_priv, SVGA_REG_GREEN_MASK, 0x0000ff00); - vmw_write(vmw_priv, SVGA_REG_BLUE_MASK, 0x000000ff); + vmw_kms_write_svga(vmw_priv, info->var.xres, info->var.yres, + info->fix.line_length, + par->bpp, par->depth);
/* TODO check if pitch and offset changes */ - - vmw_write(vmw_priv, SVGA_REG_NUM_GUEST_DISPLAYS, 1); vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, 0); vmw_write(vmw_priv, SVGA_REG_DISPLAY_IS_PRIMARY, true); vmw_write(vmw_priv, SVGA_REG_DISPLAY_POSITION_X, info->var.xoffset); @@ -183,13 +174,22 @@ static int vmw_fb_set_par(struct fb_info *info) vmw_write(vmw_priv, SVGA_REG_DISPLAY_WIDTH, info->var.xres); vmw_write(vmw_priv, SVGA_REG_DISPLAY_HEIGHT, info->var.yres); vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, SVGA_ID_INVALID); + vmw_write(vmw_priv, SVGA_REG_NUM_GUEST_DISPLAYS, 1); + vmw_write(vmw_priv, SVGA_REG_ENABLE, 1); } else { - vmw_write(vmw_priv, SVGA_REG_WIDTH, info->var.xres); - vmw_write(vmw_priv, SVGA_REG_HEIGHT, info->var.yres); + vmw_write(vmw_priv, SVGA_REG_ENABLE, 0); + vmw_kms_write_svga(vmw_priv, info->var.xres, info->var.yres, + info->fix.line_length, + par->bpp, par->depth); + vmw_write(vmw_priv, SVGA_REG_ENABLE, 1);
- /* TODO check if pitch and offset changes */ }
+ /* This is really helpfull as if this is fails the user + * can probably not see anything on the screen. + */ + WARN_ON(vmw_read(vmw_priv, SVGA_REG_FB_OFFSET) != 0); + return 0; }
@@ -416,48 +416,23 @@ int vmw_fb_init(struct vmw_private *vmw_priv) unsigned fb_bbp, fb_depth, fb_offset, fb_pitch, fb_size; int ret;
+ /* XXX these shouldn't be hardcoded */ initial_width = 800; initial_height = 600;
fb_bbp = 32; fb_depth = 24;
- if (vmw_priv->capabilities & SVGA_CAP_MULTIMON) { - fb_width = min(vmw_priv->fb_max_width, (unsigned)2048); - fb_height = min(vmw_priv->fb_max_height, (unsigned)2048); - } else { - fb_width = min(vmw_priv->fb_max_width, initial_width); - fb_height = min(vmw_priv->fb_max_height, initial_height); - } + /* XXX as shouldn't these be as well */ + fb_width = min(vmw_priv->fb_max_width, (unsigned)2048); + fb_height = min(vmw_priv->fb_max_height, (unsigned)2048);
initial_width = min(fb_width, initial_width); initial_height = min(fb_height, initial_height);
- vmw_write(vmw_priv, SVGA_REG_WIDTH, fb_width); - vmw_write(vmw_priv, SVGA_REG_HEIGHT, fb_height); - vmw_write(vmw_priv, SVGA_REG_BITS_PER_PIXEL, fb_bbp); - vmw_write(vmw_priv, SVGA_REG_DEPTH, fb_depth); - vmw_write(vmw_priv, SVGA_REG_RED_MASK, 0x00ff0000); - vmw_write(vmw_priv, SVGA_REG_GREEN_MASK, 0x0000ff00); - vmw_write(vmw_priv, SVGA_REG_BLUE_MASK, 0x000000ff); - - fb_size = vmw_read(vmw_priv, SVGA_REG_FB_SIZE); + fb_pitch = fb_width * fb_bbp / 8; + fb_size = fb_pitch * fb_height; fb_offset = vmw_read(vmw_priv, SVGA_REG_FB_OFFSET); - fb_pitch = vmw_read(vmw_priv, SVGA_REG_BYTES_PER_LINE); - - DRM_DEBUG("width %u\n", vmw_read(vmw_priv, SVGA_REG_MAX_WIDTH)); - DRM_DEBUG("height %u\n", vmw_read(vmw_priv, SVGA_REG_MAX_HEIGHT)); - DRM_DEBUG("width %u\n", vmw_read(vmw_priv, SVGA_REG_WIDTH)); - DRM_DEBUG("height %u\n", vmw_read(vmw_priv, SVGA_REG_HEIGHT)); - DRM_DEBUG("bpp %u\n", vmw_read(vmw_priv, SVGA_REG_BITS_PER_PIXEL)); - DRM_DEBUG("depth %u\n", vmw_read(vmw_priv, SVGA_REG_DEPTH)); - DRM_DEBUG("bpl %u\n", vmw_read(vmw_priv, SVGA_REG_BYTES_PER_LINE)); - DRM_DEBUG("r mask %08x\n", vmw_read(vmw_priv, SVGA_REG_RED_MASK)); - DRM_DEBUG("g mask %08x\n", vmw_read(vmw_priv, SVGA_REG_GREEN_MASK)); - DRM_DEBUG("b mask %08x\n", vmw_read(vmw_priv, SVGA_REG_BLUE_MASK)); - DRM_DEBUG("fb_offset 0x%08x\n", fb_offset); - DRM_DEBUG("fb_pitch %u\n", fb_pitch); - DRM_DEBUG("fb_size %u kiB\n", fb_size / 1024);
info = framebuffer_alloc(sizeof(*par), device); if (!info) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c index a8e5445..e6a1eb7 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c @@ -34,6 +34,9 @@ bool vmw_fifo_have_3d(struct vmw_private *dev_priv) __le32 __iomem *fifo_mem = dev_priv->mmio_virt; uint32_t fifo_min, hwversion;
+ if (!(dev_priv->capabilities & SVGA_CAP_EXTENDED_FIFO)) + return false; + fifo_min = ioread32(fifo_mem + SVGA_FIFO_MIN); if (fifo_min <= SVGA_FIFO_3D_HWVERSION * sizeof(unsigned int)) return false; @@ -48,6 +51,21 @@ bool vmw_fifo_have_3d(struct vmw_private *dev_priv) return true; }
+bool vmw_fifo_have_pitchlock(struct vmw_private *dev_priv) +{ + __le32 __iomem *fifo_mem = dev_priv->mmio_virt; + uint32_t caps; + + if (!(dev_priv->capabilities & SVGA_CAP_EXTENDED_FIFO)) + return false; + + caps = ioread32(fifo_mem + SVGA_FIFO_CAPABILITIES); + if (caps & SVGA_FIFO_CAP_PITCHLOCK) + return true; + + return false; +} + int vmw_fifo_init(struct vmw_private *dev_priv, struct vmw_fifo_state *fifo) { __le32 __iomem *fifo_mem = dev_priv->mmio_virt; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index 146792e..9d0defa 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c @@ -596,31 +596,11 @@ static int vmw_framebuffer_dmabuf_pin(struct vmw_framebuffer *vfb) vmw_framebuffer_to_vfbd(&vfb->base); int ret;
+ vmw_overlay_pause_all(dev_priv);
ret = vmw_dmabuf_to_start_of_vram(dev_priv, vfbd->buffer);
- if (dev_priv->capabilities & SVGA_CAP_MULTIMON) { - vmw_write(dev_priv, SVGA_REG_NUM_GUEST_DISPLAYS, 1); - vmw_write(dev_priv, SVGA_REG_DISPLAY_ID, 0); - vmw_write(dev_priv, SVGA_REG_DISPLAY_IS_PRIMARY, true); - vmw_write(dev_priv, SVGA_REG_DISPLAY_POSITION_X, 0); - vmw_write(dev_priv, SVGA_REG_DISPLAY_POSITION_Y, 0); - vmw_write(dev_priv, SVGA_REG_DISPLAY_WIDTH, 0); - vmw_write(dev_priv, SVGA_REG_DISPLAY_HEIGHT, 0); - vmw_write(dev_priv, SVGA_REG_DISPLAY_ID, SVGA_ID_INVALID); - - vmw_write(dev_priv, SVGA_REG_ENABLE, 1); - vmw_write(dev_priv, SVGA_REG_WIDTH, vfb->base.width); - vmw_write(dev_priv, SVGA_REG_HEIGHT, vfb->base.height); - vmw_write(dev_priv, SVGA_REG_BITS_PER_PIXEL, vfb->base.bits_per_pixel); - vmw_write(dev_priv, SVGA_REG_DEPTH, vfb->base.depth); - vmw_write(dev_priv, SVGA_REG_RED_MASK, 0x00ff0000); - vmw_write(dev_priv, SVGA_REG_GREEN_MASK, 0x0000ff00); - vmw_write(dev_priv, SVGA_REG_BLUE_MASK, 0x000000ff); - } else - WARN_ON(true); - vmw_overlay_resume_all(dev_priv);
return 0; @@ -668,7 +648,7 @@ int vmw_kms_new_framebuffer_dmabuf(struct vmw_private *dev_priv,
/* XXX get the first 3 from the surface info */ vfbd->base.base.bits_per_pixel = 32; - vfbd->base.base.pitch = width * 32 / 4; + vfbd->base.base.pitch = width * vfbd->base.base.bits_per_pixel / 8; vfbd->base.base.depth = 24; vfbd->base.base.width = width; vfbd->base.base.height = height; @@ -833,24 +813,25 @@ out: return ret; }
-int vmw_kms_save_vga(struct vmw_private *vmw_priv) +void vmw_kms_write_svga(struct vmw_private *vmw_priv, + unsigned width, unsigned height, unsigned pitch, + unsigned bbp, unsigned depth) { - /* - * setup a single multimon monitor with the size - * of 0x0, this stops the UI from resizing when we - * change the framebuffer size - */ - if (vmw_priv->capabilities & SVGA_CAP_MULTIMON) { - vmw_write(vmw_priv, SVGA_REG_NUM_GUEST_DISPLAYS, 1); - vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, 0); - vmw_write(vmw_priv, SVGA_REG_DISPLAY_IS_PRIMARY, true); - vmw_write(vmw_priv, SVGA_REG_DISPLAY_POSITION_X, 0); - vmw_write(vmw_priv, SVGA_REG_DISPLAY_POSITION_Y, 0); - vmw_write(vmw_priv, SVGA_REG_DISPLAY_WIDTH, 0); - vmw_write(vmw_priv, SVGA_REG_DISPLAY_HEIGHT, 0); - vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, SVGA_ID_INVALID); - } + if (vmw_priv->capabilities & SVGA_CAP_PITCHLOCK) + vmw_write(vmw_priv, SVGA_REG_PITCHLOCK, pitch); + else if (vmw_fifo_have_pitchlock(vmw_priv)) + iowrite32(pitch, vmw_priv->mmio_virt + SVGA_FIFO_PITCHLOCK); + vmw_write(vmw_priv, SVGA_REG_WIDTH, width); + vmw_write(vmw_priv, SVGA_REG_HEIGHT, height); + vmw_write(vmw_priv, SVGA_REG_BITS_PER_PIXEL, bbp); + vmw_write(vmw_priv, SVGA_REG_DEPTH, depth); + vmw_write(vmw_priv, SVGA_REG_RED_MASK, 0x00ff0000); + vmw_write(vmw_priv, SVGA_REG_GREEN_MASK, 0x0000ff00); + vmw_write(vmw_priv, SVGA_REG_BLUE_MASK, 0x000000ff); +}
+int vmw_kms_save_vga(struct vmw_private *vmw_priv) +{ vmw_priv->vga_width = vmw_read(vmw_priv, SVGA_REG_WIDTH); vmw_priv->vga_height = vmw_read(vmw_priv, SVGA_REG_HEIGHT); vmw_priv->vga_bpp = vmw_read(vmw_priv, SVGA_REG_BITS_PER_PIXEL); @@ -859,6 +840,12 @@ int vmw_kms_save_vga(struct vmw_private *vmw_priv) vmw_priv->vga_red_mask = vmw_read(vmw_priv, SVGA_REG_RED_MASK); vmw_priv->vga_green_mask = vmw_read(vmw_priv, SVGA_REG_GREEN_MASK); vmw_priv->vga_blue_mask = vmw_read(vmw_priv, SVGA_REG_BLUE_MASK); + if (vmw_priv->capabilities & SVGA_CAP_PITCHLOCK) + vmw_priv->vga_pitchlock = + vmw_read(vmw_priv, SVGA_REG_PITCHLOCK); + else if (vmw_fifo_have_pitchlock(vmw_priv)) + vmw_priv->vga_pitchlock = + ioread32(vmw_priv->mmio_virt + SVGA_FIFO_PITCHLOCK);
return 0; } @@ -873,9 +860,12 @@ int vmw_kms_restore_vga(struct vmw_private *vmw_priv) vmw_write(vmw_priv, SVGA_REG_RED_MASK, vmw_priv->vga_red_mask); vmw_write(vmw_priv, SVGA_REG_GREEN_MASK, vmw_priv->vga_green_mask); vmw_write(vmw_priv, SVGA_REG_BLUE_MASK, vmw_priv->vga_blue_mask); - - /* TODO check for multimon */ - vmw_write(vmw_priv, SVGA_REG_NUM_GUEST_DISPLAYS, 0); + if (vmw_priv->capabilities & SVGA_CAP_PITCHLOCK) + vmw_write(vmw_priv, SVGA_REG_PITCHLOCK, + vmw_priv->vga_pitchlock); + else if (vmw_fifo_have_pitchlock(vmw_priv)) + iowrite32(vmw_priv->vga_pitchlock, + vmw_priv->mmio_virt + SVGA_FIFO_PITCHLOCK);
return 0; } diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c index 06618a3..1b818c1 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c @@ -38,6 +38,7 @@ struct vmw_legacy_display { struct list_head active;
unsigned num_active; + unsigned last_num_active;
struct vmw_framebuffer *fb; }; @@ -88,12 +89,37 @@ static int vmw_ldu_commit_list(struct vmw_private *dev_priv) { struct vmw_legacy_display *lds = dev_priv->ldu_priv; struct vmw_legacy_display_unit *entry; - struct drm_crtc *crtc; + struct drm_framebuffer *fb = NULL; + struct drm_crtc *crtc = NULL; int i = 0;
- /* to stop the screen from changing size on resize */ - vmw_write(dev_priv, SVGA_REG_NUM_GUEST_DISPLAYS, 0); - for (i = 0; i < lds->num_active; i++) { + /* If there is no display topology the host just assumes + * that the guest will set the same layout as the host. + */ + if (!(dev_priv->capabilities & SVGA_CAP_DISPLAY_TOPOLOGY)) { + int w = 0, h = 0; + list_for_each_entry(entry, &lds->active, active) { + crtc = &entry->base.crtc; + w = max(w, crtc->x + crtc->mode.hdisplay); + h = max(h, crtc->y + crtc->mode.vdisplay); + i++; + } + + if (crtc == NULL) + return 0; + fb = entry->base.crtc.fb; + + vmw_write(dev_priv, SVGA_REG_ENABLE, 0); + vmw_kms_write_svga(dev_priv, w, h, fb->pitch, + fb->bits_per_pixel, fb->depth); + vmw_write(dev_priv, SVGA_REG_ENABLE, 1); + + return 0; + } + + vmw_write(dev_priv, SVGA_REG_ENABLE, 0); + + for (i = 0; i < lds->last_num_active; i++) { vmw_write(dev_priv, SVGA_REG_DISPLAY_ID, i); vmw_write(dev_priv, SVGA_REG_DISPLAY_IS_PRIMARY, !i); vmw_write(dev_priv, SVGA_REG_DISPLAY_POSITION_X, 0); @@ -103,8 +129,14 @@ static int vmw_ldu_commit_list(struct vmw_private *dev_priv) vmw_write(dev_priv, SVGA_REG_DISPLAY_ID, SVGA_ID_INVALID); }
- /* Now set the mode */ - vmw_write(dev_priv, SVGA_REG_NUM_GUEST_DISPLAYS, lds->num_active); + if (!list_empty(&lds->active)) { + entry = list_entry(lds->active.next, typeof(*entry), active); + fb = entry->base.crtc.fb; + + vmw_kms_write_svga(dev_priv, fb->width, fb->height, fb->pitch, + fb->bits_per_pixel, fb->depth); + } + i = 0; list_for_each_entry(entry, &lds->active, active) { crtc = &entry->base.crtc; @@ -120,6 +152,14 @@ static int vmw_ldu_commit_list(struct vmw_private *dev_priv) i++; }
+ /* Make sure we always show something */ + vmw_write(dev_priv, SVGA_REG_NUM_GUEST_DISPLAYS, i ? i : 1); + vmw_write(dev_priv, SVGA_REG_ENABLE, 1); + + BUG_ON(i != lds->num_active); + + lds->last_num_active = lds->num_active; + return 0; }
@@ -491,18 +531,22 @@ int vmw_kms_init_legacy_display_system(struct vmw_private *dev_priv)
INIT_LIST_HEAD(&dev_priv->ldu_priv->active); dev_priv->ldu_priv->num_active = 0; + dev_priv->ldu_priv->last_num_active = 0; dev_priv->ldu_priv->fb = NULL;
drm_mode_create_dirty_info_property(dev_priv->dev);
vmw_ldu_init(dev_priv, 0); - vmw_ldu_init(dev_priv, 1); - vmw_ldu_init(dev_priv, 2); - vmw_ldu_init(dev_priv, 3); - vmw_ldu_init(dev_priv, 4); - vmw_ldu_init(dev_priv, 5); - vmw_ldu_init(dev_priv, 6); - vmw_ldu_init(dev_priv, 7); + /* for old hardware without multimon only enable one display */ + if (dev_priv->capabilities & SVGA_CAP_MULTIMON) { + vmw_ldu_init(dev_priv, 1); + vmw_ldu_init(dev_priv, 2); + vmw_ldu_init(dev_priv, 3); + vmw_ldu_init(dev_priv, 4); + vmw_ldu_init(dev_priv, 5); + vmw_ldu_init(dev_priv, 6); + vmw_ldu_init(dev_priv, 7); + }
return 0; }
The host may be touching this part of VRAM at modesetting, even if we never use it ourselves, since we blit screen updates from 3D surfaces. Make sure no DMA buffers are placed in this part of VRAM.
Signed-off-by: Thomas Hellstrom thellstrom@vmware.com Signed-off-by: Jakob Bornecrantz jakob@vmware.com --- drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 39 +++++++++++++++++++++++++++++++++- 1 files changed, 37 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index 9d0defa..c1a7fd5 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c @@ -30,6 +30,8 @@ /* Might need a hrtimer here? */ #define VMWGFX_PRESENT_RATE ((HZ / 60 > 0) ? HZ / 60 : 1)
+static int vmw_surface_dmabuf_pin(struct vmw_framebuffer *vfb); +static int vmw_surface_dmabuf_unpin(struct vmw_framebuffer *vfb);
void vmw_display_unit_cleanup(struct vmw_display_unit *du) { @@ -326,6 +328,7 @@ int vmw_framebuffer_create_handle(struct drm_framebuffer *fb, struct vmw_framebuffer_surface { struct vmw_framebuffer base; struct vmw_surface *surface; + struct vmw_dma_buffer *buffer; struct delayed_work d_work; struct mutex work_lock; bool present_fs; @@ -500,8 +503,8 @@ int vmw_kms_new_framebuffer_surface(struct vmw_private *dev_priv, vfbs->base.base.depth = 24; vfbs->base.base.width = width; vfbs->base.base.height = height; - vfbs->base.pin = NULL; - vfbs->base.unpin = NULL; + vfbs->base.pin = &vmw_surface_dmabuf_pin; + vfbs->base.unpin = &vmw_surface_dmabuf_unpin; vfbs->surface = surface; mutex_init(&vfbs->work_lock); INIT_DELAYED_WORK(&vfbs->d_work, &vmw_framebuffer_present_fs_callback); @@ -589,6 +592,38 @@ static struct drm_framebuffer_funcs vmw_framebuffer_dmabuf_funcs = { .create_handle = vmw_framebuffer_create_handle, };
+static int vmw_surface_dmabuf_pin(struct vmw_framebuffer *vfb) +{ + struct vmw_private *dev_priv = vmw_priv(vfb->base.dev); + struct vmw_framebuffer_surface *vfbs = + vmw_framebuffer_to_vfbs(&vfb->base); + unsigned long size = vfbs->base.base.pitch * vfbs->base.base.height; + int ret; + + vfbs->buffer = kzalloc(sizeof(*vfbs->buffer), GFP_KERNEL); + + vmw_overlay_pause_all(dev_priv); + ret = vmw_dmabuf_init(dev_priv, vfbs->buffer, size, + &vmw_vram_ne_placement, + false, &vmw_dmabuf_bo_free); + vmw_overlay_resume_all(dev_priv); + + return ret; +} + +static int vmw_surface_dmabuf_unpin(struct vmw_framebuffer *vfb) +{ + struct ttm_buffer_object *bo; + struct vmw_framebuffer_surface *vfbs = + vmw_framebuffer_to_vfbs(&vfb->base); + + bo = &vfbs->buffer->base; + ttm_bo_unref(&bo); + vfbs->buffer = NULL; + + return 0; +} + static int vmw_framebuffer_dmabuf_pin(struct vmw_framebuffer *vfb) { struct vmw_private *dev_priv = vmw_priv(vfb->base.dev);
From: Jakob Bornecrantz jakob@vmware.com
Signed-off-by: Jakob Bornecrantz jakob@vmware.com Signed-off-by: Thomas Hellstrom thellstrom@vmware.com --- drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c | 6 ++---- 1 files changed, 2 insertions(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c index 1b818c1..d6d1905 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c @@ -50,8 +50,6 @@ struct vmw_legacy_display_unit { struct vmw_display_unit base;
struct list_head active; - - unsigned unit; };
static void vmw_ldu_destroy(struct vmw_legacy_display_unit *ldu) @@ -204,7 +202,7 @@ static int vmw_ldu_add_active(struct vmw_private *vmw_priv,
at = &ld->active; list_for_each_entry(entry, &ld->active, active) { - if (entry->unit > ldu->unit) + if (entry->base.unit > ldu->base.unit) break;
at = &entry->active; @@ -491,7 +489,7 @@ static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit) if (!ldu) return -ENOMEM;
- ldu->unit = unit; + ldu->base.unit = unit; crtc = &ldu->base.crtc; encoder = &ldu->base.encoder; connector = &ldu->base.connector;
From: Jakob Bornecrantz jakob@vmware.com
We should not use SVGA_REG_ENABLE anywhere but in the fifo setup code, since it controls whether the device is active.
Signed-off-by: Jakob Bornecrantz jakob@vmware.com Signed-off-by: Thomas Hellstrom thellstrom@vmware.com --- drivers/gpu/drm/vmwgfx/vmwgfx_fb.c | 4 ---- drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c | 5 ----- 2 files changed, 0 insertions(+), 9 deletions(-)
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c index 897ece5..f20bb20 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c @@ -153,7 +153,6 @@ static int vmw_fb_set_par(struct fb_info *info) struct vmw_private *vmw_priv = par->vmw_priv;
if (vmw_priv->capabilities & SVGA_CAP_DISPLAY_TOPOLOGY) { - vmw_write(vmw_priv, SVGA_REG_ENABLE, 0); vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, 0); vmw_write(vmw_priv, SVGA_REG_DISPLAY_IS_PRIMARY, true); vmw_write(vmw_priv, SVGA_REG_DISPLAY_POSITION_X, 0); @@ -175,13 +174,10 @@ static int vmw_fb_set_par(struct fb_info *info) vmw_write(vmw_priv, SVGA_REG_DISPLAY_HEIGHT, info->var.yres); vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, SVGA_ID_INVALID); vmw_write(vmw_priv, SVGA_REG_NUM_GUEST_DISPLAYS, 1); - vmw_write(vmw_priv, SVGA_REG_ENABLE, 1); } else { - vmw_write(vmw_priv, SVGA_REG_ENABLE, 0); vmw_kms_write_svga(vmw_priv, info->var.xres, info->var.yres, info->fix.line_length, par->bpp, par->depth); - vmw_write(vmw_priv, SVGA_REG_ENABLE, 1);
}
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c index d6d1905..c4aa653 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c @@ -107,16 +107,12 @@ static int vmw_ldu_commit_list(struct vmw_private *dev_priv) return 0; fb = entry->base.crtc.fb;
- vmw_write(dev_priv, SVGA_REG_ENABLE, 0); vmw_kms_write_svga(dev_priv, w, h, fb->pitch, fb->bits_per_pixel, fb->depth); - vmw_write(dev_priv, SVGA_REG_ENABLE, 1);
return 0; }
- vmw_write(dev_priv, SVGA_REG_ENABLE, 0); - for (i = 0; i < lds->last_num_active; i++) { vmw_write(dev_priv, SVGA_REG_DISPLAY_ID, i); vmw_write(dev_priv, SVGA_REG_DISPLAY_IS_PRIMARY, !i); @@ -152,7 +148,6 @@ static int vmw_ldu_commit_list(struct vmw_private *dev_priv)
/* Make sure we always show something */ vmw_write(dev_priv, SVGA_REG_NUM_GUEST_DISPLAYS, i ? i : 1); - vmw_write(dev_priv, SVGA_REG_ENABLE, 1);
BUG_ON(i != lds->num_active);
From: Jakob Bornecrantz jakob@vmware.com
Signed-off-by: Jakob Bornecrantz jakob@vmware.com Signed-off-by: Thomas Hellstrom thellstrom@vmware.com --- drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c | 17 ++++------------- 1 files changed, 4 insertions(+), 13 deletions(-)
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c index c4aa653..923c013 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c @@ -113,16 +113,6 @@ static int vmw_ldu_commit_list(struct vmw_private *dev_priv) return 0; }
- for (i = 0; i < lds->last_num_active; i++) { - vmw_write(dev_priv, SVGA_REG_DISPLAY_ID, i); - vmw_write(dev_priv, SVGA_REG_DISPLAY_IS_PRIMARY, !i); - vmw_write(dev_priv, SVGA_REG_DISPLAY_POSITION_X, 0); - vmw_write(dev_priv, SVGA_REG_DISPLAY_POSITION_Y, 0); - vmw_write(dev_priv, SVGA_REG_DISPLAY_WIDTH, 0); - vmw_write(dev_priv, SVGA_REG_DISPLAY_HEIGHT, 0); - vmw_write(dev_priv, SVGA_REG_DISPLAY_ID, SVGA_ID_INVALID); - } - if (!list_empty(&lds->active)) { entry = list_entry(lds->active.next, typeof(*entry), active); fb = entry->base.crtc.fb; @@ -131,6 +121,10 @@ static int vmw_ldu_commit_list(struct vmw_private *dev_priv) fb->bits_per_pixel, fb->depth); }
+ /* Make sure we always show something */ + vmw_write(dev_priv, SVGA_REG_NUM_GUEST_DISPLAYS, + lds->num_active ? lds->num_active : 1); + i = 0; list_for_each_entry(entry, &lds->active, active) { crtc = &entry->base.crtc; @@ -146,9 +140,6 @@ static int vmw_ldu_commit_list(struct vmw_private *dev_priv) i++; }
- /* Make sure we always show something */ - vmw_write(dev_priv, SVGA_REG_NUM_GUEST_DISPLAYS, i ? i : 1); - BUG_ON(i != lds->num_active);
lds->last_num_active = lds->num_active;
From: Jakob Bornecrantz jakob@vmware.com
The unpause codepath uses vmw_overlay_update() so we must unset the paused status.
Signed-off-by: Jakob Bornecrantz jakob@vmware.com Signed-off-by: Thomas Hellstrom thellstrom@vmware.com --- drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c b/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c index 5b6eabe..e4c1b98 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c @@ -358,6 +358,8 @@ static int vmw_overlay_update_stream(struct vmw_private *dev_priv, if (stream->buf != buf) stream->buf = vmw_dmabuf_reference(buf); stream->saved = *arg; + /* stream is no longer stopped/paused */ + stream->paused = false;
return 0; }
From: Jakob Bornecrantz jakob@vmware.com
Signed-off-by: Jakob Bornecrantz jakob@vmware.com Signed-off-by: Thomas Hellstrom thellstrom@vmware.com --- drivers/gpu/drm/vmwgfx/vmwgfx_fb.c | 4 ++++ drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 2 ++ 2 files changed, 6 insertions(+), 0 deletions(-)
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c index f20bb20..93c6489 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c @@ -624,6 +624,10 @@ int vmw_dmabuf_to_start_of_vram(struct vmw_private *vmw_priv, goto err_unlock;
ret = ttm_bo_validate(bo, &ne_placement, false, false); + + /* Could probably bug on */ + WARN_ON(bo->offset != 0); + ttm_bo_unreserve(bo); err_unlock: ttm_write_unlock(&vmw_priv->active_master->lock); diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index c1a7fd5..9ba4822 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c @@ -638,6 +638,8 @@ static int vmw_framebuffer_dmabuf_pin(struct vmw_framebuffer *vfb)
vmw_overlay_resume_all(dev_priv);
+ WARN_ON(ret != 0); + return 0; }
Signed-off-by: Thomas Hellstrom thellstrom@vmware.com --- drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 8 -------- 1 files changed, 0 insertions(+), 8 deletions(-)
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index 6241255..cf7aa3d 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c @@ -408,8 +408,6 @@ static int vmw_driver_unload(struct drm_device *dev) { struct vmw_private *dev_priv = vmw_priv(dev);
- DRM_INFO(VMWGFX_DRIVER_NAME " unload.\n"); - unregister_pm_notifier(&dev_priv->pm_nb);
vmw_fb_close(dev_priv); @@ -555,7 +553,6 @@ static int vmw_master_create(struct drm_device *dev, { struct vmw_master *vmaster;
- DRM_INFO("Master create.\n"); vmaster = kzalloc(sizeof(*vmaster), GFP_KERNEL); if (unlikely(vmaster == NULL)) return -ENOMEM; @@ -572,7 +569,6 @@ static void vmw_master_destroy(struct drm_device *dev, { struct vmw_master *vmaster = vmw_master(master);
- DRM_INFO("Master destroy.\n"); master->driver_priv = NULL; kfree(vmaster); } @@ -588,8 +584,6 @@ static int vmw_master_set(struct drm_device *dev, struct vmw_master *vmaster = vmw_master(file_priv->master); int ret = 0;
- DRM_INFO("Master set.\n"); - if (active) { BUG_ON(active != &dev_priv->fbdev_master); ret = ttm_vt_lock(&active->lock, false, vmw_fp->tfile); @@ -631,8 +625,6 @@ static void vmw_master_drop(struct drm_device *dev, struct vmw_master *vmaster = vmw_master(file_priv->master); int ret;
- DRM_INFO("Master drop.\n"); - /** * Make sure the master doesn't disappear while we have * it locked.
On 04/27/2010 08:45 PM, Thomas Hellstrom wrote:
From: Jakob Bornecrantzjakob@vmware.com
Signed-off-by: Jakob Bornecrantzjakob@vmware.com Signed-off-by: Thomas Hellstromthellstrom@vmware.com
drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c | 3 +++ 1 files changed, 3 insertions(+), 0 deletions(-)
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c index 9089159..be88fc6 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c @@ -130,6 +130,7 @@ static int vmw_ldu_del_active(struct vmw_private *vmw_priv, if (list_empty(&ldu->active)) return 0;
- /* must init otherwise list_empty(&ldu->active) well not work */
Spelling well->will
list_del_init(&ldu->active); if (--(ld->num_active) == 0) { BUG_ON(!ld->fb); @@ -208,6 +209,8 @@ static int vmw_ldu_crtc_set_config(struct drm_mode_set *set)
/* ldu only supports one fb active at the time */ if (dev_priv->ldu_priv->fb&& vfb&&
!(dev_priv->ldu_priv->num_active == 1&&
dev_priv->ldu_priv->fb != vfb) { DRM_ERROR("Multiple framebuffers not supported\n"); return -EINVAL;!list_empty(&ldu->active))&&
dri-devel@lists.freedesktop.org