Skip to content

Commit

Permalink
Merge branch 'vmwgfx-fixes-4.16' of git://people.freedesktop.org/~tho…
Browse files Browse the repository at this point in the history
…mash/linux into drm-fixes

Two vmwgfx fixes for 4.16. Both cc'd stable.

* 'vmwgfx-fixes-4.16' of git://people.freedesktop.org/~thomash/linux:
  drm/vmwgfx: Fix a destoy-while-held mutex problem.
  drm/vmwgfx: Fix black screen and device errors when running without fbdev
  • Loading branch information
Dave Airlie committed Mar 22, 2018
2 parents cec1b94 + 73a8825 commit 096c49e
Show file tree
Hide file tree
Showing 6 changed files with 59 additions and 17 deletions.
13 changes: 13 additions & 0 deletions drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
Original file line number Diff line number Diff line change
Expand Up @@ -1337,6 +1337,19 @@ static void __vmw_svga_disable(struct vmw_private *dev_priv)
*/
void vmw_svga_disable(struct vmw_private *dev_priv)
{
/*
* Disabling SVGA will turn off device modesetting capabilities, so
* notify KMS about that so that it doesn't cache atomic state that
* isn't valid anymore, for example crtcs turned on.
* Strictly we'd want to do this under the SVGA lock (or an SVGA mutex),
* but vmw_kms_lost_device() takes the reservation sem and thus we'll
* end up with lock order reversal. Thus, a master may actually perform
* a new modeset just after we call vmw_kms_lost_device() and race with
* vmw_svga_disable(), but that should at worst cause atomic KMS state
* to be inconsistent with the device, causing modesetting problems.
*
*/
vmw_kms_lost_device(dev_priv->dev);
ttm_write_lock(&dev_priv->reservation_sem, false);
spin_lock(&dev_priv->svga_lock);
if (dev_priv->bdev.man[TTM_PL_VRAM].use_type) {
Expand Down
1 change: 1 addition & 0 deletions drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -938,6 +938,7 @@ int vmw_kms_present(struct vmw_private *dev_priv,
int vmw_kms_update_layout_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv);
void vmw_kms_legacy_hotspot_clear(struct vmw_private *dev_priv);
void vmw_kms_lost_device(struct drm_device *dev);

int vmw_dumb_create(struct drm_file *file_priv,
struct drm_device *dev,
Expand Down
39 changes: 30 additions & 9 deletions drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_rect.h>


/* Might need a hrtimer here? */
#define VMWGFX_PRESENT_RATE ((HZ / 60 > 0) ? HZ / 60 : 1)

Expand Down Expand Up @@ -2517,9 +2516,12 @@ void vmw_kms_helper_buffer_finish(struct vmw_private *dev_priv,
* Helper to be used if an error forces the caller to undo the actions of
* vmw_kms_helper_resource_prepare.
*/
void vmw_kms_helper_resource_revert(struct vmw_resource *res)
void vmw_kms_helper_resource_revert(struct vmw_validation_ctx *ctx)
{
vmw_kms_helper_buffer_revert(res->backup);
struct vmw_resource *res = ctx->res;

vmw_kms_helper_buffer_revert(ctx->buf);
vmw_dmabuf_unreference(&ctx->buf);
vmw_resource_unreserve(res, false, NULL, 0);
mutex_unlock(&res->dev_priv->cmdbuf_mutex);
}
Expand All @@ -2536,10 +2538,14 @@ void vmw_kms_helper_resource_revert(struct vmw_resource *res)
* interrupted by a signal.
*/
int vmw_kms_helper_resource_prepare(struct vmw_resource *res,
bool interruptible)
bool interruptible,
struct vmw_validation_ctx *ctx)
{
int ret = 0;

ctx->buf = NULL;
ctx->res = res;

if (interruptible)
ret = mutex_lock_interruptible(&res->dev_priv->cmdbuf_mutex);
else
Expand All @@ -2558,14 +2564,16 @@ int vmw_kms_helper_resource_prepare(struct vmw_resource *res,
res->dev_priv->has_mob);
if (ret)
goto out_unreserve;

ctx->buf = vmw_dmabuf_reference(res->backup);
}
ret = vmw_resource_validate(res);
if (ret)
goto out_revert;
return 0;

out_revert:
vmw_kms_helper_buffer_revert(res->backup);
vmw_kms_helper_buffer_revert(ctx->buf);
out_unreserve:
vmw_resource_unreserve(res, false, NULL, 0);
out_unlock:
Expand All @@ -2581,11 +2589,13 @@ int vmw_kms_helper_resource_prepare(struct vmw_resource *res,
* @out_fence: Optional pointer to a fence pointer. If non-NULL, a
* ref-counted fence pointer is returned here.
*/
void vmw_kms_helper_resource_finish(struct vmw_resource *res,
struct vmw_fence_obj **out_fence)
void vmw_kms_helper_resource_finish(struct vmw_validation_ctx *ctx,
struct vmw_fence_obj **out_fence)
{
if (res->backup || out_fence)
vmw_kms_helper_buffer_finish(res->dev_priv, NULL, res->backup,
struct vmw_resource *res = ctx->res;

if (ctx->buf || out_fence)
vmw_kms_helper_buffer_finish(res->dev_priv, NULL, ctx->buf,
out_fence, NULL);

vmw_resource_unreserve(res, false, NULL, 0);
Expand Down Expand Up @@ -2851,3 +2861,14 @@ int vmw_kms_set_config(struct drm_mode_set *set,

return drm_atomic_helper_set_config(set, ctx);
}


/**
* vmw_kms_lost_device - Notify kms that modesetting capabilities will be lost
*
* @dev: Pointer to the drm device
*/
void vmw_kms_lost_device(struct drm_device *dev)
{
drm_atomic_helper_shutdown(dev);
}
13 changes: 9 additions & 4 deletions drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,11 @@ struct vmw_display_unit {
int set_gui_y;
};

struct vmw_validation_ctx {
struct vmw_resource *res;
struct vmw_dma_buffer *buf;
};

#define vmw_crtc_to_du(x) \
container_of(x, struct vmw_display_unit, crtc)
#define vmw_connector_to_du(x) \
Expand Down Expand Up @@ -296,9 +301,10 @@ void vmw_kms_helper_buffer_finish(struct vmw_private *dev_priv,
struct drm_vmw_fence_rep __user *
user_fence_rep);
int vmw_kms_helper_resource_prepare(struct vmw_resource *res,
bool interruptible);
void vmw_kms_helper_resource_revert(struct vmw_resource *res);
void vmw_kms_helper_resource_finish(struct vmw_resource *res,
bool interruptible,
struct vmw_validation_ctx *ctx);
void vmw_kms_helper_resource_revert(struct vmw_validation_ctx *ctx);
void vmw_kms_helper_resource_finish(struct vmw_validation_ctx *ctx,
struct vmw_fence_obj **out_fence);
int vmw_kms_readback(struct vmw_private *dev_priv,
struct drm_file *file_priv,
Expand Down Expand Up @@ -439,5 +445,4 @@ int vmw_kms_stdu_dma(struct vmw_private *dev_priv,

int vmw_kms_set_config(struct drm_mode_set *set,
struct drm_modeset_acquire_ctx *ctx);

#endif
5 changes: 3 additions & 2 deletions drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
Original file line number Diff line number Diff line change
Expand Up @@ -909,12 +909,13 @@ int vmw_kms_sou_do_surface_dirty(struct vmw_private *dev_priv,
struct vmw_framebuffer_surface *vfbs =
container_of(framebuffer, typeof(*vfbs), base);
struct vmw_kms_sou_surface_dirty sdirty;
struct vmw_validation_ctx ctx;
int ret;

if (!srf)
srf = &vfbs->surface->res;

ret = vmw_kms_helper_resource_prepare(srf, true);
ret = vmw_kms_helper_resource_prepare(srf, true, &ctx);
if (ret)
return ret;

Expand All @@ -933,7 +934,7 @@ int vmw_kms_sou_do_surface_dirty(struct vmw_private *dev_priv,
ret = vmw_kms_helper_dirty(dev_priv, framebuffer, clips, vclips,
dest_x, dest_y, num_clips, inc,
&sdirty.base);
vmw_kms_helper_resource_finish(srf, out_fence);
vmw_kms_helper_resource_finish(&ctx, out_fence);

return ret;
}
Expand Down
5 changes: 3 additions & 2 deletions drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
Original file line number Diff line number Diff line change
Expand Up @@ -980,12 +980,13 @@ int vmw_kms_stdu_surface_dirty(struct vmw_private *dev_priv,
struct vmw_framebuffer_surface *vfbs =
container_of(framebuffer, typeof(*vfbs), base);
struct vmw_stdu_dirty sdirty;
struct vmw_validation_ctx ctx;
int ret;

if (!srf)
srf = &vfbs->surface->res;

ret = vmw_kms_helper_resource_prepare(srf, true);
ret = vmw_kms_helper_resource_prepare(srf, true, &ctx);
if (ret)
return ret;

Expand All @@ -1008,7 +1009,7 @@ int vmw_kms_stdu_surface_dirty(struct vmw_private *dev_priv,
dest_x, dest_y, num_clips, inc,
&sdirty.base);
out_finish:
vmw_kms_helper_resource_finish(srf, out_fence);
vmw_kms_helper_resource_finish(&ctx, out_fence);

return ret;
}
Expand Down

0 comments on commit 096c49e

Please sign in to comment.