summaryrefslogtreecommitdiffstats
path: root/drivers/iommu
diff options
context:
space:
mode:
authorChengci.Xu <chengci.xu@mediatek.com>2023-06-02 17:02:22 +0800
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2023-09-13 09:42:53 +0200
commitfadc62aa82d29fbd2a2592fb9b1d6686aab7d394 (patch)
tree65b5c83dee9c62cbbcfe7ce144df3f3404b092be /drivers/iommu
parentf81325a709dde58d459aa2705c3eed5e8f2dbc68 (diff)
downloadlinux-stable-fadc62aa82d29fbd2a2592fb9b1d6686aab7d394.tar.gz
linux-stable-fadc62aa82d29fbd2a2592fb9b1d6686aab7d394.tar.bz2
linux-stable-fadc62aa82d29fbd2a2592fb9b1d6686aab7d394.zip
iommu/mediatek: Fix two IOMMU share pagetable issue
[ Upstream commit cf69ef46dbd980a0b1c956d668e066a73e0acd0f ] Prepare for mt8188 to fix a two IOMMU HWs share pagetable issue. We have two MM IOMMU HWs in mt8188, one is VPP-IOMMU, the other is VDO-IOMMU. The 2 MM IOMMU HWs share pagetable don't work in this case: a) VPP-IOMMU probe firstly. b) VDO-IOMMU probe. c) The master for VDO-IOMMU probe (means frstdata is vpp-iommu). d) The master in another domain probe. No matter it is vdo or vpp. Then it still create a new pagetable in step d). The problem is "frstdata->bank[0]->m4u_dom" was not initialized. Then when d) enter, it still create a new one. In this patch, we create a new variable "share_dom" for this share pgtable case, it should be helpful for readable. and put all the share pgtable logic in the mtk_iommu_domain_finalise. In mt8195, the master of VPP-IOMMU probes before than VDO-IOMMU from its dtsi node sequence, we don't see this issue in it. Prepare for mt8188. Fixes: 645b87c190c9 ("iommu/mediatek: Fix 2 HW sharing pgtable issue") Signed-off-by: Chengci.Xu <chengci.xu@mediatek.com> Signed-off-by: Yong Wu <yong.wu@mediatek.com> Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com> Reviewed-by: Alexandre Mergnat <amergnat@baylibre.com> Link: https://lore.kernel.org/r/20230602090227.7264-3-yong.wu@mediatek.com Signed-off-by: Joerg Roedel <jroedel@suse.de> Signed-off-by: Sasha Levin <sashal@kernel.org>
Diffstat (limited to 'drivers/iommu')
-rw-r--r--drivers/iommu/mtk_iommu.c22
1 files changed, 14 insertions, 8 deletions
diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index 5ff8982712e0..9673cd60c84f 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -223,6 +223,8 @@ struct mtk_iommu_data {
struct device *smicomm_dev;
struct mtk_iommu_bank_data *bank;
+ struct mtk_iommu_domain *share_dom; /* For 2 HWs share pgtable */
+
struct regmap *pericfg;
struct mutex mutex; /* Protect m4u_group/m4u_dom above */
@@ -574,15 +576,14 @@ static int mtk_iommu_domain_finalise(struct mtk_iommu_domain *dom,
struct mtk_iommu_data *data,
unsigned int region_id)
{
+ struct mtk_iommu_domain *share_dom = data->share_dom;
const struct mtk_iommu_iova_region *region;
- struct mtk_iommu_domain *m4u_dom;
-
- /* Always use bank0 in sharing pgtable case */
- m4u_dom = data->bank[0].m4u_dom;
- if (m4u_dom) {
- dom->iop = m4u_dom->iop;
- dom->cfg = m4u_dom->cfg;
- dom->domain.pgsize_bitmap = m4u_dom->cfg.pgsize_bitmap;
+
+ /* Always use share domain in sharing pgtable case */
+ if (MTK_IOMMU_HAS_FLAG(data->plat_data, SHARE_PGTABLE) && share_dom) {
+ dom->iop = share_dom->iop;
+ dom->cfg = share_dom->cfg;
+ dom->domain.pgsize_bitmap = share_dom->cfg.pgsize_bitmap;
goto update_iova_region;
}
@@ -612,6 +613,9 @@ static int mtk_iommu_domain_finalise(struct mtk_iommu_domain *dom,
/* Update our support page sizes bitmap */
dom->domain.pgsize_bitmap = dom->cfg.pgsize_bitmap;
+ if (MTK_IOMMU_HAS_FLAG(data->plat_data, SHARE_PGTABLE))
+ data->share_dom = dom;
+
update_iova_region:
/* Update the iova region for this domain */
region = data->plat_data->iova_region + region_id;
@@ -662,7 +666,9 @@ static int mtk_iommu_attach_device(struct iommu_domain *domain,
/* Data is in the frstdata in sharing pgtable case. */
frstdata = mtk_iommu_get_frst_data(hw_list);
+ mutex_lock(&frstdata->mutex);
ret = mtk_iommu_domain_finalise(dom, frstdata, region_id);
+ mutex_unlock(&frstdata->mutex);
if (ret) {
mutex_unlock(&dom->mutex);
return -ENODEV;