[PATCH 1/4] drm/amdgpu: enable IH ring 1 and ring 2 for navi

Felix Kuehling felix.kuehling at amd.com
Thu Mar 26 18:51:49 UTC 2020


Patches 1-3 are

Reviewed-by: Felix Kuehling <Felix.Kuehling at amd.com>

See my separate reply to patch 4.

Thanks,
   Felix

On 2020-03-24 17:57, Alex Sierra wrote:
> Support added into IH to enable ring1 and ring2 for navi10_ih.
>
> Signed-off-by: Alex Sierra <alex.sierra at amd.com>
> ---
>   drivers/gpu/drm/amd/amdgpu/navi10_ih.c | 205 +++++++++++++++++++++++--
>   1 file changed, 189 insertions(+), 16 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/navi10_ih.c b/drivers/gpu/drm/amd/amdgpu/navi10_ih.c
> index e08245a446fc..0c0ba572d7a3 100644
> --- a/drivers/gpu/drm/amd/amdgpu/navi10_ih.c
> +++ b/drivers/gpu/drm/amd/amdgpu/navi10_ih.c
> @@ -51,6 +51,22 @@ static void navi10_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;
> +	}
>   }
>   
>   /**
> @@ -72,6 +88,31 @@ static void navi10_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 navi10_ih_rb_cntl(struct amdgpu_ih_ring *ih, uint32_t ih_rb_cntl)
> @@ -97,6 +138,25 @@ static uint32_t navi10_ih_rb_cntl(struct amdgpu_ih_ring *ih, uint32_t ih_rb_cntl
>   	return ih_rb_cntl;
>   }
>   
> +static uint32_t navi10_ih_doorbell_rptr(struct amdgpu_ih_ring *ih)
> +{
> +	u32 ih_doorbell_rtpr = 0;
> +
> +	if (ih->use_doorbell) {
> +		ih_doorbell_rtpr = REG_SET_FIELD(ih_doorbell_rtpr,
> +						 IH_DOORBELL_RPTR, OFFSET,
> +						 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,
> +						 ENABLE, 0);
> +	}
> +	return ih_doorbell_rtpr;
> +}
> +
>   /**
>    * navi10_ih_irq_init - init and enable the interrupt ring
>    *
> @@ -111,7 +171,7 @@ static uint32_t navi10_ih_rb_cntl(struct amdgpu_ih_ring *ih, uint32_t ih_rb_cntl
>   static int navi10_ih_irq_init(struct amdgpu_device *adev)
>   {
>   	struct amdgpu_ih_ring *ih = &adev->irq.ih;
> -	u32 ih_rb_cntl, ih_doorbell_rtpr, ih_chicken;
> +	u32 ih_rb_cntl, ih_chicken;
>   	u32 tmp;
>   
>   	/* disable irqs */
> @@ -149,22 +209,52 @@ static int navi10_ih_irq_init(struct amdgpu_device *adev)
>   	WREG32_SOC15(OSSSYS, 0, mmIH_RB_RPTR, 0);
>   	WREG32_SOC15(OSSSYS, 0, mmIH_RB_WPTR, 0);
>   
> -	ih_doorbell_rtpr = RREG32_SOC15(OSSSYS, 0, mmIH_DOORBELL_RPTR);
> -	if (ih->use_doorbell) {
> -		ih_doorbell_rtpr = REG_SET_FIELD(ih_doorbell_rtpr,
> -						 IH_DOORBELL_RPTR, OFFSET,
> -						 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, ENABLE, 0);
> -	}
> -	WREG32_SOC15(OSSSYS, 0, mmIH_DOORBELL_RPTR, ih_doorbell_rtpr);
> +	WREG32_SOC15(OSSSYS, 0, mmIH_DOORBELL_RPTR,
> +			navi10_ih_doorbell_rptr(ih));
>   
>   	adev->nbio.funcs->ih_doorbell_range(adev, ih->use_doorbell,
>   					    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 = navi10_ih_rb_cntl(ih, ih_rb_cntl);
> +		ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL,
> +					   WPTR_OVERFLOW_ENABLE, 0);
> +		ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL,
> +					   RB_FULL_DRAIN_ENABLE, 1);
> +		WREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING1, ih_rb_cntl);
> +		/* set rptr, wptr to 0 */
> +		WREG32_SOC15(OSSSYS, 0, mmIH_RB_WPTR_RING1, 0);
> +		WREG32_SOC15(OSSSYS, 0, mmIH_RB_RPTR_RING1, 0);
> +
> +		WREG32_SOC15(OSSSYS, 0, mmIH_DOORBELL_RPTR_RING1,
> +				navi10_ih_doorbell_rptr(ih));
> +	}
> +
> +	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_RING2);
> +		ih_rb_cntl = navi10_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_WPTR_RING2, 0);
> +		WREG32_SOC15(OSSSYS, 0, mmIH_RB_RPTR_RING2, 0);
> +
> +		WREG32_SOC15(OSSSYS, 0, mmIH_DOORBELL_RPTR_RING2,
> +			     navi10_ih_doorbell_rptr(ih));
> +	}
> +
> +
>   	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);
> @@ -217,7 +307,15 @@ static u32 navi10_ih_get_wptr(struct amdgpu_device *adev,
>   	if (!REG_GET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW))
>   		goto out;
>   
> -	reg = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_WPTR);
> +	if (ih == &adev->irq.ih)
> +		reg = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_WPTR);
> +	else if (ih == &adev->irq.ih1)
> +		reg = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_WPTR_RING1);
> +	else if (ih == &adev->irq.ih2)
> +		reg = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_WPTR_RING2);
> +	else
> +		BUG();
> +
>   	wptr = RREG32_NO_KIQ(reg);
>   	if (!REG_GET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW))
>   		goto out;
> @@ -233,7 +331,15 @@ static u32 navi10_ih_get_wptr(struct amdgpu_device *adev,
>   		 wptr, ih->rptr, tmp);
>   	ih->rptr = tmp;
>   
> -	reg = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_CNTL);
> +	if (ih == &adev->irq.ih)
> +		reg = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_CNTL);
> +	else if (ih == &adev->irq.ih1)
> +		reg = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_CNTL_RING1);
> +	else if (ih == &adev->irq.ih2)
> +		reg = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_CNTL_RING2);
> +	else
> +		BUG();
> +
>   	tmp = RREG32_NO_KIQ(reg);
>   	tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 1);
>   	WREG32_NO_KIQ(reg, tmp);
> @@ -333,8 +439,52 @@ static void navi10_ih_set_rptr(struct amdgpu_device *adev,
>   
>   		if (amdgpu_sriov_vf(adev))
>   			navi10_ih_irq_rearm(adev, ih);
> -	} else
> +	} else if (ih == &adev->irq.ih) {
>   		WREG32_SOC15(OSSSYS, 0, mmIH_RB_RPTR, ih->rptr);
> +	} else if (ih == &adev->irq.ih1) {
> +		WREG32_SOC15(OSSSYS, 0, mmIH_RB_RPTR_RING1, ih->rptr);
> +	} else if (ih == &adev->irq.ih2) {
> +		WREG32_SOC15(OSSSYS, 0, mmIH_RB_RPTR_RING2, ih->rptr);
> +	}
> +}
> +
> +/**
> + * navi10_ih_self_irq - dispatch work for ring 1 and 2
> + *
> + * @adev: amdgpu_device pointer
> + * @source: irq source
> + * @entry: IV with WPTR update
> + *
> + * Update the WPTR from the IV and schedule work to handle the entries.
> + */
> +static int navi10_ih_self_irq(struct amdgpu_device *adev,
> +			      struct amdgpu_irq_src *source,
> +			      struct amdgpu_iv_entry *entry)
> +{
> +	uint32_t wptr = cpu_to_le32(entry->src_data[0]);
> +
> +	switch (entry->ring_id) {
> +	case 1:
> +		*adev->irq.ih1.wptr_cpu = wptr;
> +		schedule_work(&adev->irq.ih1_work);
> +		break;
> +	case 2:
> +		*adev->irq.ih2.wptr_cpu = wptr;
> +		schedule_work(&adev->irq.ih2_work);
> +		break;
> +	default: break;
> +	}
> +	return 0;
> +}
> +
> +static const struct amdgpu_irq_src_funcs navi10_ih_self_irq_funcs = {
> +	.process = navi10_ih_self_irq,
> +};
> +
> +static void navi10_ih_set_self_irq_funcs(struct amdgpu_device *adev)
> +{
> +	adev->irq.self_irq.num_types = 0;
> +	adev->irq.self_irq.funcs = &navi10_ih_self_irq_funcs;
>   }
>   
>   static int navi10_ih_early_init(void *handle)
> @@ -342,6 +492,7 @@ static int navi10_ih_early_init(void *handle)
>   	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
>   
>   	navi10_ih_set_interrupt_funcs(adev);
> +	navi10_ih_set_self_irq_funcs(adev);
>   	return 0;
>   }
>   
> @@ -351,6 +502,12 @@ static int navi10_ih_sw_init(void *handle)
>   	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
>   	bool use_bus_addr;
>   
> +	r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_IH, 0,
> +				&adev->irq.self_irq);
> +
> +	if (r)
> +		return r;
> +
>   	/* use gpu virtual address for ih ring
>   	 * until ih_checken is programmed to allow
>   	 * use bus address for ih ring by psp bl */
> @@ -363,6 +520,20 @@ static int navi10_ih_sw_init(void *handle)
>   	adev->irq.ih.use_doorbell = true;
>   	adev->irq.ih.doorbell_index = adev->doorbell_index.ih << 1;
>   
> +	r = amdgpu_ih_ring_init(adev, &adev->irq.ih1, PAGE_SIZE, true);
> +	if (r)
> +		return r;
> +
> +	adev->irq.ih1.use_doorbell = true;
> +	adev->irq.ih1.doorbell_index = (adev->doorbell_index.ih + 1) << 1;
> +
> +	r = amdgpu_ih_ring_init(adev, &adev->irq.ih2, PAGE_SIZE, true);
> +	if (r)
> +		return r;
> +
> +	adev->irq.ih2.use_doorbell = true;
> +	adev->irq.ih2.doorbell_index = (adev->doorbell_index.ih + 2) << 1;
> +
>   	r = amdgpu_irq_init(adev);
>   
>   	return r;
> @@ -373,6 +544,8 @@ static int navi10_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;


More information about the amd-gfx mailing list