blob: 949350de31d3eed5b2c9be9c746bdccd34833135 [file] [log] [blame]
From f10a5c03b4eef5d769a32638f6e5e4d41d023bb3 Mon Sep 17 00:00:00 2001
From: Yong Wu <yong.wu@mediatek.com>
Date: Fri, 12 Nov 2021 18:54:59 +0800
Subject: [PATCH] FROMGIT: iommu/mediatek: Add device_link between the consumer
and the larb devices
MediaTek IOMMU-SMI diagram is like below. all the consumer connect with
smi-larb, then connect with smi-common.
M4U
|
smi-common
|
-------------
| | ...
| |
larb1 larb2
| |
vdec venc
When the consumer works, it should enable the smi-larb's power which
also need enable the smi-common's power firstly.
Thus, First of all, use the device link connect the consumer and the
smi-larbs. then add device link between the smi-larb and smi-common.
This patch adds device_link between the consumer and the larbs.
When device_link_add, I add the flag DL_FLAG_STATELESS to avoid calling
pm_runtime_xx to keep the original status of clocks. It can avoid two
issues:
1) Display HW show fastlogo abnormally reported in [1]. At the beggining,
all the clocks are enabled before entering kernel, but the clocks for
display HW(always in larb0) will be gated after clk_enable and clk_disable
called from device_link_add(->pm_runtime_resume) and rpm_idle. The clock
operation happened before display driver probe. At that time, the display
HW will be abnormal.
2) A deadlock issue reported in [2]. Use DL_FLAG_STATELESS to skip
pm_runtime_xx to avoid the deadlock.
Corresponding, DL_FLAG_AUTOREMOVE_CONSUMER can't be added, then
device_link_removed should be added explicitly.
Meanwhile, Currently we don't have a device connect with 2 larbs at the
same time. Disallow this case, print the error log.
[1] https://lore.kernel.org/linux-mediatek/1564213888.22908.4.camel@mhfsdcap03/
[2] https://lore.kernel.org/patchwork/patch/1086569/
Suggested-by: Tomasz Figa <tfiga@chromium.org>
Signed-off-by: Yong Wu <yong.wu@mediatek.com>
Tested-by: Frank Wunderlich <frank-w@public-files.de> # BPI-R2/MT7623
Acked-by: Joerg Roedel <jroedel@suse.de>
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
(cherry picked from commit e78e915dd3764a0369f1247c269f8fec566589d1
https://git.linuxtv.org/hverkuil/media_tree.git for-v5.18g)
BUG=b:126008328
TEST=emerge-corsola sys-kernel/chromeos-kernel-5_15 succeeds
Signed-off-by: Yong Wu <yong.wu@mediatek.com>
Change-Id: I32fe040f631ff37dbdd0d06ece90d05cbd909138
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/third_party/kernel/+/3455583
Reviewed-by: Hsin-Yi Wang <hsinyi@chromium.org>
Commit-Queue: Hsin-Yi Wang <hsinyi@chromium.org>
Tested-by: Hsin-Yi Wang <hsinyi@chromium.org>
---
drivers/iommu/mtk_iommu.c | 10 +++++++++-
drivers/iommu/mtk_iommu_v1.c | 11 ++++++++++-
2 files changed, 19 insertions(+), 2 deletions(-)
diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index 7d07135b6d2b..5e4ddd22f12d 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -564,7 +564,7 @@ static struct iommu_device *mtk_iommu_probe_device(struct device *dev)
struct mtk_iommu_data *data;
struct device_link *link;
struct device *larbdev;
- unsigned int larbid;
+ unsigned int larbid, larbidx, i;
if (!fwspec || fwspec->ops != &mtk_iommu_ops)
return ERR_PTR(-ENODEV); /* Not a iommu client device */
@@ -577,6 +577,14 @@ static struct iommu_device *mtk_iommu_probe_device(struct device *dev)
* one larb here.
*/
larbid = MTK_M4U_TO_LARB(fwspec->ids[0]);
+ for (i = 1; i < fwspec->num_ids; i++) {
+ larbidx = MTK_M4U_TO_LARB(fwspec->ids[i]);
+ if (larbid != larbidx) {
+ dev_err(dev, "Can only use one larb. Fail@larb%d-%d.\n",
+ larbid, larbidx);
+ return ERR_PTR(-EINVAL);
+ }
+ }
larbdev = data->larb_imu[larbid].dev;
link = device_link_add(dev, larbdev,
DL_FLAG_PM_RUNTIME | DL_FLAG_STATELESS);
diff --git a/drivers/iommu/mtk_iommu_v1.c b/drivers/iommu/mtk_iommu_v1.c
index 5330c4e7c2e7..cf397436a379 100644
--- a/drivers/iommu/mtk_iommu_v1.c
+++ b/drivers/iommu/mtk_iommu_v1.c
@@ -425,7 +425,7 @@ static struct iommu_device *mtk_iommu_probe_device(struct device *dev)
struct mtk_iommu_data *data;
struct device_link *link;
struct device *larbdev;
- int err, larbid, idx = 0;
+ int err, larbid, idx = 0, larbidx;
/*
* In the deferred case, free the existed fwspec.
@@ -457,6 +457,15 @@ static struct iommu_device *mtk_iommu_probe_device(struct device *dev)
/* Link the consumer device with the smi-larb device(supplier) */
larbid = mt2701_m4u_to_larb(fwspec->ids[0]);
+ for (idx = 1; idx < fwspec->num_ids; idx++) {
+ larbidx = mt2701_m4u_to_larb(fwspec->ids[idx]);
+ if (larbid != larbidx) {
+ dev_err(dev, "Can only use one larb. Fail@larb%d-%d.\n",
+ larbid, larbidx);
+ return ERR_PTR(-EINVAL);
+ }
+ }
+
larbdev = data->larb_imu[larbid].dev;
link = device_link_add(dev, larbdev,
DL_FLAG_PM_RUNTIME | DL_FLAG_STATELESS);
--
2.35.1.473.g83b2b277ed-goog