[1/3] drm/amdgpu: enable IH ring 1 and ring 2 v3

Submitted by =?UTF-8?q?Christian=20K=C3=B6nig?= on Jan. 9, 2019, 1:12 p.m.

Details

Message ID 20190109131246.1274-1-christian.koenig@amd.com
State New
Headers show
Series "Series without cover letter" ( rev: 1 ) in AMD X.Org drivers

Not browsing as part of any series.

Commit Message

=?UTF-8?q?Christian=20K=C3=B6nig?= Jan. 9, 2019, 1:12 p.m.
The entries are ignored for now, but it at least stops crashing the
hardware when somebody tries to push something to the other IH rings.

v2: limit ring size, add TODO comment
v3: only program rings if they are actually allocated

Signed-off-by: Christian König <christian.koenig@amd.com>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_irq.h |   4 +-
 drivers/gpu/drm/amd/amdgpu/vega10_ih.c  | 143 ++++++++++++++++++++----
 2 files changed, 121 insertions(+), 26 deletions(-)

Patch hide | download patch | download mbox

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.h
index f6ce171cb8aa..7e06fa64321a 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.h
@@ -87,8 +87,8 @@  struct amdgpu_irq {
 	/* status, etc. */
 	bool				msi_enabled; /* msi enabled */
 
-	/* interrupt ring */
-	struct amdgpu_ih_ring		ih;
+	/* interrupt rings */
+	struct amdgpu_ih_ring		ih, ih1, ih2;
 	const struct amdgpu_ih_funcs	*ih_funcs;
 
 	/* gen irq stuff */
diff --git a/drivers/gpu/drm/amd/amdgpu/vega10_ih.c b/drivers/gpu/drm/amd/amdgpu/vega10_ih.c
index 562701939d3e..eea5530d2961 100644
--- a/drivers/gpu/drm/amd/amdgpu/vega10_ih.c
+++ b/drivers/gpu/drm/amd/amdgpu/vega10_ih.c
@@ -50,6 +50,22 @@  static void vega10_ih_enable_interrupts(struct amdgpu_device *adev)
 	ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, ENABLE_INTR, 1);
 	WREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL, ih_rb_cntl);
 	adev->irq.ih.enabled = true;
+
+	if (adev->irq.ih1.ring_size) {
+		ih_rb_cntl = RREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING1);
+		ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL_RING1,
+					   RB_ENABLE, 1);
+		WREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING1, ih_rb_cntl);
+		adev->irq.ih1.enabled = true;
+	}
+
+	if (adev->irq.ih2.ring_size) {
+		ih_rb_cntl = RREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING2);
+		ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL_RING2,
+					   RB_ENABLE, 1);
+		WREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING2, ih_rb_cntl);
+		adev->irq.ih2.enabled = true;
+	}
 }
 
 /**
@@ -71,6 +87,53 @@  static void vega10_ih_disable_interrupts(struct amdgpu_device *adev)
 	WREG32_SOC15(OSSSYS, 0, mmIH_RB_WPTR, 0);
 	adev->irq.ih.enabled = false;
 	adev->irq.ih.rptr = 0;
+
+	if (adev->irq.ih1.ring_size) {
+		ih_rb_cntl = RREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING1);
+		ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL_RING1,
+					   RB_ENABLE, 0);
+		WREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING1, ih_rb_cntl);
+		/* set rptr, wptr to 0 */
+		WREG32_SOC15(OSSSYS, 0, mmIH_RB_RPTR_RING1, 0);
+		WREG32_SOC15(OSSSYS, 0, mmIH_RB_WPTR_RING1, 0);
+		adev->irq.ih1.enabled = false;
+		adev->irq.ih1.rptr = 0;
+	}
+
+	if (adev->irq.ih2.ring_size) {
+		ih_rb_cntl = RREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING2);
+		ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL_RING2,
+					   RB_ENABLE, 0);
+		WREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING2, ih_rb_cntl);
+		/* set rptr, wptr to 0 */
+		WREG32_SOC15(OSSSYS, 0, mmIH_RB_RPTR_RING2, 0);
+		WREG32_SOC15(OSSSYS, 0, mmIH_RB_WPTR_RING2, 0);
+		adev->irq.ih2.enabled = false;
+		adev->irq.ih2.rptr = 0;
+	}
+}
+
+static uint32_t vega10_ih_rb_cntl(struct amdgpu_ih_ring *ih, uint32_t ih_rb_cntl)
+{
+	int rb_bufsz = order_base_2(ih->ring_size / 4);
+
+	ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL,
+				   MC_SPACE, ih->use_bus_addr ? 1 : 4);
+	ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL,
+				   WPTR_OVERFLOW_CLEAR, 1);
+	ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL,
+				   WPTR_OVERFLOW_ENABLE, 1);
+	ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, RB_SIZE, rb_bufsz);
+	/* Ring Buffer write pointer writeback. If enabled, IH_RB_WPTR register
+	 * value is written to memory
+	 */
+	ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL,
+				   WPTR_WRITEBACK_ENABLE, 1);
+	ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, MC_SNOOP, 1);
+	ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, MC_RO, 0);
+	ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, MC_VMID, 0);
+
+	return ih_rb_cntl;
 }
 
 /**
@@ -86,9 +149,8 @@  static void vega10_ih_disable_interrupts(struct amdgpu_device *adev)
  */
 static int vega10_ih_irq_init(struct amdgpu_device *adev)
 {
-	struct amdgpu_ih_ring *ih = &adev->irq.ih;
+	struct amdgpu_ih_ring *ih;
 	int ret = 0;
-	int rb_bufsz;
 	u32 ih_rb_cntl, ih_doorbell_rtpr;
 	u32 tmp;
 
@@ -97,26 +159,15 @@  static int vega10_ih_irq_init(struct amdgpu_device *adev)
 
 	adev->nbio_funcs->ih_control(adev);
 
-	ih_rb_cntl = RREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL);
+	ih = &adev->irq.ih;
 	/* Ring Buffer base. [39:8] of 40-bit address of the beginning of the ring buffer*/
-	WREG32_SOC15(OSSSYS, 0, mmIH_RB_BASE, adev->irq.ih.gpu_addr >> 8);
-	WREG32_SOC15(OSSSYS, 0, mmIH_RB_BASE_HI,
-		     (adev->irq.ih.gpu_addr >> 40) & 0xff);
-	ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, MC_SPACE,
-				   ih->use_bus_addr ? 1 : 4);
-	rb_bufsz = order_base_2(adev->irq.ih.ring_size / 4);
-	ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 1);
-	ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, WPTR_OVERFLOW_ENABLE, 1);
-	ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, RB_SIZE, rb_bufsz);
-	/* Ring Buffer write pointer writeback. If enabled, IH_RB_WPTR register value is written to memory */
-	ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, WPTR_WRITEBACK_ENABLE, 1);
-	ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, MC_SNOOP, 1);
-	ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, MC_RO, 0);
-	ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, MC_VMID, 0);
-
-	if (adev->irq.msi_enabled)
-		ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, RPTR_REARM, 1);
+	WREG32_SOC15(OSSSYS, 0, mmIH_RB_BASE, ih->gpu_addr >> 8);
+	WREG32_SOC15(OSSSYS, 0, mmIH_RB_BASE_HI, (ih->gpu_addr >> 40) & 0xff);
 
+	ih_rb_cntl = RREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL);
+	ih_rb_cntl = vega10_ih_rb_cntl(ih, ih_rb_cntl);
+	ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, RPTR_REARM,
+				   !!adev->irq.msi_enabled);
 	WREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL, ih_rb_cntl);
 
 	/* set the writeback address whether it's enabled or not */
@@ -131,18 +182,51 @@  static int vega10_ih_irq_init(struct amdgpu_device *adev)
 
 	ih_doorbell_rtpr = RREG32_SOC15(OSSSYS, 0, mmIH_DOORBELL_RPTR);
 	if (adev->irq.ih.use_doorbell) {
-		ih_doorbell_rtpr = REG_SET_FIELD(ih_doorbell_rtpr, IH_DOORBELL_RPTR,
-						 OFFSET, adev->irq.ih.doorbell_index);
-		ih_doorbell_rtpr = REG_SET_FIELD(ih_doorbell_rtpr, IH_DOORBELL_RPTR,
+		ih_doorbell_rtpr = REG_SET_FIELD(ih_doorbell_rtpr,
+						 IH_DOORBELL_RPTR, OFFSET,
+						 adev->irq.ih.doorbell_index);
+		ih_doorbell_rtpr = REG_SET_FIELD(ih_doorbell_rtpr,
+						 IH_DOORBELL_RPTR,
 						 ENABLE, 1);
 	} else {
-		ih_doorbell_rtpr = REG_SET_FIELD(ih_doorbell_rtpr, IH_DOORBELL_RPTR,
+		ih_doorbell_rtpr = REG_SET_FIELD(ih_doorbell_rtpr,
+						 IH_DOORBELL_RPTR,
 						 ENABLE, 0);
 	}
 	WREG32_SOC15(OSSSYS, 0, mmIH_DOORBELL_RPTR, ih_doorbell_rtpr);
 	adev->nbio_funcs->ih_doorbell_range(adev, adev->irq.ih.use_doorbell,
 					    adev->irq.ih.doorbell_index);
 
+	ih = &adev->irq.ih1;
+	if (ih->ring_size) {
+		WREG32_SOC15(OSSSYS, 0, mmIH_RB_BASE_RING1, ih->gpu_addr >> 8);
+		WREG32_SOC15(OSSSYS, 0, mmIH_RB_BASE_HI_RING1,
+			     (ih->gpu_addr >> 40) & 0xff);
+
+		ih_rb_cntl = RREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING1);
+		ih_rb_cntl = vega10_ih_rb_cntl(ih, ih_rb_cntl);
+		WREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING1, ih_rb_cntl);
+
+		/* set rptr, wptr to 0 */
+		WREG32_SOC15(OSSSYS, 0, mmIH_RB_RPTR_RING1, 0);
+		WREG32_SOC15(OSSSYS, 0, mmIH_RB_WPTR_RING1, 0);
+	}
+
+	ih = &adev->irq.ih2;
+	if (ih->ring_size) {
+		WREG32_SOC15(OSSSYS, 0, mmIH_RB_BASE_RING2, ih->gpu_addr >> 8);
+		WREG32_SOC15(OSSSYS, 0, mmIH_RB_BASE_HI_RING2,
+			     (ih->gpu_addr >> 40) & 0xff);
+
+		ih_rb_cntl = RREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING1);
+		ih_rb_cntl = vega10_ih_rb_cntl(ih, ih_rb_cntl);
+		WREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING2, ih_rb_cntl);
+
+		/* set rptr, wptr to 0 */
+		WREG32_SOC15(OSSSYS, 0, mmIH_RB_RPTR_RING2, 0);
+		WREG32_SOC15(OSSSYS, 0, mmIH_RB_WPTR_RING2, 0);
+	}
+
 	tmp = RREG32_SOC15(OSSSYS, 0, mmIH_STORM_CLIENT_LIST_CNTL);
 	tmp = REG_SET_FIELD(tmp, IH_STORM_CLIENT_LIST_CNTL,
 			    CLIENT18_IS_STORM_CLIENT, 1);
@@ -299,6 +383,15 @@  static int vega10_ih_sw_init(void *handle)
 	if (r)
 		return r;
 
+	r = amdgpu_ih_ring_init(adev, &adev->irq.ih1, PAGE_SIZE, true);
+	if (r)
+		return r;
+
+	r = amdgpu_ih_ring_init(adev, &adev->irq.ih2, PAGE_SIZE, true);
+	if (r)
+		return r;
+
+	/* TODO add doorbell for IH1 & IH2 as well */
 	adev->irq.ih.use_doorbell = true;
 	adev->irq.ih.doorbell_index = adev->doorbell_index.ih << 1;
 
@@ -312,6 +405,8 @@  static int vega10_ih_sw_fini(void *handle)
 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
 	amdgpu_irq_fini(adev);
+	amdgpu_ih_ring_fini(adev, &adev->irq.ih2);
+	amdgpu_ih_ring_fini(adev, &adev->irq.ih1);
 	amdgpu_ih_ring_fini(adev, &adev->irq.ih);
 
 	return 0;

Comments

Am 09.01.19 um 14:12 schrieb Christian König:
> The entries are ignored for now, but it at least stops crashing the
> hardware when somebody tries to push something to the other IH rings.
>
> v2: limit ring size, add TODO comment
> v3: only program rings if they are actually allocated
>
> Signed-off-by: Christian König <christian.koenig@amd.com>

Ping Alex & Felix any more comments on this series?

Christian.

