diff options
-rw-r--r-- | drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 102 | ||||
-rw-r--r-- | drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | 7 | ||||
-rw-r--r-- | drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 12 | ||||
-rw-r--r-- | 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 292aeba385e0..23e29f3a0c33 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 | ||
151 | static char *vmw_devname = "vmwgfx"; | 151 | static char *vmw_devname = "vmwgfx"; |
152 | static int enable_fbdev; | ||
152 | 153 | ||
153 | static int vmw_probe(struct pci_dev *, const struct pci_device_id *); | 154 | static int vmw_probe(struct pci_dev *, const struct pci_device_id *); |
154 | static void vmw_master_init(struct vmw_master *); | 155 | static void vmw_master_init(struct vmw_master *); |
155 | static int vmwgfx_pm_notifier(struct notifier_block *nb, unsigned long val, | 156 | static int vmwgfx_pm_notifier(struct notifier_block *nb, unsigned long val, |
156 | void *ptr); | 157 | void *ptr); |
157 | 158 | ||
159 | MODULE_PARM_DESC(enable_fbdev, "Enable vmwgfx fbdev"); | ||
160 | module_param_named(enable_fbdev, enable_fbdev, int, 0600); | ||
161 | |||
158 | static void vmw_print_capabilities(uint32_t capabilities) | 162 | static 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) | |||
206 | static void vmw_release_device(struct vmw_private *dev_priv) | 208 | static 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 | |||
213 | int 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 | ||
228 | void 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 | |||
213 | static int vmw_driver_load(struct drm_device *dev, unsigned long chipset) | 241 | static 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 | ||
424 | out_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); | ||
386 | out_no_device: | 431 | out_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 | ||
619 | out_no_active_lock: | 677 | out_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 429f917b60bf..9142454cc91e 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 | ||
290 | static inline struct vmw_private *vmw_priv(struct drm_device *dev) | 294 | 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, | |||
319 | return val; | 323 | return val; |
320 | } | 324 | } |
321 | 325 | ||
326 | int vmw_3d_resource_inc(struct vmw_private *dev_priv); | ||
327 | void 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 e6a1eb7ea954..0fe31766e4cf 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 64d7f47df868..1636e9ba81a1 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 5f2d5df01e5c..c8c40e9979db 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 | ||
216 | static int vmw_context_init(struct vmw_private *dev_priv, | 217 | static 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 | ||
411 | void vmw_surface_res_free(struct vmw_resource *res) | 414 | void 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 | } |