Re: [PATCH v6 04/16] drivers: iommu: make of_iommu_set/get_ops() DT agnostic
On Tue, Nov 01, 2016 at 04:36:10PM +, Robin Murphy wrote: > Bikeshed alert... > > On 18/10/16 17:04, Lorenzo Pieralisi wrote: > > The of_iommu_{set/get}_ops() API is used to associate a device > > tree node with a specific set of IOMMU operations. The same > > kernel interface is required on systems booting with ACPI, where > > devices are not associated with a device tree node, therefore > > the interface requires generalization. > > > > The struct device fwnode member represents the fwnode token > > associated with the device and the struct it points at is firmware > > specific; regardless, it is initialized on both ACPI and DT systems > > and makes an ideal candidate to use it to associate a set of IOMMU > > operations to a given device, through its struct device.fwnode member > > pointer. > > > > Convert the DT specific of_iommu_{set/get}_ops() interface to > > use struct device.fwnode as a look-up token, making the interface > > usable on ACPI systems. > > > > Signed-off-by: Lorenzo Pieralisi> > Cc: Will Deacon > > Cc: Hanjun Guo > > Cc: Robin Murphy > > Cc: Joerg Roedel > > --- > > drivers/iommu/iommu.c| 43 +++ > > drivers/iommu/of_iommu.c | 39 --- > > include/linux/iommu.h| 14 ++ > > include/linux/of_iommu.h | 12 ++-- > > 4 files changed, 67 insertions(+), 41 deletions(-) > > > > diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c > > index 9a2f196..320eb8c 100644 > > --- a/drivers/iommu/iommu.c > > +++ b/drivers/iommu/iommu.c > > @@ -1615,6 +1615,49 @@ int iommu_request_dm_for_dev(struct device *dev) > > return ret; > > } > > > > +struct fwnode_iommu_node { > > Having just pulled in this patch in isolation for some hacking, I > realise that by about the fifth time one reads "fwnode_iommu_node" it > just looks like meaningless gibberish. Can we just call it > "iommu_instance" instead, as that's what it's representing here? Agreed, how about iommu_(fw)entry ? Anyway, I will do, point taken. > > + struct list_head list; > > + struct fwnode_handle *fwnode; > > + const struct iommu_ops *ops; > > +}; > > +static LIST_HEAD(fwnode_iommu_list); > > +static DEFINE_SPINLOCK(fwnode_iommu_lock); > > + > > +void fwnode_iommu_set_ops(struct fwnode_handle *fwnode, > > + const struct iommu_ops *ops) > > +{ > > + struct fwnode_iommu_node *iommu = > > + kzalloc(sizeof(*iommu), GFP_KERNEL); > > (plus it shortens this line so it really doesn't the awkward break) > > Apologies, (the original rubbish name was my fault anyway) No worries, you have a point, will update for next (hopefully last) posting. Thanks ! Lorenzo > Robin. > > > + > > + if (WARN_ON(!iommu)) > > + return; > > + > > + if (is_of_node(fwnode)) > > + of_node_get(to_of_node(fwnode)); > > + > > + INIT_LIST_HEAD(>list); > > + iommu->fwnode = fwnode; > > + iommu->ops = ops; > > + spin_lock(_iommu_lock); > > + list_add_tail(>list, _iommu_list); > > + spin_unlock(_iommu_lock); > > +} > > + > > +const struct iommu_ops *fwnode_iommu_get_ops(struct fwnode_handle *fwnode) > > +{ > > + struct fwnode_iommu_node *node; > > + const struct iommu_ops *ops = NULL; > > + > > + spin_lock(_iommu_lock); > > + list_for_each_entry(node, _iommu_list, list) > > + if (node->fwnode == fwnode) { > > + ops = node->ops; > > + break; > > + } > > + spin_unlock(_iommu_lock); > > + return ops; > > +} > > + > > int iommu_fwspec_init(struct device *dev, struct fwnode_handle > > *iommu_fwnode, > > const struct iommu_ops *ops) > > { > > diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c > > index 5b82862..0f57ddc 100644 > > --- a/drivers/iommu/of_iommu.c > > +++ b/drivers/iommu/of_iommu.c > > @@ -96,45 +96,6 @@ 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; > > - > > - of_node_get(np); > > - INIT_LIST_HEAD(>list); > > - iommu->np = np; > > - iommu->ops = ops; > > - spin_lock(_iommu_lock); > > - list_add_tail(>list, _iommu_list); > > - spin_unlock(_iommu_lock); > > -} > > - > > -const struct iommu_ops *of_iommu_get_ops(struct device_node *np) > > -{ > > - struct of_iommu_node *node; > > - const struct
Re: [PATCH v6 04/16] drivers: iommu: make of_iommu_set/get_ops() DT agnostic
On Tue, Nov 01, 2016 at 04:36:10PM +, Robin Murphy wrote: > Bikeshed alert... > > On 18/10/16 17:04, Lorenzo Pieralisi wrote: > > The of_iommu_{set/get}_ops() API is used to associate a device > > tree node with a specific set of IOMMU operations. The same > > kernel interface is required on systems booting with ACPI, where > > devices are not associated with a device tree node, therefore > > the interface requires generalization. > > > > The struct device fwnode member represents the fwnode token > > associated with the device and the struct it points at is firmware > > specific; regardless, it is initialized on both ACPI and DT systems > > and makes an ideal candidate to use it to associate a set of IOMMU > > operations to a given device, through its struct device.fwnode member > > pointer. > > > > Convert the DT specific of_iommu_{set/get}_ops() interface to > > use struct device.fwnode as a look-up token, making the interface > > usable on ACPI systems. > > > > Signed-off-by: Lorenzo Pieralisi > > Cc: Will Deacon > > Cc: Hanjun Guo > > Cc: Robin Murphy > > Cc: Joerg Roedel > > --- > > drivers/iommu/iommu.c| 43 +++ > > drivers/iommu/of_iommu.c | 39 --- > > include/linux/iommu.h| 14 ++ > > include/linux/of_iommu.h | 12 ++-- > > 4 files changed, 67 insertions(+), 41 deletions(-) > > > > diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c > > index 9a2f196..320eb8c 100644 > > --- a/drivers/iommu/iommu.c > > +++ b/drivers/iommu/iommu.c > > @@ -1615,6 +1615,49 @@ int iommu_request_dm_for_dev(struct device *dev) > > return ret; > > } > > > > +struct fwnode_iommu_node { > > Having just pulled in this patch in isolation for some hacking, I > realise that by about the fifth time one reads "fwnode_iommu_node" it > just looks like meaningless gibberish. Can we just call it > "iommu_instance" instead, as that's what it's representing here? Agreed, how about iommu_(fw)entry ? Anyway, I will do, point taken. > > + struct list_head list; > > + struct fwnode_handle *fwnode; > > + const struct iommu_ops *ops; > > +}; > > +static LIST_HEAD(fwnode_iommu_list); > > +static DEFINE_SPINLOCK(fwnode_iommu_lock); > > + > > +void fwnode_iommu_set_ops(struct fwnode_handle *fwnode, > > + const struct iommu_ops *ops) > > +{ > > + struct fwnode_iommu_node *iommu = > > + kzalloc(sizeof(*iommu), GFP_KERNEL); > > (plus it shortens this line so it really doesn't the awkward break) > > Apologies, (the original rubbish name was my fault anyway) No worries, you have a point, will update for next (hopefully last) posting. Thanks ! Lorenzo > Robin. > > > + > > + if (WARN_ON(!iommu)) > > + return; > > + > > + if (is_of_node(fwnode)) > > + of_node_get(to_of_node(fwnode)); > > + > > + INIT_LIST_HEAD(>list); > > + iommu->fwnode = fwnode; > > + iommu->ops = ops; > > + spin_lock(_iommu_lock); > > + list_add_tail(>list, _iommu_list); > > + spin_unlock(_iommu_lock); > > +} > > + > > +const struct iommu_ops *fwnode_iommu_get_ops(struct fwnode_handle *fwnode) > > +{ > > + struct fwnode_iommu_node *node; > > + const struct iommu_ops *ops = NULL; > > + > > + spin_lock(_iommu_lock); > > + list_for_each_entry(node, _iommu_list, list) > > + if (node->fwnode == fwnode) { > > + ops = node->ops; > > + break; > > + } > > + spin_unlock(_iommu_lock); > > + return ops; > > +} > > + > > int iommu_fwspec_init(struct device *dev, struct fwnode_handle > > *iommu_fwnode, > > const struct iommu_ops *ops) > > { > > diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c > > index 5b82862..0f57ddc 100644 > > --- a/drivers/iommu/of_iommu.c > > +++ b/drivers/iommu/of_iommu.c > > @@ -96,45 +96,6 @@ 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; > > - > > - of_node_get(np); > > - INIT_LIST_HEAD(>list); > > - iommu->np = np; > > - iommu->ops = ops; > > - spin_lock(_iommu_lock); > > - list_add_tail(>list, _iommu_list); > > - spin_unlock(_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(_iommu_lock); > > - list_for_each_entry(node, _iommu_list, list) >
Re: [PATCH v6 04/16] drivers: iommu: make of_iommu_set/get_ops() DT agnostic
Bikeshed alert... On 18/10/16 17:04, Lorenzo Pieralisi wrote: > The of_iommu_{set/get}_ops() API is used to associate a device > tree node with a specific set of IOMMU operations. The same > kernel interface is required on systems booting with ACPI, where > devices are not associated with a device tree node, therefore > the interface requires generalization. > > The struct device fwnode member represents the fwnode token > associated with the device and the struct it points at is firmware > specific; regardless, it is initialized on both ACPI and DT systems > and makes an ideal candidate to use it to associate a set of IOMMU > operations to a given device, through its struct device.fwnode member > pointer. > > Convert the DT specific of_iommu_{set/get}_ops() interface to > use struct device.fwnode as a look-up token, making the interface > usable on ACPI systems. > > Signed-off-by: Lorenzo Pieralisi> Cc: Will Deacon > Cc: Hanjun Guo > Cc: Robin Murphy > Cc: Joerg Roedel > --- > drivers/iommu/iommu.c| 43 +++ > drivers/iommu/of_iommu.c | 39 --- > include/linux/iommu.h| 14 ++ > include/linux/of_iommu.h | 12 ++-- > 4 files changed, 67 insertions(+), 41 deletions(-) > > diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c > index 9a2f196..320eb8c 100644 > --- a/drivers/iommu/iommu.c > +++ b/drivers/iommu/iommu.c > @@ -1615,6 +1615,49 @@ int iommu_request_dm_for_dev(struct device *dev) > return ret; > } > > +struct fwnode_iommu_node { Having just pulled in this patch in isolation for some hacking, I realise that by about the fifth time one reads "fwnode_iommu_node" it just looks like meaningless gibberish. Can we just call it "iommu_instance" instead, as that's what it's representing here? > + struct list_head list; > + struct fwnode_handle *fwnode; > + const struct iommu_ops *ops; > +}; > +static LIST_HEAD(fwnode_iommu_list); > +static DEFINE_SPINLOCK(fwnode_iommu_lock); > + > +void fwnode_iommu_set_ops(struct fwnode_handle *fwnode, > + const struct iommu_ops *ops) > +{ > + struct fwnode_iommu_node *iommu = > + kzalloc(sizeof(*iommu), GFP_KERNEL); (plus it shortens this line so it really doesn't the awkward break) Apologies, (the original rubbish name was my fault anyway) Robin. > + > + if (WARN_ON(!iommu)) > + return; > + > + if (is_of_node(fwnode)) > + of_node_get(to_of_node(fwnode)); > + > + INIT_LIST_HEAD(>list); > + iommu->fwnode = fwnode; > + iommu->ops = ops; > + spin_lock(_iommu_lock); > + list_add_tail(>list, _iommu_list); > + spin_unlock(_iommu_lock); > +} > + > +const struct iommu_ops *fwnode_iommu_get_ops(struct fwnode_handle *fwnode) > +{ > + struct fwnode_iommu_node *node; > + const struct iommu_ops *ops = NULL; > + > + spin_lock(_iommu_lock); > + list_for_each_entry(node, _iommu_list, list) > + if (node->fwnode == fwnode) { > + ops = node->ops; > + break; > + } > + spin_unlock(_iommu_lock); > + return ops; > +} > + > int iommu_fwspec_init(struct device *dev, struct fwnode_handle *iommu_fwnode, > const struct iommu_ops *ops) > { > diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c > index 5b82862..0f57ddc 100644 > --- a/drivers/iommu/of_iommu.c > +++ b/drivers/iommu/of_iommu.c > @@ -96,45 +96,6 @@ 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; > - > - of_node_get(np); > - INIT_LIST_HEAD(>list); > - iommu->np = np; > - iommu->ops = ops; > - spin_lock(_iommu_lock); > - list_add_tail(>list, _iommu_list); > - spin_unlock(_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(_iommu_lock); > - list_for_each_entry(node, _iommu_list, list) > - if (node->np == np) { > - ops = node->ops; > - break; > - } > - spin_unlock(_iommu_lock); > - return ops; > -} > - > static int __get_pci_rid(struct pci_dev *pdev, u16 alias, void *data) > { > struct of_phandle_args
Re: [PATCH v6 04/16] drivers: iommu: make of_iommu_set/get_ops() DT agnostic
Bikeshed alert... On 18/10/16 17:04, Lorenzo Pieralisi wrote: > The of_iommu_{set/get}_ops() API is used to associate a device > tree node with a specific set of IOMMU operations. The same > kernel interface is required on systems booting with ACPI, where > devices are not associated with a device tree node, therefore > the interface requires generalization. > > The struct device fwnode member represents the fwnode token > associated with the device and the struct it points at is firmware > specific; regardless, it is initialized on both ACPI and DT systems > and makes an ideal candidate to use it to associate a set of IOMMU > operations to a given device, through its struct device.fwnode member > pointer. > > Convert the DT specific of_iommu_{set/get}_ops() interface to > use struct device.fwnode as a look-up token, making the interface > usable on ACPI systems. > > Signed-off-by: Lorenzo Pieralisi > Cc: Will Deacon > Cc: Hanjun Guo > Cc: Robin Murphy > Cc: Joerg Roedel > --- > drivers/iommu/iommu.c| 43 +++ > drivers/iommu/of_iommu.c | 39 --- > include/linux/iommu.h| 14 ++ > include/linux/of_iommu.h | 12 ++-- > 4 files changed, 67 insertions(+), 41 deletions(-) > > diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c > index 9a2f196..320eb8c 100644 > --- a/drivers/iommu/iommu.c > +++ b/drivers/iommu/iommu.c > @@ -1615,6 +1615,49 @@ int iommu_request_dm_for_dev(struct device *dev) > return ret; > } > > +struct fwnode_iommu_node { Having just pulled in this patch in isolation for some hacking, I realise that by about the fifth time one reads "fwnode_iommu_node" it just looks like meaningless gibberish. Can we just call it "iommu_instance" instead, as that's what it's representing here? > + struct list_head list; > + struct fwnode_handle *fwnode; > + const struct iommu_ops *ops; > +}; > +static LIST_HEAD(fwnode_iommu_list); > +static DEFINE_SPINLOCK(fwnode_iommu_lock); > + > +void fwnode_iommu_set_ops(struct fwnode_handle *fwnode, > + const struct iommu_ops *ops) > +{ > + struct fwnode_iommu_node *iommu = > + kzalloc(sizeof(*iommu), GFP_KERNEL); (plus it shortens this line so it really doesn't the awkward break) Apologies, (the original rubbish name was my fault anyway) Robin. > + > + if (WARN_ON(!iommu)) > + return; > + > + if (is_of_node(fwnode)) > + of_node_get(to_of_node(fwnode)); > + > + INIT_LIST_HEAD(>list); > + iommu->fwnode = fwnode; > + iommu->ops = ops; > + spin_lock(_iommu_lock); > + list_add_tail(>list, _iommu_list); > + spin_unlock(_iommu_lock); > +} > + > +const struct iommu_ops *fwnode_iommu_get_ops(struct fwnode_handle *fwnode) > +{ > + struct fwnode_iommu_node *node; > + const struct iommu_ops *ops = NULL; > + > + spin_lock(_iommu_lock); > + list_for_each_entry(node, _iommu_list, list) > + if (node->fwnode == fwnode) { > + ops = node->ops; > + break; > + } > + spin_unlock(_iommu_lock); > + return ops; > +} > + > int iommu_fwspec_init(struct device *dev, struct fwnode_handle *iommu_fwnode, > const struct iommu_ops *ops) > { > diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c > index 5b82862..0f57ddc 100644 > --- a/drivers/iommu/of_iommu.c > +++ b/drivers/iommu/of_iommu.c > @@ -96,45 +96,6 @@ 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; > - > - of_node_get(np); > - INIT_LIST_HEAD(>list); > - iommu->np = np; > - iommu->ops = ops; > - spin_lock(_iommu_lock); > - list_add_tail(>list, _iommu_list); > - spin_unlock(_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(_iommu_lock); > - list_for_each_entry(node, _iommu_list, list) > - if (node->np == np) { > - ops = node->ops; > - break; > - } > - spin_unlock(_iommu_lock); > - return ops; > -} > - > static int __get_pci_rid(struct pci_dev *pdev, u16 alias, void *data) > { > struct of_phandle_args *iommu_spec = data; > diff --git a/include/linux/iommu.h b/include/linux/iommu.h > index 436dc21..15d5478 100644 > ---
[PATCH v6 04/16] drivers: iommu: make of_iommu_set/get_ops() DT agnostic
The of_iommu_{set/get}_ops() API is used to associate a device tree node with a specific set of IOMMU operations. The same kernel interface is required on systems booting with ACPI, where devices are not associated with a device tree node, therefore the interface requires generalization. The struct device fwnode member represents the fwnode token associated with the device and the struct it points at is firmware specific; regardless, it is initialized on both ACPI and DT systems and makes an ideal candidate to use it to associate a set of IOMMU operations to a given device, through its struct device.fwnode member pointer. Convert the DT specific of_iommu_{set/get}_ops() interface to use struct device.fwnode as a look-up token, making the interface usable on ACPI systems. Signed-off-by: Lorenzo PieralisiCc: Will Deacon Cc: Hanjun Guo Cc: Robin Murphy Cc: Joerg Roedel --- drivers/iommu/iommu.c| 43 +++ drivers/iommu/of_iommu.c | 39 --- include/linux/iommu.h| 14 ++ include/linux/of_iommu.h | 12 ++-- 4 files changed, 67 insertions(+), 41 deletions(-) diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index 9a2f196..320eb8c 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -1615,6 +1615,49 @@ int iommu_request_dm_for_dev(struct device *dev) return ret; } +struct fwnode_iommu_node { + struct list_head list; + struct fwnode_handle *fwnode; + const struct iommu_ops *ops; +}; +static LIST_HEAD(fwnode_iommu_list); +static DEFINE_SPINLOCK(fwnode_iommu_lock); + +void fwnode_iommu_set_ops(struct fwnode_handle *fwnode, + const struct iommu_ops *ops) +{ + struct fwnode_iommu_node *iommu = + kzalloc(sizeof(*iommu), GFP_KERNEL); + + if (WARN_ON(!iommu)) + return; + + if (is_of_node(fwnode)) + of_node_get(to_of_node(fwnode)); + + INIT_LIST_HEAD(>list); + iommu->fwnode = fwnode; + iommu->ops = ops; + spin_lock(_iommu_lock); + list_add_tail(>list, _iommu_list); + spin_unlock(_iommu_lock); +} + +const struct iommu_ops *fwnode_iommu_get_ops(struct fwnode_handle *fwnode) +{ + struct fwnode_iommu_node *node; + const struct iommu_ops *ops = NULL; + + spin_lock(_iommu_lock); + list_for_each_entry(node, _iommu_list, list) + if (node->fwnode == fwnode) { + ops = node->ops; + break; + } + spin_unlock(_iommu_lock); + return ops; +} + int iommu_fwspec_init(struct device *dev, struct fwnode_handle *iommu_fwnode, const struct iommu_ops *ops) { diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c index 5b82862..0f57ddc 100644 --- a/drivers/iommu/of_iommu.c +++ b/drivers/iommu/of_iommu.c @@ -96,45 +96,6 @@ 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; - - of_node_get(np); - INIT_LIST_HEAD(>list); - iommu->np = np; - iommu->ops = ops; - spin_lock(_iommu_lock); - list_add_tail(>list, _iommu_list); - spin_unlock(_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(_iommu_lock); - list_for_each_entry(node, _iommu_list, list) - if (node->np == np) { - ops = node->ops; - break; - } - spin_unlock(_iommu_lock); - return ops; -} - static int __get_pci_rid(struct pci_dev *pdev, u16 alias, void *data) { struct of_phandle_args *iommu_spec = data; diff --git a/include/linux/iommu.h b/include/linux/iommu.h index 436dc21..15d5478 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h @@ -351,6 +351,9 @@ int iommu_fwspec_init(struct device *dev, struct fwnode_handle *iommu_fwnode, const struct iommu_ops *ops); void iommu_fwspec_free(struct device *dev); int iommu_fwspec_add_ids(struct device *dev, u32 *ids, int num_ids); +void fwnode_iommu_set_ops(struct fwnode_handle *fwnode, + const struct iommu_ops *ops); +const struct iommu_ops *fwnode_iommu_get_ops(struct fwnode_handle *fwnode); #else /*
[PATCH v6 04/16] drivers: iommu: make of_iommu_set/get_ops() DT agnostic
The of_iommu_{set/get}_ops() API is used to associate a device tree node with a specific set of IOMMU operations. The same kernel interface is required on systems booting with ACPI, where devices are not associated with a device tree node, therefore the interface requires generalization. The struct device fwnode member represents the fwnode token associated with the device and the struct it points at is firmware specific; regardless, it is initialized on both ACPI and DT systems and makes an ideal candidate to use it to associate a set of IOMMU operations to a given device, through its struct device.fwnode member pointer. Convert the DT specific of_iommu_{set/get}_ops() interface to use struct device.fwnode as a look-up token, making the interface usable on ACPI systems. Signed-off-by: Lorenzo Pieralisi Cc: Will Deacon Cc: Hanjun Guo Cc: Robin Murphy Cc: Joerg Roedel --- drivers/iommu/iommu.c| 43 +++ drivers/iommu/of_iommu.c | 39 --- include/linux/iommu.h| 14 ++ include/linux/of_iommu.h | 12 ++-- 4 files changed, 67 insertions(+), 41 deletions(-) diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index 9a2f196..320eb8c 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -1615,6 +1615,49 @@ int iommu_request_dm_for_dev(struct device *dev) return ret; } +struct fwnode_iommu_node { + struct list_head list; + struct fwnode_handle *fwnode; + const struct iommu_ops *ops; +}; +static LIST_HEAD(fwnode_iommu_list); +static DEFINE_SPINLOCK(fwnode_iommu_lock); + +void fwnode_iommu_set_ops(struct fwnode_handle *fwnode, + const struct iommu_ops *ops) +{ + struct fwnode_iommu_node *iommu = + kzalloc(sizeof(*iommu), GFP_KERNEL); + + if (WARN_ON(!iommu)) + return; + + if (is_of_node(fwnode)) + of_node_get(to_of_node(fwnode)); + + INIT_LIST_HEAD(>list); + iommu->fwnode = fwnode; + iommu->ops = ops; + spin_lock(_iommu_lock); + list_add_tail(>list, _iommu_list); + spin_unlock(_iommu_lock); +} + +const struct iommu_ops *fwnode_iommu_get_ops(struct fwnode_handle *fwnode) +{ + struct fwnode_iommu_node *node; + const struct iommu_ops *ops = NULL; + + spin_lock(_iommu_lock); + list_for_each_entry(node, _iommu_list, list) + if (node->fwnode == fwnode) { + ops = node->ops; + break; + } + spin_unlock(_iommu_lock); + return ops; +} + int iommu_fwspec_init(struct device *dev, struct fwnode_handle *iommu_fwnode, const struct iommu_ops *ops) { diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c index 5b82862..0f57ddc 100644 --- a/drivers/iommu/of_iommu.c +++ b/drivers/iommu/of_iommu.c @@ -96,45 +96,6 @@ 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; - - of_node_get(np); - INIT_LIST_HEAD(>list); - iommu->np = np; - iommu->ops = ops; - spin_lock(_iommu_lock); - list_add_tail(>list, _iommu_list); - spin_unlock(_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(_iommu_lock); - list_for_each_entry(node, _iommu_list, list) - if (node->np == np) { - ops = node->ops; - break; - } - spin_unlock(_iommu_lock); - return ops; -} - static int __get_pci_rid(struct pci_dev *pdev, u16 alias, void *data) { struct of_phandle_args *iommu_spec = data; diff --git a/include/linux/iommu.h b/include/linux/iommu.h index 436dc21..15d5478 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h @@ -351,6 +351,9 @@ int iommu_fwspec_init(struct device *dev, struct fwnode_handle *iommu_fwnode, const struct iommu_ops *ops); void iommu_fwspec_free(struct device *dev); int iommu_fwspec_add_ids(struct device *dev, u32 *ids, int num_ids); +void fwnode_iommu_set_ops(struct fwnode_handle *fwnode, + const struct iommu_ops *ops); +const struct iommu_ops *fwnode_iommu_get_ops(struct fwnode_handle *fwnode); #else /* CONFIG_IOMMU_API */ @@ -580,6 +583,17 @@ static inline int iommu_fwspec_add_ids(struct device *dev, u32 *ids,