[AMD Official Use Only - Internal Distribution Only]

Hi ,Yintian & Christian 
I still don't understand why we need this complicated  change here . Why can 
not just allocate few more extra space in the ring for each read  and use the 
space to store the output value  ?   

Regards
Shaoyun.liu
   

-----Original Message-----
From: amd-gfx <amd-gfx-boun...@lists.freedesktop.org> On Behalf Of Christian 
König
Sent: Wednesday, April 22, 2020 8:42 AM
To: Tao, Yintian <yintian....@amd.com>; Liu, Monk <monk....@amd.com>; Kuehling, 
Felix <felix.kuehl...@amd.com>
Cc: amd-gfx@lists.freedesktop.org
Subject: Re: [PATCH] drm/amdgpu: request reg_val_offs each kiq read reg

Am 22.04.20 um 14:36 schrieb Yintian Tao:
> According to the current kiq read register method, there will be race 
> condition when using KIQ to read register if multiple clients want to 
> read at same time just like the expample below:
> 1. client-A start to read REG-0 throguh KIQ 2. client-A poll the 
> seqno-0 3. client-B start to read REG-1 through KIQ 4. client-B poll 
> the seqno-1 5. the kiq complete these two read operation 6. client-A 
> to read the register at the wb buffer and
>     get REG-1 value
>
> Therefore, use amdgpu_device_wb_get() to request reg_val_offs for each 
> kiq read register.
>
> v2: fix the error remove
>
> Signed-off-by: Yintian Tao <yt...@amd.com>
> ---
>   drivers/gpu/drm/amd/amdgpu/amdgpu.h      |  2 +-
>   drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c  | 19 ++++++++++-------
>   drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h  |  1 -
>   drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h |  5 +++--
>   drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c   |  7 +++---
>   drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c    |  7 +++---
>   drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c    | 27 ++++++++++++++++--------
>   7 files changed, 41 insertions(+), 27 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h 
> b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> index 4e1d4cfe7a9f..7ee5a4da398a 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> @@ -526,7 +526,7 @@ static inline void amdgpu_set_ib_value(struct 
> amdgpu_cs_parser *p,
>   /*
>    * Writeback
>    */
> -#define AMDGPU_MAX_WB 128    /* Reserve at most 128 WB slots for 
> amdgpu-owned rings. */
> +#define AMDGPU_MAX_WB 256    /* Reserve at most 256 WB slots for 
> amdgpu-owned rings. */
>   
>   struct amdgpu_wb {
>       struct amdgpu_bo        *wb_obj;
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c 
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c
> index ea576b4260a4..d5a59d7c48d6 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c
> @@ -304,10 +304,6 @@ int amdgpu_gfx_kiq_init_ring(struct amdgpu_device 
> *adev,
>   
>       spin_lock_init(&kiq->ring_lock);
>   
> -     r = amdgpu_device_wb_get(adev, &kiq->reg_val_offs);
> -     if (r)
> -             return r;
> -
>       ring->adev = NULL;
>       ring->ring_obj = NULL;
>       ring->use_doorbell = true;
> @@ -331,7 +327,6 @@ int amdgpu_gfx_kiq_init_ring(struct amdgpu_device 
> *adev,
>   
>   void amdgpu_gfx_kiq_free_ring(struct amdgpu_ring *ring)
>   {
> -     amdgpu_device_wb_free(ring->adev, ring->adev->gfx.kiq.reg_val_offs);
>       amdgpu_ring_fini(ring);
>   }
>   
> @@ -672,15 +667,20 @@ uint32_t amdgpu_kiq_rreg(struct amdgpu_device *adev, 
> uint32_t reg)
>   {
>       signed long r, cnt = 0;
>       unsigned long flags;
> -     uint32_t seq;
> +     uint32_t seq, reg_val_offs = 0, value = 0;
>       struct amdgpu_kiq *kiq = &adev->gfx.kiq;
>       struct amdgpu_ring *ring = &kiq->ring;
>   
>       BUG_ON(!ring->funcs->emit_rreg);
>   
>       spin_lock_irqsave(&kiq->ring_lock, flags);
> +     if (amdgpu_device_wb_get(adev, &reg_val_offs)) {
> +             spin_unlock_irqrestore(&kiq->ring_lock, flags);
> +             pr_err("critical bug! too more kiq readers\n");

Typo here, this should probably read  "too many kiq readers".

But I don't think we need the error message here anyway, the failed_kiq_read 
label also prints an error.

With that fixed the patch is Reviewed-by: Christian König 
<christian.koe...@amd.com>.

Thanks,
Christian.

> +             goto failed_kiq_read;
> +     }
>       amdgpu_ring_alloc(ring, 32);
> -     amdgpu_ring_emit_rreg(ring, reg);
> +     amdgpu_ring_emit_rreg(ring, reg, reg_val_offs);
>       amdgpu_fence_emit_polling(ring, &seq);
>       amdgpu_ring_commit(ring);
>       spin_unlock_irqrestore(&kiq->ring_lock, flags); @@ -707,7 +707,10 
> @@ uint32_t amdgpu_kiq_rreg(struct amdgpu_device *adev, uint32_t reg)
>       if (cnt > MAX_KIQ_REG_TRY)
>               goto failed_kiq_read;
>   
> -     return adev->wb.wb[kiq->reg_val_offs];
> +     mb();
> +     value = adev->wb.wb[reg_val_offs];
> +     amdgpu_device_wb_free(adev, reg_val_offs);
> +     return value;
>   
>   failed_kiq_read:
>       pr_err("failed to read reg:%x\n", reg); diff --git 
> a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h 
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h
> index 634746829024..ee698f0246d8 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h
> @@ -103,7 +103,6 @@ struct amdgpu_kiq {
>       struct amdgpu_ring      ring;
>       struct amdgpu_irq_src   irq;
>       const struct kiq_pm4_funcs *pmf;
> -     uint32_t                        reg_val_offs;
>   };
>   
>   /*
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h 
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h
> index f61664ee4940..137d3d2b46e8 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h
> @@ -181,7 +181,8 @@ struct amdgpu_ring_funcs {
>       void (*end_use)(struct amdgpu_ring *ring);
>       void (*emit_switch_buffer) (struct amdgpu_ring *ring);
>       void (*emit_cntxcntl) (struct amdgpu_ring *ring, uint32_t flags);
> -     void (*emit_rreg)(struct amdgpu_ring *ring, uint32_t reg);
> +     void (*emit_rreg)(struct amdgpu_ring *ring, uint32_t reg,
> +                       uint32_t reg_val_offs);
>       void (*emit_wreg)(struct amdgpu_ring *ring, uint32_t reg, uint32_t val);
>       void (*emit_reg_wait)(struct amdgpu_ring *ring, uint32_t reg,
>                             uint32_t val, uint32_t mask); @@ -265,7 +266,7 @@ 
> struct 
> amdgpu_ring {
>   #define amdgpu_ring_emit_hdp_flush(r) (r)->funcs->emit_hdp_flush((r))
>   #define amdgpu_ring_emit_switch_buffer(r) 
> (r)->funcs->emit_switch_buffer((r))
>   #define amdgpu_ring_emit_cntxcntl(r, d) 
> (r)->funcs->emit_cntxcntl((r), (d)) -#define amdgpu_ring_emit_rreg(r, 
> d) (r)->funcs->emit_rreg((r), (d))
> +#define amdgpu_ring_emit_rreg(r, d, o) (r)->funcs->emit_rreg((r), 
> +(d), (o))
>   #define amdgpu_ring_emit_wreg(r, d, v) (r)->funcs->emit_wreg((r), (d), (v))
>   #define amdgpu_ring_emit_reg_wait(r, d, v, m) 
> (r)->funcs->emit_reg_wait((r), (d), (v), (m))
>   #define amdgpu_ring_emit_reg_write_reg_wait(r, d0, d1, v, m) 
> (r)->funcs->emit_reg_write_reg_wait((r), (d0), (d1), (v), (m)) diff 
> --git a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c 
> b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
> index 0a03e2ad5d95..0a3d3bc9d441 100644
> --- a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
> +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
> @@ -7594,7 +7594,8 @@ static void gfx_v10_0_ring_emit_frame_cntl(struct 
> amdgpu_ring *ring, bool start,
>       amdgpu_ring_write(ring, v | FRAME_CMD(start ? 0 : 1));
>   }
>   
> -static void gfx_v10_0_ring_emit_rreg(struct amdgpu_ring *ring, 
> uint32_t reg)
> +static void gfx_v10_0_ring_emit_rreg(struct amdgpu_ring *ring, uint32_t reg,
> +                                  uint32_t reg_val_offs)
>   {
>       struct amdgpu_device *adev = ring->adev;
>       struct amdgpu_kiq *kiq = &adev->gfx.kiq; @@ -7606,9 +7607,9 @@ 
> static void gfx_v10_0_ring_emit_rreg(struct amdgpu_ring *ring, uint32_t reg)
>       amdgpu_ring_write(ring, reg);
>       amdgpu_ring_write(ring, 0);
>       amdgpu_ring_write(ring, lower_32_bits(adev->wb.gpu_addr +
> -                             kiq->reg_val_offs * 4));
> +                             reg_val_offs * 4));
>       amdgpu_ring_write(ring, upper_32_bits(adev->wb.gpu_addr +
> -                             kiq->reg_val_offs * 4));
> +                             reg_val_offs * 4));
>   }
>   
>   static void gfx_v10_0_ring_emit_wreg(struct amdgpu_ring *ring, 
> uint32_t reg, diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c 
> b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
> index fc6c2f2bc76c..ccfa65c3cb5a 100644
> --- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
> +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
> @@ -6383,7 +6383,8 @@ static void gfx_v8_0_ring_emit_patch_cond_exec(struct 
> amdgpu_ring *ring, unsigne
>               ring->ring[offset] = (ring->ring_size >> 2) - offset + cur;
>   }
>   
> -static void gfx_v8_0_ring_emit_rreg(struct amdgpu_ring *ring, 
> uint32_t reg)
> +static void gfx_v8_0_ring_emit_rreg(struct amdgpu_ring *ring, uint32_t reg,
> +                                 uint32_t reg_val_offs)
>   {
>       struct amdgpu_device *adev = ring->adev;
>       struct amdgpu_kiq *kiq = &adev->gfx.kiq; @@ -6395,9 +6396,9 @@ 
> static void gfx_v8_0_ring_emit_rreg(struct amdgpu_ring *ring, uint32_t reg)
>       amdgpu_ring_write(ring, reg);
>       amdgpu_ring_write(ring, 0);
>       amdgpu_ring_write(ring, lower_32_bits(adev->wb.gpu_addr +
> -                             kiq->reg_val_offs * 4));
> +                             reg_val_offs * 4));
>       amdgpu_ring_write(ring, upper_32_bits(adev->wb.gpu_addr +
> -                             kiq->reg_val_offs * 4));
> +                             reg_val_offs * 4));
>   }
>   
>   static void gfx_v8_0_ring_emit_wreg(struct amdgpu_ring *ring, 
> uint32_t reg, diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c 
> b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
> index 84fcf842316d..0b706f908d9a 100644
> --- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
> +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
> @@ -4043,13 +4043,19 @@ static uint64_t gfx_v9_0_kiq_read_clock(struct 
> amdgpu_device *adev)
>   {
>       signed long r, cnt = 0;
>       unsigned long flags;
> -     uint32_t seq;
> +     uint32_t seq, reg_val_offs = 0;
> +     uint64_t value = 0;
>       struct amdgpu_kiq *kiq = &adev->gfx.kiq;
>       struct amdgpu_ring *ring = &kiq->ring;
>   
>       BUG_ON(!ring->funcs->emit_rreg);
>   
>       spin_lock_irqsave(&kiq->ring_lock, flags);
> +     if (amdgpu_device_wb_get(adev, &reg_val_offs)) {
> +             spin_unlock_irqrestore(&kiq->ring_lock, flags);
> +             pr_err("critical bug! too more kiq readers\n");
> +             goto failed_kiq_read;
> +     }
>       amdgpu_ring_alloc(ring, 32);
>       amdgpu_ring_write(ring, PACKET3(PACKET3_COPY_DATA, 4));
>       amdgpu_ring_write(ring, 9 |     /* src: register*/
> @@ -4059,9 +4065,9 @@ static uint64_t gfx_v9_0_kiq_read_clock(struct 
> amdgpu_device *adev)
>       amdgpu_ring_write(ring, 0);
>       amdgpu_ring_write(ring, 0);
>       amdgpu_ring_write(ring, lower_32_bits(adev->wb.gpu_addr +
> -                             kiq->reg_val_offs * 4));
> +                             reg_val_offs * 4));
>       amdgpu_ring_write(ring, upper_32_bits(adev->wb.gpu_addr +
> -                             kiq->reg_val_offs * 4));
> +                             reg_val_offs * 4));
>       amdgpu_fence_emit_polling(ring, &seq);
>       amdgpu_ring_commit(ring);
>       spin_unlock_irqrestore(&kiq->ring_lock, flags); @@ -4088,8 +4094,11 
> @@ static uint64_t gfx_v9_0_kiq_read_clock(struct amdgpu_device *adev)
>       if (cnt > MAX_KIQ_REG_TRY)
>               goto failed_kiq_read;
>   
> -     return (uint64_t)adev->wb.wb[kiq->reg_val_offs] |
> -             (uint64_t)adev->wb.wb[kiq->reg_val_offs + 1 ] << 32ULL;
> +     mb();
> +     value = (uint64_t)adev->wb.wb[reg_val_offs] |
> +             (uint64_t)adev->wb.wb[reg_val_offs + 1 ] << 32ULL;
> +     amdgpu_device_wb_free(adev, reg_val_offs);
> +     return value;
>   
>   failed_kiq_read:
>       pr_err("failed to read gpu clock\n"); @@ -5482,10 +5491,10 @@ 
> static void gfx_v9_0_ring_emit_patch_cond_exec(struct amdgpu_ring *ring, 
> unsigne
>               ring->ring[offset] = (ring->ring_size>>2) - offset + cur;
>   }
>   
> -static void gfx_v9_0_ring_emit_rreg(struct amdgpu_ring *ring, 
> uint32_t reg)
> +static void gfx_v9_0_ring_emit_rreg(struct amdgpu_ring *ring, uint32_t reg,
> +                                 uint32_t reg_val_offs)
>   {
>       struct amdgpu_device *adev = ring->adev;
> -     struct amdgpu_kiq *kiq = &adev->gfx.kiq;
>   
>       amdgpu_ring_write(ring, PACKET3(PACKET3_COPY_DATA, 4));
>       amdgpu_ring_write(ring, 0 |     /* src: register*/
> @@ -5494,9 +5503,9 @@ static void gfx_v9_0_ring_emit_rreg(struct amdgpu_ring 
> *ring, uint32_t reg)
>       amdgpu_ring_write(ring, reg);
>       amdgpu_ring_write(ring, 0);
>       amdgpu_ring_write(ring, lower_32_bits(adev->wb.gpu_addr +
> -                             kiq->reg_val_offs * 4));
> +                             reg_val_offs * 4));
>       amdgpu_ring_write(ring, upper_32_bits(adev->wb.gpu_addr +
> -                             kiq->reg_val_offs * 4));
> +                             reg_val_offs * 4));
>   }
>   
>   static void gfx_v9_0_ring_emit_wreg(struct amdgpu_ring *ring, 
> uint32_t reg,

_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Flists.freedesktop.org%2Fmailman%2Flistinfo%2Famd-gfx&amp;data=02%7C01%7CShaoyun.Liu%40amd.com%7C9d960d5be3f141f44f0608d7e6ba8962%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637231561176171819&amp;sdata=OnDtxn%2FTPnmzigVKJEAF37fQdUcfDMWB1xcbrQbDcIc%3D&amp;reserved=0
_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

Reply via email to