Commit 8bb9eb48 authored by Christian König's avatar Christian König Committed by Alex Deucher
Browse files

drm/amdgpu: add IH ring to ih_get_wptr/ih_set_rptr v2



Let's start to support multiple rings.

v2: decode IV is needed as well

Signed-off-by: default avatarChristian König <christian.koenig@amd.com>
Acked-by: default avatarAlex Deucher <alexander.deucher@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 73c97fa4
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -137,7 +137,7 @@ int amdgpu_ih_process(struct amdgpu_device *adev, struct amdgpu_ih_ring *ih,
	if (!ih->enabled || adev->shutdown)
		return IRQ_NONE;

	wptr = amdgpu_ih_get_wptr(adev);
	wptr = amdgpu_ih_get_wptr(adev, ih);

restart_ih:
	/* is somebody else already processing irqs? */
@@ -154,11 +154,11 @@ int amdgpu_ih_process(struct amdgpu_device *adev, struct amdgpu_ih_ring *ih,
		ih->rptr &= ih->ptr_mask;
	}

	amdgpu_ih_set_rptr(adev);
	amdgpu_ih_set_rptr(adev, ih);
	atomic_set(&ih->lock, 0);

	/* make sure wptr hasn't changed while processing */
	wptr = amdgpu_ih_get_wptr(adev);
	wptr = amdgpu_ih_get_wptr(adev, ih);
	if (wptr != ih->rptr)
		goto restart_ih;

+7 −6
Original line number Diff line number Diff line
@@ -50,15 +50,16 @@ struct amdgpu_ih_ring {
/* provided by the ih block */
struct amdgpu_ih_funcs {
	/* ring read/write ptr handling, called from interrupt context */
	u32 (*get_wptr)(struct amdgpu_device *adev);
	void (*decode_iv)(struct amdgpu_device *adev,
	u32 (*get_wptr)(struct amdgpu_device *adev, struct amdgpu_ih_ring *ih);
	void (*decode_iv)(struct amdgpu_device *adev, struct amdgpu_ih_ring *ih,
			  struct amdgpu_iv_entry *entry);
	void (*set_rptr)(struct amdgpu_device *adev);
	void (*set_rptr)(struct amdgpu_device *adev, struct amdgpu_ih_ring *ih);
};

#define amdgpu_ih_get_wptr(adev) (adev)->irq.ih_funcs->get_wptr((adev))
#define amdgpu_ih_decode_iv(adev, iv) (adev)->irq.ih_funcs->decode_iv((adev), (iv))
#define amdgpu_ih_set_rptr(adev) (adev)->irq.ih_funcs->set_rptr((adev))
#define amdgpu_ih_get_wptr(adev, ih) (adev)->irq.ih_funcs->get_wptr((adev), (ih))
#define amdgpu_ih_decode_iv(adev, iv) \
	(adev)->irq.ih_funcs->decode_iv((adev), (ih), (iv))
#define amdgpu_ih_set_rptr(adev, ih) (adev)->irq.ih_funcs->set_rptr((adev), (ih))

int amdgpu_ih_ring_init(struct amdgpu_device *adev, struct amdgpu_ih_ring *ih,
			unsigned ring_size, bool use_bus_addr);
+16 −13
Original line number Diff line number Diff line
@@ -183,11 +183,12 @@ static void cik_ih_irq_disable(struct amdgpu_device *adev)
 * Used by cik_irq_process().
 * Returns the value of the wptr.
 */
static u32 cik_ih_get_wptr(struct amdgpu_device *adev)
static u32 cik_ih_get_wptr(struct amdgpu_device *adev,
			   struct amdgpu_ih_ring *ih)
{
	u32 wptr, tmp;

	wptr = le32_to_cpu(adev->wb.wb[adev->irq.ih.wptr_offs]);
	wptr = le32_to_cpu(adev->wb.wb[ih->wptr_offs]);

	if (wptr & IH_RB_WPTR__RB_OVERFLOW_MASK) {
		wptr &= ~IH_RB_WPTR__RB_OVERFLOW_MASK;
@@ -196,13 +197,13 @@ static u32 cik_ih_get_wptr(struct amdgpu_device *adev)
		 * this should allow us to catchup.
		 */
		dev_warn(adev->dev, "IH ring buffer overflow (0x%08X, 0x%08X, 0x%08X)\n",
			wptr, adev->irq.ih.rptr, (wptr + 16) & adev->irq.ih.ptr_mask);
		adev->irq.ih.rptr = (wptr + 16) & adev->irq.ih.ptr_mask;
			 wptr, ih->rptr, (wptr + 16) & ih->ptr_mask);
		ih->rptr = (wptr + 16) & ih->ptr_mask;
		tmp = RREG32(mmIH_RB_CNTL);
		tmp |= IH_RB_CNTL__WPTR_OVERFLOW_CLEAR_MASK;
		WREG32(mmIH_RB_CNTL, tmp);
	}
	return (wptr & adev->irq.ih.ptr_mask);
	return (wptr & ih->ptr_mask);
}

/*        CIK IV Ring
@@ -237,16 +238,17 @@ static u32 cik_ih_get_wptr(struct amdgpu_device *adev)
 * position and also advance the position.
 */
static void cik_ih_decode_iv(struct amdgpu_device *adev,
			     struct amdgpu_ih_ring *ih,
			     struct amdgpu_iv_entry *entry)
{
	/* wptr/rptr are in bytes! */
	u32 ring_index = adev->irq.ih.rptr >> 2;
	u32 ring_index = ih->rptr >> 2;
	uint32_t dw[4];

	dw[0] = le32_to_cpu(adev->irq.ih.ring[ring_index + 0]);
	dw[1] = le32_to_cpu(adev->irq.ih.ring[ring_index + 1]);
	dw[2] = le32_to_cpu(adev->irq.ih.ring[ring_index + 2]);
	dw[3] = le32_to_cpu(adev->irq.ih.ring[ring_index + 3]);
	dw[0] = le32_to_cpu(ih->ring[ring_index + 0]);
	dw[1] = le32_to_cpu(ih->ring[ring_index + 1]);
	dw[2] = le32_to_cpu(ih->ring[ring_index + 2]);
	dw[3] = le32_to_cpu(ih->ring[ring_index + 3]);

	entry->client_id = AMDGPU_IRQ_CLIENTID_LEGACY;
	entry->src_id = dw[0] & 0xff;
@@ -256,7 +258,7 @@ static void cik_ih_decode_iv(struct amdgpu_device *adev,
	entry->pasid = (dw[2] >> 16) & 0xffff;

	/* wptr/rptr are in bytes! */
	adev->irq.ih.rptr += 16;
	ih->rptr += 16;
}

/**
@@ -266,9 +268,10 @@ static void cik_ih_decode_iv(struct amdgpu_device *adev,
 *
 * Set the IH ring buffer rptr.
 */
static void cik_ih_set_rptr(struct amdgpu_device *adev)
static void cik_ih_set_rptr(struct amdgpu_device *adev,
			    struct amdgpu_ih_ring *ih)
{
	WREG32(mmIH_RB_RPTR, adev->irq.ih.rptr);
	WREG32(mmIH_RB_RPTR, ih->rptr);
}

static int cik_ih_early_init(void *handle)
+17 −14
Original line number Diff line number Diff line
@@ -185,11 +185,12 @@ static void cz_ih_irq_disable(struct amdgpu_device *adev)
 * Used by cz_irq_process(VI).
 * Returns the value of the wptr.
 */
static u32 cz_ih_get_wptr(struct amdgpu_device *adev)
static u32 cz_ih_get_wptr(struct amdgpu_device *adev,
			  struct amdgpu_ih_ring *ih)
{
	u32 wptr, tmp;

	wptr = le32_to_cpu(adev->wb.wb[adev->irq.ih.wptr_offs]);
	wptr = le32_to_cpu(adev->wb.wb[ih->wptr_offs]);

	if (REG_GET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW)) {
		wptr = REG_SET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW, 0);
@@ -198,13 +199,13 @@ static u32 cz_ih_get_wptr(struct amdgpu_device *adev)
		 * this should allow us to catchup.
		 */
		dev_warn(adev->dev, "IH ring buffer overflow (0x%08X, 0x%08X, 0x%08X)\n",
			wptr, adev->irq.ih.rptr, (wptr + 16) & adev->irq.ih.ptr_mask);
		adev->irq.ih.rptr = (wptr + 16) & adev->irq.ih.ptr_mask;
			wptr, ih->rptr, (wptr + 16) & ih->ptr_mask);
		ih->rptr = (wptr + 16) & ih->ptr_mask;
		tmp = RREG32(mmIH_RB_CNTL);
		tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 1);
		WREG32(mmIH_RB_CNTL, tmp);
	}
	return (wptr & adev->irq.ih.ptr_mask);
	return (wptr & ih->ptr_mask);
}

