From: Nicolin Chen <nicolinc@nvidia.com>
To: Will Deacon <will@kernel.org>,
Robin Murphy <robin.murphy@arm.com>,
"Joerg Roedel" <joro@8bytes.org>,
Bjorn Helgaas <bhelgaas@google.com>,
"Jason Gunthorpe" <jgg@nvidia.com>
Cc: "Rafael J . Wysocki" <rafael@kernel.org>,
Len Brown <lenb@kernel.org>,
Pranjal Shrivastava <praan@google.com>,
Mostafa Saleh <smostafa@google.com>,
Lu Baolu <baolu.lu@linux.intel.com>,
Kevin Tian <kevin.tian@intel.com>,
<linux-arm-kernel@lists.infradead.org>, <iommu@lists.linux.dev>,
<linux-kernel@vger.kernel.org>, <linux-acpi@vger.kernel.org>,
<linux-pci@vger.kernel.org>, <vsethi@nvidia.com>,
Shuai Xue <xueshuai@linux.alibaba.com>
Subject: [PATCH v4 14/24] iommu/arm-smmu-v3: Introduce per-cmdq cmdq_err_handler callback
Date: Mon, 18 May 2026 20:38:57 -0700 [thread overview]
Message-ID: <c5a10cf76339bf8349b5db4c0bb0728db4073f8a.1779161849.git.nicolinc@nvidia.com> (raw)
In-Reply-To: <cover.1779161849.git.nicolinc@nvidia.com>
A subsequent change will need arm_smmu_cmdq_issue_cmdlist() to co-clear a
pending CMDQ_ERR after a CMD_SYNC poll timeout. And this needs to be done
for both smmu->cmdq and tegra241-cmdq.
Add a cmdq_err_handler and a paired cmdq_err_lock to struct arm_smmu_cmdq.
arm_smmu_gerror_handler() and tegra241_vintf0_handle_error() now take the
per-cmdq cmdq_err_lock when acking CMDQ_ERR.
tegra241_vintf0_handle_error() also checks (gerror ^ gerrorn) inside the
cmdq_err_lock since a concurrent cmdq_err_handler may have already acked
the error. arm_smmu_gerror_handler() already covers this via its existing
early-exit on no-active-bits.
Impl functions and caller will be added in the subsequent change.
Assisted-by: Claude:claude-opus-4-7
Signed-off-by: Nicolin Chen <nicolinc@nvidia.com>
---
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h | 12 ++++++++++--
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 18 ++++++++++++++----
drivers/iommu/arm/arm-smmu-v3/tegra241-cmdqv.c | 15 ++++++++++++---
3 files changed, 36 insertions(+), 9 deletions(-)
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
index 46f9e292a1cc8..604f7edf54158 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
@@ -695,6 +695,10 @@ struct arm_smmu_queue_poll {
bool wfe;
};
+struct arm_smmu_cmdq;
+typedef void (*arm_smmu_cmdq_err_fn)(struct arm_smmu_device *smmu,
+ struct arm_smmu_cmdq *cmdq);
+
struct arm_smmu_cmdq {
struct arm_smmu_queue q;
atomic_long_t *valid_map;
@@ -702,6 +706,10 @@ struct arm_smmu_cmdq {
atomic_t lock;
unsigned long *atc_sync_timeouts;
bool (*supports_cmd)(struct arm_smmu_cmd *cmd);
+
+ /* Drain a pending CMDQ_ERR; will hold cmdq_err_lock with irqsave */
+ arm_smmu_cmdq_err_fn cmdq_err_handler;
+ raw_spinlock_t cmdq_err_lock;
};
static inline bool arm_smmu_cmdq_supports_cmd(struct arm_smmu_cmdq *cmdq,
@@ -1163,8 +1171,8 @@ int arm_smmu_init_one_queue(struct arm_smmu_device *smmu,
struct arm_smmu_queue *q, void __iomem *page,
unsigned long prod_off, unsigned long cons_off,
size_t dwords, const char *name);
-int arm_smmu_cmdq_init(struct arm_smmu_device *smmu,
- struct arm_smmu_cmdq *cmdq);
+int arm_smmu_cmdq_init(struct arm_smmu_device *smmu, struct arm_smmu_cmdq *cmdq,
+ arm_smmu_cmdq_err_fn cmdq_err_handler);
static inline bool arm_smmu_master_canwbs(struct arm_smmu_master *master)
{
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
index d9fe48989fcd7..fc0757359b783 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -2255,13 +2255,18 @@ static irqreturn_t arm_smmu_gerror_handler(int irq, void *dev)
{
u32 gerror, gerrorn, active;
struct arm_smmu_device *smmu = dev;
+ unsigned long flags;
+
+ raw_spin_lock_irqsave(&smmu->cmdq.cmdq_err_lock, flags);
gerror = readl_relaxed(smmu->base + ARM_SMMU_GERROR);
gerrorn = readl_relaxed(smmu->base + ARM_SMMU_GERRORN);
active = gerror ^ gerrorn;
- if (!(active & GERROR_ERR_MASK))
+ if (!(active & GERROR_ERR_MASK)) {
+ raw_spin_unlock_irqrestore(&smmu->cmdq.cmdq_err_lock, flags);
return IRQ_NONE; /* No errors pending */
+ }
dev_warn(smmu->dev,
"unexpected global error reported (0x%08x), this could be serious\n",
@@ -2270,6 +2275,8 @@ static irqreturn_t arm_smmu_gerror_handler(int irq, void *dev)
if (active & GERROR_SFM_ERR) {
/* SMMU is being disabled, so other errors don't matter */
writel(gerror, smmu->base + ARM_SMMU_GERRORN);
+ /* Release before arm_smmu_device_disable() that sleeps */
+ raw_spin_unlock_irqrestore(&smmu->cmdq.cmdq_err_lock, flags);
dev_err(smmu->dev, "device has entered Service Failure Mode!\n");
arm_smmu_device_disable(smmu);
return IRQ_HANDLED;
@@ -2297,6 +2304,7 @@ static irqreturn_t arm_smmu_gerror_handler(int irq, void *dev)
arm_smmu_cmdq_skip_err(smmu);
writel(gerror, smmu->base + ARM_SMMU_GERRORN);
+ raw_spin_unlock_irqrestore(&smmu->cmdq.cmdq_err_lock, flags);
return IRQ_HANDLED;
}
@@ -4357,13 +4365,15 @@ int arm_smmu_init_one_queue(struct arm_smmu_device *smmu,
return 0;
}
-int arm_smmu_cmdq_init(struct arm_smmu_device *smmu,
- struct arm_smmu_cmdq *cmdq)
+int arm_smmu_cmdq_init(struct arm_smmu_device *smmu, struct arm_smmu_cmdq *cmdq,
+ arm_smmu_cmdq_err_fn cmdq_err_handler)
{
unsigned int nents = 1 << cmdq->q.llq.max_n_shift;
atomic_set(&cmdq->owner_prod, 0);
atomic_set(&cmdq->lock, 0);
+ raw_spin_lock_init(&cmdq->cmdq_err_lock);
+ cmdq->cmdq_err_handler = cmdq_err_handler;
cmdq->valid_map = (atomic_long_t *)devm_bitmap_zalloc(smmu->dev, nents,
GFP_KERNEL);
@@ -4389,7 +4399,7 @@ static int arm_smmu_init_queues(struct arm_smmu_device *smmu)
if (ret)
return ret;
- ret = arm_smmu_cmdq_init(smmu, &smmu->cmdq);
+ ret = arm_smmu_cmdq_init(smmu, &smmu->cmdq, NULL);
if (ret)
return ret;
diff --git a/drivers/iommu/arm/arm-smmu-v3/tegra241-cmdqv.c b/drivers/iommu/arm/arm-smmu-v3/tegra241-cmdqv.c
index 67be62a6e7640..fb2f8f68fa344 100644
--- a/drivers/iommu/arm/arm-smmu-v3/tegra241-cmdqv.c
+++ b/drivers/iommu/arm/arm-smmu-v3/tegra241-cmdqv.c
@@ -319,10 +319,19 @@ static void tegra241_vintf0_handle_error(struct tegra241_vintf *vintf)
while (map) {
unsigned long lidx = __ffs64(map);
struct tegra241_vcmdq *vcmdq = vintf->lvcmdqs[lidx];
- u32 gerror = readl_relaxed(REG_VCMDQ_PAGE0(vcmdq, GERROR));
+ struct arm_smmu_cmdq *cmdq = &vcmdq->cmdq;
+ unsigned long flags;
+ u32 gerror, gerrorn;
- __arm_smmu_cmdq_skip_err(&vintf->cmdqv->smmu, &vcmdq->cmdq);
+ raw_spin_lock_irqsave(&cmdq->cmdq_err_lock, flags);
+ gerror = readl_relaxed(REG_VCMDQ_PAGE0(vcmdq, GERROR));
+ gerrorn = readl_relaxed(REG_VCMDQ_PAGE0(vcmdq, GERRORN));
+
+ if ((gerror ^ gerrorn) & GERROR_CMDQ_ERR)
+ __arm_smmu_cmdq_skip_err(&vintf->cmdqv->smmu,
+ cmdq);
writel(gerror, REG_VCMDQ_PAGE0(vcmdq, GERRORN));
+ raw_spin_unlock_irqrestore(&cmdq->cmdq_err_lock, flags);
map &= ~BIT_ULL(lidx);
}
}
@@ -643,7 +652,7 @@ static int tegra241_vcmdq_alloc_smmu_cmdq(struct tegra241_vcmdq *vcmdq)
q->q_base = q->base_dma & VCMDQ_ADDR;
q->q_base |= FIELD_PREP(VCMDQ_LOG2SIZE, q->llq.max_n_shift);
- return arm_smmu_cmdq_init(smmu, cmdq);
+ return arm_smmu_cmdq_init(smmu, cmdq, NULL);
}
/* VINTF Logical VCMDQ Resource Helpers */
--
2.43.0
next prev parent reply other threads:[~2026-05-19 3:40 UTC|newest]
Thread overview: 54+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-05-19 3:38 [PATCH v4 00/24] iommu/arm-smmu-v3: Quarantine device upon ATC invalidation timeout Nicolin Chen
2026-05-19 3:38 ` [PATCH v4 01/24] PCI: Don't suspend IOMMU when probing reset capability Nicolin Chen
2026-05-19 3:38 ` [PATCH v4 02/24] PCI: Propagate FLR return values to callers Nicolin Chen
2026-05-19 3:38 ` [PATCH v4 03/24] iommu: Convert gdev->blocked from bool to enum gdev_blocked Nicolin Chen
2026-05-19 3:38 ` [PATCH v4 04/24] iommu: Pass in reset result to pci_dev_reset_iommu_done() Nicolin Chen
2026-05-19 3:38 ` [PATCH v4 05/24] iommu: Add reset_device_done callback for hardware fault recovery Nicolin Chen
2026-05-19 3:38 ` [PATCH v4 06/24] iommu: Defer iommu_group free via kfree_rcu() Nicolin Chen
2026-05-19 11:39 ` Jason Gunthorpe
2026-05-19 18:54 ` Nicolin Chen
2026-05-19 3:38 ` [PATCH v4 07/24] iommu: Defer __iommu_group_free_device() to be outside group->mutex Nicolin Chen
2026-05-19 11:47 ` Jason Gunthorpe
2026-05-19 3:38 ` [PATCH v4 08/24] iommu: Change group->devices to RCU-protected list Nicolin Chen
2026-05-19 3:38 ` [PATCH v4 09/24] iommu: Add group pointer to struct group_device Nicolin Chen
2026-05-19 3:38 ` [PATCH v4 10/24] iommu: Add __iommu_group_block_device helper Nicolin Chen
2026-05-19 3:38 ` [PATCH v4 11/24] iommu: Add iommu_report_device_broken() to quarantine a broken device Nicolin Chen
2026-05-19 12:07 ` Jason Gunthorpe
2026-05-19 18:29 ` Nicolin Chen
2026-05-19 19:16 ` Jason Gunthorpe
2026-05-19 22:30 ` Nicolin Chen
2026-05-19 23:02 ` Jason Gunthorpe
2026-05-20 0:21 ` Nicolin Chen
2026-05-20 0:30 ` Jason Gunthorpe
2026-05-20 7:20 ` Nicolin Chen
2026-05-20 17:51 ` Jason Gunthorpe
2026-05-20 18:13 ` Nicolin Chen
2026-05-21 13:12 ` Jason Gunthorpe
2026-05-19 3:38 ` [PATCH v4 12/24] iommu/arm-smmu-v3: Mark ATC invalidate timeouts via lockless bitmap Nicolin Chen
2026-05-19 3:38 ` [PATCH v4 13/24] iommu/arm-smmu-v3: Skip remaining GERROR causes on SFM Nicolin Chen
2026-05-19 3:38 ` Nicolin Chen [this message]
2026-05-19 3:38 ` [PATCH v4 15/24] iommu/arm-smmu-v3: Co-clear pending CMDQ_ERR when CMD_SYNC times out Nicolin Chen
2026-05-19 3:38 ` [PATCH v4 16/24] iommu/arm-smmu-v3: Co-clear pending CMDQ_ERR when queue_has_space() fails Nicolin Chen
2026-05-19 3:39 ` [PATCH v4 17/24] iommu/arm-smmu-v3: Add master in arm_smmu_inv for ATS entries Nicolin Chen
2026-05-19 12:01 ` Jason Gunthorpe
2026-05-19 3:39 ` [PATCH v4 18/24] iommu/arm-smmu-v3: Introduce master->ats_broken flag Nicolin Chen
2026-05-19 12:06 ` Jason Gunthorpe
2026-05-30 1:27 ` Nicolin Chen
2026-06-01 12:32 ` Jason Gunthorpe
2026-06-01 20:41 ` Nicolin Chen
2026-06-02 0:15 ` Jason Gunthorpe
2026-06-02 5:44 ` Nicolin Chen
2026-06-05 19:42 ` Jason Gunthorpe
2026-06-05 21:56 ` Nicolin Chen
2026-06-05 23:03 ` Jason Gunthorpe
2026-06-06 4:04 ` Nicolin Chen
2026-05-19 3:39 ` [PATCH v4 19/24] iommu/arm-smmu-v3: Add invs and has_ats to struct arm_smmu_cmdq_batch Nicolin Chen
2026-05-19 12:09 ` Jason Gunthorpe
2026-05-19 3:39 ` [PATCH v4 20/24] iommu/arm-smmu-v3: Introduce arm_smmu_cmdq_batch_issue() wrapper Nicolin Chen
2026-05-19 3:39 ` [PATCH v4 21/24] iommu/arm-smmu-v3: Move arm_smmu_invs_for_each_entry to header Nicolin Chen
2026-05-19 3:39 ` [PATCH v4 22/24] iommu/arm-smmu-v3: Introduce master->ats_invs Nicolin Chen
2026-05-19 12:12 ` Jason Gunthorpe
2026-05-19 3:39 ` [PATCH v4 23/24] iommu/arm-smmu-v3: Serialize STE.EATS and ats_broken updates Nicolin Chen
2026-05-19 3:39 ` [PATCH v4 24/24] iommu/arm-smmu-v3: Block ATS upon an ATC invalidation timeout Nicolin Chen
2026-05-20 3:59 ` [PATCH v4 00/24] iommu/arm-smmu-v3: Quarantine device upon " Tian, Kevin
2026-05-20 6:38 ` Nicolin Chen
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=c5a10cf76339bf8349b5db4c0bb0728db4073f8a.1779161849.git.nicolinc@nvidia.com \
--to=nicolinc@nvidia.com \
--cc=baolu.lu@linux.intel.com \
--cc=bhelgaas@google.com \
--cc=iommu@lists.linux.dev \
--cc=jgg@nvidia.com \
--cc=joro@8bytes.org \
--cc=kevin.tian@intel.com \
--cc=lenb@kernel.org \
--cc=linux-acpi@vger.kernel.org \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-pci@vger.kernel.org \
--cc=praan@google.com \
--cc=rafael@kernel.org \
--cc=robin.murphy@arm.com \
--cc=smostafa@google.com \
--cc=vsethi@nvidia.com \
--cc=will@kernel.org \
--cc=xueshuai@linux.alibaba.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®