mirror of
https://github.com/torvalds/linux.git
synced 2026-05-23 22:52:19 +02:00
iommu/amd: move wait_on_sem() out of spinlock
With iommu.strict=1, the existing completion wait path can cause soft lockups under stressed environment, as wait_on_sem() busy-waits under the spinlock with interrupts disabled. Move the completion wait in iommu_completion_wait() out of the spinlock. wait_on_sem() only polls the hardware-updated cmd_sem and does not require iommu->lock, so holding the lock during the busy wait unnecessarily increases contention and extends the time with interrupts disabled. Signed-off-by: Ankit Soni <Ankit.Soni@amd.com> Reviewed-by: Vasant Hegde <vasant.hegde@amd.com> Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
This commit is contained in:
parent
9ace4753a5
commit
d2a0cac105
|
|
@ -1185,7 +1185,12 @@ static int wait_on_sem(struct amd_iommu *iommu, u64 data)
|
|||
{
|
||||
int i = 0;
|
||||
|
||||
while (*iommu->cmd_sem != data && i < LOOP_TIMEOUT) {
|
||||
/*
|
||||
* cmd_sem holds a monotonically non-decreasing completion sequence
|
||||
* number.
|
||||
*/
|
||||
while ((__s64)(READ_ONCE(*iommu->cmd_sem) - data) < 0 &&
|
||||
i < LOOP_TIMEOUT) {
|
||||
udelay(1);
|
||||
i += 1;
|
||||
}
|
||||
|
|
@ -1437,14 +1442,13 @@ static int iommu_completion_wait(struct amd_iommu *iommu)
|
|||
raw_spin_lock_irqsave(&iommu->lock, flags);
|
||||
|
||||
ret = __iommu_queue_command_sync(iommu, &cmd, false);
|
||||
raw_spin_unlock_irqrestore(&iommu->lock, flags);
|
||||
|
||||
if (ret)
|
||||
goto out_unlock;
|
||||
return ret;
|
||||
|
||||
ret = wait_on_sem(iommu, data);
|
||||
|
||||
out_unlock:
|
||||
raw_spin_unlock_irqrestore(&iommu->lock, flags);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -3121,13 +3125,18 @@ static void iommu_flush_irt_and_complete(struct amd_iommu *iommu, u16 devid)
|
|||
raw_spin_lock_irqsave(&iommu->lock, flags);
|
||||
ret = __iommu_queue_command_sync(iommu, &cmd, true);
|
||||
if (ret)
|
||||
goto out;
|
||||
goto out_err;
|
||||
ret = __iommu_queue_command_sync(iommu, &cmd2, false);
|
||||
if (ret)
|
||||
goto out;
|
||||
wait_on_sem(iommu, data);
|
||||
out:
|
||||
goto out_err;
|
||||
raw_spin_unlock_irqrestore(&iommu->lock, flags);
|
||||
|
||||
wait_on_sem(iommu, data);
|
||||
return;
|
||||
|
||||
out_err:
|
||||
raw_spin_unlock_irqrestore(&iommu->lock, flags);
|
||||
return;
|
||||
}
|
||||
|
||||
static inline u8 iommu_get_int_tablen(struct iommu_dev_data *dev_data)
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user