mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	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: 645b87c190 ("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>
			
			
This commit is contained in:
		
							parent
							
								
									d5cda142d6
								
							
						
					
					
						commit
						cf69ef46db
					
				
					 1 changed files with 13 additions and 7 deletions
				
			
		| 
						 | 
					@ -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,
 | 
				
			||||||
				     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 bank0 in sharing pgtable case */
 | 
						/* Always use share domain in sharing pgtable case */
 | 
				
			||||||
	m4u_dom = data->bank[0].m4u_dom;
 | 
						if (MTK_IOMMU_HAS_FLAG(data->plat_data, SHARE_PGTABLE) && share_dom) {
 | 
				
			||||||
	if (m4u_dom) {
 | 
							dom->iop = share_dom->iop;
 | 
				
			||||||
		dom->iop = m4u_dom->iop;
 | 
							dom->cfg = share_dom->cfg;
 | 
				
			||||||
		dom->cfg = m4u_dom->cfg;
 | 
							dom->domain.pgsize_bitmap = share_dom->cfg.pgsize_bitmap;
 | 
				
			||||||
		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,
 | 
				
			||||||
	/* 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,
 | 
				
			||||||
		/* 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;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue