Skip to content

Commit ad10dce

Browse files
jgunthorpewilldeacon
authored andcommitted
iommu/arm-smmu-v3: Make smmu_domain->devices into an allocated list
The next patch will need to store the same master twice (with different SSIDs), so allocate memory for each list element. Tested-by: Nicolin Chen <[email protected]> Tested-by: Shameer Kolothum <[email protected]> Reviewed-by: Michael Shavit <[email protected]> Reviewed-by: Nicolin Chen <[email protected]> Reviewed-by: Jerry Snitselaar <[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 85f2fb6 commit ad10dce

File tree

3 files changed

+47
-10
lines changed

3 files changed

+47
-10
lines changed

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

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,13 @@ static DEFINE_MUTEX(sva_lock);
3838
static void
3939
arm_smmu_update_s1_domain_cd_entry(struct arm_smmu_domain *smmu_domain)
4040
{
41-
struct arm_smmu_master *master;
41+
struct arm_smmu_master_domain *master_domain;
4242
struct arm_smmu_cd target_cd;
4343
unsigned long flags;
4444

4545
spin_lock_irqsave(&smmu_domain->devices_lock, flags);
46-
list_for_each_entry(master, &smmu_domain->devices, domain_head) {
46+
list_for_each_entry(master_domain, &smmu_domain->devices, devices_elm) {
47+
struct arm_smmu_master *master = master_domain->master;
4748
struct arm_smmu_cd *cdptr;
4849

4950
/* S1 domains only support RID attachment right now */
@@ -301,7 +302,7 @@ static void arm_smmu_mm_release(struct mmu_notifier *mn, struct mm_struct *mm)
301302
{
302303
struct arm_smmu_mmu_notifier *smmu_mn = mn_to_smmu(mn);
303304
struct arm_smmu_domain *smmu_domain = smmu_mn->domain;
304-
struct arm_smmu_master *master;
305+
struct arm_smmu_master_domain *master_domain;
305306
unsigned long flags;
306307

307308
mutex_lock(&sva_lock);
@@ -315,7 +316,9 @@ static void arm_smmu_mm_release(struct mmu_notifier *mn, struct mm_struct *mm)
315316
* but disable translation.
316317
*/
317318
spin_lock_irqsave(&smmu_domain->devices_lock, flags);
318-
list_for_each_entry(master, &smmu_domain->devices, domain_head) {
319+
list_for_each_entry(master_domain, &smmu_domain->devices,
320+
devices_elm) {
321+
struct arm_smmu_master *master = master_domain->master;
319322
struct arm_smmu_cd target;
320323
struct arm_smmu_cd *cdptr;
321324

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

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2015,10 +2015,10 @@ static int arm_smmu_atc_inv_master(struct arm_smmu_master *master)
20152015
int arm_smmu_atc_inv_domain(struct arm_smmu_domain *smmu_domain, int ssid,
20162016
unsigned long iova, size_t size)
20172017
{
2018+
struct arm_smmu_master_domain *master_domain;
20182019
int i;
20192020
unsigned long flags;
20202021
struct arm_smmu_cmdq_ent cmd;
2021-
struct arm_smmu_master *master;
20222022
struct arm_smmu_cmdq_batch cmds;
20232023

20242024
if (!(smmu_domain->smmu->features & ARM_SMMU_FEAT_ATS))
@@ -2046,7 +2046,10 @@ int arm_smmu_atc_inv_domain(struct arm_smmu_domain *smmu_domain, int ssid,
20462046
cmds.num = 0;
20472047

20482048
spin_lock_irqsave(&smmu_domain->devices_lock, flags);
2049-
list_for_each_entry(master, &smmu_domain->devices, domain_head) {
2049+
list_for_each_entry(master_domain, &smmu_domain->devices,
2050+
devices_elm) {
2051+
struct arm_smmu_master *master = master_domain->master;
2052+
20502053
if (!master->ats_enabled)
20512054
continue;
20522055

@@ -2534,9 +2537,26 @@ static void arm_smmu_disable_pasid(struct arm_smmu_master *master)
25342537
pci_disable_pasid(pdev);
25352538
}
25362539

2540+
static struct arm_smmu_master_domain *
2541+
arm_smmu_find_master_domain(struct arm_smmu_domain *smmu_domain,
2542+
struct arm_smmu_master *master)
2543+
{
2544+
struct arm_smmu_master_domain *master_domain;
2545+
2546+
lockdep_assert_held(&smmu_domain->devices_lock);
2547+
2548+
list_for_each_entry(master_domain, &smmu_domain->devices,
2549+
devices_elm) {
2550+
if (master_domain->master == master)
2551+
return master_domain;
2552+
}
2553+
return NULL;
2554+
}
2555+
25372556
static void arm_smmu_detach_dev(struct arm_smmu_master *master)
25382557
{
25392558
struct iommu_domain *domain = iommu_get_domain_for_dev(master->dev);
2559+
struct arm_smmu_master_domain *master_domain;
25402560
struct arm_smmu_domain *smmu_domain;
25412561
unsigned long flags;
25422562

@@ -2547,7 +2567,11 @@ static void arm_smmu_detach_dev(struct arm_smmu_master *master)
25472567
arm_smmu_disable_ats(master, smmu_domain);
25482568

25492569
spin_lock_irqsave(&smmu_domain->devices_lock, flags);
2550-
list_del_init(&master->domain_head);
2570+
master_domain = arm_smmu_find_master_domain(smmu_domain, master);
2571+
if (master_domain) {
2572+
list_del(&master_domain->devices_elm);
2573+
kfree(master_domain);
2574+
}
25512575
spin_unlock_irqrestore(&smmu_domain->devices_lock, flags);
25522576

25532577
master->ats_enabled = false;
@@ -2561,6 +2585,7 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
25612585
struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
25622586
struct arm_smmu_device *smmu;
25632587
struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);
2588+
struct arm_smmu_master_domain *master_domain;
25642589
struct arm_smmu_master *master;
25652590
struct arm_smmu_cd *cdptr;
25662591

@@ -2597,6 +2622,11 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
25972622
return -ENOMEM;
25982623
}
25992624

2625+
master_domain = kzalloc(sizeof(*master_domain), GFP_KERNEL);
2626+
if (!master_domain)
2627+
return -ENOMEM;
2628+
master_domain->master = master;
2629+
26002630
/*
26012631
* Prevent arm_smmu_share_asid() from trying to change the ASID
26022632
* of either the old or new domain while we are working on it.
@@ -2610,7 +2640,7 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
26102640
master->ats_enabled = arm_smmu_ats_supported(master);
26112641

26122642
spin_lock_irqsave(&smmu_domain->devices_lock, flags);
2613-
list_add(&master->domain_head, &smmu_domain->devices);
2643+
list_add(&master_domain->devices_elm, &smmu_domain->devices);
26142644
spin_unlock_irqrestore(&smmu_domain->devices_lock, flags);
26152645

26162646
switch (smmu_domain->stage) {
@@ -2925,7 +2955,6 @@ static struct iommu_device *arm_smmu_probe_device(struct device *dev)
29252955
master->dev = dev;
29262956
master->smmu = smmu;
29272957
INIT_LIST_HEAD(&master->bonds);
2928-
INIT_LIST_HEAD(&master->domain_head);
29292958
dev_iommu_priv_set(dev, master);
29302959

29312960
ret = arm_smmu_insert_master(smmu, master);

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -697,7 +697,6 @@ struct arm_smmu_stream {
697697
struct arm_smmu_master {
698698
struct arm_smmu_device *smmu;
699699
struct device *dev;
700-
struct list_head domain_head;
701700
struct arm_smmu_stream *streams;
702701
/* Locked by the iommu core using the group mutex */
703702
struct arm_smmu_ctx_desc_cfg cd_table;
@@ -731,6 +730,7 @@ struct arm_smmu_domain {
731730

732731
struct iommu_domain domain;
733732

733+
/* List of struct arm_smmu_master_domain */
734734
struct list_head devices;
735735
spinlock_t devices_lock;
736736

@@ -767,6 +767,11 @@ void arm_smmu_make_sva_cd(struct arm_smmu_cd *target,
767767
u16 asid);
768768
#endif
769769

770+
struct arm_smmu_master_domain {
771+
struct list_head devices_elm;
772+
struct arm_smmu_master *master;
773+
};
774+
770775
static inline struct arm_smmu_domain *to_smmu_domain(struct iommu_domain *dom)
771776
{
772777
return container_of(dom, struct arm_smmu_domain, domain);

0 commit comments

Comments
 (0)