Skip to content

Commit b2a6876

Browse files
YongWu-HFjoergroedel
authored andcommitted
iommu/mediatek: Get regionid from larb/port id
After commit f1ad533 ("of: Fix "dma-ranges" handling for bus controllers"), the dma-ranges is not allowed for dts leaf node. but we still would like to separate to different masters into different iova regions. Thus we have to separate it by the HW larbid and portid. For example, larb1/2 are in region2 and larb3 is in region3. The problem is that some ports inside a larb are in region4 while some ports inside this larb are in region5. Therefore I define a "iova_region_larb_msk" to help record the information for each a port. Take a example for a larb: [1] = ~0: means all ports in this larb are in region1; [2] = BIT(3) | BIT(4): means port3/4 in this larb are region2; [3] = ~(BIT(3) | BIT(4)): means all the other ports except port3/4 in this larb are region3. This method also avoids the users forget/abuse the iova regions. Signed-off-by: Yong Wu <yong.wu@mediatek.com> Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com> Link: https://lore.kernel.org/r/20230411093144.2690-5-yong.wu@mediatek.com Signed-off-by: Joerg Roedel <jroedel@suse.de>
1 parent ae66934 commit b2a6876

1 file changed

Lines changed: 26 additions & 19 deletions

File tree

drivers/iommu/mtk_iommu.c

Lines changed: 26 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
#include <linux/clk.h>
99
#include <linux/component.h>
1010
#include <linux/device.h>
11-
#include <linux/dma-direct.h>
1211
#include <linux/err.h>
1312
#include <linux/interrupt.h>
1413
#include <linux/io.h>
@@ -212,6 +211,15 @@ struct mtk_iommu_plat_data {
212211
struct {
213212
unsigned int iova_region_nr;
214213
const struct mtk_iommu_iova_region *iova_region;
214+
/*
215+
* Indicate the correspondance between larbs, ports and regions.
216+
*
217+
* The index is the same as iova_region and larb port numbers are
218+
* described as bit positions.
219+
* For example, storing BIT(0) at index 2,1 means "larb 1, port0 is in region 2".
220+
* [2] = { [1] = BIT(0) }
221+
*/
222+
const u32 (*iova_region_larb_msk)[MTK_LARB_NR_MAX];
215223
};
216224

217225
/*
@@ -529,30 +537,29 @@ static unsigned int mtk_iommu_get_bank_id(struct device *dev,
529537
static int mtk_iommu_get_iova_region_id(struct device *dev,
530538
const struct mtk_iommu_plat_data *plat_data)
531539
{
532-
const struct mtk_iommu_iova_region *rgn = plat_data->iova_region;
533-
const struct bus_dma_region *dma_rgn = dev->dma_range_map;
534-
int i, candidate = -1;
535-
dma_addr_t dma_end;
540+
struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
541+
unsigned int portidmsk = 0, larbid;
542+
const u32 *rgn_larb_msk;
543+
int i;
536544

537-
if (!dma_rgn || plat_data->iova_region_nr == 1)
545+
if (plat_data->iova_region_nr == 1)
538546
return 0;
539547

540-
dma_end = dma_rgn->dma_start + dma_rgn->size - 1;
541-
for (i = 0; i < plat_data->iova_region_nr; i++, rgn++) {
542-
/* Best fit. */
543-
if (dma_rgn->dma_start == rgn->iova_base &&
544-
dma_end == rgn->iova_base + rgn->size - 1)
548+
larbid = MTK_M4U_TO_LARB(fwspec->ids[0]);
549+
for (i = 0; i < fwspec->num_ids; i++)
550+
portidmsk |= BIT(MTK_M4U_TO_PORT(fwspec->ids[i]));
551+
552+
for (i = 0; i < plat_data->iova_region_nr; i++) {
553+
rgn_larb_msk = plat_data->iova_region_larb_msk[i];
554+
if (!rgn_larb_msk)
555+
continue;
556+
557+
if ((rgn_larb_msk[larbid] & portidmsk) == portidmsk)
545558
return i;
546-
/* ok if it is inside this region. */
547-
if (dma_rgn->dma_start >= rgn->iova_base &&
548-
dma_end < rgn->iova_base + rgn->size)
549-
candidate = i;
550559
}
551560

552-
if (candidate >= 0)
553-
return candidate;
554-
dev_err(dev, "Can NOT find the iommu domain id(%pad 0x%llx).\n",
555-
&dma_rgn->dma_start, dma_rgn->size);
561+
dev_err(dev, "Can NOT find the region for larb(%d-%x).\n",
562+
larbid, portidmsk);
556563
return -EINVAL;
557564
}
558565

0 commit comments

Comments
 (0)