aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
diff options
context:
space:
mode:
authorThomas Hellstrom <thellstrom@vmware.com>2010-10-01 04:21:48 -0400
committerDave Airlie <airlied@redhat.com>2010-10-01 07:08:50 -0400
commit30c78bb838b26ec7997515844c0c734e454b3cba (patch)
tree04df1e7175ee697874a099477298eed3c706ec8b /drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
parent2854eedae2ff35d95e8923bebdb942bbd537c54f (diff)
vmwgfx: vt-switch (master drop) fixes
We add an option not to enable fbdev, 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. This fixes a bug where we previously lost 3D state during VT switch. Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com> Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/vmwgfx/vmwgfx_drv.c')
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_drv.c102
1 files changed, 89 insertions, 13 deletions
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
index 292aeba385e..23e29f3a0c3 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[] = {
149}; 149};
150 150
151static char *vmw_devname = "vmwgfx"; 151static char *vmw_devname = "vmwgfx";
152static int enable_fbdev;
152 153
153static int vmw_probe(struct pci_dev *, const struct pci_device_id *); 154static int vmw_probe(struct pci_dev *, const struct pci_device_id *);
154static void vmw_master_init(struct vmw_master *); 155static void vmw_master_init(struct vmw_master *);
155static int vmwgfx_pm_notifier(struct notifier_block *nb, unsigned long val, 156static int vmwgfx_pm_notifier(struct notifier_block *nb, unsigned long val,
156 void *ptr); 157 void *ptr);
157 158
159MODULE_PARM_DESC(enable_fbdev, "Enable vmwgfx fbdev");
160module_param_named(enable_fbdev, enable_fbdev, int, 0600);
161
158static void vmw_print_capabilities(uint32_t capabilities) 162static void vmw_print_capabilities(uint32_t capabilities)
159{ 163{
160 DRM_INFO("Capabilities:\n"); 164 DRM_INFO("Capabilities:\n");
@@ -192,8 +196,6 @@ static int vmw_request_device(struct vmw_private *dev_priv)
192{ 196{
193 int ret; 197 int ret;
194 198
195 vmw_kms_save_vga(dev_priv);
196
197 ret = vmw_fifo_init(dev_priv, &dev_priv->fifo); 199 ret = vmw_fifo_init(dev_priv, &dev_priv->fifo);
198 if (unlikely(ret != 0)) { 200 if (unlikely(ret != 0)) {
199 DRM_ERROR("Unable to initialize FIFO.\n"); 201 DRM_ERROR("Unable to initialize FIFO.\n");
@@ -206,10 +208,36 @@ static int vmw_request_device(struct vmw_private *dev_priv)
206static void vmw_release_device(struct vmw_private *dev_priv) 208static void vmw_release_device(struct vmw_private *dev_priv)
207{ 209{
208 vmw_fifo_release(dev_priv, &dev_priv->fifo); 210 vmw_fifo_release(dev_priv, &dev_priv->fifo);
209 vmw_kms_restore_vga(dev_priv); 211}
212
213int vmw_3d_resource_inc(struct vmw_private *dev_priv)
214{
215 int ret = 0;
216
217 mutex_lock(&dev_priv->release_mutex);
218 if (unlikely(dev_priv->num_3d_resources++ == 0)) {
219 ret = vmw_request_device(dev_priv);
220 if (unlikely(ret != 0))
221 --dev_priv->num_3d_resources;
222 }
223 mutex_unlock(&dev_priv->release_mutex);
224 return ret;
210} 225}
211 226
212 227
228void vmw_3d_resource_dec(struct vmw_private *dev_priv)
229{
230 int32_t n3d;
231
232 mutex_lock(&dev_priv->release_mutex);
233 if (unlikely(--dev_priv->num_3d_resources == 0))
234 vmw_release_device(dev_priv);
235 n3d = (int32_t) dev_priv->num_3d_resources;
236 mutex_unlock(&dev_priv->release_mutex);
237
238 BUG_ON(n3d < 0);
239}
240
213static int vmw_driver_load(struct drm_device *dev, unsigned long chipset) 241static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
214{ 242{
215 struct vmw_private *dev_priv; 243 struct vmw_private *dev_priv;
@@ -228,6 +256,7 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
228 dev_priv->last_read_sequence = (uint32_t) -100; 256 dev_priv->last_read_sequence = (uint32_t) -100;
229 mutex_init(&dev_priv->hw_mutex); 257 mutex_init(&dev_priv->hw_mutex);
230 mutex_init(&dev_priv->cmdbuf_mutex); 258 mutex_init(&dev_priv->cmdbuf_mutex);
259 mutex_init(&dev_priv->release_mutex);
231 rwlock_init(&dev_priv->resource_lock); 260 rwlock_init(&dev_priv->resource_lock);
232 idr_init(&dev_priv->context_idr); 261 idr_init(&dev_priv->context_idr);
233 idr_init(&dev_priv->surface_idr); 262 idr_init(&dev_priv->surface_idr);
@@ -244,6 +273,8 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
244 dev_priv->vram_start = pci_resource_start(dev->pdev, 1); 273 dev_priv->vram_start = pci_resource_start(dev->pdev, 1);
245 dev_priv->mmio_start = pci_resource_start(dev->pdev, 2); 274 dev_priv->mmio_start = pci_resource_start(dev->pdev, 2);
246 275
276 dev_priv->enable_fb = enable_fbdev;
277
247 mutex_lock(&dev_priv->hw_mutex); 278 mutex_lock(&dev_priv->hw_mutex);
248 279
249 vmw_write(dev_priv, SVGA_REG_ID, SVGA_ID_2); 280 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)
369 goto out_no_device; 400 goto out_no_device;
370 } 401 }
371 } 402 }
372 ret = vmw_request_device(dev_priv);
373 if (unlikely(ret != 0))
374 goto out_no_device;
375 vmw_kms_init(dev_priv); 403 vmw_kms_init(dev_priv);
376 vmw_overlay_init(dev_priv); 404 vmw_overlay_init(dev_priv);
377 vmw_fb_init(dev_priv); 405 if (dev_priv->enable_fb) {
406 ret = vmw_3d_resource_inc(dev_priv);
407 if (unlikely(ret != 0))
408 goto out_no_fifo;
409 vmw_kms_save_vga(dev_priv);
410 vmw_fb_init(dev_priv);
411 DRM_INFO("%s", vmw_fifo_have_3d(dev_priv) ?
412 "Detected device 3D availability.\n" :
413 "Detected no device 3D availability.\n");
414 } else {
415 DRM_INFO("Delayed 3D detection since we're not "
416 "running the device in SVGA mode yet.\n");
417 }
378 418
379 dev_priv->pm_nb.notifier_call = vmwgfx_pm_notifier; 419 dev_priv->pm_nb.notifier_call = vmwgfx_pm_notifier;
380 register_pm_notifier(&dev_priv->pm_nb); 420 register_pm_notifier(&dev_priv->pm_nb);
381 421
382 DRM_INFO("%s", vmw_fifo_have_3d(dev_priv) ? "Have 3D\n" : "No 3D\n");
383
384 return 0; 422 return 0;
385 423
424out_no_fifo:
425 vmw_overlay_close(dev_priv);
426 vmw_kms_close(dev_priv);
427 if (dev_priv->stealth)
428 pci_release_region(dev->pdev, 2);
429 else
430 pci_release_regions(dev->pdev);
386out_no_device: 431out_no_device:
387 if (dev_priv->capabilities & SVGA_CAP_IRQMASK) 432 if (dev_priv->capabilities & SVGA_CAP_IRQMASK)
388 drm_irq_uninstall(dev_priv->dev); 433 drm_irq_uninstall(dev_priv->dev);
@@ -415,10 +460,13 @@ static int vmw_driver_unload(struct drm_device *dev)
415 460
416 unregister_pm_notifier(&dev_priv->pm_nb); 461 unregister_pm_notifier(&dev_priv->pm_nb);
417 462
418 vmw_fb_close(dev_priv); 463 if (dev_priv->enable_fb) {
464 vmw_fb_close(dev_priv);
465 vmw_kms_restore_vga(dev_priv);
466 vmw_3d_resource_dec(dev_priv);
467 }
419 vmw_kms_close(dev_priv); 468 vmw_kms_close(dev_priv);
420 vmw_overlay_close(dev_priv); 469 vmw_overlay_close(dev_priv);
421 vmw_release_device(dev_priv);
422 if (dev_priv->stealth) 470 if (dev_priv->stealth)
423 pci_release_region(dev->pdev, 2); 471 pci_release_region(dev->pdev, 2);
424 else 472 else
@@ -589,6 +637,16 @@ static int vmw_master_set(struct drm_device *dev,
589 struct vmw_master *vmaster = vmw_master(file_priv->master); 637 struct vmw_master *vmaster = vmw_master(file_priv->master);
590 int ret = 0; 638 int ret = 0;
591 639
640 if (!dev_priv->enable_fb) {
641 ret = vmw_3d_resource_inc(dev_priv);
642 if (unlikely(ret != 0))
643 return ret;
644 vmw_kms_save_vga(dev_priv);
645 mutex_lock(&dev_priv->hw_mutex);
646 vmw_write(dev_priv, SVGA_REG_TRACES, 0);
647 mutex_unlock(&dev_priv->hw_mutex);
648 }
649
592 if (active) { 650 if (active) {
593 BUG_ON(active != &dev_priv->fbdev_master); 651 BUG_ON(active != &dev_priv->fbdev_master);
594 ret = ttm_vt_lock(&active->lock, false, vmw_fp->tfile); 652 ret = ttm_vt_lock(&active->lock, false, vmw_fp->tfile);
@@ -617,7 +675,13 @@ static int vmw_master_set(struct drm_device *dev,
617 return 0; 675 return 0;
618 676
619out_no_active_lock: 677out_no_active_lock:
620 vmw_release_device(dev_priv); 678 if (!dev_priv->enable_fb) {
679 mutex_lock(&dev_priv->hw_mutex);
680 vmw_write(dev_priv, SVGA_REG_TRACES, 1);
681 mutex_unlock(&dev_priv->hw_mutex);
682 vmw_kms_restore_vga(dev_priv);
683 vmw_3d_resource_dec(dev_priv);
684 }
621 return ret; 685 return ret;
622} 686}
623 687
@@ -645,11 +709,23 @@ static void vmw_master_drop(struct drm_device *dev,
645 709
646 ttm_lock_set_kill(&vmaster->lock, true, SIGTERM); 710 ttm_lock_set_kill(&vmaster->lock, true, SIGTERM);
647 711
712 if (!dev_priv->enable_fb) {
713 ret = ttm_bo_evict_mm(&dev_priv->bdev, TTM_PL_VRAM);
714 if (unlikely(ret != 0))
715 DRM_ERROR("Unable to clean VRAM on master drop.\n");
716 mutex_lock(&dev_priv->hw_mutex);
717 vmw_write(dev_priv, SVGA_REG_TRACES, 1);
718 mutex_unlock(&dev_priv->hw_mutex);
719 vmw_kms_restore_vga(dev_priv);
720 vmw_3d_resource_dec(dev_priv);
721 }
722
648 dev_priv->active_master = &dev_priv->fbdev_master; 723 dev_priv->active_master = &dev_priv->fbdev_master;
649 ttm_lock_set_kill(&dev_priv->fbdev_master.lock, false, SIGTERM); 724 ttm_lock_set_kill(&dev_priv->fbdev_master.lock, false, SIGTERM);
650 ttm_vt_unlock(&dev_priv->fbdev_master.lock); 725 ttm_vt_unlock(&dev_priv->fbdev_master.lock);
651 726
652 vmw_fb_on(dev_priv); 727 if (dev_priv->enable_fb)
728 vmw_fb_on(dev_priv);
653} 729}
654 730
655 731