diff mbox

[1/5] iommu/omap: Use the cache cleaning API

Message ID 1394239574-2389-2-git-send-email-laurent.pinchart@ideasonboard.com (mailing list archive)
State New, archived
Headers show

Commit Message

Laurent Pinchart March 8, 2014, 12:46 a.m. UTC
The page table entries must be cleaned from the cache before being
accessed by the IOMMU. Instead of implementing cache management manually
(and ignoring L2 cache), use clean_dcache_area() to make sure the
entries are visible to the device.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/iommu/omap-iommu.c | 41 ++++++++++-------------------------------
 1 file changed, 10 insertions(+), 31 deletions(-)

Comments

Suman Anna March 14, 2014, 2:47 a.m. UTC | #1
Hi Laurent,

On 03/07/2014 06:46 PM, Laurent Pinchart wrote:
> The page table entries must be cleaned from the cache before being
> accessed by the IOMMU. Instead of implementing cache management manually
> (and ignoring L2 cache), use clean_dcache_area() to make sure the
> entries are visible to the device.

Thanks for fixing this, this has been long pending. There have been some 
previous attempts at this as well by Ramesh Gupta, with the last thread 
(a long time now) being
http://marc.info/?t=134752035400001&r=1&w=2

Santosh,
Can you please take a look at this patch and provide your comments?

regards
Suman

>
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
>   drivers/iommu/omap-iommu.c | 41 ++++++++++-------------------------------
>   1 file changed, 10 insertions(+), 31 deletions(-)
>
> diff --git a/drivers/iommu/omap-iommu.c b/drivers/iommu/omap-iommu.c
> index a893eca..bb605c9 100644
> --- a/drivers/iommu/omap-iommu.c
> +++ b/drivers/iommu/omap-iommu.c
> @@ -500,24 +500,9 @@ EXPORT_SYMBOL_GPL(omap_foreach_iommu_device);
>   /*
>    *	H/W pagetable operations
>    */
> -static void flush_iopgd_range(u32 *first, u32 *last)
> +static void flush_pgtable(void *addr, size_t size)
>   {
> -	/* FIXME: L2 cache should be taken care of if it exists */
> -	do {
> -		asm("mcr	p15, 0, %0, c7, c10, 1 @ flush_pgd"
> -		    : : "r" (first));
> -		first += L1_CACHE_BYTES / sizeof(*first);
> -	} while (first <= last);
> -}
> -
> -static void flush_iopte_range(u32 *first, u32 *last)
> -{
> -	/* FIXME: L2 cache should be taken care of if it exists */
> -	do {
> -		asm("mcr	p15, 0, %0, c7, c10, 1 @ flush_pte"
> -		    : : "r" (first));
> -		first += L1_CACHE_BYTES / sizeof(*first);
> -	} while (first <= last);
> +	clean_dcache_area(addr, size);
>   }
>
>   static void iopte_free(u32 *iopte)
> @@ -546,7 +531,7 @@ static u32 *iopte_alloc(struct omap_iommu *obj, u32 *iopgd, u32 da)
>   			return ERR_PTR(-ENOMEM);
>
>   		*iopgd = virt_to_phys(iopte) | IOPGD_TABLE;
> -		flush_iopgd_range(iopgd, iopgd);
> +		flush_pgtable(iopgd, sizeof(*iopgd));
>
>   		dev_vdbg(obj->dev, "%s: a new pte:%p\n", __func__, iopte);
>   	} else {
> @@ -575,7 +560,7 @@ static int iopgd_alloc_section(struct omap_iommu *obj, u32 da, u32 pa, u32 prot)
>   	}
>
>   	*iopgd = (pa & IOSECTION_MASK) | prot | IOPGD_SECTION;
> -	flush_iopgd_range(iopgd, iopgd);
> +	flush_pgtable(iopgd, sizeof(*iopgd));
>   	return 0;
>   }
>
> @@ -592,7 +577,7 @@ static int iopgd_alloc_super(struct omap_iommu *obj, u32 da, u32 pa, u32 prot)
>
>   	for (i = 0; i < 16; i++)
>   		*(iopgd + i) = (pa & IOSUPER_MASK) | prot | IOPGD_SUPER;
> -	flush_iopgd_range(iopgd, iopgd + 15);
> +	flush_pgtable(iopgd, sizeof(*iopgd) * 16);
>   	return 0;
>   }
>
> @@ -605,7 +590,7 @@ static int iopte_alloc_page(struct omap_iommu *obj, u32 da, u32 pa, u32 prot)
>   		return PTR_ERR(iopte);
>
>   	*iopte = (pa & IOPAGE_MASK) | prot | IOPTE_SMALL;
> -	flush_iopte_range(iopte, iopte);
> +	flush_pgtable(iopte, sizeof(*iopte));
>
>   	dev_vdbg(obj->dev, "%s: da:%08x pa:%08x pte:%p *pte:%08x\n",
>   		 __func__, da, pa, iopte, *iopte);
> @@ -619,18 +604,12 @@ static int iopte_alloc_large(struct omap_iommu *obj, u32 da, u32 pa, u32 prot)
>   	u32 *iopte = iopte_alloc(obj, iopgd, da);
>   	int i;
>
> -	if ((da | pa) & ~IOLARGE_MASK) {
> -		dev_err(obj->dev, "%s: %08x:%08x should aligned on %08lx\n",
> -			__func__, da, pa, IOLARGE_SIZE);
> -		return -EINVAL;
> -	}
> -
>   	if (IS_ERR(iopte))
>   		return PTR_ERR(iopte);
>
>   	for (i = 0; i < 16; i++)
>   		*(iopte + i) = (pa & IOLARGE_MASK) | prot | IOPTE_LARGE;
> -	flush_iopte_range(iopte, iopte + 15);
> +	flush_pgtable(iopte, sizeof(*iopte) * 16);
>   	return 0;
>   }
>
> @@ -733,7 +712,7 @@ static size_t iopgtable_clear_entry_core(struct omap_iommu *obj, u32 da)
>   		}
>   		bytes *= nent;
>   		memset(iopte, 0, nent * sizeof(*iopte));
> -		flush_iopte_range(iopte, iopte + (nent - 1) * sizeof(*iopte));
> +		flush_pgtable(iopte, sizeof(*iopte) * nent);
>
>   		/*
>   		 * do table walk to check if this table is necessary or not
> @@ -755,7 +734,7 @@ static size_t iopgtable_clear_entry_core(struct omap_iommu *obj, u32 da)
>   		bytes *= nent;
>   	}
>   	memset(iopgd, 0, nent * sizeof(*iopgd));
> -	flush_iopgd_range(iopgd, iopgd + (nent - 1) * sizeof(*iopgd));
> +	flush_pgtable(iopgd, sizeof(*iopgd) * nent);
>   out:
>   	return bytes;
>   }
> @@ -799,7 +778,7 @@ static void iopgtable_clear_entry_all(struct omap_iommu *obj)
>   			iopte_free(iopte_offset(iopgd, 0));
>
>   		*iopgd = 0;
> -		flush_iopgd_range(iopgd, iopgd);
> +		flush_pgtable(iopgd, sizeof(*iopgd));
>   	}
>
>   	flush_iotlb_all(obj);
>

--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Santosh Shilimkar March 14, 2014, 4:15 p.m. UTC | #2
+ Russell, Arnd

On Thursday 13 March 2014 10:47 PM, Anna, Suman wrote:
> Hi Laurent,
> 
> On 03/07/2014 06:46 PM, Laurent Pinchart wrote:
>> The page table entries must be cleaned from the cache before being
>> accessed by the IOMMU. Instead of implementing cache management manually
>> (and ignoring L2 cache), use clean_dcache_area() to make sure the
>> entries are visible to the device.
> 
> Thanks for fixing this, this has been long pending. There have been some 
> previous attempts at this as well by Ramesh Gupta, with the last thread 
> (a long time now) being
> http://marc.info/?t=134752035400001&r=1&w=2
> 
> Santosh,
> Can you please take a look at this patch and provide your comments?
> 
> regards
> Suman
> 
>>
>> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
>> ---
>>   drivers/iommu/omap-iommu.c | 41 ++++++++++-------------------------------
>>   1 file changed, 10 insertions(+), 31 deletions(-)
>>
>> diff --git a/drivers/iommu/omap-iommu.c b/drivers/iommu/omap-iommu.c
>> index a893eca..bb605c9 100644
>> --- a/drivers/iommu/omap-iommu.c
>> +++ b/drivers/iommu/omap-iommu.c
>> @@ -500,24 +500,9 @@ EXPORT_SYMBOL_GPL(omap_foreach_iommu_device);
>>   /*
>>    *	H/W pagetable operations
>>    */
>> -static void flush_iopgd_range(u32 *first, u32 *last)
>> +static void flush_pgtable(void *addr, size_t size)
>>   {
>> -	/* FIXME: L2 cache should be taken care of if it exists */
>> -	do {
>> -		asm("mcr	p15, 0, %0, c7, c10, 1 @ flush_pgd"
>> -		    : : "r" (first));
>> -		first += L1_CACHE_BYTES / sizeof(*first);
>> -	} while (first <= last);
>> -}
>> -
>> -static void flush_iopte_range(u32 *first, u32 *last)
>> -{
>> -	/* FIXME: L2 cache should be taken care of if it exists */
>> -	do {
>> -		asm("mcr	p15, 0, %0, c7, c10, 1 @ flush_pte"
>> -		    : : "r" (first));
>> -		first += L1_CACHE_BYTES / sizeof(*first);
>> -	} while (first <= last);
>> +	clean_dcache_area(addr, size);
I remember NAKing this approach in past and my stand remains same.
The cache APIs which you are trying to use here are not suppose
to be used outside.

I think the right way to fix this is to make use of streaming APIs.
If needed, IOMMU can have its own dma_ops for special case
handling if any.

Russell, Arnd might have more ideas.

>>   }
>>
>>   static void iopte_free(u32 *iopte)
>> @@ -546,7 +531,7 @@ static u32 *iopte_alloc(struct omap_iommu *obj, u32 *iopgd, u32 da)
>>   			return ERR_PTR(-ENOMEM);
>>
>>   		*iopgd = virt_to_phys(iopte) | IOPGD_TABLE;
>> -		flush_iopgd_range(iopgd, iopgd);
>> +		flush_pgtable(iopgd, sizeof(*iopgd));
>>
>>   		dev_vdbg(obj->dev, "%s: a new pte:%p\n", __func__, iopte);
>>   	} else {
>> @@ -575,7 +560,7 @@ static int iopgd_alloc_section(struct omap_iommu *obj, u32 da, u32 pa, u32 prot)
>>   	}
>>
>>   	*iopgd = (pa & IOSECTION_MASK) | prot | IOPGD_SECTION;
>> -	flush_iopgd_range(iopgd, iopgd);
>> +	flush_pgtable(iopgd, sizeof(*iopgd));
>>   	return 0;
>>   }
>>
>> @@ -592,7 +577,7 @@ static int iopgd_alloc_super(struct omap_iommu *obj, u32 da, u32 pa, u32 prot)
>>
>>   	for (i = 0; i < 16; i++)
>>   		*(iopgd + i) = (pa & IOSUPER_MASK) | prot | IOPGD_SUPER;
>> -	flush_iopgd_range(iopgd, iopgd + 15);
>> +	flush_pgtable(iopgd, sizeof(*iopgd) * 16);
>>   	return 0;
>>   }
>>
>> @@ -605,7 +590,7 @@ static int iopte_alloc_page(struct omap_iommu *obj, u32 da, u32 pa, u32 prot)
>>   		return PTR_ERR(iopte);
>>
>>   	*iopte = (pa & IOPAGE_MASK) | prot | IOPTE_SMALL;
>> -	flush_iopte_range(iopte, iopte);
>> +	flush_pgtable(iopte, sizeof(*iopte));
>>
>>   	dev_vdbg(obj->dev, "%s: da:%08x pa:%08x pte:%p *pte:%08x\n",
>>   		 __func__, da, pa, iopte, *iopte);
>> @@ -619,18 +604,12 @@ static int iopte_alloc_large(struct omap_iommu *obj, u32 da, u32 pa, u32 prot)
>>   	u32 *iopte = iopte_alloc(obj, iopgd, da);
>>   	int i;
>>
>> -	if ((da | pa) & ~IOLARGE_MASK) {
>> -		dev_err(obj->dev, "%s: %08x:%08x should aligned on %08lx\n",
>> -			__func__, da, pa, IOLARGE_SIZE);
>> -		return -EINVAL;
>> -	}
>> -
>>   	if (IS_ERR(iopte))
>>   		return PTR_ERR(iopte);
>>
>>   	for (i = 0; i < 16; i++)
>>   		*(iopte + i) = (pa & IOLARGE_MASK) | prot | IOPTE_LARGE;
>> -	flush_iopte_range(iopte, iopte + 15);
>> +	flush_pgtable(iopte, sizeof(*iopte) * 16);
>>   	return 0;
>>   }
>>
>> @@ -733,7 +712,7 @@ static size_t iopgtable_clear_entry_core(struct omap_iommu *obj, u32 da)
>>   		}
>>   		bytes *= nent;
>>   		memset(iopte, 0, nent * sizeof(*iopte));
>> -		flush_iopte_range(iopte, iopte + (nent - 1) * sizeof(*iopte));
>> +		flush_pgtable(iopte, sizeof(*iopte) * nent);
>>
>>   		/*
>>   		 * do table walk to check if this table is necessary or not
>> @@ -755,7 +734,7 @@ static size_t iopgtable_clear_entry_core(struct omap_iommu *obj, u32 da)
>>   		bytes *= nent;
>>   	}
>>   	memset(iopgd, 0, nent * sizeof(*iopgd));
>> -	flush_iopgd_range(iopgd, iopgd + (nent - 1) * sizeof(*iopgd));
>> +	flush_pgtable(iopgd, sizeof(*iopgd) * nent);
>>   out:
>>   	return bytes;
>>   }
>> @@ -799,7 +778,7 @@ static void iopgtable_clear_entry_all(struct omap_iommu *obj)
>>   			iopte_free(iopte_offset(iopgd, 0));
>>
>>   		*iopgd = 0;
>> -		flush_iopgd_range(iopgd, iopgd);
>> +		flush_pgtable(iopgd, sizeof(*iopgd));
>>   	}
>>
>>   	flush_iotlb_all(obj);
>>
> 

--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Laurent Pinchart March 14, 2014, 4:38 p.m. UTC | #3
Hi Santosh,

On Friday 14 March 2014 12:15:11 Santosh Shilimkar wrote:
> + Russell, Arnd
> 
> On Thursday 13 March 2014 10:47 PM, Anna, Suman wrote:
> > On 03/07/2014 06:46 PM, Laurent Pinchart wrote:
> >> The page table entries must be cleaned from the cache before being
> >> accessed by the IOMMU. Instead of implementing cache management manually
> >> (and ignoring L2 cache), use clean_dcache_area() to make sure the
> >> entries are visible to the device.
> > 
> > Thanks for fixing this, this has been long pending. There have been some
> > previous attempts at this as well by Ramesh Gupta, with the last thread
> > (a long time now) being
> > http://marc.info/?t=134752035400001&r=1&w=2
> > 
> > Santosh,
> > Can you please take a look at this patch and provide your comments?
> > 
> > regards
> > Suman
> > 
> >> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> >> ---
> >> 
> >>   drivers/iommu/omap-iommu.c | 41 ++++++++++-----------------------------
> >>   1 file changed, 10 insertions(+), 31 deletions(-)
> >> 
> >> diff --git a/drivers/iommu/omap-iommu.c b/drivers/iommu/omap-iommu.c
> >> index a893eca..bb605c9 100644
> >> --- a/drivers/iommu/omap-iommu.c
> >> +++ b/drivers/iommu/omap-iommu.c
> >> @@ -500,24 +500,9 @@ EXPORT_SYMBOL_GPL(omap_foreach_iommu_device);
> >>   /*
> >>    *	H/W pagetable operations
> >>    */
> >> -static void flush_iopgd_range(u32 *first, u32 *last)
> >> +static void flush_pgtable(void *addr, size_t size)
> >>   {
> >> -	/* FIXME: L2 cache should be taken care of if it exists */
> >> -	do {
> >> -		asm("mcr	p15, 0, %0, c7, c10, 1 @ flush_pgd"
> >> -		    : : "r" (first));
> >> -		first += L1_CACHE_BYTES / sizeof(*first);
> >> -	} while (first <= last);
> >> -}
> >> -
> >> -static void flush_iopte_range(u32 *first, u32 *last)
> >> -{
> >> -	/* FIXME: L2 cache should be taken care of if it exists */
> >> -	do {
> >> -		asm("mcr	p15, 0, %0, c7, c10, 1 @ flush_pte"
> >> -		    : : "r" (first));
> >> -		first += L1_CACHE_BYTES / sizeof(*first);
> >> -	} while (first <= last);
> >> +	clean_dcache_area(addr, size);
> 
> I remember NAKing this approach in past and my stand remains same.
> The cache APIs which you are trying to use here are not suppose
> to be used outside.

Please note that the omap-iommu driver already uses clean_dcache_area(). 
That's where I got the idea :-)

> I think the right way to fix this is to make use of streaming APIs.
> If needed, IOMMU can have its own dma_ops for special case
> handling if any.

I can replace clean_dcache_area() with dma_map_page() as done by the arm-smmu 
driver. If that's fine I'll modify this patch accordingly in v2.

> Russell, Arnd might have more ideas.
> 
> >>   }
> >>   
> >>   static void iopte_free(u32 *iopte)
Arnd Bergmann March 14, 2014, 4:57 p.m. UTC | #4
On Friday 14 March 2014, Santosh Shilimkar wrote:
> I remember NAKing this approach in past and my stand remains same.
> The cache APIs which you are trying to use here are not suppose
> to be used outside.
> 
> I think the right way to fix this is to make use of streaming APIs.
> If needed, IOMMU can have its own dma_ops for special case
> handling if any.
> 
> Russell, Arnd might have more ideas.

