Skip to content

Commit 803cf9e

Browse files
YongWu-HFwilldeacon
authored andcommitted
iommu/mediatek: Add get_domain_id from dev->dma_range_map
Add a new interface _get_domain_id from dev->dma_range_map, The iommu consumer device will use dma-ranges in dtsi node to indicate its dma address region requirement. In this iommu driver, we will get the requirement and decide which iova domain it should locate. In the lastest SoC, there will be several iova-regions(domains), we will compare and calculate which domain is right. If the start/end of device requirement equal some region. it is best fit of course. If it is inside some region, it is also ok. the iova requirement of a device should not be inside two or more regions. Signed-off-by: Yong Wu <[email protected]> Reviewed-by: Tomasz Figa <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Will Deacon <[email protected]>
1 parent 585e58f commit 803cf9e

File tree

1 file changed

+41
-1
lines changed

1 file changed

+41
-1
lines changed

drivers/iommu/mtk_iommu.c

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <linux/clk.h>
99
#include <linux/component.h>
1010
#include <linux/device.h>
11+
#include <linux/dma-direct.h>
1112
#include <linux/dma-iommu.h>
1213
#include <linux/err.h>
1314
#include <linux/interrupt.h>
@@ -314,6 +315,36 @@ static irqreturn_t mtk_iommu_isr(int irq, void *dev_id)
314315
return IRQ_HANDLED;
315316
}
316317

318+
static int mtk_iommu_get_domain_id(struct device *dev,
319+
const struct mtk_iommu_plat_data *plat_data)
320+
{
321+
const struct mtk_iommu_iova_region *rgn = plat_data->iova_region;
322+
const struct bus_dma_region *dma_rgn = dev->dma_range_map;
323+
int i, candidate = -1;
324+
dma_addr_t dma_end;
325+
326+
if (!dma_rgn || plat_data->iova_region_nr == 1)
327+
return 0;
328+
329+
dma_end = dma_rgn->dma_start + dma_rgn->size - 1;
330+
for (i = 0; i < plat_data->iova_region_nr; i++, rgn++) {
331+
/* Best fit. */
332+
if (dma_rgn->dma_start == rgn->iova_base &&
333+
dma_end == rgn->iova_base + rgn->size - 1)
334+
return i;
335+
/* ok if it is inside this region. */
336+
if (dma_rgn->dma_start >= rgn->iova_base &&
337+
dma_end < rgn->iova_base + rgn->size)
338+
candidate = i;
339+
}
340+
341+
if (candidate >= 0)
342+
return candidate;
343+
dev_err(dev, "Can NOT find the iommu domain id(%pad 0x%llx).\n",
344+
&dma_rgn->dma_start, dma_rgn->size);
345+
return -EINVAL;
346+
}
347+
317348
static void mtk_iommu_config(struct mtk_iommu_data *data,
318349
struct device *dev, bool enable)
319350
{
@@ -400,11 +431,15 @@ static int mtk_iommu_attach_device(struct iommu_domain *domain,
400431
struct mtk_iommu_data *data = dev_iommu_priv_get(dev);
401432
struct mtk_iommu_domain *dom = to_mtk_domain(domain);
402433
struct device *m4udev = data->dev;
403-
int ret;
434+
int ret, domid;
404435

405436
if (!data)
406437
return -ENODEV;
407438

439+
domid = mtk_iommu_get_domain_id(dev, data->plat_data);
440+
if (domid < 0)
441+
return domid;
442+
408443
if (!dom->data) {
409444
if (mtk_iommu_domain_finalise(dom, data))
410445
return -ENODEV;
@@ -534,10 +569,15 @@ static void mtk_iommu_release_device(struct device *dev)
534569
static struct iommu_group *mtk_iommu_device_group(struct device *dev)
535570
{
536571
struct mtk_iommu_data *data = mtk_iommu_get_m4u_data();
572+
int domid;
537573

538574
if (!data)
539575
return ERR_PTR(-ENODEV);
540576

577+
domid = mtk_iommu_get_domain_id(dev, data->plat_data);
578+
if (domid < 0)
579+
return ERR_PTR(domid);
580+
541581
/* All the client devices are in the same m4u iommu-group */
542582
if (!data->m4u_group) {
543583
data->m4u_group = iommu_group_alloc();

0 commit comments

Comments
 (0)