* Problems with DMA from user space on MPC834x (Cache coherency?)
@ 2006-10-11 14:14 Lauri Ehrenpreis
0 siblings, 0 replies; 6+ messages in thread
From: Lauri Ehrenpreis @ 2006-10-11 14:14 UTC (permalink / raw)
To: linuxppc-embedded
Hi!
I have a problem with DMA from user space on a platform powered by MPC834x
processor (which has powerpc e300 core inside). Our linux kernel version is
2.6.17.
My user space program does something like this:
file_fd = open("/disk/file", O_RDONLY);
result = read(file_fd, page_aligned_buf, len);
call_driver_ioctl_which_performs_dma();
while /disk is mounted to a partition residing on USB memory stick or SD
card.
page_aligned_buf starts from page boundary and contains enough full pages
for
the data (so I can allways map full page with dma_map_page in kernel).
The buffer address and data length will then be passed to a driver, which
calls
get_user_pages, then maps each page with dma_map_page and tells a PCI
device
to start reading from that page:
...
down_read(¤t->mm->mmap_sem);
result = get_user_pages(current, current->mm, page_aligned_buf, nr_pages,
0, 0, pages, NULL);
up_read(¤t->mm->mmap_sem);
for (i = 0; i < nr_pages; i++) {
find_data_checksum(pages[i]);
dma_addr = dma_map_page(&fpga.pci_dev->dev, pages[i], 0, PAGE_SIZE,
DMA_TO_DEVICE);
start_dma();
wait_until_dma_ready();
dma_unmap_page(&fpga.pci_dev->dev, dma_addr, dma_len, DMA_TO_DEVICE);
if(!checksum_ok_in_fpga())
print_page_data();
}
for (i = 0; i < nr_pages; i++)
page_cache_release(pages[i]);
The problem is that sometimes the PCI device receives wrong bytes at random
locations. I find the data checksum inside the driver and inside the FPGA.
Inside the driver I use kmap(page) and kunmap(page) to access data on the
user page. Sometimes the checksums do not match and I can see with the FPGA
debugging tool, that the FPGA receives different data than the driver is
printing out.
I have noticed 3 things regarding this error:
1) When I copy the data I read from the block device to another buffer in
userspace and pass this new buffer to the driver, then this error will
never occur:
file_fd = open("/disk/file", O_RDONLY);
result = read(file_fd, page_aligned_buf, len);
memcpy(new_page_aligned_buf, page_aligned_buf, len);
call_driver_ioctl_which_performs_dma(new_page_aligned_buf, len);
2) this error does not occur when I use copy_from_user instead of
get_user_pages
and dma_map_page inside driver.
3) this error does not occur on our previuos device, which has x86
platform.
I am currently out of ideas what to do next.. It seems to me like a cache
coherency problem. Can anyone suggest what might be wrong?
--
^ permalink raw reply [flat|nested] 6+ messages in thread
* Problems with DMA from user space on MPC834x (Cache coherency?)
@ 2006-10-11 14:20 Lauri Ehrenpreis
0 siblings, 0 replies; 6+ messages in thread
From: Lauri Ehrenpreis @ 2006-10-11 14:20 UTC (permalink / raw)
To: linuxppc-embedded
Hi!
I have a problem with DMA from user space on a platform powered by MPC834x
processor (which has powerpc e300 core inside). Our linux kernel version is
2.6.17.
My user space program does something like this:
file_fd = open("/disk/file", O_RDONLY);
result = read(file_fd, page_aligned_buf, len);
call_driver_ioctl_which_performs_dma();
while /disk is mounted to a partition residing on USB memory stick or SD
card.
page_aligned_buf starts from page boundary and contains enough full pages
for
the data (so I can allways map full page with dma_map_page in kernel).
The buffer address and data length will then be passed to a driver, which
calls
get_user_pages, then maps each page with dma_map_page and tells a PCI
device
to start reading from that page:
...
down_read(¤t->mm->mmap_sem);
result = get_user_pages(current, current->mm, page_aligned_buf, nr_pages,
0, 0, pages, NULL);
up_read(¤t->mm->mmap_sem);
for (i = 0; i < nr_pages; i++) {
find_data_checksum(pages[i]);
dma_addr = dma_map_page(&fpga.pci_dev->dev, pages[i], 0, PAGE_SIZE,
DMA_TO_DEVICE);
start_dma();
wait_until_dma_ready();
dma_unmap_page(&fpga.pci_dev->dev, dma_addr, dma_len, DMA_TO_DEVICE);
if(!checksum_ok_in_fpga())
print_page_data();
}
for (i = 0; i < nr_pages; i++)
page_cache_release(pages[i]);
The problem is that sometimes the PCI device receives wrong bytes at random
locations. I find the data checksum inside the driver and inside the FPGA.
Inside the driver I use kmap(page) and kunmap(page) to access data on the
user page. Sometimes the checksums do not match and I can see with the FPGA
debugging tool, that the FPGA receives different data than the driver is
printing out.
I have noticed 3 things regarding this error:
1) When I copy the data I read from the block device to another buffer in
userspace and pass this new buffer to the driver, then this error will
never occur:
file_fd = open("/disk/file", O_RDONLY);
result = read(file_fd, page_aligned_buf, len);
memcpy(new_page_aligned_buf, page_aligned_buf, len);
call_driver_ioctl_which_performs_dma(new_page_aligned_buf, len);
2) this error does not occur when I use copy_from_user instead of
get_user_pages
and dma_map_page inside driver.
3) this error does not occur on our previuos device, which has x86
platform.
I am currently out of ideas what to do next.. It seems to me like a cache
coherency problem. Can anyone suggest what might be wrong?
--
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: Problems with DMA from user space on MPC834x (Cache coherency?)
@ 2006-10-12 17:32 Manish Joshi
2006-10-13 9:18 ` Lauri Ehrenpreis
0 siblings, 1 reply; 6+ messages in thread
From: Manish Joshi @ 2006-10-12 17:32 UTC (permalink / raw)
To: Lauri Ehrenpreis, linuxppc-embedded
[-- Attachment #1: Type: text/plain, Size: 3216 bytes --]
Yeah it looks like a cache coherency problem from the first look.
You may try enabling snooping on the DMA channel if MPC824X supports it. Check in Mode register setting.
Else you may want to use flush_dcache_range(start, last) functions and see if it helps.
----- Original Message ----
From: Lauri Ehrenpreis <lauri.ehrenpreis@liewenthal.ee>
To: linuxppc-embedded@ozlabs.org
Sent: Wednesday, October 11, 2006 7:20:03 AM
Subject: Problems with DMA from user space on MPC834x (Cache coherency?)
Hi!
I have a problem with DMA from user space on a platform powered by MPC834x
processor (which has powerpc e300 core inside). Our linux kernel version is
2.6.17.
My user space program does something like this:
file_fd = open("/disk/file", O_RDONLY);
result = read(file_fd, page_aligned_buf, len);
call_driver_ioctl_which_performs_dma();
while /disk is mounted to a partition residing on USB memory stick or SD
card.
page_aligned_buf starts from page boundary and contains enough full pages
for
the data (so I can allways map full page with dma_map_page in kernel).
The buffer address and data length will then be passed to a driver, which
calls
get_user_pages, then maps each page with dma_map_page and tells a PCI
device
to start reading from that page:
...
down_read(¤t->mm->mmap_sem);
result = get_user_pages(current, current->mm, page_aligned_buf, nr_pages,
0, 0, pages, NULL);
up_read(¤t->mm->mmap_sem);
for (i = 0; i < nr_pages; i++) {
find_data_checksum(pages[i]);
dma_addr = dma_map_page(&fpga.pci_dev->dev, pages[i], 0, PAGE_SIZE,
DMA_TO_DEVICE);
start_dma();
wait_until_dma_ready();
dma_unmap_page(&fpga.pci_dev->dev, dma_addr, dma_len, DMA_TO_DEVICE);
if(!checksum_ok_in_fpga())
print_page_data();
}
for (i = 0; i < nr_pages; i++)
page_cache_release(pages[i]);
The problem is that sometimes the PCI device receives wrong bytes at random
locations. I find the data checksum inside the driver and inside the FPGA.
Inside the driver I use kmap(page) and kunmap(page) to access data on the
user page. Sometimes the checksums do not match and I can see with the FPGA
debugging tool, that the FPGA receives different data than the driver is
printing out.
I have noticed 3 things regarding this error:
1) When I copy the data I read from the block device to another buffer in
userspace and pass this new buffer to the driver, then this error will
never occur:
file_fd = open("/disk/file", O_RDONLY);
result = read(file_fd, page_aligned_buf, len);
memcpy(new_page_aligned_buf, page_aligned_buf, len);
call_driver_ioctl_which_performs_dma(new_page_aligned_buf, len);
2) this error does not occur when I use copy_from_user instead of
get_user_pages
and dma_map_page inside driver.
3) this error does not occur on our previuos device, which has x86
platform.
I am currently out of ideas what to do next.. It seems to me like a cache
coherency problem. Can anyone suggest what might be wrong?
--
_______________________________________________
Linuxppc-embedded mailing list
Linuxppc-embedded@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-embedded
[-- Attachment #2: Type: text/html, Size: 4713 bytes --]
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: Problems with DMA from user space on MPC834x (Cache coherency?)
2006-10-12 17:32 Problems with DMA from user space on MPC834x (Cache coherency?) Manish Joshi
@ 2006-10-13 9:18 ` Lauri Ehrenpreis
2006-10-13 15:27 ` Kumar Gala
0 siblings, 1 reply; 6+ messages in thread
From: Lauri Ehrenpreis @ 2006-10-13 9:18 UTC (permalink / raw)
To: linuxppc-embedded
Thank you!
I added following before starting DMA:
kaddr = (unsigned long)kmap(pages[i]);
flush_dcache_range(kaddr, kaddr + PAGE_SIZE);
kunmap(pages[i]);
...and everything works now. As I understand this now, dma_map_page is
not flushing caches on MPS834x because the processor should snoop the
memory transactions and flush cache automatically if needed
(__dma_sync_page
is defined as do { } while (0) in kernel). But there exists an errata
(PCI5) which states that there may be some problems with this automatic
flushing. So the caches must be flushed with flush_dcache_range.
--
Lauri
On Thu, 12 Oct 2006 20:32:31 +0300, Manish Joshi <mjoshi_blr@yahoo.com>
wrote:
> Yeah it looks like a cache coherency problem from the first look.
> You may try enabling snooping on the DMA channel if MPC824X supports it.
> Check in Mode register setting.
> Else you may want to use flush_dcache_range(start, last) functions and
> see if it helps.
> ----- Original Message ----
> From: Lauri Ehrenpreis <lauri.ehrenpreis@liewenthal.ee>
> To: linuxppc-embedded@ozlabs.org
> Sent: Wednesday, October 11, 2006 7:20:03 AM
> Subject: Problems with DMA from user space on MPC834x (Cache coherency?)
>
>
> Hi!
>
> I have a problem with DMA from user space on a platform powered by
> MPC834x
> processor (which has powerpc e300 core inside). Our linux kernel version
> is
> 2.6.17.
>
> My user space program does something like this:
>
> file_fd = open("/disk/file", O_RDONLY);
> result = read(file_fd, page_aligned_buf, len);
> call_driver_ioctl_which_performs_dma();
>
> while /disk is mounted to a partition residing on USB memory stick or SD
> card.
> page_aligned_buf starts from page boundary and contains enough full pages
> for
> the data (so I can allways map full page with dma_map_page in kernel).
>
> The buffer address and data length will then be passed to a driver, which
> calls
> get_user_pages, then maps each page with dma_map_page and tells a PCI
> device
> to start reading from that page:
>
> ...
> down_read(¤t->mm->mmap_sem);
> result = get_user_pages(current, current->mm, page_aligned_buf, nr_pages,
> 0, 0, pages, NULL);
> up_read(¤t->mm->mmap_sem);
>
> for (i = 0; i < nr_pages; i++) {
> find_data_checksum(pages[i]);
> dma_addr = dma_map_page(&fpga.pci_dev->dev, pages[i], 0, PAGE_SIZE,
> DMA_TO_DEVICE);
>
> start_dma();
>
> wait_until_dma_ready();
>
> dma_unmap_page(&fpga.pci_dev->dev, dma_addr, dma_len, DMA_TO_DEVICE);
>
> if(!checksum_ok_in_fpga())
> print_page_data();
> }
>
> for (i = 0; i < nr_pages; i++)
> page_cache_release(pages[i]);
>
> The problem is that sometimes the PCI device receives wrong bytes at
> random
> locations. I find the data checksum inside the driver and inside the
> FPGA.
> Inside the driver I use kmap(page) and kunmap(page) to access data on the
> user page. Sometimes the checksums do not match and I can see with the
> FPGA
> debugging tool, that the FPGA receives different data than the driver is
> printing out.
>
> I have noticed 3 things regarding this error:
> 1) When I copy the data I read from the block device to another buffer in
> userspace and pass this new buffer to the driver, then this error will
> never occur:
>
> file_fd = open("/disk/file", O_RDONLY);
> result = read(file_fd, page_aligned_buf, len);
> memcpy(new_page_aligned_buf, page_aligned_buf, len);
> call_driver_ioctl_which_performs_dma(new_page_aligned_buf, len);
>
> 2) this error does not occur when I use copy_from_user instead of
> get_user_pages
> and dma_map_page inside driver.
>
> 3) this error does not occur on our previuos device, which has x86
> platform.
>
> I am currently out of ideas what to do next.. It seems to me like a cache
> coherency problem. Can anyone suggest what might be wrong?
>
> --
> _______________________________________________
> Linuxppc-embedded mailing list
> Linuxppc-embedded@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-embedded
>
>
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: Problems with DMA from user space on MPC834x (Cache coherency?)
2006-10-13 9:18 ` Lauri Ehrenpreis
@ 2006-10-13 15:27 ` Kumar Gala
2006-10-13 15:49 ` Liu Dave-r63238
0 siblings, 1 reply; 6+ messages in thread
From: Kumar Gala @ 2006-10-13 15:27 UTC (permalink / raw)
To: Lauri Ehrenpreis; +Cc: linuxppc-embedded
On Oct 13, 2006, at 4:18 AM, Lauri Ehrenpreis wrote:
>
> Thank you!
>
> I added following before starting DMA:
>
> kaddr = (unsigned long)kmap(pages[i]);
> flush_dcache_range(kaddr, kaddr + PAGE_SIZE);
> kunmap(pages[i]);
>
> ...and everything works now. As I understand this now, dma_map_page is
> not flushing caches on MPS834x because the processor should snoop the
> memory transactions and flush cache automatically if needed
> (__dma_sync_page
> is defined as do { } while (0) in kernel). But there exists an errata
> (PCI5) which states that there may be some problems with this
> automatic
> flushing. So the caches must be flushed with flush_dcache_range.
What silicon version are you using. PCI5 should be fixed in rev1.1
and newer. You can be taking a big perf hit having to flush all the
time.
- k
^ permalink raw reply [flat|nested] 6+ messages in thread
* RE: Problems with DMA from user space on MPC834x (Cache coherency?)
2006-10-13 15:27 ` Kumar Gala
@ 2006-10-13 15:49 ` Liu Dave-r63238
0 siblings, 0 replies; 6+ messages in thread
From: Liu Dave-r63238 @ 2006-10-13 15:49 UTC (permalink / raw)
To: Kumar Gala, Lauri Ehrenpreis; +Cc: linuxppc-embedded
You can make use of the hardware cache coherency. Setup the DMA
attribute as global.
If you use the hardware way, you don't need these flushing operation.
-Dave
> > I added following before starting DMA:
> >
> > kaddr =3D (unsigned long)kmap(pages[i]);=20
> flush_dcache_range(kaddr, kaddr=20
> > + PAGE_SIZE); kunmap(pages[i]);
> >
> > ...and everything works now. As I understand this now,=20
> dma_map_page is=20
> > not flushing caches on MPS834x because the processor should=20
> snoop the=20
> > memory transactions and flush cache automatically if needed=20
> > (__dma_sync_page is defined as do { } while (0) in kernel).=20
> But there=20
> > exists an errata
> > (PCI5) which states that there may be some problems with this=20
> > automatic flushing. So the caches must be flushed with=20
> > flush_dcache_range.
>=20
> What silicon version are you using. PCI5 should be fixed in=20
> rev1.1 and newer. You can be taking a big perf hit having to=20
> flush all the time.
>=20
> - k
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2006-10-13 15:49 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-10-12 17:32 Problems with DMA from user space on MPC834x (Cache coherency?) Manish Joshi
2006-10-13 9:18 ` Lauri Ehrenpreis
2006-10-13 15:27 ` Kumar Gala
2006-10-13 15:49 ` Liu Dave-r63238
-- strict thread matches above, loose matches on Subject: below --
2006-10-11 14:20 Lauri Ehrenpreis
2006-10-11 14:14 Lauri Ehrenpreis
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).