All of lore.kernel.org
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Anna Maniscalco" <anna.maniscalco2000@gmail.com>
Cc: dri-devel@lists.freedesktop.org, devicetree@vger.kernel.org,
	robh@kernel.org, conor+dt@kernel.org
Subject: Re: [PATCH RFC v2 14/14] drm/msm: enable LPAC on gen70900
Date: Thu, 29 Oct 2026 14:45:45 +0000	[thread overview]
Message-ID: <sashiko-outbox-189545@kernel.org> (raw)
In-Reply-To: <20261029-descriptive-name-lpac-upstream-v2-14-a21a5c850961@gmail.com>

Thank you for your contribution! Sashiko AI review found 7 potential issue(s) to consider:
- [High] drm/msm: LPAC enabled on gen70900 without checking lpac_pdev or SW fuse
- [High] drm/msm: a6xx_active_ring() and suspend ignore lpac_rb when LPAC is enabled
- [High] drm/msm: wrong runtime PM device checked for LPAC in msm_iommu_tlb_flush_all()
- [High] drm/msm: failed parent-to-child device link skips LPAC SMMU TLB flushes
- [Medium] drm/msm: LPAC not enabled on gen70900 due to enable_lpac defaulting to 0
- [Medium] drm/msm: mismatched always-on counter reads for LPAC in a7xx_submit()
- [Medium] drm/msm/adreno: missing LPAC GX registers in A750 IFPC restore lists
--

commit 80cc6b84cce3401809bd7592d96a060ab6cb7da3
Author: Anna Maniscalco <anna.maniscalco2000@gmail.com>

drm/msm: enable LPAC on gen70900

This commit adds ADRENO_QUIRK_LPAC to the gen70900 (Adreno 750) GPU entry in
a7xx_gpus[] so that LPAC is enabled on targets known to support it.

> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_catalog.c b/drivers/gpu/drm/msm/adreno/a6xx_catalog.c
> index 5ee00eead14c8..cd1bdb54429d3 100644
> --- a/drivers/gpu/drm/msm/adreno/a6xx_catalog.c
> +++ b/drivers/gpu/drm/msm/adreno/a6xx_catalog.c
> @@ -1591,7 +1591,8 @@ static const struct adreno_info a7xx_gpus[] = {
>  		.quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT |
>  			  ADRENO_QUIRK_HAS_HW_APRIV |
>  			  ADRENO_QUIRK_PREEMPTION |
> -			  ADRENO_QUIRK_IFPC,
> +			  ADRENO_QUIRK_IFPC |
> +			  ADRENO_QUIRK_LPAC,

[Severity: Medium]
Does setting ADRENO_QUIRK_LPAC here actually enable LPAC by default on
gen70900 when enable_lpac is not explicitly passed by the user?

In drivers/gpu/drm/msm/adreno/adreno_device.c, enable_lpac is initialized to
0 instead of -1:

    int enable_lpac = 0;
    MODULE_PARM_DESC(enable_lpac, "Enable LPAC (A7xx+ only) (1=on , 0=disable, -1=auto (default))");
    module_param(enable_lpac, int, 0600);

When adreno_gpu_init() in drivers/gpu/drm/msm/adreno/adreno_gpu.c sets:

    adreno_gpu_config.has_lpac = !!(config->info->quirks & ADRENO_QUIRK_LPAC);

msm_gpu_init() in drivers/gpu/drm/msm/msm_gpu.c allocates an extra
msm_rbmemptrs slot for config->has_lpac, but then skips creating
gpu->lpac_rb because enable_lpac is 0:

    if (config->has_lpac && enable_lpac != 0) {
        gpu->lpac_rb = msm_ringbuffer_new(gpu, nr_rings, memptrs, memptrs_iova);

Meanwhile, adreno_hw_init() in drivers/gpu/drm/msm/adreno/adreno_gpu.c only
checks the quirk rather than gpu->lpac_rb:

    if (info->quirks & ADRENO_QUIRK_LPAC) {
        ret = qcom_scm_set_gpu_smmu_lpac_aperture(1);

so qcom_scm_set_gpu_smmu_lpac_aperture(1) is still called during hardware
initialization even when LPAC is disabled. Additionally, because
config->has_lpac only checks ADRENO_QUIRK_LPAC, passing enable_lpac=1 cannot
force-enable LPAC on A7xx+ targets that do not set the quirk.

Should enable_lpac be initialized to -1, and should adreno_hw_init() check
gpu->lpac_rb instead of ADRENO_QUIRK_LPAC?

[Severity: High]
What happens when booting a kernel with ADRENO_QUIRK_LPAC enabled on an
older SM8650 (gen70900) device tree that lacks the qcom,lpac child node, or
on a device where firmware fuses off LPAC?

In adreno_gpu_init() in drivers/gpu/drm/msm/adreno/adreno_gpu.c,
gpu->lpac_pdev is looked up via of_get_compatible_child(pdev->dev.of_node,
"qcom,lpac"). On an older DTB without that child node, gpu->lpac_pdev is
NULL, and adreno_iommu_create_vm() passes NULL for lpac_dev:

    mmu = msm_iommu_gpu_new(&pdev->dev,
                gpu->lpac_pdev ? &gpu->lpac_pdev->dev : NULL,
                gpu, quirks);

so iommu->lpac_domain (context bank 1) is never allocated and SID 1 remains
attached to context bank 0.

However, adreno_gpu_init() sets adreno_gpu_config.has_lpac solely from
ADRENO_QUIRK_LPAC without checking gpu->lpac_pdev, and adreno_hw_init()
unconditionally calls qcom_scm_set_gpu_smmu_lpac_aperture(1). When
gpu->lpac_rb is created and userspace submits to MSM_SUBMITQUEUE_LPAC,
a7xx_submit() -> a6xx_set_pagetable() in
drivers/gpu/drm/msm/adreno/a6xx_gpu.c executes:

    /* qcom-arm-smmu always maps asid and ctxbank 1:1 */
    ctxbank = asid = is_lpac;

and emits CP_SMMU_TABLE_UPDATE targeting uninitialized context bank 1 while
SID 1 still translates through context bank 0.

Similarly, in a6xx_gmu_secure_init() in
drivers/gpu/drm/msm/adreno/a6xx_gmu.c, REG_A7XX_CX_MISC_SW_FUSE_VALUE is
read after qcom_scm_gpu_init_regs() to check
A7XX_CX_MISC_SW_FUSE_VALUE_RAYTRACING, but A7XX_CX_MISC_SW_FUSE_VALUE_LPAC
is not checked before hw_init() writes REG_A6XX_CP_LPAC_SQE_CNTL and runs
lpac_cp_init(), which can trigger a7xx_sw_fuse_violation_irq() if firmware
disables the LPAC software fuse.

Should LPAC enablement verify both that gpu->lpac_pdev is present and that
A7XX_CX_MISC_SW_FUSE_VALUE_LPAC is set?

[Severity: High]
With ADRENO_QUIRK_LPAC enabled on gen70900 and gpu->lpac_rb exposed to
userspace, how do hangcheck, fault recovery, and suspend handle the LPAC
ring?

In drivers/gpu/drm/msm/adreno/a6xx_gpu.c, a6xx_active_ring() always returns
a6xx_gpu->cur_ring (one of gpu->rb[0..gpu->nr_rings - 1]) and never returns
gpu->lpac_rb:

    static struct msm_ringbuffer *a6xx_active_ring(struct msm_gpu *gpu)
    {
        struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
        struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);

        return a6xx_gpu->cur_ring;
    }

In drivers/gpu/drm/msm/msm_gpu.c, hangcheck_handler() only checks
gpu->funcs->active_ring(gpu) for fence progress, so a hung submission on
gpu->lpac_rb while the GFX rings are idle will not be detected by software
hangcheck.

Furthermore, if hardware fault detection (a6xx_fault_detect_irq()) or
a7xx_sw_fuse_violation_irq() triggers on an LPAC job, a6xx_fault_detect_irq()
deletes gpu->hangcheck_timer, masks all GPU interrupts by writing 0 to
REG_A6XX_RBBM_INT_0_MASK, and queues gpu->recover_work. In recover_worker()
in drivers/gpu/drm/msm/msm_gpu.c:

    struct msm_ringbuffer *cur_ring = gpu->funcs->active_ring(gpu);
    ...
    submit = find_submit(cur_ring, cur_ring->memptrs->fence + 1);

    if (!submit)
        goto out_unlock;

If cur_ring is idle when LPAC faults, recover_worker() exits to out_unlock
without calling gpu->funcs->recover(gpu) or restoring
REG_A6XX_RBBM_INT_0_MASK, leaving GPU interrupts masked and the GPU wedged.
If cur_ring has a concurrent GFX submission, recover_worker() blames that
GFX submit, marks its VM unusable, advances cur_ring->memptrs->fence while
leaving gpu->lpac_rb->memptrs->fence unadvanced:

    for (i = 0; i < gpu->nr_rings + !!gpu->lpac_rb; i++) {
        struct msm_ringbuffer *ring = i < gpu->nr_rings ? gpu->rb[i] : gpu->lpac_rb;

        uint32_t fence = ring->memptrs->fence;

        if (ring == cur_ring)
            ring->memptrs->fence = ++fence;

        msm_update_fence(ring->fctx, fence);
    }

and then replays the hung LPAC submission.

Also, in a6xx_gmu_pm_suspend() and a6xx_pm_suspend() in
drivers/gpu/drm/msm/adreno/a6xx_gpu.c, the loop clearing a6xx_gpu->shadow[]
only iterates up to gpu->nr_rings:

    if (a6xx_gpu->shadow_bo)
        for (i = 0; i < gpu->nr_rings; i++)
            a6xx_gpu->shadow[i] = 0;

leaving a6xx_gpu->shadow[gpu->nr_rings] for gpu->lpac_rb stale across
suspend.

Could hangcheck_handler(), recover_worker(), and the suspend shadow-clearing
loops be updated to account for gpu->lpac_rb?

[Severity: High]
When LPAC submissions on gen70900 switch context bank 1 (ASID 1) to
per-process TTBR0 pagetables via a6xx_set_pagetable(), will TLB invalidations
on context bank 1 be skipped when those pagetables are unmapped or destroyed?

In msm_iommu_tlb_flush_all() and msm_iommu_tlb_flush_walk() in
drivers/gpu/drm/msm/msm_iommu.c, the primary context bank flushes check
pm_runtime_get_if_in_use(pagetable->iommu_dev), whereas the LPAC flushes
check pagetable->parent->lpac_dev:

    if (pagetable->parent->lpac_dev &&
        pm_runtime_get_if_in_use(pagetable->parent->lpac_dev)) {
        adreno_smmu = dev_get_drvdata(pagetable->parent->lpac_dev);

        pagetable->tlb->tlb_flush_all((void *)adreno_smmu->cookie);

        pm_runtime_put_autosuspend(pagetable->parent->lpac_dev);
    }

However, in adreno_gpu_init() in drivers/gpu/drm/msm/adreno/adreno_gpu.c:

    if (gpu->lpac_pdev) {
        pm_runtime_enable(&gpu->lpac_pdev->dev);
        if (!device_link_add(&pdev->dev, &gpu->lpac_pdev->dev,
                     DL_FLAG_PM_RUNTIME | DL_FLAG_AUTOREMOVE_CONSUMER))
            dev_err(&gpu->lpac_pdev->dev, "failed to link to lpac device\n");
    }

Because gpu->lpac_pdev is populated from the child node under the GPU node in
arch/arm64/boot/dts/qcom/sm8650.dtsi via of_platform_populate(...,
&pdev->dev), &pdev->dev is the parent of &gpu->lpac_pdev->dev. Calling
device_link_add() with the parent (&pdev->dev) as consumer and its child
(&gpu->lpac_pdev->dev) as supplier fails in device_is_dependent() because
device_is_ancestor(consumer, supplier) is true.

As a result, lpac_dev has no runtime PM link, no bound driver, and no
autosuspend configuration, so it remains permanently in RPM_SUSPENDED with
usage_count == 0. Even if lpac_dev were suspended while pagetable->iommu_dev
is active, the SMMU hardware still retains cached TLB entries for context
bank 1. Because pm_runtime_get_if_in_use(pagetable->parent->lpac_dev) always
returns 0, tlb_flush_all() and tlb_flush_walk() are never called for context
bank 1 before page table pages are freed in msm_iommu_pagetable_destroy() or
__arm_lpae_unmap().

Should msm_iommu_tlb_flush_all() and msm_iommu_tlb_flush_walk() check
pagetable->iommu_dev (or shouldn't the runtime PM handling for lpac_dev be
fixed so context bank 1 TLBs are invalidated before freeing page tables)?

[Severity: Medium]
When LPAC is enabled on gen70900 alongside ADRENO_QUIRK_IFPC, are the LPAC GX
registers restored after an Inter-Frame Power Collapse (IFPC) cycle?

During hw_init() in drivers/gpu/drm/msm/adreno/a6xx_gpu.c, when gpu->lpac_rb
is present, the driver programs several GX-domain registers:

    if (gpu->lpac_rb)
        gpu_rmw(gpu, REG_A6XX_UCHE_DEBUG_CNTL_1, BIT(30), BIT(30));
    ...
    if (gpu->lpac_rb) {
        gpu_write(gpu, REG_A7XX_CP_LPAC_CHICKEN_DBG, 0x1);

        gpu_write(gpu, REG_A7XX_SP_CHICKEN_BITS_2, BIT(4));
        gpu_write(gpu, REG_A7XX_SP_LPAC_CHICKEN_BITS_2, BIT(4));
    }

In drivers/gpu/drm/msm/adreno/a6xx_catalog.c, a750_ifpc_reglist_regs includes
REG_A6XX_CP_LPAC_PROTECT_CNTL, but REG_A6XX_UCHE_DEBUG_CNTL_1,
REG_A7XX_CP_LPAC_CHICKEN_DBG, REG_A7XX_SP_CHICKEN_BITS_2, and
REG_A7XX_SP_LPAC_CHICKEN_BITS_2 are absent from both a750_ifpc_reglist_regs
and a7xx_pwrup_reglist_regs, so their values will be lost when the GX domain
collapses during IFPC.

Should those four registers be added to the A750 IFPC / power-up register
lists?

>  		.funcs = &a7xx_gpu_funcs,

[Severity: Medium]
When gen70900 uses a7xx_gpu_funcs and submits LPAC jobs through
a7xx_submit() in drivers/gpu/drm/msm/adreno/a6xx_gpu.c, does alwayson_end
read from the wrong counter for LPAC?

At the start of a7xx_submit(), alwayson_start is sampled from
cp_always_on_counter when is_lpac is true:

    if (is_lpac)
        get_stats_counter(ring, cp_always_on_counter, rbmemptr_stats(ring, index, alwayson_start));
    else
        get_stats_counter(ring, cp_always_on_context, rbmemptr_stats(ring, index, alwayson_start));

However, at the end of a7xx_submit(), alwayson_end is unconditionally
sampled from cp_always_on_context:

    get_stats_counter(ring, rbbm_perfctr_cp0, rbmemptr_stats(ring, index, cpcycles_end));
    get_stats_counter(ring, cp_always_on_context, rbmemptr_stats(ring, index, alwayson_end));

When retire_submit() in drivers/gpu/drm/msm/msm_gpu.c computes:

    elapsed = (stats->alwayson_end - stats->alwayson_start) * 10000;

it subtracts CP_ALWAYS_ON_COUNTER from CP_ALWAYS_ON_CONTEXT, corrupting the
elapsed time, clock estimation, trace_msm_gpu_submit_retired(), and
ctx->elapsed_ns for LPAC submissions (note also that a7xx_submit() has an
unused local variable timestamp_iova).

Should the alwayson_end sample in a7xx_submit() also branch on is_lpac to
read cp_always_on_counter?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261029-descriptive-name-lpac-upstream-v2-0-a21a5c850961@gmail.com?part=14

      reply	other threads:[~2026-10-29 14:45 UTC|newest]

Thread overview: 26+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-29 13:52 [RFC PATCH v2 00/14] Enable LPAC on a7xx series GPUs Anna Maniscalco
2026-10-29 13:52 ` [PATCH RFC v2 01/14] iommu: arm-smmu-qcom: Configure lpac device with split address space Anna Maniscalco
2026-10-29 14:21   ` sashiko-bot
2026-10-29 13:52 ` [PATCH RFC v2 02/14] drm/msm: add support for lpac_domain in msm_mmu Anna Maniscalco
2026-10-29 14:12   ` sashiko-bot
2026-10-29 13:52 ` [PATCH RFC v2 03/14] drm/msm: look for lpac from dts Anna Maniscalco
2026-10-29 14:09   ` sashiko-bot
2026-10-29 13:52 ` [PATCH RFC v2 04/14] arm64: dts: qcom: sm8650: move smmu sid 1 to new lpac device Anna Maniscalco
2026-10-29 14:17   ` sashiko-bot
2026-10-29 13:52 ` [PATCH RFC v2 05/14] firmware: qcom: scm: Configure LPAC aperture Anna Maniscalco
2026-10-29 14:08   ` sashiko-bot
2026-10-29 13:52 ` [PATCH RFC v2 06/14] DEBUGGING: print contextbank and other ttbrs on fault Anna Maniscalco
2026-10-29 13:52 ` [PATCH RFC v2 07/14] iommu: arm-smmu-qcom: Fixed mapping between sid and cb for gpu and lpac Anna Maniscalco
2026-10-29 14:13   ` sashiko-bot
2026-10-29 13:52 ` [PATCH RFC v2 08/14] temp: add LPAC regs Anna Maniscalco
2026-10-29 14:13   ` sashiko-bot
2026-10-29 13:52 ` [PATCH RFC v2 09/14] drm/msm: initialize LPAC ring Anna Maniscalco
2026-10-29 14:33   ` sashiko-bot
2026-10-29 13:52 ` [PATCH RFC v2 10/14] drm/msm: Add LPAC submitqueue Anna Maniscalco
2026-10-29 14:25   ` sashiko-bot
2026-10-29 13:52 ` [PATCH RFC v2 11/14] drm/msm: set ctxbank and asid based on ring Anna Maniscalco
2026-10-29 13:52 ` [PATCH RFC v2 12/14] drm/msm: add lpac ring to devcoredump Anna Maniscalco
2026-10-29 13:52 ` [PATCH RFC v2 13/14] drm/msm: gate lpac behind modparam Anna Maniscalco
2026-10-29 14:27   ` sashiko-bot
2026-10-29 13:52 ` [PATCH RFC v2 14/14] drm/msm: enable LPAC on gen70900 Anna Maniscalco
2026-10-29 14:45   ` sashiko-bot [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=sashiko-outbox-189545@kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=anna.maniscalco2000@gmail.com \
    --cc=conor+dt@kernel.org \
    --cc=devicetree@vger.kernel.org \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=robh@kernel.org \
    --cc=sashiko-reviews@lists.linux.dev \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.