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

Reply via email to