Skip to content

Commit 25c2325

Browse files
Steven Pricejoergroedel
authored andcommitted
iommu/rockchip: Add missing set_platform_dma_ops callback
Similar to exynos, we need a set_platform_dma_ops() callback for proper operation on ARM 32 bit after recent changes in the IOMMU framework (detach ops removal). But also the use of a NULL domain is confusing. Rework the code to add support for IOMMU_DOMAIN_IDENTITY and a singleton rk_identity_domain which is assigned to domain when using an identity mapping rather than "detaching". This makes the code easier to reason about. Signed-off-by: Steven Price <[email protected]> Acked-by: Heiko Stuebner <[email protected]> Tested-by: Heiko Stuebner <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Joerg Roedel <[email protected]>
1 parent e8d018d commit 25c2325

File tree

1 file changed

+47
-14
lines changed

1 file changed

+47
-14
lines changed

drivers/iommu/rockchip-iommu.c

Lines changed: 47 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ struct rk_iommudata {
124124

125125
static struct device *dma_dev;
126126
static const struct rk_iommu_ops *rk_ops;
127+
static struct iommu_domain rk_identity_domain;
127128

128129
static inline void rk_table_flush(struct rk_iommu_domain *dom, dma_addr_t dma,
129130
unsigned int count)
@@ -646,7 +647,7 @@ static irqreturn_t rk_iommu_irq(int irq, void *dev_id)
646647
* Ignore the return code, though, since we always zap cache
647648
* and clear the page fault anyway.
648649
*/
649-
if (iommu->domain)
650+
if (iommu->domain != &rk_identity_domain)
650651
report_iommu_fault(iommu->domain, iommu->dev, iova,
651652
flags);
652653
else
@@ -980,26 +981,27 @@ static int rk_iommu_enable(struct rk_iommu *iommu)
980981
return ret;
981982
}
982983

983-
static void rk_iommu_detach_device(struct iommu_domain *domain,
984-
struct device *dev)
984+
static int rk_iommu_identity_attach(struct iommu_domain *identity_domain,
985+
struct device *dev)
985986
{
986987
struct rk_iommu *iommu;
987-
struct rk_iommu_domain *rk_domain = to_rk_domain(domain);
988+
struct rk_iommu_domain *rk_domain;
988989
unsigned long flags;
989990
int ret;
990991

991992
/* Allow 'virtual devices' (eg drm) to detach from domain */
992993
iommu = rk_iommu_from_dev(dev);
993994
if (!iommu)
994-
return;
995+
return -ENODEV;
996+
997+
rk_domain = to_rk_domain(iommu->domain);
995998

996999
dev_dbg(dev, "Detaching from iommu domain\n");
9971000

998-
/* iommu already detached */
999-
if (iommu->domain != domain)
1000-
return;
1001+
if (iommu->domain == identity_domain)
1002+
return 0;
10011003

1002-
iommu->domain = NULL;
1004+
iommu->domain = identity_domain;
10031005

10041006
spin_lock_irqsave(&rk_domain->iommus_lock, flags);
10051007
list_del_init(&iommu->node);
@@ -1011,8 +1013,31 @@ static void rk_iommu_detach_device(struct iommu_domain *domain,
10111013
rk_iommu_disable(iommu);
10121014
pm_runtime_put(iommu->dev);
10131015
}
1016+
1017+
return 0;
10141018
}
10151019

1020+
static void rk_iommu_identity_free(struct iommu_domain *domain)
1021+
{
1022+
}
1023+
1024+
static struct iommu_domain_ops rk_identity_ops = {
1025+
.attach_dev = rk_iommu_identity_attach,
1026+
.free = rk_iommu_identity_free,
1027+
};
1028+
1029+
static struct iommu_domain rk_identity_domain = {
1030+
.type = IOMMU_DOMAIN_IDENTITY,
1031+
.ops = &rk_identity_ops,
1032+
};
1033+
1034+
#ifdef CONFIG_ARM
1035+
static void rk_iommu_set_platform_dma(struct device *dev)
1036+
{
1037+
WARN_ON(rk_iommu_identity_attach(&rk_identity_domain, dev));
1038+
}
1039+
#endif
1040+
10161041
static int rk_iommu_attach_device(struct iommu_domain *domain,
10171042
struct device *dev)
10181043
{
@@ -1035,8 +1060,9 @@ static int rk_iommu_attach_device(struct iommu_domain *domain,
10351060
if (iommu->domain == domain)
10361061
return 0;
10371062

1038-
if (iommu->domain)
1039-
rk_iommu_detach_device(iommu->domain, dev);
1063+
ret = rk_iommu_identity_attach(&rk_identity_domain, dev);
1064+
if (ret)
1065+
return ret;
10401066

10411067
iommu->domain = domain;
10421068

@@ -1050,7 +1076,7 @@ static int rk_iommu_attach_device(struct iommu_domain *domain,
10501076

10511077
ret = rk_iommu_enable(iommu);
10521078
if (ret)
1053-
rk_iommu_detach_device(iommu->domain, dev);
1079+
WARN_ON(rk_iommu_identity_attach(&rk_identity_domain, dev));
10541080

10551081
pm_runtime_put(iommu->dev);
10561082

@@ -1061,6 +1087,9 @@ static struct iommu_domain *rk_iommu_domain_alloc(unsigned type)
10611087
{
10621088
struct rk_iommu_domain *rk_domain;
10631089

1090+
if (type == IOMMU_DOMAIN_IDENTITY)
1091+
return &rk_identity_domain;
1092+
10641093
if (type != IOMMU_DOMAIN_UNMANAGED && type != IOMMU_DOMAIN_DMA)
10651094
return NULL;
10661095

@@ -1176,6 +1205,7 @@ static int rk_iommu_of_xlate(struct device *dev,
11761205
iommu_dev = of_find_device_by_node(args->np);
11771206

11781207
data->iommu = platform_get_drvdata(iommu_dev);
1208+
data->iommu->domain = &rk_identity_domain;
11791209
dev_iommu_priv_set(dev, data);
11801210

11811211
platform_device_put(iommu_dev);
@@ -1188,6 +1218,9 @@ static const struct iommu_ops rk_iommu_ops = {
11881218
.probe_device = rk_iommu_probe_device,
11891219
.release_device = rk_iommu_release_device,
11901220
.device_group = rk_iommu_device_group,
1221+
#ifdef CONFIG_ARM
1222+
.set_platform_dma_ops = rk_iommu_set_platform_dma,
1223+
#endif
11911224
.pgsize_bitmap = RK_IOMMU_PGSIZE_BITMAP,
11921225
.of_xlate = rk_iommu_of_xlate,
11931226
.default_domain_ops = &(const struct iommu_domain_ops) {
@@ -1343,7 +1376,7 @@ static int __maybe_unused rk_iommu_suspend(struct device *dev)
13431376
{
13441377
struct rk_iommu *iommu = dev_get_drvdata(dev);
13451378

1346-
if (!iommu->domain)
1379+
if (iommu->domain == &rk_identity_domain)
13471380
return 0;
13481381

13491382
rk_iommu_disable(iommu);
@@ -1354,7 +1387,7 @@ static int __maybe_unused rk_iommu_resume(struct device *dev)
13541387
{
13551388
struct rk_iommu *iommu = dev_get_drvdata(dev);
13561389

1357-
if (!iommu->domain)
1390+
if (iommu->domain == &rk_identity_domain)
13581391
return 0;
13591392

13601393
return rk_iommu_enable(iommu);

0 commit comments

Comments
 (0)