Am Freitag, dem 08.05.2026 um 18:05 +0000 schrieb Ziyi Guo:
> The IOMMU mapping for a userptr BO was installed with a hard-coded
> ETNAVIV_PROT_READ | ETNAVIV_PROT_WRITE, ignoring the read-only
> attribute set when the BO was created without ETNA_USERPTR_WRITE.
> Build the prot mask from etnaviv_obj->userptr.ro so MMUv2 clears
> MMUv2_PTE_WRITEABLE for read-only userptr BOs.
> 
> MMUv1 PTEs carry no R/W bits and its fast path skips the MMU, so
> read-only cannot be enforced there; refuse such a mapping with
> -ENODEV.

I don't think it's a good idea to completely reject those mappings on
MMUv1. We can always force a BO to be mapped through the
translation/protection region of the MMUv1 by adding the
ETNA_BO_FORCE_MMU flag, which is what you might want to do when
constructing a ro userptr BO.

Regards,
Lucas

> 
> Fixes: a8c21a5451d8 ("drm/etnaviv: add initial etnaviv DRM driver")
> Signed-off-by: Ziyi Guo <[email protected]>
> ---
>  drivers/gpu/drm/etnaviv/etnaviv_mmu.c | 10 +++++++++-
>  1 file changed, 9 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/etnaviv/etnaviv_mmu.c 
> b/drivers/gpu/drm/etnaviv/etnaviv_mmu.c
> index e3572461b599..28f26d60ac05 100644
> --- a/drivers/gpu/drm/etnaviv/etnaviv_mmu.c
> +++ b/drivers/gpu/drm/etnaviv/etnaviv_mmu.c
> @@ -269,10 +269,18 @@ int etnaviv_iommu_map_gem(struct etnaviv_iommu_context 
> *context,
>  {
>       struct sg_table *sgt = etnaviv_obj->sgt;
>       struct drm_mm_node *node;
> +     int prot = ETNAVIV_PROT_READ;
>       int ret;
>  
>       lockdep_assert_held(&etnaviv_obj->lock);
>  
> +     if (!etnaviv_obj->userptr.ptr || !etnaviv_obj->userptr.ro)
> +             prot |= ETNAVIV_PROT_WRITE;
> +
> +     if (etnaviv_obj->userptr.ptr && etnaviv_obj->userptr.ro &&
> +         context->global->version == ETNAVIV_IOMMU_V1)
> +             return -ENODEV;
> +
>       mutex_lock(&context->lock);
>  
>       /* v1 MMU can optimize single entry (contiguous) scatterlists */
> @@ -301,7 +309,7 @@ int etnaviv_iommu_map_gem(struct etnaviv_iommu_context 
> *context,
>  
>       mapping->iova = node->start;
>       ret = etnaviv_iommu_map(context, node->start, etnaviv_obj->size, sgt,
> -                             ETNAVIV_PROT_READ | ETNAVIV_PROT_WRITE);
> +                             prot);
>  
>       if (ret < 0) {
>               drm_mm_remove_node(node);

Reply via email to