I have a bad feeling about using the dma-mapping API within the
IOMMU code, because that driver is also used to implement the
dma-mapping API for devices attached to the IOMMU. It's possible
that it just works.

Is the IOMMU actually designed to have page tables in noncoherent
memory? I would have expected that the iopt accesses must all be
done on dma_alloc_coherent() provided memory to guarantee proper
accesses.

	Arnd
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Santosh Shilimkar March 14, 2014, 5:51 p.m. UTC | #5
On Friday 14 March 2014 12:38 PM, Laurent Pinchart wrote:
> Hi Santosh,
> 
> On Friday 14 March 2014 12:15:11 Santosh Shilimkar wrote:
>> + Russell, Arnd
>>
>> On Thursday 13 March 2014 10:47 PM, Anna, Suman wrote:
>>> On 03/07/2014 06:46 PM, Laurent Pinchart wrote:
>>>> The page table entries must be cleaned from the cache before being
>>>> accessed by the IOMMU. Instead of implementing cache management manually
>>>> (and ignoring L2 cache), use clean_dcache_area() to make sure the
>>>> entries are visible to the device.
>>>
>>> Thanks for fixing this, this has been long pending. There have been some
>>> previous attempts at this as well by Ramesh Gupta, with the last thread
>>> (a long time now) being
>>> http://marc.info/?t=134752035400001&r=1&w=2
>>>
>>> Santosh,
>>> Can you please take a look at this patch and provide your comments?
>>>
>>> regards
>>> Suman
>>>
>>>> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
>>>> ---
>>>>
>>>>   drivers/iommu/omap-iommu.c | 41 ++++++++++-----------------------------
>>>>   1 file changed, 10 insertions(+), 31 deletions(-)
>>>>
>>>> diff --git a/drivers/iommu/omap-iommu.c b/drivers/iommu/omap-iommu.c
>>>> index a893eca..bb605c9 100644
>>>> --- a/drivers/iommu/omap-iommu.c
>>>> +++ b/drivers/iommu/omap-iommu.c
>>>> @@ -500,24 +500,9 @@ EXPORT_SYMBOL_GPL(omap_foreach_iommu_device);
>>>>   /*
>>>>    *	H/W pagetable operations
>>>>    */
>>>> -static void flush_iopgd_range(u32 *first, u32 *last)
>>>> +static void flush_pgtable(void *addr, size_t size)
>>>>   {
>>>> -	/* FIXME: L2 cache should be taken care of if it exists */
>>>> -	do {
>>>> -		asm("mcr	p15, 0, %0, c7, c10, 1 @ flush_pgd"
>>>> -		    : : "r" (first));
>>>> -		first += L1_CACHE_BYTES / sizeof(*first);
>>>> -	} while (first <= last);
>>>> -}
>>>> -
>>>> -static void flush_iopte_range(u32 *first, u32 *last)
>>>> -{
>>>> -	/* FIXME: L2 cache should be taken care of if it exists */
>>>> -	do {
>>>> -		asm("mcr	p15, 0, %0, c7, c10, 1 @ flush_pte"
>>>> -		    : : "r" (first));
>>>> -		first += L1_CACHE_BYTES / sizeof(*first);
>>>> -	} while (first <= last);
>>>> +	clean_dcache_area(addr, size);
>>
>> I remember NAKing this approach in past and my stand remains same.
>> The cache APIs which you are trying to use here are not suppose
>> to be used outside.
> 
> Please note that the omap-iommu driver already uses clean_dcache_area(). 
> That's where I got the idea :-)
> 
So that fall through the cracks then ;-)

