diff --git a/drivers/iommu/riscv/iommu.c b/drivers/iommu/riscv/iommu.c index e335beb70e42..fe8e6d0f8a23 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; @@ -462,14 +463,16 @@ 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: /* 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; } /* @@ -508,7 +511,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. */ @@ -517,9 +520,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;