linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Joerg Roedel <joro@8bytes.org>
To: Joerg Roedel <joro@8bytes.org>, Will Deacon <will@kernel.org>,
	Robin Murphy <robin.murphy@arm.com>,
	Marek Szyprowski <m.szyprowski@samsung.com>,
	Kukjin Kim <kgene@kernel.org>,
	Krzysztof Kozlowski <krzk@kernel.org>,
	David Woodhouse <dwmw2@infradead.org>,
	Lu Baolu <baolu.lu@linux.intel.com>,
	Andy Gross <agross@kernel.org>,
	Bjorn Andersson <bjorn.andersson@linaro.org>,
	Matthias Brugger <matthias.bgg@gmail.com>,
	Rob Clark <robdclark@gmail.com>, Heiko Stuebner <heiko@sntech.de>,
	Gerald Schaefer <gerald.schaefer@de.ibm.com>,
	Thierry Reding <thierry.reding@gmail.com>,
	Jonathan Hunter <jonathanh@nvidia.com>,
	Jean-Philippe Brucker <jean-philippe@linaro.org>
Cc: iommu@lists.linux-foundation.org, linux-kernel@vger.kernel.org,
	linux-samsung-soc@vger.kernel.org, linux-arm-msm@vger.kernel.org,
	linux-mediatek@lists.infradead.org,
	linux-rockchip@lists.infradead.org, linux-s390@vger.kernel.org,
	linux-tegra@vger.kernel.org,
	virtualization@lists.linux-foundation.org,
	Joerg Roedel <jroedel@suse.de>
Subject: [RFC PATCH 11/34] iommu: Split off default domain allocation from group assignment
Date: Tue,  7 Apr 2020 20:37:19 +0200	[thread overview]
Message-ID: <20200407183742.4344-12-joro@8bytes.org> (raw)
In-Reply-To: <20200407183742.4344-1-joro@8bytes.org>

From: Joerg Roedel <jroedel@suse.de>

When a bus is initialized with iommu-ops, all devices on the bus are
scanned and iommu-groups are allocated for them, and each groups will
also get a default domain allocated.

Until now this happened as soon as the group was created and the first
device added to it. When other devices with different default domain
requirements were added to the group later on, the default domain was
re-allocated, if possible.

This resulted in some back and forth and unnecessary allocations, so
change the flow to defer default domain allocation until all devices
have been added to their respective IOMMU groups.

The default domains are allocated for newly allocated groups after
each device on the bus is handled and was probed by the IOMMU driver.

Signed-off-by: Joerg Roedel <jroedel@suse.de>
---
 drivers/iommu/iommu.c | 152 +++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 149 insertions(+), 3 deletions(-)

diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index 8be047a4808f..44514e3e8ca2 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -199,7 +199,7 @@ static int __iommu_probe_device(struct device *dev, struct list_head *group_list
 	dev->iommu->iommu_dev = iommu_dev;
 
 	group = iommu_group_get_for_dev(dev);
-	if (!IS_ERR(group)) {
+	if (IS_ERR(group)) {
 		ret = PTR_ERR(group);
 		goto out_release;
 	}
@@ -1599,6 +1599,37 @@ static int add_iommu_group(struct device *dev, void *data)
 	return ret;
 }
 
+static int probe_iommu_group(struct device *dev, void *data)
+{
+	const struct iommu_ops *ops = dev->bus->iommu_ops;
+	struct list_head *group_list = data;
+	int ret;
+
+	if (!dev_iommu_get(dev))
+		return -ENOMEM;
+
+	if (!try_module_get(ops->owner)) {
+		ret = -EINVAL;
+		goto err_free_dev_iommu;
+	}
+
+	ret = __iommu_probe_device(dev, group_list);
+	if (ret)
+		goto err_module_put;
+
+	return 0;
+
+err_module_put:
+	module_put(ops->owner);
+err_free_dev_iommu:
+	dev_iommu_free(dev);
+
+	if (ret == -ENODEV)
+		ret = 0;
+
+	return ret;
+}
+
 static int remove_iommu_group(struct device *dev, void *data)
 {
 	iommu_release_device(dev);
@@ -1658,10 +1689,125 @@ static int iommu_bus_notifier(struct notifier_block *nb,
 	return 0;
 }
 
+struct __group_domain_type {
+	struct device *dev;
+	unsigned int type;
+};
+
+static int probe_get_default_domain_type(struct device *dev, void *data)
+{
+	const struct iommu_ops *ops = dev->bus->iommu_ops;
+	struct __group_domain_type *gtype = data;
+	unsigned int type = 0;
+
+	if (ops->def_domain_type)
+		type = ops->def_domain_type(dev);
+
+	if (type) {
+		if (gtype->type && gtype->type != type) {
+			dev_warn(dev, "Device needs domain type %s, but device %s in the same iommu group requires type %s - using default\n",
+				 iommu_domain_type_str(type),
+				 dev_name(gtype->dev),
+				 iommu_domain_type_str(gtype->type));
+			gtype->type = 0;
+		}
+
+		if (!gtype->dev) {
+			gtype->dev  = dev;
+			gtype->type = type;
+		}
+	}
+
+	return 0;
+}
+
+static void probe_alloc_default_domain(struct bus_type *bus,
+				       struct iommu_group *group)
+{
+	struct __group_domain_type gtype;
+
+	memset(&gtype, 0, sizeof(gtype));
+
+	/* Ask for default domain requirements of all devices in the group */
+	__iommu_group_for_each_dev(group, &gtype,
+				   probe_get_default_domain_type);
+
+	if (!gtype.type)
+		gtype.type = iommu_def_domain_type;
+
+	iommu_group_alloc_default_domain(bus, group, gtype.type);
+}
+
+static int iommu_group_do_dma_attach(struct device *dev, void *data)
+{
+	struct iommu_domain *domain = data;
+	const struct iommu_ops *ops;
+	int ret;
+
+	ret = __iommu_attach_device(domain, dev);
+
+	ops = domain->ops;
+
+	if (ret == 0 && ops->probe_finalize)
+		ops->probe_finalize(dev);
+
+	return ret;
+}
+
+static int __iommu_group_dma_attach(struct iommu_group *group)
+{
+	return __iommu_group_for_each_dev(group, group->default_domain,
+					  iommu_group_do_dma_attach);
+}
+
+static int bus_iommu_probe(struct bus_type *bus)
+{
+	const struct iommu_ops *ops = bus->iommu_ops;
+	int ret;
+
+	if (ops->probe_device) {
+		struct iommu_group *group, *next;
+		LIST_HEAD(group_list);
+
+		/*
+		 * This code-path does not allocate the default domain when
+		 * creating the iommu group, so do it after the groups are
+		 * created.
+		 */
+		ret = bus_for_each_dev(bus, NULL, &group_list, probe_iommu_group);
+		if (ret)
+			return ret;
+
+		list_for_each_entry_safe(group, next, &group_list, entry) {
+			/* Remove item from the list */
+			list_del_init(&group->entry);
+
+			mutex_lock(&group->mutex);
+
+			/* Try to allocate default domain */
+			probe_alloc_default_domain(bus, group);
+
+			if (!group->default_domain)
+				continue;
+
+			ret = __iommu_group_dma_attach(group);
+
+			mutex_unlock(&group->mutex);
+
+			if (ret)
+				break;
+		}
+	} else {
+		ret = bus_for_each_dev(bus, NULL, NULL, add_iommu_group);
+	}
+
+	return ret;
+}
+
 static int iommu_bus_init(struct bus_type *bus, const struct iommu_ops *ops)
 {
-	int err;
 	struct notifier_block *nb;
+	int err;
 
 	nb = kzalloc(sizeof(struct notifier_block), GFP_KERNEL);
 	if (!nb)
@@ -1673,7 +1819,7 @@ static int iommu_bus_init(struct bus_type *bus, const struct iommu_ops *ops)
 	if (err)
 		goto out_free;
 
-	err = bus_for_each_dev(bus, NULL, NULL, add_iommu_group);
+	err = bus_iommu_probe(bus);
 	if (err)
 		goto out_err;
 
-- 
2.17.1


  parent reply	other threads:[~2020-04-07 18:39 UTC|newest]

Thread overview: 51+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-04-07 18:37 [RFC PATCH 00/34] iommu: Move iommu_group setup to IOMMU core code Joerg Roedel
2020-04-07 18:37 ` [RFC PATCH 01/34] iommu: Move default domain allocation to separate function Joerg Roedel
2020-04-07 18:37 ` [RFC PATCH 02/34] iommu: Add def_domain_type() callback in iommu_ops Joerg Roedel
2020-04-07 18:37 ` [RFC PATCH 03/34] iommu/amd: Implement iommu_ops->def_domain_type call-back Joerg Roedel
2020-04-07 18:37 ` [RFC PATCH 04/34] iommu/vt-d: Wire up iommu_ops->def_domain_type Joerg Roedel
2020-04-07 18:37 ` [RFC PATCH 05/34] iommu/amd: Remove dma_mask check from check_device() Joerg Roedel
2020-04-07 18:37 ` [RFC PATCH 06/34] iommu/amd: Return -ENODEV in add_device when device is not handled by IOMMU Joerg Roedel
2020-04-07 18:37 ` [RFC PATCH 07/34] iommu: Add probe_device() and remove_device() call-backs Joerg Roedel
2020-04-07 18:37 ` [RFC PATCH 08/34] iommu: Move default domain allocation to iommu_probe_device() Joerg Roedel
2020-04-07 18:37 ` [RFC PATCH 09/34] iommu: Keep a list of allocated groups in __iommu_probe_device() Joerg Roedel
2020-04-07 18:37 ` [RFC PATCH 10/34] iommu: Move new probe_device path to separate function Joerg Roedel
2020-04-07 18:37 ` Joerg Roedel [this message]
2020-04-13 22:10   ` [RFC PATCH 11/34] iommu: Split off default domain allocation from group assignment Derrick, Jonathan
2020-04-14 15:27     ` joro
2020-04-07 18:37 ` [RFC PATCH 12/34] iommu: Move iommu_group_create_direct_mappings() out of iommu_group_add_device() Joerg Roedel
2020-04-07 18:37 ` [RFC PATCH 13/34] iommu: Export bus_iommu_probe() and make is safe for re-probing Joerg Roedel
2020-04-07 18:37 ` [RFC PATCH 14/34] iommu/amd: Remove dev_data->passthrough Joerg Roedel
2020-04-07 18:37 ` [RFC PATCH 15/34] iommu/amd: Convert to probe/release_device() call-backs Joerg Roedel
2020-04-07 18:37 ` [RFC PATCH 16/34] iommu/vt-d: " Joerg Roedel
2020-04-07 18:37 ` [RFC PATCH 17/34] iommu/arm-smmu: Store device instead of group in arm_smmu_s2cr Joerg Roedel
2020-04-08 12:09   ` Robin Murphy
2020-04-08 14:37     ` Joerg Roedel
2020-04-08 15:07       ` Robin Murphy
2020-04-08 19:11         ` Joerg Roedel
2020-04-07 18:37 ` [RFC PATCH 18/34] iommu/arm-smmu: Convert to probe/release_device() call-backs Joerg Roedel
2020-04-07 18:37 ` [RFC PATCH 19/34] iommu/pamu: " Joerg Roedel
2020-04-07 18:37 ` [RFC PATCH 20/34] iommu/s390: " Joerg Roedel
2020-04-07 18:37 ` [RFC PATCH 21/34] iommu/virtio: " Joerg Roedel
2020-04-07 18:37 ` [RFC PATCH 22/34] iommu/msm: " Joerg Roedel
2020-04-07 18:37 ` [RFC PATCH 23/34] iommu/mediatek: " Joerg Roedel
2020-04-07 18:37 ` [RFC PATCH 24/34] iommu/mediatek-v1 " Joerg Roedel
2020-04-07 18:37 ` [RFC PATCH 25/34] iommu/qcom: " Joerg Roedel
2020-04-07 18:37 ` [RFC PATCH 26/34] iommu/rockchip: " Joerg Roedel
2020-04-07 18:37 ` [RFC PATCH 27/34] iommu/tegra: " Joerg Roedel
2020-04-07 18:37 ` [RFC PATCH 28/34] iommu/renesas: " Joerg Roedel
2020-04-07 18:37 ` [RFC PATCH 29/34] iommu/omap: Remove orphan_dev tracking Joerg Roedel
2020-04-07 18:37 ` [RFC PATCH 30/34] iommu/omap: Convert to probe/release_device() call-backs Joerg Roedel
2020-04-07 18:37 ` [RFC PATCH 31/34] iommu/exynos: Create iommu_device in struct exynos_iommu_owner Joerg Roedel
2020-04-08 12:23   ` Marek Szyprowski
2020-04-08 14:23     ` Marek Szyprowski
2020-04-08 15:00       ` Joerg Roedel
2020-04-09 11:46       ` [PATCH] iommu/exynos: Get rid of 'struct exynos_iommu_owner' exynos_iommu_owner Joerg Roedel
2020-04-09 13:58         ` Marek Szyprowski
     [not found]           ` <CGME20200409140939eucas1p190daac74c0d5dda4627314c49c1a5b50@eucas1p1.samsung.com>
2020-04-09 14:09             ` [PATCH] iommu/exynos: Rework intialization Marek Szyprowski
2020-04-09 14:30           ` [PATCH] iommu/exynos: Get rid of 'struct exynos_iommu_owner' exynos_iommu_owner Joerg Roedel
2020-04-14 13:20           ` Joerg Roedel
2020-04-07 18:37 ` [RFC PATCH 32/34] iommu/exynos: Convert to probe/release_device() call-backs Joerg Roedel
2020-04-07 18:37 ` [RFC PATCH 33/34] iommu: Remove add_device()/remove_device() code-paths Joerg Roedel
2020-04-10 10:39   ` Marek Szyprowski
2020-04-14 13:17     ` Joerg Roedel
2020-04-07 18:37 ` [RFC PATCH 34/34] iommu: Unexport iommu_group_get_for_dev() Joerg Roedel

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20200407183742.4344-12-joro@8bytes.org \
    --to=joro@8bytes.org \
    --cc=agross@kernel.org \
    --cc=baolu.lu@linux.intel.com \
    --cc=bjorn.andersson@linaro.org \
    --cc=dwmw2@infradead.org \
    --cc=gerald.schaefer@de.ibm.com \
    --cc=heiko@sntech.de \
    --cc=iommu@lists.linux-foundation.org \
    --cc=jean-philippe@linaro.org \
    --cc=jonathanh@nvidia.com \
    --cc=jroedel@suse.de \
    --cc=kgene@kernel.org \
    --cc=krzk@kernel.org \
    --cc=linux-arm-msm@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mediatek@lists.infradead.org \
    --cc=linux-rockchip@lists.infradead.org \
    --cc=linux-s390@vger.kernel.org \
    --cc=linux-samsung-soc@vger.kernel.org \
    --cc=linux-tegra@vger.kernel.org \
    --cc=m.szyprowski@samsung.com \
    --cc=matthias.bgg@gmail.com \
    --cc=robdclark@gmail.com \
    --cc=robin.murphy@arm.com \
    --cc=thierry.reding@gmail.com \
    --cc=virtualization@lists.linux-foundation.org \
    --cc=will@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).