Skip to content

Commit 6554727

Browse files
jgunthorpewilldeacon
authored andcommitted
iommu/arm-smmu-v3: Compute the STE only once for each master
Currently arm_smmu_install_ste_for_dev() iterates over every SID and computes from scratch an identical STE. Every SID should have the same STE contents. Turn this inside out so that the STE is supplied by the caller and arm_smmu_install_ste_for_dev() simply installs it to every SID. This is possible now that the STE generation does not inform what sequence should be used to program it. This allows splitting the STE calculation up according to the call site, which following patches will make use of, and removes the confusing NULL domain special case that only supported arm_smmu_detach_dev(). Reviewed-by: Michael Shavit <[email protected]> Reviewed-by: Nicolin Chen <[email protected]> Reviewed-by: Mostafa Saleh <[email protected]> Tested-by: Shameer Kolothum <[email protected]> Tested-by: Nicolin Chen <[email protected]> Tested-by: Moritz Fischer <[email protected]> Signed-off-by: Jason Gunthorpe <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Will Deacon <[email protected]>
1 parent 9f7c689 commit 6554727

File tree

1 file changed

+22
-35
lines changed

1 file changed

+22
-35
lines changed

drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c

Lines changed: 22 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1558,35 +1558,6 @@ static void arm_smmu_make_s2_domain_ste(struct arm_smmu_ste *target,
15581558
STRTAB_STE_3_S2TTB_MASK);
15591559
}
15601560

1561-
static void arm_smmu_write_strtab_ent(struct arm_smmu_master *master, u32 sid,
1562-
struct arm_smmu_ste *dst)
1563-
{
1564-
struct arm_smmu_domain *smmu_domain = master->domain;
1565-
struct arm_smmu_ste target = {};
1566-
1567-
if (!smmu_domain) {
1568-
if (disable_bypass)
1569-
arm_smmu_make_abort_ste(&target);
1570-
else
1571-
arm_smmu_make_bypass_ste(&target);
1572-
arm_smmu_write_ste(master, sid, dst, &target);
1573-
return;
1574-
}
1575-
1576-
switch (smmu_domain->stage) {
1577-
case ARM_SMMU_DOMAIN_S1:
1578-
arm_smmu_make_cdtable_ste(&target, master);
1579-
break;
1580-
case ARM_SMMU_DOMAIN_S2:
1581-
arm_smmu_make_s2_domain_ste(&target, master, smmu_domain);
1582-
break;
1583-
case ARM_SMMU_DOMAIN_BYPASS:
1584-
arm_smmu_make_bypass_ste(&target);
1585-
break;
1586-
}
1587-
arm_smmu_write_ste(master, sid, dst, &target);
1588-
}
1589-
15901561
/*
15911562
* This can safely directly manipulate the STE memory without a sync sequence
15921563
* because the STE table has not been installed in the SMMU yet.
@@ -2413,7 +2384,8 @@ arm_smmu_get_step_for_sid(struct arm_smmu_device *smmu, u32 sid)
24132384
}
24142385
}
24152386

2416-
static void arm_smmu_install_ste_for_dev(struct arm_smmu_master *master)
2387+
static void arm_smmu_install_ste_for_dev(struct arm_smmu_master *master,
2388+
const struct arm_smmu_ste *target)
24172389
{
24182390
int i, j;
24192391
struct arm_smmu_device *smmu = master->smmu;
@@ -2430,7 +2402,7 @@ static void arm_smmu_install_ste_for_dev(struct arm_smmu_master *master)
24302402
if (j < i)
24312403
continue;
24322404

2433-
arm_smmu_write_strtab_ent(master, sid, step);
2405+
arm_smmu_write_ste(master, sid, step, target);
24342406
}
24352407
}
24362408

@@ -2537,6 +2509,7 @@ static void arm_smmu_disable_pasid(struct arm_smmu_master *master)
25372509
static void arm_smmu_detach_dev(struct arm_smmu_master *master)
25382510
{
25392511
unsigned long flags;
2512+
struct arm_smmu_ste target;
25402513
struct arm_smmu_domain *smmu_domain = master->domain;
25412514

25422515
if (!smmu_domain)
@@ -2550,7 +2523,11 @@ static void arm_smmu_detach_dev(struct arm_smmu_master *master)
25502523

25512524
master->domain = NULL;
25522525
master->ats_enabled = false;
2553-
arm_smmu_install_ste_for_dev(master);
2526+
if (disable_bypass)
2527+
arm_smmu_make_abort_ste(&target);
2528+
else
2529+
arm_smmu_make_bypass_ste(&target);
2530+
arm_smmu_install_ste_for_dev(master, &target);
25542531
/*
25552532
* Clearing the CD entry isn't strictly required to detach the domain
25562533
* since the table is uninstalled anyway, but it helps avoid confusion
@@ -2565,6 +2542,7 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
25652542
{
25662543
int ret = 0;
25672544
unsigned long flags;
2545+
struct arm_smmu_ste target;
25682546
struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
25692547
struct arm_smmu_device *smmu;
25702548
struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);
@@ -2626,7 +2604,8 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
26262604
list_add(&master->domain_head, &smmu_domain->devices);
26272605
spin_unlock_irqrestore(&smmu_domain->devices_lock, flags);
26282606

2629-
if (smmu_domain->stage == ARM_SMMU_DOMAIN_S1) {
2607+
switch (smmu_domain->stage) {
2608+
case ARM_SMMU_DOMAIN_S1:
26302609
if (!master->cd_table.cdtab) {
26312610
ret = arm_smmu_alloc_cd_tables(master);
26322611
if (ret) {
@@ -2640,9 +2619,17 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
26402619
master->domain = NULL;
26412620
goto out_list_del;
26422621
}
2643-
}
26442622

2645-
arm_smmu_install_ste_for_dev(master);
2623+
arm_smmu_make_cdtable_ste(&target, master);
2624+
break;
2625+
case ARM_SMMU_DOMAIN_S2:
2626+
arm_smmu_make_s2_domain_ste(&target, master, smmu_domain);
2627+
break;
2628+
case ARM_SMMU_DOMAIN_BYPASS:
2629+
arm_smmu_make_bypass_ste(&target);
2630+
break;
2631+
}
2632+
arm_smmu_install_ste_for_dev(master, &target);
26462633

26472634
arm_smmu_enable_ats(master);
26482635
goto out_unlock;

0 commit comments

Comments
 (0)