xen-devel.lists.xenproject.org archive mirror
 help / color / mirror / Atom feed
From: Wei Chen <Wei.Chen@arm.com>
To: xen-devel@lists.xen.org
Cc: sstabellini@kernel.org, wei.chen@arm.com, steve.capper@arm.com,
	Kaly.Xin@arm.com, julien.grall@arm.com, nd@arm.com
Subject: [PATCH 6/7] xen/arm: SMMU: Support generic IOMMU bindings
Date: Fri, 30 Jun 2017 11:15:10 +0800	[thread overview]
Message-ID: <1498792511-25149-7-git-send-email-Wei.Chen@arm.com> (raw)
In-Reply-To: <1498792511-25149-1-git-send-email-Wei.Chen@arm.com>

The SMMU MasterIDs are placed at the master devices' DT node while
using the generic bindings. In this case, it's very hard for us to
register SMMU masters while probing SMMU as we had done for legacy
bindings. Because we have to go through whole device tree for all
SMMU devices to find their master devices.

It's better to register SMMU master for generic bindings in add_device
callback. This callback will only be called while constructing Dom0.

Signed-off-by: Wei Chen <Wei.Chen@arm.com>
---
 xen/drivers/passthrough/arm/smmu.c | 144 ++++++++++++++++++++++++++++++++++++-
 1 file changed, 143 insertions(+), 1 deletion(-)

diff --git a/xen/drivers/passthrough/arm/smmu.c b/xen/drivers/passthrough/arm/smmu.c
index 895024c..25f2207 100644
--- a/xen/drivers/passthrough/arm/smmu.c
+++ b/xen/drivers/passthrough/arm/smmu.c
@@ -2621,8 +2621,150 @@ static void arm_smmu_destroy_iommu_domain(struct iommu_domain *domain)
 	xfree(domain);
 }
 
+static int arm_smmu_add_generic_master_id(struct arm_smmu_device *smmu,
+				struct device *master_dev, u16 fwid)
+{
+	struct arm_smmu_master *master;
+	struct device_node *master_np = master_dev->of_node;
+
+	master = find_smmu_master(smmu, master_np);
+	if (!master) {
+		dev_notice(smmu->dev,
+			"This smmu master [%s] hasn't been registered, creating now!\n",
+			master_np->full_name);
+		master = devm_kzalloc(smmu->dev, sizeof(*master), GFP_KERNEL);
+		if (!master)
+			return -ENOMEM;
+
+		master->of_node = master_np;
+		master->cfg.num_streamids = 0;
+
+		/*
+		 * Xen: Let Xen know that the device is protected by a SMMU.
+		 * Only do while registering the master.
+		 */
+		dt_device_set_protected(master_np);
+	}
+
+	/*
+	 * If the smmu is using the stream index mode, check whether
+	 * the streamid exceeds the max allowed id,
+	 */
+	if (!(smmu->features & ARM_SMMU_FEAT_STREAM_MATCH) &&
+		(fwid >= smmu->num_mapping_groups)) {
+		dev_err(smmu->dev,
+			"Stream ID for master device %s greater than maximum allowed (%d)\n",
+			master_np->name, smmu->num_mapping_groups);
+		return -ERANGE;
+	}
+
+	if (master->cfg.num_streamids >= MAX_MASTER_STREAMIDS) {
+		dev_err(smmu->dev,
+			"Reached maximum number (%d) of stream IDs for master device %s\n",
+			MAX_MASTER_STREAMIDS, master_np->name);
+		return -ENOSPC;
+	}
+
+	/*
+	 * If this is the first time we add id to this master,
+	 * we have to register this master to rb tree.
+	 */
+	if (!master->cfg.num_streamids) {
+		int ret;
+		ret = insert_smmu_master(smmu, master);
+		if ( ret && ret != -EEXIST ) {
+			dev_err(smmu->dev,
+				"Insert %s to smmu's master rb tree failed\n", master_np->name);
+			return ret;
+		}
+	}
+
+	master->cfg.streamids[master->cfg.num_streamids] = fwid;
+	master->cfg.num_streamids++;
+	dev_dbg(smmu->dev,
+		"Add new streamid [%d] to smmu [%s] for master [%s]!\n",
+		fwid, smmu->dev->of_node->name, master_np->name);
+
+	return 0;
+}
+
+static struct arm_smmu_device *find_smmu(const struct device *dev);
+
+static int arm_smmu_of_xlate(struct device *dev, struct of_phandle_args *args)
+{
+	struct arm_smmu_device *smmu;
+	u32 mask = 0, fwid = 0;
+
+	smmu = find_smmu(dt_to_dev(args->np));
+	if (!smmu) {
+		dev_err(dev, "Could not find smmu device!\n");
+		return -ENODEV;
+	}
+
+	if (args->args_count > 0)
+		fwid |= (u16)args->args[0];
+
+	if (args->args_count > 1)
+		fwid |= (u16)args->args[1] << SMR_MASK_SHIFT;
+	else if (!of_property_read_u32(args->np, "stream-match-mask", &mask))
+		fwid |= (u16)mask << SMR_MASK_SHIFT;
+
+	dev_dbg(dev, "%s fwid:%08x mask:%08x args_count:%d\n",
+			   args->np->full_name, fwid,
+			   mask, args->args_count);
+
+	return arm_smmu_add_generic_master_id(smmu, dev, (u16)fwid);
+}
+
+/*
+ * Parse "iommus" information from generic bindings of platfomr master
+ * device, and then xlate to master IDs and register to SMMU device.
+ */
+static int arm_smmu_platform_iommu_init(struct device *dev)
+{
+	struct of_phandle_args iommu_spec;
+	int idx = 0, ret;
+
+	/*
+	 * We don't currently walk up the tree looking for a parent IOMMU.
+	 * See the `Notes:' section of
+	 * Documentation/devicetree/bindings/iommu/iommu.txt
+	 */
+	while (!of_parse_phandle_with_args(dev->of_node, "iommus",
+				"#iommu-cells",
+				idx, &iommu_spec)) {
+		ret = arm_smmu_of_xlate(dev, &iommu_spec);
+		if (ret) {
+			dev_err(dev,
+				"Do of_xlate for platform device failed, err=%d\n", ret);
+			return ret;
+		}
+
+		idx++;
+	}
+
+	/*
+	 * Return 0 if the device is not protected to follow the behavior
+	 * of PCI add device.
+	 */
+	return 0;
+}
+
 static int arm_smmu_xen_add_device(u8 devfn, struct device*dev)
 {
+	int ret;
+
+	/*
+	 * iommu_add_dt_device() is only called for the hardware domain.
+	 * If the SMMU is using generic bindings, we should parse and
+	 * register Master IDs while this function had been invoked.
+	 */
+	if (using_generic_binding) {
+		ret = arm_smmu_platform_iommu_init(dev);
+		if (ret)
+			return ret;
+	}
+
 	if (dt_device_is_protected(dev->of_node)) {
 		if (!dev->archdata.iommu) {
 			dev->archdata.iommu = xzalloc(struct arm_smmu_xen_device);
@@ -2832,7 +2974,7 @@ static const struct iommu_ops arm_smmu_iommu_ops = {
     .unmap_page = arm_smmu_unmap_page,
 };
 
-static __init const struct arm_smmu_device *find_smmu(const struct device *dev)
+static struct arm_smmu_device *find_smmu(const struct device *dev)
 {
 	struct arm_smmu_device *smmu;
 	bool found = false;
-- 
2.7.4


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

  parent reply	other threads:[~2017-06-30  3:15 UTC|newest]

Thread overview: 33+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-06-30  3:15 [PATCH 0/7] Generic IOMMU bindings support for Xen platform devices Wei Chen
2017-06-30  3:15 ` [PATCH 1/7] xen/arm: SMMU: Implement the add_device callback in SMMU Wei Chen
2017-07-03 21:58   ` Stefano Stabellini
2017-07-04  5:37     ` Wei Chen
2017-07-05 17:57       ` Stefano Stabellini
2017-07-06  2:16         ` Wei Chen
2017-07-04 15:40   ` Julien Grall
2017-07-05  7:06     ` Wei Chen
2017-06-30  3:15 ` [PATCH 2/7] xen/arm: SMMU: Introduce a helper to add DT device to SMMU Wei Chen
2017-07-03 22:02   ` Stefano Stabellini
2017-07-04  5:45     ` Wei Chen
2017-07-05 18:02       ` Stefano Stabellini
2017-07-06  2:20         ` Wei Chen
2017-06-30  3:15 ` [PATCH 3/7] xen/arm: Prepare SMMU resources for protected devices Wei Chen
2017-07-03 22:05   ` Stefano Stabellini
2017-06-30  3:15 ` [PATCH 4/7] xen/arm: SMMU: Detect types of device tree binding Wei Chen
2017-07-03 22:30   ` Stefano Stabellini
2017-07-04  6:20     ` Wei Chen
2017-07-05 18:08       ` Stefano Stabellini
2017-07-06  2:25         ` Wei Chen
2017-06-30  3:15 ` [PATCH 5/7] xen/arm: SMMU: Keep registering legacy master in SMMU probe Wei Chen
2017-07-03 22:32   ` Stefano Stabellini
2017-06-30  3:15 ` Wei Chen [this message]
2017-07-03 22:59   ` [PATCH 6/7] xen/arm: SMMU: Support generic IOMMU bindings Stefano Stabellini
2017-07-04  6:27     ` Wei Chen
2017-07-04  7:26       ` Julien Grall
2017-07-05  7:04         ` Wei Chen
2017-07-05 13:07           ` Julien Grall
2017-07-06  2:11             ` Wei Chen
2017-07-05 18:15           ` Stefano Stabellini
2017-07-06  2:45             ` Wei Chen
2017-06-30  3:15 ` [PATCH 7/7] xen: Fix a typo in error message of iommu_do_dt_domctl Wei Chen
2017-07-03 21:53   ` Stefano Stabellini

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=1498792511-25149-7-git-send-email-Wei.Chen@arm.com \
    --to=wei.chen@arm.com \
    --cc=Kaly.Xin@arm.com \
    --cc=julien.grall@arm.com \
    --cc=nd@arm.com \
    --cc=sstabellini@kernel.org \
    --cc=steve.capper@arm.com \
    --cc=xen-devel@lists.xen.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).