Skip to content

Commit a46cdc4

Browse files
committed
Merge branch 'for-joerg/arm-smmu/fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/will/linux into iommu/fixes
2 parents 520eccd + 7655739 commit a46cdc4

File tree

6 files changed

+34
-13
lines changed

6 files changed

+34
-13
lines changed

drivers/iommu/arm-smmu.c

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,8 @@ struct arm_smmu_device {
400400

401401
u32 cavium_id_base; /* Specific to Cavium */
402402

403+
spinlock_t global_sync_lock;
404+
403405
/* IOMMU core code handle */
404406
struct iommu_device iommu;
405407
};
@@ -436,7 +438,7 @@ struct arm_smmu_domain {
436438
struct arm_smmu_cfg cfg;
437439
enum arm_smmu_domain_stage stage;
438440
struct mutex init_mutex; /* Protects smmu pointer */
439-
spinlock_t cb_lock; /* Serialises ATS1* ops */
441+
spinlock_t cb_lock; /* Serialises ATS1* ops and TLB syncs */
440442
struct iommu_domain domain;
441443
};
442444

@@ -602,19 +604,25 @@ static void __arm_smmu_tlb_sync(struct arm_smmu_device *smmu,
602604
static void arm_smmu_tlb_sync_global(struct arm_smmu_device *smmu)
603605
{
604606
void __iomem *base = ARM_SMMU_GR0(smmu);
607+
unsigned long flags;
605608

609+
spin_lock_irqsave(&smmu->global_sync_lock, flags);
606610
__arm_smmu_tlb_sync(smmu, base + ARM_SMMU_GR0_sTLBGSYNC,
607611
base + ARM_SMMU_GR0_sTLBGSTATUS);
612+
spin_unlock_irqrestore(&smmu->global_sync_lock, flags);
608613
}
609614

610615
static void arm_smmu_tlb_sync_context(void *cookie)
611616
{
612617
struct arm_smmu_domain *smmu_domain = cookie;
613618
struct arm_smmu_device *smmu = smmu_domain->smmu;
614619
void __iomem *base = ARM_SMMU_CB(smmu, smmu_domain->cfg.cbndx);
620+
unsigned long flags;
615621

622+
spin_lock_irqsave(&smmu_domain->cb_lock, flags);
616623
__arm_smmu_tlb_sync(smmu, base + ARM_SMMU_CB_TLBSYNC,
617624
base + ARM_SMMU_CB_TLBSTATUS);
625+
spin_unlock_irqrestore(&smmu_domain->cb_lock, flags);
618626
}
619627

620628
static void arm_smmu_tlb_sync_vmid(void *cookie)
@@ -1511,7 +1519,6 @@ static int arm_smmu_add_device(struct device *dev)
15111519

15121520
if (using_legacy_binding) {
15131521
ret = arm_smmu_register_legacy_master(dev, &smmu);
1514-
fwspec = dev->iommu_fwspec;
15151522
if (ret)
15161523
goto out_free;
15171524
} else if (fwspec && fwspec->ops == &arm_smmu_ops) {
@@ -1550,15 +1557,15 @@ static int arm_smmu_add_device(struct device *dev)
15501557

15511558
ret = arm_smmu_master_alloc_smes(dev);
15521559
if (ret)
1553-
goto out_free;
1560+
goto out_cfg_free;
15541561

15551562
iommu_device_link(&smmu->iommu, dev);
15561563

15571564
return 0;
15581565

1566+
out_cfg_free:
1567+
kfree(cfg);
15591568
out_free:
1560-
if (fwspec)
1561-
kfree(fwspec->iommu_priv);
15621569
iommu_fwspec_free(dev);
15631570
return ret;
15641571
}
@@ -1925,6 +1932,7 @@ static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu)
19251932

19261933
smmu->num_mapping_groups = size;
19271934
mutex_init(&smmu->stream_map_mutex);
1935+
spin_lock_init(&smmu->global_sync_lock);
19281936

