diff mbox

[Xen-devel] swiotlb-xen question

Message ID alpine.DEB.2.02.1403261741110.2747@kaball.uk.xensource.com
State New
Headers show

Commit Message

Stefano Stabellini March 26, 2014, 6:49 p.m. UTC
On Wed, 26 Mar 2014, Oleksandr Dmytryshyn wrote:
> On Wed, Mar 26, 2014 at 4:46 PM, Konrad Rzeszutek Wilk
> <konrad.wilk@oracle.com> wrote:
> > On Wed, Mar 26, 2014 at 12:35:12PM +0200, Oleksandr Dmytryshyn wrote:
> >> Hi to all.
> >>
> >> Currently I'm using hypervisor on ARM Cortex A15 processor (DRA7xx
> >> Jacinto 6 processor). I'm using mainline xen 4.4 with some patches on
> >> top plus dom0 and domU linux kernel 3.8.
> >>
> >> I've written a hack to make a camera working on my board in dom0
> >> (drivers for camera and display system are in dom0). An user-space
> >> application in dom0 is used to test camera (it reads camera captured
> >> data and sends it to the framebuffer). In the kernel code I've implemented
> >> .mmap callback function in the swiotlb-xen.c file (like xen_swiotlb_mmap())
> >> and copied to this new callback all content from the original function
> >> 'arm_dma_mmap()' from the kernel. This function creates userspace
> >> mapping for the DMA-coherent memory. With this hack camera is working
> >> (I can see captured video on display).
> >
> > Why can't you use the v4l API? Won't that work?
> >
> Currently we are using v4l api. swiotlb-xen doesnt have mmap callback
> implemented,
> so kernel use standard function dma_common_mmap() to map memory. But this
> function doesn't work correctly. We've also tried to use arm_dma_mmap() function
> instead of the dma_common_mmap() (HACK in the file
> include/asm-generic/dma-mapping-common.h only for dom0) and all is working
> in this case.

This is not a Xen specific issue.
In fact unless some of the dma pages involved could be foreign guest
pages (for example because you have a PV framebuffer frontend in a guest
sharing pages with a framebuffer backend in Dom0, and these pages are
used directly in your camera driver), swiotlb-xen shouldn't even be
involved.

The problem is that on ARM, when you call virt_to_phys on a virtual
address returned by dma_alloc_from_coherent, it doesn't return the right
physical address.
For example:

virt_address = dma_alloc_from_coherent(dev, size, dma_addr, &ret);
virt_to_phys(virt_address) != dma_addr

The issue is not that bus addresses are different from physical
addresses. The problem is that the virtual address is an ioremap address
therefore virt_to_phys and virt_to_page don't work as expected.

To fix your problem you can simply:


however that would cause problems on architectures for which bus
addresses are different from physical addresses.
Alternatively you could:

+	unsigned long pfn = bus_to_phys(dma_addr) >> PAGE_SHIFT;

however bus_to_phys is not defined on all architectures.
I am not sure what is the best way to fix this in common code such us
drivers/base/dma-mapping.c.

Comments

