aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c')
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c191
1 files changed, 101 insertions, 90 deletions
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c b/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c
index 14399ee..f1a52f9 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c
@@ -87,6 +87,48 @@ static inline void fill_flush(struct vmw_escape_video_flush *cmd,
}
/**
+ * Pin or unpin a buffer in vram.
+ *
+ * @dev_priv: Driver private.
+ * @buf: DMA buffer to pin or unpin.
+ * @pin: Pin buffer in vram if true.
+ * @interruptible: Use interruptible wait.
+ *
+ * Takes the current masters ttm lock in read.
+ *
+ * Returns
+ * -ERESTARTSYS if interrupted by a signal.
+ */
+static int vmw_dmabuf_pin_in_vram(struct vmw_private *dev_priv,
+ struct vmw_dma_buffer *buf,
+ bool pin, bool interruptible)
+{
+ struct ttm_buffer_object *bo = &buf->base;
+ struct ttm_placement *overlay_placement = &vmw_vram_placement;
+ int ret;
+
+ ret = ttm_read_lock(&dev_priv->active_master->lock, interruptible);
+ if (unlikely(ret != 0))
+ return ret;
+
+ ret = ttm_bo_reserve(bo, interruptible, false, false, 0);
+ if (unlikely(ret != 0))
+ goto err;
+
+ if (pin)
+ overlay_placement = &vmw_vram_ne_placement;
+
+ ret = ttm_bo_validate(bo, overlay_placement, interruptible, false, false);
+
+ ttm_bo_unreserve(bo);
+
+err:
+ ttm_read_unlock(&dev_priv->active_master->lock);
+
+ return ret;
+}
+
+/**
* Send put command to hw.
*
* Returns
@@ -97,80 +139,68 @@ static int vmw_overlay_send_put(struct vmw_private *dev_priv,
struct drm_vmw_control_stream_arg *arg,
bool interruptible)
{
- struct vmw_escape_video_flush *flush;
- size_t fifo_size;
- bool have_so = dev_priv->sou_priv ? true : false;
- int i, num_items;
- SVGAGuestPtr ptr;
-
struct {
struct vmw_escape_header escape;
struct {
- uint32_t cmdType;
- uint32_t streamId;
- } header;
+ struct {
+ uint32_t cmdType;
+ uint32_t streamId;
+ } header;
+ struct {
+ uint32_t registerId;
+ uint32_t value;
+ } items[SVGA_VIDEO_PITCH_3 + 1];
+ } body;
+ struct vmw_escape_video_flush flush;
} *cmds;
- struct {
- uint32_t registerId;
- uint32_t value;
- } *items;
-
- /* defines are a index needs + 1 */
- if (have_so)
- num_items = SVGA_VIDEO_DST_SCREEN_ID + 1;
- else
- num_items = SVGA_VIDEO_PITCH_3 + 1;
-
- fifo_size = sizeof(*cmds) + sizeof(*flush) + sizeof(*items) * num_items;
+ uint32_t offset;
+ int i, ret;
- cmds = vmw_fifo_reserve(dev_priv, fifo_size);
- /* hardware has hung, can't do anything here */
- if (!cmds)
- return -ENOMEM;
+ for (;;) {
+ cmds = vmw_fifo_reserve(dev_priv, sizeof(*cmds));
+ if (cmds)
+ break;
- items = (typeof(items))&cmds[1];
- flush = (struct vmw_escape_video_flush *)&items[num_items];
-
- /* the size is header + number of items */
- fill_escape(&cmds->escape, sizeof(*items) * (num_items + 1));
-
- cmds->header.cmdType = SVGA_ESCAPE_VMWARE_VIDEO_SET_REGS;
- cmds->header.streamId = arg->stream_id;
-
- /* the IDs are neatly numbered */
- for (i = 0; i < num_items; i++)
- items[i].registerId = i;
-
- vmw_bo_get_guest_ptr(&buf->base, &ptr);
- ptr.offset += arg->offset;
-
- items[SVGA_VIDEO_ENABLED].value = true;
- items[SVGA_VIDEO_FLAGS].value = arg->flags;
- items[SVGA_VIDEO_DATA_OFFSET].value = ptr.offset;
- items[SVGA_VIDEO_FORMAT].value = arg->format;
- items[SVGA_VIDEO_COLORKEY].value = arg->color_key;
- items[SVGA_VIDEO_SIZE].value = arg->size;
- items[SVGA_VIDEO_WIDTH].value = arg->width;
- items[SVGA_VIDEO_HEIGHT].value = arg->height;
- items[SVGA_VIDEO_SRC_X].value = arg->src.x;
- items[SVGA_VIDEO_SRC_Y].value = arg->src.y;
- items[SVGA_VIDEO_SRC_WIDTH].value = arg->src.w;
- items[SVGA_VIDEO_SRC_HEIGHT].value = arg->src.h;
- items[SVGA_VIDEO_DST_X].value = arg->dst.x;
- items[SVGA_VIDEO_DST_Y].value = arg->dst.y;
- items[SVGA_VIDEO_DST_WIDTH].value = arg->dst.w;
- items[SVGA_VIDEO_DST_HEIGHT].value = arg->dst.h;
- items[SVGA_VIDEO_PITCH_1].value = arg->pitch[0];
- items[SVGA_VIDEO_PITCH_2].value = arg->pitch[1];
- items[SVGA_VIDEO_PITCH_3].value = arg->pitch[2];
- if (have_so) {
- items[SVGA_VIDEO_DATA_GMRID].value = ptr.gmrId;
- items[SVGA_VIDEO_DST_SCREEN_ID].value = SVGA_ID_INVALID;
+ ret = vmw_fallback_wait(dev_priv, false, true, 0,
+ interruptible, 3*HZ);
+ if (interruptible && ret == -ERESTARTSYS)
+ return ret;
+ else
+ BUG_ON(ret != 0);
}
- fill_flush(flush, arg->stream_id);
+ fill_escape(&cmds->escape, sizeof(cmds->body));
+ cmds->body.header.cmdType = SVGA_ESCAPE_VMWARE_VIDEO_SET_REGS;
+ cmds->body.header.streamId = arg->stream_id;
+
+ for (i = 0; i <= SVGA_VIDEO_PITCH_3; i++)
+ cmds->body.items[i].registerId = i;
+
+ offset = buf->base.offset + arg->offset;
+
+ cmds->body.items[SVGA_VIDEO_ENABLED].value = true;
+ cmds->body.items[SVGA_VIDEO_FLAGS].value = arg->flags;
+ cmds->body.items[SVGA_VIDEO_DATA_OFFSET].value = offset;
+ cmds->body.items[SVGA_VIDEO_FORMAT].value = arg->format;
+ cmds->body.items[SVGA_VIDEO_COLORKEY].value = arg->color_key;
+ cmds->body.items[SVGA_VIDEO_SIZE].value = arg->size;
+ cmds->body.items[SVGA_VIDEO_WIDTH].value = arg->width;
+ cmds->body.items[SVGA_VIDEO_HEIGHT].value = arg->height;
+ cmds->body.items[SVGA_VIDEO_SRC_X].value = arg->src.x;
+ cmds->body.items[SVGA_VIDEO_SRC_Y].value = arg->src.y;
+ cmds->body.items[SVGA_VIDEO_SRC_WIDTH].value = arg->src.w;
+ cmds->body.items[SVGA_VIDEO_SRC_HEIGHT].value = arg->src.h;
+ cmds->body.items[SVGA_VIDEO_DST_X].value = arg->dst.x;
+ cmds->body.items[SVGA_VIDEO_DST_Y].value = arg->dst.y;
+ cmds->body.items[SVGA_VIDEO_DST_WIDTH].value = arg->dst.w;
+ cmds->body.items[SVGA_VIDEO_DST_HEIGHT].value = arg->dst.h;
+ cmds->body.items[SVGA_VIDEO_PITCH_1].value = arg->pitch[0];
+ cmds->body.items[SVGA_VIDEO_PITCH_2].value = arg->pitch[1];
+ cmds->body.items[SVGA_VIDEO_PITCH_3].value = arg->pitch[2];
+
+ fill_flush(&cmds->flush, arg->stream_id);
- vmw_fifo_commit(dev_priv, fifo_size);
+ vmw_fifo_commit(dev_priv, sizeof(*cmds));
return 0;
}
@@ -218,25 +248,6 @@ static int vmw_overlay_send_stop(struct vmw_private *dev_priv,
}
/**
- * Move a buffer to vram or gmr if @pin is set, else unpin the buffer.
- *
- * With the introduction of screen objects buffers could now be
- * used with GMRs instead of being locked to vram.
- */
-static int vmw_overlay_move_buffer(struct vmw_private *dev_priv,
- struct vmw_dma_buffer *buf,
- bool pin, bool inter)
-{
- if (!pin)
- return vmw_dmabuf_unpin(dev_priv, buf, inter);
-
- if (!dev_priv->sou_priv)
- return vmw_dmabuf_to_vram(dev_priv, buf, true, inter);
-
- return vmw_dmabuf_to_vram_or_gmr(dev_priv, buf, true, inter);
-}
-
-/**
* Stop or pause a stream.
*
* If the stream is paused the no evict flag is removed from the buffer
@@ -268,8 +279,8 @@ static int vmw_overlay_stop(struct vmw_private *dev_priv,
return ret;
/* We just remove the NO_EVICT flag so no -ENOMEM */
- ret = vmw_overlay_move_buffer(dev_priv, stream->buf, false,
- interruptible);
+ ret = vmw_dmabuf_pin_in_vram(dev_priv, stream->buf, false,
+ interruptible);
if (interruptible && ret == -ERESTARTSYS)
return ret;
else
@@ -331,7 +342,7 @@ static int vmw_overlay_update_stream(struct vmw_private *dev_priv,
/* We don't start the old stream if we are interrupted.
* Might return -ENOMEM if it can't fit the buffer in vram.
*/
- ret = vmw_overlay_move_buffer(dev_priv, buf, true, interruptible);
+ ret = vmw_dmabuf_pin_in_vram(dev_priv, buf, true, interruptible);
if (ret)
return ret;
@@ -340,8 +351,7 @@ static int vmw_overlay_update_stream(struct vmw_private *dev_priv,
/* This one needs to happen no matter what. We only remove
* the NO_EVICT flag so this is safe from -ENOMEM.
*/
- BUG_ON(vmw_overlay_move_buffer(dev_priv, buf, false, false)
- != 0);
+ BUG_ON(vmw_dmabuf_pin_in_vram(dev_priv, buf, false, false) != 0);
return ret;
}
@@ -575,10 +585,11 @@ int vmw_overlay_init(struct vmw_private *dev_priv)
return -ENOSYS;
}
- overlay = kzalloc(sizeof(*overlay), GFP_KERNEL);
+ overlay = kmalloc(sizeof(*overlay), GFP_KERNEL);
if (!overlay)
return -ENOMEM;
+ memset(overlay, 0, sizeof(*overlay));
mutex_init(&overlay->mutex);
for (i = 0; i < VMW_MAX_NUM_STREAMS; i++) {
overlay->stream[i].buf = NULL;