>> I think the right way to fix this is to make use of streaming APIs.
>> If needed, IOMMU can have its own dma_ops for special case
>> handling if any.
> 
> I can replace clean_dcache_area() with dma_map_page() as done by the arm-smmu 
> driver. If that's fine I'll modify this patch accordingly in v2.
> 
That will be definitely a better option than the APIs used. Those streaming
APIs will take care of L2 cache as well if present.

Regards,
Santosh

--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Santosh Shilimkar March 14, 2014, 5:59 p.m. UTC | #6
On Friday 14 March 2014 12:57 PM, Arnd Bergmann wrote:
> On Friday 14 March 2014, Santosh Shilimkar wrote:
>> I remember NAKing this approach in past and my stand remains same.
>> The cache APIs which you are trying to use here are not suppose
>> to be used outside.
>>
>> I think the right way to fix this is to make use of streaming APIs.
>> If needed, IOMMU can have its own dma_ops for special case
>> handling if any.
>>
>> Russell, Arnd might have more ideas.
> 
> I have a bad feeling about using the dma-mapping API within the
> IOMMU code, because that driver is also used to implement the
> dma-mapping API for devices attached to the IOMMU. It's possible
> that it just works.
> 
Thats a good point.

> Is the IOMMU actually designed to have page tables in noncoherent
> memory? I would have expected that the iopt accesses must all be
> done on dma_alloc_coherent() provided memory to guarantee proper
> accesses.
> 
At least the OMAP one seems to use non-coherent memory which will
need CMO.

Regards,
Santosh

--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Suman Anna March 15, 2014, 1:49 a.m. UTC | #7
Hi Santosh, Laurent, Russell, Arnd,

On 03/14/2014 12:51 PM, Santosh Shilimkar wrote:
> On Friday 14 March 2014 12:38 PM, Laurent Pinchart wrote:
>> Hi Santosh,
>>
>> On Friday 14 March 2014 12:15:11 Santosh Shilimkar wrote:
>>> + Russell, Arnd
>>>
>>> On Thursday 13 March 2014 10:47 PM, Anna, Suman wrote:
>>>> On 03/07/2014 06:46 PM, Laurent Pinchart wrote:
>>>>> The page table entries must be cleaned from the cache before being
>>>>> accessed by the IOMMU. Instead of implementing cache management manually
>>>>> (and ignoring L2 cache), use clean_dcache_area() to make sure the
>>>>> entries are visible to the device.
>>>>
>>>> Thanks for fixing this, this has been long pending. There have been some
>>>> previous attempts at this as well by Ramesh Gupta, with the last thread
>>>> (a long time now) being
>>>> http://marc.info/?t=134752035400001&r=1&w=2
>>>>
>>>> Santosh,
>>>> Can you please take a look at this patch and provide your comments?
>>>>
>>>> regards
>>>> Suman
>>>>
>>>>> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
>>>>> ---
>>>>>
>>>>>    drivers/iommu/omap-iommu.c | 41 ++++++++++-----------------------------
>>>>>    1 file changed, 10 insertions(+), 31 deletions(-)
>>>>>
>>>>> diff --git a/drivers/iommu/omap-iommu.c b/drivers/iommu/omap-iommu.c
>>>>> index a893eca..bb605c9 100644
>>>>> --- a/drivers/iommu/omap-iommu.c
>>>>> +++ b/drivers/iommu/omap-iommu.c
>>>>> @@ -500,24 +500,9 @@ EXPORT_SYMBOL_GPL(omap_foreach_iommu_device);
>>>>>    /*
>>>>>     *	H/W pagetable operations
>>>>>     */
>>>>> -static void flush_iopgd_range(u32 *first, u32 *last)
>>>>> +static void flush_pgtable(void *addr, size_t size)
>>>>>    {
>>>>> -	/* FIXME: L2 cache should be taken care of if it exists */
>>>>> -	do {
>>>>> -		asm("mcr	p15, 0, %0, c7, c10, 1 @ flush_pgd"
>>>>> -		    : : "r" (first));
>>>>> -		first += L1_CACHE_BYTES / sizeof(*first);
>>>>> -	} while (first <= last);
>>>>> -}
>>>>> -
>>>>> -static void flush_iopte_range(u32 *first, u32 *last)
>>>>> -{
>>>>> -	/* FIXME: L2 cache should be taken care of if it exists */
>>>>> -	do {
>>>>> -		asm("mcr	p15, 0, %0, c7, c10, 1 @ flush_pte"
>>>>> -		    : : "r" (first));
>>>>> -		first += L1_CACHE_BYTES / sizeof(*first);
>>>>> -	} while (first <= last);
>>>>> +	clean_dcache_area(addr, size);
>>>
>>> I remember NAKing this approach in past and my stand remains same.
>>> The cache APIs which you are trying to use here are not suppose
>>> to be used outside.

So this particular change has a long history (have to dig through to 
educate myself). I have not seen clean_dcache_area attempted before, and 
I wasn't sure myself it it can be used here. Ramesh and Fernando 
definitely did start out with dmac_flush_range and outer_flush_range 
which was definitely nacked [1].

>>
>> Please note that the omap-iommu driver already uses clean_dcache_area().
>> That's where I got the idea :-)
>>
> So that fall through the cracks then ;-)
>
>>> I think the right way to fix this is to make use of streaming APIs.
>>> If needed, IOMMU can have its own dma_ops for special case
>>> handling if any.
>>
>> I can replace clean_dcache_area() with dma_map_page() as done by the arm-smmu
>> driver. If that's fine I'll modify this patch accordingly in v2.
>>

Ramesh had also attempted to use dma_page_single() previously [2], and 
Russell has instead suggested to extend the cpu cache operations [3].
Ramesh had worked based on this suggestion and the series reached v6 [4] 
(same as link I mentioned above) and this is the last attempt on this, 
but the thread went silent.

I am wondering if that is still valid and is the right way to go, as 
this seems to be a common problem. I do see dmac_flush_range being used 
for similar purposes in msm_iommu.c and exynos-iommu.c, so looks like 
they also fell through the cracks.

Laurent,
Can you drop this patch out from v2 so that it is not clubbed with the 
small cleanup patches, and we can track this separately?

regards
Suman

[1] http://marc.info/?l=linux-omap&m=129907009019355&w=2
[2] http://marc.info/?t=130281804900005&r=1&w=2
[3] http://marc.info/?l=linux-omap&m=131310179423214&w=2
[4] http://marc.info/?t=134752035400001&r=1&w=2


--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Santosh Shilimkar March 15, 2014, 5:54 p.m. UTC | #8
On Friday 14 March 2014 09:49 PM, Suman Anna wrote:
> Hi Santosh, Laurent, Russell, Arnd,
> 
> On 03/14/2014 12:51 PM, Santosh Shilimkar wrote:
>> On Friday 14 March 2014 12:38 PM, Laurent Pinchart wrote:
>>> Hi Santosh,
>>>
>>> On Friday 14 March 2014 12:15:11 Santosh Shilimkar wrote:
>>>> + Russell, Arnd
>>>>
>>>> On Thursday 13 March 2014 10:47 PM, Anna, Suman wrote:
>>>>> On 03/07/2014 06:46 PM, Laurent Pinchart wrote:
>>>>>> The page table entries must be cleaned from the cache before being
>>>>>> accessed by the IOMMU. Instead of implementing cache management manually
>>>>>> (and ignoring L2 cache), use clean_dcache_area() to make sure the
>>>>>> entries are visible to the device.
>>>>>
>>>>> Thanks for fixing this, this has been long pending. There have been some
>>>>> previous attempts at this as well by Ramesh Gupta, with the last thread
>>>>> (a long time now) being
>>>>> http://marc.info/?t=134752035400001&r=1&w=2
>>>>>
>>>>> Santosh,
>>>>> Can you please take a look at this patch and provide your comments?
>>>>>
>>>>> regards
>>>>> Suman
>>>>>
>>>>>> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
>>>>>> ---
>>>>>>
>>>>>>    drivers/iommu/omap-iommu.c | 41 ++++++++++-----------------------------
>>>>>>    1 file changed, 10 insertions(+), 31 deletions(-)
>>>>>>
>>>>>> diff --git a/drivers/iommu/omap-iommu.c b/drivers/iommu/omap-iommu.c
>>>>>> index a893eca..bb605c9 100644
>>>>>> --- a/drivers/iommu/omap-iommu.c
>>>>>> +++ b/drivers/iommu/omap-iommu.c
>>>>>> @@ -500,24 +500,9 @@ EXPORT_SYMBOL_GPL(omap_foreach_iommu_device);
>>>>>>    /*
>>>>>>     *    H/W pagetable operations
>>>>>>     */
>>>>>> -static void flush_iopgd_range(u32 *first, u32 *last)
>>>>>> +static void flush_pgtable(void *addr, size_t size)
>>>>>>    {
>>>>>> -    /* FIXME: L2 cache should be taken care of if it exists */
>>>>>> -    do {
>>>>>> -        asm("mcr    p15, 0, %0, c7, c10, 1 @ flush_pgd"
>>>>>> -            : : "r" (first));
>>>>>> -        first += L1_CACHE_BYTES / sizeof(*first);
>>>>>> -    } while (first <= last);
>>>>>> -}
>>>>>> -
>>>>>> -static void flush_iopte_range(u32 *first, u32 *last)
>>>>>> -{
>>>>>> -    /* FIXME: L2 cache should be taken care of if it exists */
>>>>>> -    do {
>>>>>> -        asm("mcr    p15, 0, %0, c7, c10, 1 @ flush_pte"
>>>>>> -            : : "r" (first));
>>>>>> -        first += L1_CACHE_BYTES / sizeof(*first);
>>>>>> -    } while (first <= last);
>>>>>> +    clean_dcache_area(addr, size);
>>>>
>>>> I remember NAKing this approach in past and my stand remains same.
>>>> The cache APIs which you are trying to use here are not suppose
>>>> to be used outside.
> 
> So this particular change has a long history (have to dig through to educate myself). I have not seen clean_dcache_area attempted before, and I wasn't sure myself it it can be used here. Ramesh and Fernando definitely did start out with dmac_flush_range and outer_flush_range which was definitely nacked [1].
> 
OK. Please wrap the lines appropriately while replying.

>>>
>>> Please note that the omap-iommu driver already uses clean_dcache_area().
>>> That's where I got the idea :-)
>>>
>> So that fall through the cracks then ;-)
>>
>>>> I think the right way to fix this is to make use of streaming APIs.
>>>> If needed, IOMMU can have its own dma_ops for special case
>>>> handling if any.
>>>
>>> I can replace clean_dcache_area() with dma_map_page() as done by the arm-smmu
>>> driver. If that's fine I'll modify this patch accordingly in v2.
>>>
> 
> Ramesh had also attempted to use dma_page_single() previously [2], and Russell has instead suggested to extend the cpu cache operations [3].
> Ramesh had worked based on this suggestion and the series reached v6 [4] (same as link I mentioned above) and this is the last attempt on this, but the thread went silent.
> 
> I am wondering if that is still valid and is the right way to go, as this seems to be a common problem. I do see dmac_flush_range being used for similar purposes in msm_iommu.c and exynos-iommu.c, so looks like they also fell through the cracks.
> 
Thanks for the links. I think you should revive the v6 series unless and until
RMK has some other suggestion. This can also help to remove the wrong usages
from other IOMMU drivers as you pointed out.

> Laurent,
> Can you drop this patch out from v2 so that it is not clubbed with the small cleanup patches, and we can track this separately?
> 
Agree

Regards,
Santosh

> 
> [1] http://marc.info/?l=linux-omap&m=129907009019355&w=2
> [2] http://marc.info/?t=130281804900005&r=1&w=2
> [3] http://marc.info/?l=linux-omap&m=131310179423214&w=2
> [4] http://marc.info/?t=134752035400001&r=1&w=2
> 
> 

