aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_drv.c102
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_drv.h7
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c3
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_kms.c12
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_resource.c4
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 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
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
index 429f917b60b..9142454cc91 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
@@ -277,6 +277,7 @@ struct vmw_private {
277 277
278 bool stealth; 278 bool stealth;
279 bool is_opened; 279 bool is_opened;
280 bool enable_fb;
280 281
281 /** 282 /**
282 * Master management. 283 * Master management.
@@ -285,6 +286,9 @@ struct vmw_private {
285 struct vmw_master *active_master; 286 struct vmw_master *active_master;
286 struct vmw_master fbdev_master; 287 struct vmw_master fbdev_master;
287 struct notifier_block pm_nb; 288 struct notifier_block pm_nb;
289
290 struct mutex release_mutex;
291 uint32_t num_3d_resources;
288}; 292};
289 293
290static inline struct vmw_private *vmw_priv(struct drm_device *dev) 294static 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,
319 return val; 323 return val;
320} 324}
321 325
326int vmw_3d_resource_inc(struct vmw_private *dev_priv);
327void vmw_3d_resource_dec(struct vmw_private *dev_priv);
328
322/** 329/**
323 * GMR utilities - vmwgfx_gmr.c 330 * GMR utilities - vmwgfx_gmr.c
324 */ 331 */
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c
index e6a1eb7ea95..0fe31766e4c 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)
106 mutex_lock(&dev_priv->hw_mutex); 106 mutex_lock(&dev_priv->hw_mutex);
107 dev_priv->enable_state = vmw_read(dev_priv, SVGA_REG_ENABLE); 107 dev_priv->enable_state = vmw_read(dev_priv, SVGA_REG_ENABLE);
108 dev_priv->config_done_state = vmw_read(dev_priv, SVGA_REG_CONFIG_DONE); 108 dev_priv->config_done_state = vmw_read(dev_priv, SVGA_REG_CONFIG_DONE);
109 dev_priv->traces_state = vmw_read(dev_priv, SVGA_REG_TRACES);
109 vmw_write(dev_priv, SVGA_REG_ENABLE, 1); 110 vmw_write(dev_priv, SVGA_REG_ENABLE, 1);
110 111
111 min = 4; 112 min = 4;
@@ -175,6 +176,8 @@ void vmw_fifo_release(struct vmw_private *dev_priv, struct vmw_fifo_state *fifo)
175 dev_priv->config_done_state); 176 dev_priv->config_done_state);
176 vmw_write(dev_priv, SVGA_REG_ENABLE, 177 vmw_write(dev_priv, SVGA_REG_ENABLE,
177 dev_priv->enable_state); 178 dev_priv->enable_state);
179 vmw_write(dev_priv, SVGA_REG_TRACES,
180 dev_priv->traces_state);
178 181
179 mutex_unlock(&dev_priv->hw_mutex); 182 mutex_unlock(&dev_priv->hw_mutex);
180 vmw_fence_queue_takedown(&fifo->fence_queue); 183 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 64d7f47df86..1636e9ba81a 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)
898 save->width = vmw_read(vmw_priv, SVGA_REG_DISPLAY_WIDTH); 898 save->width = vmw_read(vmw_priv, SVGA_REG_DISPLAY_WIDTH);
899 save->height = vmw_read(vmw_priv, SVGA_REG_DISPLAY_HEIGHT); 899 save->height = vmw_read(vmw_priv, SVGA_REG_DISPLAY_HEIGHT);
900 vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, SVGA_ID_INVALID); 900 vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, SVGA_ID_INVALID);
901 if (i == 0 && vmw_priv->num_displays == 1 &&
902 save->width == 0 && save->height == 0) {
903
904 /*
905 * It should be fairly safe to assume that these
906 * values are uninitialized.
907 */
908
909 save->width = vmw_priv->vga_width - save->pos_x;
910 save->height = vmw_priv->vga_height - save->pos_y;
911 }
901 } 912 }
913
902 return 0; 914 return 0;
903} 915}
904 916
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
index 5f2d5df01e5..c8c40e9979d 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)
211 cmd->body.cid = cpu_to_le32(res->id); 211 cmd->body.cid = cpu_to_le32(res->id);
212 212
213 vmw_fifo_commit(dev_priv, sizeof(*cmd)); 213 vmw_fifo_commit(dev_priv, sizeof(*cmd));
214 vmw_3d_resource_dec(dev_priv);
214} 215}
215 216
216static int vmw_context_init(struct vmw_private *dev_priv, 217static int vmw_context_init(struct vmw_private *dev_priv,
@@ -247,6 +248,7 @@ static int vmw_context_init(struct vmw_private *dev_priv,
247 cmd->body.cid = cpu_to_le32(res->id); 248 cmd->body.cid = cpu_to_le32(res->id);
248 249
249 vmw_fifo_commit(dev_priv, sizeof(*cmd)); 250 vmw_fifo_commit(dev_priv, sizeof(*cmd));
251 (void) vmw_3d_resource_inc(dev_priv);
250 vmw_resource_activate(res, vmw_hw_context_destroy); 252 vmw_resource_activate(res, vmw_hw_context_destroy);
251 return 0; 253 return 0;
252} 254}
@@ -406,6 +408,7 @@ static void vmw_hw_surface_destroy(struct vmw_resource *res)
406 cmd->body.sid = cpu_to_le32(res->id); 408 cmd->body.sid = cpu_to_le32(res->id);
407 409
408 vmw_fifo_commit(dev_priv, sizeof(*cmd)); 410 vmw_fifo_commit(dev_priv, sizeof(*cmd));
411 vmw_3d_resource_dec(dev_priv);
409} 412}
410 413
411void vmw_surface_res_free(struct vmw_resource *res) 414void vmw_surface_res_free(struct vmw_resource *res)
@@ -473,6 +476,7 @@ int vmw_surface_init(struct vmw_private *dev_priv,
473 } 476 }
474 477
475 vmw_fifo_commit(dev_priv, submit_size); 478 vmw_fifo_commit(dev_priv, submit_size);
479 (void) vmw_3d_resource_inc(dev_priv);
476 vmw_resource_activate(res, vmw_hw_surface_destroy); 480 vmw_resource_activate(res, vmw_hw_surface_destroy);
477 return 0; 481 return 0;
478} 482}