Message ID | 1445894042-31468-1-git-send-email-kamal@canonical.com |
---|---|
State | New |
Headers | show |
Kamal, On 10/26/2015 10:14 PM, Kamal Mostafa wrote: > This is a note to let you know that I have just added a patch titled > > drm/vmwgfx: Fix up user_dmabuf refcounting > > to the linux-3.16.y-queue branch of the 3.16.y-ckt extended stable tree > which can be found at: > > https://urldefense.proofpoint.com/v2/url?u=http-3A__kernel.ubuntu.com_git_ubuntu_linux.git_log_-3Fh-3Dlinux-2D3.16.y-2Dqueue&d=BQIBAg&c=Sqcl0Ez6M0X8aeM67LKIiDJAXVeAw-YihVMNtXt-uEs&r=vpukPkBtpoNQp2IUKuFviOmPNYWVKmen3Jeeu55zmEA&m=isTitca95-By_EWSOxPnvLlaknByRjOoT7RUZIGf6qQ&s=TQTzdLueIXiKqaE8RiMOb_93cZMeCteUK1NObANnsFk&e= Unfortunately there was a regression introduced with this patch. The fix for the regression is tiny and introduced upstream with patch ed7d78b2da32198ca4c70172e3b63c6b3e2c570b, "drm/vmwgfx: Fix kernel NULL pointer dereference on older hardware", also CC'd stable. Please, if possible, make sure both these patches are pushed at the same time. > > This patch is scheduled to be released in version 3.19.8-ckt9. > > If you, or anyone else, feels it should not be added to this tree, please > reply to this email. > > For more information about the 3.16.y-ckt tree, see > https://urldefense.proofpoint.com/v2/url?u=https-3A__wiki.ubuntu.com_Kernel_Dev_ExtendedStable&d=BQIBAg&c=Sqcl0Ez6M0X8aeM67LKIiDJAXVeAw-YihVMNtXt-uEs&r=vpukPkBtpoNQp2IUKuFviOmPNYWVKmen3Jeeu55zmEA&m=isTitca95-By_EWSOxPnvLlaknByRjOoT7RUZIGf6qQ&s=UpPaE-obh_ulxo23i6417ysrWYr8XKtmGEnXV2ts5P0&e= > > Thanks. > -Kamal > > ------ > > From 127037ecff9d5e99fbc0c5405cb863dca04b9df7 Mon Sep 17 00:00:00 2001 > From: Thomas Hellstrom <thellstrom@vmware.com> > Date: Mon, 14 Sep 2015 01:13:11 -0700 > Subject: drm/vmwgfx: Fix up user_dmabuf refcounting > > commit 54c12bc374408faddbff75dbf1a6167c19af39c4 upstream. > > If user space calls unreference on a user_dmabuf it will typically > kill the struct ttm_base_object member which is responsible for the > user-space visibility. However the dmabuf part may still be alive and > refcounted. In some situations, like for shared guest-backed surface > referencing/opening, the driver may try to reference the > struct ttm_base_object member again, causing an immediate kernel warning > and a later kernel NULL pointer dereference. > > Fix this by always maintaining a reference on the struct > ttm_base_object member, in situations where it might subsequently be > referenced. > > Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com> > Reviewed-by: Brian Paul <brianp@vmware.com> > Reviewed-by: Sinclair Yeh <syeh@vmware.com> > Signed-off-by: Kamal Mostafa <kamal@canonical.com> > --- > drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | 6 ++++-- > drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c | 6 ++++-- > drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c | 2 +- > drivers/gpu/drm/vmwgfx/vmwgfx_resource.c | 29 +++++++++++++++++++++-------- > drivers/gpu/drm/vmwgfx/vmwgfx_shader.c | 2 +- > drivers/gpu/drm/vmwgfx/vmwgfx_surface.c | 11 ++++++++--- > 6 files changed, 39 insertions(+), 17 deletions(-) > > diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h > index d26a6da..d8896ed 100644 > --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h > +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h > @@ -636,7 +636,8 @@ extern int vmw_user_dmabuf_alloc(struct vmw_private *dev_priv, > uint32_t size, > bool shareable, > uint32_t *handle, > - struct vmw_dma_buffer **p_dma_buf); > + struct vmw_dma_buffer **p_dma_buf, > + struct ttm_base_object **p_base); > extern int vmw_user_dmabuf_reference(struct ttm_object_file *tfile, > struct vmw_dma_buffer *dma_buf, > uint32_t *handle); > @@ -650,7 +651,8 @@ extern uint32_t vmw_dmabuf_validate_node(struct ttm_buffer_object *bo, > uint32_t cur_validate_node); > extern void vmw_dmabuf_validate_clear(struct ttm_buffer_object *bo); > extern int vmw_user_dmabuf_lookup(struct ttm_object_file *tfile, > - uint32_t id, struct vmw_dma_buffer **out); > + uint32_t id, struct vmw_dma_buffer **out, > + struct ttm_base_object **base); > extern int vmw_stream_claim_ioctl(struct drm_device *dev, void *data, > struct drm_file *file_priv); > extern int vmw_stream_unref_ioctl(struct drm_device *dev, void *data, > diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c > index 2711b09..01b8423 100644 > --- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c > +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c > @@ -887,7 +887,8 @@ static int vmw_translate_mob_ptr(struct vmw_private *dev_priv, > struct vmw_relocation *reloc; > int ret; > > - ret = vmw_user_dmabuf_lookup(sw_context->fp->tfile, handle, &vmw_bo); > + ret = vmw_user_dmabuf_lookup(sw_context->fp->tfile, handle, &vmw_bo, > + NULL); > if (unlikely(ret != 0)) { > DRM_ERROR("Could not find or use MOB buffer.\n"); > return -EINVAL; > @@ -948,7 +949,8 @@ static int vmw_translate_guest_ptr(struct vmw_private *dev_priv, > struct vmw_relocation *reloc; > int ret; > > - ret = vmw_user_dmabuf_lookup(sw_context->fp->tfile, handle, &vmw_bo); > + ret = vmw_user_dmabuf_lookup(sw_context->fp->tfile, handle, &vmw_bo, > + NULL); > if (unlikely(ret != 0)) { > DRM_ERROR("Could not find or use GMR region.\n"); > return -EINVAL; > diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c b/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c > index 87e39f6..e189898 100644 > --- a/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c > +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c > @@ -484,7 +484,7 @@ int vmw_overlay_ioctl(struct drm_device *dev, void *data, > goto out_unlock; > } > > - ret = vmw_user_dmabuf_lookup(tfile, arg->handle, &buf); > + ret = vmw_user_dmabuf_lookup(tfile, arg->handle, &buf, NULL); > if (ret) > goto out_unlock; > > diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c > index 210ef15..c5b4c47 100644 > --- a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c > +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c > @@ -356,7 +356,7 @@ int vmw_user_lookup_handle(struct vmw_private *dev_priv, > } > > *out_surf = NULL; > - ret = vmw_user_dmabuf_lookup(tfile, handle, out_buf); > + ret = vmw_user_dmabuf_lookup(tfile, handle, out_buf, NULL); > return ret; > } > > @@ -483,7 +483,8 @@ int vmw_user_dmabuf_alloc(struct vmw_private *dev_priv, > uint32_t size, > bool shareable, > uint32_t *handle, > - struct vmw_dma_buffer **p_dma_buf) > + struct vmw_dma_buffer **p_dma_buf, > + struct ttm_base_object **p_base) > { > struct vmw_user_dma_buffer *user_bo; > struct ttm_buffer_object *tmp; > @@ -517,6 +518,10 @@ int vmw_user_dmabuf_alloc(struct vmw_private *dev_priv, > } > > *p_dma_buf = &user_bo->dma; > + if (p_base) { > + *p_base = &user_bo->prime.base; > + kref_get(&(*p_base)->refcount); > + } > *handle = user_bo->prime.base.hash.key; > > out_no_base_object: > @@ -633,6 +638,7 @@ int vmw_user_dmabuf_synccpu_ioctl(struct drm_device *dev, void *data, > struct vmw_dma_buffer *dma_buf; > struct vmw_user_dma_buffer *user_bo; > struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile; > + struct ttm_base_object *buffer_base; > int ret; > > if ((arg->flags & (drm_vmw_synccpu_read | drm_vmw_synccpu_write)) == 0 > @@ -645,7 +651,8 @@ int vmw_user_dmabuf_synccpu_ioctl(struct drm_device *dev, void *data, > > switch (arg->op) { > case drm_vmw_synccpu_grab: > - ret = vmw_user_dmabuf_lookup(tfile, arg->handle, &dma_buf); > + ret = vmw_user_dmabuf_lookup(tfile, arg->handle, &dma_buf, > + &buffer_base); > if (unlikely(ret != 0)) > return ret; > > @@ -653,6 +660,7 @@ int vmw_user_dmabuf_synccpu_ioctl(struct drm_device *dev, void *data, > dma); > ret = vmw_user_dmabuf_synccpu_grab(user_bo, tfile, arg->flags); > vmw_dmabuf_unreference(&dma_buf); > + ttm_base_object_unref(&buffer_base); > if (unlikely(ret != 0 && ret != -ERESTARTSYS && > ret != -EBUSY)) { > DRM_ERROR("Failed synccpu grab on handle 0x%08x.\n", > @@ -694,7 +702,8 @@ int vmw_dmabuf_alloc_ioctl(struct drm_device *dev, void *data, > return ret; > > ret = vmw_user_dmabuf_alloc(dev_priv, vmw_fpriv(file_priv)->tfile, > - req->size, false, &handle, &dma_buf); > + req->size, false, &handle, &dma_buf, > + NULL); > if (unlikely(ret != 0)) > goto out_no_dmabuf; > > @@ -723,7 +732,8 @@ int vmw_dmabuf_unref_ioctl(struct drm_device *dev, void *data, > } > > int vmw_user_dmabuf_lookup(struct ttm_object_file *tfile, > - uint32_t handle, struct vmw_dma_buffer **out) > + uint32_t handle, struct vmw_dma_buffer **out, > + struct ttm_base_object **p_base) > { > struct vmw_user_dma_buffer *vmw_user_bo; > struct ttm_base_object *base; > @@ -745,7 +755,10 @@ int vmw_user_dmabuf_lookup(struct ttm_object_file *tfile, > vmw_user_bo = container_of(base, struct vmw_user_dma_buffer, > prime.base); > (void)ttm_bo_reference(&vmw_user_bo->dma.base); > - ttm_base_object_unref(&base); > + if (p_base) > + *p_base = base; > + else > + ttm_base_object_unref(&base); > *out = &vmw_user_bo->dma; > > return 0; > @@ -1006,7 +1019,7 @@ int vmw_dumb_create(struct drm_file *file_priv, > > ret = vmw_user_dmabuf_alloc(dev_priv, vmw_fpriv(file_priv)->tfile, > args->size, false, &args->handle, > - &dma_buf); > + &dma_buf, NULL); > if (unlikely(ret != 0)) > goto out_no_dmabuf; > > @@ -1034,7 +1047,7 @@ int vmw_dumb_map_offset(struct drm_file *file_priv, > struct vmw_dma_buffer *out_buf; > int ret; > > - ret = vmw_user_dmabuf_lookup(tfile, handle, &out_buf); > + ret = vmw_user_dmabuf_lookup(tfile, handle, &out_buf, NULL); > if (ret != 0) > return -EINVAL; > > diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c b/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c > index 6a4584a..d2751ad 100644 > --- a/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c > +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c > @@ -470,7 +470,7 @@ int vmw_shader_define_ioctl(struct drm_device *dev, void *data, > > if (arg->buffer_handle != SVGA3D_INVALID_ID) { > ret = vmw_user_dmabuf_lookup(tfile, arg->buffer_handle, > - &buffer); > + &buffer, NULL); > if (unlikely(ret != 0)) { > DRM_ERROR("Could not find buffer for shader " > "creation.\n"); > diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c > index 4ecdbf3..9e190db6 100644 > --- a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c > +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c > @@ -43,6 +43,7 @@ struct vmw_user_surface { > struct vmw_surface srf; > uint32_t size; > struct drm_master *master; > + struct ttm_base_object *backup_base; > }; > > /** > @@ -652,6 +653,7 @@ static void vmw_user_surface_base_release(struct ttm_base_object **p_base) > struct vmw_resource *res = &user_srf->srf.res; > > *p_base = NULL; > + ttm_base_object_unref(&user_srf->backup_base); > vmw_resource_unreference(&res); > } > > @@ -846,7 +848,8 @@ int vmw_surface_define_ioctl(struct drm_device *dev, void *data, > res->backup_size, > true, > &backup_handle, > - &res->backup); > + &res->backup, > + &user_srf->backup_base); > if (unlikely(ret != 0)) { > vmw_resource_unreference(&res); > goto out_unlock; > @@ -1309,7 +1312,8 @@ int vmw_gb_surface_define_ioctl(struct drm_device *dev, void *data, > > if (req->buffer_handle != SVGA3D_INVALID_ID) { > ret = vmw_user_dmabuf_lookup(tfile, req->buffer_handle, > - &res->backup); > + &res->backup, > + &user_srf->backup_base); > } else if (req->drm_surface_flags & > drm_vmw_surface_flag_create_buffer) > ret = vmw_user_dmabuf_alloc(dev_priv, tfile, > @@ -1317,7 +1321,8 @@ int vmw_gb_surface_define_ioctl(struct drm_device *dev, void *data, > req->drm_surface_flags & > drm_vmw_surface_flag_shareable, > &backup_handle, > - &res->backup); > + &res->backup, > + &user_srf->backup_base); > > if (unlikely(ret != 0)) { > vmw_resource_unreference(&res); > -- > 1.9.1 >
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h index d26a6da..d8896ed 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h @@ -636,7 +636,8 @@ extern int vmw_user_dmabuf_alloc(struct vmw_private *dev_priv, uint32_t size, bool shareable, uint32_t *handle, - struct vmw_dma_buffer **p_dma_buf); + struct vmw_dma_buffer **p_dma_buf, + struct ttm_base_object **p_base); extern int vmw_user_dmabuf_reference(struct ttm_object_file *tfile, struct vmw_dma_buffer *dma_buf, uint32_t *handle); @@ -650,7 +651,8 @@ extern uint32_t vmw_dmabuf_validate_node(struct ttm_buffer_object *bo, uint32_t cur_validate_node); extern void vmw_dmabuf_validate_clear(struct ttm_buffer_object *bo); extern int vmw_user_dmabuf_lookup(struct ttm_object_file *tfile, - uint32_t id, struct vmw_dma_buffer **out); + uint32_t id, struct vmw_dma_buffer **out, + struct ttm_base_object **base); extern int vmw_stream_claim_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); extern int vmw_stream_unref_ioctl(struct drm_device *dev, void *data, diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c index 2711b09..01b8423 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c @@ -887,7 +887,8 @@ static int vmw_translate_mob_ptr(struct vmw_private *dev_priv, struct vmw_relocation *reloc; int ret; - ret = vmw_user_dmabuf_lookup(sw_context->fp->tfile, handle, &vmw_bo); + ret = vmw_user_dmabuf_lookup(sw_context->fp->tfile, handle, &vmw_bo, + NULL); if (unlikely(ret != 0)) { DRM_ERROR("Could not find or use MOB buffer.\n"); return -EINVAL; @@ -948,7 +949,8 @@ static int vmw_translate_guest_ptr(struct vmw_private *dev_priv, struct vmw_relocation *reloc; int ret; - ret = vmw_user_dmabuf_lookup(sw_context->fp->tfile, handle, &vmw_bo); + ret = vmw_user_dmabuf_lookup(sw_context->fp->tfile, handle, &vmw_bo, + NULL); if (unlikely(ret != 0)) { DRM_ERROR("Could not find or use GMR region.\n"); return -EINVAL; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c b/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c index 87e39f6..e189898 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c @@ -484,7 +484,7 @@ int vmw_overlay_ioctl(struct drm_device *dev, void *data, goto out_unlock; } - ret = vmw_user_dmabuf_lookup(tfile, arg->handle, &buf); + ret = vmw_user_dmabuf_lookup(tfile, arg->handle, &buf, NULL); if (ret) goto out_unlock; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c index 210ef15..c5b4c47 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c @@ -356,7 +356,7 @@ int vmw_user_lookup_handle(struct vmw_private *dev_priv, } *out_surf = NULL; - ret = vmw_user_dmabuf_lookup(tfile, handle, out_buf); + ret = vmw_user_dmabuf_lookup(tfile, handle, out_buf, NULL); return ret; } @@ -483,7 +483,8 @@ int vmw_user_dmabuf_alloc(struct vmw_private *dev_priv, uint32_t size, bool shareable, uint32_t *handle, - struct vmw_dma_buffer **p_dma_buf) + struct vmw_dma_buffer **p_dma_buf, + struct ttm_base_object **p_base) { struct vmw_user_dma_buffer *user_bo; struct ttm_buffer_object *tmp; @@ -517,6 +518,10 @@ int vmw_user_dmabuf_alloc(struct vmw_private *dev_priv, } *p_dma_buf = &user_bo->dma; + if (p_base) { + *p_base = &user_bo->prime.base; + kref_get(&(*p_base)->refcount); + } *handle = user_bo->prime.base.hash.key; out_no_base_object: @@ -633,6 +638,7 @@ int vmw_user_dmabuf_synccpu_ioctl(struct drm_device *dev, void *data, struct vmw_dma_buffer *dma_buf; struct vmw_user_dma_buffer *user_bo; struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile; + struct ttm_base_object *buffer_base; int ret; if ((arg->flags & (drm_vmw_synccpu_read | drm_vmw_synccpu_write)) == 0 @@ -645,7 +651,8 @@ int vmw_user_dmabuf_synccpu_ioctl(struct drm_device *dev, void *data, switch (arg->op) { case drm_vmw_synccpu_grab: - ret = vmw_user_dmabuf_lookup(tfile, arg->handle, &dma_buf); + ret = vmw_user_dmabuf_lookup(tfile, arg->handle, &dma_buf, + &buffer_base); if (unlikely(ret != 0)) return ret; @@ -653,6 +660,7 @@ int vmw_user_dmabuf_synccpu_ioctl(struct drm_device *dev, void *data, dma); ret = vmw_user_dmabuf_synccpu_grab(user_bo, tfile, arg->flags); vmw_dmabuf_unreference(&dma_buf); + ttm_base_object_unref(&buffer_base); if (unlikely(ret != 0 && ret != -ERESTARTSYS && ret != -EBUSY)) { DRM_ERROR("Failed synccpu grab on handle 0x%08x.\n", @@ -694,7 +702,8 @@ int vmw_dmabuf_alloc_ioctl(struct drm_device *dev, void *data, return ret; ret = vmw_user_dmabuf_alloc(dev_priv, vmw_fpriv(file_priv)->tfile, - req->size, false, &handle, &dma_buf); + req->size, false, &handle, &dma_buf, + NULL); if (unlikely(ret != 0)) goto out_no_dmabuf; @@ -723,7 +732,8 @@ int vmw_dmabuf_unref_ioctl(struct drm_device *dev, void *data, } int vmw_user_dmabuf_lookup(struct ttm_object_file *tfile, - uint32_t handle, struct vmw_dma_buffer **out) + uint32_t handle, struct vmw_dma_buffer **out, + struct ttm_base_object **p_base) { struct vmw_user_dma_buffer *vmw_user_bo; struct ttm_base_object *base; @@ -745,7 +755,10 @@ int vmw_user_dmabuf_lookup(struct ttm_object_file *tfile, vmw_user_bo = container_of(base, struct vmw_user_dma_buffer, prime.base); (void)ttm_bo_reference(&vmw_user_bo->dma.base); - ttm_base_object_unref(&base); + if (p_base) + *p_base = base; + else + ttm_base_object_unref(&base); *out = &vmw_user_bo->dma; return 0; @@ -1006,7 +1019,7 @@ int vmw_dumb_create(struct drm_file *file_priv, ret = vmw_user_dmabuf_alloc(dev_priv, vmw_fpriv(file_priv)->tfile, args->size, false, &args->handle, - &dma_buf); + &dma_buf, NULL); if (unlikely(ret != 0)) goto out_no_dmabuf; @@ -1034,7 +1047,7 @@ int vmw_dumb_map_offset(struct drm_file *file_priv, struct vmw_dma_buffer *out_buf; int ret; - ret = vmw_user_dmabuf_lookup(tfile, handle, &out_buf); + ret = vmw_user_dmabuf_lookup(tfile, handle, &out_buf, NULL); if (ret != 0) return -EINVAL; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c b/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c index 6a4584a..d2751ad 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c @@ -470,7 +470,7 @@ int vmw_shader_define_ioctl(struct drm_device *dev, void *data, if (arg->buffer_handle != SVGA3D_INVALID_ID) { ret = vmw_user_dmabuf_lookup(tfile, arg->buffer_handle, - &buffer); + &buffer, NULL); if (unlikely(ret != 0)) { DRM_ERROR("Could not find buffer for shader " "creation.\n"); diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c index 4ecdbf3..9e190db6 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c @@ -43,6 +43,7 @@ struct vmw_user_surface { struct vmw_surface srf; uint32_t size; struct drm_master *master; + struct ttm_base_object *backup_base; }; /** @@ -652,6 +653,7 @@ static void vmw_user_surface_base_release(struct ttm_base_object **p_base) struct vmw_resource *res = &user_srf->srf.res; *p_base = NULL; + ttm_base_object_unref(&user_srf->backup_base); vmw_resource_unreference(&res); } @@ -846,7 +848,8 @@ int vmw_surface_define_ioctl(struct drm_device *dev, void *data, res->backup_size, true, &backup_handle, - &res->backup); + &res->backup, + &user_srf->backup_base); if (unlikely(ret != 0)) { vmw_resource_unreference(&res); goto out_unlock; @@ -1309,7 +1312,8 @@ int vmw_gb_surface_define_ioctl(struct drm_device *dev, void *data, if (req->buffer_handle != SVGA3D_INVALID_ID) { ret = vmw_user_dmabuf_lookup(tfile, req->buffer_handle, - &res->backup); + &res->backup, + &user_srf->backup_base); } else if (req->drm_surface_flags & drm_vmw_surface_flag_create_buffer) ret = vmw_user_dmabuf_alloc(dev_priv, tfile, @@ -1317,7 +1321,8 @@ int vmw_gb_surface_define_ioctl(struct drm_device *dev, void *data, req->drm_surface_flags & drm_vmw_surface_flag_shareable, &backup_handle, - &res->backup); + &res->backup, + &user_srf->backup_base); if (unlikely(ret != 0)) { vmw_resource_unreference(&res);