> ---
>   drivers/gpu/drm/amd/amdgpu/amdgpu_irq.h |   4 +-
>   drivers/gpu/drm/amd/amdgpu/vega10_ih.c  | 143 ++++++++++++++++++++----
>   2 files changed, 121 insertions(+), 26 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.h
> index f6ce171cb8aa..7e06fa64321a 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.h
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.h
> @@ -87,8 +87,8 @@ struct amdgpu_irq {
>   	/* status, etc. */
>   	bool				msi_enabled; /* msi enabled */
>   
> -	/* interrupt ring */
> -	struct amdgpu_ih_ring		ih;
> +	/* interrupt rings */
> +	struct amdgpu_ih_ring		ih, ih1, ih2;
>   	const struct amdgpu_ih_funcs	*ih_funcs;
>   
>   	/* gen irq stuff */
> diff --git a/drivers/gpu/drm/amd/amdgpu/vega10_ih.c b/drivers/gpu/drm/amd/amdgpu/vega10_ih.c
> index 562701939d3e..eea5530d2961 100644
> --- a/drivers/gpu/drm/amd/amdgpu/vega10_ih.c
> +++ b/drivers/gpu/drm/amd/amdgpu/vega10_ih.c
> @@ -50,6 +50,22 @@ static void vega10_ih_enable_interrupts(struct amdgpu_device *adev)
>   	ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, ENABLE_INTR, 1);
>   	WREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL, ih_rb_cntl);
>   	adev->irq.ih.enabled = true;
> +
> +	if (adev->irq.ih1.ring_size) {
> +		ih_rb_cntl = RREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING1);
> +		ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL_RING1,
> +					   RB_ENABLE, 1);
> +		WREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING1, ih_rb_cntl);
> +		adev->irq.ih1.enabled = true;
> +	}
> +
> +	if (adev->irq.ih2.ring_size) {
> +		ih_rb_cntl = RREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING2);
> +		ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL_RING2,
> +					   RB_ENABLE, 1);
> +		WREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING2, ih_rb_cntl);
> +		adev->irq.ih2.enabled = true;
> +	}
>   }
>   
>   /**
> @@ -71,6 +87,53 @@ static void vega10_ih_disable_interrupts(struct amdgpu_device *adev)
>   	WREG32_SOC15(OSSSYS, 0, mmIH_RB_WPTR, 0);
>   	adev->irq.ih.enabled = false;
>   	adev->irq.ih.rptr = 0;
> +
> +	if (adev->irq.ih1.ring_size) {
> +		ih_rb_cntl = RREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING1);
> +		ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL_RING1,
> +					   RB_ENABLE, 0);
> +		WREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING1, ih_rb_cntl);
> +		/* set rptr, wptr to 0 */
> +		WREG32_SOC15(OSSSYS, 0, mmIH_RB_RPTR_RING1, 0);
> +		WREG32_SOC15(OSSSYS, 0, mmIH_RB_WPTR_RING1, 0);
> +		adev->irq.ih1.enabled = false;
> +		adev->irq.ih1.rptr = 0;
> +	}
> +
> +	if (adev->irq.ih2.ring_size) {
> +		ih_rb_cntl = RREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING2);
> +		ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL_RING2,
> +					   RB_ENABLE, 0);
> +		WREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING2, ih_rb_cntl);
> +		/* set rptr, wptr to 0 */
> +		WREG32_SOC15(OSSSYS, 0, mmIH_RB_RPTR_RING2, 0);
> +		WREG32_SOC15(OSSSYS, 0, mmIH_RB_WPTR_RING2, 0);
> +		adev->irq.ih2.enabled = false;
> +		adev->irq.ih2.rptr = 0;
> +	}
> +}
> +
> +static uint32_t vega10_ih_rb_cntl(struct amdgpu_ih_ring *ih, uint32_t ih_rb_cntl)
> +{
> +	int rb_bufsz = order_base_2(ih->ring_size / 4);
> +
> +	ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL,
> +				   MC_SPACE, ih->use_bus_addr ? 1 : 4);
> +	ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL,
> +				   WPTR_OVERFLOW_CLEAR, 1);
> +	ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL,
> +				   WPTR_OVERFLOW_ENABLE, 1);
> +	ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, RB_SIZE, rb_bufsz);
> +	/* Ring Buffer write pointer writeback. If enabled, IH_RB_WPTR register
> +	 * value is written to memory
> +	 */
> +	ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL,
> +				   WPTR_WRITEBACK_ENABLE, 1);
> +	ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, MC_SNOOP, 1);
> +	ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, MC_RO, 0);
> +	ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, MC_VMID, 0);
> +
> +	return ih_rb_cntl;
>   }
>   
>   /**
> @@ -86,9 +149,8 @@ static void vega10_ih_disable_interrupts(struct amdgpu_device *adev)
>    */
>   static int vega10_ih_irq_init(struct amdgpu_device *adev)
>   {
> -	struct amdgpu_ih_ring *ih = &adev->irq.ih;
> +	struct amdgpu_ih_ring *ih;
>   	int ret = 0;
> -	int rb_bufsz;
>   	u32 ih_rb_cntl, ih_doorbell_rtpr;
>   	u32 tmp;
>   
> @@ -97,26 +159,15 @@ static int vega10_ih_irq_init(struct amdgpu_device *adev)
>   
>   	adev->nbio_funcs->ih_control(adev);
>   
> -	ih_rb_cntl = RREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL);
> +	ih = &adev->irq.ih;
>   	/* Ring Buffer base. [39:8] of 40-bit address of the beginning of the ring buffer*/
> -	WREG32_SOC15(OSSSYS, 0, mmIH_RB_BASE, adev->irq.ih.gpu_addr >> 8);
> -	WREG32_SOC15(OSSSYS, 0, mmIH_RB_BASE_HI,
> -		     (adev->irq.ih.gpu_addr >> 40) & 0xff);
> -	ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, MC_SPACE,
> -				   ih->use_bus_addr ? 1 : 4);
> -	rb_bufsz = order_base_2(adev->irq.ih.ring_size / 4);
> -	ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 1);
> -	ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, WPTR_OVERFLOW_ENABLE, 1);
> -	ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, RB_SIZE, rb_bufsz);
> -	/* Ring Buffer write pointer writeback. If enabled, IH_RB_WPTR register value is written to memory */
> -	ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, WPTR_WRITEBACK_ENABLE, 1);
> -	ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, MC_SNOOP, 1);
> -	ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, MC_RO, 0);
> -	ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, MC_VMID, 0);
> -
> -	if (adev->irq.msi_enabled)
> -		ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, RPTR_REARM, 1);
> +	WREG32_SOC15(OSSSYS, 0, mmIH_RB_BASE, ih->gpu_addr >> 8);
> +	WREG32_SOC15(OSSSYS, 0, mmIH_RB_BASE_HI, (ih->gpu_addr >> 40) & 0xff);
>   
> +	ih_rb_cntl = RREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL);
> +	ih_rb_cntl = vega10_ih_rb_cntl(ih, ih_rb_cntl);
> +	ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, RPTR_REARM,
> +				   !!adev->irq.msi_enabled);
>   	WREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL, ih_rb_cntl);
>   
>   	/* set the writeback address whether it's enabled or not */
> @@ -131,18 +182,51 @@ static int vega10_ih_irq_init(struct amdgpu_device *adev)
>   
>   	ih_doorbell_rtpr = RREG32_SOC15(OSSSYS, 0, mmIH_DOORBELL_RPTR);
>   	if (adev->irq.ih.use_doorbell) {
> -		ih_doorbell_rtpr = REG_SET_FIELD(ih_doorbell_rtpr, IH_DOORBELL_RPTR,
> -						 OFFSET, adev->irq.ih.doorbell_index);
> -		ih_doorbell_rtpr = REG_SET_FIELD(ih_doorbell_rtpr, IH_DOORBELL_RPTR,
> +		ih_doorbell_rtpr = REG_SET_FIELD(ih_doorbell_rtpr,
> +						 IH_DOORBELL_RPTR, OFFSET,
> +						 adev->irq.ih.doorbell_index);
> +		ih_doorbell_rtpr = REG_SET_FIELD(ih_doorbell_rtpr,
> +						 IH_DOORBELL_RPTR,
>   						 ENABLE, 1);
>   	} else {
> -		ih_doorbell_rtpr = REG_SET_FIELD(ih_doorbell_rtpr, IH_DOORBELL_RPTR,
> +		ih_doorbell_rtpr = REG_SET_FIELD(ih_doorbell_rtpr,
> +						 IH_DOORBELL_RPTR,
>   						 ENABLE, 0);
>   	}
>   	WREG32_SOC15(OSSSYS, 0, mmIH_DOORBELL_RPTR, ih_doorbell_rtpr);
>   	adev->nbio_funcs->ih_doorbell_range(adev, adev->irq.ih.use_doorbell,
>   					    adev->irq.ih.doorbell_index);
>   
> +	ih = &adev->irq.ih1;
> +	if (ih->ring_size) {
> +		WREG32_SOC15(OSSSYS, 0, mmIH_RB_BASE_RING1, ih->gpu_addr >> 8);
> +		WREG32_SOC15(OSSSYS, 0, mmIH_RB_BASE_HI_RING1,
> +			     (ih->gpu_addr >> 40) & 0xff);
> +
> +		ih_rb_cntl = RREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING1);
> +		ih_rb_cntl = vega10_ih_rb_cntl(ih, ih_rb_cntl);
> +		WREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING1, ih_rb_cntl);
> +
> +		/* set rptr, wptr to 0 */
> +		WREG32_SOC15(OSSSYS, 0, mmIH_RB_RPTR_RING1, 0);
> +		WREG32_SOC15(OSSSYS, 0, mmIH_RB_WPTR_RING1, 0);
> +	}
> +
> +	ih = &adev->irq.ih2;
> +	if (ih->ring_size) {
> +		WREG32_SOC15(OSSSYS, 0, mmIH_RB_BASE_RING2, ih->gpu_addr >> 8);
> +		WREG32_SOC15(OSSSYS, 0, mmIH_RB_BASE_HI_RING2,
> +			     (ih->gpu_addr >> 40) & 0xff);
> +
> +		ih_rb_cntl = RREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING1);
> +		ih_rb_cntl = vega10_ih_rb_cntl(ih, ih_rb_cntl);
> +		WREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING2, ih_rb_cntl);
> +
> +		/* set rptr, wptr to 0 */
> +		WREG32_SOC15(OSSSYS, 0, mmIH_RB_RPTR_RING2, 0);
> +		WREG32_SOC15(OSSSYS, 0, mmIH_RB_WPTR_RING2, 0);
> +	}
> +
>   	tmp = RREG32_SOC15(OSSSYS, 0, mmIH_STORM_CLIENT_LIST_CNTL);
>   	tmp = REG_SET_FIELD(tmp, IH_STORM_CLIENT_LIST_CNTL,
>   			    CLIENT18_IS_STORM_CLIENT, 1);
> @@ -299,6 +383,15 @@ static int vega10_ih_sw_init(void *handle)
>   	if (r)
>   		return r;
>   
> +	r = amdgpu_ih_ring_init(adev, &adev->irq.ih1, PAGE_SIZE, true);
> +	if (r)
> +		return r;
> +
> +	r = amdgpu_ih_ring_init(adev, &adev->irq.ih2, PAGE_SIZE, true);
> +	if (r)
> +		return r;
> +
> +	/* TODO add doorbell for IH1 & IH2 as well */
>   	adev->irq.ih.use_doorbell = true;
>   	adev->irq.ih.doorbell_index = adev->doorbell_index.ih << 1;
>   
> @@ -312,6 +405,8 @@ static int vega10_ih_sw_fini(void *handle)
>   	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
>   
>   	amdgpu_irq_fini(adev);
> +	amdgpu_ih_ring_fini(adev, &adev->irq.ih2);
> +	amdgpu_ih_ring_fini(adev, &adev->irq.ih1);
>   	amdgpu_ih_ring_fini(adev, &adev->irq.ih);
>   
>   	return 0;
On Wed, Jan 9, 2019 at 8:12 AM Christian König
<ckoenig.leichtzumerken@gmail.com> wrote:
>
> The entries are ignored for now, but it at least stops crashing the
> hardware when somebody tries to push something to the other IH rings.
>
> v2: limit ring size, add TODO comment
> v3: only program rings if they are actually allocated
>
> Signed-off-by: Christian König <christian.koenig@amd.com>
> ---
>  drivers/gpu/drm/amd/amdgpu/amdgpu_irq.h |   4 +-
>  drivers/gpu/drm/amd/amdgpu/vega10_ih.c  | 143 ++++++++++++++++++++----
>  2 files changed, 121 insertions(+), 26 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.h
> index f6ce171cb8aa..7e06fa64321a 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.h
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.h
> @@ -87,8 +87,8 @@ struct amdgpu_irq {
>         /* status, etc. */
>         bool                            msi_enabled; /* msi enabled */
>
> -       /* interrupt ring */
> -       struct amdgpu_ih_ring           ih;
> +       /* interrupt rings */
> +       struct amdgpu_ih_ring           ih, ih1, ih2;
>         const struct amdgpu_ih_funcs    *ih_funcs;
>
>         /* gen irq stuff */
> diff --git a/drivers/gpu/drm/amd/amdgpu/vega10_ih.c b/drivers/gpu/drm/amd/amdgpu/vega10_ih.c
> index 562701939d3e..eea5530d2961 100644
> --- a/drivers/gpu/drm/amd/amdgpu/vega10_ih.c
> +++ b/drivers/gpu/drm/amd/amdgpu/vega10_ih.c
> @@ -50,6 +50,22 @@ static void vega10_ih_enable_interrupts(struct amdgpu_device *adev)
>         ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, ENABLE_INTR, 1);
>         WREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL, ih_rb_cntl);
>         adev->irq.ih.enabled = true;
> +
> +       if (adev->irq.ih1.ring_size) {
> +               ih_rb_cntl = RREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING1);
> +               ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL_RING1,
> +                                          RB_ENABLE, 1);
> +               WREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING1, ih_rb_cntl);
> +               adev->irq.ih1.enabled = true;
> +       }
> +
> +       if (adev->irq.ih2.ring_size) {
> +               ih_rb_cntl = RREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING2);
> +               ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL_RING2,
> +                                          RB_ENABLE, 1);
> +               WREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING2, ih_rb_cntl);
> +               adev->irq.ih2.enabled = true;
> +       }
>  }
>
>  /**
> @@ -71,6 +87,53 @@ static void vega10_ih_disable_interrupts(struct amdgpu_device *adev)
>         WREG32_SOC15(OSSSYS, 0, mmIH_RB_WPTR, 0);
>         adev->irq.ih.enabled = false;
>         adev->irq.ih.rptr = 0;
> +
> +       if (adev->irq.ih1.ring_size) {
> +               ih_rb_cntl = RREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING1);
> +               ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL_RING1,
> +                                          RB_ENABLE, 0);
> +               WREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING1, ih_rb_cntl);
> +               /* set rptr, wptr to 0 */
> +               WREG32_SOC15(OSSSYS, 0, mmIH_RB_RPTR_RING1, 0);
> +               WREG32_SOC15(OSSSYS, 0, mmIH_RB_WPTR_RING1, 0);
> +               adev->irq.ih1.enabled = false;
> +               adev->irq.ih1.rptr = 0;
> +       }
> +
> +       if (adev->irq.ih2.ring_size) {
> +               ih_rb_cntl = RREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING2);
> +               ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL_RING2,
> +                                          RB_ENABLE, 0);
> +               WREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING2, ih_rb_cntl);
> +               /* set rptr, wptr to 0 */
> +               WREG32_SOC15(OSSSYS, 0, mmIH_RB_RPTR_RING2, 0);
> +               WREG32_SOC15(OSSSYS, 0, mmIH_RB_WPTR_RING2, 0);
> +               adev->irq.ih2.enabled = false;
> +               adev->irq.ih2.rptr = 0;
> +       }
> +}
> +
> +static uint32_t vega10_ih_rb_cntl(struct amdgpu_ih_ring *ih, uint32_t ih_rb_cntl)
> +{
> +       int rb_bufsz = order_base_2(ih->ring_size / 4);
> +
> +       ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL,
> +                                  MC_SPACE, ih->use_bus_addr ? 1 : 4);
> +       ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL,
> +                                  WPTR_OVERFLOW_CLEAR, 1);
> +       ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL,
> +                                  WPTR_OVERFLOW_ENABLE, 1);
> +       ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, RB_SIZE, rb_bufsz);
> +       /* Ring Buffer write pointer writeback. If enabled, IH_RB_WPTR register
> +        * value is written to memory
> +        */
> +       ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL,
> +                                  WPTR_WRITEBACK_ENABLE, 1);
> +       ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, MC_SNOOP, 1);
> +       ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, MC_RO, 0);
> +       ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, MC_VMID, 0);
> +
> +       return ih_rb_cntl;
>  }
>
>  /**
> @@ -86,9 +149,8 @@ static void vega10_ih_disable_interrupts(struct amdgpu_device *adev)
>   */
>  static int vega10_ih_irq_init(struct amdgpu_device *adev)
>  {
> -       struct amdgpu_ih_ring *ih = &adev->irq.ih;
> +       struct amdgpu_ih_ring *ih;
>         int ret = 0;
> -       int rb_bufsz;
>         u32 ih_rb_cntl, ih_doorbell_rtpr;
>         u32 tmp;
>
> @@ -97,26 +159,15 @@ static int vega10_ih_irq_init(struct amdgpu_device *adev)
>
>         adev->nbio_funcs->ih_control(adev);
>
> -       ih_rb_cntl = RREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL);
> +       ih = &adev->irq.ih;
>         /* Ring Buffer base. [39:8] of 40-bit address of the beginning of the ring buffer*/
> -       WREG32_SOC15(OSSSYS, 0, mmIH_RB_BASE, adev->irq.ih.gpu_addr >> 8);
> -       WREG32_SOC15(OSSSYS, 0, mmIH_RB_BASE_HI,
> -                    (adev->irq.ih.gpu_addr >> 40) & 0xff);
> -       ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, MC_SPACE,
> -                                  ih->use_bus_addr ? 1 : 4);
> -       rb_bufsz = order_base_2(adev->irq.ih.ring_size / 4);
> -       ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 1);
> -       ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, WPTR_OVERFLOW_ENABLE, 1);
> -       ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, RB_SIZE, rb_bufsz);
> -       /* Ring Buffer write pointer writeback. If enabled, IH_RB_WPTR register value is written to memory */
> -       ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, WPTR_WRITEBACK_ENABLE, 1);
> -       ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, MC_SNOOP, 1);
> -       ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, MC_RO, 0);
> -       ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, MC_VMID, 0);
> -
> -       if (adev->irq.msi_enabled)
> -               ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, RPTR_REARM, 1);
> +       WREG32_SOC15(OSSSYS, 0, mmIH_RB_BASE, ih->gpu_addr >> 8);
> +       WREG32_SOC15(OSSSYS, 0, mmIH_RB_BASE_HI, (ih->gpu_addr >> 40) & 0xff);
>
> +       ih_rb_cntl = RREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL);
> +       ih_rb_cntl = vega10_ih_rb_cntl(ih, ih_rb_cntl);
> +       ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, RPTR_REARM,
> +                                  !!adev->irq.msi_enabled);
>         WREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL, ih_rb_cntl);
>
>         /* set the writeback address whether it's enabled or not */
> @@ -131,18 +182,51 @@ static int vega10_ih_irq_init(struct amdgpu_device *adev)
>
>         ih_doorbell_rtpr = RREG32_SOC15(OSSSYS, 0, mmIH_DOORBELL_RPTR);
>         if (adev->irq.ih.use_doorbell) {
> -               ih_doorbell_rtpr = REG_SET_FIELD(ih_doorbell_rtpr, IH_DOORBELL_RPTR,
> -                                                OFFSET, adev->irq.ih.doorbell_index);
> -               ih_doorbell_rtpr = REG_SET_FIELD(ih_doorbell_rtpr, IH_DOORBELL_RPTR,
> +               ih_doorbell_rtpr = REG_SET_FIELD(ih_doorbell_rtpr,
> +                                                IH_DOORBELL_RPTR, OFFSET,
> +                                                adev->irq.ih.doorbell_index);
> +               ih_doorbell_rtpr = REG_SET_FIELD(ih_doorbell_rtpr,
> +                                                IH_DOORBELL_RPTR,
>                                                  ENABLE, 1);
>         } else {
> -               ih_doorbell_rtpr = REG_SET_FIELD(ih_doorbell_rtpr, IH_DOORBELL_RPTR,
> +               ih_doorbell_rtpr = REG_SET_FIELD(ih_doorbell_rtpr,
> +                                                IH_DOORBELL_RPTR,
>                                                  ENABLE, 0);
>         }
>         WREG32_SOC15(OSSSYS, 0, mmIH_DOORBELL_RPTR, ih_doorbell_rtpr);
>         adev->nbio_funcs->ih_doorbell_range(adev, adev->irq.ih.use_doorbell,
>                                             adev->irq.ih.doorbell_index);
>
> +       ih = &adev->irq.ih1;
> +       if (ih->ring_size) {
> +               WREG32_SOC15(OSSSYS, 0, mmIH_RB_BASE_RING1, ih->gpu_addr >> 8);
> +               WREG32_SOC15(OSSSYS, 0, mmIH_RB_BASE_HI_RING1,
> +                            (ih->gpu_addr >> 40) & 0xff);
> +
> +               ih_rb_cntl = RREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING1);
> +               ih_rb_cntl = vega10_ih_rb_cntl(ih, ih_rb_cntl);
> +               WREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING1, ih_rb_cntl);
> +
> +               /* set rptr, wptr to 0 */
> +               WREG32_SOC15(OSSSYS, 0, mmIH_RB_RPTR_RING1, 0);
> +               WREG32_SOC15(OSSSYS, 0, mmIH_RB_WPTR_RING1, 0);
> +       }
> +
> +       ih = &adev->irq.ih2;
> +       if (ih->ring_size) {
> +               WREG32_SOC15(OSSSYS, 0, mmIH_RB_BASE_RING2, ih->gpu_addr >> 8);
> +               WREG32_SOC15(OSSSYS, 0, mmIH_RB_BASE_HI_RING2,
> +                            (ih->gpu_addr >> 40) & 0xff);
> +
> +               ih_rb_cntl = RREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING1);
> +               ih_rb_cntl = vega10_ih_rb_cntl(ih, ih_rb_cntl);
> +               WREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING2, ih_rb_cntl);
> +
> +               /* set rptr, wptr to 0 */
> +               WREG32_SOC15(OSSSYS, 0, mmIH_RB_RPTR_RING2, 0);
> +               WREG32_SOC15(OSSSYS, 0, mmIH_RB_WPTR_RING2, 0);
> +       }
> +
>         tmp = RREG32_SOC15(OSSSYS, 0, mmIH_STORM_CLIENT_LIST_CNTL);
>         tmp = REG_SET_FIELD(tmp, IH_STORM_CLIENT_LIST_CNTL,
>                             CLIENT18_IS_STORM_CLIENT, 1);
> @@ -299,6 +383,15 @@ static int vega10_ih_sw_init(void *handle)
>         if (r)
>                 return r;
>
> +       r = amdgpu_ih_ring_init(adev, &adev->irq.ih1, PAGE_SIZE, true);
> +       if (r)
> +               return r;
> +
> +       r = amdgpu_ih_ring_init(adev, &adev->irq.ih2, PAGE_SIZE, true);
> +       if (r)
> +               return r;

