* [RFC PATCH 00/13] Enable LPAC on a7xx series GPUs
@ 2026-07-05 19:13 Anna Maniscalco
2026-07-05 19:13 ` [PATCH RFC 01/13] iommu: arm-smmu-qcom: Configure lpac device with split address space Anna Maniscalco
` (13 more replies)
0 siblings, 14 replies; 34+ messages in thread
From: Anna Maniscalco @ 2026-07-05 19:13 UTC (permalink / raw)
To: Rob Clark, Will Deacon, Robin Murphy, Joerg Roedel, Sean Paul,
Konrad Dybcio, Akhil P Oommen, Dmitry Baryshkov, Abhinav Kumar,
Jessica Zhang, Marijn Suijten, David Airlie, Simona Vetter,
Bjorn Andersson, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann
Cc: iommu, linux-arm-msm, linux-arm-kernel, linux-kernel, dri-devel,
freedreno, devicetree, Anna Maniscalco
This series enables LPAC on a7xx GPUs
Currently hangcheck and recovery are broken as the patches to make them
work depend on https://lore.kernel.org/linux-arm-msm/20250911-preemption_aware_hangcheck-v1-0-974819876819@gmail.com/
The series also depends on https://lore.kernel.org/linux-arm-msm/177919116291.814652.1720687887970998122.b4-ty@kernel.org/
to work correctly.
Signed-off-by: Anna Maniscalco <anna.maniscalco2000@gmail.com>
---
Anna Maniscalco (13):
iommu: arm-smmu-qcom: Configure lpac device with split address space
drm/msm: add support for lpac_domain in msm_mmu
drm/msm: look for lpac from dts
arm64: dts: qcom: sm8650: move smmu sid 1 to new lpac device
firmware: qcom: scm: Configure LPAC aperture
DEBUGGING: print contextbank and other ttbrs on fault
iommu: arm-smmu-qcom: Fixed mapping between sid and cb for gpu and lpac
HACK: use cb1 address in lpac dtb node
temp: add LPAC regs
drm/msm: initialize LPAC ring
drm/msm: Add LPAC submitqueue
drm/msm: set ctxbank and asid based on ring
drm/msm: add lpac ring to devcoredump
arch/arm64/boot/dts/qcom/sm8650.dtsi | 12 +-
drivers/firmware/qcom/qcom_scm.c | 18 +++
drivers/gpu/drm/msm/adreno/a6xx_catalog.c | 1 +
drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 2 +-
drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 191 +++++++++++++++++++++-----
drivers/gpu/drm/msm/adreno/a6xx_gpu.h | 2 +-
drivers/gpu/drm/msm/adreno/adreno_device.c | 6 +
drivers/gpu/drm/msm/adreno/adreno_gpu.c | 79 +++++++----
drivers/gpu/drm/msm/msm_gem_submit.c | 6 +-
drivers/gpu/drm/msm/msm_gpu.c | 29 +++-
drivers/gpu/drm/msm/msm_gpu.h | 17 ++-
drivers/gpu/drm/msm/msm_iommu.c | 158 ++++++++++++++++++---
drivers/gpu/drm/msm/msm_mmu.h | 7 +-
drivers/gpu/drm/msm/msm_submitqueue.c | 11 +-
drivers/gpu/drm/msm/registers/adreno/a6xx.xml | 14 ++
drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c | 37 ++++-
include/linux/adreno-smmu-priv.h | 2 +
include/linux/firmware/qcom/qcom_scm.h | 1 +
include/uapi/drm/msm_drm.h | 2 +
19 files changed, 492 insertions(+), 103 deletions(-)
---
base-commit: 9a967125427e03c7ebc24d7ad26e9307e8403d4e
change-id: 20260603-descriptive-name-lpac-upstream-730a164b105b
Best regards,
--
Anna Maniscalco <anna.maniscalco2000@gmail.com>
^ permalink raw reply [flat|nested] 34+ messages in thread
* [PATCH RFC 01/13] iommu: arm-smmu-qcom: Configure lpac device with split address space
2026-07-05 19:13 [RFC PATCH 00/13] Enable LPAC on a7xx series GPUs Anna Maniscalco
@ 2026-07-05 19:13 ` Anna Maniscalco
2026-07-06 15:00 ` Dmitry Baryshkov
2026-07-05 19:13 ` [PATCH RFC 02/13] drm/msm: add support for lpac_domain in msm_mmu Anna Maniscalco
` (12 subsequent siblings)
13 siblings, 1 reply; 34+ messages in thread
From: Anna Maniscalco @ 2026-07-05 19:13 UTC (permalink / raw)
To: Rob Clark, Will Deacon, Robin Murphy, Joerg Roedel, Sean Paul,
Konrad Dybcio, Akhil P Oommen, Dmitry Baryshkov, Abhinav Kumar,
Jessica Zhang, Marijn Suijten, David Airlie, Simona Vetter,
Bjorn Andersson, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann
Cc: iommu, linux-arm-msm, linux-arm-kernel, linux-kernel, dri-devel,
freedreno, devicetree, Anna Maniscalco
We want the context bank used by LPAC to use split address space just
like GFX.
Signed-off-by: Anna Maniscalco <anna.maniscalco2000@gmail.com>
---
drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
index edd41b5a3b6a..48a590aaeb5e 100644
--- a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
+++ b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
@@ -35,6 +35,8 @@
static const struct of_device_id qcom_smmu_actlr_client_of_match[] = {
{ .compatible = "qcom,adreno",
.data = (const void *) (PREFETCH_DEEP | CPRE | CMTLB) },
+ { .compatible = "qcom,lpac",
+ .data = (const void *) (PREFETCH_DEEP | CPRE | CMTLB) },
{ .compatible = "qcom,adreno-gmu",
.data = (const void *) (PREFETCH_DEEP | CPRE | CMTLB) },
{ .compatible = "qcom,adreno-smmu",
@@ -217,6 +219,7 @@ static void qcom_adreno_smmu_set_prr_addr(const void *cookie, phys_addr_t page_a
}
#define QCOM_ADRENO_SMMU_GPU_SID 0
+#define QCOM_ADRENO_SMMU_LPAC_SID 1
static bool qcom_adreno_smmu_is_gpu_device(struct device *dev)
{
@@ -230,7 +233,8 @@ static bool qcom_adreno_smmu_is_gpu_device(struct device *dev)
for (i = 0; i < fwspec->num_ids; i++) {
u16 sid = FIELD_GET(ARM_SMMU_SMR_ID, fwspec->ids[i]);
- if (sid == QCOM_ADRENO_SMMU_GPU_SID)
+ if (sid == QCOM_ADRENO_SMMU_GPU_SID ||
+ sid == QCOM_ADRENO_SMMU_LPAC_SID)
return true;
}
@@ -305,9 +309,9 @@ static int qcom_adreno_smmu_alloc_context_bank(struct arm_smmu_domain *smmu_doma
*/
if (qcom_adreno_smmu_is_gpu_device(dev)) {
start = 0;
- count = 1;
+ count = 2;
} else {
- start = 1;
+ start = 2;
count = smmu->num_context_banks;
}
@@ -394,6 +398,7 @@ static int qcom_adreno_smmu_init_context(struct arm_smmu_domain *smmu_domain,
static const struct of_device_id qcom_smmu_client_of_match[] __maybe_unused = {
{ .compatible = "qcom,adreno" },
+ { .compatible = "qcom,lpac" },
{ .compatible = "qcom,adreno-gmu" },
{ .compatible = "qcom,glymur-mdss" },
{ .compatible = "qcom,mdp4" },
--
2.54.0
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH RFC 02/13] drm/msm: add support for lpac_domain in msm_mmu
2026-07-05 19:13 [RFC PATCH 00/13] Enable LPAC on a7xx series GPUs Anna Maniscalco
2026-07-05 19:13 ` [PATCH RFC 01/13] iommu: arm-smmu-qcom: Configure lpac device with split address space Anna Maniscalco
@ 2026-07-05 19:13 ` Anna Maniscalco
2026-07-05 19:27 ` sashiko-bot
2026-07-05 19:13 ` [PATCH RFC 03/13] drm/msm: look for lpac from dts Anna Maniscalco
` (11 subsequent siblings)
13 siblings, 1 reply; 34+ messages in thread
From: Anna Maniscalco @ 2026-07-05 19:13 UTC (permalink / raw)
To: Rob Clark, Will Deacon, Robin Murphy, Joerg Roedel, Sean Paul,
Konrad Dybcio, Akhil P Oommen, Dmitry Baryshkov, Abhinav Kumar,
Jessica Zhang, Marijn Suijten, David Airlie, Simona Vetter,
Bjorn Andersson, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann
Cc: iommu, linux-arm-msm, linux-arm-kernel, linux-kernel, dri-devel,
freedreno, devicetree, Anna Maniscalco
LPAC needs to use a separate context bank in order to be able to update
the page table independetly.
Add an iommu_domain for LPAC and keep it in sync with the main domain.
Signed-off-by: Anna Maniscalco <anna.maniscalco2000@gmail.com>
---
drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 2 +-
drivers/gpu/drm/msm/adreno/adreno_gpu.c | 2 +-
drivers/gpu/drm/msm/msm_gpu.h | 1 +
drivers/gpu/drm/msm/msm_iommu.c | 158 ++++++++++++++++++++++++++++----
drivers/gpu/drm/msm/msm_mmu.h | 7 +-
5 files changed, 148 insertions(+), 22 deletions(-)
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
index 2e5d7b53a0c3..a91d9b03ca88 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
@@ -1569,7 +1569,7 @@ static int a6xx_gmu_memory_probe(struct drm_device *drm, struct a6xx_gmu *gmu)
{
struct msm_mmu *mmu;
- mmu = msm_iommu_new(gmu->dev, 0);
+ mmu = msm_iommu_new(gmu->dev, NULL, 0);
if (IS_ERR(mmu))
return PTR_ERR(mmu);
diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
index c62c45bb0ddb..f3fc7032fadc 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
@@ -201,7 +201,7 @@ adreno_iommu_create_vm(struct msm_gpu *gpu,
struct drm_gpuvm *vm;
u64 start, size;
- mmu = msm_iommu_gpu_new(&pdev->dev, gpu, quirks);
+ mmu = msm_iommu_gpu_new(&pdev->dev, NULL, gpu, quirks);
if (IS_ERR(mmu))
return ERR_CAST(mmu);
diff --git a/drivers/gpu/drm/msm/msm_gpu.h b/drivers/gpu/drm/msm/msm_gpu.h
index 6c83b8cbbb90..e2291dfe3ca8 100644
--- a/drivers/gpu/drm/msm/msm_gpu.h
+++ b/drivers/gpu/drm/msm/msm_gpu.h
@@ -175,6 +175,7 @@ struct msm_gpu {
const struct msm_gpu_funcs *funcs;
struct adreno_smmu_priv adreno_smmu;
+ struct adreno_smmu_priv lpac_adreno_smmu;
struct msm_ringbuffer *rb[MSM_GPU_MAX_RINGS];
int nr_rings;
diff --git a/drivers/gpu/drm/msm/msm_iommu.c b/drivers/gpu/drm/msm/msm_iommu.c
index 058c71c82cf5..19bee64adb7c 100644
--- a/drivers/gpu/drm/msm/msm_iommu.c
+++ b/drivers/gpu/drm/msm/msm_iommu.c
@@ -13,7 +13,7 @@
struct msm_iommu {
struct msm_mmu base;
- struct iommu_domain *domain;
+ struct iommu_domain *domain, *lpac_domain;
struct mutex init_lock; /* protects pagetables counter and prr_page */
int pagetables;
@@ -127,6 +127,8 @@ static int msm_iommu_pagetable_unmap(struct msm_mmu *mmu, u64 iova,
}
iommu_flush_iotlb_all(to_msm_iommu(pagetable->parent)->domain);
+ if (to_msm_iommu(pagetable->parent)->lpac_domain)
+ iommu_flush_iotlb_all(to_msm_iommu(pagetable->parent)->lpac_domain);
return ret;
}
@@ -224,6 +226,10 @@ static void msm_iommu_pagetable_destroy(struct msm_mmu *mmu)
struct msm_iommu *iommu = to_msm_iommu(pagetable->parent);
struct adreno_smmu_priv *adreno_smmu =
dev_get_drvdata(pagetable->parent->dev);
+ struct adreno_smmu_priv *lpac_adreno_smmu = NULL;
+
+ if (pagetable->parent->lpac_dev)
+ lpac_adreno_smmu = dev_get_drvdata(pagetable->parent->lpac_dev);
/*
* If this is the last attached pagetable for the parent,
@@ -232,9 +238,13 @@ static void msm_iommu_pagetable_destroy(struct msm_mmu *mmu)
mutex_lock(&iommu->init_lock);
if (--iommu->pagetables == 0) {
adreno_smmu->set_ttbr0_cfg(adreno_smmu->cookie, NULL);
+ if (lpac_adreno_smmu)
+ lpac_adreno_smmu->set_ttbr0_cfg(lpac_adreno_smmu->cookie, NULL);
if (adreno_smmu->set_prr_bit) {
adreno_smmu->set_prr_bit(adreno_smmu->cookie, false);
+ if (lpac_adreno_smmu && lpac_adreno_smmu->set_prr_bit)
+ lpac_adreno_smmu->set_prr_bit(lpac_adreno_smmu->cookie, false);
__free_page(iommu->prr_page);
iommu->prr_page = NULL;
}
@@ -450,14 +460,22 @@ static void msm_iommu_tlb_flush_all(void *cookie)
struct msm_iommu_pagetable *pagetable = cookie;
struct adreno_smmu_priv *adreno_smmu;
- if (!pm_runtime_get_if_in_use(pagetable->iommu_dev))
- return;
+ if (pm_runtime_get_if_in_use(pagetable->iommu_dev)) {
+ adreno_smmu = dev_get_drvdata(pagetable->parent->dev);
+
+ pagetable->tlb->tlb_flush_all((void *)adreno_smmu->cookie);
+
+ pm_runtime_put_autosuspend(pagetable->iommu_dev);
+ }
- adreno_smmu = dev_get_drvdata(pagetable->parent->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);
+ pagetable->tlb->tlb_flush_all((void *)adreno_smmu->cookie);
- pm_runtime_put_autosuspend(pagetable->iommu_dev);
+ pm_runtime_put_autosuspend(pagetable->parent->lpac_dev);
+ }
}
static void msm_iommu_tlb_flush_walk(unsigned long iova, size_t size,
@@ -466,14 +484,23 @@ static void msm_iommu_tlb_flush_walk(unsigned long iova, size_t size,
struct msm_iommu_pagetable *pagetable = cookie;
struct adreno_smmu_priv *adreno_smmu;
- if (!pm_runtime_get_if_in_use(pagetable->iommu_dev))
- return;
- adreno_smmu = dev_get_drvdata(pagetable->parent->dev);
+ if (pm_runtime_get_if_in_use(pagetable->iommu_dev)) {
+ adreno_smmu = dev_get_drvdata(pagetable->parent->dev);
- pagetable->tlb->tlb_flush_walk(iova, size, granule, (void *)adreno_smmu->cookie);
+ pagetable->tlb->tlb_flush_walk(iova, size, granule, (void *)adreno_smmu->cookie);
- pm_runtime_put_autosuspend(pagetable->iommu_dev);
+ pm_runtime_put_autosuspend(pagetable->iommu_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_walk(iova, size, granule, (void *)adreno_smmu->cookie);
+
+ pm_runtime_put_autosuspend(pagetable->parent->lpac_dev);
+ }
}
static void msm_iommu_tlb_add_page(struct iommu_iotlb_gather *gather,
@@ -504,12 +531,16 @@ static size_t get_tblsz(const struct io_pgtable_cfg *cfg)
struct msm_mmu *msm_iommu_pagetable_create(struct msm_mmu *parent, bool kernel_managed)
{
struct adreno_smmu_priv *adreno_smmu = dev_get_drvdata(parent->dev);
+ struct adreno_smmu_priv *lpac_adreno_smmu = NULL;
struct msm_iommu *iommu = to_msm_iommu(parent);
struct msm_iommu_pagetable *pagetable;
const struct io_pgtable_cfg *ttbr1_cfg = NULL;
struct io_pgtable_cfg ttbr0_cfg;
int ret;
+ if (parent->lpac_dev)
+ lpac_adreno_smmu = dev_get_drvdata(parent->lpac_dev);
+
/* Get the pagetable configuration from the domain */
if (adreno_smmu->cookie)
ttbr1_cfg = adreno_smmu->get_ttbr1_cfg(adreno_smmu->cookie);
@@ -528,6 +559,8 @@ struct msm_mmu *msm_iommu_pagetable_create(struct msm_mmu *parent, bool kernel_m
msm_mmu_init(&pagetable->base, parent->dev, &pagetable_funcs,
MSM_MMU_IOMMU_PAGETABLE);
+ pagetable->parent = parent;
+
/* Clone the TTBR1 cfg as starting point for TTBR0 cfg: */
ttbr0_cfg = *ttbr1_cfg;
@@ -588,6 +621,17 @@ struct msm_mmu *msm_iommu_pagetable_create(struct msm_mmu *parent, bool kernel_m
return ERR_PTR(ret);
}
+ if (lpac_adreno_smmu) {
+ ret = lpac_adreno_smmu->set_ttbr0_cfg(lpac_adreno_smmu->cookie, &ttbr0_cfg);
+ if (ret) {
+ iommu->pagetables--;
+ mutex_unlock(&iommu->init_lock);
+ free_io_pgtable_ops(pagetable->pgtbl_ops);
+ kfree(pagetable);
+ return ERR_PTR(ret);
+ }
+ }
+
BUG_ON(iommu->prr_page);
if (adreno_smmu->set_prr_bit) {
/*
@@ -606,11 +650,17 @@ struct msm_mmu *msm_iommu_pagetable_create(struct msm_mmu *parent, bool kernel_m
page_to_phys(iommu->prr_page));
adreno_smmu->set_prr_bit(adreno_smmu->cookie, true);
}
+
+ if (lpac_adreno_smmu && lpac_adreno_smmu->set_prr_bit) {
+ iommu->prr_page = alloc_page(GFP_KERNEL | __GFP_ZERO);
+ lpac_adreno_smmu->set_prr_addr(lpac_adreno_smmu->cookie,
+ page_to_phys(iommu->prr_page));
+ lpac_adreno_smmu->set_prr_bit(lpac_adreno_smmu->cookie, true);
+ }
}
mutex_unlock(&iommu->init_lock);
/* Needed later for TLB flush */
- pagetable->parent = parent;
pagetable->tlb = ttbr1_cfg->tlb;
pagetable->pgsize_bitmap = ttbr0_cfg.pgsize_bitmap;
pagetable->ttbr = ttbr0_cfg.arm_lpae_s1_cfg.ttbr;
@@ -646,6 +696,26 @@ static int msm_gpu_fault_handler(struct iommu_domain *domain, struct device *dev
return 0;
}
+static int msm_lpac_fault_handler(struct iommu_domain *domain, struct device *dev,
+ unsigned long iova, int flags, void *arg)
+{
+ struct msm_iommu *iommu = arg;
+ struct adreno_smmu_priv *adreno_smmu = dev_get_drvdata(iommu->base.dev);
+ struct adreno_smmu_fault_info info, *ptr = NULL;
+
+ if (adreno_smmu->get_fault_info) {
+ adreno_smmu->get_fault_info(adreno_smmu->cookie, &info);
+ ptr = &info;
+ }
+
+ if (iommu->base.handler)
+ return iommu->base.handler(iommu->base.arg, iova, flags, ptr);
+
+ pr_warn_ratelimited("*** lpac fault: iova=%16lx, flags=%d\n", iova, flags);
+
+ return 0;
+}
+
static int msm_disp_fault_handler(struct iommu_domain *domain, struct device *dev,
unsigned long iova, int flags, void *arg)
{
@@ -660,9 +730,16 @@ static int msm_disp_fault_handler(struct iommu_domain *domain, struct device *de
static void msm_iommu_set_stall(struct msm_mmu *mmu, bool enable)
{
struct adreno_smmu_priv *adreno_smmu = dev_get_drvdata(mmu->dev);
+ struct adreno_smmu_priv *lpac_adreno_smmu = NULL;
+
+ if (mmu->lpac_dev)
+ lpac_adreno_smmu = dev_get_drvdata(mmu->lpac_dev);
if (adreno_smmu->set_stall)
adreno_smmu->set_stall(adreno_smmu->cookie, enable);
+
+ if (lpac_adreno_smmu && lpac_adreno_smmu->set_stall)
+ lpac_adreno_smmu->set_stall(lpac_adreno_smmu->cookie, enable);
}
static void msm_iommu_detach(struct msm_mmu *mmu)
@@ -670,6 +747,9 @@ static void msm_iommu_detach(struct msm_mmu *mmu)
struct msm_iommu *iommu = to_msm_iommu(mmu);
iommu_detach_device(iommu->domain, mmu->dev);
+
+ if (iommu->lpac_domain)
+ iommu_detach_device(iommu->lpac_domain, mmu->lpac_dev);
}
static int msm_iommu_map(struct msm_mmu *mmu, uint64_t iova,
@@ -689,6 +769,11 @@ static int msm_iommu_map(struct msm_mmu *mmu, uint64_t iova,
if (ret < 0)
return ret;
+ if (iommu->lpac_domain) {
+ ret = iommu_map_sgtable(iommu->lpac_domain, iova, sgt, prot);
+ WARN_ON(!ret);
+ }
+
return (ret == len) ? 0 : -EINVAL;
}
@@ -701,6 +786,9 @@ static int msm_iommu_unmap(struct msm_mmu *mmu, uint64_t iova, size_t len)
iommu_unmap(iommu->domain, iova, len);
+ if (iommu->lpac_domain)
+ iommu_unmap(iommu->lpac_domain, iova, len);
+
return 0;
}
@@ -708,6 +796,8 @@ static void msm_iommu_destroy(struct msm_mmu *mmu)
{
struct msm_iommu *iommu = to_msm_iommu(mmu);
iommu_domain_free(iommu->domain);
+ if (iommu->lpac_domain)
+ iommu_domain_free(iommu->lpac_domain);
kmem_cache_destroy(iommu->pt_cache);
kfree(iommu);
}
@@ -720,9 +810,9 @@ static const struct msm_mmu_funcs funcs = {
.set_stall = msm_iommu_set_stall,
};
-struct msm_mmu *msm_iommu_new(struct device *dev, unsigned long quirks)
+struct msm_mmu *msm_iommu_new(struct device *dev, struct device *lpac_dev, unsigned long quirks)
{
- struct iommu_domain *domain;
+ struct iommu_domain *domain, *lpac_domain = NULL;
struct msm_iommu *iommu;
int ret;
@@ -753,6 +843,30 @@ struct msm_mmu *msm_iommu_new(struct device *dev, unsigned long quirks)
return ERR_PTR(ret);
}
+ if (lpac_dev) {
+ if (!device_iommu_mapped(lpac_dev))
+ return ERR_PTR(-ENODEV);
+
+ lpac_domain = iommu_paging_domain_alloc(lpac_dev);
+ if (IS_ERR(lpac_domain))
+ return ERR_CAST(lpac_domain);
+
+ iommu_set_pgtable_quirks(lpac_domain, quirks);
+
+ iommu->lpac_domain = lpac_domain;
+ iommu->base.lpac_dev = lpac_dev;
+ }
+
+ if (lpac_domain) {
+ ret = iommu_attach_device(lpac_domain, lpac_dev);
+ if (ret) {
+ iommu_domain_free(domain);
+ iommu_domain_free(lpac_domain);
+ kfree(iommu);
+ return ERR_PTR(ret);
+ }
+ }
+
return &iommu->base;
}
@@ -761,7 +875,7 @@ struct msm_mmu *msm_iommu_disp_new(struct device *dev, unsigned long quirks)
struct msm_iommu *iommu;
struct msm_mmu *mmu;
- mmu = msm_iommu_new(dev, quirks);
+ mmu = msm_iommu_new(dev, NULL, quirks);
if (IS_ERR(mmu))
return mmu;
@@ -771,13 +885,18 @@ struct msm_mmu *msm_iommu_disp_new(struct device *dev, unsigned long quirks)
return mmu;
}
-struct msm_mmu *msm_iommu_gpu_new(struct device *dev, struct msm_gpu *gpu, unsigned long quirks)
+struct msm_mmu *msm_iommu_gpu_new(struct device *dev, struct device *lpac_dev,
+ struct msm_gpu *gpu, unsigned long quirks)
{
struct adreno_smmu_priv *adreno_smmu = dev_get_drvdata(dev);
+ struct adreno_smmu_priv *lpac_adreno_smmu = NULL;
struct msm_iommu *iommu;
struct msm_mmu *mmu;
- mmu = msm_iommu_new(dev, quirks);
+ if (lpac_dev)
+ lpac_adreno_smmu = dev_get_drvdata(lpac_dev);
+
+ mmu = msm_iommu_new(dev, lpac_dev, quirks);
if (IS_ERR(mmu))
return mmu;
@@ -791,10 +910,15 @@ struct msm_mmu *msm_iommu_gpu_new(struct device *dev, struct msm_gpu *gpu, unsig
kmem_cache_create("msm-mmu-pt", tblsz, tblsz, 0, NULL);
}
iommu_set_fault_handler(iommu->domain, msm_gpu_fault_handler, iommu);
+ if (iommu->lpac_domain)
+ iommu_set_fault_handler(iommu->lpac_domain, msm_lpac_fault_handler, iommu);
/* Enable stall on iommu fault: */
if (adreno_smmu->set_stall)
adreno_smmu->set_stall(adreno_smmu->cookie, true);
+ if (lpac_adreno_smmu && lpac_adreno_smmu->set_stall)
+ lpac_adreno_smmu->set_stall(lpac_adreno_smmu->cookie, true);
+
return mmu;
}
diff --git a/drivers/gpu/drm/msm/msm_mmu.h b/drivers/gpu/drm/msm/msm_mmu.h
index 8915662fbd4d..1965b98d20db 100644
--- a/drivers/gpu/drm/msm/msm_mmu.h
+++ b/drivers/gpu/drm/msm/msm_mmu.h
@@ -52,7 +52,7 @@ struct msm_mmu_prealloc {
struct msm_mmu {
const struct msm_mmu_funcs *funcs;
- struct device *dev;
+ struct device *dev, *lpac_dev;
int (*handler)(void *arg, unsigned long iova, int flags, void *data);
void *arg;
enum msm_mmu_type type;
@@ -74,8 +74,9 @@ static inline void msm_mmu_init(struct msm_mmu *mmu, struct device *dev,
mmu->type = type;
}
-struct msm_mmu *msm_iommu_new(struct device *dev, unsigned long quirks);
-struct msm_mmu *msm_iommu_gpu_new(struct device *dev, struct msm_gpu *gpu, unsigned long quirks);
+struct msm_mmu *msm_iommu_new(struct device *dev, struct device *lpac_dev, unsigned long quirks);
+struct msm_mmu *msm_iommu_gpu_new(struct device *dev, struct device *lpac_dev,
+ struct msm_gpu *gpu, unsigned long quirks);
struct msm_mmu *msm_iommu_disp_new(struct device *dev, unsigned long quirks);
static inline void msm_mmu_set_fault_handler(struct msm_mmu *mmu, void *arg,
--
2.54.0
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH RFC 03/13] drm/msm: look for lpac from dts
2026-07-05 19:13 [RFC PATCH 00/13] Enable LPAC on a7xx series GPUs Anna Maniscalco
2026-07-05 19:13 ` [PATCH RFC 01/13] iommu: arm-smmu-qcom: Configure lpac device with split address space Anna Maniscalco
2026-07-05 19:13 ` [PATCH RFC 02/13] drm/msm: add support for lpac_domain in msm_mmu Anna Maniscalco
@ 2026-07-05 19:13 ` Anna Maniscalco
2026-07-05 19:27 ` sashiko-bot
2026-07-06 15:04 ` Dmitry Baryshkov
2026-07-05 19:13 ` [PATCH RFC 04/13] arm64: dts: qcom: sm8650: move smmu sid 1 to new lpac device Anna Maniscalco
` (10 subsequent siblings)
13 siblings, 2 replies; 34+ messages in thread
From: Anna Maniscalco @ 2026-07-05 19:13 UTC (permalink / raw)
To: Rob Clark, Will Deacon, Robin Murphy, Joerg Roedel, Sean Paul,
Konrad Dybcio, Akhil P Oommen, Dmitry Baryshkov, Abhinav Kumar,
Jessica Zhang, Marijn Suijten, David Airlie, Simona Vetter,
Bjorn Andersson, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann
Cc: iommu, linux-arm-msm, linux-arm-kernel, linux-kernel, dri-devel,
freedreno, devicetree, Anna Maniscalco
In order to associate the SID used by LPAC to it's own domain and
context bank we need a separate node on the DTS.
Add the code to look up that node on initialization.
Signed-off-by: Anna Maniscalco <anna.maniscalco2000@gmail.com>
---
drivers/gpu/drm/msm/adreno/adreno_gpu.c | 21 ++++++++++++++++++++-
drivers/gpu/drm/msm/msm_gpu.h | 1 +
2 files changed, 21 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
index f3fc7032fadc..71ce4cbbf27a 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
@@ -11,6 +11,8 @@
#include <linux/firmware/qcom/qcom_scm.h>
#include <linux/kernel.h>
#include <linux/of_reserved_mem.h>
+#include <linux/of_device.h>
+#include <linux/of_platform.h>
#include <linux/pm_opp.h>
#include <linux/slab.h>
#include <linux/soc/qcom/mdt_loader.h>
@@ -201,7 +203,9 @@ adreno_iommu_create_vm(struct msm_gpu *gpu,
struct drm_gpuvm *vm;
u64 start, size;
- mmu = msm_iommu_gpu_new(&pdev->dev, NULL, gpu, quirks);
+ mmu = msm_iommu_gpu_new(&pdev->dev,
+ gpu->lpac_pdev ? &gpu->lpac_pdev->dev : NULL,
+ gpu, quirks);
if (IS_ERR(mmu))
return ERR_CAST(mmu);
@@ -1187,6 +1191,7 @@ int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev,
const struct adreno_gpu_funcs *funcs, int nr_rings)
{
struct device *dev = &pdev->dev;
+ struct device_node *lpac_node;
struct adreno_platform_config *config = dev->platform_data;
struct msm_gpu_config adreno_gpu_config = { 0 };
struct msm_gpu *gpu = &adreno_gpu->base;
@@ -1200,6 +1205,20 @@ int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev,
gpu->allow_relocs = config->info->family < ADRENO_6XX_GEN1;
gpu->pdev = pdev;
+ lpac_node = of_parse_phandle(pdev->dev.of_node, "qcom,lpac", 0);
+ if (lpac_node)
+ gpu->lpac_pdev = of_find_device_by_node(lpac_node);
+ if (gpu->lpac_pdev) {
+ of_dma_configure(&gpu->lpac_pdev->dev, lpac_node, true);
+ platform_set_drvdata(gpu->lpac_pdev, &gpu->lpac_adreno_smmu);
+ 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 gpu device\n");
+ pm_runtime_enable(&gpu->lpac_pdev->dev);
+ }
+ if (lpac_node)
+ of_node_put(lpac_node);
+
/* Only handle the core clock when GMU is not in use (or is absent). */
if (adreno_has_gmu_wrapper(adreno_gpu) ||
adreno_has_rgmu(adreno_gpu) ||
diff --git a/drivers/gpu/drm/msm/msm_gpu.h b/drivers/gpu/drm/msm/msm_gpu.h
index e2291dfe3ca8..271956e7f870 100644
--- a/drivers/gpu/drm/msm/msm_gpu.h
+++ b/drivers/gpu/drm/msm/msm_gpu.h
@@ -172,6 +172,7 @@ struct msm_gpu {
const char *name;
struct drm_device *dev;
struct platform_device *pdev;
+ struct platform_device *lpac_pdev;
const struct msm_gpu_funcs *funcs;
struct adreno_smmu_priv adreno_smmu;
--
2.54.0
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH RFC 04/13] arm64: dts: qcom: sm8650: move smmu sid 1 to new lpac device
2026-07-05 19:13 [RFC PATCH 00/13] Enable LPAC on a7xx series GPUs Anna Maniscalco
` (2 preceding siblings ...)
2026-07-05 19:13 ` [PATCH RFC 03/13] drm/msm: look for lpac from dts Anna Maniscalco
@ 2026-07-05 19:13 ` Anna Maniscalco
2026-07-05 19:24 ` sashiko-bot
2026-07-06 8:40 ` Konrad Dybcio
2026-07-05 19:13 ` [PATCH RFC 05/13] firmware: qcom: scm: Configure LPAC aperture Anna Maniscalco
` (9 subsequent siblings)
13 siblings, 2 replies; 34+ messages in thread
From: Anna Maniscalco @ 2026-07-05 19:13 UTC (permalink / raw)
To: Rob Clark, Will Deacon, Robin Murphy, Joerg Roedel, Sean Paul,
Konrad Dybcio, Akhil P Oommen, Dmitry Baryshkov, Abhinav Kumar,
Jessica Zhang, Marijn Suijten, David Airlie, Simona Vetter,
Bjorn Andersson, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann
Cc: iommu, linux-arm-msm, linux-arm-kernel, linux-kernel, dri-devel,
freedreno, devicetree, Anna Maniscalco
Previously both SID 0 and 1 where associated with the same domain.
When LPAC is not used this is needed so firmware can acces memory when
initializing using the same page table as GFX.
To use LPAC however we need to move SID 1 to a different device.
Signed-off-by: Anna Maniscalco <anna.maniscalco2000@gmail.com>
---
arch/arm64/boot/dts/qcom/sm8650.dtsi | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/arch/arm64/boot/dts/qcom/sm8650.dtsi b/arch/arm64/boot/dts/qcom/sm8650.dtsi
index 1604bc8cff37..44e5f9d4b335 100644
--- a/arch/arm64/boot/dts/qcom/sm8650.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm8650.dtsi
@@ -4133,6 +4133,13 @@ tcsr: clock-controller@1fc0000 {
#reset-cells = <1>;
};
+ lpac: lpac@3d00000 {
+ compatible = "qcom,lpac";
+ reg = <0x0 0x03d00000 0x0 0x61000>;
+
+ iommus = <&adreno_smmu 1 0x0>;
+ };
+
gpu: gpu@3d00000 {
compatible = "qcom,adreno-43051401", "qcom,adreno";
reg = <0x0 0x03d00000 0x0 0x40000>,
@@ -4144,8 +4151,9 @@ gpu: gpu@3d00000 {
interrupts = <GIC_SPI 300 IRQ_TYPE_LEVEL_HIGH 0>;
- iommus = <&adreno_smmu 0 0x0>,
- <&adreno_smmu 1 0x0>;
+ iommus = <&adreno_smmu 0 0x0>;
+
+ qcom,lpac= <&lpac>;
operating-points-v2 = <&gpu_opp_table>;
--
2.54.0
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH RFC 05/13] firmware: qcom: scm: Configure LPAC aperture
2026-07-05 19:13 [RFC PATCH 00/13] Enable LPAC on a7xx series GPUs Anna Maniscalco
` (3 preceding siblings ...)
2026-07-05 19:13 ` [PATCH RFC 04/13] arm64: dts: qcom: sm8650: move smmu sid 1 to new lpac device Anna Maniscalco
@ 2026-07-05 19:13 ` Anna Maniscalco
2026-07-05 19:20 ` sashiko-bot
2026-07-05 19:13 ` [PATCH RFC 06/13] DEBUGGING: print contextbank and other ttbrs on fault Anna Maniscalco
` (8 subsequent siblings)
13 siblings, 1 reply; 34+ messages in thread
From: Anna Maniscalco @ 2026-07-05 19:13 UTC (permalink / raw)
To: Rob Clark, Will Deacon, Robin Murphy, Joerg Roedel, Sean Paul,
Konrad Dybcio, Akhil P Oommen, Dmitry Baryshkov, Abhinav Kumar,
Jessica Zhang, Marijn Suijten, David Airlie, Simona Vetter,
Bjorn Andersson, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann
Cc: iommu, linux-arm-msm, linux-arm-kernel, linux-kernel, dri-devel,
freedreno, devicetree, Anna Maniscalco
In order to be able to update the SMMU registers from CP for page table
updates we need to configure the LPAC aperture to include the context
bank that will be associated with SID 1.
Signed-off-by: Anna Maniscalco <anna.maniscalco2000@gmail.com>
---
drivers/firmware/qcom/qcom_scm.c | 18 ++++++++++++++++++
drivers/gpu/drm/msm/adreno/adreno_gpu.c | 3 +++
include/linux/firmware/qcom/qcom_scm.h | 1 +
3 files changed, 22 insertions(+)
diff --git a/drivers/firmware/qcom/qcom_scm.c b/drivers/firmware/qcom/qcom_scm.c
index 9b06a69d3a6d..92093399f20d 100644
--- a/drivers/firmware/qcom/qcom_scm.c
+++ b/drivers/firmware/qcom/qcom_scm.c
@@ -1204,6 +1204,7 @@ int qcom_scm_restore_sec_cfg(u32 device_id, u32 spare)
EXPORT_SYMBOL_GPL(qcom_scm_restore_sec_cfg);
#define QCOM_SCM_CP_APERTURE_CONTEXT_MASK GENMASK(7, 0)
+#define QCOM_SCM_LPAC_APERTURE_CONTEXT_MASK GENMASK(7, 1)
bool qcom_scm_set_gpu_smmu_aperture_is_available(void)
{
@@ -1229,6 +1230,23 @@ int qcom_scm_set_gpu_smmu_aperture(unsigned int context_bank)
}
EXPORT_SYMBOL_GPL(qcom_scm_set_gpu_smmu_aperture);
+int qcom_scm_set_gpu_smmu_lpac_aperture(unsigned int context_bank)
+{
+ struct qcom_scm_desc desc = {
+ .svc = QCOM_SCM_SVC_MP,
+ .cmd = QCOM_SCM_MP_CP_SMMU_APERTURE_ID,
+ .arginfo = QCOM_SCM_ARGS(4),
+ .args[0] = 0xffff0000 | (1 << 8 | context_bank),
+ .args[1] = 0xffffffff,
+ .args[2] = 0xffffffff,
+ .args[3] = 0xffffffff,
+ .owner = ARM_SMCCC_OWNER_SIP
+ };
+
+ return qcom_scm_call(__scm->dev, &desc, NULL);
+}
+EXPORT_SYMBOL_GPL(qcom_scm_set_gpu_smmu_lpac_aperture);
+
int qcom_scm_iommu_secure_ptbl_size(u32 spare, size_t *size)
{
struct qcom_scm_desc desc = {
diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
index 71ce4cbbf27a..be374cf209f4 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
@@ -668,6 +668,9 @@ int adreno_hw_init(struct msm_gpu *gpu)
ret = qcom_scm_set_gpu_smmu_aperture(0);
if (ret)
DRM_DEV_ERROR(gpu->dev->dev, "unable to set SMMU aperture: %d\n", ret);
+ ret = qcom_scm_set_gpu_smmu_lpac_aperture(1);
+ if (ret)
+ DRM_DEV_ERROR(gpu->dev->dev, "unable to set lpac SMMU aperture: %d\n", ret);
}
for (int i = 0; i < gpu->nr_rings; i++) {
diff --git a/include/linux/firmware/qcom/qcom_scm.h b/include/linux/firmware/qcom/qcom_scm.h
index 5747bd191bf1..70fb93e303e2 100644
--- a/include/linux/firmware/qcom/qcom_scm.h
+++ b/include/linux/firmware/qcom/qcom_scm.h
@@ -100,6 +100,7 @@ int qcom_scm_io_writel(phys_addr_t addr, unsigned int val);
bool qcom_scm_restore_sec_cfg_available(void);
int qcom_scm_restore_sec_cfg(u32 device_id, u32 spare);
int qcom_scm_set_gpu_smmu_aperture(unsigned int context_bank);
+int qcom_scm_set_gpu_smmu_lpac_aperture(unsigned int context_bank);
bool qcom_scm_set_gpu_smmu_aperture_is_available(void);
int qcom_scm_iommu_secure_ptbl_size(u32 spare, size_t *size);
int qcom_scm_iommu_secure_ptbl_init(u64 addr, u32 size, u32 spare);
--
2.54.0
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH RFC 06/13] DEBUGGING: print contextbank and other ttbrs on fault
2026-07-05 19:13 [RFC PATCH 00/13] Enable LPAC on a7xx series GPUs Anna Maniscalco
` (4 preceding siblings ...)
2026-07-05 19:13 ` [PATCH RFC 05/13] firmware: qcom: scm: Configure LPAC aperture Anna Maniscalco
@ 2026-07-05 19:13 ` Anna Maniscalco
2026-07-05 19:13 ` [PATCH RFC 07/13] iommu: arm-smmu-qcom: Fixed mapping between sid and cb for gpu and lpac Anna Maniscalco
` (7 subsequent siblings)
13 siblings, 0 replies; 34+ messages in thread
From: Anna Maniscalco @ 2026-07-05 19:13 UTC (permalink / raw)
To: Rob Clark, Will Deacon, Robin Murphy, Joerg Roedel, Sean Paul,
Konrad Dybcio, Akhil P Oommen, Dmitry Baryshkov, Abhinav Kumar,
Jessica Zhang, Marijn Suijten, David Airlie, Simona Vetter,
Bjorn Andersson, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann
Cc: iommu, linux-arm-msm, linux-arm-kernel, linux-kernel, dri-devel,
freedreno, devicetree, Anna Maniscalco
Faults can now come from different context banks so print that
information as well.
Signed-off-by: Anna Maniscalco <anna.maniscalco2000@gmail.com>
---
drivers/gpu/drm/msm/adreno/adreno_gpu.c | 4 ++--
drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c | 4 ++++
include/linux/adreno-smmu-priv.h | 2 ++
3 files changed, 8 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
index be374cf209f4..6a48e211fa3c 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
@@ -329,8 +329,8 @@ int adreno_fault_handler(struct msm_gpu *gpu, unsigned long iova, int flags,
else if (info->fsr & ARM_SMMU_FSR_EF)
type = "EXTERNAL";
- pr_warn_ratelimited("*** gpu fault: ttbr0=%.16llx iova=%.16lx dir=%s type=%s source=%s (%u,%u,%u,%u)\n",
- info->ttbr0, iova,
+ pr_warn_ratelimited("*** gpu fault: cb=%d ttbr0=%.16llx cb0_ttbr0=%.16llx cb1_ttbr0=%.16llx iova=%.16lx dir=%s type=%s source=%s (%u,%u,%u,%u)\n",
+ info->contextbank, info->ttbr0, info->cb0_ttbr0, info->cb1_ttbr0, iova,
flags & IOMMU_FAULT_WRITE ? "WRITE" : "READ",
type, block,
scratch[0], scratch[1], scratch[2], scratch[3]);
diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
index 48a590aaeb5e..ae6152bddf8f 100644
--- a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
+++ b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
@@ -136,6 +136,10 @@ static void qcom_adreno_smmu_get_fault_info(const void *cookie,
info->cbfrsynra = arm_smmu_gr1_read(smmu, ARM_SMMU_GR1_CBFRSYNRA(cfg->cbndx));
info->ttbr0 = arm_smmu_cb_readq(smmu, cfg->cbndx, ARM_SMMU_CB_TTBR0);
info->contextidr = arm_smmu_cb_read(smmu, cfg->cbndx, ARM_SMMU_CB_CONTEXTIDR);
+ info->contextbank = cfg->cbndx;
+
+ info->cb0_ttbr0 = arm_smmu_cb_readq(smmu, 0, ARM_SMMU_CB_TTBR0);
+ info->cb1_ttbr0 = arm_smmu_cb_readq(smmu, 1, ARM_SMMU_CB_TTBR0);
}
static void qcom_adreno_smmu_set_stall(const void *cookie, bool enabled)
diff --git a/include/linux/adreno-smmu-priv.h b/include/linux/adreno-smmu-priv.h
index d83c9175828f..5d6de4b4de06 100644
--- a/include/linux/adreno-smmu-priv.h
+++ b/include/linux/adreno-smmu-priv.h
@@ -32,6 +32,8 @@ struct adreno_smmu_fault_info {
u32 fsynr0;
u32 fsynr1;
u32 cbfrsynra;
+ u32 contextbank;
+ u64 cb0_ttbr0, cb1_ttbr0;
};
/**
--
2.54.0
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH RFC 07/13] iommu: arm-smmu-qcom: Fixed mapping between sid and cb for gpu and lpac
2026-07-05 19:13 [RFC PATCH 00/13] Enable LPAC on a7xx series GPUs Anna Maniscalco
` (5 preceding siblings ...)
2026-07-05 19:13 ` [PATCH RFC 06/13] DEBUGGING: print contextbank and other ttbrs on fault Anna Maniscalco
@ 2026-07-05 19:13 ` Anna Maniscalco
2026-07-05 19:27 ` sashiko-bot
2026-07-05 19:13 ` [PATCH RFC 08/13] HACK: use cb1 address in lpac dtb node Anna Maniscalco
` (6 subsequent siblings)
13 siblings, 1 reply; 34+ messages in thread
From: Anna Maniscalco @ 2026-07-05 19:13 UTC (permalink / raw)
To: Rob Clark, Will Deacon, Robin Murphy, Joerg Roedel, Sean Paul,
Konrad Dybcio, Akhil P Oommen, Dmitry Baryshkov, Abhinav Kumar,
Jessica Zhang, Marijn Suijten, David Airlie, Simona Vetter,
Bjorn Andersson, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann
Cc: iommu, linux-arm-msm, linux-arm-kernel, linux-kernel, dri-devel,
freedreno, devicetree, Anna Maniscalco
We want to map context bank 0 to SID 0 and context bank 1 to SID 1 as it
makes it simpler to deal with.
Signed-off-by: Anna Maniscalco <anna.maniscalco2000@gmail.com>
---
drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c | 24 +++++++++++++++++++++---
1 file changed, 21 insertions(+), 3 deletions(-)
diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
index ae6152bddf8f..e605a535f328 100644
--- a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
+++ b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
@@ -225,6 +225,25 @@ static void qcom_adreno_smmu_set_prr_addr(const void *cookie, phys_addr_t page_a
#define QCOM_ADRENO_SMMU_GPU_SID 0
#define QCOM_ADRENO_SMMU_LPAC_SID 1
+static bool qcom_adreno_smmu_is_lpac_device(struct device *dev)
+{
+ struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
+ int i;
+
+ /*
+ * The GPU will always use SID 0 so that is a handy way to uniquely
+ * identify it and configure it for per-instance pagetables
+ */
+ for (i = 0; i < fwspec->num_ids; i++) {
+ u16 sid = FIELD_GET(ARM_SMMU_SMR_ID, fwspec->ids[i]);
+
+ if (sid == QCOM_ADRENO_SMMU_LPAC_SID)
+ return true;
+ }
+
+ return false;
+}
+
static bool qcom_adreno_smmu_is_gpu_device(struct device *dev)
{
struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
@@ -312,13 +331,12 @@ static int qcom_adreno_smmu_alloc_context_bank(struct arm_smmu_domain *smmu_doma
* switch pagetables
*/
if (qcom_adreno_smmu_is_gpu_device(dev)) {
- start = 0;
- count = 2;
+ start = !!qcom_adreno_smmu_is_lpac_device(dev);
+ count = start + 1;
} else {
start = 2;
count = smmu->num_context_banks;
}
-
return __arm_smmu_alloc_bitmap(smmu->context_map, start, count);
}
--
2.54.0
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH RFC 08/13] HACK: use cb1 address in lpac dtb node
2026-07-05 19:13 [RFC PATCH 00/13] Enable LPAC on a7xx series GPUs Anna Maniscalco
` (6 preceding siblings ...)
2026-07-05 19:13 ` [PATCH RFC 07/13] iommu: arm-smmu-qcom: Fixed mapping between sid and cb for gpu and lpac Anna Maniscalco
@ 2026-07-05 19:13 ` Anna Maniscalco
2026-07-05 19:18 ` sashiko-bot
2026-07-05 19:13 ` [PATCH RFC 09/13] temp: add LPAC regs Anna Maniscalco
` (5 subsequent siblings)
13 siblings, 1 reply; 34+ messages in thread
From: Anna Maniscalco @ 2026-07-05 19:13 UTC (permalink / raw)
To: Rob Clark, Will Deacon, Robin Murphy, Joerg Roedel, Sean Paul,
Konrad Dybcio, Akhil P Oommen, Dmitry Baryshkov, Abhinav Kumar,
Jessica Zhang, Marijn Suijten, David Airlie, Simona Vetter,
Bjorn Andersson, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann
Cc: iommu, linux-arm-msm, linux-arm-kernel, linux-kernel, dri-devel,
freedreno, devicetree, Anna Maniscalco
Signed-off-by: Anna Maniscalco <anna.maniscalco2000@gmail.com>
---
arch/arm64/boot/dts/qcom/sm8650.dtsi | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/arch/arm64/boot/dts/qcom/sm8650.dtsi b/arch/arm64/boot/dts/qcom/sm8650.dtsi
index 44e5f9d4b335..66ea9155e228 100644
--- a/arch/arm64/boot/dts/qcom/sm8650.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm8650.dtsi
@@ -4133,13 +4133,6 @@ tcsr: clock-controller@1fc0000 {
#reset-cells = <1>;
};
- lpac: lpac@3d00000 {
- compatible = "qcom,lpac";
- reg = <0x0 0x03d00000 0x0 0x61000>;
-
- iommus = <&adreno_smmu 1 0x0>;
- };
-
gpu: gpu@3d00000 {
compatible = "qcom,adreno-43051401", "qcom,adreno";
reg = <0x0 0x03d00000 0x0 0x40000>,
@@ -4254,6 +4247,13 @@ opp-834000000 {
};
};
+ lpac: lpac@3dc1000 {
+ compatible = "qcom,lpac";
+ reg = <0x0 0x03d00000 0x0 0x61000>;
+
+ iommus = <&adreno_smmu 1 0x0>;
+ };
+
gmu: gmu@3d6a000 {
compatible = "qcom,adreno-gmu-750.1", "qcom,adreno-gmu";
reg = <0x0 0x03d6a000 0x0 0x35000>,
--
2.54.0
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH RFC 09/13] temp: add LPAC regs
2026-07-05 19:13 [RFC PATCH 00/13] Enable LPAC on a7xx series GPUs Anna Maniscalco
` (7 preceding siblings ...)
2026-07-05 19:13 ` [PATCH RFC 08/13] HACK: use cb1 address in lpac dtb node Anna Maniscalco
@ 2026-07-05 19:13 ` Anna Maniscalco
2026-07-05 19:23 ` sashiko-bot
2026-07-05 19:13 ` [PATCH RFC 10/13] drm/msm: initialize LPAC ring Anna Maniscalco
` (4 subsequent siblings)
13 siblings, 1 reply; 34+ messages in thread
From: Anna Maniscalco @ 2026-07-05 19:13 UTC (permalink / raw)
To: Rob Clark, Will Deacon, Robin Murphy, Joerg Roedel, Sean Paul,
Konrad Dybcio, Akhil P Oommen, Dmitry Baryshkov, Abhinav Kumar,
Jessica Zhang, Marijn Suijten, David Airlie, Simona Vetter,
Bjorn Andersson, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann
Cc: iommu, linux-arm-msm, linux-arm-kernel, linux-kernel, dri-devel,
freedreno, devicetree, Anna Maniscalco
https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/39416
should we merged and we should sync to mesa instead
Signed-off-by: Anna Maniscalco <anna.maniscalco2000@gmail.com>
---
drivers/gpu/drm/msm/registers/adreno/a6xx.xml | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/drivers/gpu/drm/msm/registers/adreno/a6xx.xml b/drivers/gpu/drm/msm/registers/adreno/a6xx.xml
index 3349c01646e1..bb49f6a61a9a 100644
--- a/drivers/gpu/drm/msm/registers/adreno/a6xx.xml
+++ b/drivers/gpu/drm/msm/registers/adreno/a6xx.xml
@@ -276,6 +276,11 @@ by a particular renderpass/blit.
<bitfield pos="1" name="ACCESS_FAULT_ON_VIOL_EN" type="boolean"/>
<bitfield pos="0" name="ACCESS_PROT_EN" type="boolean"/>
</bitset>
+ <reg32 offset="0x0B09" name="CP_LPAC_PROTECT_CNTL">
+ <bitfield pos="3" name="LAST_SPAN_INF_RANGE" type="boolean"/>
+ <bitfield pos="1" name="ACCESS_FAULT_ON_VIOL_EN" type="boolean"/>
+ <bitfield pos="0" name="ACCESS_PROT_EN" type="boolean"/>
+ </reg32>
<reg32 offset="0x084f" name="CP_PROTECT_CNTL" type="a6xx_cp_protect_cntl" variants="A6XX-A7XX"/>
<bitset name="a8xx_cp_protect_cntl" inline="yes">
@@ -333,6 +338,11 @@ by a particular renderpass/blit.
<reg32 offset="0x0845" name="CP_CRASH_DUMP_STATUS" variants="A8XX-"/>
<reg32 offset="0x0908" name="CP_SQE_STAT_ADDR" variants="A6XX-A7XX"/>
<reg32 offset="0x0909" name="CP_SQE_STAT_DATA" variants="A6XX-A7XX"/>
+ <reg64 offset="0x0b00" name="CP_LPAC_RB_BASE" variants="A7XX-"/>
+ <reg32 offset="0x0b02" name="CP_LPAC_RB_CNTL" variants="A7XX-"/>
+ <reg64 offset="0x0b04" name="CP_LPAC_RB_RPTR_ADDR" variants="A7XX-"/>
+ <reg32 offset="0x0b06" name="CP_LPAC_RB_RPTR" variants="A7XX-"/>
+ <reg32 offset="0x0b07" name="CP_LPAC_RB_WPTR" variants="A7XX-"/>
<reg32 offset="0x090a" name="CP_DRAW_STATE_ADDR" variants="A6XX-A7XX"/>
<reg32 offset="0x090b" name="CP_DRAW_STATE_DATA" variants="A6XX-A7XX"/>
<reg32 offset="0x090c" name="CP_ROQ_DBG_ADDR" variants="A6XX-A7XX"/>
@@ -521,6 +531,7 @@ by a particular renderpass/blit.
<reg32 offset="0x0b29" name="CP_SQE_AC_STAT_ADDR" variants="A7XX"/>
<reg32 offset="0x0b2a" name="CP_SQE_AC_STAT_DATA" variants="A7XX"/>
+ <reg32 offset="0x0b30" name="CP_LPAC_CHICKEN_DBG" variants="A7XX-"/>
<reg32 offset="0x0b31" name="CP_LPAC_APRIV_CNTL" variants="A7XX"/>
<reg32 offset="0x0b34" name="CP_LPAC_PROG_FIFO_SIZE" variants="A7XX"/>
<reg32 offset="0x0b35" name="CP_LPAC_ROQ_DBG_DATA" variants="A7XX"/>
@@ -1207,6 +1218,7 @@ by a particular renderpass/blit.
<reg64 offset="0x0E08" name="UCHE_TRAP_BASE" variants="A8XX-"/>
<reg64 offset="0x0E0B" name="UCHE_GMEM_RANGE_MIN" variants="A6XX-A7XX"/>
<reg64 offset="0x0E0D" name="UCHE_GMEM_RANGE_MAX" variants="A6XX-A7XX"/>
+ <reg32 offset="0x0E12" name="UCHE_DEBUG_CNTL_1" usage="cmd"/>
<reg32 offset="0x0e17" name="UCHE_CACHE_WAYS" variants="A6XX-A7XX" usage="init"/>
<reg32 offset="0x0e04" name="UCHE_CACHE_WAYS" variants="A8XX-"/>
<reg32 offset="0x0E18" name="UCHE_FILTER_CNTL"/>
@@ -4406,6 +4418,8 @@ by a particular renderpass/blit.
<array offset="0xaec0" name="SP_PERFCTR_HLSQ_SEL_2" stride="1" length="6" variants="A7XX-"/>
+ <reg32 offset="0xaf84" name="SP_LPAC_CHICKEN_BITS_2" variants="A7XX-" usage="cmd"/>
+
<!--
The downstream kernel calls the debug cluster of registers
"a6xx_sp_ps_tp_cluster" but this actually specifies the border
--
2.54.0
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH RFC 10/13] drm/msm: initialize LPAC ring
2026-07-05 19:13 [RFC PATCH 00/13] Enable LPAC on a7xx series GPUs Anna Maniscalco
` (8 preceding siblings ...)
2026-07-05 19:13 ` [PATCH RFC 09/13] temp: add LPAC regs Anna Maniscalco
@ 2026-07-05 19:13 ` Anna Maniscalco
2026-07-05 19:26 ` sashiko-bot
2026-07-06 8:44 ` Konrad Dybcio
2026-07-05 19:13 ` [PATCH RFC 11/13] drm/msm: Add LPAC submitqueue Anna Maniscalco
` (3 subsequent siblings)
13 siblings, 2 replies; 34+ messages in thread
From: Anna Maniscalco @ 2026-07-05 19:13 UTC (permalink / raw)
To: Rob Clark, Will Deacon, Robin Murphy, Joerg Roedel, Sean Paul,
Konrad Dybcio, Akhil P Oommen, Dmitry Baryshkov, Abhinav Kumar,
Jessica Zhang, Marijn Suijten, David Airlie, Simona Vetter,
Bjorn Andersson, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann
Cc: iommu, linux-arm-msm, linux-arm-kernel, linux-kernel, dri-devel,
freedreno, devicetree, Anna Maniscalco
Program all the register needed to start up LPAC and send initialization
sequence.
Additionally, now that the LPAC ring is live, make the code aware of it.
Signed-off-by: Anna Maniscalco <anna.maniscalco2000@gmail.com>
---
drivers/gpu/drm/msm/adreno/a6xx_catalog.c | 1 +
drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 98 ++++++++++++++++++++++++++++--
drivers/gpu/drm/msm/adreno/adreno_device.c | 6 ++
drivers/gpu/drm/msm/adreno/adreno_gpu.c | 32 ++++++----
drivers/gpu/drm/msm/msm_gpu.c | 21 ++++++-
drivers/gpu/drm/msm/msm_gpu.h | 9 +++
6 files changed, 148 insertions(+), 19 deletions(-)
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_catalog.c b/drivers/gpu/drm/msm/adreno/a6xx_catalog.c
index 3e6f409d13a2..5ee00eead14c 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_catalog.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_catalog.c
@@ -1394,6 +1394,7 @@ static const u32 a750_ifpc_reglist_regs[] = {
REG_A6XX_SP_NC_MODE_CNTL,
REG_A6XX_CP_DBG_ECO_CNTL,
REG_A6XX_CP_PROTECT_CNTL,
+ REG_A6XX_CP_LPAC_PROTECT_CNTL,
REG_A6XX_CP_PROTECT(0),
REG_A6XX_CP_PROTECT(1),
REG_A6XX_CP_PROTECT(2),
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
index 8b3bb2fd433b..9f69aada9b7b 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
@@ -168,6 +168,18 @@ void a6xx_flush(struct msm_gpu *gpu, struct msm_ringbuffer *ring)
update_shadow_rptr(gpu, ring);
+ if (ring == gpu->lpac_rb) {
+ /* Copy the shadow to the actual register */
+ ring->cur = ring->next;
+
+ /* Make sure to wrap wptr if we need to */
+ wptr = get_wptr(ring);
+
+ a6xx_fenced_write(a6xx_gpu, REG_A7XX_CP_LPAC_RB_WPTR, wptr, BIT(3), false);
+
+ return;
+ }
+
spin_lock_irqsave(&ring->preempt_lock, flags);
/* Copy the shadow to the actual register */
@@ -730,6 +742,12 @@ static void a6xx_set_cp_protect(struct msm_gpu *gpu)
A6XX_CP_PROTECT_CNTL_ACCESS_FAULT_ON_VIOL_EN |
A6XX_CP_PROTECT_CNTL_LAST_SPAN_INF_RANGE);
+ //TODO if LPAC
+ gpu_write(gpu, REG_A6XX_CP_LPAC_PROTECT_CNTL,
+ A6XX_CP_PROTECT_CNTL_ACCESS_PROT_EN |
+ A6XX_CP_PROTECT_CNTL_ACCESS_FAULT_ON_VIOL_EN |
+ A6XX_CP_PROTECT_CNTL_LAST_SPAN_INF_RANGE);
+
for (i = 0; i < protect->count - 1; i++) {
/* Intentionally skip writing to some registers */
if (protect->regs[i])
@@ -972,6 +990,53 @@ static int a7xx_cp_init(struct msm_gpu *gpu)
return a6xx_idle(gpu, ring) ? 0 : -EINVAL;
}
+static int lpac_cp_init(struct msm_gpu *gpu)
+{
+ struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
+ struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
+ struct msm_ringbuffer *ring = gpu->lpac_rb;
+ u32 mask;
+
+ OUT_PKT7(ring, CP_ME_INIT, 7);
+
+ /* Use multiple HW contexts */
+ mask = BIT(0);
+
+ /* Enable error detection */
+ mask |= BIT(1);
+
+ /* Set default reset state */
+ mask |= BIT(3);
+
+ /* Disable save/restore of performance counters across preemption */
+ mask |= BIT(6);
+
+ /* Enable the register init list with the spinlock */
+ mask |= BIT(8);
+
+ OUT_RING(ring, mask);
+
+ /* Enable multiple hardware contexts */
+ OUT_RING(ring, 0x00000003);
+
+ /* Enable error detection */
+ OUT_RING(ring, 0x20000000);
+
+ /* Operation mode mask */
+ OUT_RING(ring, 0x00000002);
+
+ /* *Don't* send a power up reg list for concurrent binning (TODO) */
+ /* Lo address */
+ OUT_RING(ring, lower_32_bits(a6xx_gpu->pwrup_reglist_iova));
+ /* Hi address */
+ OUT_RING(ring, upper_32_bits(a6xx_gpu->pwrup_reglist_iova));
+ /* BIT(31) set => read the regs from the list */
+ OUT_RING(ring, BIT(31));
+
+ a6xx_flush(gpu, ring);
+ return a6xx_idle(gpu, ring) ? 0 : -EINVAL;
+}
+
/*
* Check that the microcode version is new enough to include several key
* security fixes. Return true if the ucode is safe.
@@ -1096,7 +1161,7 @@ static int a6xx_ucode_load(struct msm_gpu *gpu)
if ((adreno_gpu->base.hw_apriv || a6xx_gpu->has_whereami) &&
!a6xx_gpu->shadow_bo) {
a6xx_gpu->shadow = msm_gem_kernel_new(gpu->dev,
- sizeof(u32) * gpu->nr_rings,
+ sizeof(u32) * (gpu->nr_rings + !!gpu->lpac_rb),
MSM_BO_WC | MSM_BO_MAP_PRIV,
gpu->vm, &a6xx_gpu->shadow_bo,
&a6xx_gpu->shadow_iova);
@@ -1289,6 +1354,8 @@ static int hw_init(struct msm_gpu *gpu)
gpu_write(gpu, REG_A6XX_UCHE_CACHE_WAYS, 0x4);
}
+ gpu_rmw(gpu, REG_A6XX_UCHE_DEBUG_CNTL_1, BIT(30), BIT(30));
+
if (adreno_is_a640_family(adreno_gpu) || adreno_is_a650_family(adreno_gpu)) {
gpu_write(gpu, REG_A6XX_CP_ROQ_THRESHOLDS_2, 0x02000140);
gpu_write(gpu, REG_A6XX_CP_ROQ_THRESHOLDS_1, 0x8040362c);
@@ -1386,6 +1453,11 @@ static int hw_init(struct msm_gpu *gpu)
gpu_write(gpu, REG_A6XX_CP_CHICKEN_DBG, BIT(24));
}
+ 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));
+
if (adreno_is_a690(adreno_gpu))
gpu_write(gpu, REG_A6XX_UCHE_CMDQ_CONFIG, 0x90);
/* Set dualQ + disable afull for A660 GPU */
@@ -1437,13 +1509,17 @@ static int hw_init(struct msm_gpu *gpu)
/* Set the ringbuffer address */
gpu_write64(gpu, REG_A6XX_CP_RB_BASE, gpu->rb[0]->iova);
+ /* Set the ringbuffer address for lpac */
+ gpu_write64(gpu, REG_A7XX_CP_LPAC_RB_BASE, gpu->lpac_rb->iova);
+
/* Targets that support extended APRIV can use the RPTR shadow from
* hardware but all the other ones need to disable the feature. Targets
* that support the WHERE_AM_I opcode can use that instead
*/
- if (adreno_gpu->base.hw_apriv)
+ if (adreno_gpu->base.hw_apriv) {
gpu_write(gpu, REG_A6XX_CP_RB_CNTL, MSM_GPU_RB_CNTL_DEFAULT);
- else
+ gpu_write(gpu, REG_A7XX_CP_LPAC_RB_CNTL, MSM_GPU_RB_CNTL_DEFAULT);
+ } else
gpu_write(gpu, REG_A6XX_CP_RB_CNTL,
MSM_GPU_RB_CNTL_DEFAULT | AXXX_CP_RB_CNTL_NO_UPDATE);
@@ -1451,7 +1527,10 @@ static int hw_init(struct msm_gpu *gpu)
if (a6xx_gpu->shadow_bo) {
gpu_write64(gpu, REG_A6XX_CP_RB_RPTR_ADDR,
shadowptr(a6xx_gpu, gpu->rb[0]));
- for (unsigned int i = 0; i < gpu->nr_rings; i++)
+ if (gpu->lpac_rb)
+ gpu_write64(gpu, REG_A7XX_CP_LPAC_RB_RPTR_ADDR,
+ shadowptr(a6xx_gpu, gpu->lpac_rb));
+ for (unsigned int i = 0; i < (gpu->nr_rings + !!gpu->lpac_rb); i++)
a6xx_gpu->shadow[i] = 0;
}
@@ -1469,9 +1548,16 @@ static int hw_init(struct msm_gpu *gpu)
for (i = 0; i < gpu->nr_rings; i++)
gpu->rb[i]->cur_ctx_seqno = 0;
+ if (gpu->lpac_rb)
+ gpu->lpac_rb->cur_ctx_seqno = 0;
+
/* Enable the SQE_to start the CP engine */
gpu_write(gpu, REG_A6XX_CP_SQE_CNTL, 1);
+ /* Enable the LPAC SQE_to start the CP engine */
+ //TODO is this needed? Doesn't fw do this at init?
+ gpu_write(gpu, REG_A6XX_CP_LPAC_SQE_CNTL, 1);
+
if (adreno_is_a7xx(adreno_gpu) && !a6xx_gpu->pwrup_reglist_emitted) {
a7xx_patch_pwrup_reglist(gpu);
a6xx_gpu->pwrup_reglist_emitted = true;
@@ -1481,6 +1567,10 @@ static int hw_init(struct msm_gpu *gpu)
if (ret)
goto out;
+ ret = lpac_cp_init(gpu);
+ if (ret)
+ goto out;
+
/*
* Try to load a zap shader into the secure world. If successful
* we can use the CP to switch out of secure mode. If not then we
diff --git a/drivers/gpu/drm/msm/adreno/adreno_device.c b/drivers/gpu/drm/msm/adreno/adreno_device.c
index 7f20320ef66a..881fa09f3943 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_device.c
+++ b/drivers/gpu/drm/msm/adreno/adreno_device.c
@@ -349,6 +349,9 @@ static void suspend_scheduler(struct msm_gpu *gpu)
drm_sched_wqueue_stop(sched);
}
+
+ if (gpu->lpac_rb)
+ drm_sched_wqueue_stop(&gpu->lpac_rb->sched);
}
static void resume_scheduler(struct msm_gpu *gpu)
@@ -360,6 +363,9 @@ static void resume_scheduler(struct msm_gpu *gpu)
drm_sched_wqueue_start(sched);
}
+
+ if (gpu->lpac_rb)
+ drm_sched_wqueue_start(&gpu->lpac_rb->sched);
}
static int adreno_system_suspend(struct device *dev)
diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
index 6a48e211fa3c..94dbec9464a4 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
@@ -655,6 +655,22 @@ struct drm_gem_object *adreno_fw_create_bo(struct msm_gpu *gpu,
return bo;
}
+static inline void init_ring(struct msm_ringbuffer *ring)
+{
+ ring->cur = ring->start;
+ ring->next = ring->start;
+ ring->memptrs->rptr = 0;
+ ring->memptrs->bv_fence = ring->fctx->completed_fence;
+
+ /* Detect and clean up an impossible fence, ie. if GPU managed
+ * to scribble something invalid, we don't want that to confuse
+ * us into mistakingly believing that submits have completed.
+ */
+ if (fence_before(ring->fctx->last_fence, ring->memptrs->fence)) {
+ ring->memptrs->fence = ring->fctx->last_fence;
+ }
+}
+
int adreno_hw_init(struct msm_gpu *gpu)
{
struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
@@ -679,20 +695,12 @@ int adreno_hw_init(struct msm_gpu *gpu)
if (!ring)
continue;
- ring->cur = ring->start;
- ring->next = ring->start;
- ring->memptrs->rptr = 0;
- ring->memptrs->bv_fence = ring->fctx->completed_fence;
-
- /* Detect and clean up an impossible fence, ie. if GPU managed
- * to scribble something invalid, we don't want that to confuse
- * us into mistakingly believing that submits have completed.
- */
- if (fence_before(ring->fctx->last_fence, ring->memptrs->fence)) {
- ring->memptrs->fence = ring->fctx->last_fence;
- }
+ init_ring(ring);
}
+ if (gpu->lpac_rb)
+ init_ring(gpu->lpac_rb);
+
return 0;
}
diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c
index 18ed00e5f143..932e2a7c24b3 100644
--- a/drivers/gpu/drm/msm/msm_gpu.c
+++ b/drivers/gpu/drm/msm/msm_gpu.c
@@ -739,8 +739,8 @@ static void retire_submits(struct msm_gpu *gpu)
int i;
/* Retire the commits starting with highest priority */
- for (i = 0; i < gpu->nr_rings; i++) {
- struct msm_ringbuffer *ring = gpu->rb[i];
+ 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;
while (true) {
struct msm_gem_submit *submit = NULL;
@@ -782,6 +782,9 @@ void msm_gpu_retire(struct msm_gpu *gpu)
for (i = 0; i < gpu->nr_rings; i++)
msm_update_fence(gpu->rb[i]->fctx, gpu->rb[i]->memptrs->fence);
+ if (gpu->lpac_rb)
+ msm_update_fence(gpu->lpac_rb->fctx, gpu->lpac_rb->memptrs->fence);
+
kthread_queue_work(gpu->worker, &gpu->retire_work);
}
@@ -973,7 +976,7 @@ int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev,
}
memptrs = msm_gem_kernel_new(drm,
- sizeof(struct msm_rbmemptrs) * nr_rings,
+ sizeof(struct msm_rbmemptrs) * (nr_rings + 1),
check_apriv(gpu, MSM_BO_WC), gpu->vm, &gpu->memptrs_bo,
&memptrs_iova);
@@ -1006,6 +1009,15 @@ int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev,
memptrs_iova += sizeof(struct msm_rbmemptrs);
}
+ gpu->lpac_rb = msm_ringbuffer_new(gpu, nr_rings, memptrs, memptrs_iova);
+
+ if (IS_ERR(gpu->rb[i])) {
+ ret = PTR_ERR(gpu->rb[i]);
+ DRM_DEV_ERROR(drm->dev,
+ "could not create lpac ringbuffer %d\n", ret);
+ goto fail;
+ }
+
gpu->nr_rings = nr_rings;
refcount_set(&gpu->sysprof_active, 1);
@@ -1046,6 +1058,9 @@ void msm_gpu_cleanup(struct msm_gpu *gpu)
gpu->rb[i] = NULL;
}
+ msm_ringbuffer_destroy(gpu->lpac_rb);
+ gpu->lpac_rb = NULL;
+
msm_gem_kernel_put(gpu->memptrs_bo, gpu->vm);
if (!IS_ERR_OR_NULL(gpu->vm)) {
diff --git a/drivers/gpu/drm/msm/msm_gpu.h b/drivers/gpu/drm/msm/msm_gpu.h
index 271956e7f870..9a213fb65b4f 100644
--- a/drivers/gpu/drm/msm/msm_gpu.h
+++ b/drivers/gpu/drm/msm/msm_gpu.h
@@ -181,6 +181,8 @@ struct msm_gpu {
struct msm_ringbuffer *rb[MSM_GPU_MAX_RINGS];
int nr_rings;
+ struct msm_ringbuffer *lpac_rb;
+
/**
* sysprof_active:
*
@@ -323,6 +325,13 @@ static inline bool msm_gpu_active(struct msm_gpu *gpu)
return true;
}
+ if (gpu->lpac_rb) {
+ struct msm_ringbuffer *ring = gpu->lpac_rb;
+
+ if (fence_after(ring->fctx->last_fence, ring->memptrs->fence))
+ return true;
+ }
+
return false;
}
--
2.54.0
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH RFC 11/13] drm/msm: Add LPAC submitqueue
2026-07-05 19:13 [RFC PATCH 00/13] Enable LPAC on a7xx series GPUs Anna Maniscalco
` (9 preceding siblings ...)
2026-07-05 19:13 ` [PATCH RFC 10/13] drm/msm: initialize LPAC ring Anna Maniscalco
@ 2026-07-05 19:13 ` Anna Maniscalco
2026-07-05 19:36 ` sashiko-bot
2026-07-05 19:13 ` [PATCH RFC 12/13] drm/msm: set ctxbank and asid based on ring Anna Maniscalco
` (2 subsequent siblings)
13 siblings, 1 reply; 34+ messages in thread
From: Anna Maniscalco @ 2026-07-05 19:13 UTC (permalink / raw)
To: Rob Clark, Will Deacon, Robin Murphy, Joerg Roedel, Sean Paul,
Konrad Dybcio, Akhil P Oommen, Dmitry Baryshkov, Abhinav Kumar,
Jessica Zhang, Marijn Suijten, David Airlie, Simona Vetter,
Bjorn Andersson, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann
Cc: iommu, linux-arm-msm, linux-arm-kernel, linux-kernel, dri-devel,
freedreno, devicetree, Anna Maniscalco
Add UAPI and infostructure to support sending submission to the LPAC
ring.
Signed-off-by: Anna Maniscalco <anna.maniscalco2000@gmail.com>
---
drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 86 ++++++++++++++++++++++-------------
drivers/gpu/drm/msm/adreno/a6xx_gpu.h | 2 +-
drivers/gpu/drm/msm/msm_gem_submit.c | 6 ++-
drivers/gpu/drm/msm/msm_gpu.c | 8 ++--
drivers/gpu/drm/msm/msm_gpu.h | 4 +-
drivers/gpu/drm/msm/msm_submitqueue.c | 11 ++++-
include/uapi/drm/msm_drm.h | 2 +
7 files changed, 78 insertions(+), 41 deletions(-)
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
index 9f69aada9b7b..4417a9d04d7c 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
@@ -204,8 +204,10 @@ void a6xx_flush(struct msm_gpu *gpu, struct msm_ringbuffer *ring)
void
a6xx_flush_yield(struct msm_gpu *gpu, struct msm_ringbuffer *ring)
{
+ bool is_lpac = ring == gpu->lpac_rb;
+
/* If preemption is enabled */
- if (gpu->nr_rings > 1) {
+ if (gpu->nr_rings > 1 && !is_lpac) {
/* Yield the floor on command completion */
OUT_PKT7(ring, CP_CONTEXT_SWITCH_YIELD, 4);
@@ -244,6 +246,7 @@ static void a6xx_set_pagetable(struct a6xx_gpu *a6xx_gpu,
struct drm_gpuvm *vm = msm_context_vm(submit->dev, ctx);
struct adreno_gpu *adreno_gpu = &a6xx_gpu->base;
phys_addr_t ttbr;
+ bool is_lpac = ring == a6xx_gpu->base.base.lpac_rb;
u32 asid;
u64 memptr = rbmemptr(ring, ttbr0);
@@ -261,25 +264,27 @@ static void a6xx_set_pagetable(struct a6xx_gpu *a6xx_gpu,
OUT_RING(ring, upper_32_bits(rbmemptr(ring, fence)));
OUT_RING(ring, submit->seqno - 1);
- OUT_PKT7(ring, CP_THREAD_CONTROL, 1);
- OUT_RING(ring, CP_THREAD_CONTROL_0_SYNC_THREADS | CP_SET_THREAD_BOTH);
+ if (!is_lpac) {
+ OUT_PKT7(ring, CP_THREAD_CONTROL, 1);
+ OUT_RING(ring, CP_THREAD_CONTROL_0_SYNC_THREADS | CP_SET_THREAD_BOTH);
- /* Reset state used to synchronize BR and BV */
- OUT_PKT7(ring, CP_RESET_CONTEXT_STATE, 1);
- OUT_RING(ring,
- CP_RESET_CONTEXT_STATE_0_CLEAR_ON_CHIP_TS |
- CP_RESET_CONTEXT_STATE_0_CLEAR_RESOURCE_TABLE |
- CP_RESET_CONTEXT_STATE_0_CLEAR_BV_BR_COUNTER |
- CP_RESET_CONTEXT_STATE_0_RESET_GLOBAL_LOCAL_TS);
+ /* Reset state used to synchronize BR and BV */
+ OUT_PKT7(ring, CP_RESET_CONTEXT_STATE, 1);
+ OUT_RING(ring,
+ CP_RESET_CONTEXT_STATE_0_CLEAR_ON_CHIP_TS |
+ CP_RESET_CONTEXT_STATE_0_CLEAR_RESOURCE_TABLE |
+ CP_RESET_CONTEXT_STATE_0_CLEAR_BV_BR_COUNTER |
+ CP_RESET_CONTEXT_STATE_0_RESET_GLOBAL_LOCAL_TS);
- OUT_PKT7(ring, CP_THREAD_CONTROL, 1);
- OUT_RING(ring, CP_THREAD_CONTROL_0_SYNC_THREADS | CP_SET_THREAD_BOTH);
+ OUT_PKT7(ring, CP_THREAD_CONTROL, 1);
+ OUT_RING(ring, CP_THREAD_CONTROL_0_SYNC_THREADS | CP_SET_THREAD_BOTH);
- OUT_PKT7(ring, CP_EVENT_WRITE, 1);
- OUT_RING(ring, LRZ_FLUSH_INVALIDATE);
+ OUT_PKT7(ring, CP_EVENT_WRITE, 1);
+ OUT_RING(ring, LRZ_FLUSH_INVALIDATE);
- OUT_PKT7(ring, CP_THREAD_CONTROL, 1);
- OUT_RING(ring, CP_THREAD_CONTROL_0_SYNC_THREADS | CP_SET_THREAD_BR);
+ OUT_PKT7(ring, CP_THREAD_CONTROL, 1);
+ OUT_RING(ring, CP_THREAD_CONTROL_0_SYNC_THREADS | CP_SET_THREAD_BR);
+ }
}
if (!sysprof) {
@@ -493,7 +498,10 @@ static void a7xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
struct msm_ringbuffer *ring = submit->ring;
- u32 rbbm_perfctr_cp0, cp_always_on_context;
+ u32 rbbm_perfctr_cp0, cp_always_on_context,
+ cp_always_on_counter;
+ bool is_lpac = ring == gpu->lpac_rb;
+ u64 timestamp_iova;
unsigned int i, ibs = 0;
adreno_check_and_reenable_stall(adreno_gpu);
@@ -511,19 +519,24 @@ static void a7xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
* If preemption is enabled, then set the pseudo register for the save
* sequence
*/
- if (gpu->nr_rings > 1)
+ if (gpu->nr_rings > 1 && !is_lpac)
a6xx_emit_set_pseudo_reg(ring, a6xx_gpu, submit->queue);
if (adreno_is_a8xx(adreno_gpu)) {
rbbm_perfctr_cp0 = REG_A8XX_RBBM_PERFCTR_CP(0);
cp_always_on_context = REG_A8XX_CP_ALWAYS_ON_CONTEXT;
+ cp_always_on_counter = REG_A8XX_CP_ALWAYS_ON_COUNTER;
} else {
rbbm_perfctr_cp0 = REG_A7XX_RBBM_PERFCTR_CP(0);
cp_always_on_context = REG_A6XX_CP_ALWAYS_ON_CONTEXT;
+ cp_always_on_counter = REG_A6XX_CP_ALWAYS_ON_COUNTER;
}
get_stats_counter(ring, rbbm_perfctr_cp0, rbmemptr_stats(ring, index, cpcycles_start));
- get_stats_counter(ring, cp_always_on_context, rbmemptr_stats(ring, index, alwayson_start));
+ 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));
OUT_PKT7(ring, CP_THREAD_CONTROL, 1);
OUT_RING(ring, CP_SET_THREAD_BOTH);
@@ -582,17 +595,19 @@ static void a7xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
OUT_RING(ring, submit->seqno);
}
- OUT_PKT7(ring, CP_THREAD_CONTROL, 1);
- OUT_RING(ring, CP_SET_THREAD_BR);
+ if (!is_lpac) {
+ OUT_PKT7(ring, CP_THREAD_CONTROL, 1);
+ OUT_RING(ring, CP_SET_THREAD_BR);
- OUT_PKT7(ring, CP_EVENT_WRITE, 1);
- OUT_RING(ring, CCU_INVALIDATE_DEPTH);
+ OUT_PKT7(ring, CP_EVENT_WRITE, 1);
+ OUT_RING(ring, CCU_INVALIDATE_DEPTH);
- OUT_PKT7(ring, CP_EVENT_WRITE, 1);
- OUT_RING(ring, CCU_INVALIDATE_COLOR);
+ OUT_PKT7(ring, CP_EVENT_WRITE, 1);
+ OUT_RING(ring, CCU_INVALIDATE_COLOR);
- OUT_PKT7(ring, CP_THREAD_CONTROL, 1);
- OUT_RING(ring, CP_SET_THREAD_BV);
+ OUT_PKT7(ring, CP_THREAD_CONTROL, 1);
+ OUT_RING(ring, CP_SET_THREAD_BV);
+ }
/*
* Make sure the timestamp is committed once BV pipe is
@@ -638,10 +653,12 @@ static void a7xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
a6xx_flush_yield(gpu, ring);
/* Check to see if we need to start preemption */
- if (adreno_is_a8xx(adreno_gpu))
- a8xx_preempt_trigger(gpu);
- else
- a6xx_preempt_trigger(gpu);
+ if (!is_lpac) {
+ if (adreno_is_a8xx(adreno_gpu))
+ a8xx_preempt_trigger(gpu);
+ else
+ a6xx_preempt_trigger(gpu);
+ }
}
static void a6xx_set_hwcg(struct msm_gpu *gpu, bool state)
@@ -1219,6 +1236,7 @@ int a6xx_zap_shader_init(struct msm_gpu *gpu)
A6XX_RBBM_INT_0_MASK_PM4CPINTERRUPT | \
A6XX_RBBM_INT_0_MASK_CP_RB_DONE_TS | \
A6XX_RBBM_INT_0_MASK_CP_CACHE_FLUSH_TS | \
+ A6XX_RBBM_INT_0_MASK_CP_CACHE_FLUSH_TS_LPAC | \
A6XX_RBBM_INT_0_MASK_RBBM_ATB_BUS_OVERFLOW | \
A6XX_RBBM_INT_0_MASK_RBBM_HANG_DETECT | \
A6XX_RBBM_INT_0_MASK_UCHE_OOB_ACCESS | \
@@ -2030,6 +2048,9 @@ static irqreturn_t a6xx_irq(struct msm_gpu *gpu)
a6xx_preempt_trigger(gpu);
}
+ if (status & A6XX_RBBM_INT_0_MASK_CP_CACHE_FLUSH_TS_LPAC)
+ msm_gpu_retire(gpu);
+
if (status & A6XX_RBBM_INT_0_MASK_CP_SW)
a6xx_preempt_irq(gpu);
@@ -2500,6 +2521,9 @@ static bool a6xx_progress(struct msm_gpu *gpu, struct msm_ringbuffer *ring)
if (to_adreno_gpu(gpu)->info->quirks & ADRENO_QUIRK_IFPC)
return true;
+ if (ring == gpu->lpac_rb)
+ return true;
+
cp_state = (struct msm_cp_state) {
.ib1_base = gpu_read64(gpu, REG_A6XX_CP_IB1_BASE),
.ib2_base = gpu_read64(gpu, REG_A6XX_CP_IB2_BASE),
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.h b/drivers/gpu/drm/msm/adreno/a6xx_gpu.h
index b50c57f427b4..d85f2536551c 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.h
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.h
@@ -75,7 +75,7 @@ struct a6xx_gpu {
struct drm_gem_object *preempt_smmu_bo[MSM_GPU_MAX_RINGS];
void *preempt_smmu[MSM_GPU_MAX_RINGS];
uint64_t preempt_smmu_iova[MSM_GPU_MAX_RINGS];
- uint32_t last_seqno[MSM_GPU_MAX_RINGS];
+ uint32_t last_seqno[MSM_GPU_MAX_RINGS + 1];
atomic_t preempt_state;
spinlock_t eval_lock;
diff --git a/drivers/gpu/drm/msm/msm_gem_submit.c b/drivers/gpu/drm/msm/msm_gem_submit.c
index 26ea8a28be47..45e7f8b72dc9 100644
--- a/drivers/gpu/drm/msm/msm_gem_submit.c
+++ b/drivers/gpu/drm/msm/msm_gem_submit.c
@@ -71,7 +71,8 @@ static struct msm_gem_submit *submit_create(struct drm_device *dev,
submit->cmd = (void *)&submit->bos[nr_bos];
submit->queue = queue;
submit->pid = get_pid(task_pid(current));
- submit->ring = gpu->rb[queue->ring_nr];
+ submit->ring = queue->ring_nr == gpu->nr_rings ?
+ gpu->lpac_rb : gpu->rb[queue->ring_nr];
submit->fault_dumped = false;
/* Get a unique identifier for the submission for logging purposes */
@@ -599,7 +600,8 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
goto out_post_unlock;
}
- ring = gpu->rb[queue->ring_nr];
+ ring = queue->ring_nr == gpu->nr_rings ?
+ gpu->lpac_rb : gpu->rb[queue->ring_nr];
if (args->flags & MSM_SUBMIT_FENCE_FD_OUT) {
out_fence_fd = get_unused_fd_flags(O_CLOEXEC);
diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c
index 932e2a7c24b3..38fdf8d95cc0 100644
--- a/drivers/gpu/drm/msm/msm_gpu.c
+++ b/drivers/gpu/drm/msm/msm_gpu.c
@@ -537,8 +537,8 @@ static void recover_worker(struct kthread_work *work)
* needs to happen after msm_rd_dump_submit() to ensure that the
* bo's referenced by the offending submit are still around.
*/
- for (i = 0; i < gpu->nr_rings; i++) {
- struct msm_ringbuffer *ring = gpu->rb[i];
+ 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;
@@ -561,8 +561,8 @@ static void recover_worker(struct kthread_work *work)
* Replay all remaining submits starting with highest priority
* ring
*/
- for (i = 0; i < gpu->nr_rings; i++) {
- struct msm_ringbuffer *ring = gpu->rb[i];
+ 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;
unsigned long flags;
spin_lock_irqsave(&ring->submit_lock, flags);
diff --git a/drivers/gpu/drm/msm/msm_gpu.h b/drivers/gpu/drm/msm/msm_gpu.h
index 9a213fb65b4f..263dafeb9652 100644
--- a/drivers/gpu/drm/msm/msm_gpu.h
+++ b/drivers/gpu/drm/msm/msm_gpu.h
@@ -490,9 +490,11 @@ struct msm_context {
* create at most one &drm_sched_entity per-process per-priority-
* level.
*/
- struct drm_sched_entity *entities[NR_SCHED_PRIORITIES * MSM_GPU_MAX_RINGS];
+ struct drm_sched_entity *entities[NR_SCHED_PRIORITIES * (MSM_GPU_MAX_RINGS + 1)];
+
/**
* @ctx_mem:
+ *
* Total amount of memory of GEM buffers with handles attached for
* this context.
*/
diff --git a/drivers/gpu/drm/msm/msm_submitqueue.c b/drivers/gpu/drm/msm/msm_submitqueue.c
index 1a5a77b28016..042b4f90fb73 100644
--- a/drivers/gpu/drm/msm/msm_submitqueue.c
+++ b/drivers/gpu/drm/msm/msm_submitqueue.c
@@ -175,6 +175,7 @@ int msm_submitqueue_create(struct drm_device *drm, struct msm_context *ctx,
struct msm_drm_private *priv = drm->dev_private;
struct msm_gpu_submitqueue *queue;
enum drm_sched_priority sched_prio;
+ struct msm_ringbuffer *ring;
unsigned ring_nr;
int ret;
@@ -211,6 +212,13 @@ int msm_submitqueue_create(struct drm_device *drm, struct msm_context *ctx,
queue = kzalloc_obj(*queue);
}
+ if (flags & MSM_SUBMITQUEUE_LPAC) {
+ ring_nr = priv->gpu->nr_rings;
+ ring = priv->gpu->lpac_rb;
+ } else {
+ ring = priv->gpu->rb[ring_nr];
+ }
+
if (!queue)
return -ENOMEM;
@@ -227,8 +235,7 @@ int msm_submitqueue_create(struct drm_device *drm, struct msm_context *ctx,
} else {
queue->ring_nr = ring_nr;
- queue->entity = get_sched_entity(ctx, priv->gpu->rb[ring_nr],
- ring_nr, sched_prio);
+ queue->entity = get_sched_entity(ctx, ring, ring_nr, sched_prio);
}
if (IS_ERR(queue->entity)) {
diff --git a/include/uapi/drm/msm_drm.h b/include/uapi/drm/msm_drm.h
index 7f2e594be4eb..058228a56213 100644
--- a/include/uapi/drm/msm_drm.h
+++ b/include/uapi/drm/msm_drm.h
@@ -465,10 +465,12 @@ struct drm_msm_gem_madvise {
#define MSM_SUBMITQUEUE_ALLOW_PREEMPT 0x00000001
#define MSM_SUBMITQUEUE_VM_BIND 0x00000002 /* virtual queue for VM_BIND ops */
+#define MSM_SUBMITQUEUE_LPAC 0x00000004
#define MSM_SUBMITQUEUE_FLAGS ( \
MSM_SUBMITQUEUE_ALLOW_PREEMPT | \
MSM_SUBMITQUEUE_VM_BIND | \
+ MSM_SUBMITQUEUE_LPAC | \
0)
/*
--
2.54.0
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH RFC 12/13] drm/msm: set ctxbank and asid based on ring
2026-07-05 19:13 [RFC PATCH 00/13] Enable LPAC on a7xx series GPUs Anna Maniscalco
` (10 preceding siblings ...)
2026-07-05 19:13 ` [PATCH RFC 11/13] drm/msm: Add LPAC submitqueue Anna Maniscalco
@ 2026-07-05 19:13 ` Anna Maniscalco
2026-07-05 19:13 ` [PATCH RFC 13/13] drm/msm: add lpac ring to devcoredump Anna Maniscalco
2026-07-06 14:57 ` [RFC PATCH 00/13] Enable LPAC on a7xx series GPUs Dmitry Baryshkov
13 siblings, 0 replies; 34+ messages in thread
From: Anna Maniscalco @ 2026-07-05 19:13 UTC (permalink / raw)
To: Rob Clark, Will Deacon, Robin Murphy, Joerg Roedel, Sean Paul,
Konrad Dybcio, Akhil P Oommen, Dmitry Baryshkov, Abhinav Kumar,
Jessica Zhang, Marijn Suijten, David Airlie, Simona Vetter,
Bjorn Andersson, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann
Cc: iommu, linux-arm-msm, linux-arm-kernel, linux-kernel, dri-devel,
freedreno, devicetree, Anna Maniscalco
qcom-arm-smmu always maps asid and ctxbank 1:1 and lpac is always 1
Signed-off-by: Anna Maniscalco <anna.maniscalco2000@gmail.com>
---
drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
index 4417a9d04d7c..a8a061652ec2 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
@@ -247,7 +247,7 @@ static void a6xx_set_pagetable(struct a6xx_gpu *a6xx_gpu,
struct adreno_gpu *adreno_gpu = &a6xx_gpu->base;
phys_addr_t ttbr;
bool is_lpac = ring == a6xx_gpu->base.base.lpac_rb;
- u32 asid;
+ u32 asid, ctxbank;
u64 memptr = rbmemptr(ring, ttbr0);
if (ctx->seqno == ring->cur_ctx_seqno)
@@ -256,6 +256,9 @@ static void a6xx_set_pagetable(struct a6xx_gpu *a6xx_gpu,
if (msm_iommu_pagetable_params(to_msm_vm(vm)->mmu, &ttbr, &asid))
return;
+ /* qcom-arm-smmu always maps asid and ctxbank 1:1 */
+ ctxbank = asid = is_lpac;
+
if (adreno_gpu->info->family >= ADRENO_7XX_GEN1) {
/* Wait for previous submit to complete before continuing: */
OUT_PKT7(ring, CP_WAIT_TIMESTAMP, 4);
@@ -313,7 +316,7 @@ static void a6xx_set_pagetable(struct a6xx_gpu *a6xx_gpu,
CP_SMMU_TABLE_UPDATE_1_TTBR0_HI(upper_32_bits(ttbr)) |
CP_SMMU_TABLE_UPDATE_1_ASID(asid));
OUT_RING(ring, CP_SMMU_TABLE_UPDATE_2_CONTEXTIDR(0));
- OUT_RING(ring, CP_SMMU_TABLE_UPDATE_3_CONTEXTBANK(0));
+ OUT_RING(ring, CP_SMMU_TABLE_UPDATE_3_CONTEXTBANK(ctxbank));
/*
* Write the new TTBR0 to the memstore. This is good for debugging.
--
2.54.0
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH RFC 13/13] drm/msm: add lpac ring to devcoredump
2026-07-05 19:13 [RFC PATCH 00/13] Enable LPAC on a7xx series GPUs Anna Maniscalco
` (11 preceding siblings ...)
2026-07-05 19:13 ` [PATCH RFC 12/13] drm/msm: set ctxbank and asid based on ring Anna Maniscalco
@ 2026-07-05 19:13 ` Anna Maniscalco
2026-07-05 19:35 ` sashiko-bot
2026-07-06 14:57 ` [RFC PATCH 00/13] Enable LPAC on a7xx series GPUs Dmitry Baryshkov
13 siblings, 1 reply; 34+ messages in thread
From: Anna Maniscalco @ 2026-07-05 19:13 UTC (permalink / raw)
To: Rob Clark, Will Deacon, Robin Murphy, Joerg Roedel, Sean Paul,
Konrad Dybcio, Akhil P Oommen, Dmitry Baryshkov, Abhinav Kumar,
Jessica Zhang, Marijn Suijten, David Airlie, Simona Vetter,
Bjorn Andersson, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann
Cc: iommu, linux-arm-msm, linux-arm-kernel, linux-kernel, dri-devel,
freedreno, devicetree, Anna Maniscalco
Add the LPAC ring state to the devcoredump for debugging.
Signed-off-by: Anna Maniscalco <anna.maniscalco2000@gmail.com>
---
drivers/gpu/drm/msm/adreno/adreno_gpu.c | 19 ++++++++++---------
drivers/gpu/drm/msm/msm_gpu.h | 2 +-
2 files changed, 11 insertions(+), 10 deletions(-)
diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
index 94dbec9464a4..030bb1aeb7ee 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
@@ -782,25 +782,26 @@ int adreno_gpu_state_get(struct msm_gpu *gpu, struct msm_gpu_state *state)
ktime_get_real_ts64(&state->time);
- for (i = 0; i < gpu->nr_rings; i++) {
+ 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;
int size = 0, j;
- state->ring[i].fence = gpu->rb[i]->memptrs->fence;
- state->ring[i].iova = gpu->rb[i]->iova;
- state->ring[i].seqno = gpu->rb[i]->fctx->last_fence;
- state->ring[i].rptr = get_rptr(adreno_gpu, gpu->rb[i]);
- state->ring[i].wptr = get_wptr(gpu->rb[i]);
+ state->ring[i].fence = ring->memptrs->fence;
+ state->ring[i].iova = ring->iova;
+ state->ring[i].seqno = ring->fctx->last_fence;
+ state->ring[i].rptr = get_rptr(adreno_gpu, ring);
+ state->ring[i].wptr = get_wptr(ring);
/* Copy at least 'wptr' dwords of the data */
size = state->ring[i].wptr;
/* After wptr find the last non zero dword to save space */
for (j = state->ring[i].wptr; j < MSM_GPU_RINGBUFFER_SZ >> 2; j++)
- if (gpu->rb[i]->start[j])
+ if (ring->start[j])
size = j + 1;
if (size) {
- state->ring[i].data = kvmemdup(gpu->rb[i]->start, size << 2, GFP_KERNEL);
+ state->ring[i].data = kvmemdup(ring->start, size << 2, GFP_KERNEL);
if (state->ring[i].data)
state->ring[i].data_size = size << 2;
}
@@ -1001,7 +1002,7 @@ void adreno_show(struct msm_gpu *gpu, struct msm_gpu_state *state,
drm_puts(p, "ringbuffer:\n");
- for (i = 0; i < gpu->nr_rings; i++) {
+ for (i = 0; i < gpu->nr_rings + !!gpu->lpac_rb; i++) {
drm_printf(p, " - id: %d\n", i);
drm_printf(p, " iova: 0x%016llx\n", state->ring[i].iova);
drm_printf(p, " last-fence: %u\n", state->ring[i].seqno);
diff --git a/drivers/gpu/drm/msm/msm_gpu.h b/drivers/gpu/drm/msm/msm_gpu.h
index 263dafeb9652..4fbf0dedc334 100644
--- a/drivers/gpu/drm/msm/msm_gpu.h
+++ b/drivers/gpu/drm/msm/msm_gpu.h
@@ -639,7 +639,7 @@ struct msm_gpu_state {
void *data;
int data_size;
bool encoded;
- } ring[MSM_GPU_MAX_RINGS];
+ } ring[MSM_GPU_MAX_RINGS+1];
int nr_registers;
u32 *registers;
--
2.54.0
^ permalink raw reply related [flat|nested] 34+ messages in thread
* Re: [PATCH RFC 08/13] HACK: use cb1 address in lpac dtb node
2026-07-05 19:13 ` [PATCH RFC 08/13] HACK: use cb1 address in lpac dtb node Anna Maniscalco
@ 2026-07-05 19:18 ` sashiko-bot
0 siblings, 0 replies; 34+ messages in thread
From: sashiko-bot @ 2026-07-05 19:18 UTC (permalink / raw)
To: Anna Maniscalco; +Cc: devicetree, robh, conor+dt, dri-devel
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] Mismatch between node unit-address and 'reg' property in the 'lpac' node, and incorrect topological sorting.
--
commit 3a9d2680f6799fd4ea05a09430cb0898981bea9a
Author: Anna Maniscalco <anna.maniscalco2000@gmail.com>
HACK: use cb1 address in lpac dtb node
This commit relocates the lpac device tree node within the sm8650 device
tree and modifies its unit-address.
> diff --git a/arch/arm64/boot/dts/qcom/sm8650.dtsi b/arch/arm64/boot/dts/qcom/sm8650.dtsi
> index 44e5f9d4b335f..66ea9155e2289 100644
> --- a/arch/arm64/boot/dts/qcom/sm8650.dtsi
> +++ b/arch/arm64/boot/dts/qcom/sm8650.dtsi
[ ... ]
> @@ -4254,6 +4247,13 @@ opp-834000000 {
> };
> };
>
> + lpac: lpac@3dc1000 {
> + compatible = "qcom,lpac";
> + reg = <0x0 0x03d00000 0x0 0x61000>;
[Severity: Medium]
Does this code miss updating the reg property to match the new unit-address?
The unit-address is set to @3dc1000, but the first address specified in the
reg property is still 0x03d00000.
According to the Devicetree Specification, a node's unit-address must exactly
match the first address in its reg property. Leaving it as 0x03d00000 means
the device continues to map to the old address space (which overlaps with the
gpu node) and fails to actually use the cb1 address. It will also trigger a
unit_address_vs_reg warning from the Device Tree Compiler.
> +
> + iommus = <&adreno_smmu 1 0x0>;
> + };
> +
> gmu: gmu@3d6a000 {
> compatible = "qcom,adreno-gmu-750.1", "qcom,adreno-gmu";
Should the lpac node be placed after this gmu node? Device tree nodes are
typically sorted by unit-address, and 3dc1000 comes after 3d6a000, making
this current placement topologically incorrect.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260705-descriptive-name-lpac-upstream-v1-0-01d50c3e0c99@gmail.com?part=8
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH RFC 05/13] firmware: qcom: scm: Configure LPAC aperture
2026-07-05 19:13 ` [PATCH RFC 05/13] firmware: qcom: scm: Configure LPAC aperture Anna Maniscalco
@ 2026-07-05 19:20 ` sashiko-bot
0 siblings, 0 replies; 34+ messages in thread
From: sashiko-bot @ 2026-07-05 19:20 UTC (permalink / raw)
To: Anna Maniscalco; +Cc: devicetree, robh, conor+dt, dri-devel
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] Unconditional SCM call for LPAC aperture configuration on hardware that does not support it.
- [Medium] Unused mask macro `QCOM_SCM_LPAC_APERTURE_CONTEXT_MASK` and missing `FIELD_PREP` bounds masking in `qcom_scm_set_gpu_smmu_lpac_aperture`.
--
commit 25a397c9a4153cea4348b027438df84a69f95cee
Author: Anna Maniscalco <anna.maniscalco2000@gmail.com>
firmware: qcom: scm: Configure LPAC aperture
In order to be able to update the SMMU registers from CP for page table
updates we need to configure the LPAC aperture to include the context
bank that will be associated with SID 1.
> diff --git a/drivers/firmware/qcom/qcom_scm.c b/drivers/firmware/qcom/qcom_scm.c
> index 9b06a69d3a6d7..92093399f20d9 100644
> --- a/drivers/firmware/qcom/qcom_scm.c
> +++ b/drivers/firmware/qcom/qcom_scm.c
> @@ -1204,6 +1204,7 @@ int qcom_scm_restore_sec_cfg(u32 device_id, u32 spare)
> EXPORT_SYMBOL_GPL(qcom_scm_restore_sec_cfg);
>
> #define QCOM_SCM_CP_APERTURE_CONTEXT_MASK GENMASK(7, 0)
> +#define QCOM_SCM_LPAC_APERTURE_CONTEXT_MASK GENMASK(7, 1)
[Severity: Medium]
This isn't a bug, but QCOM_SCM_LPAC_APERTURE_CONTEXT_MASK is defined here
but left unused. Also, is GENMASK(7, 1) correct, or should it be
GENMASK(7, 0) like the CP mask above?
[ ... ]
> @@ -1229,6 +1230,23 @@ int qcom_scm_set_gpu_smmu_aperture(unsigned int context_bank)
> }
> EXPORT_SYMBOL_GPL(qcom_scm_set_gpu_smmu_aperture);
>
> +int qcom_scm_set_gpu_smmu_lpac_aperture(unsigned int context_bank)
> +{
> + struct qcom_scm_desc desc = {
> + .svc = QCOM_SCM_SVC_MP,
> + .cmd = QCOM_SCM_MP_CP_SMMU_APERTURE_ID,
> + .arginfo = QCOM_SCM_ARGS(4),
> + .args[0] = 0xffff0000 | (1 << 8 | context_bank),
[Severity: Medium]
Should this use FIELD_PREP() with the QCOM_SCM_LPAC_APERTURE_CONTEXT_MASK
defined above?
Directly ORing context_bank bypasses bounds checking, which could
potentially allow an out-of-bounds context_bank to corrupt adjacent bits
like the LPAC bit (1 << 8).
> + .args[1] = 0xffffffff,
> + .args[2] = 0xffffffff,
> + .args[3] = 0xffffffff,
> + .owner = ARM_SMCCC_OWNER_SIP
> + };
> +
> + return qcom_scm_call(__scm->dev, &desc, NULL);
> +}
> +EXPORT_SYMBOL_GPL(qcom_scm_set_gpu_smmu_lpac_aperture);
[ ... ]
> diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
> index 71ce4cbbf27ae..be374cf209f4f 100644
> --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c
> +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
> @@ -668,6 +668,9 @@ int adreno_hw_init(struct msm_gpu *gpu)
> ret = qcom_scm_set_gpu_smmu_aperture(0);
> if (ret)
> DRM_DEV_ERROR(gpu->dev->dev, "unable to set SMMU aperture: %d\n", ret);
> + ret = qcom_scm_set_gpu_smmu_lpac_aperture(1);
> + if (ret)
> + DRM_DEV_ERROR(gpu->dev->dev, "unable to set lpac SMMU aperture: %d\n", ret);
[Severity: High]
Does this unconditionally call qcom_scm_set_gpu_smmu_lpac_aperture() on
hardware that might not support LPAC?
The outer condition only checks qcom_scm_set_gpu_smmu_aperture_is_available()
which verifies the existence of QCOM_SCM_MP_CP_SMMU_APERTURE_ID. Older
ADRENO_6XX_GEN1+ devices support this command for the CP aperture, but
may not support LPAC.
If older firmware rejects the LPAC command, could it cause boot failures or
log errors on every boot and resume?
Alternatively, if the older firmware doesn't validate bit 8 and simply
masks the lower 8 bits, could it silently overwrite the primary CP aperture
context bank from 0 to 1, causing SMMU translation faults and rendering the
GPU unusable?
Should this be conditionally guarded by checking if LPAC is available,
such as checking if gpu->lpac_pdev is non-NULL?
> }
>
> for (int i = 0; i < gpu->nr_rings; i++) {
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260705-descriptive-name-lpac-upstream-v1-0-01d50c3e0c99@gmail.com?part=5
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH RFC 09/13] temp: add LPAC regs
2026-07-05 19:13 ` [PATCH RFC 09/13] temp: add LPAC regs Anna Maniscalco
@ 2026-07-05 19:23 ` sashiko-bot
0 siblings, 0 replies; 34+ messages in thread
From: sashiko-bot @ 2026-07-05 19:23 UTC (permalink / raw)
To: Anna Maniscalco; +Cc: robh, conor+dt, devicetree, dri-devel
Thank you for your contribution! Sashiko AI review found 6 potential issue(s) to consider:
- [High] Missing 'variants' attribute on CP_LPAC_PROTECT_CNTL makes an A7XX-only LPAC register available to older hardware.
- [High] UCHE_DEBUG_CNTL_1 overlaps with existing UCHE_UNKNOWN_0E12 and UCHE_GBIF_GX_CONFIG registers at offset 0x0E12.
- [High] CP_LPAC_RB_* registers are applied to A8XX where they conflict with CP_SLICE_MEM_POOL_DBG_*_PIPE registers.
- [Medium] The patch is explicitly marked as a temporary commit ('temp:') and directly modifies a file that should be synchronized from Mesa.
- [Low] Registers are inserted significantly out of order regarding their offsets.
- [Low] Redundant inline bitfield definitions instead of reusing the existing bitset type.
--
commit 6a32a45a3775682b98c44924ebd725197283df72
Author: Anna Maniscalco <anna.maniscalco2000@gmail.com>
temp: add LPAC regs
This patch adds LPAC register definitions to the adreno a6xx XML database.
It notes that the definitions are pulled from a Mesa merge request.
Link: https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/39416
> temp: add LPAC regs
>
> https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/39416
>
> should we merged and we should sync to mesa instead
[Severity: Medium]
This isn't a bug, but since this patch is explicitly marked as a temporary
commit ("temp:") and notes that we should sync from Mesa instead, should
these register definitions be finalized and synchronized through the Mesa
rnndb workflow before merging upstream to avoid divergence?
> diff --git a/drivers/gpu/drm/msm/registers/adreno/a6xx.xml b/drivers/gpu/drm/msm/registers/adreno/a6xx.xml
> index 3349c01646e12..bb49f6a61a9af 100644
> --- a/drivers/gpu/drm/msm/registers/adreno/a6xx.xml
> +++ b/drivers/gpu/drm/msm/registers/adreno/a6xx.xml
> @@ -276,6 +276,11 @@ by a particular renderpass/blit.
> <bitfield pos="1" name="ACCESS_FAULT_ON_VIOL_EN" type="boolean"/>
> <bitfield pos="0" name="ACCESS_PROT_EN" type="boolean"/>
> </bitset>
> + <reg32 offset="0x0B09" name="CP_LPAC_PROTECT_CNTL">
> + <bitfield pos="3" name="LAST_SPAN_INF_RANGE" type="boolean"/>
> + <bitfield pos="1" name="ACCESS_FAULT_ON_VIOL_EN" type="boolean"/>
> + <bitfield pos="0" name="ACCESS_PROT_EN" type="boolean"/>
> + </reg32>
>
> <reg32 offset="0x084f" name="CP_PROTECT_CNTL" type="a6xx_cp_protect_cntl" variants="A6XX-A7XX"/>
[Severity: High]
Does CP_LPAC_PROTECT_CNTL need a variants="A7XX-" attribute here? By omitting
the variants attribute, this A7XX-only LPAC register will be generated and
applied for A6XX hardware, which could write to an undefined register at
0x0B09 during early hardware initialization and cause an access fault.
[Severity: Low]
Instead of manually defining these bitfields inline, could this register
reuse the existing a6xx_cp_protect_cntl bitset by specifying
type="a6xx_cp_protect_cntl" to prevent duplication?
[Severity: Low]
Also, this register at offset 0x0B09 is inserted before 0x084f. Should these
be kept ordered by offset to prevent overlapping definitions and XML parser
warnings?
[ ... ]
> @@ -333,6 +338,11 @@ by a particular renderpass/blit.
> <reg32 offset="0x0845" name="CP_CRASH_DUMP_STATUS" variants="A8XX-"/>
> <reg32 offset="0x0908" name="CP_SQE_STAT_ADDR" variants="A6XX-A7XX"/>
> <reg32 offset="0x0909" name="CP_SQE_STAT_DATA" variants="A6XX-A7XX"/>
> + <reg64 offset="0x0b00" name="CP_LPAC_RB_BASE" variants="A7XX-"/>
> + <reg32 offset="0x0b02" name="CP_LPAC_RB_CNTL" variants="A7XX-"/>
> + <reg64 offset="0x0b04" name="CP_LPAC_RB_RPTR_ADDR" variants="A7XX-"/>
> + <reg32 offset="0x0b06" name="CP_LPAC_RB_RPTR" variants="A7XX-"/>
> + <reg32 offset="0x0b07" name="CP_LPAC_RB_WPTR" variants="A7XX-"/>
> <reg32 offset="0x090a" name="CP_DRAW_STATE_ADDR" variants="A6XX-A7XX"/>
> <reg32 offset="0x090b" name="CP_DRAW_STATE_DATA" variants="A6XX-A7XX"/>
[Severity: High]
Do these offsets conflict with existing A8XX definitions? Using
variants="A7XX-" applies them to A8XX, but A8XX already defines
CP_SLICE_MEM_POOL_DBG_ADDR_PIPE at 0x0b00, and the A8XX LPAC ring buffer
base is generally at 0x080b. Should this be restricted to variants="A7XX"
to avoid an XML offset collision during the build?
[Severity: Low]
Similar to the earlier register, the 0x0b00-0x0b07 block is placed between
0x0909 and 0x090a. Would it be better to place it further down to keep the
XML offsets ordered?
[ ... ]
> @@ -1207,6 +1218,7 @@ by a particular renderpass/blit.
> <reg64 offset="0x0E08" name="UCHE_TRAP_BASE" variants="A8XX-"/>
> <reg64 offset="0x0E0B" name="UCHE_GMEM_RANGE_MIN" variants="A6XX-A7XX"/>
> <reg64 offset="0x0E0D" name="UCHE_GMEM_RANGE_MAX" variants="A6XX-A7XX"/>
> + <reg32 offset="0x0E12" name="UCHE_DEBUG_CNTL_1" usage="cmd"/>
> <reg32 offset="0x0e17" name="UCHE_CACHE_WAYS" variants="A6XX-A7XX" usage="init"/>
> <reg32 offset="0x0e04" name="UCHE_CACHE_WAYS" variants="A8XX-"/>
[Severity: High]
Will adding UCHE_DEBUG_CNTL_1 at offset 0x0E12 without a variants attribute
cause a build failure? 0x0e12 is already defined as UCHE_UNKNOWN_0E12 for
A6XX-A7XX and as UCHE_GBIF_GX_CONFIG for A8XX. Does this new definition need
a variant constraint, or should the old conflicting registers be removed?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260705-descriptive-name-lpac-upstream-v1-0-01d50c3e0c99@gmail.com?part=9
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH RFC 04/13] arm64: dts: qcom: sm8650: move smmu sid 1 to new lpac device
2026-07-05 19:13 ` [PATCH RFC 04/13] arm64: dts: qcom: sm8650: move smmu sid 1 to new lpac device Anna Maniscalco
@ 2026-07-05 19:24 ` sashiko-bot
2026-07-06 8:40 ` Konrad Dybcio
1 sibling, 0 replies; 34+ messages in thread
From: sashiko-bot @ 2026-07-05 19:24 UTC (permalink / raw)
To: Anna Maniscalco; +Cc: dri-devel, robh, conor+dt, devicetree
Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
- [High] Device Tree Forward-Compatibility Breakage (GPU Firmware Crash on Older Kernels)
- [High] Resource Leak and Unbalanced PM Runtime in GPU Driver LPAC Initialization
- [Medium] Device Tree Anti-Pattern and Syntax Violation (Overlapping Reg / Mismatched Unit Address)
--
commit e35e1c1ccf71441e2995511a6a0a9c69917e0605
Author: Anna Maniscalco <anna.maniscalco2000@gmail.com>
arm64: dts: qcom: sm8650: move smmu sid 1 to new lpac device
Moves SID 1 from the GPU node to a new LPAC node to allow SID 1 to use a
different domain when LPAC is used.
> diff --git a/arch/arm64/boot/dts/qcom/sm8650.dtsi b/arch/arm64/boot/dts/qcom/sm8650.dtsi
> index 1604bc8cff373..44e5f9d4b335f 100644
> --- a/arch/arm64/boot/dts/qcom/sm8650.dtsi
> +++ b/arch/arm64/boot/dts/qcom/sm8650.dtsi
> @@ -4133,6 +4133,13 @@ tcsr: clock-controller@1fc0000 {
> #reset-cells = <1>;
> };
>
> + lpac: lpac@3d00000 {
> + compatible = "qcom,lpac";
> + reg = <0x0 0x03d00000 0x0 0x61000>;
> +
> + iommus = <&adreno_smmu 1 0x0>;
> + };
> +
[Severity: Medium]
Does this node violate the Devicetree specification by overlapping with its
sibling node?
The memory region (0x3d00000) for the lpac@3d00000 node completely overlaps
with the gpu@3d00000 node below.
Also, creating a top-level dummy platform device solely to bind a second
IOMMU SID to a separate struct device (to work around driver domain
isolation limitations) appears to be an architectural anti-pattern.
> gpu: gpu@3d00000 {
> compatible = "qcom,adreno-43051401", "qcom,adreno";
> reg = <0x0 0x03d00000 0x0 0x40000>,
[ ... ]
> @@ -4144,8 +4151,9 @@ gpu: gpu@3d00000 {
>
> interrupts = <GIC_SPI 300 IRQ_TYPE_LEVEL_HIGH 0>;
>
> - iommus = <&adreno_smmu 0 0x0>,
> - <&adreno_smmu 1 0x0>;
> + iommus = <&adreno_smmu 0 0x0>;
> +
> + qcom,lpac= <&lpac>;
[Severity: High]
Does removing SID 1 from the gpu@3d00000 node break forward-compatibility
for older kernels?
If an older kernel (which lacks the LPAC DRM driver modifications to parse
qcom,lpac) boots with this updated DT, it will only attach SID 0 to the
GPU's SMMU domain, leaving SID 1 unmapped.
Since the commit message notes that firmware requires both SID 0 and 1
mapped to the same page table during initialization, attempting to boot an
older kernel with this DT could trigger an SMMU context fault and completely
break GPU initialization.
Regarding the DRM driver code that handles the new lpac node:
[Severity: High]
Does the driver initialization leak the LPAC device reference and leave PM
runtime unbalanced?
Looking at adreno_gpu_init() in drivers/gpu/drm/msm/adreno/adreno_gpu.c:
drivers/gpu/drm/msm/adreno/adreno_gpu.c:adreno_gpu_init() {
...
gpu->lpac_pdev = of_find_device_by_node(lpac_node);
if (gpu->lpac_pdev) {
...
pm_runtime_enable(&gpu->lpac_pdev->dev);
}
...
}
The driver acquires a reference using of_find_device_by_node() (which
increments the reference count) and calls pm_runtime_enable().
However, adreno_gpu_cleanup() handles the main gpu_pdev but does not seem
to call put_device() or pm_runtime_disable() to clean up gpu->lpac_pdev:
drivers/gpu/drm/msm/adreno/adreno_gpu.c:adreno_gpu_cleanup() {
...
if (priv && pm_runtime_enabled(&priv->gpu_pdev->dev))
pm_runtime_disable(&priv->gpu_pdev->dev);
msm_gpu_cleanup(&adreno_gpu->base);
...
}
Could this result in a memory leak of the device structure and trigger an
"Unbalanced pm_runtime_enable!" warning when the GPU driver is unbound
or fails to probe?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260705-descriptive-name-lpac-upstream-v1-0-01d50c3e0c99@gmail.com?part=4
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH RFC 10/13] drm/msm: initialize LPAC ring
2026-07-05 19:13 ` [PATCH RFC 10/13] drm/msm: initialize LPAC ring Anna Maniscalco
@ 2026-07-05 19:26 ` sashiko-bot
2026-07-06 8:44 ` Konrad Dybcio
1 sibling, 0 replies; 34+ messages in thread
From: sashiko-bot @ 2026-07-05 19:26 UTC (permalink / raw)
To: Anna Maniscalco; +Cc: dri-devel, robh, devicetree, conor+dt
Thank you for your contribution! Sashiko AI review found 5 potential issue(s) to consider:
- [Critical] Unconditional execution of LPAC initialization on all A6xx/A7xx GPUs will crash hardware without LPAC support.
- [High] The error check for the LPAC ringbuffer allocation evaluates the wrong variable, ignoring allocation failures and reading out-of-bounds.
- [Medium] The GPU hangcheck timer does not monitor the LPAC ring, causing LPAC-only hangs to go undetected.
- [Medium] Missing cleanup of `gpu->lpac_rb` in the error path of `msm_gpu_init()`.
- [Low] Unconditional allocation of the LPAC ringbuffer wastes resources for all MSM GPUs.
--
commit 35c6bd5d02bb9ed8858bdd2395719b06651d77e8
Author: Anna Maniscalco <anna.maniscalco2000@gmail.com>
drm/msm: initialize LPAC ring
Program all the register needed to start up LPAC and send initialization
sequence. Additionally, now that the LPAC ring is live, make the code aware
of it.
> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
[ ... ]
> @@ -1481,6 +1567,10 @@ static int hw_init(struct msm_gpu *gpu)
> if (ret)
> goto out;
>
> + ret = lpac_cp_init(gpu);
> + if (ret)
> + goto out;
> +
[Severity: Critical]
Will this unconditional execution of LPAC initialization cause a regression on
hardware without LPAC support?
During hw_init(), the driver unconditionally writes to LPAC-specific registers
and calls lpac_cp_init(). This function sends a CP_ME_INIT packet to the LPAC
ring and waits for it to idle using a6xx_idle().
On older GPUs lacking LPAC hardware (e.g., A630), the CP engine ignores this
ring, causing the idle wait to time out and hw_init() to return -EINVAL.
> /*
> * Try to load a zap shader into the secure world. If successful
[ ... ]
> diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c
> --- a/drivers/gpu/drm/msm/msm_gpu.c
> +++ b/drivers/gpu/drm/msm/msm_gpu.c
[ ... ]
> @@ -1006,6 +1009,15 @@ int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev,
> memptrs_iova += sizeof(struct msm_rbmemptrs);
> }
>
> + gpu->lpac_rb = msm_ringbuffer_new(gpu, nr_rings, memptrs, memptrs_iova);
> +
[Severity: Low]
Does this unconditional allocation of the LPAC ringbuffer waste resources for
legacy non-LPAC GPUs?
A GEM object, DRM scheduler kthread, and fence context are allocated for every
MSM GPU even if they do not support LPAC.
> + if (IS_ERR(gpu->rb[i])) {
> + ret = PTR_ERR(gpu->rb[i]);
> + DRM_DEV_ERROR(drm->dev,
> + "could not create lpac ringbuffer %d\n", ret);
> + goto fail;
> + }
> +
[Severity: High]
Does this check the wrong variable for the LPAC allocation failure?
The error check evaluates gpu->rb[i] instead of gpu->lpac_rb. If the LPAC
allocation fails, gpu->lpac_rb holds an error pointer but the initialization
succeeds.
This later causes a kernel panic when the error pointer is dereferenced during
device setup. Additionally, because the loop counter i equals nr_rings here,
checking gpu->rb[i] results in an out-of-bounds array read if nr_rings equals
MSM_GPU_MAX_RINGS.
[Severity: Medium]
If GPU initialization fails and we take this goto fail path, is there a memory
leak for the LPAC ringbuffer?
The fail path in msm_gpu_init() iterates over gpu->rb and destroys those
ringbuffers, but it lacks a call to msm_ringbuffer_destroy(gpu->lpac_rb).
> gpu->nr_rings = nr_rings;
>
> refcount_set(&gpu->sysprof_active, 1);
[ ... ]
> diff --git a/drivers/gpu/drm/msm/msm_gpu.h b/drivers/gpu/drm/msm/msm_gpu.h
> --- a/drivers/gpu/drm/msm/msm_gpu.h
> +++ b/drivers/gpu/drm/msm/msm_gpu.h
[ ... ]
> @@ -181,6 +181,8 @@ struct msm_gpu {
> struct msm_ringbuffer *rb[MSM_GPU_MAX_RINGS];
> int nr_rings;
>
> + struct msm_ringbuffer *lpac_rb;
> +
[Severity: Medium]
Is the GPU hangcheck timer missing monitoring for the LPAC ring?
In msm_gpu.c:hangcheck_handler(), the code only monitors the primary active
ring:
struct msm_ringbuffer *ring = gpu->funcs->active_ring(gpu);
...
if (fence_after(ring->fctx->last_fence, ring->hangcheck_fence))
hangcheck_timer_reset(gpu);
If a task submitted to the LPAC ring hangs and the primary ring is idle,
fence_after() evaluates to false and the timer is not reset. The stall goes
undetected, leaving the task hanging indefinitely without GPU recovery.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260705-descriptive-name-lpac-upstream-v1-0-01d50c3e0c99@gmail.com?part=10
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH RFC 03/13] drm/msm: look for lpac from dts
2026-07-05 19:13 ` [PATCH RFC 03/13] drm/msm: look for lpac from dts Anna Maniscalco
@ 2026-07-05 19:27 ` sashiko-bot
2026-07-06 15:04 ` Dmitry Baryshkov
1 sibling, 0 replies; 34+ messages in thread
From: sashiko-bot @ 2026-07-05 19:27 UTC (permalink / raw)
To: Anna Maniscalco; +Cc: dri-devel, robh, devicetree, conor+dt
Thank you for your contribution! Sashiko AI review found 10 potential issue(s) to consider:
- [High] Dangling pointer in LPAC device's driver data leads to Use-After-Free.
- [High] Incorrect order of `device_link_add()` and `pm_runtime_enable()` causes device link failure.
- [High] Severe memory and resource leak in `msm_iommu_new()` error paths.
- [High] LPAC fault handler retrieves fault information from the wrong hardware block.
- [High] Missing rollback of main SMMU `set_ttbr0_cfg` upon LPAC configuration failure causes Use-After-Free.
- [Medium] Memory leak of the LPAC platform device reference.
- [Medium] Unbalanced `pm_runtime_enable()` for the LPAC device corrupts PM state.
- [Medium] Calling `of_dma_configure()` explicitly on an already-instantiated platform device.
- [Medium] Double allocation of `prr_page` causing a memory leak, and incorrectly scoped cleanup.
- [Medium] Partial mapping failures in the main domain are silently ignored if the LPAC domain maps successfully.
--
commit 8c24a0d4aac07c998e8a7b231ed5f964a1584875
Author: Anna Maniscalco <anna.maniscalco2000@gmail.com>
Date: Sun Jul 5 19:13:37 2026 +0000
drm/msm: look for lpac from dts
In order to associate the SID used by LPAC to it's own domain and
context bank we need a separate node on the DTS.
Add the code to look up that node on initialization.
> diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
> index f3fc7032fadcd..71ce4cbbf27ae 100644
> --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c
> +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
[ ... ]
> @@ -1200,6 +1205,20 @@ int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev,
> gpu->allow_relocs = config->info->family < ADRENO_6XX_GEN1;
> gpu->pdev = pdev;
>
> + lpac_node = of_parse_phandle(pdev->dev.of_node, "qcom,lpac", 0);
> + if (lpac_node)
> + gpu->lpac_pdev = of_find_device_by_node(lpac_node);
[Severity: Medium]
Does this code leak the LPAC platform device reference?
of_find_device_by_node() acquires a reference to the LPAC platform device via
bus_find_device(). This reference is stored in gpu->lpac_pdev but is never
released using put_device(&gpu->lpac_pdev->dev) in the error paths of
adreno_gpu_init() or in the driver teardown path adreno_gpu_cleanup(), causing
a memory leak of the device structure.
> + if (gpu->lpac_pdev) {
> + of_dma_configure(&gpu->lpac_pdev->dev, lpac_node, true);
[Severity: Medium]
Is it correct to call of_dma_configure() explicitly on an already-instantiated
platform device?
The LPAC platform device is instantiated by of_platform_populate(), meaning it
has already been configured for DMA and probed by the IOMMU subsystem.
Re-calling of_dma_configure() explicitly on an active platform device
reallocates DMA mappings, violating driver core API contracts and potentially
causing duplicate IOMMU attachments or resource leaks.
> + platform_set_drvdata(gpu->lpac_pdev, &gpu->lpac_adreno_smmu);
[Severity: High]
Does this create a dangling pointer in the LPAC device's driver data that
could lead to a use-after-free?
platform_set_drvdata() sets the external LPAC device's driver data to point to
&gpu->lpac_adreno_smmu, a field within the dynamically allocated msm_gpu.
On driver unbind or probe failure, msm_gpu is freed, but the LPAC device
(created by OF platform populate) persists.
The driver data is not cleared to NULL, leaving a dangling pointer. Subsequent
accesses to the device (e.g., via sysfs or another driver binding to it) will
dereference freed memory.
> + 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 gpu device\n");
> + pm_runtime_enable(&gpu->lpac_pdev->dev);
[Severity: High]
Does the incorrect order of device_link_add() and pm_runtime_enable() cause
the device link to fail?
device_link_add() is called with DL_FLAG_PM_RUNTIME, which internally calls
pm_runtime_get_sync() on the supplier (lpac_pdev).
Because pm_runtime_enable() hasn't been called on the supplier yet, it is
still disabled, causing pm_runtime_get_sync() to return -EACCES.
This causes device_link_add() to fail and return NULL, completely breaking the
runtime PM dependency between the GPU and LPAC.
[Severity: Medium]
Will this unbalance the pm_runtime_enable() for the LPAC device and corrupt PM
state?
pm_runtime_enable() decreases the PM disable_depth of the LPAC device.
The matching pm_runtime_disable() is missing in the teardown path
adreno_gpu_cleanup().
Reloading the driver module will trigger a kernel warning for unbalanced PM
enable and corrupts the LPAC device's PM state machine.
> + }
> + if (lpac_node)
> + of_node_put(lpac_node);
> +
[ ... ]
> diff --git a/drivers/gpu/drm/msm/msm_iommu.c b/drivers/gpu/drm/msm/msm_iommu.c
> index 058c71c82cf54..19bee64adb7ca 100644
> --- a/drivers/gpu/drm/msm/msm_iommu.c
> +++ b/drivers/gpu/drm/msm/msm_iommu.c
[ ... ]
> @@ -224,6 +226,10 @@ static void msm_iommu_pagetable_destroy(struct msm_mmu *mmu)
> struct msm_iommu *iommu = to_msm_iommu(pagetable->parent);
> struct adreno_smmu_priv *adreno_smmu =
> dev_get_drvdata(pagetable->parent->dev);
> + struct adreno_smmu_priv *lpac_adreno_smmu = NULL;
> +
> + if (pagetable->parent->lpac_dev)
> + lpac_adreno_smmu = dev_get_drvdata(pagetable->parent->lpac_dev);
>
> /*
> * If this is the last attached pagetable for the parent,
> @@ -232,9 +238,13 @@ static void msm_iommu_pagetable_destroy(struct msm_mmu *mmu)
> mutex_lock(&iommu->init_lock);
> if (--iommu->pagetables == 0) {
> adreno_smmu->set_ttbr0_cfg(adreno_smmu->cookie, NULL);
> + if (lpac_adreno_smmu)
> + lpac_adreno_smmu->set_ttbr0_cfg(lpac_adreno_smmu->cookie, NULL);
>
> if (adreno_smmu->set_prr_bit) {
> adreno_smmu->set_prr_bit(adreno_smmu->cookie, false);
> + if (lpac_adreno_smmu && lpac_adreno_smmu->set_prr_bit)
> + lpac_adreno_smmu->set_prr_bit(lpac_adreno_smmu->cookie, false);
[Severity: Medium]
Will this incorrectly scope the LPAC PRR cleanup and cause a memory leak?
In msm_iommu_pagetable_destroy(), the cleanup for LPAC PRR is nested inside the
condition for the main GPU PRR. If only the LPAC PRR is enabled, the page is
never freed.
> __free_page(iommu->prr_page);
> iommu->prr_page = NULL;
> }
[ ... ]
> @@ -588,6 +621,17 @@ struct msm_mmu *msm_iommu_pagetable_create(struct msm_mmu *parent, bool kernel_m
> return ERR_PTR(ret);
> }
>
> + if (lpac_adreno_smmu) {
> + ret = lpac_adreno_smmu->set_ttbr0_cfg(lpac_adreno_smmu->cookie, &ttbr0_cfg);
> + if (ret) {
> + iommu->pagetables--;
> + mutex_unlock(&iommu->init_lock);
> + free_io_pgtable_ops(pagetable->pgtbl_ops);
> + kfree(pagetable);
> + return ERR_PTR(ret);
[Severity: High]
Does this error path miss rolling back the main SMMU configuration, leading to
a use-after-free?
In msm_iommu_pagetable_create(), set_ttbr0_cfg() programs the main SMMU
hardware with the new page tables.
If the subsequent set_ttbr0_cfg() for the LPAC SMMU fails, the function
immediately frees the page tables (free_io_pgtable_ops) and returns an error.
It fails to call set_ttbr0_cfg(..., NULL) for the main SMMU to unprogram it.
The main SMMU hardware is left actively configured to use the freed page
tables, resulting in a use-after-free of memory by the hardware.
> + }
> + }
> +
> BUG_ON(iommu->prr_page);
> if (adreno_smmu->set_prr_bit) {
> /*
> @@ -606,11 +650,17 @@ struct msm_mmu *msm_iommu_pagetable_create(struct msm_mmu *parent, bool kernel_m
> page_to_phys(iommu->prr_page));
> adreno_smmu->set_prr_bit(adreno_smmu->cookie, true);
> }
> +
> + if (lpac_adreno_smmu && lpac_adreno_smmu->set_prr_bit) {
> + iommu->prr_page = alloc_page(GFP_KERNEL | __GFP_ZERO);
[Severity: Medium]
Will this allocate prr_page a second time and leak the first allocation?
If both adreno_smmu->set_prr_bit and lpac_adreno_smmu->set_prr_bit are true,
iommu->prr_page is allocated twice in msm_iommu_pagetable_create(),
overwriting the pointer and leaking the first page.
> + lpac_adreno_smmu->set_prr_addr(lpac_adreno_smmu->cookie,
> + page_to_phys(iommu->prr_page));
> + lpac_adreno_smmu->set_prr_bit(lpac_adreno_smmu->cookie, true);
> + }
> }
> mutex_unlock(&iommu->init_lock);
>
[ ... ]
> @@ -646,6 +696,26 @@ static int msm_gpu_fault_handler(struct iommu_domain *domain, struct device *dev
> return 0;
> }
>
> +static int msm_lpac_fault_handler(struct iommu_domain *domain, struct device *dev,
> + unsigned long iova, int flags, void *arg)
> +{
> + struct msm_iommu *iommu = arg;
> + struct adreno_smmu_priv *adreno_smmu = dev_get_drvdata(iommu->base.dev);
[Severity: High]
Does the LPAC fault handler retrieve fault information from the wrong hardware
block?
msm_lpac_fault_handler() retrieves the adreno_smmu driver data using
dev_get_drvdata(iommu->base.dev) (the main GPU device).
It then calls get_fault_info() using the main GPU SMMU's cookie.
This reads the fault registers of the main GPU hardware block rather than the
LPAC block, leading to incorrect fault reporting and potentially failing to
clear the actual LPAC fault.
> + struct adreno_smmu_fault_info info, *ptr = NULL;
> +
> + if (adreno_smmu->get_fault_info) {
> + adreno_smmu->get_fault_info(adreno_smmu->cookie, &info);
> + ptr = &info;
> + }
> +
> + if (iommu->base.handler)
> + return iommu->base.handler(iommu->base.arg, iova, flags, ptr);
> +
> + pr_warn_ratelimited("*** lpac fault: iova=%16lx, flags=%d\n", iova, flags);
> +
> + return 0;
> +}
[ ... ]
> @@ -689,6 +769,11 @@ static int msm_iommu_map(struct msm_mmu *mmu, uint64_t iova,
> if (ret < 0)
> return ret;
>
> + if (iommu->lpac_domain) {
> + ret = iommu_map_sgtable(iommu->lpac_domain, iova, sgt, prot);
> + WARN_ON(!ret);
> + }
[Severity: Medium]
Are partial mapping failures in the main domain silently ignored if the LPAC
domain maps successfully?
In msm_iommu_map(), if iommu_map_sgtable() on the main domain returns a
size < len (but > 0), it is a partial failure.
The result ret is overwritten by the mapping result of the LPAC domain.
If the LPAC domain maps the full len, the function returns success 0,
completely masking the partial mapping failure of the main domain.
> +
> return (ret == len) ? 0 : -EINVAL;
> }
[ ... ]
> @@ -753,6 +843,30 @@ struct msm_mmu *msm_iommu_new(struct device *dev, unsigned long quirks)
> return ERR_PTR(ret);
> }
>
> + if (lpac_dev) {
> + if (!device_iommu_mapped(lpac_dev))
> + return ERR_PTR(-ENODEV);
> +
> + lpac_domain = iommu_paging_domain_alloc(lpac_dev);
> + if (IS_ERR(lpac_domain))
> + return ERR_CAST(lpac_domain);
[Severity: High]
Does this early return cause a memory and resource leak in the error path?
If device_iommu_mapped(lpac_dev) is false or iommu_paging_domain_alloc()
fails for the LPAC device, the function returns an error early.
It fails to free the previously allocated iommu and domain structures, and
fails to detach the main dev from the domain.
Similarly, if iommu_attach_device() for LPAC fails below, it forgets to detach
the main dev. This causes a permanent resource leak and leaves the device
attached to a freed domain.
> +
> + iommu_set_pgtable_quirks(lpac_domain, quirks);
> +
> + iommu->lpac_domain = lpac_domain;
> + iommu->base.lpac_dev = lpac_dev;
> + }
> +
> + if (lpac_domain) {
> + ret = iommu_attach_device(lpac_domain, lpac_dev);
> + if (ret) {
> + iommu_domain_free(domain);
> + iommu_domain_free(lpac_domain);
> + kfree(iommu);
> + return ERR_PTR(ret);
> + }
> + }
> +
> return &iommu->base;
> }
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260705-descriptive-name-lpac-upstream-v1-0-01d50c3e0c99@gmail.com?part=3
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH RFC 07/13] iommu: arm-smmu-qcom: Fixed mapping between sid and cb for gpu and lpac
2026-07-05 19:13 ` [PATCH RFC 07/13] iommu: arm-smmu-qcom: Fixed mapping between sid and cb for gpu and lpac Anna Maniscalco
@ 2026-07-05 19:27 ` sashiko-bot
0 siblings, 0 replies; 34+ messages in thread
From: sashiko-bot @ 2026-07-05 19:27 UTC (permalink / raw)
To: Anna Maniscalco; +Cc: robh, conor+dt, dri-devel, devicetree
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] The context bank allocation logic assigns Context Bank 1 instead of Context Bank 0 to legacy unified GPU devices that declare both SID 0 and SID 1, breaking GPU hardware pagetable switching.
--
commit ae389e90eddaec7861c0838f081fce60156d8874
Author: Anna Maniscalco <anna.maniscalco2000@gmail.com>
iommu: arm-smmu-qcom: Fixed mapping between sid and cb for gpu and lpac
This patch updates the context bank allocation logic for Adreno SMMU devices.
It introduces device identification functions and modifies the context bank
allocator to map context bank 0 to SID 0 and context bank 1 to SID 1.
> diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
> index ae6152bddf8fe..e605a535f328f 100644
> --- a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
> +++ b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
> @@ -225,6 +225,25 @@ static void qcom_adreno_smmu_set_prr_addr(const void *cookie, phys_addr_t page_a
> #define QCOM_ADRENO_SMMU_GPU_SID 0
> #define QCOM_ADRENO_SMMU_LPAC_SID 1
>
> +static bool qcom_adreno_smmu_is_lpac_device(struct device *dev)
> +{
> + struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
> + int i;
> +
> + /*
> + * The GPU will always use SID 0 so that is a handy way to uniquely
> + * identify it and configure it for per-instance pagetables
> + */
> + for (i = 0; i < fwspec->num_ids; i++) {
> + u16 sid = FIELD_GET(ARM_SMMU_SMR_ID, fwspec->ids[i]);
> +
> + if (sid == QCOM_ADRENO_SMMU_LPAC_SID)
> + return true;
> + }
> +
> + return false;
> +}
> +
[ ... ]
> @@ -312,13 +331,12 @@ static int qcom_adreno_smmu_alloc_context_bank(struct arm_smmu_domain *smmu_doma
> * switch pagetables
> */
> if (qcom_adreno_smmu_is_gpu_device(dev)) {
> - start = 0;
> - count = 2;
> + start = !!qcom_adreno_smmu_is_lpac_device(dev);
> + count = start + 1;
[Severity: High]
Does this break context bank allocation for legacy unified GPU devices?
When probing older supported SoCs where a single unified primary GPU device
node declares both SID 0 and SID 1, qcom_adreno_smmu_is_lpac_device() will
return true because one of the SIDs matches QCOM_ADRENO_SMMU_LPAC_SID.
This calculates start = 1 and count = 2. The __arm_smmu_alloc_bitmap() call
will then search exclusively in the [1, 2) range and allocate Context Bank 1
for the primary GPU domain, completely skipping Context Bank 0.
Since the Adreno GPU hardware natively expects and hardcodes Context Bank 0
for its main pagetable switching via its internal APERTURE, allocating
Context Bank 1 instead of 0 violates hardware constraints. Will this result
in SMMU faults and a frozen GPU on those legacy platforms?
> } else {
> start = 2;
> count = smmu->num_context_banks;
> }
> -
> return __arm_smmu_alloc_bitmap(smmu->context_map, start, count);
> }
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260705-descriptive-name-lpac-upstream-v1-0-01d50c3e0c99@gmail.com?part=7
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH RFC 02/13] drm/msm: add support for lpac_domain in msm_mmu
2026-07-05 19:13 ` [PATCH RFC 02/13] drm/msm: add support for lpac_domain in msm_mmu Anna Maniscalco
@ 2026-07-05 19:27 ` sashiko-bot
0 siblings, 0 replies; 34+ messages in thread
From: sashiko-bot @ 2026-07-05 19:27 UTC (permalink / raw)
To: Anna Maniscalco; +Cc: conor+dt, robh, devicetree, dri-devel
Thank you for your contribution! Sashiko AI review found 5 potential issue(s) to consider:
- [High] Error paths in msm_iommu_new() leak allocated structures and fail to detach the primary device.
- [High] Double allocation of iommu->prr_page overwrites the pointer, leaking memory, and cleanup logic is improperly gated.
- [High] Missing rollback of the primary SMMU TTBR0 configuration when LPAC TTBR0 setup fails.
- [High] msm_iommu_map leaves stale mappings in the primary domain if LPAC mapping fails.
- [Medium] The LPAC fault handler fetches fault information from the primary SMMU instead of the LPAC SMMU.
--
commit 2c00819136c6aa733650fd70add5fb287b7ba815
Author: Anna Maniscalco <anna.maniscalco2000@gmail.com>
drm/msm: add support for lpac_domain in msm_mmu
This commit adds an iommu_domain for LPAC (Low Power Audio Subsystem
context) and attempts to keep it in sync with the main domain. This allows
LPAC to use a separate context bank to update page tables independently.
> diff --git a/drivers/gpu/drm/msm/msm_iommu.c b/drivers/gpu/drm/msm/msm_iommu.c
> index 058c71c82cf54..19bee64adb7ca 100644
> --- a/drivers/gpu/drm/msm/msm_iommu.c
> +++ b/drivers/gpu/drm/msm/msm_iommu.c
[ ... ]
> @@ -224,6 +226,10 @@ static void msm_iommu_pagetable_destroy(struct msm_mmu *mmu)
> struct msm_iommu *iommu = to_msm_iommu(pagetable->parent);
> struct adreno_smmu_priv *adreno_smmu =
> dev_get_drvdata(pagetable->parent->dev);
> + struct adreno_smmu_priv *lpac_adreno_smmu = NULL;
> +
> + if (pagetable->parent->lpac_dev)
> + lpac_adreno_smmu = dev_get_drvdata(pagetable->parent->lpac_dev);
>
> /*
> * If this is the last attached pagetable for the parent,
> @@ -232,9 +238,13 @@ static void msm_iommu_pagetable_destroy(struct msm_mmu *mmu)
> mutex_lock(&iommu->init_lock);
> if (--iommu->pagetables == 0) {
> adreno_smmu->set_ttbr0_cfg(adreno_smmu->cookie, NULL);
> + if (lpac_adreno_smmu)
> + lpac_adreno_smmu->set_ttbr0_cfg(lpac_adreno_smmu->cookie, NULL);
>
> if (adreno_smmu->set_prr_bit) {
> adreno_smmu->set_prr_bit(adreno_smmu->cookie, false);
> + if (lpac_adreno_smmu && lpac_adreno_smmu->set_prr_bit)
> + lpac_adreno_smmu->set_prr_bit(lpac_adreno_smmu->cookie, false);
> __free_page(iommu->prr_page);
> iommu->prr_page = NULL;
> }
[Severity: High]
If the primary SMMU does not support PRR (so adreno_smmu->set_prr_bit is
false/NULL) but the LPAC SMMU does, does this logic bypass the LPAC PRR
teardown and leak iommu->prr_page?
[ ... ]
> @@ -588,6 +621,17 @@ struct msm_mmu *msm_iommu_pagetable_create(struct msm_mmu *parent, bool kernel_m
> return ERR_PTR(ret);
> }
>
> + if (lpac_adreno_smmu) {
> + ret = lpac_adreno_smmu->set_ttbr0_cfg(lpac_adreno_smmu->cookie, &ttbr0_cfg);
> + if (ret) {
> + iommu->pagetables--;
> + mutex_unlock(&iommu->init_lock);
> + free_io_pgtable_ops(pagetable->pgtbl_ops);
> + kfree(pagetable);
> + return ERR_PTR(ret);
> + }
> + }
[Severity: High]
If lpac_adreno_smmu->set_ttbr0_cfg() fails here, does this error path
leave the primary SMMU TTBR0 actively configured to point to page tables
that are about to be freed?
Should there be a rollback for adreno_smmu->set_ttbr0_cfg() before returning?
> +
> BUG_ON(iommu->prr_page);
> if (adreno_smmu->set_prr_bit) {
> /*
> @@ -606,11 +650,17 @@ struct msm_mmu *msm_iommu_pagetable_create(struct msm_mmu *parent, bool kernel_m
> page_to_phys(iommu->prr_page));
> adreno_smmu->set_prr_bit(adreno_smmu->cookie, true);
> }
> +
> + if (lpac_adreno_smmu && lpac_adreno_smmu->set_prr_bit) {
> + iommu->prr_page = alloc_page(GFP_KERNEL | __GFP_ZERO);
> + lpac_adreno_smmu->set_prr_addr(lpac_adreno_smmu->cookie,
> + page_to_phys(iommu->prr_page));
> + lpac_adreno_smmu->set_prr_bit(lpac_adreno_smmu->cookie, true);
> + }
> }
> mutex_unlock(&iommu->init_lock);
[Severity: High]
If both the primary SMMU and the LPAC SMMU have set_prr_bit, will this
second call to alloc_page() unconditionally overwrite iommu->prr_page
and leak the first page allocation?
[ ... ]
> @@ -646,6 +696,26 @@ static int msm_gpu_fault_handler(struct iommu_domain *domain, struct device *dev
> return 0;
> }
>
> +static int msm_lpac_fault_handler(struct iommu_domain *domain, struct device *dev,
> + unsigned long iova, int flags, void *arg)
> +{
> + struct msm_iommu *iommu = arg;
> + struct adreno_smmu_priv *adreno_smmu = dev_get_drvdata(iommu->base.dev);
> + struct adreno_smmu_fault_info info, *ptr = NULL;
> +
> + if (adreno_smmu->get_fault_info) {
> + adreno_smmu->get_fault_info(adreno_smmu->cookie, &info);
> + ptr = &info;
> + }
[Severity: Medium]
Does this fetch the fault information from the primary SMMU instead of the
LPAC SMMU?
Using iommu->base.lpac_dev instead of iommu->base.dev for dev_get_drvdata()
might be needed to read the correct hardware registers.
[ ... ]
> @@ -689,6 +769,11 @@ static int msm_iommu_map(struct msm_mmu *mmu, uint64_t iova,
> if (ret < 0)
> return ret;
>
> + if (iommu->lpac_domain) {
> + ret = iommu_map_sgtable(iommu->lpac_domain, iova, sgt, prot);
> + WARN_ON(!ret);
> + }
> +
> return (ret == len) ? 0 : -EINVAL;
> }
[Severity: High]
If iommu_map_sgtable() fails for the LPAC domain (e.g. returning a negative
error), does this error path leave stale mappings in the primary domain?
Since the function returns an error without an unmap rollback, the caller
might eventually free the underlying physical pages, potentially leaving a
dangling mapping in the primary domain.
[ ... ]
> @@ -753,6 +843,30 @@ struct msm_mmu *msm_iommu_new(struct device *dev, unsigned long quirks)
> return ERR_PTR(ret);
> }
>
> + if (lpac_dev) {
> + if (!device_iommu_mapped(lpac_dev))
> + return ERR_PTR(-ENODEV);
[Severity: High]
Can this early return cause a memory leak? It appears to bypass the cleanup
of the iommu struct and the main domain that were allocated earlier in this
function.
> +
> + lpac_domain = iommu_paging_domain_alloc(lpac_dev);
> + if (IS_ERR(lpac_domain))
> + return ERR_CAST(lpac_domain);
> +
> + iommu_set_pgtable_quirks(lpac_domain, quirks);
> +
> + iommu->lpac_domain = lpac_domain;
> + iommu->base.lpac_dev = lpac_dev;
> + }
> +
> + if (lpac_domain) {
> + ret = iommu_attach_device(lpac_domain, lpac_dev);
> + if (ret) {
> + iommu_domain_free(domain);
> + iommu_domain_free(lpac_domain);
> + kfree(iommu);
> + return ERR_PTR(ret);
> + }
> + }
[Severity: High]
If iommu_attach_device() fails for the LPAC domain, does this error path
forget to detach the primary domain?
The primary domain was successfully attached earlier in the function via
iommu_attach_device(iommu->domain, dev), so an iommu_detach_device() call
might be missing before returning.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260705-descriptive-name-lpac-upstream-v1-0-01d50c3e0c99@gmail.com?part=2
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH RFC 13/13] drm/msm: add lpac ring to devcoredump
2026-07-05 19:13 ` [PATCH RFC 13/13] drm/msm: add lpac ring to devcoredump Anna Maniscalco
@ 2026-07-05 19:35 ` sashiko-bot
0 siblings, 0 replies; 34+ messages in thread
From: sashiko-bot @ 2026-07-05 19:35 UTC (permalink / raw)
To: Anna Maniscalco; +Cc: robh, devicetree, dri-devel, conor+dt
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
Pre-existing issues:
- [High] Unchecked error pointer causes kernel panic during devcoredump
--
commit d796b03f3d2b7a2a3e2dcafef659304fe3dd3b3e
Author: Anna Maniscalco <anna.maniscalco2000@gmail.com>
drm/msm: add lpac ring to devcoredump
This commit adds the LPAC ring state to the devcoredump to aid in debugging
GPU issues. It updates the loop conditions in the adreno GPU state functions
to include the LPAC ringbuffer data if it is present on the device.
> diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
> index 94dbec9464a4d..030bb1aeb7ee1 100644
> --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c
> +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
> @@ -782,25 +782,26 @@ int adreno_gpu_state_get(struct msm_gpu *gpu, struct msm_gpu_state *state)
>
> ktime_get_real_ts64(&state->time);
>
> - for (i = 0; i < gpu->nr_rings; i++) {
> + 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;
[Severity: High]
This isn't a bug introduced by this patch, but this devcoredump modification
exposes a pre-existing unhandled error pointer.
In msm_gpu_init(), if the allocation of gpu->lpac_rb fails (e.g., due to memory
pressure), it returns an error pointer. Due to a pre-existing bug, the error
check incorrectly evaluates IS_ERR(gpu->rb[i]) instead of IS_ERR(gpu->lpac_rb):
drivers/gpu/drm/msm/msm_gpu.c:msm_gpu_init() {
...
if (IS_ERR(gpu->rb[i])) {
...
}
Since an error pointer evaluates to true for !!gpu->lpac_rb, will this loop
include the error pointer and cause a kernel panic when it attempts to
dereference ring->memptrs->fence below?
> int size = 0, j;
>
> - state->ring[i].fence = gpu->rb[i]->memptrs->fence;
> - state->ring[i].iova = gpu->rb[i]->iova;
> - state->ring[i].seqno = gpu->rb[i]->fctx->last_fence;
> - state->ring[i].rptr = get_rptr(adreno_gpu, gpu->rb[i]);
> - state->ring[i].wptr = get_wptr(gpu->rb[i]);
> + state->ring[i].fence = ring->memptrs->fence;
> + state->ring[i].iova = ring->iova;
[ ... ]
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260705-descriptive-name-lpac-upstream-v1-0-01d50c3e0c99@gmail.com?part=13
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH RFC 11/13] drm/msm: Add LPAC submitqueue
2026-07-05 19:13 ` [PATCH RFC 11/13] drm/msm: Add LPAC submitqueue Anna Maniscalco
@ 2026-07-05 19:36 ` sashiko-bot
0 siblings, 0 replies; 34+ messages in thread
From: sashiko-bot @ 2026-07-05 19:36 UTC (permalink / raw)
To: Anna Maniscalco; +Cc: devicetree, conor+dt, robh, dri-devel
Thank you for your contribution! Sashiko AI review found 7 potential issue(s) to consider:
- [Critical] LPAC-specific registers and commands are programmed unconditionally for all A6XX-family GPUs, breaking hardware initialization on older chips.
- [High] Missing error check for LPAC ringbuffer allocation leads to out-of-bounds array access and silent failures.
- [High] Unconditional creation of LPAC submitqueues allows unprivileged users to cause unrecoverable GPU hangs on hardware without LPAC support.
- [High] The GPU hangcheck mechanism ignores the LPAC ring, meaning LPAC-exclusive hangs will never be recovered.
- [High] In `msm_iommu_new`, failing to attach the LPAC domain causes resource leaks and use-after-free bugs by freeing attached domains.
- [Medium] Performance counter statistics for LPAC submissions will be corrupted due to mismatched start and end register reads.
- [Medium] When error interrupts are disabled, LPAC completion interrupts are inadvertently dropped, causing job timeouts.
--
commit f42a6839003ad94fdc9d88ca88077e9fcbcda345
Author: Anna Maniscalco <anna.maniscalco2000@gmail.com>
drm/msm: Add LPAC submitqueue
Add UAPI and infostructure to support sending submission to the LPAC
ring.
> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> index 9f69aada9b7b7..4417a9d04d7c2 100644
> --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
[ ... ]
> @@ -493,7 +498,10 @@ static void a7xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
[ ... ]
> get_stats_counter(ring, rbbm_perfctr_cp0, rbmemptr_stats(ring, index, cpcycles_start));
> - get_stats_counter(ring, cp_always_on_context, rbmemptr_stats(ring, index, alwayson_start));
> + 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));
[Severity: Medium]
Does this cause a mismatch for LPAC submissions? The start counter
conditionally reads from cp_always_on_counter for LPAC, but the end counter
unconditionally reads from cp_always_on_context later in the function:
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));
This will cause the duration of LPAC jobs to be incorrectly calculated since
the start and end values are read from different registers.
> OUT_PKT7(ring, CP_THREAD_CONTROL, 1);
> OUT_RING(ring, CP_SET_THREAD_BOTH);
[ ... ]
> @@ -2030,6 +2048,9 @@ static irqreturn_t a6xx_irq(struct msm_gpu *gpu)
> a6xx_preempt_trigger(gpu);
> }
>
> + if (status & A6XX_RBBM_INT_0_MASK_CP_CACHE_FLUSH_TS_LPAC)
> + msm_gpu_retire(gpu);
> +
[Severity: Medium]
Are LPAC completion interrupts inadvertently dropped when error interrupts are
disabled?
Earlier in a6xx_irq():
if (priv->disable_err_irq)
status &= A6XX_RBBM_INT_0_MASK_CP_CACHE_FLUSH_TS;
In testing or debug modes where disable_err_irq is set, the interrupt status
mask preserves the main ring's completion bit but drops the newly added LPAC
completion bit (CP_CACHE_FLUSH_TS_LPAC). This causes LPAC jobs to artificially
time out during these tests. Should the mask be updated to include the LPAC
bit?
> if (status & A6XX_RBBM_INT_0_MASK_CP_SW)
[ ... ]
> diff --git a/drivers/gpu/drm/msm/msm_submitqueue.c b/drivers/gpu/drm/msm/msm_submitqueue.c
> index 1a5a77b280163..042b4f90fb73f 100644
> --- a/drivers/gpu/drm/msm/msm_submitqueue.c
> +++ b/drivers/gpu/drm/msm/msm_submitqueue.c
[ ... ]
> @@ -211,6 +212,13 @@ int msm_submitqueue_create(struct drm_device *drm, struct msm_context *ctx,
> queue = kzalloc_obj(*queue);
> }
>
> + if (flags & MSM_SUBMITQUEUE_LPAC) {
> + ring_nr = priv->gpu->nr_rings;
> + ring = priv->gpu->lpac_rb;
> + } else {
> + ring = priv->gpu->rb[ring_nr];
> + }
> +
[Severity: High]
Can an unprivileged user cause a GPU hang regression on hardware without LPAC
support?
Because lpac_rb is exposed unconditionally here, userspace can request an LPAC
submitqueue and push commands to it even on hardware without an LPAC processor.
The hardware will ignore the software ringbuffer, causing the jobs to time out
and the GPU to enter a recovery loop. Should this verify if the hardware
actually supports LPAC first?
> if (!queue)
> return -ENOMEM;
[ ... ]
I also noticed a few regressions in the broader LPAC enablement changes outside
of this specific diff:
[Severity: Critical]
Is it safe to unconditionally program LPAC registers for all A6xx-family GPUs?
drivers/gpu/drm/msm/adreno/a6xx_gpu.c:hw_init() {
...
/* Set the ringbuffer address for lpac */
gpu_write64(gpu, REG_A7XX_CP_LPAC_RB_BASE, gpu->lpac_rb->iova);
...
ret = lpac_cp_init(gpu);
if (ret)
goto out;
...
}
Writing to A7xx-only registers and submitting initialization commands to the
non-existent LPAC ring on older A6xx GPUs appears to cause the hardware to
timeout during a6xx_idle() and potentially trigger AHB bus errors. This
introduces a regression in GPU driver initialization on non-LPAC platforms.
[Severity: High]
Does this error check inspect the wrong variable?
drivers/gpu/drm/msm/msm_gpu.c:msm_gpu_init() {
...
gpu->lpac_rb = msm_ringbuffer_new(gpu, nr_rings, memptrs, memptrs_iova);
if (IS_ERR(gpu->rb[i])) {
ret = PTR_ERR(gpu->rb[i]);
...
}
This checks gpu->rb[i] instead of gpu->lpac_rb. This accesses memory past the
end of the initialized gpu->rb array and ignores lpac_rb allocation failures.
If the allocation fails, gpu->lpac_rb remains an error pointer and can cause a
panic when accessed later.
[Severity: High]
Will the GPU hangcheck mechanism fail to detect LPAC-exclusive hangs?
drivers/gpu/drm/msm/msm_gpu.c:hangcheck_handler() {
...
struct msm_ringbuffer *ring = gpu->funcs->active_ring(gpu);
...
}
The handler only inspects progress on the main ring returned by
active_ring(gpu), skipping the concurrent lpac_rb. If a job hangs on the LPAC
ring while the main ring is idle or progressing normally, the timer will never
detect the lockup and the GPU will remain stuck.
[Severity: High]
Could this error path leak the primary domain or cause a use-after-free?
drivers/gpu/drm/msm/msm_iommu.c:msm_iommu_new() {
...
if (lpac_dev) {
if (!device_iommu_mapped(lpac_dev))
return ERR_PTR(-ENODEV);
lpac_domain = iommu_paging_domain_alloc(lpac_dev);
if (IS_ERR(lpac_domain))
return ERR_CAST(lpac_domain);
...
ret = iommu_attach_device(lpac_domain, lpac_dev);
if (ret) {
iommu_domain_free(domain);
iommu_domain_free(lpac_domain);
kfree(iommu);
return ERR_PTR(ret);
}
...
}
If device_iommu_mapped(lpac_dev) is false or domain allocation fails, it
returns an error without freeing the primary domain, causing a memory leak.
Additionally, if iommu_attach_device() fails, it calls iommu_domain_free() on
the primary domain while it is still actively attached to dev. Freeing an
attached domain without first calling iommu_detach_device() can lead to
use-after-free corruption in the IOMMU subsystem.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260705-descriptive-name-lpac-upstream-v1-0-01d50c3e0c99@gmail.com?part=11
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH RFC 04/13] arm64: dts: qcom: sm8650: move smmu sid 1 to new lpac device
2026-07-05 19:13 ` [PATCH RFC 04/13] arm64: dts: qcom: sm8650: move smmu sid 1 to new lpac device Anna Maniscalco
2026-07-05 19:24 ` sashiko-bot
@ 2026-07-06 8:40 ` Konrad Dybcio
1 sibling, 0 replies; 34+ messages in thread
From: Konrad Dybcio @ 2026-07-06 8:40 UTC (permalink / raw)
To: Anna Maniscalco, Rob Clark, Will Deacon, Robin Murphy,
Joerg Roedel, Sean Paul, Konrad Dybcio, Akhil P Oommen,
Dmitry Baryshkov, Abhinav Kumar, Jessica Zhang, Marijn Suijten,
David Airlie, Simona Vetter, Bjorn Andersson, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann
Cc: iommu, linux-arm-msm, linux-arm-kernel, linux-kernel, dri-devel,
freedreno, devicetree
On 7/5/26 9:13 PM, Anna Maniscalco wrote:
> Previously both SID 0 and 1 where associated with the same domain.
>
> When LPAC is not used this is needed so firmware can acces memory when
> initializing using the same page table as GFX.
>
> To use LPAC however we need to move SID 1 to a different device.
>
> Signed-off-by: Anna Maniscalco <anna.maniscalco2000@gmail.com>
> ---
> arch/arm64/boot/dts/qcom/sm8650.dtsi | 12 ++++++++++--
> 1 file changed, 10 insertions(+), 2 deletions(-)
>
> diff --git a/arch/arm64/boot/dts/qcom/sm8650.dtsi b/arch/arm64/boot/dts/qcom/sm8650.dtsi
> index 1604bc8cff37..44e5f9d4b335 100644
> --- a/arch/arm64/boot/dts/qcom/sm8650.dtsi
> +++ b/arch/arm64/boot/dts/qcom/sm8650.dtsi
> @@ -4133,6 +4133,13 @@ tcsr: clock-controller@1fc0000 {
> #reset-cells = <1>;
> };
>
> + lpac: lpac@3d00000 {
> + compatible = "qcom,lpac";
> + reg = <0x0 0x03d00000 0x0 0x61000>;
> +
> + iommus = <&adreno_smmu 1 0x0>;
> + };
I think this could work better as a subnode of the GPU (or perhaps
if there's no "actual" separate address space, maybe just iommu-maps?
for something also making use of the latter, see patches 1-5 of:
https://lore.kernel.org/all/20260610-glymur-v8-0-1c79b9d51fc0@oss.qualcomm.com/
Konrad
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH RFC 10/13] drm/msm: initialize LPAC ring
2026-07-05 19:13 ` [PATCH RFC 10/13] drm/msm: initialize LPAC ring Anna Maniscalco
2026-07-05 19:26 ` sashiko-bot
@ 2026-07-06 8:44 ` Konrad Dybcio
2026-07-06 11:07 ` Anna Maniscalco
1 sibling, 1 reply; 34+ messages in thread
From: Konrad Dybcio @ 2026-07-06 8:44 UTC (permalink / raw)
To: Anna Maniscalco, Rob Clark, Will Deacon, Robin Murphy,
Joerg Roedel, Sean Paul, Konrad Dybcio, Akhil P Oommen,
Dmitry Baryshkov, Abhinav Kumar, Jessica Zhang, Marijn Suijten,
David Airlie, Simona Vetter, Bjorn Andersson, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann
Cc: iommu, linux-arm-msm, linux-arm-kernel, linux-kernel, dri-devel,
freedreno, devicetree
On 7/5/26 9:13 PM, Anna Maniscalco wrote:
> Program all the register needed to start up LPAC and send initialization
> sequence.
>
> Additionally, now that the LPAC ring is live, make the code aware of it.
>
> Signed-off-by: Anna Maniscalco <anna.maniscalco2000@gmail.com>
> ---
I believe some/all of these writes need to be guarded by if (has_lpac),
as many GPUs lack these registers and there may be side effects on
others
[...]
> a6xx_gpu->shadow = msm_gem_kernel_new(gpu->dev,
> - sizeof(u32) * gpu->nr_rings,
> + sizeof(u32) * (gpu->nr_rings + !!gpu->lpac_rb),
Should we rename nr_rings to something like nr_XXX_rings
where XXX is some uarch-generic (i.e. not SQE because we also
support pre-a6xx) name for the main number cruncher?
Konrad
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH RFC 10/13] drm/msm: initialize LPAC ring
2026-07-06 8:44 ` Konrad Dybcio
@ 2026-07-06 11:07 ` Anna Maniscalco
2026-07-06 11:09 ` Konrad Dybcio
2026-07-06 21:56 ` Akhil P Oommen
0 siblings, 2 replies; 34+ messages in thread
From: Anna Maniscalco @ 2026-07-06 11:07 UTC (permalink / raw)
To: Konrad Dybcio, Rob Clark, Will Deacon, Robin Murphy, Joerg Roedel,
Sean Paul, Konrad Dybcio, Akhil P Oommen, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, David Airlie,
Simona Vetter, Bjorn Andersson, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann
Cc: iommu, linux-arm-msm, linux-arm-kernel, linux-kernel, dri-devel,
freedreno, devicetree
On 7/6/26 10:44 AM, Konrad Dybcio wrote:
> On 7/5/26 9:13 PM, Anna Maniscalco wrote:
>> Program all the register needed to start up LPAC and send initialization
>> sequence.
>>
>> Additionally, now that the LPAC ring is live, make the code aware of it.
>>
>> Signed-off-by: Anna Maniscalco <anna.maniscalco2000@gmail.com>
>> ---
> I believe some/all of these writes need to be guarded by if (has_lpac),
> as many GPUs lack these registers and there may be side effects on
> others
That's correct yeah. I'm not sure what has_lpac should be though.
Something we add to catalog? Or checking if it is a gen that has LPAC?
>
>
> [...]
>
>> a6xx_gpu->shadow = msm_gem_kernel_new(gpu->dev,
>> - sizeof(u32) * gpu->nr_rings,
>> + sizeof(u32) * (gpu->nr_rings + !!gpu->lpac_rb),
> Should we rename nr_rings to something like nr_XXX_rings
> where XXX is some uarch-generic (i.e. not SQE because we also
> support pre-a6xx) name for the main number cruncher?
Qualcom calls it GC so nr_gc_rings perhaps?
>
> Konrad
Best regards,
--
Anna Maniscalco <anna.maniscalco2000@gmail.com>
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH RFC 10/13] drm/msm: initialize LPAC ring
2026-07-06 11:07 ` Anna Maniscalco
@ 2026-07-06 11:09 ` Konrad Dybcio
2026-07-06 21:56 ` Akhil P Oommen
1 sibling, 0 replies; 34+ messages in thread
From: Konrad Dybcio @ 2026-07-06 11:09 UTC (permalink / raw)
To: Anna Maniscalco, Rob Clark, Will Deacon, Robin Murphy,
Joerg Roedel, Sean Paul, Konrad Dybcio, Akhil P Oommen,
Dmitry Baryshkov, Abhinav Kumar, Jessica Zhang, Marijn Suijten,
David Airlie, Simona Vetter, Bjorn Andersson, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann
Cc: iommu, linux-arm-msm, linux-arm-kernel, linux-kernel, dri-devel,
freedreno, devicetree
On 7/6/26 1:07 PM, Anna Maniscalco wrote:
> On 7/6/26 10:44 AM, Konrad Dybcio wrote:
>> On 7/5/26 9:13 PM, Anna Maniscalco wrote:
>>> Program all the register needed to start up LPAC and send initialization
>>> sequence.
>>>
>>> Additionally, now that the LPAC ring is live, make the code aware of it.
>>>
>>> Signed-off-by: Anna Maniscalco <anna.maniscalco2000@gmail.com>
>>> ---
>> I believe some/all of these writes need to be guarded by if (has_lpac),
>> as many GPUs lack these registers and there may be side effects on
>> others
>
> That's correct yeah. I'm not sure what has_lpac should be though.
>
> Something we add to catalog? Or checking if it is a gen that has LPAC?
'Generation' is very much an umbrella term that we can't put too
much trust in in the feature department, kgsl defines it in the
catalog, per-GPU. I think that's the right thing to do.
>
>>
>>
>> [...]
>>
>>> a6xx_gpu->shadow = msm_gem_kernel_new(gpu->dev,
>>> - sizeof(u32) * gpu->nr_rings,
>>> + sizeof(u32) * (gpu->nr_rings + !!gpu->lpac_rb),
>> Should we rename nr_rings to something like nr_XXX_rings
>> where XXX is some uarch-generic (i.e. not SQE because we also
>> support pre-a6xx) name for the main number cruncher?
> Qualcom calls it GC so nr_gc_rings perhaps?
I'm not in the right part of Qualcomm to know, I'll let others comment
Konrad
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [RFC PATCH 00/13] Enable LPAC on a7xx series GPUs
2026-07-05 19:13 [RFC PATCH 00/13] Enable LPAC on a7xx series GPUs Anna Maniscalco
` (12 preceding siblings ...)
2026-07-05 19:13 ` [PATCH RFC 13/13] drm/msm: add lpac ring to devcoredump Anna Maniscalco
@ 2026-07-06 14:57 ` Dmitry Baryshkov
2026-07-06 22:00 ` Akhil P Oommen
13 siblings, 1 reply; 34+ messages in thread
From: Dmitry Baryshkov @ 2026-07-06 14:57 UTC (permalink / raw)
To: Anna Maniscalco
Cc: Rob Clark, Will Deacon, Robin Murphy, Joerg Roedel, Sean Paul,
Konrad Dybcio, Akhil P Oommen, Dmitry Baryshkov, Abhinav Kumar,
Jessica Zhang, Marijn Suijten, David Airlie, Simona Vetter,
Bjorn Andersson, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, iommu,
linux-arm-msm, linux-arm-kernel, linux-kernel, dri-devel,
freedreno, devicetree
On Sun, Jul 05, 2026 at 09:13:34PM +0200, Anna Maniscalco wrote:
> This series enables LPAC on a7xx GPUs
What is LPAC? Please explain (or at least expand it once) it here and in
the first commit goes to each subsystem
>
> Currently hangcheck and recovery are broken as the patches to make them
> work depend on https://lore.kernel.org/linux-arm-msm/20250911-preemption_aware_hangcheck-v1-0-974819876819@gmail.com/
>
> The series also depends on https://lore.kernel.org/linux-arm-msm/177919116291.814652.1720687887970998122.b4-ty@kernel.org/
> to work correctly.
>
> Signed-off-by: Anna Maniscalco <anna.maniscalco2000@gmail.com>
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH RFC 01/13] iommu: arm-smmu-qcom: Configure lpac device with split address space
2026-07-05 19:13 ` [PATCH RFC 01/13] iommu: arm-smmu-qcom: Configure lpac device with split address space Anna Maniscalco
@ 2026-07-06 15:00 ` Dmitry Baryshkov
0 siblings, 0 replies; 34+ messages in thread
From: Dmitry Baryshkov @ 2026-07-06 15:00 UTC (permalink / raw)
To: Anna Maniscalco
Cc: Rob Clark, Will Deacon, Robin Murphy, Joerg Roedel, Sean Paul,
Konrad Dybcio, Akhil P Oommen, Dmitry Baryshkov, Abhinav Kumar,
Jessica Zhang, Marijn Suijten, David Airlie, Simona Vetter,
Bjorn Andersson, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, iommu,
linux-arm-msm, linux-arm-kernel, linux-kernel, dri-devel,
freedreno, devicetree
On Sun, Jul 05, 2026 at 09:13:35PM +0200, Anna Maniscalco wrote:
> We want the context bank used by LPAC to use split address space just
> like GFX.
Why?
>
> Signed-off-by: Anna Maniscalco <anna.maniscalco2000@gmail.com>
> ---
> drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c | 11 ++++++++---
> 1 file changed, 8 insertions(+), 3 deletions(-)
>
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH RFC 03/13] drm/msm: look for lpac from dts
2026-07-05 19:13 ` [PATCH RFC 03/13] drm/msm: look for lpac from dts Anna Maniscalco
2026-07-05 19:27 ` sashiko-bot
@ 2026-07-06 15:04 ` Dmitry Baryshkov
1 sibling, 0 replies; 34+ messages in thread
From: Dmitry Baryshkov @ 2026-07-06 15:04 UTC (permalink / raw)
To: Anna Maniscalco
Cc: Rob Clark, Will Deacon, Robin Murphy, Joerg Roedel, Sean Paul,
Konrad Dybcio, Akhil P Oommen, Dmitry Baryshkov, Abhinav Kumar,
Jessica Zhang, Marijn Suijten, David Airlie, Simona Vetter,
Bjorn Andersson, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, iommu,
linux-arm-msm, linux-arm-kernel, linux-kernel, dri-devel,
freedreno, devicetree
On Sun, Jul 05, 2026 at 09:13:37PM +0200, Anna Maniscalco wrote:
> In order to associate the SID used by LPAC to it's own domain and
> context bank we need a separate node on the DTS.
Can we use iommu-map instead of adding a new device using the same
addresses? You provide zero explanations, but it seems like you are
trying to separate a part of the GPU into a separate device, but it's
unnecessary.
>
> Add the code to look up that node on initialization.
>
> Signed-off-by: Anna Maniscalco <anna.maniscalco2000@gmail.com>
> ---
> drivers/gpu/drm/msm/adreno/adreno_gpu.c | 21 ++++++++++++++++++++-
> drivers/gpu/drm/msm/msm_gpu.h | 1 +
> 2 files changed, 21 insertions(+), 1 deletion(-)
>
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH RFC 10/13] drm/msm: initialize LPAC ring
2026-07-06 11:07 ` Anna Maniscalco
2026-07-06 11:09 ` Konrad Dybcio
@ 2026-07-06 21:56 ` Akhil P Oommen
2026-07-06 22:13 ` Anna Maniscalco
1 sibling, 1 reply; 34+ messages in thread
From: Akhil P Oommen @ 2026-07-06 21:56 UTC (permalink / raw)
To: Anna Maniscalco, Konrad Dybcio, Rob Clark, Will Deacon,
Robin Murphy, Joerg Roedel, Sean Paul, Konrad Dybcio,
Dmitry Baryshkov, Abhinav Kumar, Jessica Zhang, Marijn Suijten,
David Airlie, Simona Vetter, Bjorn Andersson, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann
Cc: iommu, linux-arm-msm, linux-arm-kernel, linux-kernel, dri-devel,
freedreno, devicetree
On 7/6/2026 4:37 PM, Anna Maniscalco wrote:
> On 7/6/26 10:44 AM, Konrad Dybcio wrote:
>> On 7/5/26 9:13 PM, Anna Maniscalco wrote:
>>> Program all the register needed to start up LPAC and send initialization
>>> sequence.
>>>
>>> Additionally, now that the LPAC ring is live, make the code aware of it.
>>>
>>> Signed-off-by: Anna Maniscalco <anna.maniscalco2000@gmail.com>
>>> ---
>> I believe some/all of these writes need to be guarded by if (has_lpac),
>> as many GPUs lack these registers and there may be side effects on
>> others
>
> That's correct yeah. I'm not sure what has_lpac should be though.
>
> Something we add to catalog? Or checking if it is a gen that has LPAC?
We can introduce a new QUIRK (ADRENO_QUIRK_LPAC?).
>
>>
>>
>> [...]
>>
>>> a6xx_gpu->shadow = msm_gem_kernel_new(gpu->dev,
>>> - sizeof(u32) * gpu->nr_rings,
>>> + sizeof(u32) * (gpu->nr_rings + !!gpu-
>>> >lpac_rb),
>> Should we rename nr_rings to something like nr_XXX_rings
>> where XXX is some uarch-generic (i.e. not SQE because we also
>> support pre-a6xx) name for the main number cruncher?
> Qualcom calls it GC so nr_gc_rings perhaps?
How about nr_gfx_rings as those rings can handle graphics workload?
-Akhil.
>>
>> Konrad
>
>
> Best regards,
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [RFC PATCH 00/13] Enable LPAC on a7xx series GPUs
2026-07-06 14:57 ` [RFC PATCH 00/13] Enable LPAC on a7xx series GPUs Dmitry Baryshkov
@ 2026-07-06 22:00 ` Akhil P Oommen
0 siblings, 0 replies; 34+ messages in thread
From: Akhil P Oommen @ 2026-07-06 22:00 UTC (permalink / raw)
To: Dmitry Baryshkov, Anna Maniscalco
Cc: Rob Clark, Will Deacon, Robin Murphy, Joerg Roedel, Sean Paul,
Konrad Dybcio, Dmitry Baryshkov, Abhinav Kumar, Jessica Zhang,
Marijn Suijten, David Airlie, Simona Vetter, Bjorn Andersson,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann, iommu, linux-arm-msm,
linux-arm-kernel, linux-kernel, dri-devel, freedreno, devicetree
On 7/6/2026 8:27 PM, Dmitry Baryshkov wrote:
> On Sun, Jul 05, 2026 at 09:13:34PM +0200, Anna Maniscalco wrote:
>> This series enables LPAC on a7xx GPUs
>
> What is LPAC? Please explain (or at least expand it once) it here and in
> the first commit goes to each subsystem
Low Priority Async Compute.
-Akhil.
>
>>
>> Currently hangcheck and recovery are broken as the patches to make them
>> work depend on https://lore.kernel.org/linux-arm-msm/20250911-preemption_aware_hangcheck-v1-0-974819876819@gmail.com/
>>
>> The series also depends on https://lore.kernel.org/linux-arm-msm/177919116291.814652.1720687887970998122.b4-ty@kernel.org/
>> to work correctly.
>>
>> Signed-off-by: Anna Maniscalco <anna.maniscalco2000@gmail.com>
>
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH RFC 10/13] drm/msm: initialize LPAC ring
2026-07-06 21:56 ` Akhil P Oommen
@ 2026-07-06 22:13 ` Anna Maniscalco
0 siblings, 0 replies; 34+ messages in thread
From: Anna Maniscalco @ 2026-07-06 22:13 UTC (permalink / raw)
To: Akhil P Oommen, Konrad Dybcio, Rob Clark, Will Deacon,
Robin Murphy, Joerg Roedel, Sean Paul, Konrad Dybcio,
Dmitry Baryshkov, Abhinav Kumar, Jessica Zhang, Marijn Suijten,
David Airlie, Simona Vetter, Bjorn Andersson, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann
Cc: iommu, linux-arm-msm, linux-arm-kernel, linux-kernel, dri-devel,
freedreno, devicetree
On 7/6/26 11:56 PM, Akhil P Oommen wrote:
> On 7/6/2026 4:37 PM, Anna Maniscalco wrote:
>> On 7/6/26 10:44 AM, Konrad Dybcio wrote:
>>> On 7/5/26 9:13 PM, Anna Maniscalco wrote:
>>>> Program all the register needed to start up LPAC and send initialization
>>>> sequence.
>>>>
>>>> Additionally, now that the LPAC ring is live, make the code aware of it.
>>>>
>>>> Signed-off-by: Anna Maniscalco <anna.maniscalco2000@gmail.com>
>>>> ---
>>> I believe some/all of these writes need to be guarded by if (has_lpac),
>>> as many GPUs lack these registers and there may be side effects on
>>> others
>> That's correct yeah. I'm not sure what has_lpac should be though.
>>
>> Something we add to catalog? Or checking if it is a gen that has LPAC?
> We can introduce a new QUIRK (ADRENO_QUIRK_LPAC?).
>
>>>
>>> [...]
>>>
>>>> a6xx_gpu->shadow = msm_gem_kernel_new(gpu->dev,
>>>> - sizeof(u32) * gpu->nr_rings,
>>>> + sizeof(u32) * (gpu->nr_rings + !!gpu-
>>>>> lpac_rb),
>>> Should we rename nr_rings to something like nr_XXX_rings
>>> where XXX is some uarch-generic (i.e. not SQE because we also
>>> support pre-a6xx) name for the main number cruncher?
>> Qualcom calls it GC so nr_gc_rings perhaps?
> How about nr_gfx_rings as those rings can handle graphics workload?
That could be more intuitive yeah
>
> -Akhil.
>
>>> Konrad
>>
>> Best regards,
Best regards,
--
Anna Maniscalco <anna.maniscalco2000@gmail.com>
^ permalink raw reply [flat|nested] 34+ messages in thread
end of thread, other threads:[~2026-07-06 22:13 UTC | newest]
Thread overview: 34+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-05 19:13 [RFC PATCH 00/13] Enable LPAC on a7xx series GPUs Anna Maniscalco
2026-07-05 19:13 ` [PATCH RFC 01/13] iommu: arm-smmu-qcom: Configure lpac device with split address space Anna Maniscalco
2026-07-06 15:00 ` Dmitry Baryshkov
2026-07-05 19:13 ` [PATCH RFC 02/13] drm/msm: add support for lpac_domain in msm_mmu Anna Maniscalco
2026-07-05 19:27 ` sashiko-bot
2026-07-05 19:13 ` [PATCH RFC 03/13] drm/msm: look for lpac from dts Anna Maniscalco
2026-07-05 19:27 ` sashiko-bot
2026-07-06 15:04 ` Dmitry Baryshkov
2026-07-05 19:13 ` [PATCH RFC 04/13] arm64: dts: qcom: sm8650: move smmu sid 1 to new lpac device Anna Maniscalco
2026-07-05 19:24 ` sashiko-bot
2026-07-06 8:40 ` Konrad Dybcio
2026-07-05 19:13 ` [PATCH RFC 05/13] firmware: qcom: scm: Configure LPAC aperture Anna Maniscalco
2026-07-05 19:20 ` sashiko-bot
2026-07-05 19:13 ` [PATCH RFC 06/13] DEBUGGING: print contextbank and other ttbrs on fault Anna Maniscalco
2026-07-05 19:13 ` [PATCH RFC 07/13] iommu: arm-smmu-qcom: Fixed mapping between sid and cb for gpu and lpac Anna Maniscalco
2026-07-05 19:27 ` sashiko-bot
2026-07-05 19:13 ` [PATCH RFC 08/13] HACK: use cb1 address in lpac dtb node Anna Maniscalco
2026-07-05 19:18 ` sashiko-bot
2026-07-05 19:13 ` [PATCH RFC 09/13] temp: add LPAC regs Anna Maniscalco
2026-07-05 19:23 ` sashiko-bot
2026-07-05 19:13 ` [PATCH RFC 10/13] drm/msm: initialize LPAC ring Anna Maniscalco
2026-07-05 19:26 ` sashiko-bot
2026-07-06 8:44 ` Konrad Dybcio
2026-07-06 11:07 ` Anna Maniscalco
2026-07-06 11:09 ` Konrad Dybcio
2026-07-06 21:56 ` Akhil P Oommen
2026-07-06 22:13 ` Anna Maniscalco
2026-07-05 19:13 ` [PATCH RFC 11/13] drm/msm: Add LPAC submitqueue Anna Maniscalco
2026-07-05 19:36 ` sashiko-bot
2026-07-05 19:13 ` [PATCH RFC 12/13] drm/msm: set ctxbank and asid based on ring Anna Maniscalco
2026-07-05 19:13 ` [PATCH RFC 13/13] drm/msm: add lpac ring to devcoredump Anna Maniscalco
2026-07-05 19:35 ` sashiko-bot
2026-07-06 14:57 ` [RFC PATCH 00/13] Enable LPAC on a7xx series GPUs Dmitry Baryshkov
2026-07-06 22:00 ` Akhil P Oommen
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox