Commit cf69ef46 authored by Chengci.Xu's avatar Chengci.Xu Committed by Joerg Roedel

iommu/mediatek: Fix two IOMMU share pagetable issue

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: 645b87c1 ("iommu/mediatek: Fix 2 HW sharing pgtable issue")
Signed-off-by: default avatarChengci.Xu <chengci.xu@mediatek.com>
Signed-off-by: default avatarYong Wu <yong.wu@mediatek.com>
Reviewed-by: default avatarAngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Reviewed-by: default avatarAlexandre Mergnat <amergnat@baylibre.com>
Link: https://lore.kernel.org/r/20230602090227.7264-3-yong.wu@mediatek.comSigned-off-by: default avatarJoerg Roedel <jroedel@suse.de>
parent d5cda142
...@@ -258,6 +258,8 @@ struct mtk_iommu_data { ...@@ -258,6 +258,8 @@ struct mtk_iommu_data {
struct device *smicomm_dev; struct device *smicomm_dev;
struct mtk_iommu_bank_data *bank; struct mtk_iommu_bank_data *bank;
struct mtk_iommu_domain *share_dom; /* For 2 HWs share pgtable */
struct regmap *pericfg; struct regmap *pericfg;
struct mutex mutex; /* Protect m4u_group/m4u_dom above */ struct mutex mutex; /* Protect m4u_group/m4u_dom above */
...@@ -620,15 +622,14 @@ static int mtk_iommu_domain_finalise(struct mtk_iommu_domain *dom, ...@@ -620,15 +622,14 @@ static int mtk_iommu_domain_finalise(struct mtk_iommu_domain *dom,
struct mtk_iommu_data *data, struct mtk_iommu_data *data,
unsigned int region_id) unsigned int region_id)
{ {
struct mtk_iommu_domain *share_dom = data->share_dom;
const struct mtk_iommu_iova_region *region; const struct mtk_iommu_iova_region *region;
struct mtk_iommu_domain *m4u_dom;
/* Always use share domain in sharing pgtable case */
/* Always use bank0 in sharing pgtable case */ if (MTK_IOMMU_HAS_FLAG(data->plat_data, SHARE_PGTABLE) && share_dom) {
m4u_dom = data->bank[0].m4u_dom; dom->iop = share_dom->iop;
if (m4u_dom) { dom->cfg = share_dom->cfg;
dom->iop = m4u_dom->iop; dom->domain.pgsize_bitmap = share_dom->cfg.pgsize_bitmap;
dom->cfg = m4u_dom->cfg;
dom->domain.pgsize_bitmap = m4u_dom->cfg.pgsize_bitmap;
goto update_iova_region; goto update_iova_region;
} }
...@@ -658,6 +659,9 @@ static int mtk_iommu_domain_finalise(struct mtk_iommu_domain *dom, ...@@ -658,6 +659,9 @@ static int mtk_iommu_domain_finalise(struct mtk_iommu_domain *dom,
/* Update our support page sizes bitmap */ /* Update our support page sizes bitmap */
dom->domain.pgsize_bitmap = dom->cfg.pgsize_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_iova_region:
/* Update the iova region for this domain */ /* Update the iova region for this domain */
region = data->plat_data->iova_region + region_id; region = data->plat_data->iova_region + region_id;
...@@ -708,7 +712,9 @@ static int mtk_iommu_attach_device(struct iommu_domain *domain, ...@@ -708,7 +712,9 @@ static int mtk_iommu_attach_device(struct iommu_domain *domain,
/* Data is in the frstdata in sharing pgtable case. */ /* Data is in the frstdata in sharing pgtable case. */
frstdata = mtk_iommu_get_frst_data(hw_list); frstdata = mtk_iommu_get_frst_data(hw_list);
mutex_lock(&frstdata->mutex);
ret = mtk_iommu_domain_finalise(dom, frstdata, region_id); ret = mtk_iommu_domain_finalise(dom, frstdata, region_id);
mutex_unlock(&frstdata->mutex);
if (ret) { if (ret) {
mutex_unlock(&dom->mutex); mutex_unlock(&dom->mutex);
return ret; return ret;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment