Skip to content

Commit bccc37a

Browse files
ssuthiku-amdjoergroedel
authored andcommitted
iommu/amd: Improving Interrupt Remapping Table Invalidation
Invalidating Interrupt Remapping Table (IRT) requires, the AMD IOMMU driver to issue INVALIDATE_INTERRUPT_TABLE and COMPLETION_WAIT commands. Currently, the driver issues the two commands separately, which requires calling raw_spin_lock_irqsave() twice. In addition, the COMPLETION_WAIT could potentially be interleaved with other commands causing delay of the COMPLETION_WAIT command. Therefore, combine issuing of the two commands in one spin-lock, and changing struct amd_iommu.cmd_sem_val to use atomic64 to minimize locking. Reviewed-by: Jerry Snitselaar <[email protected]> Signed-off-by: Suravee Suthikulpanit <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Joerg Roedel <[email protected]>
1 parent 98aeb4e commit bccc37a

File tree

3 files changed

+24
-7
lines changed

3 files changed

+24
-7
lines changed

drivers/iommu/amd/amd_iommu_types.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -752,7 +752,7 @@ struct amd_iommu {
752752

753753
u32 flags;
754754
volatile u64 *cmd_sem;
755-
u64 cmd_sem_val;
755+
atomic64_t cmd_sem_val;
756756

757757
#ifdef CONFIG_AMD_IOMMU_DEBUGFS
758758
/* DebugFS Info */

drivers/iommu/amd/init.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1733,7 +1733,7 @@ static int __init init_iommu_one(struct amd_iommu *iommu, struct ivhd_header *h,
17331733
iommu->pci_seg = pci_seg;
17341734

17351735
raw_spin_lock_init(&iommu->lock);
1736-
iommu->cmd_sem_val = 0;
1736+
atomic64_set(&iommu->cmd_sem_val, 0);
17371737

17381738
/* Add IOMMU to internal data structures */
17391739
list_add_tail(&iommu->list, &amd_iommu_list);

drivers/iommu/amd/iommu.c

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1175,11 +1175,11 @@ static int iommu_completion_wait(struct amd_iommu *iommu)
11751175
if (!iommu->need_sync)
11761176
return 0;
11771177

1178-
raw_spin_lock_irqsave(&iommu->lock, flags);
1179-
1180-
data = ++iommu->cmd_sem_val;
1178+
data = atomic64_add_return(1, &iommu->cmd_sem_val);
11811179
build_completion_wait(&cmd, iommu, data);
11821180

1181+
raw_spin_lock_irqsave(&iommu->lock, flags);
1182+
11831183
ret = __iommu_queue_command_sync(iommu, &cmd, false);
11841184
if (ret)
11851185
goto out_unlock;
@@ -1277,11 +1277,28 @@ static void amd_iommu_flush_irt_all(struct amd_iommu *iommu)
12771277

12781278
static void iommu_flush_irt_and_complete(struct amd_iommu *iommu, u16 devid)
12791279
{
1280+
int ret;
1281+
u64 data;
1282+
unsigned long flags;
1283+
struct iommu_cmd cmd, cmd2;
1284+
12801285
if (iommu->irtcachedis_enabled)
12811286
return;
12821287

1283-
iommu_flush_irt(iommu, devid);
1284-
iommu_completion_wait(iommu);
1288+
build_inv_irt(&cmd, devid);
1289+
data = atomic64_add_return(1, &iommu->cmd_sem_val);
1290+
build_completion_wait(&cmd2, iommu, data);
1291+
1292+
raw_spin_lock_irqsave(&iommu->lock, flags);
1293+
ret = __iommu_queue_command_sync(iommu, &cmd, true);
1294+
if (ret)
1295+
goto out;
1296+
ret = __iommu_queue_command_sync(iommu, &cmd2, false);
1297+
if (ret)
1298+
goto out;
1299+
wait_on_sem(iommu, data);
1300+
out:
1301+
raw_spin_unlock_irqrestore(&iommu->lock, flags);
12851302
}
12861303

12871304
void iommu_flush_all_caches(struct amd_iommu *iommu)

0 commit comments

Comments
 (0)