/**
@@ -216,16 +217,17 @@ static u32 cz_ih_get_wptr(struct amdgpu_device *adev)
 * position and also advance the position.
 */
static void cz_ih_decode_iv(struct amdgpu_device *adev,
			    struct amdgpu_ih_ring *ih,
			    struct amdgpu_iv_entry *entry)
{
	/* wptr/rptr are in bytes! */
	u32 ring_index = adev->irq.ih.rptr >> 2;
	u32 ring_index = ih->rptr >> 2;
	uint32_t dw[4];

	dw[0] = le32_to_cpu(adev->irq.ih.ring[ring_index + 0]);
	dw[1] = le32_to_cpu(adev->irq.ih.ring[ring_index + 1]);
	dw[2] = le32_to_cpu(adev->irq.ih.ring[ring_index + 2]);
	dw[3] = le32_to_cpu(adev->irq.ih.ring[ring_index + 3]);
	dw[0] = le32_to_cpu(ih->ring[ring_index + 0]);
	dw[1] = le32_to_cpu(ih->ring[ring_index + 1]);
	dw[2] = le32_to_cpu(ih->ring[ring_index + 2]);
	dw[3] = le32_to_cpu(ih->ring[ring_index + 3]);

	entry->client_id = AMDGPU_IRQ_CLIENTID_LEGACY;
	entry->src_id = dw[0] & 0xff;
@@ -235,7 +237,7 @@ static void cz_ih_decode_iv(struct amdgpu_device *adev,
	entry->pasid = (dw[2] >> 16) & 0xffff;

	/* wptr/rptr are in bytes! */
	adev->irq.ih.rptr += 16;
	ih->rptr += 16;
}

/**
@@ -245,9 +247,10 @@ static void cz_ih_decode_iv(struct amdgpu_device *adev,
 *
 * Set the IH ring buffer rptr.
 */
static void cz_ih_set_rptr(struct amdgpu_device *adev)
static void cz_ih_set_rptr(struct amdgpu_device *adev,
			   struct amdgpu_ih_ring *ih)
{
	WREG32(mmIH_RB_RPTR, adev->irq.ih.rptr);
	WREG32(mmIH_RB_RPTR, ih->rptr);
}

static int cz_ih_early_init(void *handle)
+16 −13
Original line number Diff line number Diff line
@@ -185,11 +185,12 @@ static void iceland_ih_irq_disable(struct amdgpu_device *adev)
 * Used by cz_irq_process(VI).
 * Returns the value of the wptr.
 */
static u32 iceland_ih_get_wptr(struct amdgpu_device *adev)
static u32 iceland_ih_get_wptr(struct amdgpu_device *adev,
			       struct amdgpu_ih_ring *ih)
{
	u32 wptr, tmp;

