On 7/2/26 10:40, Srinivasan Shanmugam wrote:
> AMDGPU already has a global PASID xarray used by the PASID allocator.
> 
> Currently allocated PASIDs store a dummy value in that xarray.
> 
> Add helper functions so DRM-owned PASIDs can store and retrieve their
> owning DRM file-private object.
> 
> This prepares for using:
> 
>       PASID -> fpriv -> vm
> 
> instead of the separate per-device:
> 
>       PASID -> vm
> 
> mapping.
> 
> v3: (per Christian)
> - Document that PASID allocation is intentionally kept separate
>   from fpriv registration because fpriv is not fully initialized
>   when the PASID is allocated.
> 
> Cc: Alex Deucher <[email protected]>
> Suggested-by: Christian König <[email protected]>
> Signed-off-by: Srinivasan Shanmugam <[email protected]>
> ---
>  drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c | 126 ++++++++++++++++++++++++
>  drivers/gpu/drm/amd/amdgpu/amdgpu_ids.h |  13 +++
>  2 files changed, 139 insertions(+)
> 
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c 
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c
> index 684f40fce73f..5333937f0d04 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c
> @@ -78,6 +78,132 @@ int amdgpu_pasid_alloc(unsigned int bits)
>       return pasid;
>  }
>  
> +/**
> + * amdgpu_pasid_set_fpriv - register the DRM owner of a PASID
> + * @pasid: PASID allocated for the DRM client
> + * @fpriv: owning DRM file-private object
> + *
> + * PASID allocation is intentionally kept separate from owner
> + * registration because the DRM file-private object is not fully
> + * initialized when the PASID is allocated.
> + *
> + * This helper replaces the temporary allocation marker with the
> + * initialized DRM owner.

Taking a closer look at I think we should rather re-structure the fprif init 
code to allocate the pasid later.

> + */
> +int amdgpu_pasid_set_fpriv(u32 pasid,
> +                        struct amdgpu_fpriv *fpriv)
> +{
> +     unsigned long flags;
> +     void *entry;
> +     int r = 0;
> +
> +     if (!pasid || !fpriv)
> +             return -EINVAL;
> +
> +     xa_lock_irqsave(&amdgpu_pasid_xa, flags);
> +
> +     entry = xa_load(&amdgpu_pasid_xa, pasid);
> +
> +     if (!entry) {
> +             r = -ENOENT;
> +             goto unlock;
> +     }
> +
> +     if (!xa_is_value(entry)) {
> +             r = -EBUSY;
> +             goto unlock;
> +     }
> +
> +     entry = __xa_store(&amdgpu_pasid_xa, pasid,
> +                        fpriv, GFP_ATOMIC);
> +     r = xa_err(entry);
> +
> +unlock:
> +     xa_unlock_irqrestore(&amdgpu_pasid_xa, flags);
> +
> +     return r;
> +}
> +
> +/**
> + * amdgpu_pasid_clear_fpriv - unregister PASID ownership
> + * @pasid: PASID whose owner is being removed
> + * @fpriv: DRM file-private object owning the PASID
> + *
> + * Restore the PASID entry back to the allocation marker before the
> + * DRM file-private object is destroyed.

That should clearly be merged into 
amdgpu_pasid_free()/amdgpu_pasid_free_delayed() instead.

Regards,
Christian.

> + */
> +void amdgpu_pasid_clear_fpriv(u32 pasid,
> +                           struct amdgpu_fpriv *fpriv)
> +{
> +     unsigned long flags;
> +     void *entry;
> +
> +     if (!pasid || !fpriv)
> +             return;
> +
> +     xa_lock_irqsave(&amdgpu_pasid_xa, flags);
> +
> +     entry = xa_load(&amdgpu_pasid_xa, pasid);
> +
> +     if (entry == fpriv)
> +             __xa_store(&amdgpu_pasid_xa,
> +                        pasid,
> +                        xa_mk_value(0),
> +                        GFP_ATOMIC);
> +
> +     xa_unlock_irqrestore(&amdgpu_pasid_xa, flags);
> +}
> +
> +/**
> + * amdgpu_pasid_lock - acquire the global PASID xarray lock
> + * @flags: storage for interrupt state
> + *
> + * Acquire the global PASID xarray lock with interrupts disabled.
> + * The saved interrupt state must be passed to
> + * amdgpu_pasid_unlock().
> + */
> +void amdgpu_pasid_lock(unsigned long *flags)
> +{
> +     xa_lock_irqsave(&amdgpu_pasid_xa, *flags);
> +}
> +
> +/**
> + * amdgpu_pasid_unlock - release the global PASID xarray lock
> + * @flags: interrupt state returned by amdgpu_pasid_lock()
> + *
> + * Release the global PASID xarray lock and restore the previous
> + * interrupt state.
> + */
> +void amdgpu_pasid_unlock(unsigned long flags)
> +{
> +     xa_unlock_irqrestore(&amdgpu_pasid_xa, flags);
> +}
> +
> +/**
> + * amdgpu_pasid_get_fpriv_locked - get fpriv from PASID
> + * @pasid: PASID to resolve
> + *
> + * Caller must hold the PASID XA lock.
> + *
> + * The returned pointer is only protected by the PASID XA lock.
> + * Callers must not continue using it after dropping the lock
> + * unless additional lifetime protection exists.
> + *
> + * This intentionally does not add kref/RCU lifetime handling.
> + */
> +     struct amdgpu_fpriv *
> +amdgpu_pasid_get_fpriv_locked(u32 pasid)
> +{
> +     void *entry;
> +
> +     entry = xa_load(&amdgpu_pasid_xa, pasid);
> +
> +     if (!entry || xa_is_value(entry))
> +             return NULL;
> +
> +     return entry;
> +}
> +
>  /**
>   * amdgpu_pasid_free - Free a PASID
>   * @pasid: PASID to free
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.h 
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.h
> index a57919478d3b..220a0ba0cfb6 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.h
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.h
> @@ -38,6 +38,7 @@ struct amdgpu_vm;
>  struct amdgpu_ring;
>  struct amdgpu_sync;
>  struct amdgpu_job;
> +struct amdgpu_fpriv;
>  
>  struct amdgpu_vmid {
>       struct list_head        list;
> @@ -92,4 +93,16 @@ void amdgpu_vmid_reset_all(struct amdgpu_device *adev);
>  void amdgpu_vmid_mgr_init(struct amdgpu_device *adev);
>  void amdgpu_vmid_mgr_fini(struct amdgpu_device *adev);
>  
> +int amdgpu_pasid_set_fpriv(u32 pasid,
> +                        struct amdgpu_fpriv *fpriv);
> +
> +void amdgpu_pasid_clear_fpriv(u32 pasid,
> +                           struct amdgpu_fpriv *fpriv);
> +
> +void amdgpu_pasid_lock(unsigned long *flags);
> +void amdgpu_pasid_unlock(unsigned long flags);
> +
> +struct amdgpu_fpriv *
> +amdgpu_pasid_get_fpriv_locked(u32 pasid);
> +
>  #endif

Reply via email to