mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-15 16:24:13 +08:00
media: 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> Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl> Signed-off-by: Mauro Carvalho Chehab <mchehab@kernel.org>
This commit is contained in:
parent
7d09aaf831
commit
635319a4a7
@ -562,22 +562,52 @@ static struct iommu_device *mtk_iommu_probe_device(struct device *dev)
|
||||
{
|
||||
struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
|
||||
struct mtk_iommu_data *data;
|
||||
struct device_link *link;
|
||||
struct device *larbdev;
|
||||
unsigned int larbid, larbidx, i;
|
||||
|
||||
if (!fwspec || fwspec->ops != &mtk_iommu_ops)
|
||||
return ERR_PTR(-ENODEV); /* Not a iommu client device */
|
||||
|
||||
data = dev_iommu_priv_get(dev);
|
||||
|
||||
/*
|
||||
* Link the consumer device with the smi-larb device(supplier).
|
||||
* The device that connects with each a larb is a independent HW.
|
||||
* All the ports in each a device should be in the same larbs.
|
||||
*/
|
||||
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);
|
||||
if (!link)
|
||||
dev_err(dev, "Unable to link %s\n", dev_name(larbdev));
|
||||
return &data->iommu;
|
||||
}
|
||||
|
||||
static void mtk_iommu_release_device(struct device *dev)
|
||||
{
|
||||
struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
|
||||
struct mtk_iommu_data *data;
|
||||
struct device *larbdev;
|
||||
unsigned int larbid;
|
||||
|
||||
if (!fwspec || fwspec->ops != &mtk_iommu_ops)
|
||||
return;
|
||||
|
||||
data = dev_iommu_priv_get(dev);
|
||||
larbid = MTK_M4U_TO_LARB(fwspec->ids[0]);
|
||||
larbdev = data->larb_imu[larbid].dev;
|
||||
device_link_remove(dev, larbdev);
|
||||
|
||||
iommu_fwspec_free(dev);
|
||||
}
|
||||
|
||||
|
@ -423,7 +423,9 @@ static struct iommu_device *mtk_iommu_probe_device(struct device *dev)
|
||||
struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
|
||||
struct of_phandle_args iommu_spec;
|
||||
struct mtk_iommu_data *data;
|
||||
int err, idx = 0;
|
||||
int err, idx = 0, larbid, larbidx;
|
||||
struct device_link *link;
|
||||
struct device *larbdev;
|
||||
|
||||
/*
|
||||
* In the deferred case, free the existed fwspec.
|
||||
@ -453,6 +455,23 @@ static struct iommu_device *mtk_iommu_probe_device(struct device *dev)
|
||||
|
||||
data = dev_iommu_priv_get(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);
|
||||
if (!link)
|
||||
dev_err(dev, "Unable to link %s\n", dev_name(larbdev));
|
||||
|
||||
return &data->iommu;
|
||||
}
|
||||
|
||||
@ -473,10 +492,18 @@ static void mtk_iommu_probe_finalize(struct device *dev)
|
||||
static void mtk_iommu_release_device(struct device *dev)
|
||||
{
|
||||
struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
|
||||
struct mtk_iommu_data *data;
|
||||
struct device *larbdev;
|
||||
unsigned int larbid;
|
||||
|
||||
if (!fwspec || fwspec->ops != &mtk_iommu_ops)
|
||||
return;
|
||||
|
||||
data = dev_iommu_priv_get(dev);
|
||||
larbid = mt2701_m4u_to_larb(fwspec->ids[0]);
|
||||
larbdev = data->larb_imu[larbid].dev;
|
||||
device_link_remove(dev, larbdev);
|
||||
|
||||
iommu_fwspec_free(dev);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user