We may want to limit this to vega10 for now until we've tested other
soc15 asics more thoroughly with the changes.  Maybe add a
has_secondary_ih_rings flag like we did for the paging queue on SDMA.
Then we can set it early_init on a per-asic basis.  With that fixed
the series is:
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>

Alex

> +
> +       /* TODO add doorbell for IH1 & IH2 as well */
>         adev->irq.ih.use_doorbell = true;
>         adev->irq.ih.doorbell_index = adev->doorbell_index.ih << 1;
>
> @@ -312,6 +405,8 @@ static int vega10_ih_sw_fini(void *handle)
>         struct amdgpu_device *adev = (struct amdgpu_device *)handle;
>
>         amdgpu_irq_fini(adev);
> +       amdgpu_ih_ring_fini(adev, &adev->irq.ih2);
> +       amdgpu_ih_ring_fini(adev, &adev->irq.ih1);
>         amdgpu_ih_ring_fini(adev, &adev->irq.ih);
>
>         return 0;
> --
> 2.17.1
>
> _______________________________________________
> amd-gfx mailing list
> amd-gfx@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/amd-gfx
The series is Reviewed-by: Felix Kuehling <Felix.Kuehling@amd.com>

-----Original Message-----
From: Christian König <ckoenig.leichtzumerken@gmail.com> 

Sent: Friday, January 11, 2019 7:02 AM
To: amd-gfx@lists.freedesktop.org; Deucher, Alexander <Alexander.Deucher@amd.com>; Kuehling, Felix <Felix.Kuehling@amd.com>
Subject: Re: [PATCH 1/3] drm/amdgpu: enable IH ring 1 and ring 2 v3

Am 09.01.19 um 14:12 schrieb Christian König:
> The entries are ignored for now, but it at least stops crashing the 

> hardware when somebody tries to push something to the other IH rings.

>

> v2: limit ring size, add TODO comment

> v3: only program rings if they are actually allocated

>

> Signed-off-by: Christian König <christian.koenig@amd.com>


Ping Alex & Felix any more comments on this series?

Christian.

> ---

>   drivers/gpu/drm/amd/amdgpu/amdgpu_irq.h |   4 +-

>   drivers/gpu/drm/amd/amdgpu/vega10_ih.c  | 143 ++++++++++++++++++++----

>   2 files changed, 121 insertions(+), 26 deletions(-)

>

> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.h 

> b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.h

> index f6ce171cb8aa..7e06fa64321a 100644

> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.h

> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.h

> @@ -87,8 +87,8 @@ struct amdgpu_irq {

>   	/* status, etc. */

>   	bool				msi_enabled; /* msi enabled */

>   

> -	/* interrupt ring */

> -	struct amdgpu_ih_ring		ih;

> +	/* interrupt rings */

> +	struct amdgpu_ih_ring		ih, ih1, ih2;

>   	const struct amdgpu_ih_funcs	*ih_funcs;

>   

>   	/* gen irq stuff */

> diff --git a/drivers/gpu/drm/amd/amdgpu/vega10_ih.c 

> b/drivers/gpu/drm/amd/amdgpu/vega10_ih.c

> index 562701939d3e..eea5530d2961 100644

> --- a/drivers/gpu/drm/amd/amdgpu/vega10_ih.c

> +++ b/drivers/gpu/drm/amd/amdgpu/vega10_ih.c

> @@ -50,6 +50,22 @@ static void vega10_ih_enable_interrupts(struct amdgpu_device *adev)

>   	ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, ENABLE_INTR, 1);