Konrad Rzeszutek Wilk March 26, 2014, 7:44 p.m. UTC | #1
On Wed, Mar 26, 2014 at 06:49:57PM +0000, Stefano Stabellini wrote:
> On Wed, 26 Mar 2014, Oleksandr Dmytryshyn wrote:
> > On Wed, Mar 26, 2014 at 4:46 PM, Konrad Rzeszutek Wilk
> > <konrad.wilk@oracle.com> wrote:
> > > On Wed, Mar 26, 2014 at 12:35:12PM +0200, Oleksandr Dmytryshyn wrote:
> > >> Hi to all.
> > >>
> > >> Currently I'm using hypervisor on ARM Cortex A15 processor (DRA7xx
> > >> Jacinto 6 processor). I'm using mainline xen 4.4 with some patches on
> > >> top plus dom0 and domU linux kernel 3.8.
> > >>
> > >> I've written a hack to make a camera working on my board in dom0
> > >> (drivers for camera and display system are in dom0). An user-space
> > >> application in dom0 is used to test camera (it reads camera captured
> > >> data and sends it to the framebuffer). In the kernel code I've implemented
> > >> .mmap callback function in the swiotlb-xen.c file (like xen_swiotlb_mmap())
> > >> and copied to this new callback all content from the original function
> > >> 'arm_dma_mmap()' from the kernel. This function creates userspace
> > >> mapping for the DMA-coherent memory. With this hack camera is working
> > >> (I can see captured video on display).
> > >
> > > Why can't you use the v4l API? Won't that work?
> > >
> > Currently we are using v4l api. swiotlb-xen doesnt have mmap callback
> > implemented,
> > so kernel use standard function dma_common_mmap() to map memory. But this
> > function doesn't work correctly. We've also tried to use arm_dma_mmap() function
> > instead of the dma_common_mmap() (HACK in the file
> > include/asm-generic/dma-mapping-common.h only for dom0) and all is working
> > in this case.
> 
> This is not a Xen specific issue.
> In fact unless some of the dma pages involved could be foreign guest
> pages (for example because you have a PV framebuffer frontend in a guest
> sharing pages with a framebuffer backend in Dom0, and these pages are
> used directly in your camera driver), swiotlb-xen shouldn't even be
> involved.
> 
> The problem is that on ARM, when you call virt_to_phys on a virtual
> address returned by dma_alloc_from_coherent, it doesn't return the right
> physical address.
> For example:
> 
> virt_address = dma_alloc_from_coherent(dev, size, dma_addr, &ret);
> virt_to_phys(virt_address) != dma_addr
> 
> The issue is not that bus addresses are different from physical
> addresses. The problem is that the virtual address is an ioremap address
> therefore virt_to_phys and virt_to_page don't work as expected.
> 
> To fix your problem you can simply:
> 
> diff --git a/drivers/base/dma-mapping.c b/drivers/base/dma-mapping.c
> index 0ce39a3..052a5ed 100644
> --- a/drivers/base/dma-mapping.c
> +++ b/drivers/base/dma-mapping.c
> @@ -248,7 +248,7 @@ int dma_common_mmap(struct device *dev, struct vm_area_struct *vma,
>  #ifdef CONFIG_MMU
>  	unsigned long user_count = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
>  	unsigned long count = PAGE_ALIGN(size) >> PAGE_SHIFT;
> -	unsigned long pfn = page_to_pfn(virt_to_page(cpu_addr));
> +	unsigned long pfn = dma_addr >> PAGE_SHIFT;
>  	unsigned long off = vma->vm_pgoff;
>  
>  	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
> 
> however that would cause problems on architectures for which bus
> addresses are different from physical addresses.
> Alternatively you could:
> 
> +	unsigned long pfn = bus_to_phys(dma_addr) >> PAGE_SHIFT;
> 
> however bus_to_phys is not defined on all architectures.
> I am not sure what is the best way to fix this in common code such us
> drivers/base/dma-mapping.c.

Ugh. Usually drivers have an 'dma_addr_t[]' array to go along with the
virtual addresses (or the array of the 'struct page'.). That way they
have both the CPU and the bus addresses for the same region.

Could that be used here?
Oleksandr Dmytryshyn March 27, 2014, 10:11 a.m. UTC | #2
Hi, Stefano.

Thank You for advice.

I'll try this few days later.

Oleksandr Dmytryshyn | Product Engineering and Development
GlobalLogic
M +38.067.382.2525
www.globallogic.com

http://www.globallogic.com/email_disclaimer.txt


On Wed, Mar 26, 2014 at 8:49 PM, Stefano Stabellini
<stefano.stabellini@eu.citrix.com> wrote:
> On Wed, 26 Mar 2014, Oleksandr Dmytryshyn wrote:
>> On Wed, Mar 26, 2014 at 4:46 PM, Konrad Rzeszutek Wilk
>> <konrad.wilk@oracle.com> wrote:
>> > On Wed, Mar 26, 2014 at 12:35:12PM +0200, Oleksandr Dmytryshyn wrote:
>> >> Hi to all.
>> >>
>> >> Currently I'm using hypervisor on ARM Cortex A15 processor (DRA7xx
>> >> Jacinto 6 processor). I'm using mainline xen 4.4 with some patches on
>> >> top plus dom0 and domU linux kernel 3.8.
>> >>
>> >> I've written a hack to make a camera working on my board in dom0
>> >> (drivers for camera and display system are in dom0). An user-space
>> >> application in dom0 is used to test camera (it reads camera captured
>> >> data and sends it to the framebuffer). In the kernel code I've implemented
>> >> .mmap callback function in the swiotlb-xen.c file (like xen_swiotlb_mmap())
>> >> and copied to this new callback all content from the original function
>> >> 'arm_dma_mmap()' from the kernel. This function creates userspace
>> >> mapping for the DMA-coherent memory. With this hack camera is working
>> >> (I can see captured video on display).
>> >
>> > Why can't you use the v4l API? Won't that work?
>> >
>> Currently we are using v4l api. swiotlb-xen doesnt have mmap callback
>> implemented,
>> so kernel use standard function dma_common_mmap() to map memory. But this
>> function doesn't work correctly. We've also tried to use arm_dma_mmap() function
>> instead of the dma_common_mmap() (HACK in the file
>> include/asm-generic/dma-mapping-common.h only for dom0) and all is working
>> in this case.
>
> This is not a Xen specific issue.
> In fact unless some of the dma pages involved could be foreign guest
> pages (for example because you have a PV framebuffer frontend in a guest
> sharing pages with a framebuffer backend in Dom0, and these pages are
> used directly in your camera driver), swiotlb-xen shouldn't even be
> involved.
>
> The problem is that on ARM, when you call virt_to_phys on a virtual
> address returned by dma_alloc_from_coherent, it doesn't return the right
> physical address.
> For example:
>
> virt_address = dma_alloc_from_coherent(dev, size, dma_addr, &ret);
> virt_to_phys(virt_address) != dma_addr
>
> The issue is not that bus addresses are different from physical
> addresses. The problem is that the virtual address is an ioremap address
> therefore virt_to_phys and virt_to_page don't work as expected.
>
> To fix your problem you can simply:
>
> diff --git a/drivers/base/dma-mapping.c b/drivers/base/dma-mapping.c
> index 0ce39a3..052a5ed 100644
> --- a/drivers/base/dma-mapping.c
> +++ b/drivers/base/dma-mapping.c
> @@ -248,7 +248,7 @@ int dma_common_mmap(struct device *dev, struct vm_area_struct *vma,
>  #ifdef CONFIG_MMU
>         unsigned long user_count = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
>         unsigned long count = PAGE_ALIGN(size) >> PAGE_SHIFT;
> -       unsigned long pfn = page_to_pfn(virt_to_page(cpu_addr));
> +       unsigned long pfn = dma_addr >> PAGE_SHIFT;
>         unsigned long off = vma->vm_pgoff;
>
>         vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
>
> however that would cause problems on architectures for which bus
> addresses are different from physical addresses.
> Alternatively you could:
>
> +       unsigned long pfn = bus_to_phys(dma_addr) >> PAGE_SHIFT;
>
> however bus_to_phys is not defined on all architectures.
> I am not sure what is the best way to fix this in common code such us
> drivers/base/dma-mapping.c.
Oleksandr Dmytryshyn April 1, 2014, 2:27 p.m. UTC | #3
Hi to all. I've investigated my issue deeper.

Currently we use mmap in 2 cases: video-in (camera) and video-out (display).

In case video-out all is working because mmap callback in the video-out device
leads to the remap_pfn_range() function (this function doesn't use unimplemented
.mmap callback in the swiotlb-xen.c file).

In case video-out mmap callback in the video-in device leads to the .mmap
callback from the dma ops (unimplemented callback in the swiotlb-xen.c file)

I've investigated kernel code. We have patch from the Stefano Stabellini
(068a6e62 - arm/xen: get_dma_ops: return xen_dma_ops if we are running as
xen_initial_domain)

Before this patch the function *get_dma_ops() always returned
__generic_dma_ops()
which returned &arm_dma_ops (if archdata.dma_ops is absent). In this case
for arm architecture .mmap callback is arm_dma_mmap() function.

After this patch for domU all is the same as before this patch. But in case
dom0 kernel uses xen_dma_ops with unimplemented .mmap callback. If some
function tries to use .mmap callback in dom0 then kernel calls generic
function dma_common_mmap() which doesn't work properly.

May be some mechanism for swiotlb-xen should be implemented for unimplemented
callbacks: if callback is not implemented then right architectural callback
should be used (.mmap - arm_dma_mmap() for ARM)?

Oleksandr Dmytryshyn | Product Engineering and Development
GlobalLogic
M +38.067.382.2525
www.globallogic.com

http://www.globallogic.com/email_disclaimer.txt


On Thu, Mar 27, 2014 at 12:11 PM, Oleksandr Dmytryshyn
<oleksandr.dmytryshyn@globallogic.com> wrote:
> Hi, Stefano.
>
> Thank You for advice.
>
> I'll try this few days later.
>
> Oleksandr Dmytryshyn | Product Engineering and Development
> GlobalLogic
> M +38.067.382.2525
> www.globallogic.com
>
> http://www.globallogic.com/email_disclaimer.txt
>
>
> On Wed, Mar 26, 2014 at 8:49 PM, Stefano Stabellini
> <stefano.stabellini@eu.citrix.com> wrote:
>> On Wed, 26 Mar 2014, Oleksandr Dmytryshyn wrote:
>>> On Wed, Mar 26, 2014 at 4:46 PM, Konrad Rzeszutek Wilk
>>> <konrad.wilk@oracle.com> wrote:
>>> > On Wed, Mar 26, 2014 at 12:35:12PM +0200, Oleksandr Dmytryshyn wrote:
>>> >> Hi to all.
>>> >>
>>> >> Currently I'm using hypervisor on ARM Cortex A15 processor (DRA7xx
>>> >> Jacinto 6 processor). I'm using mainline xen 4.4 with some patches on
>>> >> top plus dom0 and domU linux kernel 3.8.
>>> >>
>>> >> I've written a hack to make a camera working on my board in dom0
>>> >> (drivers for camera and display system are in dom0). An user-space
>>> >> application in dom0 is used to test camera (it reads camera captured
>>> >> data and sends it to the framebuffer). In the kernel code I've implemented
>>> >> .mmap callback function in the swiotlb-xen.c file (like xen_swiotlb_mmap())
>>> >> and copied to this new callback all content from the original function
>>> >> 'arm_dma_mmap()' from the kernel. This function creates userspace
>>> >> mapping for the DMA-coherent memory. With this hack camera is working
>>> >> (I can see captured video on display).
>>> >
>>> > Why can't you use the v4l API? Won't that work?
>>> >
>>> Currently we are using v4l api. swiotlb-xen doesnt have mmap callback
>>> implemented,
>>> so kernel use standard function dma_common_mmap() to map memory. But this
>>> function doesn't work correctly. We've also tried to use arm_dma_mmap() function
>>> instead of the dma_common_mmap() (HACK in the file
>>> include/asm-generic/dma-mapping-common.h only for dom0) and all is working
>>> in this case.
>>
>> This is not a Xen specific issue.
>> In fact unless some of the dma pages involved could be foreign guest
>> pages (for example because you have a PV framebuffer frontend in a guest
>> sharing pages with a framebuffer backend in Dom0, and these pages are
>> used directly in your camera driver), swiotlb-xen shouldn't even be
>> involved.
>>
>> The problem is that on ARM, when you call virt_to_phys on a virtual
>> address returned by dma_alloc_from_coherent, it doesn't return the right
>> physical address.
>> For example:
>>
>> virt_address = dma_alloc_from_coherent(dev, size, dma_addr, &ret);
>> virt_to_phys(virt_address) != dma_addr
>>
>> The issue is not that bus addresses are different from physical
>> addresses. The problem is that the virtual address is an ioremap address
>> therefore virt_to_phys and virt_to_page don't work as expected.
>>
>> To fix your problem you can simply:
>>
>> diff --git a/drivers/base/dma-mapping.c b/drivers/base/dma-mapping.c
>> index 0ce39a3..052a5ed 100644
>> --- a/drivers/base/dma-mapping.c
>> +++ b/drivers/base/dma-mapping.c
>> @@ -248,7 +248,7 @@ int dma_common_mmap(struct device *dev, struct vm_area_struct *vma,
>>  #ifdef CONFIG_MMU
>>         unsigned long user_count = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
>>         unsigned long count = PAGE_ALIGN(size) >> PAGE_SHIFT;
>> -       unsigned long pfn = page_to_pfn(virt_to_page(cpu_addr));
>> +       unsigned long pfn = dma_addr >> PAGE_SHIFT;
>>         unsigned long off = vma->vm_pgoff;
>>
>>         vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
>>
>> however that would cause problems on architectures for which bus
>> addresses are different from physical addresses.
>> Alternatively you could:
>>
>> +       unsigned long pfn = bus_to_phys(dma_addr) >> PAGE_SHIFT;
>>
>> however bus_to_phys is not defined on all architectures.
>> I am not sure what is the best way to fix this in common code such us
>> drivers/base/dma-mapping.c.
Stefano Stabellini April 3, 2014, 10:51 a.m. UTC | #4
On Tue, 1 Apr 2014, Oleksandr Dmytryshyn wrote:
> Hi to all. I've investigated my issue deeper.
> 
> Currently we use mmap in 2 cases: video-in (camera) and video-out (display).
> 
> In case video-out all is working because mmap callback in the video-out device
> leads to the remap_pfn_range() function (this function doesn't use unimplemented
> .mmap callback in the swiotlb-xen.c file).
> 
> In case video-out mmap callback in the video-in device leads to the .mmap
> callback from the dma ops (unimplemented callback in the swiotlb-xen.c file)
> 
> I've investigated kernel code. We have patch from the Stefano Stabellini
> (068a6e62 - arm/xen: get_dma_ops: return xen_dma_ops if we are running as
> xen_initial_domain)
> 
> Before this patch the function *get_dma_ops() always returned
> __generic_dma_ops()
> which returned &arm_dma_ops (if archdata.dma_ops is absent). In this case
> for arm architecture .mmap callback is arm_dma_mmap() function.
> 
> After this patch for domU all is the same as before this patch. But in case
> dom0 kernel uses xen_dma_ops with unimplemented .mmap callback. If some
> function tries to use .mmap callback in dom0 then kernel calls generic
> function dma_common_mmap() which doesn't work properly.
> 
> May be some mechanism for swiotlb-xen should be implemented for unimplemented
> callbacks: if callback is not implemented then right architectural callback
> should be used (.mmap - arm_dma_mmap() for ARM)?

I understand now. Thanks for investingating!
I think that we'll have to introduce our own version of .mmap,
because dma_to_pfn doesn't work correctly on Xen on ARM.
The implementation would be something like (untested):

int xen_swiotlb_dma_mmap(struct device *dev, struct vm_area_struct *vma,
		 void *cpu_addr, dma_addr_t dma_addr, size_t size,
		 struct dma_attrs *attrs)
{
	int ret = -ENXIO;
#ifdef CONFIG_MMU
	unsigned long nr_vma_pages = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
	unsigned long nr_pages = PAGE_ALIGN(size) >> PAGE_SHIFT;
	unsigned long pfn = PFN_DOWN(xen_bus_to_phys(dev, dma_addr));
	unsigned long off = vma->vm_pgoff;

	vma->vm_page_prot = __get_dma_pgprot(attrs, vma->vm_page_prot);

	if (dma_mmap_from_coherent(dev, vma, cpu_addr, size, &ret))
		return ret;

	if (off < nr_pages && nr_vma_pages <= (nr_pages - off)) {
		ret = remap_pfn_range(vma, vma->vm_start,
				      pfn + off,
				      vma->vm_end - vma->vm_start,
				      vma->vm_page_prot);
	}
#endif	/* CONFIG_MMU */

	return ret;
}

then we can add the function to xen_swiotlb_dma_ops.
Would you be up for coming up with a proper patch?
Stefano Stabellini April 3, 2014, 12:52 p.m. UTC | #5
On Thu, 3 Apr 2014, Oleksandr Dmytryshyn wrote:
> Hi, Stefano.
> 
> Thank You for advice!
> I see that You just copied the content from the original function arm_dma_mmap()
> to the swiotlb-xen driver.

I did not :-)
I changed the function used to translate from dma addresses to pfn from
dma_to_pfn to xen_bus_to_phys.


> I've tested the same solution (except that I've copied __get_dma_pgprot()
> function to the swiotlb-xen.c file too because this function is static in the
> original file). This solution is working (I've tested it). But there is
> an easier solution:
> 
> diff --git a/arch/arm/xen/mm.c b/arch/arm/xen/mm.c
> index b0e77de..f3e820f 100644
> --- a/arch/arm/xen/mm.c
> +++ b/arch/arm/xen/mm.c
> @@ -48,6 +48,7 @@ static struct dma_map_ops xen_swiotlb_dma_ops = {
>   .sync_sg_for_device = xen_swiotlb_sync_sg_for_device,
>   .map_sg = xen_swiotlb_map_sg_attrs,
>   .unmap_sg = xen_swiotlb_unmap_sg_attrs,
> + .mmap = arm_dma_mmap,
>   .map_page = xen_swiotlb_map_page,
>   .unmap_page = xen_swiotlb_unmap_page,
>   .dma_supported = xen_swiotlb_dma_supported,
> 
> The original arm_dma_mmap() function is implemented in the file
> arch/arm/mm/dma-mapping.c which always is compiled for arm arhitecture.
> I've checked this solution too. It is working.
> 
> I have a question. Is my solution correct?

No, because if any foreign pages are involved the physical address
corresponding to the dma address would not be the one returned by
dma_to_pfn. We need to call xen_bus_to_phys.


> Oleksandr Dmytryshyn | Product Engineering and Development
> GlobalLogic
> M +38.067.382.2525
> www.globallogic.com
> 
> http://www.globallogic.com/email_disclaimer.txt
> 
> 
> On Thu, Apr 3, 2014 at 1:51 PM, Stefano Stabellini
> <stefano.stabellini@eu.citrix.com> wrote:
> > On Tue, 1 Apr 2014, Oleksandr Dmytryshyn wrote:
> >> Hi to all. I've investigated my issue deeper.
> >>
> >> Currently we use mmap in 2 cases: video-in (camera) and video-out (display).
> >>
> >> In case video-out all is working because mmap callback in the video-out device
> >> leads to the remap_pfn_range() function (this function doesn't use unimplemented
> >> .mmap callback in the swiotlb-xen.c file).
> >>
> >> In case video-out mmap callback in the video-in device leads to the .mmap
> >> callback from the dma ops (unimplemented callback in the swiotlb-xen.c file)
> >>
> >> I've investigated kernel code. We have patch from the Stefano Stabellini
> >> (068a6e62 - arm/xen: get_dma_ops: return xen_dma_ops if we are running as
> >> xen_initial_domain)
> >>
> >> Before this patch the function *get_dma_ops() always returned
> >> __generic_dma_ops()
> >> which returned &arm_dma_ops (if archdata.dma_ops is absent). In this case
> >> for arm architecture .mmap callback is arm_dma_mmap() function.
> >>
> >> After this patch for domU all is the same as before this patch. But in case
> >> dom0 kernel uses xen_dma_ops with unimplemented .mmap callback. If some
> >> function tries to use .mmap callback in dom0 then kernel calls generic
> >> function dma_common_mmap() which doesn't work properly.
> >>
> >> May be some mechanism for swiotlb-xen should be implemented for unimplemented
> >> callbacks: if callback is not implemented then right architectural callback
> >> should be used (.mmap - arm_dma_mmap() for ARM)?
> >
> > I understand now. Thanks for investingating!
> > I think that we'll have to introduce our own version of .mmap,
> > because dma_to_pfn doesn't work correctly on Xen on ARM.
> > The implementation would be something like (untested):
> >
> > int xen_swiotlb_dma_mmap(struct device *dev, struct vm_area_struct *vma,
> >                  void *cpu_addr, dma_addr_t dma_addr, size_t size,
> >                  struct dma_attrs *attrs)
> > {
> >         int ret = -ENXIO;
> > #ifdef CONFIG_MMU
> >         unsigned long nr_vma_pages = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
> >         unsigned long nr_pages = PAGE_ALIGN(size) >> PAGE_SHIFT;
> >         unsigned long pfn = PFN_DOWN(xen_bus_to_phys(dev, dma_addr));
> >         unsigned long off = vma->vm_pgoff;
> >
> >         vma->vm_page_prot = __get_dma_pgprot(attrs, vma->vm_page_prot);
> >
> >         if (dma_mmap_from_coherent(dev, vma, cpu_addr, size, &ret))
> >                 return ret;
> >
> >         if (off < nr_pages && nr_vma_pages <= (nr_pages - off)) {
> >                 ret = remap_pfn_range(vma, vma->vm_start,
> >                                       pfn + off,
> >                                       vma->vm_end - vma->vm_start,
> >                                       vma->vm_page_prot);
> >         }
> > #endif  /* CONFIG_MMU */
> >
> >         return ret;
> > }
> >
> > then we can add the function to xen_swiotlb_dma_ops.
> > Would you be up for coming up with a proper patch?
>
Oleksandr Dmytryshyn April 3, 2014, 12:59 p.m. UTC | #6
On Thu, Apr 3, 2014 at 3:52 PM, Stefano Stabellini
<stefano.stabellini@eu.citrix.com> wrote:
> On Thu, 3 Apr 2014, Oleksandr Dmytryshyn wrote:
>> Hi, Stefano.
>>
>> Thank You for advice!
>> I see that You just copied the content from the original function arm_dma_mmap()
>> to the swiotlb-xen driver.
>
> I did not :-)
> I changed the function used to translate from dma addresses to pfn from
> dma_to_pfn to xen_bus_to_phys.
>
>
>> I've tested the same solution (except that I've copied __get_dma_pgprot()
>> function to the swiotlb-xen.c file too because this function is static in the
>> original file). This solution is working (I've tested it). But there is
>> an easier solution:
>>
>> diff --git a/arch/arm/xen/mm.c b/arch/arm/xen/mm.c
>> index b0e77de..f3e820f 100644
>> --- a/arch/arm/xen/mm.c
>> +++ b/arch/arm/xen/mm.c
>> @@ -48,6 +48,7 @@ static struct dma_map_ops xen_swiotlb_dma_ops = {
>>   .sync_sg_for_device = xen_swiotlb_sync_sg_for_device,
>>   .map_sg = xen_swiotlb_map_sg_attrs,
>>   .unmap_sg = xen_swiotlb_unmap_sg_attrs,
>> + .mmap = arm_dma_mmap,
>>   .map_page = xen_swiotlb_map_page,
>>   .unmap_page = xen_swiotlb_unmap_page,
>>   .dma_supported = xen_swiotlb_dma_supported,
>>
>> The original arm_dma_mmap() function is implemented in the file
>> arch/arm/mm/dma-mapping.c which always is compiled for arm arhitecture.
>> I've checked this solution too. It is working.
>>
>> I have a question. Is my solution correct?
>
> No, because if any foreign pages are involved the physical address
> corresponding to the dma address would not be the one returned by
> dma_to_pfn. We need to call xen_bus_to_phys.
>
>
>> Oleksandr Dmytryshyn | Product Engineering and Development
>> GlobalLogic
>> M +38.067.382.2525
>> www.globallogic.com
>>
>> http://www.globallogic.com/email_disclaimer.txt
>>
>>
>> On Thu, Apr 3, 2014 at 1:51 PM, Stefano Stabellini
>> <stefano.stabellini@eu.citrix.com> wrote:
>> > On Tue, 1 Apr 2014, Oleksandr Dmytryshyn wrote:
>> >> Hi to all. I've investigated my issue deeper.
>> >>
>> >> Currently we use mmap in 2 cases: video-in (camera) and video-out (display).
>> >>
>> >> In case video-out all is working because mmap callback in the video-out device
>> >> leads to the remap_pfn_range() function (this function doesn't use unimplemented
>> >> .mmap callback in the swiotlb-xen.c file).
>> >>
>> >> In case video-out mmap callback in the video-in device leads to the .mmap
>> >> callback from the dma ops (unimplemented callback in the swiotlb-xen.c file)
>> >>
>> >> I've investigated kernel code. We have patch from the Stefano Stabellini
>> >> (068a6e62 - arm/xen: get_dma_ops: return xen_dma_ops if we are running as
>> >> xen_initial_domain)
>> >>
>> >> Before this patch the function *get_dma_ops() always returned
>> >> __generic_dma_ops()
>> >> which returned &arm_dma_ops (if archdata.dma_ops is absent). In this case
>> >> for arm architecture .mmap callback is arm_dma_mmap() function.
>> >>
>> >> After this patch for domU all is the same as before this patch. But in case
>> >> dom0 kernel uses xen_dma_ops with unimplemented .mmap callback. If some
>> >> function tries to use .mmap callback in dom0 then kernel calls generic
>> >> function dma_common_mmap() which doesn't work properly.
>> >>
>> >> May be some mechanism for swiotlb-xen should be implemented for unimplemented
>> >> callbacks: if callback is not implemented then right architectural callback
>> >> should be used (.mmap - arm_dma_mmap() for ARM)?
>> >
>> > I understand now. Thanks for investingating!
>> > I think that we'll have to introduce our own version of .mmap,
>> > because dma_to_pfn doesn't work correctly on Xen on ARM.
>> > The implementation would be something like (untested):
>> >
>> > int xen_swiotlb_dma_mmap(struct device *dev, struct vm_area_struct *vma,
>> >                  void *cpu_addr, dma_addr_t dma_addr, size_t size,
>> >                  struct dma_attrs *attrs)
>> > {
>> >         int ret = -ENXIO;
>> > #ifdef CONFIG_MMU
>> >         unsigned long nr_vma_pages = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
>> >         unsigned long nr_pages = PAGE_ALIGN(size) >> PAGE_SHIFT;
>> >         unsigned long pfn = PFN_DOWN(xen_bus_to_phys(dev, dma_addr));
>> >         unsigned long off = vma->vm_pgoff;
>> >
>> >         vma->vm_page_prot = __get_dma_pgprot(attrs, vma->vm_page_prot);
>> >
>> >         if (dma_mmap_from_coherent(dev, vma, cpu_addr, size, &ret))
>> >                 return ret;
>> >
>> >         if (off < nr_pages && nr_vma_pages <= (nr_pages - off)) {
>> >                 ret = remap_pfn_range(vma, vma->vm_start,
>> >                                       pfn + off,
>> >                                       vma->vm_end - vma->vm_start,
>> >                                       vma->vm_page_prot);
>> >         }
>> > #endif  /* CONFIG_MMU */
>> >
>> >         return ret;
>> > }
>> >
>> > then we can add the function to xen_swiotlb_dma_ops.
>> > Would you be up for coming up with a proper patch?
>>

Hi, Stefano.

Thank You for the response.
I'll test Your solution and write about results.

Oleksandr Dmytryshyn | Product Engineering and Development
GlobalLogic
M +38.067.382.2525
www.globallogic.com

http://www.globallogic.com/email_disclaimer.txt
Stefano Stabellini April 4, 2014, 11:26 a.m. UTC | #7
On Fri, 4 Apr 2014, Oleksandr Dmytryshyn wrote:
> On Thu, Apr 3, 2014 at 1:51 PM, Stefano Stabellini
> <stefano.stabellini@eu.citrix.com> wrote:
> > On Tue, 1 Apr 2014, Oleksandr Dmytryshyn wrote:
> >> Hi to all. I've investigated my issue deeper.
> >>
> >> Currently we use mmap in 2 cases: video-in (camera) and video-out (display).
> >>
> >> In case video-out all is working because mmap callback in the video-out device
> >> leads to the remap_pfn_range() function (this function doesn't use unimplemented
> >> .mmap callback in the swiotlb-xen.c file).
> >>
> >> In case video-out mmap callback in the video-in device leads to the .mmap
> >> callback from the dma ops (unimplemented callback in the swiotlb-xen.c file)
> >>
> >> I've investigated kernel code. We have patch from the Stefano Stabellini
> >> (068a6e62 - arm/xen: get_dma_ops: return xen_dma_ops if we are running as
> >> xen_initial_domain)
> >>
> >> Before this patch the function *get_dma_ops() always returned
> >> __generic_dma_ops()
> >> which returned &arm_dma_ops (if archdata.dma_ops is absent). In this case
> >> for arm architecture .mmap callback is arm_dma_mmap() function.
> >>
> >> After this patch for domU all is the same as before this patch. But in case
> >> dom0 kernel uses xen_dma_ops with unimplemented .mmap callback. If some
> >> function tries to use .mmap callback in dom0 then kernel calls generic
> >> function dma_common_mmap() which doesn't work properly.
> >>
> >> May be some mechanism for swiotlb-xen should be implemented for unimplemented
> >> callbacks: if callback is not implemented then right architectural callback
> >> should be used (.mmap - arm_dma_mmap() for ARM)?
> >
> > I understand now. Thanks for investingating!
> > I think that we'll have to introduce our own version of .mmap,
> > because dma_to_pfn doesn't work correctly on Xen on ARM.
> > The implementation would be something like (untested):
> >
> > int xen_swiotlb_dma_mmap(struct device *dev, struct vm_area_struct *vma,
> >                  void *cpu_addr, dma_addr_t dma_addr, size_t size,
> >                  struct dma_attrs *attrs)
> > {
> >         int ret = -ENXIO;
> > #ifdef CONFIG_MMU
> >         unsigned long nr_vma_pages = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
> >         unsigned long nr_pages = PAGE_ALIGN(size) >> PAGE_SHIFT;
> >         unsigned long pfn = PFN_DOWN(xen_bus_to_phys(dev, dma_addr));
> >         unsigned long off = vma->vm_pgoff;
> >
> >         vma->vm_page_prot = __get_dma_pgprot(attrs, vma->vm_page_prot);
> >
> >         if (dma_mmap_from_coherent(dev, vma, cpu_addr, size, &ret))
> >                 return ret;
> >
> >         if (off < nr_pages && nr_vma_pages <= (nr_pages - off)) {
> >                 ret = remap_pfn_range(vma, vma->vm_start,
> >                                       pfn + off,
> >                                       vma->vm_end - vma->vm_start,
> >                                       vma->vm_page_prot);
> >         }
> > #endif  /* CONFIG_MMU */
> >
> >         return ret;
> > }
> >
> > then we can add the function to xen_swiotlb_dma_ops.
> > Would you be up for coming up with a proper patch?
> 
> Hi, Stefano.
> 
> Here is a slightly modified solution from You (I've only replaced a
> __get_dma_pgprot() function with its original implementation):

Looks fine.
Could you resend to the list as a proper patch and with a signed-off-by
line? Otherwise I can do it.


> diff --git a/arch/arm/xen/mm.c b/arch/arm/xen/mm.c
> index b0e77de..91408b1 100644
> --- a/arch/arm/xen/mm.c
> +++ b/arch/arm/xen/mm.c
> @@ -48,6 +48,7 @@ static struct dma_map_ops xen_swiotlb_dma_ops = {
>   .sync_sg_for_device = xen_swiotlb_sync_sg_for_device,
>   .map_sg = xen_swiotlb_map_sg_attrs,
>   .unmap_sg = xen_swiotlb_unmap_sg_attrs,
> + .mmap = xen_swiotlb_dma_mmap,
>   .map_page = xen_swiotlb_map_page,
>   .unmap_page = xen_swiotlb_unmap_page,
>   .dma_supported = xen_swiotlb_dma_supported,
> diff --git a/drivers/xen/swiotlb-xen.c b/drivers/xen/swiotlb-xen.c
> index 5403855..acf0c06 100644
> --- a/drivers/xen/swiotlb-xen.c
> +++ b/drivers/xen/swiotlb-xen.c
> @@ -407,6 +407,42 @@ dma_addr_t xen_swiotlb_map_page(struct device
> *dev, struct page *page,
>  EXPORT_SYMBOL_GPL(xen_swiotlb_map_page);
> 
>  /*
> + * Create userspace mapping for the DMA-coherent memory.
> + */
> +int xen_swiotlb_dma_mmap(struct device *dev, struct vm_area_struct *vma,
> + void *cpu_addr, dma_addr_t dma_addr, size_t size,
> + struct dma_attrs *attrs)
> +{
> + int ret = -ENXIO;
> +#ifdef CONFIG_MMU
> + unsigned long nr_vma_pages = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
> + unsigned long nr_pages = PAGE_ALIGN(size) >> PAGE_SHIFT;
> + unsigned long pfn = PFN_DOWN(xen_bus_to_phys(dma_addr));
> + unsigned long off = vma->vm_pgoff;
> + pgprot_t prot = vma->vm_page_prot;
> +
> + prot = dma_get_attr(DMA_ATTR_WRITE_COMBINE, attrs) ?
> +    pgprot_writecombine(prot) :
> +    pgprot_dmacoherent(prot);
> +
> + vma->vm_page_prot = prot;
> +
> + if (dma_mmap_from_coherent(dev, vma, cpu_addr, size, &ret))
> + return ret;
> +
> + if (off < nr_pages && nr_vma_pages <= (nr_pages - off)) {
> + ret = remap_pfn_range(vma, vma->vm_start,
> + pfn + off,
> + vma->vm_end - vma->vm_start,
> + vma->vm_page_prot);
> + }
> +#endif  /* CONFIG_MMU */
> +
> + return ret;
> +}
> +EXPORT_SYMBOL_GPL(xen_swiotlb_dma_mmap);
> +
> +/*
>   * Unmap a single streaming mode DMA translation.  The dma_addr and size must
>   * match what was provided for in a previous xen_swiotlb_map_page call.  All
>   * other usages are undefined.
> diff --git a/include/xen/swiotlb-xen.h b/include/xen/swiotlb-xen.h
> index 7b64465..930fa94 100644
> --- a/include/xen/swiotlb-xen.h
> +++ b/include/xen/swiotlb-xen.h
> @@ -15,6 +15,11 @@ xen_swiotlb_free_coherent(struct device *hwdev, size_t size,
>    void *vaddr, dma_addr_t dma_handle,
>    struct dma_attrs *attrs);
> 
> +extern int
> +xen_swiotlb_dma_mmap(struct device *dev, struct vm_area_struct *vma,
> +     void *cpu_addr, dma_addr_t dma_addr, size_t size,
> +     struct dma_attrs *attrs);
> +
>  extern dma_addr_t xen_swiotlb_map_page(struct device *dev, struct page *page,
>         unsigned long offset, size_t size,
>         enum dma_data_direction dir,
> 
> 
> I've checked it on Xen 4.4 stable + some our architecture specific
> patches on top
> plus Dom0 and DomU Linux Kernel 3.8 on DRA7xxx based board. Camera application
> is working (I can see a captured data from the camera on my board). Can we use
> this implementation of the .mmap callback as the correct solution?
> 
> Oleksandr Dmytryshyn | Product Engineering and Development
> GlobalLogic
> M +38.067.382.2525
> www.globallogic.com
> 
> http://www.globallogic.com/email_disclaimer.txt
>
Konrad Rzeszutek Wilk April 4, 2014, 4:26 p.m. UTC | #8
On Fri, Apr 04, 2014 at 02:30:22PM +0300, Oleksandr Dmytryshyn wrote:
> >From f52bafc1ba51324ca5044df22778aacf815c59bf Mon Sep 17 00:00:00 2001
> From: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
> Date: Fri, 4 Apr 2014 12:16:27 +0300
> Subject: [PATCH] swiotlb-xen: implement xen_swiotlb_dma_mmap callback
> 
> This function creates userspace mapping for the DMA-coherent memory.
> 
> Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
> Signed-off-by: Oleksandr Dmytryshyn <oleksandr.dmytryshyn@globallogic.com>
> 
> diff --git a/arch/arm/xen/mm.c b/arch/arm/xen/mm.c
> index b0e77de..91408b1 100644
> --- a/arch/arm/xen/mm.c
> +++ b/arch/arm/xen/mm.c
> @@ -48,6 +48,7 @@ static struct dma_map_ops xen_swiotlb_dma_ops = {
>   .sync_sg_for_device = xen_swiotlb_sync_sg_for_device,
>   .map_sg = xen_swiotlb_map_sg_attrs,
>   .unmap_sg = xen_swiotlb_unmap_sg_attrs,
> + .mmap = xen_swiotlb_dma_mmap,
>   .map_page = xen_swiotlb_map_page,
>   .unmap_page = xen_swiotlb_unmap_page,
>   .dma_supported = xen_swiotlb_dma_supported,
> diff --git a/drivers/xen/swiotlb-xen.c b/drivers/xen/swiotlb-xen.c
> index 5403855..acf0c06 100644
> --- a/drivers/xen/swiotlb-xen.c
> +++ b/drivers/xen/swiotlb-xen.c
> @@ -407,6 +407,42 @@ dma_addr_t xen_swiotlb_map_page(struct device
> *dev, struct page *page,
>  EXPORT_SYMBOL_GPL(xen_swiotlb_map_page);
> 
>  /*
> + * Create userspace mapping for the DMA-coherent memory.
> + */
> +int xen_swiotlb_dma_mmap(struct device *dev, struct vm_area_struct *vma,
> + void *cpu_addr, dma_addr_t dma_addr, size_t size,
> + struct dma_attrs *attrs)

Wow. Your editor ate all the nice tabs and spaces. Could you
please also run

scripts/checkpatch.pl on the patch and fix the issues it would
complain about.

Thank you!
> +{
> + int ret = -ENXIO;
> +#ifdef CONFIG_MMU
> + unsigned long nr_vma_pages = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
> + unsigned long nr_pages = PAGE_ALIGN(size) >> PAGE_SHIFT;
> + unsigned long pfn = PFN_DOWN(xen_bus_to_phys(dma_addr));
> + unsigned long off = vma->vm_pgoff;
> + pgprot_t prot = vma->vm_page_prot;
> +
> + prot = dma_get_attr(DMA_ATTR_WRITE_COMBINE, attrs) ?
> +    pgprot_writecombine(prot) :
> +    pgprot_dmacoherent(prot);
> +
> + vma->vm_page_prot = prot;
> +
> + if (dma_mmap_from_coherent(dev, vma, cpu_addr, size, &ret))
> + return ret;
> +
> + if (off < nr_pages && nr_vma_pages <= (nr_pages - off)) {
> + ret = remap_pfn_range(vma, vma->vm_start,
> + pfn + off,
> + vma->vm_end - vma->vm_start,
> + vma->vm_page_prot);
> + }
> +#endif  /* CONFIG_MMU */
> +
> + return ret;
> +}
> +EXPORT_SYMBOL_GPL(xen_swiotlb_dma_mmap);
> +
> +/*
>   * Unmap a single streaming mode DMA translation.  The dma_addr and size must
>   * match what was provided for in a previous xen_swiotlb_map_page call.  All
>   * other usages are undefined.
> diff --git a/include/xen/swiotlb-xen.h b/include/xen/swiotlb-xen.h
> index 7b64465..930fa94 100644
> --- a/include/xen/swiotlb-xen.h
> +++ b/include/xen/swiotlb-xen.h
> @@ -15,6 +15,11 @@ xen_swiotlb_free_coherent(struct device *hwdev, size_t size,
>    void *vaddr, dma_addr_t dma_handle,
>    struct dma_attrs *attrs);
> 
> +extern int
> +xen_swiotlb_dma_mmap(struct device *dev, struct vm_area_struct *vma,
> +     void *cpu_addr, dma_addr_t dma_addr, size_t size,
> +     struct dma_attrs *attrs);
> +
>  extern dma_addr_t xen_swiotlb_map_page(struct device *dev, struct page *page,
>         unsigned long offset, size_t size,
>         enum dma_data_direction dir,
Oleksandr Dmytryshyn April 7, 2014, 6:34 a.m. UTC | #9
On Fri, Apr 4, 2014 at 7:26 PM, Konrad Rzeszutek Wilk
<konrad.wilk@oracle.com> wrote:
> On Fri, Apr 04, 2014 at 02:30:22PM +0300, Oleksandr Dmytryshyn wrote:
>> >From f52bafc1ba51324ca5044df22778aacf815c59bf Mon Sep 17 00:00:00 2001
>> From: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
>> Date: Fri, 4 Apr 2014 12:16:27 +0300
>> Subject: [PATCH] swiotlb-xen: implement xen_swiotlb_dma_mmap callback
>>
>> This function creates userspace mapping for the DMA-coherent memory.
>>
>> Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
>> Signed-off-by: Oleksandr Dmytryshyn <oleksandr.dmytryshyn@globallogic.com>
>>
>> diff --git a/arch/arm/xen/mm.c b/arch/arm/xen/mm.c
>> index b0e77de..91408b1 100644
>> --- a/arch/arm/xen/mm.c
>> +++ b/arch/arm/xen/mm.c
>> @@ -48,6 +48,7 @@ static struct dma_map_ops xen_swiotlb_dma_ops = {
>>   .sync_sg_for_device = xen_swiotlb_sync_sg_for_device,
>>   .map_sg = xen_swiotlb_map_sg_attrs,
>>   .unmap_sg = xen_swiotlb_unmap_sg_attrs,
>> + .mmap = xen_swiotlb_dma_mmap,
>>   .map_page = xen_swiotlb_map_page,
>>   .unmap_page = xen_swiotlb_unmap_page,
>>   .dma_supported = xen_swiotlb_dma_supported,
>> diff --git a/drivers/xen/swiotlb-xen.c b/drivers/xen/swiotlb-xen.c
>> index 5403855..acf0c06 100644
>> --- a/drivers/xen/swiotlb-xen.c
>> +++ b/drivers/xen/swiotlb-xen.c
>> @@ -407,6 +407,42 @@ dma_addr_t xen_swiotlb_map_page(struct device
>> *dev, struct page *page,
>>  EXPORT_SYMBOL_GPL(xen_swiotlb_map_page);
>>
>>  /*
>> + * Create userspace mapping for the DMA-coherent memory.
>> + */
>> +int xen_swiotlb_dma_mmap(struct device *dev, struct vm_area_struct *vma,
>> + void *cpu_addr, dma_addr_t dma_addr, size_t size,
>> + struct dma_attrs *attrs)
>
> Wow. Your editor ate all the nice tabs and spaces. Could you
> please also run
>
> scripts/checkpatch.pl on the patch and fix the issues it would
> complain about.
>
> Thank you!
>> +{
>> + int ret = -ENXIO;
>> +#ifdef CONFIG_MMU
>> + unsigned long nr_vma_pages = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
>> + unsigned long nr_pages = PAGE_ALIGN(size) >> PAGE_SHIFT;
>> + unsigned long pfn = PFN_DOWN(xen_bus_to_phys(dma_addr));
>> + unsigned long off = vma->vm_pgoff;
>> + pgprot_t prot = vma->vm_page_prot;
>> +
>> + prot = dma_get_attr(DMA_ATTR_WRITE_COMBINE, attrs) ?
>> +    pgprot_writecombine(prot) :
>> +    pgprot_dmacoherent(prot);
>> +
>> + vma->vm_page_prot = prot;
>> +
>> + if (dma_mmap_from_coherent(dev, vma, cpu_addr, size, &ret))
>> + return ret;
>> +
>> + if (off < nr_pages && nr_vma_pages <= (nr_pages - off)) {
>> + ret = remap_pfn_range(vma, vma->vm_start,
>> + pfn + off,
>> + vma->vm_end - vma->vm_start,
>> + vma->vm_page_prot);
>> + }
>> +#endif  /* CONFIG_MMU */
>> +
>> + return ret;
>> +}
>> +EXPORT_SYMBOL_GPL(xen_swiotlb_dma_mmap);
>> +
>> +/*
>>   * Unmap a single streaming mode DMA translation.  The dma_addr and size must
>>   * match what was provided for in a previous xen_swiotlb_map_page call.  All
>>   * other usages are undefined.
>> diff --git a/include/xen/swiotlb-xen.h b/include/xen/swiotlb-xen.h
>> index 7b64465..930fa94 100644
>> --- a/include/xen/swiotlb-xen.h
>> +++ b/include/xen/swiotlb-xen.h
>> @@ -15,6 +15,11 @@ xen_swiotlb_free_coherent(struct device *hwdev, size_t size,
>>    void *vaddr, dma_addr_t dma_handle,
>>    struct dma_attrs *attrs);
>>
>> +extern int
>> +xen_swiotlb_dma_mmap(struct device *dev, struct vm_area_struct *vma,
>> +     void *cpu_addr, dma_addr_t dma_addr, size_t size,
>> +     struct dma_attrs *attrs);
>> +
>>  extern dma_addr_t xen_swiotlb_map_page(struct device *dev, struct page *page,
>>         unsigned long offset, size_t size,
>>         enum dma_data_direction dir,

Hi to all.
I've sent a patch in another thread (used git send).

Oleksandr Dmytryshyn | Product Engineering and Development
GlobalLogic
M +38.067.382.2525
www.globallogic.com

http://www.globallogic.com/email_disclaimer.txt
diff mbox

Patch

diff --git a/drivers/base/dma-mapping.c b/drivers/base/dma-mapping.c
index 0ce39a3..052a5ed 100644
--- a/drivers/base/dma-mapping.c
+++ b/drivers/base/dma-mapping.c
@@ -248,7 +248,7 @@  int dma_common_mmap(struct device *dev, struct vm_area_struct *vma,
 #ifdef CONFIG_MMU
 	unsigned long user_count = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
 	unsigned long count = PAGE_ALIGN(size) >> PAGE_SHIFT;
-	unsigned long pfn = page_to_pfn(virt_to_page(cpu_addr));
+	unsigned long pfn = dma_addr >> PAGE_SHIFT;
 	unsigned long off = vma->vm_pgoff;
 
 	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);