Skip to content

Commit 1014a2f

Browse files
robclarkjoergroedel
authored andcommitted
iommu/qcom: Use domain rather than dev as tlb cookie
The device may be torn down, but the domain should still be valid. Lets use that as the tlb flush ops cookie. Fixes a problem reported in [1] [1] https://lkml.org/lkml/2020/7/20/104 Reported-by: Naresh Kamboju <[email protected]> Signed-off-by: Rob Clark <[email protected]> Tested-by: Naresh Kamboju <[email protected]> Fixes: 09b5dff ("iommu/qcom: Use accessor functions for iommu private data") Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Joerg Roedel <[email protected]>
1 parent ba47d84 commit 1014a2f

File tree

1 file changed

+17
-20
lines changed

1 file changed

+17
-20
lines changed

drivers/iommu/qcom_iommu.c

Lines changed: 17 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ struct qcom_iommu_domain {
6565
struct mutex init_mutex; /* Protects iommu pointer */
6666
struct iommu_domain domain;
6767
struct qcom_iommu_dev *iommu;
68+
struct iommu_fwspec *fwspec;
6869
};
6970

7071
static struct qcom_iommu_domain *to_qcom_iommu_domain(struct iommu_domain *dom)
@@ -84,9 +85,9 @@ static struct qcom_iommu_dev * to_iommu(struct device *dev)
8485
return dev_iommu_priv_get(dev);
8586
}
8687

87-
static struct qcom_iommu_ctx * to_ctx(struct device *dev, unsigned asid)
88+
static struct qcom_iommu_ctx * to_ctx(struct qcom_iommu_domain *d, unsigned asid)
8889
{
89-
struct qcom_iommu_dev *qcom_iommu = to_iommu(dev);
90+
struct qcom_iommu_dev *qcom_iommu = d->iommu;
9091
if (!qcom_iommu)
9192
return NULL;
9293
return qcom_iommu->ctxs[asid - 1];
@@ -118,14 +119,12 @@ iommu_readq(struct qcom_iommu_ctx *ctx, unsigned reg)
118119

119120
static void qcom_iommu_tlb_sync(void *cookie)
120121
{
121-
struct iommu_fwspec *fwspec;
122-
struct device *dev = cookie;
122+
struct qcom_iommu_domain *qcom_domain = cookie;
123+
struct iommu_fwspec *fwspec = qcom_domain->fwspec;
123124
unsigned i;
124125

125-
fwspec = dev_iommu_fwspec_get(dev);
126-
127126
for (i = 0; i < fwspec->num_ids; i++) {
128-
struct qcom_iommu_ctx *ctx = to_ctx(dev, fwspec->ids[i]);
127+
struct qcom_iommu_ctx *ctx = to_ctx(qcom_domain, fwspec->ids[i]);
129128
unsigned int val, ret;
130129

131130
iommu_writel(ctx, ARM_SMMU_CB_TLBSYNC, 0);
@@ -139,14 +138,12 @@ static void qcom_iommu_tlb_sync(void *cookie)
139138

140139
static void qcom_iommu_tlb_inv_context(void *cookie)
141140
{
142-
struct device *dev = cookie;
143-
struct iommu_fwspec *fwspec;
141+
struct qcom_iommu_domain *qcom_domain = cookie;
142+
struct iommu_fwspec *fwspec = qcom_domain->fwspec;
144143
unsigned i;
145144

146-
fwspec = dev_iommu_fwspec_get(dev);
147-
148145
for (i = 0; i < fwspec->num_ids; i++) {
149-
struct qcom_iommu_ctx *ctx = to_ctx(dev, fwspec->ids[i]);
146+
struct qcom_iommu_ctx *ctx = to_ctx(qcom_domain, fwspec->ids[i]);
150147
iommu_writel(ctx, ARM_SMMU_CB_S1_TLBIASID, ctx->asid);
151148
}
152149

@@ -156,16 +153,14 @@ static void qcom_iommu_tlb_inv_context(void *cookie)
156153
static void qcom_iommu_tlb_inv_range_nosync(unsigned long iova, size_t size,
157154
size_t granule, bool leaf, void *cookie)
158155
{
159-
struct device *dev = cookie;
160-
struct iommu_fwspec *fwspec;
156+
struct qcom_iommu_domain *qcom_domain = cookie;
157+
struct iommu_fwspec *fwspec = qcom_domain->fwspec;
161158
unsigned i, reg;
162159

163160
reg = leaf ? ARM_SMMU_CB_S1_TLBIVAL : ARM_SMMU_CB_S1_TLBIVA;
164161

165-
fwspec = dev_iommu_fwspec_get(dev);
166-
167162
for (i = 0; i < fwspec->num_ids; i++) {
168-
struct qcom_iommu_ctx *ctx = to_ctx(dev, fwspec->ids[i]);
163+
struct qcom_iommu_ctx *ctx = to_ctx(qcom_domain, fwspec->ids[i]);
169164
size_t s = size;
170165

171166
iova = (iova >> 12) << 12;
@@ -256,7 +251,9 @@ static int qcom_iommu_init_domain(struct iommu_domain *domain,
256251
};
257252

258253
qcom_domain->iommu = qcom_iommu;
259-
pgtbl_ops = alloc_io_pgtable_ops(ARM_32_LPAE_S1, &pgtbl_cfg, dev);
254+
qcom_domain->fwspec = fwspec;
255+
256+
pgtbl_ops = alloc_io_pgtable_ops(ARM_32_LPAE_S1, &pgtbl_cfg, qcom_domain);
260257
if (!pgtbl_ops) {
261258
dev_err(qcom_iommu->dev, "failed to allocate pagetable ops\n");
262259
ret = -ENOMEM;
@@ -269,7 +266,7 @@ static int qcom_iommu_init_domain(struct iommu_domain *domain,
269266
domain->geometry.force_aperture = true;
270267

271268
for (i = 0; i < fwspec->num_ids; i++) {
272-
struct qcom_iommu_ctx *ctx = to_ctx(dev, fwspec->ids[i]);
269+
struct qcom_iommu_ctx *ctx = to_ctx(qcom_domain, fwspec->ids[i]);
273270

274271
if (!ctx->secure_init) {
275272
ret = qcom_scm_restore_sec_cfg(qcom_iommu->sec_id, ctx->asid);
@@ -419,7 +416,7 @@ static void qcom_iommu_detach_dev(struct iommu_domain *domain, struct device *de
419416

420417
pm_runtime_get_sync(qcom_iommu->dev);
421418
for (i = 0; i < fwspec->num_ids; i++) {
422-
struct qcom_iommu_ctx *ctx = to_ctx(dev, fwspec->ids[i]);
419+
struct qcom_iommu_ctx *ctx = to_ctx(qcom_domain, fwspec->ids[i]);
423420

424421
/* Disable the context bank: */
425422
iommu_writel(ctx, ARM_SMMU_CB_SCTLR, 0);

0 commit comments

Comments
 (0)