On Fri, Aug 21, 2026 at 1:44 PM Paul Hollinsky
<[email protected]> wrote:
>
> Commit 0be72be03ca7 ("drm/msm: Switch to generic PAS TZ APIs") replaced
> the qcom_scm_is_available() check in adreno_zap_shader_load() with
> qcom_pas_is_available(). These are not equivalent: the former reports
> whether the SCM transport is up, the latter whether the TrustZone
> firmware implements the peripheral authentication service.
>
> On SC7180 Chromebooks (trogdor) TZ does not implement PAS at all. SCM
> call-availability queries return 0 for every PAS command while other
> services answer normally:
>
>   svc 0x06 cmd 0x01 IS_CALL_AVAIL    -> 1
>   svc 0x02 cmd 0x01 PAS_INIT_IMAGE   -> 0
>   svc 0x02 cmd 0x05 PAS_AUTH_RESET   -> 0
>   svc 0x02 cmd 0x07 PAS_IS_SUPPORTED -> 0
>   svc 0x0c cmd 0x16 MP_ASSIGN        -> 1
>   svc 0x05 cmd 0x01 IO_READ          -> 1
>
> so qcom_scm_probe() never registers a PAS backend and
> qcom_pas_is_available() is false for the lifetime of the boot.
>
> That on its own need not matter, because sc7180-trogdor.dtsi does
> /delete-node/ &gpu_zap_shader;, and the intended path for such a board
> is for zap_shader_load_mdt() to find no zap-shader child, clear
> zap_available, return -ENODEV, and let the caller fall back to
> SECVID_TRUST_CNTL.
>
> The problem is the ordering. zap_available is a static initialised to
> true and is only ever cleared inside zap_shader_load_mdt(), but
> adreno_zap_shader_load() consults PAS before calling it. The discovery
> that decides whether a zap shader is needed at all can therefore never
> run, the flag is never cleared, and every call returns -EPROBE_DEFER:
>
>   adreno 5000000.gpu: [drm:adreno_zap_shader_load] *ERROR* PAS is not 
> available
>   msm_dpu ae01000.display-controller: [drm:adreno_load_gpu] *ERROR* gpu hw 
> init failed: -517
>
> Nothing retries that deferral, either. adreno_zap_shader_load() is
> called from a6xx_hw_init() rather than from probe, so the -EPROBE_DEFER
> is not a probe return value: it propagates up until adreno_load_gpu()
> returns NULL. load_gpu() re-attempts on every DRM open while priv->gpu
> is NULL, each open fails identically, and PAS cannot become available in
> between - which is why the error repeats and userspace stays on
> llvmpipe.
>
> Move the availability check into zap_shader_load_mdt(), behind the
> zap-shader node lookup, so the driver only consults PAS once it knows it
> needs PAS. Boards with no zap-shader node take the intended -ENODEV
> fallback without ever asking, and boards that do have one keep the
> qcom_pas_is_available() gate.
>
> Fixes: 0be72be03ca7 ("drm/msm: Switch to generic PAS TZ APIs")
> Link: 
> https://lore.kernel.org/r/[email protected]
> Signed-off-by: Paul Hollinsky <[email protected]>
> ---
> Reported and analysed in:
> https://lore.kernel.org/linux-arm-msm/[email protected]/
> Konrad agreed with this shape in
> https://lore.kernel.org/linux-arm-msm/[email protected]/
>
> 0be72be03ca7 landed in mainline during the v7.3 merge window (via the
> soc-drivers-7.3 pull), so this is based on Linus' tree. Note that
> msm-fixes and msm-next both still predate it as I write this, so it
> needs a base that includes the merge window; happy to respin against
> whatever base you prefer, and it can equally go via the qcom tree the
> culprit came through.
>
> Tested on a Lenovo IdeaPad Duet 3 (sc7180-trogdor-wormdingler) on
> next-20260805, which carries the same code: with this applied the GPU
> initialises and logs "Zap shader not enabled - using SECVID_TRUST_CNTL
> instead", and userspace gets a6xx rather than llvmpipe.
>
>  drivers/gpu/drm/msm/adreno/adreno_gpu.c | 13 ++++++-------
>  1 file changed, 6 insertions(+), 7 deletions(-)
>

Reviewed-by: Sumit Garg <[email protected]>

-Sumit

> diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c 
> b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
> index 489462065ea9..995161215ad5 100644
> --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c
> +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
> @@ -52,6 +52,12 @@ static int zap_shader_load_mdt(struct msm_gpu *gpu, const 
> char *fwname,
>                 return -ENODEV;
>         }
>
> +       /* We need PAS to be able to load the firmware */
> +       if (!qcom_pas_is_available()) {
> +               DRM_DEV_ERROR(dev, "PAS is not available\n");
> +               return -EPROBE_DEFER;
> +       }
> +
>         ret = of_reserved_mem_region_to_resource(np, 0, &r);
>         if (ret) {
>                 zap_available = false;
> @@ -170,18 +176,11 @@ static int zap_shader_load_mdt(struct msm_gpu *gpu, 
> const char *fwname,
>  int adreno_zap_shader_load(struct msm_gpu *gpu, u32 pasid)
>  {
>         struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
> -       struct platform_device *pdev = gpu->pdev;
>
>         /* Short cut if we determine the zap shader isn't available/needed */
>         if (!zap_available)
>                 return -ENODEV;
>
> -       /* We need PAS to be able to load the firmware */
> -       if (!qcom_pas_is_available()) {
> -               DRM_DEV_ERROR(&pdev->dev, "PAS is not available\n");
> -               return -EPROBE_DEFER;
> -       }
> -
>         return zap_shader_load_mdt(gpu, adreno_gpu->info->zapfw, pasid);
>  }
>
>
> base-commit: 818bebeb63dd6bf5f4e07e145f6cdbace520a34c
> --
> 2.55.0
>

Reply via email to