[PATCH 07/11] drm/amdgpu: enable IH ring 1 and ring 2 v2

Alex Deucher alexdeucher at gmail.com
Fri Nov 30 16:01:12 UTC 2018


On Fri, Nov 30, 2018 at 7:36 AM Christian König
<ckoenig.leichtzumerken at 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
>
> Signed-off-by: Christian König <christian.koenig at amd.com>

We may want to guard this with some flag so we can easily disable it
(like we did for the paging queue) in case we run into issues on any
asics.

Alex

> ---
>  drivers/gpu/drm/amd/amdgpu/amdgpu_irq.h |   4 +-
>  drivers/gpu/drm/amd/amdgpu/vega10_ih.c  | 129 +++++++++++++++++++-----
>  2 files changed, 107 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 3e9ebb0de94d..562fd036bb9e 100644
> --- a/drivers/gpu/drm/amd/amdgpu/vega10_ih.c
> +++ b/drivers/gpu/drm/amd/amdgpu/vega10_ih.c
> @@ -50,6 +50,16 @@ 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;
> +
> +       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;
> +
> +       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 +81,47 @@ 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;
> +
> +       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;
> +
> +       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 +137,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 +147,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 +170,49 @@ 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;
> +       /* Ring Buffer base. [39:8] of 40-bit address of the beginning of the ring buffer*/
> +       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;
> +       /* Ring Buffer base. [39:8] of 40-bit address of the beginning of the ring buffer*/
> +       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);
> @@ -290,6 +360,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;
>
> @@ -303,6 +382,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 at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/amd-gfx


More information about the amd-gfx mailing list