Commit 096c49ec authored by Dave Airlie's avatar Dave Airlie

Merge branch 'vmwgfx-fixes-4.16' of git://people.freedesktop.org/~thomash/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
parents cec1b948 73a88250
...@@ -1337,6 +1337,19 @@ static void __vmw_svga_disable(struct vmw_private *dev_priv) ...@@ -1337,6 +1337,19 @@ static void __vmw_svga_disable(struct vmw_private *dev_priv)
*/ */
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); ttm_write_lock(&dev_priv->reservation_sem, false);
spin_lock(&dev_priv->svga_lock); spin_lock(&dev_priv->svga_lock);
if (dev_priv->bdev.man[TTM_PL_VRAM].use_type) { if (dev_priv->bdev.man[TTM_PL_VRAM].use_type) {
......
...@@ -938,6 +938,7 @@ int vmw_kms_present(struct vmw_private *dev_priv, ...@@ -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, int vmw_kms_update_layout_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv); struct drm_file *file_priv);
void vmw_kms_legacy_hotspot_clear(struct vmw_private *dev_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, int vmw_dumb_create(struct drm_file *file_priv,
struct drm_device *dev, struct drm_device *dev,
......
...@@ -31,7 +31,6 @@ ...@@ -31,7 +31,6 @@
#include <drm/drm_atomic_helper.h> #include <drm/drm_atomic_helper.h>
#include <drm/drm_rect.h> #include <drm/drm_rect.h>
/* Might need a hrtimer here? */ /* Might need a hrtimer here? */
#define VMWGFX_PRESENT_RATE ((HZ / 60 > 0) ? HZ / 60 : 1) #define VMWGFX_PRESENT_RATE ((HZ / 60 > 0) ? HZ / 60 : 1)
...@@ -2517,9 +2516,12 @@ void vmw_kms_helper_buffer_finish(struct vmw_private *dev_priv, ...@@ -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 * Helper to be used if an error forces the caller to undo the actions of
* vmw_kms_helper_resource_prepare. * 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); vmw_resource_unreserve(res, false, NULL, 0);
mutex_unlock(&res->dev_priv->cmdbuf_mutex); mutex_unlock(&res->dev_priv->cmdbuf_mutex);
} }
...@@ -2536,10 +2538,14 @@ void vmw_kms_helper_resource_revert(struct vmw_resource *res) ...@@ -2536,10 +2538,14 @@ void vmw_kms_helper_resource_revert(struct vmw_resource *res)
* interrupted by a signal. * interrupted by a signal.
*/ */
int vmw_kms_helper_resource_prepare(struct vmw_resource *res, int vmw_kms_helper_resource_prepare(struct vmw_resource *res,
bool interruptible) bool interruptible,
struct vmw_validation_ctx *ctx)
{ {
int ret = 0; int ret = 0;
ctx->buf = NULL;
ctx->res = res;
if (interruptible) if (interruptible)
ret = mutex_lock_interruptible(&res->dev_priv->cmdbuf_mutex); ret = mutex_lock_interruptible(&res->dev_priv->cmdbuf_mutex);
else else
...@@ -2558,6 +2564,8 @@ int vmw_kms_helper_resource_prepare(struct vmw_resource *res, ...@@ -2558,6 +2564,8 @@ int vmw_kms_helper_resource_prepare(struct vmw_resource *res,
res->dev_priv->has_mob); res->dev_priv->has_mob);
if (ret) if (ret)
goto out_unreserve; goto out_unreserve;
ctx->buf = vmw_dmabuf_reference(res->backup);
} }
ret = vmw_resource_validate(res); ret = vmw_resource_validate(res);
if (ret) if (ret)
...@@ -2565,7 +2573,7 @@ int vmw_kms_helper_resource_prepare(struct vmw_resource *res, ...@@ -2565,7 +2573,7 @@ int vmw_kms_helper_resource_prepare(struct vmw_resource *res,
return 0; return 0;
out_revert: out_revert:
vmw_kms_helper_buffer_revert(res->backup); vmw_kms_helper_buffer_revert(ctx->buf);
out_unreserve: out_unreserve:
vmw_resource_unreserve(res, false, NULL, 0); vmw_resource_unreserve(res, false, NULL, 0);
out_unlock: out_unlock:
...@@ -2581,11 +2589,13 @@ int vmw_kms_helper_resource_prepare(struct vmw_resource *res, ...@@ -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 * @out_fence: Optional pointer to a fence pointer. If non-NULL, a
* ref-counted fence pointer is returned here. * ref-counted fence pointer is returned here.
*/ */
void vmw_kms_helper_resource_finish(struct vmw_resource *res, void vmw_kms_helper_resource_finish(struct vmw_validation_ctx *ctx,
struct vmw_fence_obj **out_fence) struct vmw_fence_obj **out_fence)
{ {
if (res->backup || out_fence) struct vmw_resource *res = ctx->res;
vmw_kms_helper_buffer_finish(res->dev_priv, NULL, res->backup,
if (ctx->buf || out_fence)
vmw_kms_helper_buffer_finish(res->dev_priv, NULL, ctx->buf,
out_fence, NULL); out_fence, NULL);
vmw_resource_unreserve(res, false, NULL, 0); vmw_resource_unreserve(res, false, NULL, 0);
...@@ -2851,3 +2861,14 @@ int vmw_kms_set_config(struct drm_mode_set *set, ...@@ -2851,3 +2861,14 @@ int vmw_kms_set_config(struct drm_mode_set *set,
return drm_atomic_helper_set_config(set, ctx); 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);
}
...@@ -240,6 +240,11 @@ struct vmw_display_unit { ...@@ -240,6 +240,11 @@ struct vmw_display_unit {
int set_gui_y; int set_gui_y;
}; };
struct vmw_validation_ctx {
struct vmw_resource *res;
struct vmw_dma_buffer *buf;
};
#define vmw_crtc_to_du(x) \ #define vmw_crtc_to_du(x) \
container_of(x, struct vmw_display_unit, crtc) container_of(x, struct vmw_display_unit, crtc)
#define vmw_connector_to_du(x) \ #define vmw_connector_to_du(x) \
...@@ -296,9 +301,10 @@ void vmw_kms_helper_buffer_finish(struct vmw_private *dev_priv, ...@@ -296,9 +301,10 @@ void vmw_kms_helper_buffer_finish(struct vmw_private *dev_priv,
struct drm_vmw_fence_rep __user * struct drm_vmw_fence_rep __user *
user_fence_rep); user_fence_rep);
int vmw_kms_helper_resource_prepare(struct vmw_resource *res, int vmw_kms_helper_resource_prepare(struct vmw_resource *res,
bool interruptible); bool interruptible,
void vmw_kms_helper_resource_revert(struct vmw_resource *res); struct vmw_validation_ctx *ctx);
void vmw_kms_helper_resource_finish(struct vmw_resource *res, 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); struct vmw_fence_obj **out_fence);
int vmw_kms_readback(struct vmw_private *dev_priv, int vmw_kms_readback(struct vmw_private *dev_priv,
struct drm_file *file_priv, struct drm_file *file_priv,
...@@ -439,5 +445,4 @@ int vmw_kms_stdu_dma(struct vmw_private *dev_priv, ...@@ -439,5 +445,4 @@ int vmw_kms_stdu_dma(struct vmw_private *dev_priv,
int vmw_kms_set_config(struct drm_mode_set *set, int vmw_kms_set_config(struct drm_mode_set *set,
struct drm_modeset_acquire_ctx *ctx); struct drm_modeset_acquire_ctx *ctx);
#endif #endif
...@@ -909,12 +909,13 @@ int vmw_kms_sou_do_surface_dirty(struct vmw_private *dev_priv, ...@@ -909,12 +909,13 @@ int vmw_kms_sou_do_surface_dirty(struct vmw_private *dev_priv,
struct vmw_framebuffer_surface *vfbs = struct vmw_framebuffer_surface *vfbs =
container_of(framebuffer, typeof(*vfbs), base); container_of(framebuffer, typeof(*vfbs), base);
struct vmw_kms_sou_surface_dirty sdirty; struct vmw_kms_sou_surface_dirty sdirty;
struct vmw_validation_ctx ctx;
int ret; int ret;
if (!srf) if (!srf)
srf = &vfbs->surface->res; srf = &vfbs->surface->res;
ret = vmw_kms_helper_resource_prepare(srf, true); ret = vmw_kms_helper_resource_prepare(srf, true, &ctx);
if (ret) if (ret)
return ret; return ret;
...@@ -933,7 +934,7 @@ int vmw_kms_sou_do_surface_dirty(struct vmw_private *dev_priv, ...@@ -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, ret = vmw_kms_helper_dirty(dev_priv, framebuffer, clips, vclips,
dest_x, dest_y, num_clips, inc, dest_x, dest_y, num_clips, inc,
&sdirty.base); &sdirty.base);
vmw_kms_helper_resource_finish(srf, out_fence); vmw_kms_helper_resource_finish(&ctx, out_fence);
return ret; return ret;
} }
......
...@@ -980,12 +980,13 @@ int vmw_kms_stdu_surface_dirty(struct vmw_private *dev_priv, ...@@ -980,12 +980,13 @@ int vmw_kms_stdu_surface_dirty(struct vmw_private *dev_priv,
struct vmw_framebuffer_surface *vfbs = struct vmw_framebuffer_surface *vfbs =
container_of(framebuffer, typeof(*vfbs), base); container_of(framebuffer, typeof(*vfbs), base);
struct vmw_stdu_dirty sdirty; struct vmw_stdu_dirty sdirty;
struct vmw_validation_ctx ctx;
int ret; int ret;
if (!srf) if (!srf)
srf = &vfbs->surface->res; srf = &vfbs->surface->res;
ret = vmw_kms_helper_resource_prepare(srf, true); ret = vmw_kms_helper_resource_prepare(srf, true, &ctx);
if (ret) if (ret)
return ret; return ret;
...@@ -1008,7 +1009,7 @@ int vmw_kms_stdu_surface_dirty(struct vmw_private *dev_priv, ...@@ -1008,7 +1009,7 @@ int vmw_kms_stdu_surface_dirty(struct vmw_private *dev_priv,
dest_x, dest_y, num_clips, inc, dest_x, dest_y, num_clips, inc,
&sdirty.base); &sdirty.base);
out_finish: out_finish:
vmw_kms_helper_resource_finish(srf, out_fence); vmw_kms_helper_resource_finish(&ctx, out_fence);
return ret; return ret;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment