Thread (52 messages) 52 messages, 7 authors, 2014-10-27
STALE4236d

[RFC PATCH v3 4/7] iommu: provide helper function to configure an IOMMU for an of master

From: laurent.pinchart@ideasonboard.com (Laurent Pinchart)
Date: 2014-10-14 13:12:59
Also in: linux-iommu

Hi Will,

On Monday 22 September 2014 18:13:52 Will Deacon wrote:
On Thu, Sep 18, 2014 at 12:13:13PM +0100, Laurent Pinchart wrote:
quoted
Hi Will,
Hi Laurent,
quoted
Thank you for the patch.
Sorry for the delay in replying, I was at Connect last week and the email
has backed up.
No worries.
quoted
On Friday 12 September 2014 17:34:52 Will Deacon wrote:
quoted
The generic IOMMU device-tree bindings can be used to add arbitrary OF
masters to an IOMMU with a compliant binding.

This patch introduces of_iommu_configure, which does exactly that. A
list of iommu_dma_mapping structures are created for each device, which
represent the set of IOMMU instances through which the device can
master. The list is protected by a kref count and freed when no users
remain. It is expected that DMA-mapping code will take a reference if it
wishes to make use of the IOMMU information.
[...]
quoted
quoted
+struct iommu_dma_mapping *of_iommu_configure(struct device *dev)
+{
+	struct of_phandle_args iommu_spec;
+	struct iommu_dma_mapping *mapping;
+	struct device_node *np;
+	struct iommu_data *iommu = NULL;
+	int idx = 0;
+
+	/*
+	 * 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)) {
+		struct iommu_data *data;
+
+		np = iommu_spec.np;
+		data = of_iommu_get_data(np);
+
+		if (!data || !data->ops || !data->ops->of_xlate)
+			goto err_put_node;
+
+		if (!iommu) {
+			iommu = data;
+		} else if (iommu != data) {
+			/* We don't currently support multi-IOMMU masters */
+			pr_warn("Rejecting device %s with multiple IOMMU 
instances\n",
quoted
quoted
+				dev_name(dev));
+			goto err_put_node;
+		}
+
+		if (!data->ops->of_xlate(dev, &iommu_spec))
+			goto err_put_node;
+
+		of_node_put(np);
+		idx++;
+	}
+
+	if (!iommu)
+		return NULL;
+
+	mapping = kzalloc(sizeof(*mapping), GFP_KERNEL);
+	if (!mapping)
+		return NULL;
+
+	kref_init(&mapping->kref);
+	INIT_LIST_HEAD(&mapping->node);
I might be missing something, but that doesn't seem to match the commit
message. This creates a single iommu_dma_mapping per device, where is the
list supposed to be populated ?
Right. I currently only populate the first node in the list, and the loop
above barfs if we find multiple IOMMUs. I was hoping you'd add support for
that later on, as you mentioned the need for this so I guess you can test it
too?
I can, I was just puzzled by the mismatch between the code and commit message. 
As your patch series doesn't provide a complete end-to-end implementation it's 
not always easy to understand how you envision that implementation to work, 
and thus difficult to implement the required modifications to the IOMMU 
driver.
quoted
quoted
+void of_iommu_deconfigure(struct kref *kref)
+{
+	struct iommu_dma_mapping *mapping, *curr, *next;
+
+	mapping = container_of(kref, struct iommu_dma_mapping, kref);
+	list_for_each_entry_safe(curr, next, &mapping->node, node) {
+		list_del(&curr->node);
+		kfree(curr);
+	}
Don't you need to also kfree(mapping) here ?
Yup, thanks.
quoted
quoted
+}
+
Do you expect other users of of_iommu_deconfigure() than kref_put() ? If
not, how about exposing an of_iommu_put(struct iommu_dma_mapping *) that
would call kref_put() internally, and hiding of_iommu_deconfigure() ?
That's a good idea, I'll do that.
quoted
quoted
 void __init of_iommu_init(void)
 {
 	struct device_node *np;
diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
index 1e944e77d38d..e60e52d82db9 100644
--- a/include/linux/dma-mapping.h
+++ b/include/linux/dma-mapping.h
@@ -62,6 +62,14 @@ struct dma_map_ops {
 	int is_phys;
 };

+struct iommu_data;
+
+struct iommu_dma_mapping {
+	struct iommu_data *iommu;
+	struct list_head node;
+	struct kref kref;
+};
Could you please document the structure with kerneldoc ?
Ok, I'll try!
-- 
Regards,

Laurent Pinchart
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help