在 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; > }; >