All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/15] vmwgfx updates
@ 2010-09-27 13:20 Thomas Hellstrom
  2010-09-27 13:20 ` [PATCH 01/15] vmwgfx: Add an option to choose whether to enable fbdev at load time Thomas Hellstrom
  0 siblings, 1 reply; 20+ messages in thread
From: Thomas Hellstrom @ 2010-09-27 13:20 UTC (permalink / raw)
  To: airlied; +Cc: dri-devel

This patch series contains a number of bugfixes and brings the vmwgfx driver
up-to-date with the standalone repo.

Patch 05/15 contains a modesetting driver API change needed for 06/15, and may
as such not be suitable for kernel RCs but rather for the next merge window.

Thanks,
Thomas

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH 01/15] vmwgfx: Add an option to choose whether to enable fbdev at load time
  2010-09-27 13:20 [PATCH 0/15] vmwgfx updates Thomas Hellstrom
@ 2010-09-27 13:20 ` Thomas Hellstrom
  2010-09-27 13:20   ` [PATCH 02/15] vmwgfx: Really support other depths than 32 Thomas Hellstrom
  0 siblings, 1 reply; 20+ messages in thread
From: Thomas Hellstrom @ 2010-09-27 13:20 UTC (permalink / raw)
  To: airlied; +Cc: Thomas Hellstrom, dri-devel

This option is off (0) by default.
Not enabling fbdev at load time makes it possible to co-operate with
vga16fb and vga text mode when VT switching.

However, if 3D resources are active when VT switching, we're currently
not able to switch over to vga, due to device limitations.

Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com>
---
 drivers/gpu/drm/vmwgfx/vmwgfx_drv.c      |  102 ++++++++++++++++++++++++++----
 drivers/gpu/drm/vmwgfx/vmwgfx_drv.h      |    7 ++
 drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c     |    3 +
 drivers/gpu/drm/vmwgfx/vmwgfx_kms.c      |   12 ++++
 drivers/gpu/drm/vmwgfx/vmwgfx_resource.c |    4 +
 5 files changed, 115 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
index e645f44..40bdb54 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
@@ -149,12 +149,16 @@ static struct pci_device_id vmw_pci_id_list[] = {
 };
 
 static char *vmw_devname = "vmwgfx";
+static int enable_fbdev;
 
 static int vmw_probe(struct pci_dev *, const struct pci_device_id *);
 static void vmw_master_init(struct vmw_master *);
 static int vmwgfx_pm_notifier(struct notifier_block *nb, unsigned long val,
 			      void *ptr);
 
+MODULE_PARM_DESC(enable_fbdev, "Enable vmwgfx fbdev");
+module_param_named(enable_fbdev, enable_fbdev, int, 0600);
+
 static void vmw_print_capabilities(uint32_t capabilities)
 {
 	DRM_INFO("Capabilities:\n");
@@ -192,8 +196,6 @@ static int vmw_request_device(struct vmw_private *dev_priv)
 {
 	int ret;
 
-	vmw_kms_save_vga(dev_priv);
-
 	ret = vmw_fifo_init(dev_priv, &dev_priv->fifo);
 	if (unlikely(ret != 0)) {
 		DRM_ERROR("Unable to initialize FIFO.\n");
@@ -206,10 +208,36 @@ static int vmw_request_device(struct vmw_private *dev_priv)
 static void vmw_release_device(struct vmw_private *dev_priv)
 {
 	vmw_fifo_release(dev_priv, &dev_priv->fifo);
-	vmw_kms_restore_vga(dev_priv);
+}
+
+int vmw_3d_resource_inc(struct vmw_private *dev_priv)
+{
+	int ret = 0;
+
+	mutex_lock(&dev_priv->release_mutex);
+	if (unlikely(dev_priv->num_3d_resources++ == 0)) {
+		ret = vmw_request_device(dev_priv);
+		if (unlikely(ret != 0))
+			--dev_priv->num_3d_resources;
+	}
+	mutex_unlock(&dev_priv->release_mutex);
+	return ret;
 }
 
 
+void vmw_3d_resource_dec(struct vmw_private *dev_priv)
+{
+	int32_t n3d;
+
+	mutex_lock(&dev_priv->release_mutex);
+	if (unlikely(--dev_priv->num_3d_resources == 0))
+		vmw_release_device(dev_priv);
+	n3d = (int32_t) dev_priv->num_3d_resources;
+	mutex_unlock(&dev_priv->release_mutex);
+
+	BUG_ON(n3d < 0);
+}
+
 static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
 {
 	struct vmw_private *dev_priv;
@@ -228,6 +256,7 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
 	dev_priv->last_read_sequence = (uint32_t) -100;
 	mutex_init(&dev_priv->hw_mutex);
 	mutex_init(&dev_priv->cmdbuf_mutex);
+	mutex_init(&dev_priv->release_mutex);
 	rwlock_init(&dev_priv->resource_lock);
 	idr_init(&dev_priv->context_idr);
 	idr_init(&dev_priv->surface_idr);
@@ -244,6 +273,8 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
 	dev_priv->vram_start = pci_resource_start(dev->pdev, 1);
 	dev_priv->mmio_start = pci_resource_start(dev->pdev, 2);
 
+	dev_priv->enable_fb = enable_fbdev;
+
 	mutex_lock(&dev_priv->hw_mutex);
 
 	vmw_write(dev_priv, SVGA_REG_ID, SVGA_ID_2);
@@ -369,20 +400,34 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
 			goto out_no_device;
 		}
 	}
-	ret = vmw_request_device(dev_priv);
-	if (unlikely(ret != 0))
-		goto out_no_device;
 	vmw_kms_init(dev_priv);
 	vmw_overlay_init(dev_priv);
-	vmw_fb_init(dev_priv);
+	if (dev_priv->enable_fb) {
+		ret = vmw_3d_resource_inc(dev_priv);
+		if (unlikely(ret != 0))
+			goto out_no_fifo;
+		vmw_kms_save_vga(dev_priv);
+		vmw_fb_init(dev_priv);
+		DRM_INFO("%s", vmw_fifo_have_3d(dev_priv) ?
+			 "Detected device 3D availability.\n" :
+			 "Detected no device 3D availability.\n");
+	} else {
+		DRM_INFO("Delayed 3D detection since we're not "
+			 "running the device in SVGA mode yet.\n");
+	}
 
 	dev_priv->pm_nb.notifier_call = vmwgfx_pm_notifier;
 	register_pm_notifier(&dev_priv->pm_nb);
 
-	DRM_INFO("%s", vmw_fifo_have_3d(dev_priv) ? "Have 3D\n" : "No 3D\n");
-
 	return 0;
 
+out_no_fifo:
+	vmw_overlay_close(dev_priv);
+	vmw_kms_close(dev_priv);
+	if (dev_priv->stealth)
+		pci_release_region(dev->pdev, 2);
+	else
+		pci_release_regions(dev->pdev);
 out_no_device:
 	if (dev_priv->capabilities & SVGA_CAP_IRQMASK)
 		drm_irq_uninstall(dev_priv->dev);
@@ -415,10 +460,13 @@ static int vmw_driver_unload(struct drm_device *dev)
 
 	unregister_pm_notifier(&dev_priv->pm_nb);
 
-	vmw_fb_close(dev_priv);
+	if (dev_priv->enable_fb) {
+		vmw_fb_close(dev_priv);
+		vmw_kms_restore_vga(dev_priv);
+		vmw_3d_resource_dec(dev_priv);
+	}
 	vmw_kms_close(dev_priv);
 	vmw_overlay_close(dev_priv);
-	vmw_release_device(dev_priv);
 	if (dev_priv->stealth)
 		pci_release_region(dev->pdev, 2);
 	else
@@ -589,6 +637,16 @@ static int vmw_master_set(struct drm_device *dev,
 	struct vmw_master *vmaster = vmw_master(file_priv->master);
 	int ret = 0;
 
+	if (!dev_priv->enable_fb) {
+		ret = vmw_3d_resource_inc(dev_priv);
+		if (unlikely(ret != 0))
+			return ret;
+		vmw_kms_save_vga(dev_priv);
+		mutex_lock(&dev_priv->hw_mutex);
+		vmw_write(dev_priv, SVGA_REG_TRACES, 0);
+		mutex_unlock(&dev_priv->hw_mutex);
+	}
+
 	if (active) {
 		BUG_ON(active != &dev_priv->fbdev_master);
 		ret = ttm_vt_lock(&active->lock, false, vmw_fp->tfile);
@@ -617,7 +675,13 @@ static int vmw_master_set(struct drm_device *dev,
 	return 0;
 
 out_no_active_lock:
-	vmw_release_device(dev_priv);
+	if (!dev_priv->enable_fb) {
+		mutex_lock(&dev_priv->hw_mutex);
+		vmw_write(dev_priv, SVGA_REG_TRACES, 1);
+		mutex_unlock(&dev_priv->hw_mutex);
+		vmw_kms_restore_vga(dev_priv);
+		vmw_3d_resource_dec(dev_priv);
+	}
 	return ret;
 }
 
@@ -645,11 +709,23 @@ static void vmw_master_drop(struct drm_device *dev,
 
 	ttm_lock_set_kill(&vmaster->lock, true, SIGTERM);
 
+	if (!dev_priv->enable_fb) {
+		ret = ttm_bo_evict_mm(&dev_priv->bdev, TTM_PL_VRAM);
+		if (unlikely(ret != 0))
+			DRM_ERROR("Unable to clean VRAM on master drop.\n");
+		mutex_lock(&dev_priv->hw_mutex);
+		vmw_write(dev_priv, SVGA_REG_TRACES, 1);
+		mutex_unlock(&dev_priv->hw_mutex);
+		vmw_kms_restore_vga(dev_priv);
+		vmw_3d_resource_dec(dev_priv);
+	}
+
 	dev_priv->active_master = &dev_priv->fbdev_master;
 	ttm_lock_set_kill(&dev_priv->fbdev_master.lock, false, SIGTERM);
 	ttm_vt_unlock(&dev_priv->fbdev_master.lock);
 
-	vmw_fb_on(dev_priv);
+	if (dev_priv->enable_fb)
+		vmw_fb_on(dev_priv);
 }
 
 
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
index 429f917..9142454 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
@@ -277,6 +277,7 @@ struct vmw_private {
 
 	bool stealth;
 	bool is_opened;
+	bool enable_fb;
 
 	/**
 	 * Master management.
@@ -285,6 +286,9 @@ struct vmw_private {
 	struct vmw_master *active_master;
 	struct vmw_master fbdev_master;
 	struct notifier_block pm_nb;
+
+	struct mutex release_mutex;
+	uint32_t num_3d_resources;
 };
 
 static inline struct vmw_private *vmw_priv(struct drm_device *dev)
@@ -319,6 +323,9 @@ static inline uint32_t vmw_read(struct vmw_private *dev_priv,
 	return val;
 }
 
+int vmw_3d_resource_inc(struct vmw_private *dev_priv);
+void vmw_3d_resource_dec(struct vmw_private *dev_priv);
+
 /**
  * GMR utilities - vmwgfx_gmr.c
  */
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c
index e6a1eb7..0fe3176 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c
@@ -106,6 +106,7 @@ int vmw_fifo_init(struct vmw_private *dev_priv, struct vmw_fifo_state *fifo)
 	mutex_lock(&dev_priv->hw_mutex);
 	dev_priv->enable_state = vmw_read(dev_priv, SVGA_REG_ENABLE);
 	dev_priv->config_done_state = vmw_read(dev_priv, SVGA_REG_CONFIG_DONE);
+	dev_priv->traces_state = vmw_read(dev_priv, SVGA_REG_TRACES);
 	vmw_write(dev_priv, SVGA_REG_ENABLE, 1);
 
 	min = 4;
@@ -175,6 +176,8 @@ void vmw_fifo_release(struct vmw_private *dev_priv, struct vmw_fifo_state *fifo)
 		  dev_priv->config_done_state);
 	vmw_write(dev_priv, SVGA_REG_ENABLE,
 		  dev_priv->enable_state);
+	vmw_write(dev_priv, SVGA_REG_TRACES,
+		  dev_priv->traces_state);
 
 	mutex_unlock(&dev_priv->hw_mutex);
 	vmw_fence_queue_takedown(&fifo->fence_queue);
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
index 64d7f47..1636e9b 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
@@ -898,7 +898,19 @@ int vmw_kms_save_vga(struct vmw_private *vmw_priv)
 		save->width = vmw_read(vmw_priv, SVGA_REG_DISPLAY_WIDTH);
 		save->height = vmw_read(vmw_priv, SVGA_REG_DISPLAY_HEIGHT);
 		vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, SVGA_ID_INVALID);
+		if (i == 0 && vmw_priv->num_displays == 1 &&
+		    save->width == 0 && save->height == 0) {
+
+			/*
+			 * It should be fairly safe to assume that these
+			 * values are uninitialized.
+			 */
+
+			save->width = vmw_priv->vga_width - save->pos_x;
+			save->height = vmw_priv->vga_height - save->pos_y;
+		}
 	}
+
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
index 5f2d5df..c8c40e9 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
@@ -211,6 +211,7 @@ static void vmw_hw_context_destroy(struct vmw_resource *res)
 	cmd->body.cid = cpu_to_le32(res->id);
 
 	vmw_fifo_commit(dev_priv, sizeof(*cmd));
+	vmw_3d_resource_dec(dev_priv);
 }
 
 static int vmw_context_init(struct vmw_private *dev_priv,
@@ -247,6 +248,7 @@ static int vmw_context_init(struct vmw_private *dev_priv,
 	cmd->body.cid = cpu_to_le32(res->id);
 
 	vmw_fifo_commit(dev_priv, sizeof(*cmd));
+	(void) vmw_3d_resource_inc(dev_priv);
 	vmw_resource_activate(res, vmw_hw_context_destroy);
 	return 0;
 }
@@ -406,6 +408,7 @@ static void vmw_hw_surface_destroy(struct vmw_resource *res)
 	cmd->body.sid = cpu_to_le32(res->id);
 
 	vmw_fifo_commit(dev_priv, sizeof(*cmd));
+	vmw_3d_resource_dec(dev_priv);
 }
 
 void vmw_surface_res_free(struct vmw_resource *res)
@@ -473,6 +476,7 @@ int vmw_surface_init(struct vmw_private *dev_priv,
 	}
 
 	vmw_fifo_commit(dev_priv, submit_size);
+	(void) vmw_3d_resource_inc(dev_priv);
 	vmw_resource_activate(res, vmw_hw_surface_destroy);
 	return 0;
 }
-- 
1.6.2.5

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 02/15] vmwgfx: Really support other depths than 32
  2010-09-27 13:20 ` [PATCH 01/15] vmwgfx: Add an option to choose whether to enable fbdev at load time Thomas Hellstrom
