Re: [PATCH v6 1/8] iommu: provide early initialisation hook for IOMMU drivers
On Wed, Dec 03, 2014 at 07:57:50PM +, Arnd Bergmann wrote: On Tuesday 02 December 2014 14:16:57 Grant Likely wrote: On Mon, Dec 1, 2014 at 11:54 PM, Rob Herring robherri...@gmail.com wrote: On Mon, Dec 1, 2014 at 10:57 AM, Will Deacon will.dea...@arm.com wrote: +static inline void of_iommu_set_ops(struct device_node *np, + const struct iommu_ops *ops) +{ + np-data = (struct iommu_ops *)ops; +} + +static inline struct iommu_ops *of_iommu_get_ops(struct device_node *np) +{ + return np-data; +} This may collide with other users. While use of it is rare, PPC uses it in its PCI code. The OF_DYNAMIC code frees it but never actually sets it. There may be some coming usage with the DT overlay code or that's just a bug. Pantelis or Grant can comment. If not, I think we really should try to get rid of this pointer rather than expand it's usage. I didn't see a user of this. I'm guessing that is coming in a SMMU patch? Good catch. This is not good. The data pointer should be avoided since there are no controls over its use. Until a better solution can be implemented, probably the safest thing to do is add a struct iommu_ops pointer to struct device_node. However, assuming that only a small portion of nodes will actually have iommu_ops set, I'd rather see a separate registry that matches device_nodes to iommu_ops. Fair enough. Will, can you take a copy of drivers/dma/of-dma.c and adapt it as needed? It should be exactly what we need to start out and can be extended and generalized later. Sure, I'll add this to my list of stuff to do for 3.20. Will ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH v6 1/8] iommu: provide early initialisation hook for IOMMU drivers
On Thursday 04 December 2014 09:49:53 Will Deacon wrote: On Wed, Dec 03, 2014 at 07:57:50PM +, Arnd Bergmann wrote: On Tuesday 02 December 2014 14:16:57 Grant Likely wrote: On Mon, Dec 1, 2014 at 11:54 PM, Rob Herring robherri...@gmail.com wrote: On Mon, Dec 1, 2014 at 10:57 AM, Will Deacon will.dea...@arm.com wrote: +static inline void of_iommu_set_ops(struct device_node *np, + const struct iommu_ops *ops) +{ + np-data = (struct iommu_ops *)ops; +} + +static inline struct iommu_ops *of_iommu_get_ops(struct device_node *np) +{ + return np-data; +} This may collide with other users. While use of it is rare, PPC uses it in its PCI code. The OF_DYNAMIC code frees it but never actually sets it. There may be some coming usage with the DT overlay code or that's just a bug. Pantelis or Grant can comment. If not, I think we really should try to get rid of this pointer rather than expand it's usage. I didn't see a user of this. I'm guessing that is coming in a SMMU patch? Good catch. This is not good. The data pointer should be avoided since there are no controls over its use. Until a better solution can be implemented, probably the safest thing to do is add a struct iommu_ops pointer to struct device_node. However, assuming that only a small portion of nodes will actually have iommu_ops set, I'd rather see a separate registry that matches device_nodes to iommu_ops. Fair enough. Will, can you take a copy of drivers/dma/of-dma.c and adapt it as needed? It should be exactly what we need to start out and can be extended and generalized later. Sure, I'll add this to my list of stuff to do for 3.20. Does that mean the we don't get any of the patches for 3.19 despite the Acks? Arnd ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH v6 1/8] iommu: provide early initialisation hook for IOMMU drivers
On Thu, Dec 04, 2014 at 10:10:17AM +, Arnd Bergmann wrote: On Thursday 04 December 2014 09:49:53 Will Deacon wrote: On Wed, Dec 03, 2014 at 07:57:50PM +, Arnd Bergmann wrote: On Tuesday 02 December 2014 14:16:57 Grant Likely wrote: On Mon, Dec 1, 2014 at 11:54 PM, Rob Herring robherri...@gmail.com wrote: On Mon, Dec 1, 2014 at 10:57 AM, Will Deacon will.dea...@arm.com wrote: +static inline void of_iommu_set_ops(struct device_node *np, + const struct iommu_ops *ops) +{ + np-data = (struct iommu_ops *)ops; +} + +static inline struct iommu_ops *of_iommu_get_ops(struct device_node *np) +{ + return np-data; +} This may collide with other users. While use of it is rare, PPC uses it in its PCI code. The OF_DYNAMIC code frees it but never actually sets it. There may be some coming usage with the DT overlay code or that's just a bug. Pantelis or Grant can comment. If not, I think we really should try to get rid of this pointer rather than expand it's usage. I didn't see a user of this. I'm guessing that is coming in a SMMU patch? Good catch. This is not good. The data pointer should be avoided since there are no controls over its use. Until a better solution can be implemented, probably the safest thing to do is add a struct iommu_ops pointer to struct device_node. However, assuming that only a small portion of nodes will actually have iommu_ops set, I'd rather see a separate registry that matches device_nodes to iommu_ops. Fair enough. Will, can you take a copy of drivers/dma/of-dma.c and adapt it as needed? It should be exactly what we need to start out and can be extended and generalized later. Sure, I'll add this to my list of stuff to do for 3.20. Does that mean the we don't get any of the patches for 3.19 despite the Acks? Hmm, I don't know how useful they are without the get/set ops and I don't think I can get those ready for 3.19 given where we currently are. Grant's suggestion of adding an iommu_ops pointer to device_node would work as a temporary hack, but anything more advanced is going to need proper review. Will ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [RFC 0/4] Separate the IOVA library from the intel-iommu driver
On Fri, 2014-11-21 at 13:11 +0200, Sakari Ailus wrote: Hi, This set separates the IOVA library from the intel-iommu driver, and makes it usable for other implementations (such as DMA mapping) as well. While I don't have a DMA mapping implementation to share at the moment, the patches might be useful for the others in the meantime and I wouldn't mind having them in upstream either. Acked-By: David Woodhouse david.woodho...@intel.com for all 4, with the caveat that I don't actually want to see various IOMMU drivers *using* the IOVA code directly. Where possible, we really want to be *losing* the separate DMA API implementation, which would do nothing but call this library and then use the underlying IOMMU API functions with the IOVAs that result. Let the whole of that wrapper be generic, rather than just abstracting out the IOVA allocator for everyone to use in their own wrapper. -- dwmw2 smime.p7s Description: S/MIME cryptographic signature ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH v6 1/8] iommu: provide early initialisation hook for IOMMU drivers
On Thursday 04 December 2014 10:21:27 Will Deacon wrote: On Thu, Dec 04, 2014 at 10:10:17AM +, Arnd Bergmann wrote: On Thursday 04 December 2014 09:49:53 Will Deacon wrote: On Wed, Dec 03, 2014 at 07:57:50PM +, Arnd Bergmann wrote: On Tuesday 02 December 2014 14:16:57 Grant Likely wrote: On Mon, Dec 1, 2014 at 11:54 PM, Rob Herring robherri...@gmail.com wrote: On Mon, Dec 1, 2014 at 10:57 AM, Will Deacon will.dea...@arm.com wrote: +static inline void of_iommu_set_ops(struct device_node *np, + const struct iommu_ops *ops) +{ + np-data = (struct iommu_ops *)ops; +} + +static inline struct iommu_ops *of_iommu_get_ops(struct device_node *np) +{ + return np-data; +} This may collide with other users. While use of it is rare, PPC uses it in its PCI code. The OF_DYNAMIC code frees it but never actually sets it. There may be some coming usage with the DT overlay code or that's just a bug. Pantelis or Grant can comment. If not, I think we really should try to get rid of this pointer rather than expand it's usage. I didn't see a user of this. I'm guessing that is coming in a SMMU patch? Good catch. This is not good. The data pointer should be avoided since there are no controls over its use. Until a better solution can be implemented, probably the safest thing to do is add a struct iommu_ops pointer to struct device_node. However, assuming that only a small portion of nodes will actually have iommu_ops set, I'd rather see a separate registry that matches device_nodes to iommu_ops. Fair enough. Will, can you take a copy of drivers/dma/of-dma.c and adapt it as needed? It should be exactly what we need to start out and can be extended and generalized later. Sure, I'll add this to my list of stuff to do for 3.20. Does that mean the we don't get any of the patches for 3.19 despite the Acks? Hmm, I don't know how useful they are without the get/set ops and I don't think I can get those ready for 3.19 given where we currently are. Grant's suggestion of adding an iommu_ops pointer to device_node would work as a temporary hack, but anything more advanced is going to need proper review. Right. I guess it doesn't hurt much if we put the new pointer inside #ifdef CONFIG_OF_IOMMU, then at least there is no significant size increase in most DT based platforms. Arnd ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH v6 1/8] iommu: provide early initialisation hook for IOMMU drivers
On Thu, Dec 4, 2014 at 11:19 AM, Arnd Bergmann a...@arndb.de wrote: On Thursday 04 December 2014 10:21:27 Will Deacon wrote: On Thu, Dec 04, 2014 at 10:10:17AM +, Arnd Bergmann wrote: On Thursday 04 December 2014 09:49:53 Will Deacon wrote: On Wed, Dec 03, 2014 at 07:57:50PM +, Arnd Bergmann wrote: On Tuesday 02 December 2014 14:16:57 Grant Likely wrote: On Mon, Dec 1, 2014 at 11:54 PM, Rob Herring robherri...@gmail.com wrote: On Mon, Dec 1, 2014 at 10:57 AM, Will Deacon will.dea...@arm.com wrote: +static inline void of_iommu_set_ops(struct device_node *np, + const struct iommu_ops *ops) +{ + np-data = (struct iommu_ops *)ops; +} + +static inline struct iommu_ops *of_iommu_get_ops(struct device_node *np) +{ + return np-data; +} This may collide with other users. While use of it is rare, PPC uses it in its PCI code. The OF_DYNAMIC code frees it but never actually sets it. There may be some coming usage with the DT overlay code or that's just a bug. Pantelis or Grant can comment. If not, I think we really should try to get rid of this pointer rather than expand it's usage. I didn't see a user of this. I'm guessing that is coming in a SMMU patch? Good catch. This is not good. The data pointer should be avoided since there are no controls over its use. Until a better solution can be implemented, probably the safest thing to do is add a struct iommu_ops pointer to struct device_node. However, assuming that only a small portion of nodes will actually have iommu_ops set, I'd rather see a separate registry that matches device_nodes to iommu_ops. Fair enough. Will, can you take a copy of drivers/dma/of-dma.c and adapt it as needed? It should be exactly what we need to start out and can be extended and generalized later. Sure, I'll add this to my list of stuff to do for 3.20. Does that mean the we don't get any of the patches for 3.19 despite the Acks? Hmm, I don't know how useful they are without the get/set ops and I don't think I can get those ready for 3.19 given where we currently are. Grant's suggestion of adding an iommu_ops pointer to device_node would work as a temporary hack, but anything more advanced is going to need proper review. Right. I guess it doesn't hurt much if we put the new pointer inside #ifdef CONFIG_OF_IOMMU, then at least there is no significant size increase in most DT based platforms. Yes, I can live with that hack on the proviso that it will be removed by v3.20 Oh, and please put an ugly /* */ comment block in the #ifdef CONFIG_OF_IOMMU section that makes it really clear that it is an ugly hack and will be removed in the next release. I don't want anyone getting ideas that adding pointers to struct device_node is a good idea. g. ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH v6 1/8] iommu: provide early initialisation hook for IOMMU drivers
On Thu, Dec 04, 2014 at 11:25:35AM +, Grant Likely wrote: On Thu, Dec 4, 2014 at 11:19 AM, Arnd Bergmann a...@arndb.de wrote: On Thursday 04 December 2014 10:21:27 Will Deacon wrote: Sure, I'll add this to my list of stuff to do for 3.20. Does that mean the we don't get any of the patches for 3.19 despite the Acks? Hmm, I don't know how useful they are without the get/set ops and I don't think I can get those ready for 3.19 given where we currently are. Grant's suggestion of adding an iommu_ops pointer to device_node would work as a temporary hack, but anything more advanced is going to need proper review. Right. I guess it doesn't hurt much if we put the new pointer inside #ifdef CONFIG_OF_IOMMU, then at least there is no significant size increase in most DT based platforms. Yes, I can live with that hack on the proviso that it will be removed by v3.20 Oh, and please put an ugly /* */ comment block in the #ifdef CONFIG_OF_IOMMU section that makes it really clear that it is an ugly hack and will be removed in the next release. I don't want anyone getting ideas that adding pointers to struct device_node is a good idea. Something like the mess below? Will ---8 diff --git a/include/linux/of.h b/include/linux/of.h index 29f0adc5f3e4..6f85c02bc1a6 100644 --- a/include/linux/of.h +++ b/include/linux/of.h @@ -43,6 +43,9 @@ struct property { #if defined(CONFIG_SPARC) struct of_irq_controller; #endif +#ifdef CONFIG_OF_IOMMU +struct iommu_ops; +#endif struct device_node { const char *name; @@ -65,6 +68,19 @@ struct device_node { unsigned int unique_id; struct of_irq_controller *irq_trans; #endif +#ifdef CONFIG_OF_IOMMU +/* + * HACK! HACK! HACK! + * + * This is a temporary hack to associate a device_node for an + * IOMMU with its set of iommu_ops so that we can probe its upstream DMA + * masters on the platform bus by parsing the iommus property directly. + * + * This is going away in 3.20. Please use the of_iommu_{get,set}_ops + * functions to get hold of this data. + */ + struct iommu_ops *__iommu_ops_use_accessors; +#endif }; #define MAX_PHANDLE_ARGS 16 diff --git a/include/linux/of_iommu.h b/include/linux/of_iommu.h index d03abbb11c34..392ec5f212db 100644 --- a/include/linux/of_iommu.h +++ b/include/linux/of_iommu.h @@ -14,6 +14,17 @@ extern int of_get_dma_window(struct device_node *dn, const char *prefix, extern void of_iommu_init(void); extern struct iommu_ops *of_iommu_configure(struct device *dev); +static inline void of_iommu_set_ops(struct device_node *np, + const struct iommu_ops *ops) +{ + np-__iommu_ops_use_accessors = ops; +} + +static inline struct iommu_ops *of_iommu_get_ops(struct device_node *np) +{ + return np-__iommu_ops_use_accessors; +} + #else static inline int of_get_dma_window(struct device_node *dn, const char *prefix, @@ -29,19 +40,15 @@ static inline struct iommu_ops *of_iommu_configure(struct device *dev) return NULL; } -#endif /* CONFIG_OF_IOMMU */ - static inline void of_iommu_set_ops(struct device_node *np, - const struct iommu_ops *ops) -{ - np-data = (struct iommu_ops *)ops; -} - + const struct iommu_ops *ops) { } static inline struct iommu_ops *of_iommu_get_ops(struct device_node *np) { - return np-data; + return NULL; } +#endif /* CONFIG_OF_IOMMU */ + extern struct of_device_id __iommu_of_table; typedef int (*of_iommu_init_fn)(struct device_node *); ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH v6 1/8] iommu: provide early initialisation hook for IOMMU drivers
Hi Arnd, On 03/12/14 19:57, Arnd Bergmann wrote: [...] Good catch. This is not good. The data pointer should be avoided since there are no controls over its use. Until a better solution can be implemented, probably the safest thing to do is add a struct iommu_ops pointer to struct device_node. However, assuming that only a small portion of nodes will actually have iommu_ops set, I'd rather see a separate registry that matches device_nodes to iommu_ops. Fair enough. Will, can you take a copy of drivers/dma/of-dma.c and adapt it as needed? It should be exactly what we need to start out and can be extended and generalized later. I'm quite keen to see this series go in, since I'm depending on it to make arm64 IOMMU DMA ops just work. Will and I came to the conclusion the other day that we pretty much need to build up some kind of bus abstraction based on the probe data in order to be able to assign IOMMU groups correctly, which can also subsume this particular problem in the long run. Since I've made a start on that already, I've hacked the following short-term fix out of it. Tested on my Juno - admittedly with only two SMMUs and one master (EHCI) being probed, but it didn't blow up or regress anything. Regards, Robin. ---8--- From 1f3d2612682c239e53f2c20e2ac5d19ef3f5387c Mon Sep 17 00:00:00 2001 Message-Id: 1f3d2612682c239e53f2c20e2ac5d19ef3f5387c.1417695078.git.robin.mur...@arm.com From: Robin Murphy robin.mur...@arm.com Date: Thu, 4 Dec 2014 11:53:13 + Subject: [PATCH] iommu: store DT-probed IOMMU data privately Since the data pointer in the DT node is public and may be overwritten by conflicting code, move the DT-probed IOMMU ops to a private list where they will be safe. Signed-off-by: Robin Murphy robin.mur...@arm.com --- drivers/iommu/of_iommu.c | 38 ++ include/linux/of_iommu.h | 12 ++-- 2 files changed, 40 insertions(+), 10 deletions(-) diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c index 73236d3..5cd451c 100644 --- a/drivers/iommu/of_iommu.c +++ b/drivers/iommu/of_iommu.c @@ -94,6 +94,44 @@ int of_get_dma_window(struct device_node *dn, const char *prefix, int index, } EXPORT_SYMBOL_GPL(of_get_dma_window); +struct of_iommu_node { + struct hlist_node list; + struct device_node *np; + const struct iommu_ops *ops; +}; +static HLIST_HEAD(of_iommu_list); +static DEFINE_SPINLOCK(of_iommu_lock); + +void of_iommu_set_ops(struct device_node *np, const struct iommu_ops *ops) +{ + struct of_iommu_node *iommu = kmalloc(sizeof(*iommu), GFP_KERNEL); + + if (!iommu) + return; + + INIT_HLIST_NODE(iommu-list); + iommu-np = np; + iommu-ops = ops; + spin_lock(of_iommu_lock); + hlist_add_head(iommu-list, of_iommu_list); + spin_unlock(of_iommu_lock); +} + +struct iommu_ops *of_iommu_get_ops(struct device_node *np) +{ + struct of_iommu_node *node; + const struct iommu_ops *ops = NULL; + + spin_lock(of_iommu_lock); + hlist_for_each_entry(node, of_iommu_list, list) + if (node-np == np) { + ops = node-ops; + break; + } + spin_unlock(of_iommu_lock); + return (struct iommu_ops *)ops; +} + struct iommu_ops *of_iommu_configure(struct device *dev) { struct of_phandle_args iommu_spec; diff --git a/include/linux/of_iommu.h b/include/linux/of_iommu.h index d03abbb..e27c53a 100644 --- a/include/linux/of_iommu.h +++ b/include/linux/of_iommu.h @@ -31,16 +31,8 @@ static inline struct iommu_ops *of_iommu_configure(struct device *dev) #endif /* CONFIG_OF_IOMMU */ -static inline void of_iommu_set_ops(struct device_node *np, - const struct iommu_ops *ops) -{ - np-data = (struct iommu_ops *)ops; -} - -static inline struct iommu_ops *of_iommu_get_ops(struct device_node *np) -{ - return np-data; -} +void of_iommu_set_ops(struct device_node *np, const struct iommu_ops *ops); +struct iommu_ops *of_iommu_get_ops(struct device_node *np); extern struct of_device_id __iommu_of_table; -- 1.9.1 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH v6 1/8] iommu: provide early initialisation hook for IOMMU drivers
On Thu, Dec 4, 2014 at 12:26 PM, Robin Murphy robin.mur...@arm.com wrote: Hi Arnd, On 03/12/14 19:57, Arnd Bergmann wrote: [...] Good catch. This is not good. The data pointer should be avoided since there are no controls over its use. Until a better solution can be implemented, probably the safest thing to do is add a struct iommu_ops pointer to struct device_node. However, assuming that only a small portion of nodes will actually have iommu_ops set, I'd rather see a separate registry that matches device_nodes to iommu_ops. Fair enough. Will, can you take a copy of drivers/dma/of-dma.c and adapt it as needed? It should be exactly what we need to start out and can be extended and generalized later. I'm quite keen to see this series go in, since I'm depending on it to make arm64 IOMMU DMA ops just work. Will and I came to the conclusion the other day that we pretty much need to build up some kind of bus abstraction based on the probe data in order to be able to assign IOMMU groups correctly, which can also subsume this particular problem in the long run. Since I've made a start on that already, I've hacked the following short-term fix out of it. Tested on my Juno - admittedly with only two SMMUs and one master (EHCI) being probed, but it didn't blow up or regress anything. Regards, Robin. ---8--- From 1f3d2612682c239e53f2c20e2ac5d19ef3f5387c Mon Sep 17 00:00:00 2001 Message-Id: 1f3d2612682c239e53f2c20e2ac5d19ef3f5387c.1417695078.git.robin.mur...@arm.com From: Robin Murphy robin.mur...@arm.com Date: Thu, 4 Dec 2014 11:53:13 + Subject: [PATCH] iommu: store DT-probed IOMMU data privately Since the data pointer in the DT node is public and may be overwritten by conflicting code, move the DT-probed IOMMU ops to a private list where they will be safe. Signed-off-by: Robin Murphy robin.mur...@arm.com Looks reasonable to me. Comments below... --- drivers/iommu/of_iommu.c | 38 ++ include/linux/of_iommu.h | 12 ++-- 2 files changed, 40 insertions(+), 10 deletions(-) diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c index 73236d3..5cd451c 100644 --- a/drivers/iommu/of_iommu.c +++ b/drivers/iommu/of_iommu.c @@ -94,6 +94,44 @@ int of_get_dma_window(struct device_node *dn, const char *prefix, int index, } EXPORT_SYMBOL_GPL(of_get_dma_window); +struct of_iommu_node { + struct hlist_node list; + struct device_node *np; + const struct iommu_ops *ops; +}; +static HLIST_HEAD(of_iommu_list); Just use a list_head. hlist_head merely saves one pointer in this case. +static DEFINE_SPINLOCK(of_iommu_lock); + +void of_iommu_set_ops(struct device_node *np, const struct iommu_ops *ops) +{ + struct of_iommu_node *iommu = kmalloc(sizeof(*iommu), GFP_KERNEL); kzalloc() + + if (!iommu) + return; Shouldn't there be a WARN() here on failure? I don't think failing silently is desired. + + INIT_HLIST_NODE(iommu-list); + iommu-np = np; + iommu-ops = ops; + spin_lock(of_iommu_lock); + hlist_add_head(iommu-list, of_iommu_list); + spin_unlock(of_iommu_lock); +} + +struct iommu_ops *of_iommu_get_ops(struct device_node *np) +{ + struct of_iommu_node *node; + const struct iommu_ops *ops = NULL; + + spin_lock(of_iommu_lock); + hlist_for_each_entry(node, of_iommu_list, list) + if (node-np == np) { + ops = node-ops; + break; + } + spin_unlock(of_iommu_lock); + return (struct iommu_ops *)ops; The cast looks fishy. If you need to use a cast, then the data types are probably wrong. If you drop the const from *ops here and in the structure then it should probably work fine. Due to the way it is being used, there isn't any advantage to using const (unless you changes of_iommu_get_ops() to return a const pointer, then const would make sense). +} + struct iommu_ops *of_iommu_configure(struct device *dev) { struct of_phandle_args iommu_spec; diff --git a/include/linux/of_iommu.h b/include/linux/of_iommu.h index d03abbb..e27c53a 100644 --- a/include/linux/of_iommu.h +++ b/include/linux/of_iommu.h @@ -31,16 +31,8 @@ static inline struct iommu_ops *of_iommu_configure(struct device *dev) #endif /* CONFIG_OF_IOMMU */ -static inline void of_iommu_set_ops(struct device_node *np, - const struct iommu_ops *ops) -{ - np-data = (struct iommu_ops *)ops; -} - -static inline struct iommu_ops *of_iommu_get_ops(struct device_node *np) -{ - return np-data; -} +void of_iommu_set_ops(struct device_node *np, const struct iommu_ops *ops); +struct iommu_ops *of_iommu_get_ops(struct device_node *np); extern struct of_device_id __iommu_of_table; -- 1.9.1 ___ iommu mailing list
Re: [PATCH v6 1/8] iommu: provide early initialisation hook for IOMMU drivers
On Thu, Dec 4, 2014 at 11:52 AM, Will Deacon will.dea...@arm.com wrote: On Thu, Dec 04, 2014 at 11:25:35AM +, Grant Likely wrote: On Thu, Dec 4, 2014 at 11:19 AM, Arnd Bergmann a...@arndb.de wrote: On Thursday 04 December 2014 10:21:27 Will Deacon wrote: Sure, I'll add this to my list of stuff to do for 3.20. Does that mean the we don't get any of the patches for 3.19 despite the Acks? Hmm, I don't know how useful they are without the get/set ops and I don't think I can get those ready for 3.19 given where we currently are. Grant's suggestion of adding an iommu_ops pointer to device_node would work as a temporary hack, but anything more advanced is going to need proper review. Right. I guess it doesn't hurt much if we put the new pointer inside #ifdef CONFIG_OF_IOMMU, then at least there is no significant size increase in most DT based platforms. Yes, I can live with that hack on the proviso that it will be removed by v3.20 Oh, and please put an ugly /* */ comment block in the #ifdef CONFIG_OF_IOMMU section that makes it really clear that it is an ugly hack and will be removed in the next release. I don't want anyone getting ideas that adding pointers to struct device_node is a good idea. Something like the mess below? Yes... Although it looks like Robin's patch does what is needed without the hack. g. Will ---8 diff --git a/include/linux/of.h b/include/linux/of.h index 29f0adc5f3e4..6f85c02bc1a6 100644 --- a/include/linux/of.h +++ b/include/linux/of.h @@ -43,6 +43,9 @@ struct property { #if defined(CONFIG_SPARC) struct of_irq_controller; #endif +#ifdef CONFIG_OF_IOMMU +struct iommu_ops; +#endif struct device_node { const char *name; @@ -65,6 +68,19 @@ struct device_node { unsigned int unique_id; struct of_irq_controller *irq_trans; #endif +#ifdef CONFIG_OF_IOMMU +/* + * HACK! HACK! HACK! + * + * This is a temporary hack to associate a device_node for an + * IOMMU with its set of iommu_ops so that we can probe its upstream DMA + * masters on the platform bus by parsing the iommus property directly. + * + * This is going away in 3.20. Please use the of_iommu_{get,set}_ops + * functions to get hold of this data. + */ + struct iommu_ops *__iommu_ops_use_accessors; +#endif }; #define MAX_PHANDLE_ARGS 16 diff --git a/include/linux/of_iommu.h b/include/linux/of_iommu.h index d03abbb11c34..392ec5f212db 100644 --- a/include/linux/of_iommu.h +++ b/include/linux/of_iommu.h @@ -14,6 +14,17 @@ extern int of_get_dma_window(struct device_node *dn, const char *prefix, extern void of_iommu_init(void); extern struct iommu_ops *of_iommu_configure(struct device *dev); +static inline void of_iommu_set_ops(struct device_node *np, + const struct iommu_ops *ops) +{ + np-__iommu_ops_use_accessors = ops; +} + +static inline struct iommu_ops *of_iommu_get_ops(struct device_node *np) +{ + return np-__iommu_ops_use_accessors; +} + #else static inline int of_get_dma_window(struct device_node *dn, const char *prefix, @@ -29,19 +40,15 @@ static inline struct iommu_ops *of_iommu_configure(struct device *dev) return NULL; } -#endif /* CONFIG_OF_IOMMU */ - static inline void of_iommu_set_ops(struct device_node *np, - const struct iommu_ops *ops) -{ - np-data = (struct iommu_ops *)ops; -} - + const struct iommu_ops *ops) { } static inline struct iommu_ops *of_iommu_get_ops(struct device_node *np) { - return np-data; + return NULL; } +#endif /* CONFIG_OF_IOMMU */ + extern struct of_device_id __iommu_of_table; typedef int (*of_iommu_init_fn)(struct device_node *); ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH v6 1/8] iommu: provide early initialisation hook for IOMMU drivers
On Thursday 04 December 2014 12:26:58 Robin Murphy wrote: +struct of_iommu_node { + struct hlist_node list; + struct device_node *np; + const struct iommu_ops *ops; +}; +static HLIST_HEAD(of_iommu_list); +static DEFINE_SPINLOCK(of_iommu_lock); Looks good to me. For 3.20, I would hope to get consensus on renaming this structure to 'struct iommmu' and adding additional members into it as needed, but let's do that another day. Please address Grant's feedback and send a new version. Arnd ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH v6 1/8] iommu: provide early initialisation hook for IOMMU drivers
Hi Grant, thanks for the advice - silly micro-optimisations removed, and I'll make a note to do so from my in-development code, too ;) I didn't much like the casting either, so rather than push it elsewhere or out to the caller I've just changed the prototype to obviate it completely. Since we're also expecting to churn this again to use something more suitable than iommu_ops as the private data, I think keeping things simple wins over const-correctness for now. Thanks, Robin ---8--- From b2e8c91ac49bef4008661e4628cd6b7249d84af5 Mon Sep 17 00:00:00 2001 Message-Id: b2e8c91ac49bef4008661e4628cd6b7249d84af5.1417698001.git.robin.mur...@arm.com From: Robin Murphy robin.mur...@arm.com Date: Thu, 4 Dec 2014 11:53:13 + Subject: [PATCH v2] iommu: store DT-probed IOMMU data privately Since the data pointer in the DT node is public and may be overwritten by conflicting code, move the DT-probed IOMMU ops to a private list where they will be safe. Signed-off-by: Robin Murphy robin.mur...@arm.com --- drivers/iommu/of_iommu.c | 40 include/linux/of_iommu.h | 12 ++-- 2 files changed, 42 insertions(+), 10 deletions(-) diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c index 73236d3..c7078f6 100644 --- a/drivers/iommu/of_iommu.c +++ b/drivers/iommu/of_iommu.c @@ -94,6 +94,46 @@ int of_get_dma_window(struct device_node *dn, const char *prefix, int index, } EXPORT_SYMBOL_GPL(of_get_dma_window); +struct of_iommu_node { + struct list_head list; + struct device_node *np; + struct iommu_ops *ops; +}; +static LIST_HEAD(of_iommu_list); +static DEFINE_SPINLOCK(of_iommu_lock); + +void of_iommu_set_ops(struct device_node *np, struct iommu_ops *ops) +{ + struct of_iommu_node *iommu = kzalloc(sizeof(*iommu), GFP_KERNEL); + + if (!iommu) { + __WARN(); + return; + } + + INIT_LIST_HEAD(iommu-list); + iommu-np = np; + iommu-ops = ops; + spin_lock(of_iommu_lock); + list_add_tail(iommu-list, of_iommu_list); + spin_unlock(of_iommu_lock); +} + +struct iommu_ops *of_iommu_get_ops(struct device_node *np) +{ + struct of_iommu_node *node; + struct iommu_ops *ops = NULL; + + spin_lock(of_iommu_lock); + list_for_each_entry(node, of_iommu_list, list) + if (node-np == np) { + ops = node-ops; + break; + } + spin_unlock(of_iommu_lock); + return ops; +} + struct iommu_ops *of_iommu_configure(struct device *dev) { struct of_phandle_args iommu_spec; diff --git a/include/linux/of_iommu.h b/include/linux/of_iommu.h index d03abbb..16c7554 100644 --- a/include/linux/of_iommu.h +++ b/include/linux/of_iommu.h @@ -31,16 +31,8 @@ static inline struct iommu_ops *of_iommu_configure(struct device *dev) #endif /* CONFIG_OF_IOMMU */ -static inline void of_iommu_set_ops(struct device_node *np, - const struct iommu_ops *ops) -{ - np-data = (struct iommu_ops *)ops; -} - -static inline struct iommu_ops *of_iommu_get_ops(struct device_node *np) -{ - return np-data; -} +void of_iommu_set_ops(struct device_node *np, struct iommu_ops *ops); +struct iommu_ops *of_iommu_get_ops(struct device_node *np); extern struct of_device_id __iommu_of_table; -- 1.9.1 On 04/12/14 12:42, Grant Likely wrote: On Thu, Dec 4, 2014 at 12:26 PM, Robin Murphy robin.mur...@arm.com wrote: Hi Arnd, On 03/12/14 19:57, Arnd Bergmann wrote: [...] Good catch. This is not good. The data pointer should be avoided since there are no controls over its use. Until a better solution can be implemented, probably the safest thing to do is add a struct iommu_ops pointer to struct device_node. However, assuming that only a small portion of nodes will actually have iommu_ops set, I'd rather see a separate registry that matches device_nodes to iommu_ops. Fair enough. Will, can you take a copy of drivers/dma/of-dma.c and adapt it as needed? It should be exactly what we need to start out and can be extended and generalized later. I'm quite keen to see this series go in, since I'm depending on it to make arm64 IOMMU DMA ops just work. Will and I came to the conclusion the other day that we pretty much need to build up some kind of bus abstraction based on the probe data in order to be able to assign IOMMU groups correctly, which can also subsume this particular problem in the long run. Since I've made a start on that already, I've hacked the following short-term fix out of it. Tested on my Juno - admittedly with only two SMMUs and one master (EHCI) being probed, but it didn't blow up or regress anything. Regards, Robin. ---8--- From 1f3d2612682c239e53f2c20e2ac5d19ef3f5387c Mon Sep 17 00:00:00 2001 Message-Id: 1f3d2612682c239e53f2c20e2ac5d19ef3f5387c.1417695078.git.robin.mur...@arm.com From: Robin Murphy robin.mur...@arm.com Date: Thu, 4 Dec 2014
Re: [PATCH v6 1/8] iommu: provide early initialisation hook for IOMMU drivers
On Thu, Dec 4, 2014 at 1:43 PM, Robin Murphy robin.mur...@arm.com wrote: Hi Grant, thanks for the advice - silly micro-optimisations removed, and I'll make a note to do so from my in-development code, too ;) I didn't much like the casting either, so rather than push it elsewhere or out to the caller I've just changed the prototype to obviate it completely. Since we're also expecting to churn this again to use something more suitable than iommu_ops as the private data, I think keeping things simple wins over const-correctness for now. Thanks, Robin ---8--- From b2e8c91ac49bef4008661e4628cd6b7249d84af5 Mon Sep 17 00:00:00 2001 Message-Id: b2e8c91ac49bef4008661e4628cd6b7249d84af5.1417698001.git.robin.mur...@arm.com From: Robin Murphy robin.mur...@arm.com Date: Thu, 4 Dec 2014 11:53:13 + Subject: [PATCH v2] iommu: store DT-probed IOMMU data privately Since the data pointer in the DT node is public and may be overwritten by conflicting code, move the DT-probed IOMMU ops to a private list where they will be safe. Signed-off-by: Robin Murphy robin.mur...@arm.com Acked-by: Grant Likely grant.lik...@linaro.org --- drivers/iommu/of_iommu.c | 40 include/linux/of_iommu.h | 12 ++-- 2 files changed, 42 insertions(+), 10 deletions(-) diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c index 73236d3..c7078f6 100644 --- a/drivers/iommu/of_iommu.c +++ b/drivers/iommu/of_iommu.c @@ -94,6 +94,46 @@ int of_get_dma_window(struct device_node *dn, const char *prefix, int index, } EXPORT_SYMBOL_GPL(of_get_dma_window); +struct of_iommu_node { + struct list_head list; + struct device_node *np; + struct iommu_ops *ops; +}; +static LIST_HEAD(of_iommu_list); +static DEFINE_SPINLOCK(of_iommu_lock); + +void of_iommu_set_ops(struct device_node *np, struct iommu_ops *ops) +{ + struct of_iommu_node *iommu = kzalloc(sizeof(*iommu), GFP_KERNEL); + + if (!iommu) { + __WARN(); + return; + } + + INIT_LIST_HEAD(iommu-list); + iommu-np = np; + iommu-ops = ops; + spin_lock(of_iommu_lock); + list_add_tail(iommu-list, of_iommu_list); + spin_unlock(of_iommu_lock); +} + +struct iommu_ops *of_iommu_get_ops(struct device_node *np) +{ + struct of_iommu_node *node; + struct iommu_ops *ops = NULL; + + spin_lock(of_iommu_lock); + list_for_each_entry(node, of_iommu_list, list) + if (node-np == np) { + ops = node-ops; + break; + } + spin_unlock(of_iommu_lock); + return ops; +} + struct iommu_ops *of_iommu_configure(struct device *dev) { struct of_phandle_args iommu_spec; diff --git a/include/linux/of_iommu.h b/include/linux/of_iommu.h index d03abbb..16c7554 100644 --- a/include/linux/of_iommu.h +++ b/include/linux/of_iommu.h @@ -31,16 +31,8 @@ static inline struct iommu_ops *of_iommu_configure(struct device *dev) #endif /* CONFIG_OF_IOMMU */ -static inline void of_iommu_set_ops(struct device_node *np, - const struct iommu_ops *ops) -{ - np-data = (struct iommu_ops *)ops; -} - -static inline struct iommu_ops *of_iommu_get_ops(struct device_node *np) -{ - return np-data; -} +void of_iommu_set_ops(struct device_node *np, struct iommu_ops *ops); +struct iommu_ops *of_iommu_get_ops(struct device_node *np); extern struct of_device_id __iommu_of_table; -- 1.9.1 On 04/12/14 12:42, Grant Likely wrote: On Thu, Dec 4, 2014 at 12:26 PM, Robin Murphy robin.mur...@arm.com wrote: Hi Arnd, On 03/12/14 19:57, Arnd Bergmann wrote: [...] Good catch. This is not good. The data pointer should be avoided since there are no controls over its use. Until a better solution can be implemented, probably the safest thing to do is add a struct iommu_ops pointer to struct device_node. However, assuming that only a small portion of nodes will actually have iommu_ops set, I'd rather see a separate registry that matches device_nodes to iommu_ops. Fair enough. Will, can you take a copy of drivers/dma/of-dma.c and adapt it as needed? It should be exactly what we need to start out and can be extended and generalized later. I'm quite keen to see this series go in, since I'm depending on it to make arm64 IOMMU DMA ops just work. Will and I came to the conclusion the other day that we pretty much need to build up some kind of bus abstraction based on the probe data in order to be able to assign IOMMU groups correctly, which can also subsume this particular problem in the long run. Since I've made a start on that already, I've hacked the following short-term fix out of it. Tested on my Juno - admittedly with only two SMMUs and one master (EHCI) being probed, but it didn't blow up or regress anything. Regards, Robin.
Re: [v2 17/25] KVM: kvm-vfio: User API for VT-d Posted-Interrupts
Hi Feng, On 12/03/2014 08:39 AM, Feng Wu wrote: This patch adds and documents a new attribute KVM_DEV_VFIO_DEVICE_POSTING_IRQ in KVM_DEV_VFIO_DEVICE group. This new attribute is used for VT-d Posted-Interrupts. When guest OS changes the interrupt configuration for an assigned device, such as, MSI/MSIx data/address fields, QEMU will use this IRQ attribute to tell KVM to update the related IRTE according the VT-d Posted-Interrrupts Specification, such as, the guest vector should be updated in the related IRTE. Signed-off-by: Feng Wu feng...@intel.com --- Documentation/virtual/kvm/devices/vfio.txt |9 + include/uapi/linux/kvm.h | 10 ++ 2 files changed, 19 insertions(+), 0 deletions(-) diff --git a/Documentation/virtual/kvm/devices/vfio.txt b/Documentation/virtual/kvm/devices/vfio.txt index f7aff29..41e12b7 100644 --- a/Documentation/virtual/kvm/devices/vfio.txt +++ b/Documentation/virtual/kvm/devices/vfio.txt @@ -42,3 +42,12 @@ activated before VFIO_DEVICE_SET_IRQS has been called to trigger the IRQ or associate an eventfd to it. Unforwarding can only be called while the signaling has been disabled with VFIO_DEVICE_SET_IRQS. If this condition is not satisfied, the command returns an -EBUSY. + + KVM_DEV_VFIO_DEVICE_POSTING_IRQ: Use posted interrtups mechanism to post typo + the IRQ to guests. +For this attribute, kvm_device_attr.addr points to a kvm_vfio_dev_irq struct. + +When guest OS changes the interrupt configuration for an assigned device, +such as, MSI/MSIx data/address fields, QEMU will use this IRQ attribute +to tell KVM to update the related IRTE according the VT-d Posted-Interrrupts +Specification, such as, the guest vector should be updated in the related IRTE. For my curiosity are there any restrictions about the instant at which the change can be done? I do not get here how you deactivate the posting? diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h index a269a42..7d98650 100644 --- a/include/uapi/linux/kvm.h +++ b/include/uapi/linux/kvm.h @@ -949,6 +949,7 @@ struct kvm_device_attr { #define KVM_DEV_VFIO_DEVICE 2 #define KVM_DEV_VFIO_DEVICE_FORWARD_IRQ1 #define KVM_DEV_VFIO_DEVICE_UNFORWARD_IRQ 2 +#define KVM_DEV_VFIO_DEVICE_POSTING_IRQ3 Maybe we should align our naming verb vs verbing here? Best Regards Eric enum kvm_device_type { KVM_DEV_TYPE_FSL_MPIC_20= 1, @@ -973,6 +974,15 @@ struct kvm_arch_forwarded_irq { __u32 gsi; /* gsi, ie. virtual IRQ number */ }; +struct kvm_vfio_dev_irq { + __u32 argsz; + __u32 fd; /* file descriptor of the VFIO device */ + __u32 index; /* VFIO device IRQ index */ + __u32 start; + __u32 count; + __u32 gsi[]; /* gsi, ie. virtual IRQ number */ +}; + /* * ioctls for VM fds */ ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [v2 18/25] KVM: kvm-vfio: implement the VFIO skeleton for VT-d Posted-Interrupts
Hi Feng, On 12/03/2014 08:39 AM, Feng Wu wrote: This patch adds the kvm-vfio interface for VT-d Posted-Interrrupts. When guests updates MSI/MSI-x information for an assigned-device, update QEMU will use KVM_DEV_VFIO_DEVICE_POSTING_IRQ attribute to setup IRTE for VT-d PI. This patch implement this IRQ attribute. s/implement/implements Signed-off-by: Feng Wu feng...@intel.com --- include/linux/kvm_host.h | 19 virt/kvm/vfio.c | 103 ++ 2 files changed, 122 insertions(+), 0 deletions(-) diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h index 5cd4420..8d06678 100644 --- a/include/linux/kvm_host.h +++ b/include/linux/kvm_host.h @@ -1134,6 +1134,25 @@ static inline int kvm_arch_vfio_set_forward(struct kvm_fwd_irq *fwd_irq, } #endif +#ifdef __KVM_HAVE_ARCH_KVM_VFIO_POSTING +/* + * kvm_arch_vfio_update_pi_irte - set IRTE for Posted-Interrupts + * + * @kvm: kvm + * @host_irq: host irq of the interrupt + * @guest_irq: gsi of the interrupt + * returns 0 on success, 0 on failure + */ +int kvm_arch_vfio_update_pi_irte(struct kvm *kvm, unsigned int host_irq, + uint32_t guest_irq); +#else +static int kvm_arch_vfio_update_pi_irte(struct kvm *kvm, unsigned int host_irq, + uint32_t guest_irq) +{ + return 0; +} +#endif + #ifdef CONFIG_HAVE_KVM_CPU_RELAX_INTERCEPT static inline void kvm_vcpu_set_in_spin_loop(struct kvm_vcpu *vcpu, bool val) diff --git a/virt/kvm/vfio.c b/virt/kvm/vfio.c index 6bc7001..5e5515f 100644 --- a/virt/kvm/vfio.c +++ b/virt/kvm/vfio.c @@ -446,6 +446,99 @@ out: return ret; } +static int kvm_vfio_pci_get_irq_count(struct pci_dev *pdev, int irq_type) +{ + if (irq_type == VFIO_PCI_INTX_IRQ_INDEX) { + u8 pin; + + pci_read_config_byte(pdev, PCI_INTERRUPT_PIN, pin); + if (pin) + return 1; + } else if (irq_type == VFIO_PCI_MSI_IRQ_INDEX) + return pci_msi_vec_count(pdev); + else if (irq_type == VFIO_PCI_MSIX_IRQ_INDEX) + return pci_msix_vec_count(pdev); + + return 0; +} for platform case I was asked to move the retrieval of absolute irq number to the architecture specific part. I don't know if it should apply to PCI stuff as well? This explains why I need to pass the VFIO device (or struct device handle) to the arch specific part. Actually we do the same job, we provide a phys/virt IRQ mapping to KVM, right? So to me our architecture specific API should look quite similar? + +static int kvm_vfio_set_pi(struct kvm_device *kdev, int32_t __user *argp) +{ + struct kvm_vfio_dev_irq pi_info; + uint32_t *gsi; + unsigned long minsz; + struct vfio_device *vdev; + struct msi_desc *entry; + struct device *dev; + struct pci_dev *pdev; + int i, max, ret; + + minsz = offsetofend(struct kvm_vfio_dev_irq, count); + + if (copy_from_user(pi_info, (void __user *)argp, minsz)) + return -EFAULT; + + if (pi_info.argsz minsz || pi_info.index = VFIO_PCI_NUM_IRQS) PCI specific check, same remark as above but I will let Alex further comment on this and possibly invalidate this commeny ;-) + return -EINVAL; + + vdev = kvm_vfio_get_vfio_device(pi_info.fd); + if (IS_ERR(vdev)) + return PTR_ERR(vdev); + + dev = kvm_vfio_external_base_device(vdev); + if (!dev || !dev_is_pci(dev)) { + ret = -EFAULT; + goto put_vfio_device; + } + + pdev = to_pci_dev(dev); + + max = kvm_vfio_pci_get_irq_count(pdev, pi_info.index); + if (max = 0) { + ret = -EFAULT; + goto put_vfio_device; + } + + if (pi_info.argsz - minsz pi_info.count * sizeof(int) || shouldn' we use the actual datatype? + pi_info.start = max || pi_info.start + pi_info.count max) { + ret = -EINVAL; + goto put_vfio_device; + } + + gsi = memdup_user((void __user *)((unsigned long)argp + minsz), +pi_info.count * sizeof(int)); same question as above + if (IS_ERR(gsi)) { + ret = PTR_ERR(gsi); + goto put_vfio_device; + } + +#ifdef CONFIG_PCI_MSI + for (i = 0; i pi_info.count; i++) { + list_for_each_entry(entry, pdev-msi_list, list) { + if (entry-msi_attrib.entry_nr != pi_info.start+i) + continue; + + ret = kvm_arch_vfio_update_pi_irte(kdev-kvm, +entry-irq, +gsi[i]); + if (ret) { + ret = -EFAULT; why -EFAULT? and not propagation of original error code? you may have posting set for part of the subindexes
Re: [PATCH v6 1/8] iommu: provide early initialisation hook for IOMMU drivers
Hi Grant, On 04/12/14 17:58, Grant Likely wrote: [...] +struct of_iommu_node { + struct list_head list; + struct device_node *np; + struct iommu_ops *ops; Why can't this be const? Why would anyone ever need to modify it? Also drivers do define their iommu_ops structures const these days, so you'll either still have to cast away at some point or the compiler will complain once you start calling this from drivers. ...whereas if we make everything const then the drivers that _do_ want to use the private data introduced by this series and thus pass mutable per-instance iommu_ops will be the ones having to cast. We have no users either way until this series is merged, and the need to stash the per-instance data somewhere other than np-data is in the way of getting it merged - this is just a quick hack to address that. I think we've already agreed that mutable per-instance iommu_ops holding private data aren't particularly pleasant and will (hopefully) go away in the next iteration[1], at which point this all changes anyway. Do you expect drivers to modify that *priv pointer after the ops structure is registered? I'd be very surprised if that was the use case. It's fine for the driver to register a non-const version, but once it is registered, the infrastructure can treat it as const from then on. Possibly not - certainly my current port of the ARM SMMU which makes use of *priv is only ever reading it - although we did also wave around reasons for mutable ops like dynamically changing the pgsize_bitmap and possibly even swizzling individual ops for runtime reconfiguration. On consideration though, I'd agree that things like that are mad enough to stay well within individual drivers if they did ever happen, and certainly shouldn't apply to this bit of the infrastructure at any rate. Here's a respin the other way - making the get/set infrastructure fully const and fixing up the callsite in of_iommu_configure instead to avoid the warning. Trying to chase const-correctness beyond that quickly got too invasive and out of scope for this fix - I'm just keen to get the merge-blocker out of the way. Regards, Robin. ---8--- From 9eba5081aaf4fa8ed5158675a6e622be11a64ae2 Mon Sep 17 00:00:00 2001 Message-Id: 9eba5081aaf4fa8ed5158675a6e622be11a64ae2.1417719305.git.robin.mur...@arm.com From: Robin Murphy robin.mur...@arm.com Date: Thu, 4 Dec 2014 11:53:13 + Subject: [PATCH v3] iommu: store DT-probed IOMMU data privately Since the data pointer in the DT node is public and may be overwritten by conflicting code, move the DT-probed IOMMU ops to a private list where they will be safe. Signed-off-by: Robin Murphy robin.mur...@arm.com --- drivers/iommu/of_iommu.c | 40 +++- include/linux/of_iommu.h | 12 ++-- 2 files changed, 41 insertions(+), 11 deletions(-) diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c index 73236d3..39f581f 100644 --- a/drivers/iommu/of_iommu.c +++ b/drivers/iommu/of_iommu.c @@ -94,6 +94,44 @@ int of_get_dma_window(struct device_node *dn, const char *prefix, int index, } EXPORT_SYMBOL_GPL(of_get_dma_window); +struct of_iommu_node { + struct list_head list; + struct device_node *np; + const struct iommu_ops *ops; +}; +static LIST_HEAD(of_iommu_list); +static DEFINE_SPINLOCK(of_iommu_lock); + +void of_iommu_set_ops(struct device_node *np, const struct iommu_ops *ops) +{ + struct of_iommu_node *iommu = kzalloc(sizeof(*iommu), GFP_KERNEL); + + if (WARN_ON(!iommu)) + return; + + INIT_LIST_HEAD(iommu-list); + iommu-np = np; + iommu-ops = ops; + spin_lock(of_iommu_lock); + list_add_tail(iommu-list, of_iommu_list); + spin_unlock(of_iommu_lock); +} + +const struct iommu_ops *of_iommu_get_ops(struct device_node *np) +{ + struct of_iommu_node *node; + const struct iommu_ops *ops = NULL; + + spin_lock(of_iommu_lock); + list_for_each_entry(node, of_iommu_list, list) + if (node-np == np) { + ops = node-ops; + break; + } + spin_unlock(of_iommu_lock); + return ops; +} + struct iommu_ops *of_iommu_configure(struct device *dev) { struct of_phandle_args iommu_spec; @@ -110,7 +148,7 @@ struct iommu_ops *of_iommu_configure(struct device *dev) #iommu-cells, idx, iommu_spec)) { np = iommu_spec.np; - ops = of_iommu_get_ops(np); + ops = (struct iommu_ops *)of_iommu_get_ops(np); if (!ops || !ops-of_xlate || ops-of_xlate(dev, iommu_spec)) goto err_put_node; diff --git a/include/linux/of_iommu.h b/include/linux/of_iommu.h index d03abbb..83f6d0b 100644 --- a/include/linux/of_iommu.h +++ b/include/linux/of_iommu.h @@ -31,16 +31,8 @@ static inline struct
Re: [PATCH v6 0/8] Introduce automatic DMA configuration for IOMMU masters
On Mon, Dec 1, 2014 at 8:57 AM, Will Deacon will.dea...@arm.com wrote: Hello again, This is version 6 of the patches previously posted here: RFCv1: http://lists.infradead.org/pipermail/linux-arm-kernel/2014-August/283023.html RFCv2: http://lists.infradead.org/pipermail/linux-arm-kernel/2014-September/283752.html RFCv3: http://lists.infradead.org/pipermail/linux-arm-kernel/2014-September/287031.html RFCv4: http://lists.infradead.org/pipermail/linux-arm-kernel/2014-November/302711.html v5: http://lists.infradead.org/pipermail/linux-arm-kernel/2014-November/307213.html The only change since v5 is the addition of acks from various maintainers. Now that the ARM bits have rmk's ack and the IOMMU bits have joro's ack, I think this is good for merging via the arm-soc tree. Please let me know if a pull request would be preferable. Hi, Yes, please collect the acks from the discussion in the last day or so and send a pull request (and include Robin's patch, obviously). -Olof ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu