[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