Commit 30c60ba3 authored by Dave Airlie's avatar Dave Airlie
Browse files

Merge tag 'vmwgfx-drm-fixes-5.18-2022-05-13' of...

Merge tag 'vmwgfx-drm-fixes-5.18-2022-05-13' of https://gitlab.freedesktop.org/zack/vmwgfx

 into drm-fixes

vmwgfx fixes for:
- Black screen due to fences using FIFO checks on SVGA3
- Random black screens on boot due to uninitialized drm_mode_fb_cmd2
- Hangs on SVGA3 due to command buffers being used with gbobjects

Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
From: Zack Rusin <zackr@vmware.com>
Link: https://patchwork.freedesktop.org/patch/msgid/a1d32799e4c74b8540216376d7576bb783ca07ba.camel@vmware.com
parents 5005e981 21d1d192
Loading
Loading
Loading
Loading
+8 −5
Original line number Diff line number Diff line
@@ -528,7 +528,7 @@ int vmw_cmd_send_fence(struct vmw_private *dev_priv, uint32_t *seqno)
		*seqno = atomic_add_return(1, &dev_priv->marker_seq);
	} while (*seqno == 0);

	if (!(vmw_fifo_caps(dev_priv) & SVGA_FIFO_CAP_FENCE)) {
	if (!vmw_has_fences(dev_priv)) {

		/*
		 * Don't request hardware to send a fence. The
@@ -675,11 +675,14 @@ int vmw_cmd_emit_dummy_query(struct vmw_private *dev_priv,
 */
bool vmw_cmd_supported(struct vmw_private *vmw)
{
	if ((vmw->capabilities & (SVGA_CAP_COMMAND_BUFFERS |
				  SVGA_CAP_CMD_BUFFERS_2)) != 0)
		return true;
	bool has_cmdbufs =
		(vmw->capabilities & (SVGA_CAP_COMMAND_BUFFERS |
				      SVGA_CAP_CMD_BUFFERS_2)) != 0;
	if (vmw_is_svga_v3(vmw))
		return (has_cmdbufs &&
			(vmw->capabilities & SVGA_CAP_GBOBJECTS) != 0);
	/*
	 * We have FIFO cmd's
	 */
	return vmw->fifo_mem != NULL;
	return has_cmdbufs || vmw->fifo_mem != NULL;
}
+8 −0
Original line number Diff line number Diff line
@@ -1679,4 +1679,12 @@ static inline void vmw_irq_status_write(struct vmw_private *vmw,
		outl(status, vmw->io_start + SVGA_IRQSTATUS_PORT);
}

static inline bool vmw_has_fences(struct vmw_private *vmw)
{
	if ((vmw->capabilities & (SVGA_CAP_COMMAND_BUFFERS |
				  SVGA_CAP_CMD_BUFFERS_2)) != 0)
		return true;
	return (vmw_fifo_caps(vmw) & SVGA_FIFO_CAP_FENCE) != 0;
}

#endif
+1 −1
Original line number Diff line number Diff line
@@ -483,7 +483,7 @@ static int vmw_fb_kms_detach(struct vmw_fb_par *par,

static int vmw_fb_kms_framebuffer(struct fb_info *info)
{
	struct drm_mode_fb_cmd2 mode_cmd;
	struct drm_mode_fb_cmd2 mode_cmd = {0};
	struct vmw_fb_par *par = info->par;
	struct fb_var_screeninfo *var = &info->var;
	struct drm_framebuffer *cur_fb;
+21 −7
Original line number Diff line number Diff line
@@ -82,6 +82,22 @@ fman_from_fence(struct vmw_fence_obj *fence)
	return container_of(fence->base.lock, struct vmw_fence_manager, lock);
}

static u32 vmw_fence_goal_read(struct vmw_private *vmw)
{
	if ((vmw->capabilities2 & SVGA_CAP2_EXTRA_REGS) != 0)
		return vmw_read(vmw, SVGA_REG_FENCE_GOAL);
	else
		return vmw_fifo_mem_read(vmw, SVGA_FIFO_FENCE_GOAL);
}

static void vmw_fence_goal_write(struct vmw_private *vmw, u32 value)
{
	if ((vmw->capabilities2 & SVGA_CAP2_EXTRA_REGS) != 0)
		vmw_write(vmw, SVGA_REG_FENCE_GOAL, value);
	else
		vmw_fifo_mem_write(vmw, SVGA_FIFO_FENCE_GOAL, value);
}

/*
 * Note on fencing subsystem usage of irqs:
 * Typically the vmw_fences_update function is called
@@ -392,7 +408,7 @@ static bool vmw_fence_goal_new_locked(struct vmw_fence_manager *fman,
	if (likely(!fman->seqno_valid))
		return false;

	goal_seqno = vmw_fifo_mem_read(fman->dev_priv, SVGA_FIFO_FENCE_GOAL);
	goal_seqno = vmw_fence_goal_read(fman->dev_priv);
	if (likely(passed_seqno - goal_seqno >= VMW_FENCE_WRAP))
		return false;

@@ -400,8 +416,7 @@ static bool vmw_fence_goal_new_locked(struct vmw_fence_manager *fman,
	list_for_each_entry(fence, &fman->fence_list, head) {
		if (!list_empty(&fence->seq_passed_actions)) {
			fman->seqno_valid = true;
			vmw_fifo_mem_write(fman->dev_priv,
					   SVGA_FIFO_FENCE_GOAL,
			vmw_fence_goal_write(fman->dev_priv,
					     fence->base.seqno);
			break;
		}
@@ -434,13 +449,12 @@ static bool vmw_fence_goal_check_locked(struct vmw_fence_obj *fence)
	if (dma_fence_is_signaled_locked(&fence->base))
		return false;

	goal_seqno = vmw_fifo_mem_read(fman->dev_priv, SVGA_FIFO_FENCE_GOAL);
	goal_seqno = vmw_fence_goal_read(fman->dev_priv);
	if (likely(fman->seqno_valid &&
		   goal_seqno - fence->base.seqno < VMW_FENCE_WRAP))
		return false;

	vmw_fifo_mem_write(fman->dev_priv, SVGA_FIFO_FENCE_GOAL,
			   fence->base.seqno);
	vmw_fence_goal_write(fman->dev_priv, fence->base.seqno);
	fman->seqno_valid = true;

	return true;
+18 −8
Original line number Diff line number Diff line
@@ -32,6 +32,14 @@

#define VMW_FENCE_WRAP (1 << 24)

static u32 vmw_irqflag_fence_goal(struct vmw_private *vmw)
{
	if ((vmw->capabilities2 & SVGA_CAP2_EXTRA_REGS) != 0)
		return SVGA_IRQFLAG_REG_FENCE_GOAL;
	else
		return SVGA_IRQFLAG_FENCE_GOAL;
}

/**
 * vmw_thread_fn - Deferred (process context) irq handler
 *
@@ -96,7 +104,7 @@ static irqreturn_t vmw_irq_handler(int irq, void *arg)
		wake_up_all(&dev_priv->fifo_queue);

	if ((masked_status & (SVGA_IRQFLAG_ANY_FENCE |
			      SVGA_IRQFLAG_FENCE_GOAL)) &&
			      vmw_irqflag_fence_goal(dev_priv))) &&
	    !test_and_set_bit(VMW_IRQTHREAD_FENCE, dev_priv->irqthread_pending))
		ret = IRQ_WAKE_THREAD;

@@ -137,8 +145,7 @@ bool vmw_seqno_passed(struct vmw_private *dev_priv,
	if (likely(dev_priv->last_read_seqno - seqno < VMW_FENCE_WRAP))
		return true;

	if (!(vmw_fifo_caps(dev_priv) & SVGA_FIFO_CAP_FENCE) &&
	    vmw_fifo_idle(dev_priv, seqno))
	if (!vmw_has_fences(dev_priv) && vmw_fifo_idle(dev_priv, seqno))
		return true;

	/**
@@ -160,6 +167,7 @@ int vmw_fallback_wait(struct vmw_private *dev_priv,
		      unsigned long timeout)
{
	struct vmw_fifo_state *fifo_state = dev_priv->fifo;
	bool fifo_down = false;

	uint32_t count = 0;
	uint32_t signal_seq;
@@ -176,12 +184,14 @@ int vmw_fallback_wait(struct vmw_private *dev_priv,
	 */

	if (fifo_idle) {
		down_read(&fifo_state->rwsem);
		if (dev_priv->cman) {
			ret = vmw_cmdbuf_idle(dev_priv->cman, interruptible,
					      10*HZ);
			if (ret)
				goto out_err;
		} else if (fifo_state) {
			down_read(&fifo_state->rwsem);
			fifo_down = true;
		}
	}

@@ -218,12 +228,12 @@ int vmw_fallback_wait(struct vmw_private *dev_priv,
		}
	}
	finish_wait(&dev_priv->fence_queue, &__wait);
	if (ret == 0 && fifo_idle)
	if (ret == 0 && fifo_idle && fifo_state)
		vmw_fence_write(dev_priv, signal_seq);

	wake_up_all(&dev_priv->fence_queue);
out_err:
	if (fifo_idle)
	if (fifo_down)
		up_read(&fifo_state->rwsem);

	return ret;
@@ -266,13 +276,13 @@ void vmw_seqno_waiter_remove(struct vmw_private *dev_priv)

void vmw_goal_waiter_add(struct vmw_private *dev_priv)
{
	vmw_generic_waiter_add(dev_priv, SVGA_IRQFLAG_FENCE_GOAL,
	vmw_generic_waiter_add(dev_priv, vmw_irqflag_fence_goal(dev_priv),
			       &dev_priv->goal_queue_waiters);
}

void vmw_goal_waiter_remove(struct vmw_private *dev_priv)
{
	vmw_generic_waiter_remove(dev_priv, SVGA_IRQFLAG_FENCE_GOAL,
	vmw_generic_waiter_remove(dev_priv, vmw_irqflag_fence_goal(dev_priv),
				  &dev_priv->goal_queue_waiters);
}

Loading