--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Suman Anna March 17, 2014, 7:16 p.m. UTC | #9
Hi Santosh,

On 03/15/2014 12:54 PM, Santosh Shilimkar wrote:
> On Friday 14 March 2014 09:49 PM, Suman Anna wrote:
>> Hi Santosh, Laurent, Russell, Arnd,
>>
>> On 03/14/2014 12:51 PM, Santosh Shilimkar wrote:
>>> On Friday 14 March 2014 12:38 PM, Laurent Pinchart wrote:
>>>> Hi Santosh,
>>>>
>>>> On Friday 14 March 2014 12:15:11 Santosh Shilimkar wrote:
>>>>> + Russell, Arnd
>>>>>
>>>>> On Thursday 13 March 2014 10:47 PM, Anna, Suman wrote:
>>>>>> On 03/07/2014 06:46 PM, Laurent Pinchart wrote:
>>>>>>> The page table entries must be cleaned from the cache before being
>>>>>>> accessed by the IOMMU. Instead of implementing cache management manually
>>>>>>> (and ignoring L2 cache), use clean_dcache_area() to make sure the
>>>>>>> entries are visible to the device.
>>>>>>
>>>>>> Thanks for fixing this, this has been long pending. There have been some
>>>>>> previous attempts at this as well by Ramesh Gupta, with the last thread
>>>>>> (a long time now) being
>>>>>> http://marc.info/?t=134752035400001&r=1&w=2
>>>>>>
>>>>>> Santosh,
>>>>>> Can you please take a look at this patch and provide your comments?
>>>>>>
>>>>>> regards
>>>>>> Suman
>>>>>>
>>>>>>> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
>>>>>>> ---
>>>>>>>
>>>>>>>     drivers/iommu/omap-iommu.c | 41 ++++++++++-----------------------------
>>>>>>>     1 file changed, 10 insertions(+), 31 deletions(-)
>>>>>>>
>>>>>>> diff --git a/drivers/iommu/omap-iommu.c b/drivers/iommu/omap-iommu.c
>>>>>>> index a893eca..bb605c9 100644
>>>>>>> --- a/drivers/iommu/omap-iommu.c
>>>>>>> +++ b/drivers/iommu/omap-iommu.c
>>>>>>> @@ -500,24 +500,9 @@ EXPORT_SYMBOL_GPL(omap_foreach_iommu_device);
>>>>>>>     /*
>>>>>>>      *    H/W pagetable operations
>>>>>>>      */
>>>>>>> -static void flush_iopgd_range(u32 *first, u32 *last)
>>>>>>> +static void flush_pgtable(void *addr, size_t size)
>>>>>>>     {
>>>>>>> -    /* FIXME: L2 cache should be taken care of if it exists */
>>>>>>> -    do {
>>>>>>> -        asm("mcr    p15, 0, %0, c7, c10, 1 @ flush_pgd"
>>>>>>> -            : : "r" (first));
>>>>>>> -        first += L1_CACHE_BYTES / sizeof(*first);
>>>>>>> -    } while (first <= last);
>>>>>>> -}
>>>>>>> -
>>>>>>> -static void flush_iopte_range(u32 *first, u32 *last)
>>>>>>> -{
>>>>>>> -    /* FIXME: L2 cache should be taken care of if it exists */
>>>>>>> -    do {
>>>>>>> -        asm("mcr    p15, 0, %0, c7, c10, 1 @ flush_pte"
>>>>>>> -            : : "r" (first));
>>>>>>> -        first += L1_CACHE_BYTES / sizeof(*first);
>>>>>>> -    } while (first <= last);
>>>>>>> +    clean_dcache_area(addr, size);
>>>>>
>>>>> I remember NAKing this approach in past and my stand remains same.
>>>>> The cache APIs which you are trying to use here are not suppose
>>>>> to be used outside.
>>
>> So this particular change has a long history (have to dig through to educate myself). I have not seen clean_dcache_area attempted before, and I wasn't sure myself it it can be used here. Ramesh and Fernando definitely did start out with dmac_flush_range and outer_flush_range which was definitely nacked [1].
>>
> OK. Please wrap the lines appropriately while replying.

Hmm, weird. I don't see this with my other responses. But sorry for
the trouble.

>
>>>>
>>>> Please note that the omap-iommu driver already uses clean_dcache_area().
>>>> That's where I got the idea :-)
>>>>
>>> So that fall through the cracks then ;-)
>>>
>>>>> I think the right way to fix this is to make use of streaming APIs.
>>>>> If needed, IOMMU can have its own dma_ops for special case
>>>>> handling if any.
>>>>
>>>> I can replace clean_dcache_area() with dma_map_page() as done by the arm-smmu
>>>> driver. If that's fine I'll modify this patch accordingly in v2.
>>>>
>>
>> Ramesh had also attempted to use dma_page_single() previously [2], and Russell has instead suggested to extend the cpu cache operations [3].
>> Ramesh had worked based on this suggestion and the series reached v6 [4] (same as link I mentioned above) and this is the last attempt on this, but the thread went silent.
>>
>> I am wondering if that is still valid and is the right way to go, as this seems to be a common problem. I do see dmac_flush_range being used for similar purposes in msm_iommu.c and exynos-iommu.c, so looks like they also fell through the cracks.
>>
> Thanks for the links. I think you should revive the v6 series unless and until
> RMK has some other suggestion. This can also help to remove the wrong usages
> from other IOMMU drivers as you pointed out.

OK, will do.

regards
Suman

>
>> Laurent,
>> Can you drop this patch out from v2 so that it is not clubbed with the small cleanup patches, and we can track this separately?
>>
> Agree
>
> Regards,
> Santosh
>
>>
>> [1] http://marc.info/?l=linux-omap&m=129907009019355&w=2
>> [2] http://marc.info/?t=130281804900005&r=1&w=2
>> [3] http://marc.info/?l=linux-omap&m=131310179423214&w=2
>> [4] http://marc.info/?t=134752035400001&r=1&w=2
>>
>>
>

--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Laurent Pinchart March 17, 2014, 10:56 p.m. UTC | #10
Hi all,

On Friday 14 March 2014 20:49:56 Suman Anna wrote:
> On 03/14/2014 12:51 PM, Santosh Shilimkar wrote:
> > On Friday 14 March 2014 12:38 PM, Laurent Pinchart wrote:
> >> On Friday 14 March 2014 12:15:11 Santosh Shilimkar wrote:
> >>> On Thursday 13 March 2014 10:47 PM, Anna, Suman wrote:
> >>>> On 03/07/2014 06:46 PM, Laurent Pinchart wrote:
> >>>>> The page table entries must be cleaned from the cache before being
> >>>>> accessed by the IOMMU. Instead of implementing cache management
> >>>>> manually (and ignoring L2 cache), use clean_dcache_area() to make sure
> >>>>> the entries are visible to the device.
> >>>> 
> >>>> Thanks for fixing this, this has been long pending. There have been
> >>>> some previous attempts at this as well by Ramesh Gupta, with the last
> >>>> thread (a long time now) being
> >>>> http://marc.info/?t=134752035400001&r=1&w=2
> >>>> 
> >>>> Santosh,
> >>>> Can you please take a look at this patch and provide your comments?
> >>>> 
> >>>> regards
> >>>> Suman
> >>>> 
> >>>>> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> >>>>> ---
> >>>>> 
> >>>>>  drivers/iommu/omap-iommu.c | 41 ++++++++++---------------------------
> >>>>>  1 file changed, 10 insertions(+), 31 deletions(-)
> >>>>> 
> >>>>> diff --git a/drivers/iommu/omap-iommu.c b/drivers/iommu/omap-iommu.c
> >>>>> index a893eca..bb605c9 100644
> >>>>> --- a/drivers/iommu/omap-iommu.c
> >>>>> +++ b/drivers/iommu/omap-iommu.c
> >>>>> @@ -500,24 +500,9 @@ EXPORT_SYMBOL_GPL(omap_foreach_iommu_device);
> >>>>>    /*
> >>>>>     *	H/W pagetable operations
> >>>>>     */
> >>>>> -static void flush_iopgd_range(u32 *first, u32 *last)
> >>>>> +static void flush_pgtable(void *addr, size_t size)
> >>>>>  {
> >>>>> -	/* FIXME: L2 cache should be taken care of if it exists */
> >>>>> -	do {
> >>>>> -		asm("mcr	p15, 0, %0, c7, c10, 1 @ flush_pgd"
> >>>>> -		    : : "r" (first));
> >>>>> -		first += L1_CACHE_BYTES / sizeof(*first);
> >>>>> -	} while (first <= last);
> >>>>> -}
> >>>>> -
> >>>>> -static void flush_iopte_range(u32 *first, u32 *last)
> >>>>> -{
> >>>>> -	/* FIXME: L2 cache should be taken care of if it exists */
> >>>>> -	do {
> >>>>> -		asm("mcr	p15, 0, %0, c7, c10, 1 @ flush_pte"
> >>>>> -		    : : "r" (first));
> >>>>> -		first += L1_CACHE_BYTES / sizeof(*first);
> >>>>> -	} while (first <= last);
> >>>>> +	clean_dcache_area(addr, size);
> >>> 
> >>> I remember NAKing this approach in past and my stand remains same.
> >>> The cache APIs which you are trying to use here are not suppose
> >>> to be used outside.
> 
> So this particular change has a long history (have to dig through to educate
> myself).

Thank you for doing so, the result is pretty informative.

> I have not seen clean_dcache_area attempted before, and I wasn't sure myself
> it it can be used here. Ramesh and Fernando definitely did start out with
> dmac_flush_range and outer_flush_range which was definitely nacked [1].
> 
> >> Please note that the omap-iommu driver already uses clean_dcache_area().
> >> That's where I got the idea :-)
> > 
> > So that fall through the cracks then ;-)
> > 
> >>> I think the right way to fix this is to make use of streaming APIs.
> >>> If needed, IOMMU can have its own dma_ops for special case
> >>> handling if any.
> >> 
> >> I can replace clean_dcache_area() with dma_map_page() as done by the
> >> arm-smmu driver. If that's fine I'll modify this patch accordingly in
> >> v2.
> 
> Ramesh had also attempted to use dma_page_single() previously [2], and
> Russell has instead suggested to extend the cpu cache operations [3].
> Ramesh had worked based on this suggestion and the series reached v6 [4]
> (same as link I mentioned above) and this is the last attempt on this,
> but the thread went silent.

I'm not sure yet whether I totally agree with Russell here, not on the 
rationale of his opinion, but on what we're trying to achieve. Isn't the IOMMU 
just a device that can perform direct memory access to fetch page table 
entries ? It seems to me that what the driver needs is to make sure that 
changes to the page tables are visible to the device when performing direct 
memory access. That doesn't really differ from other DMA use cases, so why 
would it need an IOMMU-specific API ? Or does the OMAP IOMMU fetch page table 
entries using a special kind of DMA ?

> I am wondering if that is still valid and is the right way to go, as this
> seems to be a common problem. I do see dmac_flush_range being used for
> similar purposes in msm_iommu.c and exynos-iommu.c, so looks like they also
> fell through the cracks.
> 
> Laurent,
> Can you drop this patch out from v2 so that it is not clubbed with the small
> cleanup patches, and we can track this separately?

Sure, I'll do that.

> [1] http://marc.info/?l=linux-omap&m=129907009019355&w=2
> [2] http://marc.info/?t=130281804900005&r=1&w=2
> [3] http://marc.info/?l=linux-omap&m=131310179423214&w=2
> [4] http://marc.info/?t=134752035400001&r=1&w=2
Laurent Pinchart March 17, 2014, 11:12 p.m. UTC | #11
Hi Arnd,

On Friday 14 March 2014 17:57:48 Arnd Bergmann wrote:
> On Friday 14 March 2014, Santosh Shilimkar wrote:
> > I remember NAKing this approach in past and my stand remains same. The
> > cache APIs which you are trying to use here are not suppose to be used
> > outside.
> > 
> > I think the right way to fix this is to make use of streaming APIs.
> > If needed, IOMMU can have its own dma_ops for special case handling if
> > any.
> > 
> > Russell, Arnd might have more ideas.
> 
> I have a bad feeling about using the dma-mapping API within the IOMMU code,
> because that driver is also used to implement the dma-mapping API for
> devices attached to the IOMMU. It's possible that it just works.

Right, but I hope the memory port used by the IOMMU to fetch page table 
entries will not go through itself the same IOMMU :-)

> Is the IOMMU actually designed to have page tables in noncoherent memory? I
> would have expected that the iopt accesses must all be done on
> dma_alloc_coherent() provided memory to guarantee proper accesses.

