[PATCH 3/3] iommu/riscv: Avoid waiting on failed command enqueue
fangyu.yu at linux.alibaba.com
fangyu.yu at linux.alibaba.com
Mon Aug 17 07:27:28 PDT 2026
From: Fangyu Yu <fangyu.yu at linux.alibaba.com>
Do not wait for IOFENCE.C completion when the command failed to enter the
queue. The command was not published to hardware, so waiting for its
producer index can only report a misleading execution timeout.
Fixes: 856c0cfe5c5f ("iommu/riscv: Command and fault queue support")
Signed-off-by: Fangyu Yu <fangyu.yu at linux.alibaba.com>
---
drivers/iommu/riscv/iommu.c | 20 +++++++++++++-------
1 file changed, 13 insertions(+), 7 deletions(-)
diff --git a/drivers/iommu/riscv/iommu.c b/drivers/iommu/riscv/iommu.c
index 86cec408be5b..2b3dc63536d5 100644
--- a/drivers/iommu/riscv/iommu.c
+++ b/drivers/iommu/riscv/iommu.c
@@ -419,8 +419,9 @@ static int riscv_iommu_queue_wait_for_space(struct riscv_iommu_queue *queue,
}
/* Enqueue an entry and publish it to the hardware queue. */
-static unsigned int riscv_iommu_queue_send(struct riscv_iommu_queue *queue,
- void *entry, size_t entry_size)
+static int riscv_iommu_queue_send(struct riscv_iommu_queue *queue,
+ void *entry, size_t entry_size,
+ unsigned int *out_prod)
{
unsigned int prod;
unsigned int head;
@@ -465,15 +466,17 @@ static unsigned int riscv_iommu_queue_send(struct riscv_iommu_queue *queue,
atomic_set(&queue->tail, prod + 1);
atomic_set(&queue->prod, prod + 1);
- raw_spin_unlock_irqrestore(&queue->lock, flags);
+ if (out_prod)
+ *out_prod = prod;
- return prod;
+ raw_spin_unlock_irqrestore(&queue->lock, flags);
+ return 0;
err_busy:
raw_spin_unlock_irqrestore(&queue->lock, flags);
/* Report the failure and continue; full RAS recovery is not implemented. */
dev_err_once(queue->iommu->dev, "Hardware error: command enqueue failed\n");
- return prod;
+ return ret;
}
/*
@@ -512,7 +515,7 @@ static irqreturn_t riscv_iommu_cmdq_process(int irq, void *data)
static void riscv_iommu_cmd_send(struct riscv_iommu_device *iommu,
struct riscv_iommu_command *cmd)
{
- riscv_iommu_queue_send(&iommu->cmdq, cmd, sizeof(*cmd));
+ riscv_iommu_queue_send(&iommu->cmdq, cmd, sizeof(*cmd), NULL);
}
/* Send IOFENCE.C command and wait for all scheduled commands to complete. */
@@ -521,9 +524,12 @@ static void riscv_iommu_cmd_sync(struct riscv_iommu_device *iommu,
{
struct riscv_iommu_command cmd;
unsigned int prod;
+ int ret;
riscv_iommu_cmd_iofence(&cmd);
- prod = riscv_iommu_queue_send(&iommu->cmdq, &cmd, sizeof(cmd));
+ ret = riscv_iommu_queue_send(&iommu->cmdq, &cmd, sizeof(cmd), &prod);
+ if (ret)
+ return;
if (!timeout_us)
return;
--
2.50.1
More information about the linux-riscv
mailing list