@ 2010-09-27 13:20   ` Thomas Hellstrom
  2010-09-27 13:20     ` [PATCH 03/15] vmwgfx: Fix ACPI S3 & S4 functionality Thomas Hellstrom
  0 siblings, 1 reply; 20+ messages in thread
From: Thomas Hellstrom @ 2010-09-27 13:20 UTC (permalink / raw)
  To: airlied; +Cc: Thomas Hellstrom, dri-devel

Also add some sanity checks.

Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com>
---
 drivers/gpu/drm/vmwgfx/vmwgfx_kms.c |  106 ++++++++++++++++++++++++++++-------
 1 files changed, 85 insertions(+), 21 deletions(-)

diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
index 1636e9b..e4444e0 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
@@ -471,16 +471,55 @@ static struct drm_framebuffer_funcs vmw_framebuffer_surface_funcs = {
 	.create_handle = vmw_framebuffer_create_handle,
 };
 
-int vmw_kms_new_framebuffer_surface(struct vmw_private *dev_priv,
-				    struct vmw_surface *surface,
-				    struct vmw_framebuffer **out,
-				    unsigned width, unsigned height)
+static int vmw_kms_new_framebuffer_surface(struct vmw_private *dev_priv,
+					   struct vmw_surface *surface,
+					   struct vmw_framebuffer **out,
+					   const struct drm_mode_fb_cmd
+					   *mode_cmd)
 
 {
 	struct drm_device *dev = dev_priv->dev;
 	struct vmw_framebuffer_surface *vfbs;
+	enum SVGA3dSurfaceFormat format;
 	int ret;
 
+	/*
+	 * Sanity checks.
+	 */
+
+	if (unlikely(surface->mip_levels[0] != 1 ||
+		     surface->num_sizes != 1 ||
+		     surface->sizes[0].width < mode_cmd->width ||
+		     surface->sizes[0].height < mode_cmd->height ||
+		     surface->sizes[0].depth != 1)) {
+		DRM_ERROR("Incompatible surface dimensions "
+			  "for requested mode.\n");
+		return -EINVAL;
+	}
+
+	switch (mode_cmd->depth) {
+	case 32:
+		format = SVGA3D_A8R8G8B8;
+		break;
+	case 24:
+		format = SVGA3D_X8R8G8B8;
+		break;
+	case 16:
+		format = SVGA3D_R5G6B5;
+		break;
+	case 15:
+		format = SVGA3D_A1R5G5B5;
+		break;
+	default:
+		DRM_ERROR("Invalid color depth: %d\n", mode_cmd->depth);
+		return -EINVAL;
+	}
+
+	if (unlikely(format != surface->format)) {
+		DRM_ERROR("Invalid surface format for requested mode.\n");
+		return -EINVAL;
+	}
+
 	vfbs = kzalloc(sizeof(*vfbs), GFP_KERNEL);
 	if (!vfbs) {
 		ret = -ENOMEM;
@@ -498,11 +537,11 @@ int vmw_kms_new_framebuffer_surface(struct vmw_private *dev_priv,
 	}
 
 	/* XXX get the first 3 from the surface info */
-	vfbs->base.base.bits_per_pixel = 32;
-	vfbs->base.base.pitch = width * 32 / 4;
-	vfbs->base.base.depth = 24;
-	vfbs->base.base.width = width;
-	vfbs->base.base.height = height;
+	vfbs->base.base.bits_per_pixel = mode_cmd->bpp;
+	vfbs->base.base.pitch = mode_cmd->pitch;
+	vfbs->base.base.depth = mode_cmd->depth;
+	vfbs->base.base.width = mode_cmd->width;
+	vfbs->base.base.height = mode_cmd->height;
 	vfbs->base.pin = &vmw_surface_dmabuf_pin;
 	vfbs->base.unpin = &vmw_surface_dmabuf_unpin;
 	vfbs->surface = surface;
@@ -659,16 +698,25 @@ static int vmw_framebuffer_dmabuf_unpin(struct vmw_framebuffer *vfb)
 	return vmw_dmabuf_from_vram(dev_priv, vfbd->buffer);
 }
 
-int vmw_kms_new_framebuffer_dmabuf(struct vmw_private *dev_priv,
-				   struct vmw_dma_buffer *dmabuf,
-				   struct vmw_framebuffer **out,
-				   unsigned width, unsigned height)
+static int vmw_kms_new_framebuffer_dmabuf(struct vmw_private *dev_priv,
+					  struct vmw_dma_buffer *dmabuf,
+					  struct vmw_framebuffer **out,
+					  const struct drm_mode_fb_cmd
+					  *mode_cmd)
 
 {
 	struct drm_device *dev = dev_priv->dev;
 	struct vmw_framebuffer_dmabuf *vfbd;
+	unsigned int requested_size;
 	int ret;
 
+	requested_size = mode_cmd->height * mode_cmd->pitch;
+	if (unlikely(requested_size > dmabuf->base.num_pages * PAGE_SIZE)) {
+		DRM_ERROR("Screen buffer object size is too small "
+			  "for requested mode.\n");
+		return -EINVAL;
+	}
+
 	vfbd = kzalloc(sizeof(*vfbd), GFP_KERNEL);
 	if (!vfbd) {
 		ret = -ENOMEM;
@@ -685,12 +733,11 @@ int vmw_kms_new_framebuffer_dmabuf(struct vmw_private *dev_priv,
 		goto out_err3;
 	}
 
-	/* XXX get the first 3 from the surface info */
-	vfbd->base.base.bits_per_pixel = 32;
-	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;
+	vfbd->base.base.bits_per_pixel = mode_cmd->bpp;
+	vfbd->base.base.pitch = mode_cmd->pitch;
+	vfbd->base.base.depth = mode_cmd->depth;
+	vfbd->base.base.width = mode_cmd->width;
+	vfbd->base.base.height = mode_cmd->height;
 	vfbd->base.pin = vmw_framebuffer_dmabuf_pin;
 	vfbd->base.unpin = vmw_framebuffer_dmabuf_unpin;
 	vfbd->buffer = dmabuf;
@@ -719,8 +766,25 @@ static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev,
 	struct vmw_framebuffer *vfb = NULL;
 	struct vmw_surface *surface = NULL;
 	struct vmw_dma_buffer *bo = NULL;
+	unsigned int required_size;
 	int ret;
 
+	/**
+	 * This code should be conditioned on Screen Objects not being used.
+	 * If screen objects are used, we can allocate a GMR to hold the
+	 * requested framebuffer.
+	 */
+
+	required_size = mode_cmd->pitch * mode_cmd->height;
+	if (unlikely(required_size > dev_priv->vram_size)) {
+		DRM_ERROR("VRAM size is too small for requested mode.\n");
+		return NULL;
+	}
+
+	/**
+	 * End conditioned code.
+	 */
+
 	ret = vmw_user_surface_lookup_handle(dev_priv, tfile,
 					     mode_cmd->handle, &surface);
 	if (ret)
@@ -730,7 +794,7 @@ static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev,
 		goto err_not_scanout;
 
 	ret = vmw_kms_new_framebuffer_surface(dev_priv, surface, &vfb,
-					      mode_cmd->width, mode_cmd->height);
+					      mode_cmd);
 
 	/* vmw_user_surface_lookup takes one ref so does new_fb */
 	vmw_surface_unreference(&surface);
@@ -751,7 +815,7 @@ try_dmabuf:
 	}
 
 	ret = vmw_kms_new_framebuffer_dmabuf(dev_priv, bo, &vfb,
-					     mode_cmd->width, mode_cmd->height);
+					     mode_cmd);
 
 	/* vmw_user_dmabuf_lookup takes one ref so does new_fb */
 	vmw_dmabuf_unreference(&bo);