>   	WREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL, ih_rb_cntl);

>   	adev->irq.ih.enabled = true;

> +

> +	if (adev->irq.ih1.ring_size) {

> +		ih_rb_cntl = RREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING1);

> +		ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL_RING1,

> +					   RB_ENABLE, 1);

> +		WREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING1, ih_rb_cntl);

> +		adev->irq.ih1.enabled = true;

> +	}

> +

> +	if (adev->irq.ih2.ring_size) {

> +		ih_rb_cntl = RREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING2);

> +		ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL_RING2,

> +					   RB_ENABLE, 1);

> +		WREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING2, ih_rb_cntl);

> +		adev->irq.ih2.enabled = true;

> +	}

>   }

>   

>   /**

> @@ -71,6 +87,53 @@ static void vega10_ih_disable_interrupts(struct amdgpu_device *adev)

>   	WREG32_SOC15(OSSSYS, 0, mmIH_RB_WPTR, 0);

>   	adev->irq.ih.enabled = false;

>   	adev->irq.ih.rptr = 0;

> +

> +	if (adev->irq.ih1.ring_size) {

> +		ih_rb_cntl = RREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING1);

> +		ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL_RING1,

> +					   RB_ENABLE, 0);

> +		WREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING1, ih_rb_cntl);

> +		/* set rptr, wptr to 0 */

> +		WREG32_SOC15(OSSSYS, 0, mmIH_RB_RPTR_RING1, 0);

> +		WREG32_SOC15(OSSSYS, 0, mmIH_RB_WPTR_RING1, 0);

> +		adev->irq.ih1.enabled = false;

> +		adev->irq.ih1.rptr = 0;

> +	}

> +

> +	if (adev->irq.ih2.ring_size) {

> +		ih_rb_cntl = RREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING2);

> +		ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL_RING2,

> +					   RB_ENABLE, 0);

> +		WREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING2, ih_rb_cntl);

> +		/* set rptr, wptr to 0 */

> +		WREG32_SOC15(OSSSYS, 0, mmIH_RB_RPTR_RING2, 0);

> +		WREG32_SOC15(OSSSYS, 0, mmIH_RB_WPTR_RING2, 0);

> +		adev->irq.ih2.enabled = false;

> +		adev->irq.ih2.rptr = 0;

> +	}

> +}

> +

> +static uint32_t vega10_ih_rb_cntl(struct amdgpu_ih_ring *ih, uint32_t 

> +ih_rb_cntl) {

> +	int rb_bufsz = order_base_2(ih->ring_size / 4);

> +

> +	ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL,

> +				   MC_SPACE, ih->use_bus_addr ? 1 : 4);

> +	ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL,

> +				   WPTR_OVERFLOW_CLEAR, 1);

> +	ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL,

> +				   WPTR_OVERFLOW_ENABLE, 1);

> +	ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, RB_SIZE, rb_bufsz);

> +	/* Ring Buffer write pointer writeback. If enabled, IH_RB_WPTR register

> +	 * value is written to memory

> +	 */

> +	ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL,

> +				   WPTR_WRITEBACK_ENABLE, 1);

> +	ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, MC_SNOOP, 1);

> +	ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, MC_RO, 0);

> +	ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, MC_VMID, 0);

> +

> +	return ih_rb_cntl;

>   }

>   

>   /**

> @@ -86,9 +149,8 @@ static void vega10_ih_disable_interrupts(struct amdgpu_device *adev)

>    */

>   static int vega10_ih_irq_init(struct amdgpu_device *adev)

>   {

> -	struct amdgpu_ih_ring *ih = &adev->irq.ih;

> +	struct amdgpu_ih_ring *ih;

>   	int ret = 0;

> -	int rb_bufsz;

>   	u32 ih_rb_cntl, ih_doorbell_rtpr;

>   	u32 tmp;

>   

> @@ -97,26 +159,15 @@ static int vega10_ih_irq_init(struct 

> amdgpu_device *adev)

>   

>   	adev->nbio_funcs->ih_control(adev);

>   

> -	ih_rb_cntl = RREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL);

> +	ih = &adev->irq.ih;

>   	/* Ring Buffer base. [39:8] of 40-bit address of the beginning of the ring buffer*/

> -	WREG32_SOC15(OSSSYS, 0, mmIH_RB_BASE, adev->irq.ih.gpu_addr >> 8);

> -	WREG32_SOC15(OSSSYS, 0, mmIH_RB_BASE_HI,

> -		     (adev->irq.ih.gpu_addr >> 40) & 0xff);

