diff mbox

[v3,5/7] ARM: dma: Use dma_pfn_offset for dma address translation

Message ID 1398353407-2345-6-git-send-email-santosh.shilimkar@ti.com
State New
Headers show

Commit Message

Santosh Shilimkar April 24, 2014, 3:30 p.m. UTC
From: Grygorii Strashko <grygorii.strashko@ti.com>

In most of cases DMA addresses can be performed using offset value of
 Bus address space relatively to physical address space as following:

PFN->DMA:
 __pfn_to_phys(pfn + [-]dma_pfn_offset)

DMA->PFN:
 __phys_to_pfn(dma_addr) + [-]dma_pfn_offset

Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Russell King <linux@arm.linux.org.uk>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Olof Johansson <olof@lixom.net>
Cc: Grant Likely <grant.likely@linaro.org>
Cc: Rob Herring <robh+dt@kernel.org>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com>
Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
---
 arch/arm/include/asm/dma-mapping.h |   21 +++++++++++++++++----
 1 file changed, 17 insertions(+), 4 deletions(-)

Comments

Rob Herring May 2, 2014, 2:32 p.m. UTC | #1
On Thu, Apr 24, 2014 at 10:30 AM, Santosh Shilimkar
<santosh.shilimkar@ti.com> wrote:
> From: Grygorii Strashko <grygorii.strashko@ti.com>
>
> In most of cases DMA addresses can be performed using offset value of
>  Bus address space relatively to physical address space as following:
>
> PFN->DMA:
>  __pfn_to_phys(pfn + [-]dma_pfn_offset)
>
> DMA->PFN:
>  __phys_to_pfn(dma_addr) + [-]dma_pfn_offset
>
> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> Cc: Russell King <linux@arm.linux.org.uk>
> Cc: Arnd Bergmann <arnd@arndb.de>
> Cc: Olof Johansson <olof@lixom.net>
> Cc: Grant Likely <grant.likely@linaro.org>
> Cc: Rob Herring <robh+dt@kernel.org>
> Cc: Catalin Marinas <catalin.marinas@arm.com>
> Cc: Linus Walleij <linus.walleij@linaro.org>
> Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com>
> Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>

Reviewed-by: Rob Herring <robh@kernel.org>