	wptr = le32_to_cpu(adev->wb.wb[adev->irq.ih.wptr_offs]);
	wptr = le32_to_cpu(adev->wb.wb[ih->wptr_offs]);

	if (REG_GET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW)) {
		wptr = REG_SET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW, 0);
@@ -198,13 +199,13 @@ static u32 iceland_ih_get_wptr(struct amdgpu_device *adev)
		 * this should allow us to catchup.
		 */
		dev_warn(adev->dev, "IH ring buffer overflow (0x%08X, 0x%08X, 0x%08X)\n",
			wptr, adev->irq.ih.rptr, (wptr + 16) & adev->irq.ih.ptr_mask);
		adev->irq.ih.rptr = (wptr + 16) & adev->irq.ih.ptr_mask;
			 wptr, ih->rptr, (wptr + 16) & ih->ptr_mask);
		ih->rptr = (wptr + 16) & ih->ptr_mask;
		tmp = RREG32(mmIH_RB_CNTL);
		tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 1);
		WREG32(mmIH_RB_CNTL, tmp);
	}
	return (wptr & adev->irq.ih.ptr_mask);
	return (wptr & ih->ptr_mask);
}

/**
@@ -216,16 +217,17 @@ static u32 iceland_ih_get_wptr(struct amdgpu_device *adev)
 * position and also advance the position.
 */
static void iceland_ih_decode_iv(struct amdgpu_device *adev,
				 struct amdgpu_ih_ring *ih,
				 struct amdgpu_iv_entry *entry)
{
	/* wptr/rptr are in bytes! */
	u32 ring_index = adev->irq.ih.rptr >> 2;
	u32 ring_index = ih->rptr >> 2;
	uint32_t dw[4];

	dw[0] = le32_to_cpu(adev->irq.ih.ring[ring_index + 0]);
	dw[1] = le32_to_cpu(adev->irq.ih.ring[ring_index + 1]);
	dw[2] = le32_to_cpu(adev->irq.ih.ring[ring_index + 2]);
	dw[3] = le32_to_cpu(adev->irq.ih.ring[ring_index + 3]);
	dw[0] = le32_to_cpu(ih->ring[ring_index + 0]);
	dw[1] = le32_to_cpu(ih->ring[ring_index + 1]);
	dw[2] = le32_to_cpu(ih->ring[ring_index + 2]);
	dw[3] = le32_to_cpu(ih->ring[ring_index + 3]);

	entry->client_id = AMDGPU_IRQ_CLIENTID_LEGACY;
	entry->src_id = dw[0] & 0xff;
@@ -235,7 +237,7 @@ static void iceland_ih_decode_iv(struct amdgpu_device *adev,
	entry->pasid = (dw[2] >> 16) & 0xffff;

	/* wptr/rptr are in bytes! */
	adev->irq.ih.rptr += 16;
	ih->rptr += 16;
}

/**
@@ -245,9 +247,10 @@ static void iceland_ih_decode_iv(struct amdgpu_device *adev,
 *
 * Set the IH ring buffer rptr.
 */
static void iceland_ih_set_rptr(struct amdgpu_device *adev)
static void iceland_ih_set_rptr(struct amdgpu_device *adev,
				struct amdgpu_ih_ring *ih)
{
	WREG32(mmIH_RB_RPTR, adev->irq.ih.rptr);
	WREG32(mmIH_RB_RPTR, ih->rptr);
}

static int iceland_ih_early_init(void *handle)
Loading