> -	ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, MC_SPACE,

> -				   ih->use_bus_addr ? 1 : 4);

> -	rb_bufsz = order_base_2(adev->irq.ih.ring_size / 4);

> -	ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 1);

> -	ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, WPTR_OVERFLOW_ENABLE, 1);

> -	ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, RB_SIZE, rb_bufsz);

> -	/* Ring Buffer write pointer writeback. If enabled, IH_RB_WPTR register value is written to memory */

> -	ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, WPTR_WRITEBACK_ENABLE, 1);

> -	ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, MC_SNOOP, 1);

> -	ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, MC_RO, 0);

> -	ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, MC_VMID, 0);

> -

> -	if (adev->irq.msi_enabled)

> -		ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, RPTR_REARM, 1);

> +	WREG32_SOC15(OSSSYS, 0, mmIH_RB_BASE, ih->gpu_addr >> 8);

> +	WREG32_SOC15(OSSSYS, 0, mmIH_RB_BASE_HI, (ih->gpu_addr >> 40) & 

> +0xff);

>   

> +	ih_rb_cntl = RREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL);

> +	ih_rb_cntl = vega10_ih_rb_cntl(ih, ih_rb_cntl);

> +	ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, RPTR_REARM,

> +				   !!adev->irq.msi_enabled);

>   	WREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL, ih_rb_cntl);

>   

>   	/* set the writeback address whether it's enabled or not */ @@ 

> -131,18 +182,51 @@ static int vega10_ih_irq_init(struct amdgpu_device 

> *adev)

>   

>   	ih_doorbell_rtpr = RREG32_SOC15(OSSSYS, 0, mmIH_DOORBELL_RPTR);

>   	if (adev->irq.ih.use_doorbell) {

> -		ih_doorbell_rtpr = REG_SET_FIELD(ih_doorbell_rtpr, IH_DOORBELL_RPTR,

> -						 OFFSET, adev->irq.ih.doorbell_index);

> -		ih_doorbell_rtpr = REG_SET_FIELD(ih_doorbell_rtpr, IH_DOORBELL_RPTR,

> +		ih_doorbell_rtpr = REG_SET_FIELD(ih_doorbell_rtpr,

> +						 IH_DOORBELL_RPTR, OFFSET,

> +						 adev->irq.ih.doorbell_index);

> +		ih_doorbell_rtpr = REG_SET_FIELD(ih_doorbell_rtpr,

> +						 IH_DOORBELL_RPTR,

>   						 ENABLE, 1);

>   	} else {

> -		ih_doorbell_rtpr = REG_SET_FIELD(ih_doorbell_rtpr, IH_DOORBELL_RPTR,

> +		ih_doorbell_rtpr = REG_SET_FIELD(ih_doorbell_rtpr,

> +						 IH_DOORBELL_RPTR,

>   						 ENABLE, 0);

>   	}

>   	WREG32_SOC15(OSSSYS, 0, mmIH_DOORBELL_RPTR, ih_doorbell_rtpr);

>   	adev->nbio_funcs->ih_doorbell_range(adev, adev->irq.ih.use_doorbell,

>   					    adev->irq.ih.doorbell_index);

>   

> +	ih = &adev->irq.ih1;

> +	if (ih->ring_size) {

> +		WREG32_SOC15(OSSSYS, 0, mmIH_RB_BASE_RING1, ih->gpu_addr >> 8);

> +		WREG32_SOC15(OSSSYS, 0, mmIH_RB_BASE_HI_RING1,

> +			     (ih->gpu_addr >> 40) & 0xff);

> +

> +		ih_rb_cntl = RREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING1);

> +		ih_rb_cntl = vega10_ih_rb_cntl(ih, ih_rb_cntl);

> +		WREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING1, ih_rb_cntl);

> +

> +		/* set rptr, wptr to 0 */

> +		WREG32_SOC15(OSSSYS, 0, mmIH_RB_RPTR_RING1, 0);

> +		WREG32_SOC15(OSSSYS, 0, mmIH_RB_WPTR_RING1, 0);

> +	}

> +

> +	ih = &adev->irq.ih2;

> +	if (ih->ring_size) {

> +		WREG32_SOC15(OSSSYS, 0, mmIH_RB_BASE_RING2, ih->gpu_addr >> 8);

> +		WREG32_SOC15(OSSSYS, 0, mmIH_RB_BASE_HI_RING2,

> +			     (ih->gpu_addr >> 40) & 0xff);

> +

> +		ih_rb_cntl = RREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING1);

> +		ih_rb_cntl = vega10_ih_rb_cntl(ih, ih_rb_cntl);

> +		WREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING2, ih_rb_cntl);

> +

> +		/* set rptr, wptr to 0 */

> +		WREG32_SOC15(OSSSYS, 0, mmIH_RB_RPTR_RING2, 0);

> +		WREG32_SOC15(OSSSYS, 0, mmIH_RB_WPTR_RING2, 0);

> +	}

> +

>   	tmp = RREG32_SOC15(OSSSYS, 0, mmIH_STORM_CLIENT_LIST_CNTL);

>   	tmp = REG_SET_FIELD(tmp, IH_STORM_CLIENT_LIST_CNTL,

>   			    CLIENT18_IS_STORM_CLIENT, 1); @@ -299,6 +383,15 @@ static int 

> vega10_ih_sw_init(void *handle)

>   	if (r)

>   		return r;

>   

> +	r = amdgpu_ih_ring_init(adev, &adev->irq.ih1, PAGE_SIZE, true);

> +	if (r)

> +		return r;

> +

> +	r = amdgpu_ih_ring_init(adev, &adev->irq.ih2, PAGE_SIZE, true);

> +	if (r)

> +		return r;

> +

> +	/* TODO add doorbell for IH1 & IH2 as well */

>   	adev->irq.ih.use_doorbell = true;

>   	adev->irq.ih.doorbell_index = adev->doorbell_index.ih << 1;

>   

> @@ -312,6 +405,8 @@ static int vega10_ih_sw_fini(void *handle)

>   	struct amdgpu_device *adev = (struct amdgpu_device *)handle;

>   

>   	amdgpu_irq_fini(adev);

> +	amdgpu_ih_ring_fini(adev, &adev->irq.ih2);

> +	amdgpu_ih_ring_fini(adev, &adev->irq.ih1);

>   	amdgpu_ih_ring_fini(adev, &adev->irq.ih);

>   

>   	return 0;