-- 
1.6.2.5

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 03/15] vmwgfx: Fix ACPI S3 & S4 functionality.
  2010-09-27 13:20   ` [PATCH 02/15] vmwgfx: Really support other depths than 32 Thomas Hellstrom
@ 2010-09-27 13:20     ` Thomas Hellstrom
  2010-09-27 13:20       ` [PATCH 04/15] vmwgfx: Add new-style PM hooks to improve hibernation behavior Thomas Hellstrom
  2010-09-27 22:41       ` [PATCH 03/15] vmwgfx: Fix ACPI S3 & S4 functionality Dave Airlie
  0 siblings, 2 replies; 20+ messages in thread
From: Thomas Hellstrom @ 2010-09-27 13:20 UTC (permalink / raw)
  To: airlied; +Cc: Thomas Hellstrom, dri-devel

Don't suspend or hibernate when there are 3D resources active since we
can't restore the device's 3D state. Instead fail with an error message.

In other cases, make sure we re-enable the fifo and unlock ttm on resume.

Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com>
---
 drivers/gpu/drm/vmwgfx/vmwgfx_drv.c |   38 +++++++++++++++++++++++++++++++++-
 drivers/gpu/drm/vmwgfx/vmwgfx_drv.h |    1 +
 2 files changed, 37 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
index 40bdb54..a3ab1e7 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
@@ -753,15 +753,40 @@ static int vmwgfx_pm_notifier(struct notifier_block *nb, unsigned long val,
 		 * Buffer contents is moved to swappable memory.
 		 */
 		ttm_bo_swapout_all(&dev_priv->bdev);
+
+		/**
+		 * Release 3d reference held by fbdev and potentially
+		 * stop fifo.
+		 */
+		dev_priv->suspended = true;
+		if (dev_priv->enable_fb)
+			vmw_3d_resource_dec(dev_priv);
+
 		break;
 	case PM_POST_HIBERNATION:
 	case PM_POST_SUSPEND:
+	case PM_POST_RESTORE:
+		if (!dev_priv->suspended) {
+			printk(KERN_WARNING
+			       "[%s] Driver is not suspended at resume"
+			       " point.\n", VMWGFX_DRIVER_NAME);
+
+			break;
+		}
+
+		/**
+		 * Reclaim 3d reference held by fbdev and potentially
+		 * start fifo.
+		 */
+		if (dev_priv->enable_fb)
+			vmw_3d_resource_inc(dev_priv);
+
+		dev_priv->suspended = false;
 		ttm_suspend_unlock(&vmaster->lock);
+
 		break;
 	case PM_RESTORE_PREPARE:
 		break;
-	case PM_POST_RESTORE:
-		break;
 	default:
 		break;
 	}