19291937
if (smmu->version < ARM_SMMU_V2 || !(id & ID0_PTFS_NO_AARCH32)) {
19301938
smmu->features |= ARM_SMMU_FEAT_FMT_AARCH32_L;

drivers/iommu/io-pgtable-arm-v7s.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -479,6 +479,9 @@ static int arm_v7s_map(struct io_pgtable_ops *ops, unsigned long iova,
479479
if (!(prot & (IOMMU_READ | IOMMU_WRITE)))
480480
return 0;
481481

482+
if (WARN_ON(upper_32_bits(iova) || upper_32_bits(paddr)))
483+
return -ERANGE;
484+
482485
ret = __arm_v7s_map(data, iova, paddr, size, prot, 1, data->pgd);
483486
/*
484487
* Synchronise all PTE updates for the new mapping before there's
@@ -659,6 +662,9 @@ static int arm_v7s_unmap(struct io_pgtable_ops *ops, unsigned long iova,
659662
struct arm_v7s_io_pgtable *data = io_pgtable_ops_to_data(ops);
660663
size_t unmapped;
661664

665+
if (WARN_ON(upper_32_bits(iova)))
666+
return 0;
667+
662668
unmapped = __arm_v7s_unmap(data, iova, size, 1, data->pgd);
663669
if (unmapped)
664670
io_pgtable_tlb_sync(&data->iop);

drivers/iommu/io-pgtable-arm.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -452,6 +452,10 @@ static int arm_lpae_map(struct io_pgtable_ops *ops, unsigned long iova,
452452
if (!(iommu_prot & (IOMMU_READ | IOMMU_WRITE)))
453453
return 0;
454454

455+
if (WARN_ON(iova >= (1ULL << data->iop.cfg.ias) ||
456+
paddr >= (1ULL << data->iop.cfg.oas)))
457+
return -ERANGE;
458+
455459
prot = arm_lpae_prot_to_pte(data, iommu_prot);
456460
ret = __arm_lpae_map(data, iova, paddr, size, prot, lvl, ptep);
457461
/*
@@ -610,6 +614,9 @@ static int arm_lpae_unmap(struct io_pgtable_ops *ops, unsigned long iova,
610614
arm_lpae_iopte *ptep = data->pgd;
611615
int lvl = ARM_LPAE_START_LVL(data);
612616

617+
if (WARN_ON(iova >= (1ULL << data->iop.cfg.ias)))
618+
return 0;
619+
613620
unmapped = __arm_lpae_unmap(data, iova, size, lvl, ptep);
614621
if (unmapped)
615622
io_pgtable_tlb_sync(&data->iop);

drivers/iommu/io-pgtable.h

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -158,14 +158,12 @@ void free_io_pgtable_ops(struct io_pgtable_ops *ops);
158158
* @fmt: The page table format.
159159
* @cookie: An opaque token provided by the IOMMU driver and passed back to
160160
* any callback routines.
161-
* @tlb_sync_pending: Private flag for optimising out redundant syncs.
162161
* @cfg: A copy of the page table configuration.
163162
* @ops: The page table operations in use for this set of page tables.
164163
*/
165164
struct io_pgtable {
166165
enum io_pgtable_fmt fmt;
167166
void *cookie;
168-
bool tlb_sync_pending;
169167
struct io_pgtable_cfg cfg;
170168
struct io_pgtable_ops ops;
171169
};
@@ -175,22 +173,17 @@ struct io_pgtable {
175173
static inline void io_pgtable_tlb_flush_all(struct io_pgtable *iop)
176174
{
177175
iop->cfg.tlb->tlb_flush_all(iop->cookie);
178-
iop->tlb_sync_pending = true;
179176
}
180177

181178
static inline void io_pgtable_tlb_add_flush(struct io_pgtable *iop,
182179
unsigned long iova, size_t size, size_t granule, bool leaf)
183180
{
184181
iop->cfg.tlb->tlb_add_flush(iova, size, granule, leaf, iop->cookie);
185-
iop->tlb_sync_pending = true;
186182
}
187183

188184
static inline void io_pgtable_tlb_sync(struct io_pgtable *iop)
189185
{
190-
if (iop->tlb_sync_pending) {
191-
iop->cfg.tlb->tlb_sync(iop->cookie);
192-
iop->tlb_sync_pending = false;
193-
}
186+
iop->cfg.tlb->tlb_sync(iop->cookie);
194187
}
195188

196189
/**

drivers/iommu/mtk_iommu.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ static void mtk_iommu_tlb_add_flush_nosync(unsigned long iova, size_t size,
129129
writel_relaxed(iova, data->base + REG_MMU_INVLD_START_A);
130130
writel_relaxed(iova + size - 1, data->base + REG_MMU_INVLD_END_A);
131131
writel_relaxed(F_MMU_INV_RANGE, data->base + REG_MMU_INVALIDATE);
132+
data->tlb_flush_active = true;
132133
}
133134

134135
static void mtk_iommu_tlb_sync(void *cookie)
@@ -137,6 +138,10 @@ static void mtk_iommu_tlb_sync(void *cookie)
137138
int ret;
138139
u32 tmp;
139140

141+
/* Avoid timing out if there's nothing to wait for */
142+
if (!data->tlb_flush_active)
143+
return;
144+
140145
ret = readl_poll_timeout_atomic(data->base + REG_MMU_CPE_DONE, tmp,
141146
tmp != 0, 10, 100000);
142147
if (ret) {
@@ -146,6 +151,7 @@ static void mtk_iommu_tlb_sync(void *cookie)
146151
}
147152
/* Clear the CPE status */
148153
writel_relaxed(0, data->base + REG_MMU_CPE_DONE);
154+
data->tlb_flush_active = false;
149155
}
150156

151157
static const struct iommu_gather_ops mtk_iommu_gather_ops = {

drivers/iommu/mtk_iommu.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ struct mtk_iommu_data {
4747
struct iommu_group *m4u_group;
4848
struct mtk_smi_iommu smi_imu; /* SMI larb iommu info */
4949
bool enable_4GB;
50+
bool tlb_flush_active;
5051

5152
struct iommu_device iommu;
5253
};

0 commit comments

Comments
 (0)