在 2025-08-16星期六的 15:47 +0800,Icenowy Zheng写道:
> Unfortunately the GC620 GPU seems to have broken PTA capibility, and
> switching page table ID in command stream after it's running won't
> work.
> As directly switching mtlb isn't working either, there will be no
> reliable way to switch page table in the command stream, and a shared
> context, like iommuv1, is needed.
> 
> Add support for this shared context situation. Shared context is set
> when the broken PTA is known, and the context allocation code will be
> made short circuit when a shared context is set.
> 
> Signed-off-by: Icenowy Zheng <u...@icenowy.me>
> ---
>  drivers/gpu/drm/etnaviv/etnaviv_iommu_v2.c | 8 ++++++++
>  drivers/gpu/drm/etnaviv/etnaviv_mmu.c      | 1 +
>  drivers/gpu/drm/etnaviv/etnaviv_mmu.h      | 2 ++
>  3 files changed, 11 insertions(+)
> 
> diff --git a/drivers/gpu/drm/etnaviv/etnaviv_iommu_v2.c
> b/drivers/gpu/drm/etnaviv/etnaviv_iommu_v2.c
> index 5654a604c70cf..960ba3d659dc5 100644
> --- a/drivers/gpu/drm/etnaviv/etnaviv_iommu_v2.c
> +++ b/drivers/gpu/drm/etnaviv/etnaviv_iommu_v2.c

Well, I forgot to clean shared_context in etnaviv_iommuv2_free() when
the shared context is torn down...

> @@ -273,6 +273,12 @@ etnaviv_iommuv2_context_alloc(struct
> etnaviv_iommu_global *global)
>         struct etnaviv_iommu_context *context;
>  
>         mutex_lock(&global->lock);
> +       if (global->shared_context) {
> +               context = global->shared_context;
> +               etnaviv_iommu_context_get(context);
> +               mutex_unlock(&global->lock);
> +               return context;
> +       }
>  
>         v2_context = vzalloc(sizeof(*v2_context));
>         if (!v2_context)
> @@ -301,6 +307,8 @@ etnaviv_iommuv2_context_alloc(struct
> etnaviv_iommu_global *global)
>         mutex_init(&context->lock);
>         INIT_LIST_HEAD(&context->mappings);
>         drm_mm_init(&context->mm, SZ_4K, (u64)SZ_1G * 4 - SZ_4K);
> +       if (global->v2.broken_pta)
> +               global->shared_context = context;
>  
>         mutex_unlock(&global->lock);
>         return context;
> diff --git a/drivers/gpu/drm/etnaviv/etnaviv_mmu.c
> b/drivers/gpu/drm/etnaviv/etnaviv_mmu.c
> index df5192083b201..a0f9c950504e0 100644
> --- a/drivers/gpu/drm/etnaviv/etnaviv_mmu.c
> +++ b/drivers/gpu/drm/etnaviv/etnaviv_mmu.c
> @@ -504,6 +504,7 @@ int etnaviv_iommu_global_init(struct etnaviv_gpu
> *gpu)
>         memset32(global->bad_page_cpu, 0xdead55aa, SZ_4K /
> sizeof(u32));
>  
>         if (version == ETNAVIV_IOMMU_V2) {
> +               global->v2.broken_pta = gpu->identity.model ==
> chipModel_GC620;
>                 global->v2.pta_cpu = dma_alloc_wc(dev,
> ETNAVIV_PTA_SIZE,
>                                                &global->v2.pta_dma,
> GFP_KERNEL);
>                 if (!global->v2.pta_cpu)
> diff --git a/drivers/gpu/drm/etnaviv/etnaviv_mmu.h
> b/drivers/gpu/drm/etnaviv/etnaviv_mmu.h
> index 2ec4acda02bc6..5627d2a0d0237 100644
> --- a/drivers/gpu/drm/etnaviv/etnaviv_mmu.h
> +++ b/drivers/gpu/drm/etnaviv/etnaviv_mmu.h
> @@ -55,6 +55,8 @@ struct etnaviv_iommu_global {
>                 u64 *pta_cpu;
>                 dma_addr_t pta_dma;
>                 DECLARE_BITMAP(pta_alloc, ETNAVIV_PTA_ENTRIES);
> +               /* Whether runtime switching page table ID will fail
> */
> +               bool broken_pta;
>         } v2;
>  };
>  

Reply via email to