Hi Laurent,
thanks for your help. I got it working. I tried it with the first
approach you suggested: In the "uvc_lock_buffer" function, I do the
ioremap of the physical address range and store the pointer in the
uvc_buffer struct in a new variable (ioremap is not working in the
"uvc_buffer_write" function because we are in an interrupt).
Then, the "uvc_buffer_write" function writes the data to the memory.
"iounmap" is done in "uvc_unlock_buffer".
I hope that's the right way!?
Cheers,
Andreas
Laurent Pinchart schrieb:
Hi Andreas,
On Tuesday 01 June 2010 16:14:35 Andreas Auer wrote:
Thanks for the answer. I'll try to add this changes by myself.
Right now, I can get the physical pfn of the user pointer. The first
approach that came into my mind was to get a pointer to the page struct
with the pfn_to_page(...) function.
You already added a new function called uvc_buffer_write which maps
(kmap_atomic) the pfn associated with the page struct into the kernel
space (basically the logical kernel address is returned). And then the
data from the uvc cam is copied to the buffer and finally, the pfn is
unmapped with kunmap_atomic.
So, I thought this should work. But, I'm getting a paging error:
"Unable to handle kernel paging request at virtual address cdf46000"
Could that paging error occur because the physical page resides outside
of the physical memory that linux holds. That means I specified 216MB
for Linux. The memory from 216MB to 256MB is reserved for the DSP. And
the user pointer passed to the UVC driver points to 223MB which is above
the memory of Linux.
That's correct. Linux doesn't handle that memory, and didn't create any struct
page for it. pfn_to_page() on such memory isn't valid, which means you can't
call kmap_atomic in that case.
So, maybe the MMU doesn't know that there are physical pages and has no
mapping for it!?
The MMU has mappings for that memory, but I don't think those can be easily
accessed from the UVC driver interrupt handler. The userspace mapping (created
through mmap on the DSP driver) is specific to the userspace application, and
the kernel mapping (created through ioremap in the DSP driver), if it exists,
isn't easily accessible.
I can think of two ways to solve the problem. The first one would be to
ioremap() the memory using its physical address. You would then get a kernel
virtual mapping. I'm not sure if that would work though (cache coherency
issues come to mind). The second way is to change the way the UVC interrupt
handler works, and add completed URBs to a list instead of decoding them. A
workqueue would then decode the URBs, using copy_to_user instead of
kmap/memcpy/kunmap. That approach will introduce more delay in URB processing
and might thus require an increased number of URBs. It would be nice to
experiment with it.
_______________________________________________
Linux-uvc-devel mailing list
[email protected]
https://lists.berlios.de/mailman/listinfo/linux-uvc-devel