> ---
>  arch/arm/include/asm/dma-mapping.h |   21 +++++++++++++++++----
>  1 file changed, 17 insertions(+), 4 deletions(-)
>
> diff --git a/arch/arm/include/asm/dma-mapping.h b/arch/arm/include/asm/dma-mapping.h
> index e701a4d..424fda9 100644
> --- a/arch/arm/include/asm/dma-mapping.h
> +++ b/arch/arm/include/asm/dma-mapping.h
> @@ -58,22 +58,35 @@ static inline int dma_set_mask(struct device *dev, u64 mask)
>  #ifndef __arch_pfn_to_dma
>  static inline dma_addr_t pfn_to_dma(struct device *dev, unsigned long pfn)
>  {
> -       return (dma_addr_t)__pfn_to_bus(pfn);
> +       if (!dev)
> +               return (dma_addr_t)__pfn_to_bus(pfn);
> +       else
> +               return (dma_addr_t)__pfn_to_bus(pfn - dev->dma_pfn_offset);
>  }
>
>  static inline unsigned long dma_to_pfn(struct device *dev, dma_addr_t addr)
>  {
> -       return __bus_to_pfn(addr);
> +       if (!dev)
> +               return __bus_to_pfn(addr);
> +       else
> +               return __bus_to_pfn(addr) + dev->dma_pfn_offset;
>  }
>
>  static inline void *dma_to_virt(struct device *dev, dma_addr_t addr)
>  {
> -       return (void *)__bus_to_virt((unsigned long)addr);
> +       if (!dev)
> +               return (void *)__bus_to_virt((unsigned long)addr);
> +       else
> +               return (void *)__bus_to_virt(__pfn_to_bus(dma_to_pfn(dev, addr)));
>  }
>
>  static inline dma_addr_t virt_to_dma(struct device *dev, void *addr)
>  {
> -       return (dma_addr_t)__virt_to_bus((unsigned long)(addr));
> +       if (!dev)
> +               return (dma_addr_t)__virt_to_bus((unsigned long)(addr));
> +       else
> +               return pfn_to_dma(dev,
> +                               __bus_to_pfn(__virt_to_bus((unsigned long)(addr))));
>  }
>
>  #else
> --
> 1.7.9.5
>
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Russell King - ARM Linux May 2, 2014, 2:58 p.m. UTC | #2
On Thu, Apr 24, 2014 at 11:30:05AM -0400, Santosh Shilimkar wrote:
> diff --git a/arch/arm/include/asm/dma-mapping.h b/arch/arm/include/asm/dma-mapping.h
> index e701a4d..424fda9 100644
> --- a/arch/arm/include/asm/dma-mapping.h
> +++ b/arch/arm/include/asm/dma-mapping.h
> @@ -58,22 +58,35 @@ static inline int dma_set_mask(struct device *dev, u64 mask)
>  #ifndef __arch_pfn_to_dma
>  static inline dma_addr_t pfn_to_dma(struct device *dev, unsigned long pfn)
>  {
> -	return (dma_addr_t)__pfn_to_bus(pfn);
> +	if (!dev)
> +		return (dma_addr_t)__pfn_to_bus(pfn);
> +	else
> +		return (dma_addr_t)__pfn_to_bus(pfn - dev->dma_pfn_offset);

I really don't trust gcc to do this right, so I think it would be better
to make life easier on the compiler:

	if (dev)
		pfn -= dev->dma_pfn_offset;
	return (dma_addr_t)__pfn_to_bus(pfn);

>  static inline unsigned long dma_to_pfn(struct device *dev, dma_addr_t addr)
>  {
> -	return __bus_to_pfn(addr);
> +	if (!dev)
> +		return __bus_to_pfn(addr);
> +	else
> +		return __bus_to_pfn(addr) + dev->dma_pfn_offset;

and:

	unsigned long pfn = __bus_to_pfn(addr);

	if (dev)
		pfn += dev->dma_pfn_offset;

	return pfn;

>  }
>  
>  static inline void *dma_to_virt(struct device *dev, dma_addr_t addr)
>  {
> -	return (void *)__bus_to_virt((unsigned long)addr);
> +	if (!dev)
> +		return (void *)__bus_to_virt((unsigned long)addr);
> +	else
> +		return (void *)__bus_to_virt(__pfn_to_bus(dma_to_pfn(dev, addr)));

This is quite horrendous.  There's easier ways to do this...  I assume
you haven't looked at the assembler resulting from this at all with
stuff like the p2v patching enabled?

>  }
>  
>  static inline dma_addr_t virt_to_dma(struct device *dev, void *addr)
>  {
> -	return (dma_addr_t)__virt_to_bus((unsigned long)(addr));
> +	if (!dev)
> +		return (dma_addr_t)__virt_to_bus((unsigned long)(addr));
> +	else
> +		return pfn_to_dma(dev,
> +				__bus_to_pfn(__virt_to_bus((unsigned long)(addr))));

Same here.
Santosh Shilimkar May 2, 2014, 3:05 p.m. UTC | #3
On Friday 02 May 2014 10:58 AM, Russell King - ARM Linux wrote:
> On Thu, Apr 24, 2014 at 11:30:05AM -0400, Santosh Shilimkar wrote:
>> diff --git a/arch/arm/include/asm/dma-mapping.h b/arch/arm/include/asm/dma-mapping.h
>> index e701a4d..424fda9 100644
>> --- a/arch/arm/include/asm/dma-mapping.h
>> +++ b/arch/arm/include/asm/dma-mapping.h
>> @@ -58,22 +58,35 @@ static inline int dma_set_mask(struct device *dev, u64 mask)
>>  #ifndef __arch_pfn_to_dma
>>  static inline dma_addr_t pfn_to_dma(struct device *dev, unsigned long pfn)
>>  {
>> -	return (dma_addr_t)__pfn_to_bus(pfn);
>> +	if (!dev)
>> +		return (dma_addr_t)__pfn_to_bus(pfn);
>> +	else
>> +		return (dma_addr_t)__pfn_to_bus(pfn - dev->dma_pfn_offset);
> 
> I really don't trust gcc to do this right, so I think it would be better
> to make life easier on the compiler:
> 
> 	if (dev)
> 		pfn -= dev->dma_pfn_offset;
> 	return (dma_addr_t)__pfn_to_bus(pfn);
> 
This looks better. Will udpate with above.

>>  static inline unsigned long dma_to_pfn(struct device *dev, dma_addr_t addr)
>>  {
>> -	return __bus_to_pfn(addr);
>> +	if (!dev)
>> +		return __bus_to_pfn(addr);
>> +	else
>> +		return __bus_to_pfn(addr) + dev->dma_pfn_offset;
> 
> and:
> 
> 	unsigned long pfn = __bus_to_pfn(addr);
> 
> 	if (dev)
> 		pfn += dev->dma_pfn_offset;
> 
> 	return pfn;
> 
Ok..

>>  }
>>  
>>  static inline void *dma_to_virt(struct device *dev, dma_addr_t addr)
>>  {
>> -	return (void *)__bus_to_virt((unsigned long)addr);
>> +	if (!dev)
>> +		return (void *)__bus_to_virt((unsigned long)addr);
>> +	else
>> +		return (void *)__bus_to_virt(__pfn_to_bus(dma_to_pfn(dev, addr)));
> 
> This is quite horrendous.  There's easier ways to do this...  I assume
> you haven't looked at the assembler resulting from this at all with
> stuff like the p2v patching enabled?
> 
I haven't. Will check.

>>  }
>>  
>>  static inline dma_addr_t virt_to_dma(struct device *dev, void *addr)
>>  {
>> -	return (dma_addr_t)__virt_to_bus((unsigned long)(addr));
>> +	if (!dev)
>> +		return (dma_addr_t)__virt_to_bus((unsigned long)(addr));
>> +	else
>> +		return pfn_to_dma(dev,
>> +				__bus_to_pfn(__virt_to_bus((unsigned long)(addr))));
> 
> Same here.
> 
ok.

Thanks !!

Regards,
Santosh
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/
Russell King - ARM Linux May 5, 2014, 7:50 p.m. UTC | #4
On Fri, May 02, 2014 at 11:05:16AM -0400, Santosh Shilimkar wrote:
> On Friday 02 May 2014 10:58 AM, Russell King - ARM Linux wrote:
> > On Thu, Apr 24, 2014 at 11:30:05AM -0400, Santosh Shilimkar wrote:
> >>  static inline void *dma_to_virt(struct device *dev, dma_addr_t addr)
> >>  {
> >> -	return (void *)__bus_to_virt((unsigned long)addr);
> >> +	if (!dev)
> >> +		return (void *)__bus_to_virt((unsigned long)addr);
> >> +	else
> >> +		return (void *)__bus_to_virt(__pfn_to_bus(dma_to_pfn(dev, addr)));
> > 
> > This is quite horrendous.  There's easier ways to do this...  I assume
> > you haven't looked at the assembler resulting from this at all with
> > stuff like the p2v patching enabled?
> > 
> I haven't. Will check.

	if (dev) {
		unsigned long pfn = dma_to_pfn(dev, addr);

		return phys_to_virt(__pfn_to_phys(pfn));
	}

	return (void *)__bus_to_virt((unsigned long)addr);

> >>  static inline dma_addr_t virt_to_dma(struct device *dev, void *addr)
> >>  {
> >> -	return (dma_addr_t)__virt_to_bus((unsigned long)(addr));
> >> +	if (!dev)
> >> +		return (dma_addr_t)__virt_to_bus((unsigned long)(addr));
> >> +	else
> >> +		return pfn_to_dma(dev,
> >> +				__bus_to_pfn(__virt_to_bus((unsigned long)(addr))));
> > 
> > Same here.
> > 
> ok.


	if (dev)
		return pfn_to_dma(dev, virt_to_pfn(addr));

	return (dma_addr_t)__virt_to_bus((unsigned long)(addr));
diff mbox

Patch

diff --git a/arch/arm/include/asm/dma-mapping.h b/arch/arm/include/asm/dma-mapping.h
index e701a4d..424fda9 100644
--- a/arch/arm/include/asm/dma-mapping.h
+++ b/arch/arm/include/asm/dma-mapping.h
@@ -58,22 +58,35 @@  static inline int dma_set_mask(struct device *dev, u64 mask)
 #ifndef __arch_pfn_to_dma
 static inline dma_addr_t pfn_to_dma(struct device *dev, unsigned long pfn)
 {
-	return (dma_addr_t)__pfn_to_bus(pfn);
+	if (!dev)
+		return (dma_addr_t)__pfn_to_bus(pfn);
+	else
+		return (dma_addr_t)__pfn_to_bus(pfn - dev->dma_pfn_offset);
 }
 
 static inline unsigned long dma_to_pfn(struct device *dev, dma_addr_t addr)
 {
-	return __bus_to_pfn(addr);
+	if (!dev)
+		return __bus_to_pfn(addr);
+	else
+		return __bus_to_pfn(addr) + dev->dma_pfn_offset;
 }
 
 static inline void *dma_to_virt(struct device *dev, dma_addr_t addr)
 {
-	return (void *)__bus_to_virt((unsigned long)addr);
+	if (!dev)
+		return (void *)__bus_to_virt((unsigned long)addr);
+	else
+		return (void *)__bus_to_virt(__pfn_to_bus(dma_to_pfn(dev, addr)));
 }
 
 static inline dma_addr_t virt_to_dma(struct device *dev, void *addr)
 {
-	return (dma_addr_t)__virt_to_bus((unsigned long)(addr));
+	if (!dev)
+		return (dma_addr_t)__virt_to_bus((unsigned long)(addr));
+	else
+		return pfn_to_dma(dev,
+				__bus_to_pfn(__virt_to_bus((unsigned long)(addr))));
 }
 
 #else