@@ -774,6 +799,15 @@ static int vmwgfx_pm_notifier(struct notifier_block *nb, unsigned long val,
 
 int vmw_pci_suspend(struct pci_dev *pdev, pm_message_t state)
 {
+	struct drm_device *dev = pci_get_drvdata(pdev);
+	struct vmw_private *dev_priv = vmw_priv(dev);
+
+	if (dev_priv->num_3d_resources != 0) {
+		DRM_INFO("Can't suspend or hibernate "
+			 "while 3D resources are active.\n");
+		return -EBUSY;
+	}
+
 	pci_save_state(pdev);
 	pci_disable_device(pdev);
 	pci_set_power_state(pdev, PCI_D3hot);
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
index 9142454..b0b10a4 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
@@ -286,6 +286,7 @@ struct vmw_private {
 	struct vmw_master *active_master;
 	struct vmw_master fbdev_master;
 	struct notifier_block pm_nb;
+	bool suspended;
 
 	struct mutex release_mutex;
 	uint32_t num_3d_resources;
-- 
1.6.2.5

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 04/15] vmwgfx: Add new-style PM hooks to improve hibernation behavior
  2010-09-27 13:20     ` [PATCH 03/15] vmwgfx: Fix ACPI S3 & S4 functionality Thomas Hellstrom
@ 2010-09-27 13:20       ` Thomas Hellstrom
  2010-09-27 13:20         ` [PATCH 05/15] drm: vmwgfx: Add a struct drm_file parameter to the dirty framebuffer callback Thomas Hellstrom
  2010-09-27 22:41       ` [PATCH 03/15] vmwgfx: Fix ACPI S3 & S4 functionality Dave Airlie
  1 sibling, 1 reply; 20+ messages in thread
From: Thomas Hellstrom @ 2010-09-27 13:20 UTC (permalink / raw)
  To: airlied; +Cc: Thomas Hellstrom, dri-devel

Add the new-style PM hooks prepare and complete. This allows us to
power up the device again after the hibernation image has been created, and
display output will thus be active until the VM is finally powered off.

Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com>
---
 drivers/gpu/drm/vmwgfx/vmwgfx_drv.c |  113 ++++++++++++++++++++++++-----------
 1 files changed, 79 insertions(+), 34 deletions(-)

diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
index a3ab1e7..6902b72 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
@@ -754,34 +754,10 @@ static int vmwgfx_pm_notifier(struct notifier_block *nb, unsigned long val,
 		 */
 		ttm_bo_swapout_all(&dev_priv->bdev);
 
-		/**
-		 * Release 3d reference held by fbdev and potentially
-		 * stop fifo.
-		 */
-		dev_priv->suspended = true;
-		if (dev_priv->enable_fb)
-			vmw_3d_resource_dec(dev_priv);
-
 		break;
 	case PM_POST_HIBERNATION:
 	case PM_POST_SUSPEND:
 	case PM_POST_RESTORE:
-		if (!dev_priv->suspended) {
-			printk(KERN_WARNING
-			       "[%s] Driver is not suspended at resume"
-			       " point.\n", VMWGFX_DRIVER_NAME);
-
-			break;
-		}
-
-		/**
-		 * Reclaim 3d reference held by fbdev and potentially
-		 * start fifo.
-		 */
-		if (dev_priv->enable_fb)
-			vmw_3d_resource_inc(dev_priv);
-
-		dev_priv->suspended = false;
 		ttm_suspend_unlock(&vmaster->lock);
 
 		break;
@@ -797,7 +773,7 @@ static int vmwgfx_pm_notifier(struct notifier_block *nb, unsigned long val,
  * These might not be needed with the virtual SVGA device.
  */
 
-int vmw_pci_suspend(struct pci_dev *pdev, pm_message_t state)
+static int vmw_pci_suspend(struct pci_dev *pdev, pm_message_t state)
 {
 	struct drm_device *dev = pci_get_drvdata(pdev);
 	struct vmw_private *dev_priv = vmw_priv(dev);
@@ -814,13 +790,81 @@ int vmw_pci_suspend(struct pci_dev *pdev, pm_message_t state)
 	return 0;
 }
 
-int vmw_pci_resume(struct pci_dev *pdev)
+static int vmw_pci_resume(struct pci_dev *pdev)
 {
 	pci_set_power_state(pdev, PCI_D0);
 	pci_restore_state(pdev);
 	return pci_enable_device(pdev);
 }
 
+static int vmw_pm_suspend(struct device *kdev)
+{
+	struct pci_dev *pdev = to_pci_dev(kdev);
+	struct pm_message dummy;
+
+	dummy.event = 0;
+
+	return vmw_pci_suspend(pdev, dummy);
+}
+
+static int vmw_pm_resume(struct device *kdev)
+{
+	struct pci_dev *pdev = to_pci_dev(kdev);
+
+	return vmw_pci_resume(pdev);
+}
+
+static int vmw_pm_prepare(struct device *kdev)
+{
+	struct pci_dev *pdev = to_pci_dev(kdev);
+	struct drm_device *dev = pci_get_drvdata(pdev);
+	struct vmw_private *dev_priv = vmw_priv(dev);
+
+	/**
+	 * Release 3d reference held by fbdev and potentially
+	 * stop fifo.
+	 */
+	dev_priv->suspended = true;
+	if (dev_priv->enable_fb)
+		vmw_3d_resource_dec(dev_priv);
+
+	if (dev_priv->num_3d_resources != 0) {
+
+		DRM_INFO("Can't suspend or hibernate "
+			 "while 3D resources are active.\n");
+
+		if (dev_priv->enable_fb)
+			vmw_3d_resource_inc(dev_priv);
+		dev_priv->suspended = false;
+		return -EBUSY;
+	}
+
+	return 0;
+}
+
+static void vmw_pm_complete(struct device *kdev)
+{
+	struct pci_dev *pdev = to_pci_dev(kdev);
+	struct drm_device *dev = pci_get_drvdata(pdev);
+	struct vmw_private *dev_priv = vmw_priv(dev);
+
+	/**
+	 * Reclaim 3d reference held by fbdev and potentially
+	 * start fifo.
+	 */
+	if (dev_priv->enable_fb)
+		vmw_3d_resource_inc(dev_priv);
+
+	dev_priv->suspended = false;
+}
+
+static const struct dev_pm_ops vmw_pm_ops = {
+	.prepare = vmw_pm_prepare,
+	.complete = vmw_pm_complete,
+	.suspend = vmw_pm_suspend,
+	.resume = vmw_pm_resume,
+};
+
 static struct drm_driver driver = {
 	.driver_features = DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED |
 	DRIVER_MODESET,
@@ -853,15 +897,16 @@ static struct drm_driver driver = {
 #if defined(CONFIG_COMPAT)
 		 .compat_ioctl = drm_compat_ioctl,
 #endif
-		 },
+	},
 	.pci_driver = {
-		       .name = VMWGFX_DRIVER_NAME,
-		       .id_table = vmw_pci_id_list,
-		       .probe = vmw_probe,
-		       .remove = vmw_remove,
-		       .suspend = vmw_pci_suspend,
-		       .resume = vmw_pci_resume
-		       },
+		 .name = VMWGFX_DRIVER_NAME,
+		 .id_table = vmw_pci_id_list,
+		 .probe = vmw_probe,
+		 .remove = vmw_remove,
+		 .driver = {
+			 .pm = &vmw_pm_ops
+		 }
+	 },
 	.name = VMWGFX_DRIVER_NAME,
 	.desc = VMWGFX_DRIVER_DESC,
 	.date = VMWGFX_DRIVER_DATE,
-- 
1.6.2.5

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 05/15] drm: vmwgfx: Add a struct drm_file parameter to the dirty framebuffer callback
  2010-09-27 13:20       ` [PATCH 04/15] vmwgfx: Add new-style PM hooks to improve hibernation behavior Thomas Hellstrom
@ 2010-09-27 13:20         ` Thomas Hellstrom
  2010-09-27 13:20           ` [PATCH 06/15] vmwgfx: Take the ttm lock around the dirty ioctl Thomas Hellstrom
  0 siblings, 1 reply; 20+ messages in thread
From: Thomas Hellstrom @ 2010-09-27 13:20 UTC (permalink / raw)
  To: airlied; +Cc: Thomas Hellstrom, dri-devel

This is needed for the callback to identify the caller and take
appropriate locks if needed.

Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com>
---
 drivers/gpu/drm/drm_crtc.c          |    3 ++-
 drivers/gpu/drm/vmwgfx/vmwgfx_kms.c |    2 ++
 include/drm/drm_crtc.h              |    3 ++-
 3 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 37e0b4f..6985cb1 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -1854,7 +1854,8 @@ int drm_mode_dirtyfb_ioctl(struct drm_device *dev,
 	}
 
 	if (fb->funcs->dirty) {
-		ret = fb->funcs->dirty(fb, flags, r->color, clips, num_clips);
+		ret = fb->funcs->dirty(fb, file_priv, flags, r->color,
+				       clips, num_clips);
 	} else {
 		ret = -ENOSYS;
 		goto out_err2;
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
index e4444e0..fc31ea7 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
@@ -392,6 +392,7 @@ out_unlock:
 
 
 int vmw_framebuffer_surface_dirty(struct drm_framebuffer *framebuffer,
+				  struct drm_file *file_priv,
 				  unsigned flags, unsigned color,
 				  struct drm_clip_rect *clips,
 				  unsigned num_clips)
@@ -583,6 +584,7 @@ void vmw_framebuffer_dmabuf_destroy(struct drm_framebuffer *framebuffer)
 }
 
 int vmw_framebuffer_dmabuf_dirty(struct drm_framebuffer *framebuffer,
+				 struct drm_file *file_priv,
 				 unsigned flags, unsigned color,
 				 struct drm_clip_rect *clips,
 				 unsigned num_clips)
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 3e5a51a..15c4796 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -221,7 +221,8 @@ struct drm_framebuffer_funcs {
 	 * the semantics and arguments have a one to one mapping
 	 * on this function.
 	 */
-	int (*dirty)(struct drm_framebuffer *framebuffer, unsigned flags,
+	int (*dirty)(struct drm_framebuffer *framebuffer,
+		     struct drm_file *file_priv, unsigned flags,
 		     unsigned color, struct drm_clip_rect *clips,
 		     unsigned num_clips);
 };
-- 
1.6.2.5

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 06/15] vmwgfx: Take the ttm lock around the dirty ioctl
  2010-09-27 13:20         ` [PATCH 05/15] drm: vmwgfx: Add a struct drm_file parameter to the dirty framebuffer callback Thomas Hellstrom
@ 2010-09-27 13:20           ` Thomas Hellstrom
  2010-09-27 13:20             ` [PATCH 07/15] vmwgfx: Prune modes based on available VRAM size Thomas Hellstrom
  0 siblings, 1 reply; 20+ messages in thread
From: Thomas Hellstrom @ 2010-09-27 13:20 UTC (permalink / raw)
  To: airlied; +Cc: Thomas Hellstrom, dri-devel

This makes sure noone accesses the fifo while it's taken down using the
dirty ioctl.
Also make sure all workqueues are idled before the fifo is taken down.

Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com>
---
 drivers/gpu/drm/vmwgfx/vmwgfx_drv.c |    5 ++-
 drivers/gpu/drm/vmwgfx/vmwgfx_drv.h |    3 +
 drivers/gpu/drm/vmwgfx/vmwgfx_kms.c |   84 ++++++++++++++++++++++++++++++++---
 3 files changed, 84 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
index 6902b72..76d7842 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
@@ -599,6 +599,8 @@ static void vmw_lastclose(struct drm_device *dev)
 static void vmw_master_init(struct vmw_master *vmaster)
 {
 	ttm_lock_init(&vmaster->lock);
+	INIT_LIST_HEAD(&vmaster->fb_surf);
+	mutex_init(&vmaster->fb_surf_mutex);
 }
 
 static int vmw_master_create(struct drm_device *dev,
@@ -610,7 +612,7 @@ static int vmw_master_create(struct drm_device *dev,
 	if (unlikely(vmaster == NULL))
 		return -ENOMEM;
 
-	ttm_lock_init(&vmaster->lock);
+	vmw_master_init(vmaster);
 	ttm_lock_set_kill(&vmaster->lock, true, SIGTERM);
 	master->driver_priv = vmaster;
 
@@ -701,6 +703,7 @@ static void vmw_master_drop(struct drm_device *dev,
 
 	vmw_fp->locked_master = drm_master_get(file_priv->master);
 	ret = ttm_vt_lock(&vmaster->lock, false, vmw_fp->tfile);
+	vmw_kms_idle_workqueues(vmaster);
 
 	if (unlikely((ret != 0))) {
 		DRM_ERROR("Unable to lock TTM at VT switch.\n");
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
index b0b10a4..8f09a56 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
@@ -151,6 +151,8 @@ struct vmw_overlay;
 
 struct vmw_master {
 	struct ttm_lock lock;
+	struct mutex fb_surf_mutex;
+	struct list_head fb_surf;
 };
 
 struct vmw_vga_topology_state {
@@ -519,6 +521,7 @@ void vmw_kms_write_svga(struct vmw_private *vmw_priv,
 			unsigned bbp, unsigned depth);
 int vmw_kms_update_layout_ioctl(struct drm_device *dev, void *data,
 				struct drm_file *file_priv);
+void vmw_kms_idle_workqueues(struct vmw_master *vmaster);
 
 /**
  * Overlay control - vmwgfx_overlay.c
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
index fc31ea7..56ce75b 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
@@ -332,18 +332,55 @@ struct vmw_framebuffer_surface {
 	struct delayed_work d_work;
 	struct mutex work_lock;
 	bool present_fs;
+	struct list_head head;
+	struct drm_master *master;
 };
 
+/**
+ * vmw_kms_idle_workqueues - Flush workqueues on this master
+ *
+ * @vmaster - Pointer identifying the master, for the surfaces of which
+ * we idle the dirty work queues.
+ *
+ * This function should be called with the ttm lock held in exclusive mode
+ * to idle all dirty work queues before the fifo is taken down.
+ *
+ * The work task may actually requeue itself, but after the flush returns we're
+ * sure that there's nothing to present, since the ttm lock is held in
+ * exclusive mode, so the fifo will never get used.
+ */
+
+void vmw_kms_idle_workqueues(struct vmw_master *vmaster)
+{
+	struct vmw_framebuffer_surface *entry;
+
+	mutex_lock(&vmaster->fb_surf_mutex);
+	list_for_each_entry(entry, &vmaster->fb_surf, head) {
+		if (cancel_delayed_work_sync(&entry->d_work))
+			(void) entry->d_work.work.func(&entry->d_work.work);
+
+		(void) cancel_delayed_work_sync(&entry->d_work);
+	}
+	mutex_unlock(&vmaster->fb_surf_mutex);
+}
+
 void vmw_framebuffer_surface_destroy(struct drm_framebuffer *framebuffer)
 {
-	struct vmw_framebuffer_surface *vfb =
+	struct vmw_framebuffer_surface *vfbs =
 		vmw_framebuffer_to_vfbs(framebuffer);
+	struct vmw_master *vmaster = vmw_master(vfbs->master);
+
 
-	cancel_delayed_work_sync(&vfb->d_work);
+	mutex_lock(&vmaster->fb_surf_mutex);
+	list_del(&vfbs->head);
+	mutex_unlock(&vmaster->fb_surf_mutex);
+
+	cancel_delayed_work_sync(&vfbs->d_work);
+	drm_master_put(&vfbs->master);
 	drm_framebuffer_cleanup(framebuffer);
-	vmw_surface_unreference(&vfb->surface);
+	vmw_surface_unreference(&vfbs->surface);
 
-	kfree(framebuffer);
+	kfree(vfbs);
 }
 
 static void vmw_framebuffer_present_fs_callback(struct work_struct *work)
@@ -362,6 +399,12 @@ static void vmw_framebuffer_present_fs_callback(struct work_struct *work)
 		SVGA3dCopyRect cr;
 	} *cmd;
 
+	/**
+	 * Strictly we should take the ttm_lock in read mode before accessing
+	 * the fifo, to make sure the fifo is present and up. However,
+	 * instead we flush all workqueues under the ttm lock in exclusive mode
+	 * before taking down the fifo.
+	 */
 	mutex_lock(&vfbs->work_lock);
 	if (!vfbs->present_fs)
 		goto out_unlock;
@@ -398,12 +441,14 @@ int vmw_framebuffer_surface_dirty(struct drm_framebuffer *framebuffer,
 				  unsigned num_clips)
 {
 	struct vmw_private *dev_priv = vmw_priv(framebuffer->dev);
+	struct vmw_master *vmaster = vmw_master(file_priv->master);
 	struct vmw_framebuffer_surface *vfbs =
 		vmw_framebuffer_to_vfbs(framebuffer);
 	struct vmw_surface *surf = vfbs->surface;
 	struct drm_clip_rect norect;
 	SVGA3dCopyRect *cr;
 	int i, inc = 1;
+	int ret;
 
 	struct {
 		SVGA3dCmdHeader header;
@@ -411,6 +456,13 @@ int vmw_framebuffer_surface_dirty(struct drm_framebuffer *framebuffer,
 		SVGA3dCopyRect cr;
 	} *cmd;
 
+	if (unlikely(vfbs->master != file_priv->master))
+		return -EINVAL;
+
+	ret = ttm_read_lock(&vmaster->lock, true);
+	if (unlikely(ret != 0))
+		return ret;
+
 	if (!num_clips ||
 	    !(dev_priv->fifo.capabilities &
 	      SVGA_FIFO_CAP_SCREEN_OBJECT)) {
@@ -426,6 +478,7 @@ int vmw_framebuffer_surface_dirty(struct drm_framebuffer *framebuffer,
 			 */
 			vmw_framebuffer_present_fs_callback(&vfbs->d_work.work);
 		}
+		ttm_read_unlock(&vmaster->lock);
 		return 0;
 	}
 
@@ -443,6 +496,7 @@ int vmw_framebuffer_surface_dirty(struct drm_framebuffer *framebuffer,
 	cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd) + (num_clips - 1) * sizeof(cmd->cr));
 	if (unlikely(cmd == NULL)) {
 		DRM_ERROR("Fifo reserve failed.\n");
+		ttm_read_unlock(&vmaster->lock);
 		return -ENOMEM;
 	}
 
@@ -462,7 +516,7 @@ int vmw_framebuffer_surface_dirty(struct drm_framebuffer *framebuffer,
 	}
 
 	vmw_fifo_commit(dev_priv, sizeof(*cmd) + (num_clips - 1) * sizeof(cmd->cr));
-
+	ttm_read_unlock(&vmaster->lock);
 	return 0;
 }
 
@@ -473,6 +527,7 @@ static struct drm_framebuffer_funcs vmw_framebuffer_surface_funcs = {
 };
 
 static int vmw_kms_new_framebuffer_surface(struct vmw_private *dev_priv,
+					   struct drm_file *file_priv,
 					   struct vmw_surface *surface,
 					   struct vmw_framebuffer **out,
 					   const struct drm_mode_fb_cmd
@@ -482,6 +537,7 @@ static int vmw_kms_new_framebuffer_surface(struct vmw_private *dev_priv,
 	struct drm_device *dev = dev_priv->dev;
 	struct vmw_framebuffer_surface *vfbs;
 	enum SVGA3dSurfaceFormat format;
+	struct vmw_master *vmaster = vmw_master(file_priv->master);
 	int ret;
 
 	/*
@@ -546,8 +602,14 @@ static int vmw_kms_new_framebuffer_surface(struct vmw_private *dev_priv,
 	vfbs->base.pin = &vmw_surface_dmabuf_pin;
 	vfbs->base.unpin = &vmw_surface_dmabuf_unpin;
 	vfbs->surface = surface;
+	vfbs->master = drm_master_get(file_priv->master);
 	mutex_init(&vfbs->work_lock);
+
+	mutex_lock(&vmaster->fb_surf_mutex);
 	INIT_DELAYED_WORK(&vfbs->d_work, &vmw_framebuffer_present_fs_callback);
+	list_add_tail(&vfbs->head, &vmaster->fb_surf);
+	mutex_unlock(&vmaster->fb_surf_mutex);
+
 	*out = &vfbs->base;
 
 	return 0;
@@ -590,13 +652,19 @@ int vmw_framebuffer_dmabuf_dirty(struct drm_framebuffer *framebuffer,
 				 unsigned num_clips)
 {
 	struct vmw_private *dev_priv = vmw_priv(framebuffer->dev);
+	struct vmw_master *vmaster = vmw_master(file_priv->master);
 	struct drm_clip_rect norect;
+	int ret;
 	struct {
 		uint32_t header;
 		SVGAFifoCmdUpdate body;
 	} *cmd;
 	int i, increment = 1;
 
+	ret = ttm_read_lock(&vmaster->lock, true);
+	if (unlikely(ret != 0))
+		return ret;
+
 	if (!num_clips) {
 		num_clips = 1;
 		clips = &norect;
@@ -611,6 +679,7 @@ int vmw_framebuffer_dmabuf_dirty(struct drm_framebuffer *framebuffer,
 	cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd) * num_clips);
 	if (unlikely(cmd == NULL)) {
 		DRM_ERROR("Fifo reserve failed.\n");
+		ttm_read_unlock(&vmaster->lock);
 		return -ENOMEM;
 	}
 
@@ -623,6 +692,7 @@ int vmw_framebuffer_dmabuf_dirty(struct drm_framebuffer *framebuffer,
 	}
 
 	vmw_fifo_commit(dev_priv, sizeof(*cmd) * num_clips);
+	ttm_read_unlock(&vmaster->lock);
 
 	return 0;
 }
@@ -795,8 +865,8 @@ static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev,
 	if (!surface->scanout)
 		goto err_not_scanout;
 
-	ret = vmw_kms_new_framebuffer_surface(dev_priv, surface, &vfb,
-					      mode_cmd);
+	ret = vmw_kms_new_framebuffer_surface(dev_priv, file_priv, surface,
+					      &vfb, mode_cmd);
 
 	/* vmw_user_surface_lookup takes one ref so does new_fb */
 	vmw_surface_unreference(&surface);
-- 
1.6.2.5

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 07/15] vmwgfx: Prune modes based on available VRAM size
  2010-09-27 13:20           ` [PATCH 06/15] vmwgfx: Take the ttm lock around the dirty ioctl Thomas Hellstrom
@ 2010-09-27 13:20             ` Thomas Hellstrom
  2010-09-27 13:20               ` [PATCH 08/15] vmwgfx: Don't flush fb if we're in the suspended state Thomas Hellstrom
  0 siblings, 1 reply; 20+ messages in thread
From: Thomas Hellstrom @ 2010-09-27 13:20 UTC (permalink / raw)
  To: airlied; +Cc: Thomas Hellstrom, dri-devel

This needs to be reviewed once we support screen objects and don't rely
on VRAM for the frame-buffer.

Also fix some integer overflow issues pointed out by Michel Daenzer.

Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com>
---
 drivers/gpu/drm/vmwgfx/vmwgfx_drv.h |    3 +++
 drivers/gpu/drm/vmwgfx/vmwgfx_fb.c  |    7 +++++++
 drivers/gpu/drm/vmwgfx/vmwgfx_kms.c |   11 +++++++++--
 drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c |   28 +++++++++++++++++++---------
 4 files changed, 38 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
index 8f09a56..38e8b3c 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
@@ -522,6 +522,9 @@ void vmw_kms_write_svga(struct vmw_private *vmw_priv,
 int vmw_kms_update_layout_ioctl(struct drm_device *dev, void *data,
 				struct drm_file *file_priv);
 void vmw_kms_idle_workqueues(struct vmw_master *vmaster);
+bool vmw_kms_validate_mode_vram(struct vmw_private *dev_priv,
+				uint32_t pitch,
+				uint32_t height);
 
 /**
  * Overlay control - vmwgfx_overlay.c
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c
index 870967a..cf38a61 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c
@@ -144,6 +144,13 @@ static int vmw_fb_check_var(struct fb_var_screeninfo *var,
 		return -EINVAL;
 	}
 
+	if (!vmw_kms_validate_mode_vram(vmw_priv,
+					info->fix.line_length,
+					var->yoffset + var->yres)) {
+		DRM_ERROR("Requested geom can not fit in framebuffer\n");
+		return -EINVAL;
+	}
+
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
index 56ce75b..3ee2492 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
@@ -838,7 +838,7 @@ static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev,
 	struct vmw_framebuffer *vfb = NULL;
 	struct vmw_surface *surface = NULL;
 	struct vmw_dma_buffer *bo = NULL;
-	unsigned int required_size;
+	u64 required_size;
 	int ret;
 
 	/**
@@ -848,7 +848,7 @@ static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev,
 	 */
 
 	required_size = mode_cmd->pitch * mode_cmd->height;
-	if (unlikely(required_size > dev_priv->vram_size)) {
+	if (unlikely(required_size > (u64) dev_priv->vram_size)) {
 		DRM_ERROR("VRAM size is too small for requested mode.\n");
 		return NULL;
 	}
@@ -1132,3 +1132,10 @@ out_unlock:
 	ttm_read_unlock(&vmaster->lock);
 	return ret;
 }
+
+bool vmw_kms_validate_mode_vram(struct vmw_private *dev_priv,
+				uint32_t pitch,
+				uint32_t height)
+{
+	return ((u64) pitch * (u64) height) < (u64) dev_priv->vram_size;
+}
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
index 7083b1a..2337e72 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
@@ -425,7 +425,9 @@ static int vmw_ldu_connector_fill_modes(struct drm_connector *connector,
 {
 	struct vmw_legacy_display_unit *ldu = vmw_connector_to_ldu(connector);
 	struct drm_device *dev = connector->dev;
+	struct vmw_private *dev_priv = vmw_priv(dev);
 	struct drm_display_mode *mode = NULL;
+	struct drm_display_mode *bmode;
 	struct drm_display_mode prefmode = { DRM_MODE("preferred",
 		DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
 		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@@ -441,22 +443,30 @@ static int vmw_ldu_connector_fill_modes(struct drm_connector *connector,
 		mode->hdisplay = ldu->pref_width;
 		mode->vdisplay = ldu->pref_height;
 		mode->vrefresh = drm_mode_vrefresh(mode);
-		drm_mode_probed_add(connector, mode);
+		if (vmw_kms_validate_mode_vram(dev_priv, mode->hdisplay * 2,
+					       mode->vdisplay)) {
+			drm_mode_probed_add(connector, mode);
 
-		if (ldu->pref_mode) {
-			list_del_init(&ldu->pref_mode->head);
-			drm_mode_destroy(dev, ldu->pref_mode);
-		}
+			if (ldu->pref_mode) {
+				list_del_init(&ldu->pref_mode->head);
+				drm_mode_destroy(dev, ldu->pref_mode);
+			}
 
-		ldu->pref_mode = mode;
+			ldu->pref_mode = mode;
+		}
 	}
 
 	for (i = 0; vmw_ldu_connector_builtin[i].type != 0; i++) {
-		if (vmw_ldu_connector_builtin[i].hdisplay > max_width ||
-		    vmw_ldu_connector_builtin[i].vdisplay > max_height)
+		bmode = &vmw_ldu_connector_builtin[i];
+		if (bmode->hdisplay > max_width ||
+		    bmode->vdisplay > max_height)
+			continue;
+
+		if (!vmw_kms_validate_mode_vram(dev_priv, bmode->hdisplay * 2,
+						bmode->vdisplay))
 			continue;
 
-		mode = drm_mode_duplicate(dev, &vmw_ldu_connector_builtin[i]);
+		mode = drm_mode_duplicate(dev, bmode);
 		if (!mode)
 			return 0;
 		mode->vrefresh = drm_mode_vrefresh(mode);
-- 
1.6.2.5

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 08/15] vmwgfx: Don't flush fb if we're in the suspended state.
  2010-09-27 13:20             ` [PATCH 07/15] vmwgfx: Prune modes based on available VRAM size Thomas Hellstrom
@ 2010-09-27 13:20               ` Thomas Hellstrom
  2010-09-27 13:20                 ` [PATCH 09/15] vmwgfx: Add a parameter to get the max fb size Thomas Hellstrom
  0 siblings, 1 reply; 20+ messages in thread
From: Thomas Hellstrom @ 2010-09-27 13:20 UTC (permalink / raw)
  To: airlied; +Cc: Thomas Hellstrom, dri-devel

Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com>
---
 drivers/gpu/drm/vmwgfx/vmwgfx_fb.c |    3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)

diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c
index cf38a61..cac0db0 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c
@@ -212,6 +212,9 @@ static void vmw_fb_dirty_flush(struct vmw_fb_par *par)
 		SVGAFifoCmdUpdate body;
 	} *cmd;
 
+	if (vmw_priv->suspended)
+		return;
+
 	spin_lock_irqsave(&par->dirty.lock, flags);
 	if (!par->dirty.active) {
 		spin_unlock_irqrestore(&par->dirty.lock, flags);
-- 
1.6.2.5

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 09/15] vmwgfx: Add a parameter to get the max fb size
  2010-09-27 13:20               ` [PATCH 08/15] vmwgfx: Don't flush fb if we're in the suspended state Thomas Hellstrom
@ 2010-09-27 13:20                 ` Thomas Hellstrom
  2010-09-27 13:20                   ` [PATCH 10/15] vmwgfx: Enable use of the vblank system Thomas Hellstrom
  0 siblings, 1 reply; 20+ messages in thread
From: Thomas Hellstrom @ 2010-09-27 13:20 UTC (permalink / raw)
  To: airlied; +Cc: Thomas Hellstrom, dri-devel

This can be used by the X server to restrict mode resolutions and size of
root pixmap.

Bump minor to announce this availability.
Bump driver date.

Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com>
---
 drivers/gpu/drm/vmwgfx/vmwgfx_drv.h   |    4 ++--
 drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c |    3 +++
 include/drm/vmwgfx_drm.h              |    1 +
 3 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
index 38e8b3c..f65e19f 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
@@ -39,9 +39,9 @@
 #include "ttm/ttm_execbuf_util.h"
 #include "ttm/ttm_module.h"
 
-#define VMWGFX_DRIVER_DATE "20100209"
+#define VMWGFX_DRIVER_DATE "20100723"
 #define VMWGFX_DRIVER_MAJOR 1
-#define VMWGFX_DRIVER_MINOR 2
+#define VMWGFX_DRIVER_MINOR 3
 #define VMWGFX_DRIVER_PATCHLEVEL 0
 #define VMWGFX_FILE_PAGE_OFFSET 0x00100000
 #define VMWGFX_FIFO_STATIC_SIZE (1024*1024)
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c
index 1c7a316..570d577 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c
@@ -54,6 +54,9 @@ int vmw_getparam_ioctl(struct drm_device *dev, void *data,
 	case DRM_VMW_PARAM_FIFO_CAPS:
 		param->value = dev_priv->fifo.capabilities;
 		break;
+	case DRM_VMW_PARAM_MAX_FB_SIZE:
+		param->value = dev_priv->vram_size;
+		break;
 	default:
 		DRM_ERROR("Illegal vmwgfx get param request: %d\n",
 			  param->param);
diff --git a/include/drm/vmwgfx_drm.h b/include/drm/vmwgfx_drm.h
index 4d08423..650e6bf 100644
--- a/include/drm/vmwgfx_drm.h
+++ b/include/drm/vmwgfx_drm.h
@@ -72,6 +72,7 @@
 #define DRM_VMW_PARAM_FIFO_OFFSET      3
 #define DRM_VMW_PARAM_HW_CAPS          4
 #define DRM_VMW_PARAM_FIFO_CAPS        5
+#define DRM_VMW_PARAM_MAX_FB_SIZE      6
 
 /**
  * struct drm_vmw_getparam_arg
-- 
1.6.2.5

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 10/15] vmwgfx: Enable use of the vblank system
  2010-09-27 13:20                 ` [PATCH 09/15] vmwgfx: Add a parameter to get the max fb size Thomas Hellstrom
@ 2010-09-27 13:20                   ` Thomas Hellstrom
  2010-09-27 13:20                     ` [PATCH 11/15] vmwgfx: Add modinfo version Thomas Hellstrom
  0 siblings, 1 reply; 20+ messages in thread
From: Thomas Hellstrom @ 2010-09-27 13:20 UTC (permalink / raw)
  To: airlied; +Cc: Thomas Hellstrom, dri-devel

This is to avoid accessing uninitialized data during
drm_irq_uninstall. At the same time, enable error check from
drm_kms_init which previously appeared to ignore all errors.

Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com>
---
 drivers/gpu/drm/vmwgfx/vmwgfx_drv.c |   46 +++++++++++++++++++----------------
 drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c |   27 +++++++++++++-------
 2 files changed, 42 insertions(+), 31 deletions(-)

diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
index 76d7842..3d896b7 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
@@ -374,17 +374,6 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
 
 	dev->dev_private = dev_priv;
 
-	if (!dev->devname)
-		dev->devname = vmw_devname;
-
-	if (dev_priv->capabilities & SVGA_CAP_IRQMASK) {
-		ret = drm_irq_install(dev);
-		if (unlikely(ret != 0)) {
-			DRM_ERROR("Failed installing irq: %d\n", ret);
-			goto out_no_irq;
-		}
-	}
-
 	ret = pci_request_regions(dev->pdev, "vmwgfx probe");
 	dev_priv->stealth = (ret != 0);
 	if (dev_priv->stealth) {
@@ -400,7 +389,9 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
 			goto out_no_device;
 		}
 	}
-	vmw_kms_init(dev_priv);
+	ret = vmw_kms_init(dev_priv);
+	if (unlikely(ret != 0))
+		goto out_no_kms;
 	vmw_overlay_init(dev_priv);
 	if (dev_priv->enable_fb) {
 		ret = vmw_3d_resource_inc(dev_priv);
@@ -416,24 +407,37 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
 			 "running the device in SVGA mode yet.\n");
 	}
 
+	if (!dev->devname)
+		dev->devname = vmw_devname;
+
+	if (dev_priv->capabilities & SVGA_CAP_IRQMASK) {
+		ret = drm_irq_install(dev);
+		if (unlikely(ret != 0)) {
+			DRM_ERROR("Failed installing irq: %d\n", ret);
+			goto out_no_irq;
+		}
+	}
+
 	dev_priv->pm_nb.notifier_call = vmwgfx_pm_notifier;
 	register_pm_notifier(&dev_priv->pm_nb);
 
 	return 0;
 
+out_no_irq:
+	if (dev_priv->enable_fb) {
+		vmw_fb_close(dev_priv);
+		vmw_kms_restore_vga(dev_priv);
+		vmw_3d_resource_dec(dev_priv);
+	}
 out_no_fifo:
 	vmw_overlay_close(dev_priv);
 	vmw_kms_close(dev_priv);
+out_no_kms:
 	if (dev_priv->stealth)
 		pci_release_region(dev->pdev, 2);
 	else
 		pci_release_regions(dev->pdev);
 out_no_device:
-	if (dev_priv->capabilities & SVGA_CAP_IRQMASK)
-		drm_irq_uninstall(dev_priv->dev);
-	if (dev->devname == vmw_devname)
-		dev->devname = NULL;
-out_no_irq:
 	ttm_object_device_release(&dev_priv->tdev);
 out_err4:
 	iounmap(dev_priv->mmio_virt);
@@ -460,6 +464,10 @@ static int vmw_driver_unload(struct drm_device *dev)
 
 	unregister_pm_notifier(&dev_priv->pm_nb);
 
+	if (dev_priv->capabilities & SVGA_CAP_IRQMASK)
+		drm_irq_uninstall(dev_priv->dev);
+	if (dev->devname == vmw_devname)
+		dev->devname = NULL;
 	if (dev_priv->enable_fb) {
 		vmw_fb_close(dev_priv);
 		vmw_kms_restore_vga(dev_priv);
@@ -472,10 +480,6 @@ static int vmw_driver_unload(struct drm_device *dev)
 	else
 		pci_release_regions(dev->pdev);
 
-	if (dev_priv->capabilities & SVGA_CAP_IRQMASK)
-		drm_irq_uninstall(dev_priv->dev);
-	if (dev->devname == vmw_devname)
-		dev->devname = NULL;
 	ttm_object_device_release(&dev_priv->tdev);
 	iounmap(dev_priv->mmio_virt);
 	drm_mtrr_del(dev_priv->mmio_mtrr, dev_priv->mmio_start,
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
index 2337e72..a01c47d 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
@@ -27,6 +27,8 @@
 
 #include "vmwgfx_kms.h"
 
+#define VMWGFX_LDU_NUM_DU 8
+
 #define vmw_crtc_to_ldu(x) \
 	container_of(x, struct vmw_legacy_display_unit, base.crtc)
 #define vmw_encoder_to_ldu(x) \
@@ -546,6 +548,10 @@ static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit)
 
 int vmw_kms_init_legacy_display_system(struct vmw_private *dev_priv)
 {
+	struct drm_device *dev = dev_priv->dev;
+	int i;
+	int ret;
+
 	if (dev_priv->ldu_priv) {
 		DRM_INFO("ldu system already on\n");
 		return -EINVAL;
@@ -563,23 +569,24 @@ int vmw_kms_init_legacy_display_system(struct vmw_private *dev_priv)
 
 	drm_mode_create_dirty_info_property(dev_priv->dev);
 
-	vmw_ldu_init(dev_priv, 0);
-	/* 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);
+		for (i = 0; i < VMWGFX_LDU_NUM_DU; ++i)
+			vmw_ldu_init(dev_priv, i);
+		ret = drm_vblank_init(dev, VMWGFX_LDU_NUM_DU);
+	} else {
+		/* for old hardware without multimon only enable one display */
+		vmw_ldu_init(dev_priv, 0);
+		ret = drm_vblank_init(dev, 1);
 	}
 
-	return 0;
+	return ret;
 }
 
 int vmw_kms_close_legacy_display_system(struct vmw_private *dev_priv)
 {
+	struct drm_device *dev = dev_priv->dev;
+
+	drm_vblank_cleanup(dev);
 	if (!dev_priv->ldu_priv)
 		return -ENOSYS;
 
-- 
1.6.2.5

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 11/15] vmwgfx: Add modinfo version
  2010-09-27 13:20                   ` [PATCH 10/15] vmwgfx: Enable use of the vblank system Thomas Hellstrom
@ 2010-09-27 13:20                     ` Thomas Hellstrom
  2010-09-27 13:20                       ` [PATCH 12/15] vmwgfx: Remove initialisation of dev::devname Thomas Hellstrom
  0 siblings, 1 reply; 20+ messages in thread
From: Thomas Hellstrom @ 2010-09-27 13:20 UTC (permalink / raw)
  To: airlied; +Cc: Thomas Hellstrom, dri-devel

Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com>
---
 drivers/gpu/drm/vmwgfx/vmwgfx_drv.c |    4 ++++
 1 files changed, 4 insertions(+), 0 deletions(-)

diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
index 3d896b7..0e5703a 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
@@ -947,3 +947,7 @@ module_exit(vmwgfx_exit);
 MODULE_AUTHOR("VMware Inc. and others");
 MODULE_DESCRIPTION("Standalone drm driver for the VMware SVGA device");
 MODULE_LICENSE("GPL and additional rights");
+MODULE_VERSION(__stringify(VMWGFX_DRIVER_MAJOR) "."
+	       __stringify(VMWGFX_DRIVER_MINOR) "."
+	       __stringify(VMWGFX_DRIVER_PATCHLEVEL) "."
+	       "0");
-- 
1.6.2.5

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 12/15] vmwgfx: Remove initialisation of dev::devname
  2010-09-27 13:20                     ` [PATCH 11/15] vmwgfx: Add modinfo version Thomas Hellstrom
@ 2010-09-27 13:20                       ` Thomas Hellstrom
  2010-09-27 13:20                         ` [PATCH 13/15] vmwgfx: Add a get_vblank_counter function Thomas Hellstrom
  0 siblings, 1 reply; 20+ messages in thread
From: Thomas Hellstrom @ 2010-09-27 13:20 UTC (permalink / raw)
  To: airlied; +Cc: Thomas Hellstrom, dri-devel

The removed code causes oopses with newer drms on master drop.

Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com>
---
 drivers/gpu/drm/vmwgfx/vmwgfx_drv.c |    6 ------
 1 files changed, 0 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
index 0e5703a..b819535 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
@@ -148,7 +148,6 @@ static struct pci_device_id vmw_pci_id_list[] = {
 	{0, 0, 0}
 };
 
-static char *vmw_devname = "vmwgfx";
 static int enable_fbdev;
 
 static int vmw_probe(struct pci_dev *, const struct pci_device_id *);
@@ -407,9 +406,6 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
 			 "running the device in SVGA mode yet.\n");
 	}
 
-	if (!dev->devname)
-		dev->devname = vmw_devname;
-
 	if (dev_priv->capabilities & SVGA_CAP_IRQMASK) {
 		ret = drm_irq_install(dev);
 		if (unlikely(ret != 0)) {
@@ -466,8 +462,6 @@ static int vmw_driver_unload(struct drm_device *dev)
 
 	if (dev_priv->capabilities & SVGA_CAP_IRQMASK)
 		drm_irq_uninstall(dev_priv->dev);
-	if (dev->devname == vmw_devname)
-		dev->devname = NULL;
 	if (dev_priv->enable_fb) {
 		vmw_fb_close(dev_priv);
 		vmw_kms_restore_vga(dev_priv);
-- 
1.6.2.5

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 13/15] vmwgfx: Add a get_vblank_counter function
  2010-09-27 13:20                       ` [PATCH 12/15] vmwgfx: Remove initialisation of dev::devname Thomas Hellstrom
@ 2010-09-27 13:20                         ` Thomas Hellstrom
  2010-09-27 13:20                           ` [PATCH 14/15] vmwgfx: Save at least one screen layout Thomas Hellstrom
  2010-09-28  7:23                           ` [PATCH 13/15] vmwgfx: Add a get_vblank_counter function Michel Dänzer
  0 siblings, 2 replies; 20+ messages in thread
From: Thomas Hellstrom @ 2010-09-27 13:20 UTC (permalink / raw)
  To: airlied; +Cc: Thomas Hellstrom, dri-devel

Avoids an oops during drm_irq_uninstall.

Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com>
---
 drivers/gpu/drm/vmwgfx/vmwgfx_drv.c |    1 +
 drivers/gpu/drm/vmwgfx/vmwgfx_drv.h |    2 ++
 drivers/gpu/drm/vmwgfx/vmwgfx_kms.c |    5 +++++
 3 files changed, 8 insertions(+), 0 deletions(-)

diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
index b819535..bd6ff3e 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
@@ -877,6 +877,7 @@ static struct drm_driver driver = {
 	.irq_postinstall = vmw_irq_postinstall,
 	.irq_uninstall = vmw_irq_uninstall,
 	.irq_handler = vmw_irq_handler,
+	.get_vblank_counter = vmw_get_vblank_counter,
 	.reclaim_buffers_locked = NULL,
 	.ioctls = vmw_ioctls,
 	.num_ioctls = DRM_ARRAY_SIZE(vmw_ioctls),
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
index f65e19f..5e9d61f 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
@@ -525,6 +525,8 @@ void vmw_kms_idle_workqueues(struct vmw_master *vmaster);
 bool vmw_kms_validate_mode_vram(struct vmw_private *dev_priv,
 				uint32_t pitch,
 				uint32_t height);
+u32 vmw_get_vblank_counter(struct drm_device *dev, int crtc);
+
 
 /**
  * Overlay control - vmwgfx_overlay.c
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
index 3ee2492..5fb68f3 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
@@ -1139,3 +1139,8 @@ bool vmw_kms_validate_mode_vram(struct vmw_private *dev_priv,
 {
 	return ((u64) pitch * (u64) height) < (u64) dev_priv->vram_size;
 }
+
+u32 vmw_get_vblank_counter(struct drm_device *dev, int crtc)
+{
+	return 0;
+}
-- 
1.6.2.5

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 14/15] vmwgfx: Save at least one screen layout
  2010-09-27 13:20                         ` [PATCH 13/15] vmwgfx: Add a get_vblank_counter function Thomas Hellstrom
@ 2010-09-27 13:20                           ` Thomas Hellstrom
  2010-09-27 13:20                             ` [PATCH 15/15] vmwgfx: Bump minor and driver date Thomas Hellstrom
  2010-09-28  7:23                           ` [PATCH 13/15] vmwgfx: Add a get_vblank_counter function Michel Dänzer
  1 sibling, 1 reply; 20+ messages in thread
From: Thomas Hellstrom @ 2010-09-27 13:20 UTC (permalink / raw)
  To: airlied; +Cc: Thomas Hellstrom, dri-devel

Save at least one screen layout during vga save to avoid odd things
happening during restore.

Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com>
---
 drivers/gpu/drm/vmwgfx/vmwgfx_kms.c |    3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)

diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
index 5fb68f3..87c6e61 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
@@ -1025,6 +1025,9 @@ int vmw_kms_save_vga(struct vmw_private *vmw_priv)
 	vmw_priv->num_displays = vmw_read(vmw_priv,
 					  SVGA_REG_NUM_GUEST_DISPLAYS);
 
+	if (vmw_priv->num_displays == 0)
+		vmw_priv->num_displays = 1;
+
 	for (i = 0; i < vmw_priv->num_displays; ++i) {
 		save = &vmw_priv->vga_save[i];
 		vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, i);
-- 
1.6.2.5

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 15/15] vmwgfx: Bump minor and driver date
  2010-09-27 13:20                           ` [PATCH 14/15] vmwgfx: Save at least one screen layout Thomas Hellstrom
@ 2010-09-27 13:20                             ` Thomas Hellstrom
  0 siblings, 0 replies; 20+ messages in thread
From: Thomas Hellstrom @ 2010-09-27 13:20 UTC (permalink / raw)
  To: airlied; +Cc: Thomas Hellstrom, dri-devel

Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com>
---
 drivers/gpu/drm/vmwgfx/vmwgfx_drv.h |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
index 5e9d61f..38f9b84 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
@@ -39,9 +39,9 @@
 #include "ttm/ttm_execbuf_util.h"
 #include "ttm/ttm_module.h"
 
-#define VMWGFX_DRIVER_DATE "20100723"
+#define VMWGFX_DRIVER_DATE "20100927"
 #define VMWGFX_DRIVER_MAJOR 1
-#define VMWGFX_DRIVER_MINOR 3
+#define VMWGFX_DRIVER_MINOR 4
 #define VMWGFX_DRIVER_PATCHLEVEL 0
 #define VMWGFX_FILE_PAGE_OFFSET 0x00100000
 #define VMWGFX_FIFO_STATIC_SIZE (1024*1024)
-- 
1.6.2.5

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* Re: [PATCH 03/15] vmwgfx: Fix ACPI S3 & S4 functionality.
  2010-09-27 13:20     ` [PATCH 03/15] vmwgfx: Fix ACPI S3 & S4 functionality Thomas Hellstrom
  2010-09-27 13:20       ` [PATCH 04/15] vmwgfx: Add new-style PM hooks to improve hibernation behavior Thomas Hellstrom
@ 2010-09-27 22:41       ` Dave Airlie
  2010-09-28  6:44         ` Thomas Hellstrom
  1 sibling, 1 reply; 20+ messages in thread
From: Dave Airlie @ 2010-09-27 22:41 UTC (permalink / raw)
  To: Thomas Hellstrom; +Cc: airlied, dri-devel

On Mon, Sep 27, 2010 at 11:20 PM, Thomas Hellstrom
<thellstrom@vmware.com> wrote:
> Don't suspend or hibernate when there are 3D resources active since we
> can't restore the device's 3D state. Instead fail with an error message.

Its not acceptable to block suspend ever like that, you need to
restore the devices 3D state somehow,

since if you are running a compiz desktop or something, you'll never
have a time when the resources aren't active.

Dave.

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH 03/15] vmwgfx: Fix ACPI S3 & S4 functionality.
  2010-09-27 22:41       ` [PATCH 03/15] vmwgfx: Fix ACPI S3 & S4 functionality Dave Airlie
@ 2010-09-28  6:44         ` Thomas Hellstrom
  0 siblings, 0 replies; 20+ messages in thread
From: Thomas Hellstrom @ 2010-09-28  6:44 UTC (permalink / raw)
  To: Dave Airlie; +Cc: airlied, dri-devel

On 09/28/2010 12:41 AM, Dave Airlie wrote:
> On Mon, Sep 27, 2010 at 11:20 PM, Thomas Hellstrom
> <thellstrom@vmware.com>  wrote:
>    
>> Don't suspend or hibernate when there are 3D resources active since we
>> can't restore the device's 3D state. Instead fail with an error message.
>>      
> Its not acceptable to block suspend ever like that, you need to
> restore the devices 3D state somehow,
>
> since if you are running a compiz desktop or something, you'll never
> have a time when the resources aren't active.
>
> Dave.
>    
Dave,

In principle I agree.

However, in this case we should be aware, that suspending / hibernating 
a guest VM using S3 / S4 is an extremely rare event, that is the result 
of the user doing something stupid. A VM should be suspended from the 
GUI (which justs makes the host stop the VM saving its complete state).

If the host is suspending / hibernating, like if you close the lid, the 
VM will just go to sleep like any other user-space process, and the 
suspend / hibernate event will not be propagated to the guest.

But unfortunately we can't stop the user from trying S3/S4 suspend / 
hibernate, from within the guest VM, so we need to do some kind of 
graceful failure here. The alternative is a 3D hang when the user 
resumes, because we can't really introduce code in the kernel that 
tracks the complete state of all 3D contexts (well, we probably can, but 
it's going to be ugly and error-prone).

I think a future version of the device will have capabilities to save 
and restore the device state.

Given this special case,
Would this patch be acceptable?

Thanks,
Thomas

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH 13/15] vmwgfx: Add a get_vblank_counter function
  2010-09-27 13:20                         ` [PATCH 13/15] vmwgfx: Add a get_vblank_counter function Thomas Hellstrom
  2010-09-27 13:20                           ` [PATCH 14/15] vmwgfx: Save at least one screen layout Thomas Hellstrom
@ 2010-09-28  7:23                           ` Michel Dänzer
  2010-09-28  8:06                             ` Thomas Hellstrom
  1 sibling, 1 reply; 20+ messages in thread
From: Michel Dänzer @ 2010-09-28  7:23 UTC (permalink / raw)
  To: Thomas Hellstrom; +Cc: airlied, dri-devel

On Mon, 2010-09-27 at 15:20 +0200, Thomas Hellstrom wrote: 
> Avoids an oops during drm_irq_uninstall.

Why not fix the oops instead of providing dummy hooks to work around it?


-- 
Earthling Michel Dänzer           |                http://www.vmware.com
Libre software enthusiast         |          Debian, X and DRI developer
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH 13/15] vmwgfx: Add a get_vblank_counter function
  2010-09-28  7:23                           ` [PATCH 13/15] vmwgfx: Add a get_vblank_counter function Michel Dänzer
@ 2010-09-28  8:06                             ` Thomas Hellstrom
  0 siblings, 0 replies; 20+ messages in thread
From: Thomas Hellstrom @ 2010-09-28  8:06 UTC (permalink / raw)
  To: Michel Dänzer; +Cc: airlied, dri-devel

On 09/28/2010 09:23 AM, Michel Dänzer wrote:
> On Mon, 2010-09-27 at 15:20 +0200, Thomas Hellstrom wrote:
>    
>> Avoids an oops during drm_irq_uninstall.
>>      
> Why not fix the oops instead of providing dummy hooks to work around it?
>
>
>    
This is because the vblank system in DRM appears unconditional. You 
can't choose not to enable it, because then you'd hit uninitialized 
values during various ioctls and drm_irq_uninstall.

Simply testing for presence of the get_vblank_counter function before 
calling it would mean providing the dummy hook in core drm instead of 
the driver...

A correct fix would require making the vblank system optional, and isn't 
a trivial task, so I figured better to put that on the to-do list and 
fix the oops now.

/Thomas

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 20+ messages in thread

end of thread, other threads:[~2010-09-28  8:06 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-09-27 13:20 [PATCH 0/15] vmwgfx updates Thomas Hellstrom
2010-09-27 13:20 ` [PATCH 01/15] vmwgfx: Add an option to choose whether to enable fbdev at load time Thomas Hellstrom
2010-09-27 13:20   ` [PATCH 02/15] vmwgfx: Really support other depths than 32 Thomas Hellstrom
2010-09-27 13:20     ` [PATCH 03/15] vmwgfx: Fix ACPI S3 & S4 functionality Thomas Hellstrom
2010-09-27 13:20       ` [PATCH 04/15] vmwgfx: Add new-style PM hooks to improve hibernation behavior Thomas Hellstrom
2010-09-27 13:20         ` [PATCH 05/15] drm: vmwgfx: Add a struct drm_file parameter to the dirty framebuffer callback Thomas Hellstrom
2010-09-27 13:20           ` [PATCH 06/15] vmwgfx: Take the ttm lock around the dirty ioctl Thomas Hellstrom
2010-09-27 13:20             ` [PATCH 07/15] vmwgfx: Prune modes based on available VRAM size Thomas Hellstrom
2010-09-27 13:20               ` [PATCH 08/15] vmwgfx: Don't flush fb if we're in the suspended state Thomas Hellstrom
2010-09-27 13:20                 ` [PATCH 09/15] vmwgfx: Add a parameter to get the max fb size Thomas Hellstrom
2010-09-27 13:20                   ` [PATCH 10/15] vmwgfx: Enable use of the vblank system Thomas Hellstrom
2010-09-27 13:20                     ` [PATCH 11/15] vmwgfx: Add modinfo version Thomas Hellstrom
2010-09-27 13:20                       ` [PATCH 12/15] vmwgfx: Remove initialisation of dev::devname Thomas Hellstrom
2010-09-27 13:20                         ` [PATCH 13/15] vmwgfx: Add a get_vblank_counter function Thomas Hellstrom
2010-09-27 13:20                           ` [PATCH 14/15] vmwgfx: Save at least one screen layout Thomas Hellstrom
2010-09-27 13:20                             ` [PATCH 15/15] vmwgfx: Bump minor and driver date Thomas Hellstrom
2010-09-28  7:23                           ` [PATCH 13/15] vmwgfx: Add a get_vblank_counter function Michel Dänzer
2010-09-28  8:06                             ` Thomas Hellstrom
2010-09-27 22:41       ` [PATCH 03/15] vmwgfx: Fix ACPI S3 & S4 functionality Dave Airlie
2010-09-28  6:44         ` Thomas Hellstrom

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.