Received: by 2002:a05:6a10:f347:0:0:0:0 with SMTP id d7csp3995438pxu; Wed, 9 Dec 2020 06:01:41 -0800 (PST) X-Google-Smtp-Source: ABdhPJyYWMopgU213wVIKnB/0vQJ+PBtLxS6tkQTImTpp2dz2nEsPZXwhDGnaVQeZP8YYP1N54FN X-Received: by 2002:a50:f604:: with SMTP id c4mr2221595edn.307.1607522501146; Wed, 09 Dec 2020 06:01:41 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1607522501; cv=none; d=google.com; s=arc-20160816; b=ETemHOhCLJZTMUgxt8KvmwHLka3lXgQvKc5b7WpYCGzs01w5T2z/yXSBy6vBvmpfwn PviL9TO3N98YqCpxDGUCHCw7jQElXGwTvv5D2gFh27TjRGPfvQbmVcQStF+XAwbaSuAN VaXEPqqlkWw0ft86XoWZBARcKiZ7M22h5IyjgjBhas4E7S9uaV74XEk8zeD2nSBX3CFV TaxzciYz5LRdNURsYt+CrtzoVnyQNrDYXKt+RGsCMynJb/lae0iUtWqkY6OfpJtk+Jn/ 7uCYo7mo9A0/LyFHHM1X7Ap/OnaYguTrr2xn3bYQFnX4xxqJFs7foZZW3IczlHOjOU+f qOdw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:mime-version:references:in-reply-to:message-id :date:subject:cc:to:from; bh=ugSnP9+2ubVhTVBRINBLQgWlcbWhaZqbE6+oXJNKKRY=; b=RGf2fVLkZfIh53DBob8+432G8pAFj6trSS+QY2hEfy6ROh05ffNtN0l1HGljs3ULg7 B4wR84ULxDUCs8e5FQKaZNawkq9TCbsVDVNPw9aScdjhNQcUG5eEYEqNpdp7tI36z3v0 H5sPhVTHZNLpwInma+0Hzdl3Y2uxhrFqFHoUJ3l3mIE93MvohgIW24vgwEMbon/n7EHo 6SaCkJ4SMrIVNcGgzXMKbiElVwmYhzlLFZHxXRdRI3HFwSl8W5kupIguxnj5EyShBkqc Cn2pTrSrxgoLakVNkSVsImVlHQZQAdqlLKXeDO+1qb8TeOGsKfnzJSDUIAD0sm2mjxd9 xEUQ== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=mediatek.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id i17si842895ejk.401.2020.12.09.06.01.15; Wed, 09 Dec 2020 06:01:41 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=mediatek.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728647AbgLIIHw (ORCPT + 99 others); Wed, 9 Dec 2020 03:07:52 -0500 Received: from mailgw02.mediatek.com ([210.61.82.184]:47650 "EHLO mailgw02.mediatek.com" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S1725953AbgLIIFq (ORCPT ); Wed, 9 Dec 2020 03:05:46 -0500 X-UUID: d79506fcdef44599989a91ea7396edf3-20201209 X-UUID: d79506fcdef44599989a91ea7396edf3-20201209 Received: from mtkcas10.mediatek.inc [(172.21.101.39)] by mailgw02.mediatek.com (envelope-from ) (Cellopoint E-mail Firewall v4.1.14 Build 0819 with TLSv1.2 ECDHE-RSA-AES256-SHA384 256/256) with ESMTP id 1201943558; Wed, 09 Dec 2020 16:05:03 +0800 Received: from MTKCAS06.mediatek.inc (172.21.101.30) by mtkmbs07n1.mediatek.inc (172.21.101.16) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Wed, 9 Dec 2020 16:04:59 +0800 Received: from localhost.localdomain (10.17.3.153) by MTKCAS06.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.0.1497.2 via Frontend Transport; Wed, 9 Dec 2020 16:05:02 +0800 From: Yong Wu To: Joerg Roedel , Matthias Brugger , Rob Herring , Will Deacon , Robin Murphy CC: Krzysztof Kozlowski , Evan Green , Tomasz Figa , , , , , , , , , Nicolas Boichat , , Subject: [PATCH v5 24/27] iommu/mediatek: Add support for multi domain Date: Wed, 9 Dec 2020 16:00:59 +0800 Message-ID: <20201209080102.26626-25-yong.wu@mediatek.com> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20201209080102.26626-1-yong.wu@mediatek.com> References: <20201209080102.26626-1-yong.wu@mediatek.com> MIME-Version: 1.0 Content-Type: text/plain X-MTK: N Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Some HW IP(ex: CCU) require the special iova range. That means the iova got from dma_alloc_attrs for that devices must locate in his special range. In this patch, we allocate a special iova_range for each a special requirement and create each a iommu domain for each a iova_range. meanwhile we still use one pagetable which support 16GB iova. After this patch, If the iova range of a master is over 4G, the master should: a) Declare its special dma_ranges in its dtsi node. For example, If we preassign the iova 4G-8G for vcodec, then the vcodec dtsi node should add this: /* * iova start at 0x1_0000_0000, pa still start at 0x4000_0000 * size is 0x1_0000_0000. */ dma-ranges = <0x1 0x0 0x0 0x40000000 0x1 0x0>; /* 4G ~ 8G */ Note: we don't have a actual bus concept here. the master doesn't have its special parent node, thus this dma-ranges can only be put in the master's node. b) Update the dma_mask: dma_set_mask_and_coherent(dev, DMA_BIT_MASK(33)); Signed-off-by: Yong Wu --- drivers/iommu/mtk_iommu.c | 47 +++++++++++++++++++++++++++++++-------- drivers/iommu/mtk_iommu.h | 3 ++- 2 files changed, 40 insertions(+), 10 deletions(-) diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c index ed771133643d..160690d56bd2 100644 --- a/drivers/iommu/mtk_iommu.c +++ b/drivers/iommu/mtk_iommu.c @@ -355,6 +355,14 @@ static int mtk_iommu_domain_finalise(struct mtk_iommu_domain *dom) { struct mtk_iommu_data *data = mtk_iommu_get_m4u_data(); + /* Use the exist domain as there is only one m4u pgtable here. */ + if (data->m4u_dom) { + dom->iop = data->m4u_dom->iop; + dom->cfg = data->m4u_dom->cfg; + dom->domain.pgsize_bitmap = data->m4u_dom->cfg.pgsize_bitmap; + return 0; + } + dom->cfg = (struct io_pgtable_cfg) { .quirks = IO_PGTABLE_QUIRK_ARM_NS | IO_PGTABLE_QUIRK_NO_PERMS | @@ -380,6 +388,8 @@ static int mtk_iommu_domain_finalise(struct mtk_iommu_domain *dom) static struct iommu_domain *mtk_iommu_domain_alloc(unsigned type) { + struct mtk_iommu_data *data = mtk_iommu_get_m4u_data(); + const struct mtk_iommu_iova_region *region; struct mtk_iommu_domain *dom; if (type != IOMMU_DOMAIN_DMA) @@ -395,8 +405,9 @@ static struct iommu_domain *mtk_iommu_domain_alloc(unsigned type) if (mtk_iommu_domain_finalise(dom)) goto put_dma_cookie; - dom->domain.geometry.aperture_start = 0; - dom->domain.geometry.aperture_end = DMA_BIT_MASK(32); + region = data->plat_data->iova_region + data->cur_domid; + dom->domain.geometry.aperture_start = region->iova_base; + dom->domain.geometry.aperture_end = region->iova_base + region->size - 1; dom->domain.geometry.force_aperture = true; return &dom->domain; @@ -548,19 +559,31 @@ static void mtk_iommu_release_device(struct device *dev) static struct iommu_group *mtk_iommu_device_group(struct device *dev) { struct mtk_iommu_data *data = mtk_iommu_get_m4u_data(); + struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev); + struct iommu_group *group; + int domid; if (!data) return ERR_PTR(-ENODEV); - /* All the client devices are in the same m4u iommu-group */ - if (!data->m4u_group) { - data->m4u_group = iommu_group_alloc(); - if (IS_ERR(data->m4u_group)) + domid = MTK_M4U_TO_DOM(fwspec->ids[0]); + if (domid >= data->plat_data->iova_region_nr) { + dev_err(dev, "iommu domain id(%d/%d) is error.\n", domid, + data->plat_data->iova_region_nr); + return ERR_PTR(-EINVAL); + } + + group = data->m4u_group[domid]; + if (!group) { + group = iommu_group_alloc(); + if (IS_ERR(group)) dev_err(dev, "Failed to allocate M4U IOMMU group\n"); + data->m4u_group[domid] = group; } else { - iommu_group_ref_get(data->m4u_group); + iommu_group_ref_get(group); } - return data->m4u_group; + data->cur_domid = domid; + return group; } static int mtk_iommu_of_xlate(struct device *dev, struct of_phandle_args *args) @@ -589,14 +612,20 @@ static void mtk_iommu_get_resv_regions(struct device *dev, struct list_head *head) { struct mtk_iommu_data *data = dev_iommu_priv_get(dev); - const struct mtk_iommu_iova_region *resv; + const struct mtk_iommu_iova_region *resv, *curdom; struct iommu_resv_region *region; int prot = IOMMU_WRITE | IOMMU_READ; unsigned int i; + curdom = data->plat_data->iova_region + data->cur_domid; for (i = 0; i < data->plat_data->iova_region_nr; i++) { resv = data->plat_data->iova_region + i; + /* Only reserve when the region is in the current domain */ + if (resv->iova_base <= curdom->iova_base || + resv->iova_base + resv->size >= curdom->iova_base + curdom->size) + continue; + region = iommu_alloc_resv_region(resv->iova_base, resv->size, prot, IOMMU_RESV_RESERVED); if (!region) diff --git a/drivers/iommu/mtk_iommu.h b/drivers/iommu/mtk_iommu.h index e867cd3aeeac..b54862307128 100644 --- a/drivers/iommu/mtk_iommu.h +++ b/drivers/iommu/mtk_iommu.h @@ -67,7 +67,7 @@ struct mtk_iommu_data { phys_addr_t protect_base; /* protect memory base */ struct mtk_iommu_suspend_reg reg; struct mtk_iommu_domain *m4u_dom; - struct iommu_group *m4u_group; + struct iommu_group *m4u_group[MTK_M4U_DOM_NR_MAX]; bool enable_4GB; spinlock_t tlb_lock; /* lock for tlb range flush */ @@ -77,6 +77,7 @@ struct mtk_iommu_data { struct dma_iommu_mapping *mapping; /* For mtk_iommu_v1.c */ + unsigned int cur_domid; struct list_head list; struct mtk_smi_larb_iommu larb_imu[MTK_LARB_NR_MAX]; }; -- 2.18.0