コード例 #1
0
ファイル: vmwgfx_overlay.c プロジェクト: EvanHa/rbp
/**
 * Send stop command to hw.
 *
 * Returns
 * -ERESTARTSYS if interrupted by a signal.
 */
static int vmw_overlay_send_stop(struct vmw_private *dev_priv,
				 uint32_t stream_id,
				 bool interruptible)
{
	struct {
		struct vmw_escape_header escape;
		SVGAEscapeVideoSetRegs body;
		struct vmw_escape_video_flush flush;
	} *cmds;
	int ret;

	for (;;) {
		cmds = vmw_fifo_reserve(dev_priv, sizeof(*cmds));
		if (cmds)
			break;

		ret = vmw_fallback_wait(dev_priv, false, true, 0,
					interruptible, 3*HZ);
		if (interruptible && ret == -ERESTARTSYS)
			return ret;
		else
			BUG_ON(ret != 0);
	}

	fill_escape(&cmds->escape, sizeof(cmds->body));
	cmds->body.header.cmdType = SVGA_ESCAPE_VMWARE_VIDEO_SET_REGS;
	cmds->body.header.streamId = stream_id;
	cmds->body.items[0].registerId = SVGA_VIDEO_ENABLED;
	cmds->body.items[0].value = false;
	fill_flush(&cmds->flush, stream_id);

	vmw_fifo_commit(dev_priv, sizeof(*cmds));

	return 0;
}
コード例 #2
0
int vmw_wait_seqno(struct vmw_private *dev_priv,
		      bool lazy, uint32_t seqno,
		      bool interruptible, unsigned long timeout)
{
	long ret;
	struct vmw_fifo_state *fifo = &dev_priv->fifo;

	if (likely(dev_priv->last_read_seqno - seqno < VMW_FENCE_WRAP))
		return 0;

	if (likely(vmw_seqno_passed(dev_priv, seqno)))
		return 0;

	vmw_fifo_ping_host(dev_priv, SVGA_SYNC_GENERIC);

	if (!(fifo->capabilities & SVGA_FIFO_CAP_FENCE))
		return vmw_fallback_wait(dev_priv, lazy, true, seqno,
					 interruptible, timeout);

	if (!(dev_priv->capabilities & SVGA_CAP_IRQMASK))
		return vmw_fallback_wait(dev_priv, lazy, false, seqno,
					 interruptible, timeout);

	vmw_seqno_waiter_add(dev_priv);

	if (interruptible)
		ret = wait_event_interruptible_timeout
		    (dev_priv->fence_queue,
		     vmw_seqno_passed(dev_priv, seqno),
		     timeout);
	else
		ret = wait_event_timeout
		    (dev_priv->fence_queue,
		     vmw_seqno_passed(dev_priv, seqno),
		     timeout);

	vmw_seqno_waiter_remove(dev_priv);

	if (unlikely(ret == 0))
		ret = -EBUSY;
	else if (likely(ret > 0))
		ret = 0;

	return ret;
}
コード例 #3
0
ファイル: vmwgfx_scrn.c プロジェクト: Astralix/mainline-dss11
/**
 * Send the fifo command to destroy a screen.
 */
static int vmw_sou_fifo_destroy(struct vmw_private *dev_priv,
				struct vmw_screen_object_unit *sou)
{
	size_t fifo_size;
	int ret;

	struct {
		struct {
			uint32_t cmdType;
		} header;
		SVGAFifoCmdDestroyScreen body;
	} *cmd;

	/* no need to do anything */
	if (unlikely(!sou->defined))
		return 0;

	fifo_size = sizeof(*cmd);
	cmd = vmw_fifo_reserve(dev_priv, fifo_size);
	/* the hardware has hung, nothing we can do about it here */
	if (unlikely(cmd == NULL)) {
		DRM_ERROR("Fifo reserve failed.\n");
		return -ENOMEM;
	}

	memset(cmd, 0, fifo_size);
	cmd->header.cmdType = SVGA_CMD_DESTROY_SCREEN;
	cmd->body.screenId = sou->base.unit;

	vmw_fifo_commit(dev_priv, fifo_size);

	/* Force sync */
	ret = vmw_fallback_wait(dev_priv, false, true, 0, false, 3*HZ);
	if (unlikely(ret != 0))
		DRM_ERROR("Failed to sync with HW");
	else
		sou->defined = false;

	return ret;
}
コード例 #4
0
ファイル: vmwgfx_stdu.c プロジェクト: mhei/linux
/**
 * vmw_stdu_destroy_st - Destroy a Screen Target
 *
 * @dev_priv:  VMW DRM device
 * @stdu: display unit to destroy
 */
static int vmw_stdu_destroy_st(struct vmw_private *dev_priv,
                               struct vmw_screen_target_display_unit *stdu)
{
    int    ret;

    struct {
        SVGA3dCmdHeader header;
        SVGA3dCmdDestroyGBScreenTarget body;
    } *cmd;


    /* Nothing to do if not successfully defined */
    if (unlikely(!stdu->defined))
        return 0;

    cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));

    if (unlikely(cmd == NULL)) {
        DRM_ERROR("Out of FIFO space, screen target not destroyed\n");
        return -ENOMEM;
    }

    cmd->header.id   = SVGA_3D_CMD_DESTROY_GB_SCREENTARGET;
    cmd->header.size = sizeof(cmd->body);

    cmd->body.stid   = stdu->base.unit;

    vmw_fifo_commit(dev_priv, sizeof(*cmd));

    /* Force sync */
    ret = vmw_fallback_wait(dev_priv, false, true, 0, false, 3*HZ);
    if (unlikely(ret != 0))
        DRM_ERROR("Failed to sync with HW");

    stdu->defined = false;

    return ret;
}
コード例 #5
0
/**
 * Send put command to hw.
 *
 * Returns
 * -ERESTARTSYS if interrupted by a signal.
 */
static int vmw_overlay_send_put(struct vmw_private *dev_priv,
				struct vmw_dma_buffer *buf,
				struct drm_vmw_control_stream_arg *arg,
				bool interruptible)
{
	struct {
		struct vmw_escape_header escape;
		struct {
			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;
	uint32_t offset;
	int i, ret;

	for (;;) {
		cmds = vmw_fifo_reserve(dev_priv, sizeof(*cmds));
		if (cmds)
			break;

		ret = vmw_fallback_wait(dev_priv, false, true, 0,
					interruptible, 3*HZ);
		if (interruptible && ret == -ERESTARTSYS)
			return ret;
		else
			BUG_ON(ret != 0);
	}

	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, sizeof(*cmds));

	return 0;
}
コード例 #6
0
int vmw_wait_fence(struct vmw_private *dev_priv,
		   bool lazy, uint32_t sequence,
		   bool interruptible, unsigned long timeout)
{
	long ret;
	unsigned long irq_flags;
	struct vmw_fifo_state *fifo = &dev_priv->fifo;

	if (likely(dev_priv->last_read_sequence - sequence < VMW_FENCE_WRAP))
		return 0;

	if (likely(vmw_fence_signaled(dev_priv, sequence)))
		return 0;

	vmw_fifo_ping_host(dev_priv, SVGA_SYNC_GENERIC);

	if (!(fifo->capabilities & SVGA_FIFO_CAP_FENCE))
		return vmw_fallback_wait(dev_priv, lazy, true, sequence,
					 interruptible, timeout);

	if (!(dev_priv->capabilities & SVGA_CAP_IRQMASK))
		return vmw_fallback_wait(dev_priv, lazy, false, sequence,
					 interruptible, timeout);

	mutex_lock(&dev_priv->hw_mutex);
	if (atomic_add_return(1, &dev_priv->fence_queue_waiters) > 0) {
		spin_lock_irqsave(&dev_priv->irq_lock, irq_flags);
		outl(SVGA_IRQFLAG_ANY_FENCE,
		     dev_priv->io_start + VMWGFX_IRQSTATUS_PORT);
		vmw_write(dev_priv, SVGA_REG_IRQMASK,
			  vmw_read(dev_priv, SVGA_REG_IRQMASK) |
			  SVGA_IRQFLAG_ANY_FENCE);
		spin_unlock_irqrestore(&dev_priv->irq_lock, irq_flags);
	}
	mutex_unlock(&dev_priv->hw_mutex);

	if (interruptible)
		ret = wait_event_interruptible_timeout
		    (dev_priv->fence_queue,
		     vmw_fence_signaled(dev_priv, sequence),
		     timeout);
	else
		ret = wait_event_timeout
		    (dev_priv->fence_queue,
		     vmw_fence_signaled(dev_priv, sequence),
		     timeout);

	if (unlikely(ret == 0))
		ret = -EBUSY;
	else if (likely(ret > 0))
		ret = 0;

	mutex_lock(&dev_priv->hw_mutex);
	if (atomic_dec_and_test(&dev_priv->fence_queue_waiters)) {
		spin_lock_irqsave(&dev_priv->irq_lock, irq_flags);
		vmw_write(dev_priv, SVGA_REG_IRQMASK,
			  vmw_read(dev_priv, SVGA_REG_IRQMASK) &
			  ~SVGA_IRQFLAG_ANY_FENCE);
		spin_unlock_irqrestore(&dev_priv->irq_lock, irq_flags);
	}
	mutex_unlock(&dev_priv->hw_mutex);

	return ret;
}