diff mbox

[1/1] ARM: tegra: bus_notifier registers IOMMU devices(was: How to specify IOMMU'able devices in DT)

Message ID 20121128.154832.539666140149950229.hdoyu@nvidia.com
State Superseded, archived
Headers show

Commit Message

Hiroshi Doyu Nov. 28, 2012, 1:48 p.m. UTC
Hiroshi Doyu <hdoyu@nvidia.com> wrote @ Mon, 24 Sep 2012 14:50:14 +0300 (EEST):
...
> > > > On Mon, 2012-09-24 at 12:04 +0300, Hiroshi Doyu wrote:
> > > > > diff --git a/drivers/base/platform.c b/drivers/base/platform.c
> > > > > index a1a7225..9eae3be 100644
> > > > > --- a/drivers/base/platform.c
> > > > > +++ b/drivers/base/platform.c
> > > > > @@ -21,6 +21,8 @@
> > > > >  #include <linux/slab.h>
> > > > >  #include <linux/pm_runtime.h>
> > > > >
> > > > > +#include <asm/dma-iommu.h>
> > > > > +
> > > > >  #include "base.h"
> > > > >
> > > > >  #define to_platform_driver(drv)        (container_of((drv), struct
> > > > > platform_driver, \
> > > > > @@ -305,8 +307,19 @@ int platform_device_add(struct platform_device
> > > > > *pdev)
> > > > >                  dev_name(&pdev->dev), dev_name(pdev->dev.parent));
> > > > >
> > > > >         ret = device_add(&pdev->dev);
> > > > > -       if (ret == 0)
> > > > > -               return ret;
> > > > > +       if (ret)
> > > > > +               goto failed;
> > > > > +
> > > > > +#ifdef CONFIG_PLATFORM_ENABLE_IOMMU
> > > > > +       if (platform_bus_type.map && !pdev->dev.archdata.mapping) {
> > > > > +               ret = arm_iommu_attach_device(&pdev->dev,
> > > > > +                                             platform_bus_type.map);
> > > > > +               if (ret)
> > > > > +                       goto failed;
> > > >
> > > > This is horrible ... you're adding an architecture specific callback
> > > > into our generic code; that's really a no-no.  If the concept of
> > > > CONFIG_PLATFORM_ENABE_IOMMU is useful to more than just arm, then this
> > > > could become a generic callback.
> > > 
> > > As mentioned in the original, this is a heck to explain what is
> > > needed. I am looking for some generic solution for how to specify
> > > IOMMU info for each platform devices. I'm guessing that some other SoC
> > > may have the similar requirements on the above. As you mentioned, this
> > > solution should be a generic, not arch specific.
> > 
> > Please read more about bus notifiers. IMHO a good example is provided in 
> > the following thread:
> > http://www.mail-archive.com/linux-samsung-soc@vger.kernel.org/msg12238.html
> 
> This bus notifier seems enough flexible to afford the variation of
> IOMMU map info, like Tegra ASID, which could be platform-specific, and
> the other could be common too. There's already iommu_bus_notifier
> too. I'll try to implement something base on this.

Experimentally implemented as below. With the followig patch, each
device could specify its own map in DT, and automatically the device
would be attached to the map.

There is a case that some devices share a map. This patch doesn't
suppor such case yet.

From 8cb75bb6f3a8535a077e0e85265f87c1f1289bfd Mon Sep 17 00:00:00 2001
From: Hiroshi Doyu <hdoyu@nvidia.com>
Date: Wed, 28 Nov 2012 14:47:04 +0200
Subject: [PATCH 1/1] ARM: tegra: bus_notifier registers IOMMU devices

platform_bus notifier registers IOMMU devices if dma-window is
specified.

Its format is:
  dma-window = <"start" "size">;
ex)
  dma-window = <0x12345000 0x8000>;

Signed-off-by: Hiroshi Doyu <hdoyu@nvidia.com>
---
 arch/arm/mach-tegra/board-dt-tegra30.c |   40 ++++++++++++++++++++++++++++++++
 1 file changed, 40 insertions(+)

Comments

Stephen Warren Nov. 28, 2012, 6:07 p.m. UTC | #1
On 11/28/2012 06:48 AM, Hiroshi Doyu wrote:
> Hiroshi Doyu <hdoyu@nvidia.com> wrote @ Mon, 24 Sep 2012 14:50:14 +0300 (EEST):
> ...
>>>>> On Mon, 2012-09-24 at 12:04 +0300, Hiroshi Doyu wrote:
>>>>>> diff --git a/drivers/base/platform.c b/drivers/base/platform.c
>>>>>> index a1a7225..9eae3be 100644
>>>>>> --- a/drivers/base/platform.c
>>>>>> +++ b/drivers/base/platform.c
>>>>>> @@ -21,6 +21,8 @@
>>>>>>  #include <linux/slab.h>
>>>>>>  #include <linux/pm_runtime.h>
>>>>>>
>>>>>> +#include <asm/dma-iommu.h>
>>>>>> +
>>>>>>  #include "base.h"
>>>>>>
>>>>>>  #define to_platform_driver(drv)        (container_of((drv), struct
>>>>>> platform_driver, \
>>>>>> @@ -305,8 +307,19 @@ int platform_device_add(struct platform_device
>>>>>> *pdev)
>>>>>>                  dev_name(&pdev->dev), dev_name(pdev->dev.parent));
>>>>>>
>>>>>>         ret = device_add(&pdev->dev);
>>>>>> -       if (ret == 0)
>>>>>> -               return ret;
>>>>>> +       if (ret)
>>>>>> +               goto failed;
>>>>>> +
>>>>>> +#ifdef CONFIG_PLATFORM_ENABLE_IOMMU
>>>>>> +       if (platform_bus_type.map && !pdev->dev.archdata.mapping) {
>>>>>> +               ret = arm_iommu_attach_device(&pdev->dev,
>>>>>> +                                             platform_bus_type.map);
>>>>>> +               if (ret)
>>>>>> +                       goto failed;
>>>>>
>>>>> This is horrible ... you're adding an architecture specific callback
>>>>> into our generic code; that's really a no-no.  If the concept of
>>>>> CONFIG_PLATFORM_ENABE_IOMMU is useful to more than just arm, then this
>>>>> could become a generic callback.
>>>>
>>>> As mentioned in the original, this is a heck to explain what is
>>>> needed. I am looking for some generic solution for how to specify
>>>> IOMMU info for each platform devices. I'm guessing that some other SoC
>>>> may have the similar requirements on the above. As you mentioned, this
>>>> solution should be a generic, not arch specific.
>>>
>>> Please read more about bus notifiers. IMHO a good example is provided in 
>>> the following thread:
>>> http://www.mail-archive.com/linux-samsung-soc@vger.kernel.org/msg12238.html
>>
>> This bus notifier seems enough flexible to afford the variation of
>> IOMMU map info, like Tegra ASID, which could be platform-specific, and
>> the other could be common too. There's already iommu_bus_notifier
>> too. I'll try to implement something base on this.
> 
> Experimentally implemented as below. With the followig patch, each
> device could specify its own map in DT, and automatically the device
> would be attached to the map.
> 
> There is a case that some devices share a map. This patch doesn't
> suppor such case yet.
> 
> From 8cb75bb6f3a8535a077e0e85265f87c1f1289bfd Mon Sep 17 00:00:00 2001
> From: Hiroshi Doyu <hdoyu@nvidia.com>
> Date: Wed, 28 Nov 2012 14:47:04 +0200
> Subject: [PATCH 1/1] ARM: tegra: bus_notifier registers IOMMU devices
> 
> platform_bus notifier registers IOMMU devices if dma-window is
> specified.
> 
> Its format is:
>   dma-window = <"start" "size">;
> ex)
>   dma-window = <0x12345000 0x8000>;
> 
> Signed-off-by: Hiroshi Doyu <hdoyu@nvidia.com>
> ---
>  arch/arm/mach-tegra/board-dt-tegra30.c |   40 ++++++++++++++++++++++++++++++++

Shouldn't this patch be to the IOMMU driver itself, not the core Tegra code?