I'm not knowledgeable enough about the OMAP IOMMU, but at least the Renesas 
IOMMU doesn't need coherent memory as long as the driver makes sure that 
changes to the page tables are made visible to the device. That IOMMU can also 
use the DVM hardware coherency protocols on a cache coherent interconnect, but 
I haven't investigated that yet.
Suman Anna March 18, 2014, 1:20 a.m. UTC | #12
On 03/17/2014 06:12 PM, Laurent Pinchart wrote:
> Hi Arnd,
> 
> On Friday 14 March 2014 17:57:48 Arnd Bergmann wrote:
>> On Friday 14 March 2014, Santosh Shilimkar wrote:
>>> I remember NAKing this approach in past and my stand remains same. The
>>> cache APIs which you are trying to use here are not suppose to be used
>>> outside.
>>>
>>> I think the right way to fix this is to make use of streaming APIs.
>>> If needed, IOMMU can have its own dma_ops for special case handling if
>>> any.
>>>
>>> Russell, Arnd might have more ideas.
>>
>> I have a bad feeling about using the dma-mapping API within the IOMMU code,
>> because that driver is also used to implement the dma-mapping API for
>> devices attached to the IOMMU. It's possible that it just works.
> 
> Right, but I hope the memory port used by the IOMMU to fetch page table 
> entries will not go through itself the same IOMMU :-)
> 
>> Is the IOMMU actually designed to have page tables in noncoherent memory? I
>> would have expected that the iopt accesses must all be done on
>> dma_alloc_coherent() provided memory to guarantee proper accesses.
> 
> I'm not knowledgeable enough about the OMAP IOMMU, but at least the Renesas 
> IOMMU doesn't need coherent memory as long as the driver makes sure that 
> changes to the page tables are made visible to the device. 

That is the case with OMAP IOMMU as well, we have all along been using
non-coherent memory. Switching to coherent memory will probably simplify
things in the IOMMU driver (and eliminate this discussion on OMAP :))

regards
Suman
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" 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/drivers/iommu/omap-iommu.c b/drivers/iommu/omap-iommu.c
index a893eca..bb605c9 100644
--- a/drivers/iommu/omap-iommu.c
+++ b/drivers/iommu/omap-iommu.c
@@ -500,24 +500,9 @@  EXPORT_SYMBOL_GPL(omap_foreach_iommu_device);
 /*
  *	H/W pagetable operations
  */
-static void flush_iopgd_range(u32 *first, u32 *last)
+static void flush_pgtable(void *addr, size_t size)
 {
-	/* FIXME: L2 cache should be taken care of if it exists */
-	do {
-		asm("mcr	p15, 0, %0, c7, c10, 1 @ flush_pgd"
-		    : : "r" (first));
-		first += L1_CACHE_BYTES / sizeof(*first);
-	} while (first <= last);
-}
-
-static void flush_iopte_range(u32 *first, u32 *last)
-{
-	/* FIXME: L2 cache should be taken care of if it exists */
-	do {
-		asm("mcr	p15, 0, %0, c7, c10, 1 @ flush_pte"
-		    : : "r" (first));
-		first += L1_CACHE_BYTES / sizeof(*first);
-	} while (first <= last);
+	clean_dcache_area(addr, size);
 }
 
 static void iopte_free(u32 *iopte)
@@ -546,7 +531,7 @@  static u32 *iopte_alloc(struct omap_iommu *obj, u32 *iopgd, u32 da)
 			return ERR_PTR(-ENOMEM);
 
 		*iopgd = virt_to_phys(iopte) | IOPGD_TABLE;
-		flush_iopgd_range(iopgd, iopgd);
+		flush_pgtable(iopgd, sizeof(*iopgd));
 
 		dev_vdbg(obj->dev, "%s: a new pte:%p\n", __func__, iopte);
 	} else {
@@ -575,7 +560,7 @@  static int iopgd_alloc_section(struct omap_iommu *obj, u32 da, u32 pa, u32 prot)
 	}
 
 	*iopgd = (pa & IOSECTION_MASK) | prot | IOPGD_SECTION;
-	flush_iopgd_range(iopgd, iopgd);
+	flush_pgtable(iopgd, sizeof(*iopgd));
 	return 0;
 }
 
@@ -592,7 +577,7 @@  static int iopgd_alloc_super(struct omap_iommu *obj, u32 da, u32 pa, u32 prot)
 
 	for (i = 0; i < 16; i++)
 		*(iopgd + i) = (pa & IOSUPER_MASK) | prot | IOPGD_SUPER;
-	flush_iopgd_range(iopgd, iopgd + 15);
+	flush_pgtable(iopgd, sizeof(*iopgd) * 16);
 	return 0;
 }
 
@@ -605,7 +590,7 @@  static int iopte_alloc_page(struct omap_iommu *obj, u32 da, u32 pa, u32 prot)
 		return PTR_ERR(iopte);
 
 	*iopte = (pa & IOPAGE_MASK) | prot | IOPTE_SMALL;
-	flush_iopte_range(iopte, iopte);
+	flush_pgtable(iopte, sizeof(*iopte));
 
 	dev_vdbg(obj->dev, "%s: da:%08x pa:%08x pte:%p *pte:%08x\n",
 		 __func__, da, pa, iopte, *iopte);
@@ -619,18 +604,12 @@  static int iopte_alloc_large(struct omap_iommu *obj, u32 da, u32 pa, u32 prot)
 	u32 *iopte = iopte_alloc(obj, iopgd, da);
 	int i;
 
-	if ((da | pa) & ~IOLARGE_MASK) {
-		dev_err(obj->dev, "%s: %08x:%08x should aligned on %08lx\n",
-			__func__, da, pa, IOLARGE_SIZE);
-		return -EINVAL;
-	}
-
 	if (IS_ERR(iopte))
 		return PTR_ERR(iopte);
 
 	for (i = 0; i < 16; i++)
 		*(iopte + i) = (pa & IOLARGE_MASK) | prot | IOPTE_LARGE;
-	flush_iopte_range(iopte, iopte + 15);
+	flush_pgtable(iopte, sizeof(*iopte) * 16);
 	return 0;
 }
 
@@ -733,7 +712,7 @@  static size_t iopgtable_clear_entry_core(struct omap_iommu *obj, u32 da)
 		}
 		bytes *= nent;
 		memset(iopte, 0, nent * sizeof(*iopte));
-		flush_iopte_range(iopte, iopte + (nent - 1) * sizeof(*iopte));
+		flush_pgtable(iopte, sizeof(*iopte) * nent);
 
 		/*
 		 * do table walk to check if this table is necessary or not
@@ -755,7 +734,7 @@  static size_t iopgtable_clear_entry_core(struct omap_iommu *obj, u32 da)
 		bytes *= nent;
 	}
 	memset(iopgd, 0, nent * sizeof(*iopgd));
-	flush_iopgd_range(iopgd, iopgd + (nent - 1) * sizeof(*iopgd));
+	flush_pgtable(iopgd, sizeof(*iopgd) * nent);
 out:
 	return bytes;
 }
@@ -799,7 +778,7 @@  static void iopgtable_clear_entry_all(struct omap_iommu *obj)
 			iopte_free(iopte_offset(iopgd, 0));
 
 		*iopgd = 0;
-		flush_iopgd_range(iopgd, iopgd);
+		flush_pgtable(iopgd, sizeof(*iopgd));
 	}
 
 	flush_iotlb_all(obj);