Patchwork [v2,13/22] iommu/tegra: smmu: Create default IOVA maps

login
register
mail settings
Submitter Hiroshi Doyu
Date July 5, 2013, 10:44 a.m.
Message ID <1373021097-32420-14-git-send-email-hdoyu@nvidia.com>
Download mbox | patch
Permalink /patch/257097/
State Superseded, archived
Headers show

Comments

Hiroshi Doyu - July 5, 2013, 10:44 a.m.
Create default IOVA maps at boot-up which can be attached to devices.

Signed-off-by: Hiroshi Doyu <hdoyu@nvidia.com>
---
 drivers/iommu/tegra-smmu.c |   28 ++++++++++++++++++++++++++--
 1 file changed, 26 insertions(+), 2 deletions(-)
Stephen Warren - July 18, 2013, 8:10 p.m.
On 07/05/2013 04:44 AM, Hiroshi Doyu wrote:
> Create default IOVA maps at boot-up which can be attached to devices.

> diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c

>  static int tegra_smmu_probe(struct platform_device *pdev)
>  {
>  	struct smmu_device *smmu;

> @@ -1160,13 +1182,15 @@ static int tegra_smmu_probe(struct platform_device *pdev)
>  	if (of_property_read_u32(dev->of_node, "nvidia,#asids", &asids))
>  		return -ENODEV;
>  
> -	bytes = sizeof(*smmu) + asids * sizeof(*smmu->as);
> +	bytes = sizeof(*smmu) + asids * (sizeof(*smmu->as) +
> +					 sizeof(struct dma_iommu_mapping *));
>  	smmu = devm_kzalloc(dev, bytes, GFP_KERNEL);
>  	if (!smmu) {
>  		dev_err(dev, "failed to allocate smmu_device\n");
>  		return -ENOMEM;
>  	}
>  
> +	smmu->map = (struct dma_iommu_mapping **)(smmu->as + asids);

Shouldn't "+ asids" be "+ asids * sizeof(*smmu->as)" to match the
calculation of "bytes" above?
--
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 - July 29, 2013, 11:24 a.m.
Stephen Warren <swarren@wwwdotorg.org> wrote @ Thu, 18 Jul 2013 22:10:29 +0200:

> On 07/05/2013 04:44 AM, Hiroshi Doyu wrote:
> > Create default IOVA maps at boot-up which can be attached to devices.
> 
> > diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c
> 
> >  static int tegra_smmu_probe(struct platform_device *pdev)
> >  {
> >  	struct smmu_device *smmu;
> 
> > @@ -1160,13 +1182,15 @@ static int tegra_smmu_probe(struct platform_device *pdev)
> >  	if (of_property_read_u32(dev->of_node, "nvidia,#asids", &asids))
> >  		return -ENODEV;
> >  
> > -	bytes = sizeof(*smmu) + asids * sizeof(*smmu->as);
> > +	bytes = sizeof(*smmu) + asids * (sizeof(*smmu->as) +
> > +					 sizeof(struct dma_iommu_mapping *));
> >  	smmu = devm_kzalloc(dev, bytes, GFP_KERNEL);
> >  	if (!smmu) {
> >  		dev_err(dev, "failed to allocate smmu_device\n");
> >  		return -ENOMEM;
> >  	}
> >  
> > +	smmu->map = (struct dma_iommu_mapping **)(smmu->as + asids);
> 
> Shouldn't "+ asids" be "+ asids * sizeof(*smmu->as)" to match the
> calculation of "bytes" above?

The structure is:

smmu {
     ....
     struct dma_iommu_mapping **map;
     ....	
     struct smmu_as	as[0];
};

I think that this is correct, but is the following better?

+ smmu->map = (struct dma_iommu_mapping **)&smmu->as[asids];
--
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
Stephen Warren - July 29, 2013, 5:50 p.m.
On 07/29/2013 05:24 AM, Hiroshi Doyu wrote:
> Stephen Warren <swarren@wwwdotorg.org> wrote @ Thu, 18 Jul 2013 22:10:29 +0200:
> 
>> On 07/05/2013 04:44 AM, Hiroshi Doyu wrote:
>>> Create default IOVA maps at boot-up which can be attached to devices.
>>
>>> diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c
>>
>>>  static int tegra_smmu_probe(struct platform_device *pdev)
>>>  {
>>>  	struct smmu_device *smmu;
>>
>>> @@ -1160,13 +1182,15 @@ static int tegra_smmu_probe(struct platform_device *pdev)
>>>  	if (of_property_read_u32(dev->of_node, "nvidia,#asids", &asids))
>>>  		return -ENODEV;
>>>  
>>> -	bytes = sizeof(*smmu) + asids * sizeof(*smmu->as);
>>> +	bytes = sizeof(*smmu) + asids * (sizeof(*smmu->as) +
>>> +					 sizeof(struct dma_iommu_mapping *));
>>>  	smmu = devm_kzalloc(dev, bytes, GFP_KERNEL);
>>>  	if (!smmu) {
>>>  		dev_err(dev, "failed to allocate smmu_device\n");
>>>  		return -ENOMEM;
>>>  	}
>>>  
>>> +	smmu->map = (struct dma_iommu_mapping **)(smmu->as + asids);
>>
>> Shouldn't "+ asids" be "+ asids * sizeof(*smmu->as)" to match the
>> calculation of "bytes" above?
> 
> The structure is:
> 
> smmu {
>      ....
>      struct dma_iommu_mapping **map;
>      ....	
>      struct smmu_as	as[0];
> };
> 
> I think that this is correct, but is the following better?

Oh right, I guess since that's pointer-math, the compiler already
multiplies by the array entry size.

> + smmu->map = (struct dma_iommu_mapping **)&smmu->as[asids];

That would be a bit more obvious.
--
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

Patch

diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c
index 3e03c69..1617c90 100644
--- a/drivers/iommu/tegra-smmu.c
+++ b/drivers/iommu/tegra-smmu.c
@@ -319,6 +319,8 @@  struct smmu_device {
 
 	struct device_node *ahb;
 
+	struct dma_iommu_mapping **map;
+
 	int		num_as;
 	struct smmu_as	as[0];		/* Run-time allocated array */
 };
@@ -1144,6 +1146,26 @@  static int tegra_smmu_resume(struct device *dev)
 	return err;
 }
 
+static int tegra_smmu_create_default_map(struct smmu_device *smmu)
+{
+	int i;
+
+	for (i = 0; i < smmu->num_as; i++) {
+		dma_addr_t base = smmu->iovmm_base;
+		size_t size = smmu->page_count << PAGE_SHIFT;
+
+		smmu->map[i] = arm_iommu_create_mapping(&platform_bus_type,
+							base, size, 0);
+		if (WARN_ON(IS_ERR(smmu->map[i])))
+			return -EINVAL;
+
+		dev_dbg(smmu->dev, "map:%p %08x-%08x\n",
+			smmu->map[i], base, base + size - 1);
+	}
+
+	return 0;
+}
+
 static int tegra_smmu_probe(struct platform_device *pdev)
 {
 	struct smmu_device *smmu;
@@ -1160,13 +1182,15 @@  static int tegra_smmu_probe(struct platform_device *pdev)
 	if (of_property_read_u32(dev->of_node, "nvidia,#asids", &asids))
 		return -ENODEV;
 
-	bytes = sizeof(*smmu) + asids * sizeof(*smmu->as);
+	bytes = sizeof(*smmu) + asids * (sizeof(*smmu->as) +
+					 sizeof(struct dma_iommu_mapping *));
 	smmu = devm_kzalloc(dev, bytes, GFP_KERNEL);
 	if (!smmu) {
 		dev_err(dev, "failed to allocate smmu_device\n");
 		return -ENOMEM;
 	}
 
+	smmu->map = (struct dma_iommu_mapping **)(smmu->as + asids);
 	smmu->nregs = pdev->num_resources;
 	smmu->regs = devm_kzalloc(dev, 2 * smmu->nregs * sizeof(*smmu->regs),
 				  GFP_KERNEL);
@@ -1238,7 +1262,7 @@  static int tegra_smmu_probe(struct platform_device *pdev)
 	smmu_debugfs_create(smmu);
 	smmu_handle = smmu;
 	bus_set_iommu(&platform_bus_type, &smmu_iommu_ops);
-	return 0;
+	return tegra_smmu_create_default_map(smmu);
 }
 
 static int tegra_smmu_remove(struct platform_device *pdev)