--
To unsubscribe from this list: send the line "unsubscribe linux-tegra" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Hiroshi Doyu Nov. 29, 2012, 6:45 a.m. UTC | #2
On Wed, 28 Nov 2012 19:07:46 +0100
Stephen Warren <swarren@wwwdotorg.org> wrote:
......
> >>> Please read more about bus notifiers. IMHO a good example is provided in 
> >>> the following thread:
> >>> http://www.mail-archive.com/linux-samsung-soc@vger.kernel.org/msg12238.html
> >>
> >> This bus notifier seems enough flexible to afford the variation of
> >> IOMMU map info, like Tegra ASID, which could be platform-specific, and
> >> the other could be common too. There's already iommu_bus_notifier
> >> too. I'll try to implement something base on this.
> > 
> > Experimentally implemented as below. With the followig patch, each
> > device could specify its own map in DT, and automatically the device
> > would be attached to the map.
> > 
> > There is a case that some devices share a map. This patch doesn't
> > suppor such case yet.
> > 
> > From 8cb75bb6f3a8535a077e0e85265f87c1f1289bfd Mon Sep 17 00:00:00 2001
> > From: Hiroshi Doyu <hdoyu@nvidia.com>
> > Date: Wed, 28 Nov 2012 14:47:04 +0200
> > Subject: [PATCH 1/1] ARM: tegra: bus_notifier registers IOMMU devices
> > 
> > platform_bus notifier registers IOMMU devices if dma-window is
> > specified.
> > 
> > Its format is:
> >   dma-window = <"start" "size">;
> > ex)
> >   dma-window = <0x12345000 0x8000>;
> > 
> > Signed-off-by: Hiroshi Doyu <hdoyu@nvidia.com>
> > ---
> >  arch/arm/mach-tegra/board-dt-tegra30.c |   40 ++++++++++++++++++++++++++++++++
> 
> Shouldn't this patch be to the IOMMU driver itself, not the core Tegra code?

That could be possible and cleaner. I'll check if it works.
--
To unsubscribe from this list: send the line "unsubscribe linux-tegra" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Thierry Reding Nov. 29, 2012, 10:17 a.m. UTC | #3
On Wed, Nov 28, 2012 at 02:48:32PM +0100, Hiroshi Doyu wrote:
[...]
> From: Hiroshi Doyu <hdoyu@nvidia.com>
> Date: Wed, 28 Nov 2012 14:47:04 +0200
> Subject: [PATCH 1/1] ARM: tegra: bus_notifier registers IOMMU devices
> 
> platform_bus notifier registers IOMMU devices if dma-window is
> specified.
> 
> Its format is:
>   dma-window = <"start" "size">;
> ex)
>   dma-window = <0x12345000 0x8000>;
> 
> Signed-off-by: Hiroshi Doyu <hdoyu@nvidia.com>
> ---
>  arch/arm/mach-tegra/board-dt-tegra30.c |   40 ++++++++++++++++++++++++++++++++
>  1 file changed, 40 insertions(+)
> 
> diff --git a/arch/arm/mach-tegra/board-dt-tegra30.c b/arch/arm/mach-tegra/board-dt-tegra30.c
> index a2b6cf1..570d718 100644
> --- a/arch/arm/mach-tegra/board-dt-tegra30.c
> +++ b/arch/arm/mach-tegra/board-dt-tegra30.c
> @@ -30,9 +30,11 @@
>  #include <linux/of_fdt.h>
>  #include <linux/of_irq.h>
>  #include <linux/of_platform.h>
> +#include <linux/of_iommu.h>
>  
>  #include <asm/mach/arch.h>
>  #include <asm/hardware/gic.h>
> +#include <asm/dma-iommu.h>
>  
>  #include "board.h"
>  #include "clock.h"
> @@ -86,10 +88,48 @@ static __initdata struct tegra_clk_init_table tegra_dt_clk_init_table[] = {
>  	{ NULL,		NULL,		0,		0},
>  };
>  
> +#ifdef CONFIG_ARM_DMA_USE_IOMMU
> +static int tegra_iommu_device_notifier(struct notifier_block *nb,
> +				       unsigned long event, void *_dev)
> +{
> +	struct dma_iommu_mapping *map = NULL;
> +	struct device *dev = _dev;
> +	dma_addr_t base;
> +	size_t size;
> +	int err;
> +
> +	switch (event) {
> +	case BUS_NOTIFY_ADD_DEVICE:
> +		err = of_get_dma_window(dev->of_node, NULL, 0, NULL, &base,
> +					&size);
> +		if (!err)
> +			map = arm_iommu_create_mapping(&platform_bus_type,
> +						       base, size, 0);
> +		if (IS_ERR_OR_NULL(map))
> +			break;
> +		if (arm_iommu_attach_device(dev, map))
> +			dev_err(dev, "Failed to attach %s\n", dev_name(dev));
> +		dev_dbg(dev, "Attached %s to map %p\n", dev_name(dev), map);
> +		break;
> +	}
> +	return NOTIFY_DONE;
> +}
> +#else
> +#define tegra_iommu_device_notifier NULL
> +#endif
> +
> +static struct notifier_block tegra_iommu_device_nb = {
> +	.notifier_call = tegra_iommu_device_notifier,
> +};

