[PATCH] drm/amdgpu: add ih waiter on process until checkpoint

Kim, Jonathan Jonathan.Kim at amd.com
Fri Mar 5 21:34:42 UTC 2021


[AMD Official Use Only - Internal Distribution Only]

> -----Original Message-----
> From: Christian König <ckoenig.leichtzumerken at gmail.com>
> Sent: Friday, March 5, 2021 3:18 PM
> To: Kim, Jonathan <Jonathan.Kim at amd.com>; amd-
> gfx at lists.freedesktop.org
> Cc: Yang, Philip <Philip.Yang at amd.com>; Kuehling, Felix
> <Felix.Kuehling at amd.com>; Koenig, Christian <Christian.Koenig at amd.com>
> Subject: Re: [PATCH] drm/amdgpu: add ih waiter on process until checkpoint
>
> [CAUTION: External Email]
>
> Am 05.03.21 um 21:11 schrieb Jonathan Kim:
> > Add IH function to allow caller to wait until ring entries are
> > processed until the checkpoint write pointer.
> >
> > This will be primarily used by HMM to drain pending page fault
> > interrupts before memory unmap to prevent HMM from handling stale
> interrupts.
> >
> > v2: Update title and description to clarify use.
> > Add rptr/wptr wrap counter checks to guarantee ring entries are
> > processed until the checkpoint.
>
> First of all as I said please use a wait_event, busy waiting is a clear NAK.

Who would do the wake though?  Are you suggesting wake be done in amdgpu_ih_process?  Or is waiting happening by the caller and this should go somewhere higher (like amdgpu_amdkfd for example)?

>
> >
> > Signed-off-by: Jonathan Kim <jonathan.kim at amd.com>
> > ---
> >   drivers/gpu/drm/amd/amdgpu/amdgpu_ih.c | 68
> +++++++++++++++++++++++++-
> >   drivers/gpu/drm/amd/amdgpu/amdgpu_ih.h |  2 +
> >   2 files changed, 69 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ih.c
> > b/drivers/gpu/drm/amd/amdgpu/amdgpu_ih.c
> > index dc852af4f3b7..954518b4fb79 100644
> > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ih.c
> > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ih.c
> > @@ -22,7 +22,7 @@
> >    */
> >
> >   #include <linux/dma-mapping.h>
> > -
> > +#include <linux/processor.h>
> >   #include "amdgpu.h"
> >   #include "amdgpu_ih.h"
> >
> > @@ -160,6 +160,72 @@ void amdgpu_ih_ring_write(struct
> amdgpu_ih_ring *ih, const uint32_t *iv,
> >       }
> >   }
> >
> > +/**
> > + * amdgpu_ih_wait_on_checkpoint_process - wait to process IVs up to
> > +checkpoint
> > + *
> > + * @adev: amdgpu_device pointer
> > + * @ih: ih ring to process
> > + *
> > + * Used to ensure ring has processed IVs up to the checkpoint write
> pointer.
> > + */
> > +int amdgpu_ih_wait_on_checkpoint_process(struct amdgpu_device
> *adev,
> > +                                     struct amdgpu_ih_ring *ih) {
> > +     u64 rptr_check, wptr_check, rptr_wrap = 0, wptr_wrap = 0;
> > +     u32 prev_rptr, prev_wptr;
> > +
> > +     if (!ih->enabled || adev->shutdown)
> > +             return -ENODEV;
> > +
> > +     prev_wptr = amdgpu_ih_get_wptr(adev, ih);
> > +     /* Order wptr with rptr. */
> > +     rmb();
> > +     prev_rptr = READ_ONCE(ih->rptr);
> > +     rptr_check = prev_rptr | (rptr_wrap << 32);
> > +     wptr_check = prev_wptr | (wptr_wrap << 32);
>
> Hui what? That check doesn't even make remotely sense to me.

Can you clarify what you meant by creating a new 64 bit compare?
Snip from your last response:

"This way you do something like this:
1. get the wrap around counter.
2. get wptr
3. get rptr
4. compare the wrap around counter with the old one, if it has changed start over with #1
5. Use wrap around counter and rptr/wptr to come up with 64bit values.
6. Compare wptr with rptr/wrap around counter until we are sure the IHs are processed."

From a discussion with Felix, I interpreted this as a way to guarantee rptr/wtpr ordering so that rptr monotonically follows wptr per check.
I'm assuming rptr/wptrs are 32 bits wide by the use of ptr_mask on read/write functions so a respective mask of rptr/wptr wrap count to the top 32 bits would mark how far apart the rptr and wptr are per check.

Thanks,

Jon

>
> Christian.
>
> > +
> > +     spin_begin();
> > +     while (true) {
> > +             bool rptr_wrapped = false, wptr_wrapped = false;
> > +             u32 rptr, wptr;
> > +
> > +             spin_cpu_relax();
> > +
> > +             /* Update wptr checkpoint/wrap count compare. */
> > +             wptr = amdgpu_ih_get_wptr(adev, ih);
> > +             if (wptr < prev_wptr) {
> > +                     wptr_wrap++;
> > +                     wptr_check = wptr | (wptr_wrap << 32);
> > +                     wptr_wrapped = true;
> > +             }
> > +             prev_wptr = wptr;
> > +
> > +             /* Order wptr with rptr. */
> > +             rmb();
> > +
> > +             /* Update rptr/wrap count compare. */
> > +             rptr = READ_ONCE(ih->rptr);
> > +             if (rptr < prev_rptr) {
> > +                     rptr_wrap++;
> > +                     rptr_wrapped = true;
> > +             }
> > +             rptr_check = rptr | (rptr_wrap << 32);
> > +             prev_rptr = rptr;
> > +
> > +             /* Wrapping occurred so restart. */
> > +             if (rptr_wrapped || wptr_wrapped)
> > +                     continue;
> > +
> > +             /* Exit on reaching or passing checkpoint. */
> > +             if (rptr_check >= wptr_check &&
> > +                                     rptr >= (wptr_check & ih->ptr_mask))
> > +                     break;
> > +     }
> > +     spin_end();
> > +
> > +     return 0;
> > +}
> > +
> >   /**
> >    * amdgpu_ih_process - interrupt handler
> >    *
> > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ih.h
> > b/drivers/gpu/drm/amd/amdgpu/amdgpu_ih.h
> > index 6ed4a85fc7c3..6817f0a812d2 100644
> > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ih.h
> > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ih.h
> > @@ -87,6 +87,8 @@ int amdgpu_ih_ring_init(struct amdgpu_device *adev,
> struct amdgpu_ih_ring *ih,
> >   void amdgpu_ih_ring_fini(struct amdgpu_device *adev, struct
> amdgpu_ih_ring *ih);
> >   void amdgpu_ih_ring_write(struct amdgpu_ih_ring *ih, const uint32_t *iv,
> >                         unsigned int num_dw);
> > +int amdgpu_ih_wait_on_checkpoint_process(struct amdgpu_device
> *adev,
> > +                                     struct amdgpu_ih_ring *ih);
> >   int amdgpu_ih_process(struct amdgpu_device *adev, struct
> amdgpu_ih_ring *ih);
> >   void amdgpu_ih_decode_iv_helper(struct amdgpu_device *adev,
> >                               struct amdgpu_ih_ring *ih,



More information about the amd-gfx mailing list