aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSinclair Yeh <syeh@vmware.com>2015-08-12 01:53:39 -0400
committerThomas Hellstrom <thellstrom@vmware.com>2015-08-12 13:06:13 -0400
commit05c9501859c8bd80635d7299c384e2a8db7c0ce1 (patch)
treee47acf304f87b83a2fae3cbb0827e3399ab4ffd0
parentdf45e9d410fc07ab816b006414f52ec4e2fbf2d7 (diff)
drm/vmwgfx: Fix crash when unloading vmwgfx v2
This patch fixes two issues. One, when a surface is a proxy for a DMA buffer, it holds an extra reference that needs to be cleared. Two, when fbdev is enabled, we need to unpin the framebuffer before unloading the driver. This is done by a call to vmw_fb_off(). v2 Moved unreferencing surface to from vmw_framebuffer_surface_destroy() to vmw_kms_new_framebuffer() Added "struct vmw_framebuffer *vfb = NULL;" to silence a compiler warning. Removed error checking after calling vmw_surface/dmabuf_reference() Signed-off-by: Sinclair Yeh <syeh@vmware.com> Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com>
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_drv.c1
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_kms.c42
2 files changed, 19 insertions, 24 deletions
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
index bc4235f75f61..65e35654f0f2 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
@@ -915,6 +915,7 @@ static int vmw_driver_unload(struct drm_device *dev)
915 drm_ht_remove(&dev_priv->ctx.res_ht); 915 drm_ht_remove(&dev_priv->ctx.res_ht);
916 vfree(dev_priv->ctx.cmd_bounce); 916 vfree(dev_priv->ctx.cmd_bounce);
917 if (dev_priv->enable_fb) { 917 if (dev_priv->enable_fb) {
918 vmw_fb_off(dev_priv);
918 vmw_fb_close(dev_priv); 919 vmw_fb_close(dev_priv);
919 vmw_fifo_resource_dec(dev_priv); 920 vmw_fifo_resource_dec(dev_priv);
920 vmw_svga_disable(dev_priv); 921 vmw_svga_disable(dev_priv);
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
index 8b8ae20ab62f..34d04bf17dfa 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
@@ -539,19 +539,13 @@ static int vmw_kms_new_framebuffer_surface(struct vmw_private *dev_priv,
539 goto out_err1; 539 goto out_err1;
540 } 540 }
541 541
542 if (!vmw_surface_reference(surface)) {
543 DRM_ERROR("failed to reference surface %p\n", surface);
544 ret = -EINVAL;
545 goto out_err2;
546 }
547
548 /* XXX get the first 3 from the surface info */ 542 /* XXX get the first 3 from the surface info */
549 vfbs->base.base.bits_per_pixel = mode_cmd->bpp; 543 vfbs->base.base.bits_per_pixel = mode_cmd->bpp;
550 vfbs->base.base.pitches[0] = mode_cmd->pitch; 544 vfbs->base.base.pitches[0] = mode_cmd->pitch;
551 vfbs->base.base.depth = mode_cmd->depth; 545 vfbs->base.base.depth = mode_cmd->depth;
552 vfbs->base.base.width = mode_cmd->width; 546 vfbs->base.base.width = mode_cmd->width;
553 vfbs->base.base.height = mode_cmd->height; 547 vfbs->base.base.height = mode_cmd->height;
554 vfbs->surface = surface; 548 vfbs->surface = vmw_surface_reference(surface);
555 vfbs->base.user_handle = mode_cmd->handle; 549 vfbs->base.user_handle = mode_cmd->handle;
556 vfbs->is_dmabuf_proxy = is_dmabuf_proxy; 550 vfbs->is_dmabuf_proxy = is_dmabuf_proxy;
557 551
@@ -560,13 +554,12 @@ static int vmw_kms_new_framebuffer_surface(struct vmw_private *dev_priv,
560 ret = drm_framebuffer_init(dev, &vfbs->base.base, 554 ret = drm_framebuffer_init(dev, &vfbs->base.base,
561 &vmw_framebuffer_surface_funcs); 555 &vmw_framebuffer_surface_funcs);
562 if (ret) 556 if (ret)
563 goto out_err3; 557 goto out_err2;
564 558
565 return 0; 559 return 0;
566 560
567out_err3:
568 vmw_surface_unreference(&surface);
569out_err2: 561out_err2:
562 vmw_surface_unreference(&surface);
570 kfree(vfbs); 563 kfree(vfbs);
571out_err1: 564out_err1:
572 return ret; 565 return ret;
@@ -836,32 +829,25 @@ static int vmw_kms_new_framebuffer_dmabuf(struct vmw_private *dev_priv,
836 goto out_err1; 829 goto out_err1;
837 } 830 }
838 831
839 if (!vmw_dmabuf_reference(dmabuf)) {
840 DRM_ERROR("failed to reference dmabuf %p\n", dmabuf);
841 ret = -EINVAL;
842 goto out_err2;
843 }
844
845 vfbd->base.base.bits_per_pixel = mode_cmd->bpp; 832 vfbd->base.base.bits_per_pixel = mode_cmd->bpp;
846 vfbd->base.base.pitches[0] = mode_cmd->pitch; 833 vfbd->base.base.pitches[0] = mode_cmd->pitch;
847 vfbd->base.base.depth = mode_cmd->depth; 834 vfbd->base.base.depth = mode_cmd->depth;
848 vfbd->base.base.width = mode_cmd->width; 835 vfbd->base.base.width = mode_cmd->width;
849 vfbd->base.base.height = mode_cmd->height; 836 vfbd->base.base.height = mode_cmd->height;
850 vfbd->base.dmabuf = true; 837 vfbd->base.dmabuf = true;
851 vfbd->buffer = dmabuf; 838 vfbd->buffer = vmw_dmabuf_reference(dmabuf);
852 vfbd->base.user_handle = mode_cmd->handle; 839 vfbd->base.user_handle = mode_cmd->handle;
853 *out = &vfbd->base; 840 *out = &vfbd->base;
854 841
855 ret = drm_framebuffer_init(dev, &vfbd->base.base, 842 ret = drm_framebuffer_init(dev, &vfbd->base.base,
856 &vmw_framebuffer_dmabuf_funcs); 843 &vmw_framebuffer_dmabuf_funcs);
857 if (ret) 844 if (ret)
858 goto out_err3; 845 goto out_err2;
859 846
860 return 0; 847 return 0;
861 848
862out_err3:
863 vmw_dmabuf_unreference(&dmabuf);
864out_err2: 849out_err2:
850 vmw_dmabuf_unreference(&dmabuf);
865 kfree(vfbd); 851 kfree(vfbd);
866out_err1: 852out_err1:
867 return ret; 853 return ret;
@@ -886,7 +872,7 @@ vmw_kms_new_framebuffer(struct vmw_private *dev_priv,
886 bool only_2d, 872 bool only_2d,
887 const struct drm_mode_fb_cmd *mode_cmd) 873 const struct drm_mode_fb_cmd *mode_cmd)
888{ 874{
889 struct vmw_framebuffer *vfb; 875 struct vmw_framebuffer *vfb = NULL;
890 bool is_dmabuf_proxy = false; 876 bool is_dmabuf_proxy = false;
891 int ret; 877 int ret;
892 878
@@ -906,15 +892,23 @@ vmw_kms_new_framebuffer(struct vmw_private *dev_priv,
906 } 892 }
907 893
908 /* Create the new framebuffer depending one what we have */ 894 /* Create the new framebuffer depending one what we have */
909 if (surface) 895 if (surface) {
910 ret = vmw_kms_new_framebuffer_surface(dev_priv, surface, &vfb, 896 ret = vmw_kms_new_framebuffer_surface(dev_priv, surface, &vfb,
911 mode_cmd, 897 mode_cmd,
912 is_dmabuf_proxy); 898 is_dmabuf_proxy);
913 else if (dmabuf) 899
900 /*
901 * vmw_create_dmabuf_proxy() adds a reference that is no longer
902 * needed
903 */
904 if (is_dmabuf_proxy)
905 vmw_surface_unreference(&surface);
906 } else if (dmabuf) {
914 ret = vmw_kms_new_framebuffer_dmabuf(dev_priv, dmabuf, &vfb, 907 ret = vmw_kms_new_framebuffer_dmabuf(dev_priv, dmabuf, &vfb,
915 mode_cmd); 908 mode_cmd);
916 else 909 } else {
917 BUG(); 910 BUG();
911 }
918 912
919 if (ret) 913 if (ret)
920 return ERR_PTR(ret); 914 return ERR_PTR(ret);