You don't need this extra protection since you use IS_ENABLED below and
these are all static variables. The whole point of IS_ENABLED is to
allow full compile coverage while leaving it up to the compiler to
eliminate dead code.

Thierry
Mark Zhang Nov. 30, 2012, 4:59 a.m. UTC | #4
On 11/28/2012 09:48 PM, Hiroshi Doyu wrote:
> Hiroshi Doyu <hdoyu@nvidia.com> wrote @ Mon, 24 Sep 2012 14:50:14 +0300 (EEST):
> ...
>>>>> On Mon, 2012-09-24 at 12:04 +0300, Hiroshi Doyu wrote:
>>>>>> diff --git a/drivers/base/platform.c b/drivers/base/platform.c
>>>>>> index a1a7225..9eae3be 100644
>>>>>> --- a/drivers/base/platform.c
>>>>>> +++ b/drivers/base/platform.c
>>>>>> @@ -21,6 +21,8 @@
>>>>>>  #include <linux/slab.h>
>>>>>>  #include <linux/pm_runtime.h>
>>>>>>
>>>>>> +#include <asm/dma-iommu.h>
>>>>>> +
>>>>>>  #include "base.h"
>>>>>>
>>>>>>  #define to_platform_driver(drv)        (container_of((drv), struct
>>>>>> platform_driver, \
>>>>>> @@ -305,8 +307,19 @@ int platform_device_add(struct platform_device
>>>>>> *pdev)
>>>>>>                  dev_name(&pdev->dev), dev_name(pdev->dev.parent));
>>>>>>
>>>>>>         ret = device_add(&pdev->dev);
>>>>>> -       if (ret == 0)
>>>>>> -               return ret;
>>>>>> +       if (ret)
>>>>>> +               goto failed;
>>>>>> +
>>>>>> +#ifdef CONFIG_PLATFORM_ENABLE_IOMMU
>>>>>> +       if (platform_bus_type.map && !pdev->dev.archdata.mapping) {
>>>>>> +               ret = arm_iommu_attach_device(&pdev->dev,
>>>>>> +                                             platform_bus_type.map);
>>>>>> +               if (ret)
>>>>>> +                       goto failed;
>>>>>
>>>>> This is horrible ... you're adding an architecture specific callback
>>>>> into our generic code; that's really a no-no.  If the concept of
>>>>> CONFIG_PLATFORM_ENABE_IOMMU is useful to more than just arm, then this
>>>>> could become a generic callback.
>>>>
>>>> As mentioned in the original, this is a heck to explain what is
>>>> needed. I am looking for some generic solution for how to specify
>>>> IOMMU info for each platform devices. I'm guessing that some other SoC
>>>> may have the similar requirements on the above. As you mentioned, this
>>>> solution should be a generic, not arch specific.
>>>
>>> Please read more about bus notifiers. IMHO a good example is provided in 
>>> the following thread:
>>> http://www.mail-archive.com/linux-samsung-soc@vger.kernel.org/msg12238.html
>>
>> This bus notifier seems enough flexible to afford the variation of
>> IOMMU map info, like Tegra ASID, which could be platform-specific, and
>> the other could be common too. There's already iommu_bus_notifier
>> too. I'll try to implement something base on this.
> 
> Experimentally implemented as below. With the followig patch, each
> device could specify its own map in DT, and automatically the device
> would be attached to the map.
> 
> There is a case that some devices share a map. This patch doesn't
> suppor such case yet.
> 
> From 8cb75bb6f3a8535a077e0e85265f87c1f1289bfd Mon Sep 17 00:00:00 2001
> From: Hiroshi Doyu <hdoyu@nvidia.com>
> Date: Wed, 28 Nov 2012 14:47:04 +0200
> Subject: [PATCH 1/1] ARM: tegra: bus_notifier registers IOMMU devices
> 
> platform_bus notifier registers IOMMU devices if dma-window is
> specified.
> 
> Its format is:
>   dma-window = <"start" "size">;
> ex)
>   dma-window = <0x12345000 0x8000>;
> 
> Signed-off-by: Hiroshi Doyu <hdoyu@nvidia.com>
> ---
>  arch/arm/mach-tegra/board-dt-tegra30.c |   40 ++++++++++++++++++++++++++++++++
>  1 file changed, 40 insertions(+)
> 
> diff --git a/arch/arm/mach-tegra/board-dt-tegra30.c b/arch/arm/mach-tegra/board-dt-tegra30.c
> index a2b6cf1..570d718 100644
> --- a/arch/arm/mach-tegra/board-dt-tegra30.c
> +++ b/arch/arm/mach-tegra/board-dt-tegra30.c
> @@ -30,9 +30,11 @@
>  #include <linux/of_fdt.h>
>  #include <linux/of_irq.h>
>  #include <linux/of_platform.h>
> +#include <linux/of_iommu.h>
>  
>  #include <asm/mach/arch.h>
>  #include <asm/hardware/gic.h>
> +#include <asm/dma-iommu.h>
>  
>  #include "board.h"
>  #include "clock.h"
> @@ -86,10 +88,48 @@ static __initdata struct tegra_clk_init_table tegra_dt_clk_init_table[] = {
>  	{ NULL,		NULL,		0,		0},
>  };
>  
> +#ifdef CONFIG_ARM_DMA_USE_IOMMU
> +static int tegra_iommu_device_notifier(struct notifier_block *nb,
> +				       unsigned long event, void *_dev)
> +{
> +	struct dma_iommu_mapping *map = NULL;
> +	struct device *dev = _dev;
> +	dma_addr_t base;
> +	size_t size;
> +	int err;
> +
> +	switch (event) {
> +	case BUS_NOTIFY_ADD_DEVICE:
> +		err = of_get_dma_window(dev->of_node, NULL, 0, NULL, &base,
> +					&size);
> +		if (!err)
> +			map = arm_iommu_create_mapping(&platform_bus_type,
> +						       base, size, 0);
> +		if (IS_ERR_OR_NULL(map))
> +			break;
> +		if (arm_iommu_attach_device(dev, map))

Add "arm_iommu_release_mapping" here.

And finally we see this patch, that's great. :)

> +			dev_err(dev, "Failed to attach %s\n", dev_name(dev));
> +		dev_dbg(dev, "Attached %s to map %p\n", dev_name(dev), map);
> +		break;
> +	}
> +	return NOTIFY_DONE;
> +}
> +#else
> +#define tegra_iommu_device_notifier NULL
> +#endif
> +
> +static struct notifier_block tegra_iommu_device_nb = {
> +	.notifier_call = tegra_iommu_device_notifier,
> +};
> +
>  static void __init tegra30_dt_init(void)
>  {
>  	tegra_clk_init_from_table(tegra_dt_clk_init_table);
>  
> +	if (IS_ENABLED(CONFIG_ARM_DMA_USE_IOMMU))
> +		bus_register_notifier(&platform_bus_type,
> +				      &tegra_iommu_device_nb);
> +
>  	of_platform_populate(NULL, of_default_bus_match_table,
>  				tegra30_auxdata_lookup, NULL);
>  }
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-tegra" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Hiroshi Doyu Nov. 30, 2012, 8:06 a.m. UTC | #5
Mark Zhang <nvmarkzhang@gmail.com> wrote @ Fri, 30 Nov 2012 05:59:32 +0100:

> On 11/28/2012 09:48 PM, Hiroshi Doyu wrote:
> > Hiroshi Doyu <hdoyu@nvidia.com> wrote @ Mon, 24 Sep 2012 14:50:14 +0300 (EEST):
> > ...
> >>>>> On Mon, 2012-09-24 at 12:04 +0300, Hiroshi Doyu wrote:
> >>>>>> diff --git a/drivers/base/platform.c b/drivers/base/platform.c
> >>>>>> index a1a7225..9eae3be 100644
> >>>>>> --- a/drivers/base/platform.c
> >>>>>> +++ b/drivers/base/platform.c
> >>>>>> @@ -21,6 +21,8 @@
> >>>>>>  #include <linux/slab.h>
> >>>>>>  #include <linux/pm_runtime.h>
> >>>>>>
> >>>>>> +#include <asm/dma-iommu.h>
> >>>>>> +
> >>>>>>  #include "base.h"
> >>>>>>
> >>>>>>  #define to_platform_driver(drv)        (container_of((drv), struct
> >>>>>> platform_driver, \
> >>>>>> @@ -305,8 +307,19 @@ int platform_device_add(struct platform_device
> >>>>>> *pdev)
> >>>>>>                  dev_name(&pdev->dev), dev_name(pdev->dev.parent));
> >>>>>>
> >>>>>>         ret = device_add(&pdev->dev);
> >>>>>> -       if (ret == 0)
> >>>>>> -               return ret;
> >>>>>> +       if (ret)
> >>>>>> +               goto failed;
> >>>>>> +
> >>>>>> +#ifdef CONFIG_PLATFORM_ENABLE_IOMMU
> >>>>>> +       if (platform_bus_type.map && !pdev->dev.archdata.mapping) {
> >>>>>> +               ret = arm_iommu_attach_device(&pdev->dev,
> >>>>>> +                                             platform_bus_type.map);
> >>>>>> +               if (ret)
> >>>>>> +                       goto failed;
> >>>>>
> >>>>> This is horrible ... you're adding an architecture specific callback
> >>>>> into our generic code; that's really a no-no.  If the concept of
> >>>>> CONFIG_PLATFORM_ENABE_IOMMU is useful to more than just arm, then this
> >>>>> could become a generic callback.
> >>>>
> >>>> As mentioned in the original, this is a heck to explain what is
> >>>> needed. I am looking for some generic solution for how to specify
> >>>> IOMMU info for each platform devices. I'm guessing that some other SoC
> >>>> may have the similar requirements on the above. As you mentioned, this
> >>>> solution should be a generic, not arch specific.
> >>>
> >>> Please read more about bus notifiers. IMHO a good example is provided in 
> >>> the following thread:
> >>> http://www.mail-archive.com/linux-samsung-soc@vger.kernel.org/msg12238.html
> >>
> >> This bus notifier seems enough flexible to afford the variation of
> >> IOMMU map info, like Tegra ASID, which could be platform-specific, and
> >> the other could be common too. There's already iommu_bus_notifier
> >> too. I'll try to implement something base on this.
> > 
> > Experimentally implemented as below. With the followig patch, each
> > device could specify its own map in DT, and automatically the device
> > would be attached to the map.
> > 
> > There is a case that some devices share a map. This patch doesn't
> > suppor such case yet.
> > 
> > From 8cb75bb6f3a8535a077e0e85265f87c1f1289bfd Mon Sep 17 00:00:00 2001
> > From: Hiroshi Doyu <hdoyu@nvidia.com>
> > Date: Wed, 28 Nov 2012 14:47:04 +0200
> > Subject: [PATCH 1/1] ARM: tegra: bus_notifier registers IOMMU devices
> > 
> > platform_bus notifier registers IOMMU devices if dma-window is
> > specified.
> > 
> > Its format is:
> >   dma-window = <"start" "size">;
> > ex)
> >   dma-window = <0x12345000 0x8000>;
> > 
> > Signed-off-by: Hiroshi Doyu <hdoyu@nvidia.com>
> > ---
> >  arch/arm/mach-tegra/board-dt-tegra30.c |   40 ++++++++++++++++++++++++++++++++
> >  1 file changed, 40 insertions(+)
> > 
> > diff --git a/arch/arm/mach-tegra/board-dt-tegra30.c b/arch/arm/mach-tegra/board-dt-tegra30.c
> > index a2b6cf1..570d718 100644
> > --- a/arch/arm/mach-tegra/board-dt-tegra30.c
> > +++ b/arch/arm/mach-tegra/board-dt-tegra30.c
> > @@ -30,9 +30,11 @@
> >  #include <linux/of_fdt.h>
> >  #include <linux/of_irq.h>
> >  #include <linux/of_platform.h>
> > +#include <linux/of_iommu.h>
> >  
> >  #include <asm/mach/arch.h>
> >  #include <asm/hardware/gic.h>
> > +#include <asm/dma-iommu.h>
> >  
> >  #include "board.h"
> >  #include "clock.h"
> > @@ -86,10 +88,48 @@ static __initdata struct tegra_clk_init_table tegra_dt_clk_init_table[] = {
> >  	{ NULL,		NULL,		0,		0},
> >  };
> >  
> > +#ifdef CONFIG_ARM_DMA_USE_IOMMU
> > +static int tegra_iommu_device_notifier(struct notifier_block *nb,
> > +				       unsigned long event, void *_dev)
> > +{
> > +	struct dma_iommu_mapping *map = NULL;
> > +	struct device *dev = _dev;
> > +	dma_addr_t base;
> > +	size_t size;
> > +	int err;
> > +
> > +	switch (event) {
> > +	case BUS_NOTIFY_ADD_DEVICE:
> > +		err = of_get_dma_window(dev->of_node, NULL, 0, NULL, &base,
> > +					&size);
> > +		if (!err)
> > +			map = arm_iommu_create_mapping(&platform_bus_type,
> > +						       base, size, 0);
> > +		if (IS_ERR_OR_NULL(map))
> > +			break;
> > +		if (arm_iommu_attach_device(dev, map))
> 
> Add "arm_iommu_release_mapping" here.

Yes.

> And finally we see this patch, that's great. :)

I'll move the location of patch to drivers/iommu/tegra-smmu.c and repost.
--
To unsubscribe from this list: send the line "unsubscribe linux-tegra" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/arch/arm/mach-tegra/board-dt-tegra30.c b/arch/arm/mach-tegra/board-dt-tegra30.c
index a2b6cf1..570d718 100644
--- a/arch/arm/mach-tegra/board-dt-tegra30.c
+++ b/arch/arm/mach-tegra/board-dt-tegra30.c
@@ -30,9 +30,11 @@ 
 #include <linux/of_fdt.h>
 #include <linux/of_irq.h>
 #include <linux/of_platform.h>
+#include <linux/of_iommu.h>
 
 #include <asm/mach/arch.h>
 #include <asm/hardware/gic.h>
+#include <asm/dma-iommu.h>
 
 #include "board.h"
 #include "clock.h"
@@ -86,10 +88,48 @@  static __initdata struct tegra_clk_init_table tegra_dt_clk_init_table[] = {
 	{ NULL,		NULL,		0,		0},
 };
 
+#ifdef CONFIG_ARM_DMA_USE_IOMMU
+static int tegra_iommu_device_notifier(struct notifier_block *nb,
+				       unsigned long event, void *_dev)
+{
+	struct dma_iommu_mapping *map = NULL;
+	struct device *dev = _dev;
+	dma_addr_t base;
+	size_t size;
+	int err;
+
+	switch (event) {
+	case BUS_NOTIFY_ADD_DEVICE:
+		err = of_get_dma_window(dev->of_node, NULL, 0, NULL, &base,
+					&size);
+		if (!err)
+			map = arm_iommu_create_mapping(&platform_bus_type,
+						       base, size, 0);
+		if (IS_ERR_OR_NULL(map))
+			break;
+		if (arm_iommu_attach_device(dev, map))
+			dev_err(dev, "Failed to attach %s\n", dev_name(dev));
+		dev_dbg(dev, "Attached %s to map %p\n", dev_name(dev), map);
+		break;
+	}
+	return NOTIFY_DONE;
+}
+#else
+#define tegra_iommu_device_notifier NULL
+#endif
+
+static struct notifier_block tegra_iommu_device_nb = {
+	.notifier_call = tegra_iommu_device_notifier,
+};
+
 static void __init tegra30_dt_init(void)
 {
 	tegra_clk_init_from_table(tegra_dt_clk_init_table);
 
+	if (IS_ENABLED(CONFIG_ARM_DMA_USE_IOMMU))
+		bus_register_notifier(&platform_bus_type,
+				      &tegra_iommu_device_nb);
+
 	of_platform_populate(NULL, of_default_bus_match_table,
 				tegra30_auxdata_lookup, NULL);
 }