2009-07-25 21:47:50

by Laurent Pinchart

[permalink] [raw]
Subject: Should I use kmap or kmap_atomic to map user pages that will be written in a loop ?

Hi everybody,

I'm trying to implement the USERPTR V4L2 streaming I/O method in the uvcvideo
driver. In a nutshell, that methods uses userspace-allocated buffers to
transfer video data from kernelspace to userspace. The buffers are reused
during the whole video stream in a circular fashion.

The kernel driver receives userspace pointers to those buffers, which can have
been allocated using different methods (malloc, Xv alloc, mmap() on a reserved
memory region, ...). I get the list of underlying pages using
get_user_pages(), and I then need to map those pages to the kernel virtual
address space.

Pages will be written to from the kernel in USB interrupt context. I can then
either kmap_atomic() pages before copying data and kunmap_atomic() them right
after, or kmap() them once at the beginning of the video stream and keep them
mapped until the end.

As I don't have much experience with the memory management subsystem, I'd
appreciate if someone could give me a few advices regarding the best way to
proceed. kmap() is expensive, but it would only be called once, while
kmap_atomic() would be called many times (4500 times per second for a 640x480
30fps video stream). On the other hand, I'm not sure how much pressure keeping
all those kmap() pages mapped into kernel virtual memory for a long time would
put on the memory subsystem.

Please CC me on answers.

Regards,

Laurent Pinchart


2009-07-26 21:27:48

by Jonathan Corbet

[permalink] [raw]
Subject: Re: Should I use kmap or kmap_atomic to map user pages that will be written in a loop ?

On Sat, 25 Jul 2009 23:41:47 +0200
Laurent Pinchart <[email protected]> wrote:

> Pages will be written to from the kernel in USB interrupt context. I can then
> either kmap_atomic() pages before copying data and kunmap_atomic() them right
> after, or kmap() them once at the beginning of the video stream and keep them
> mapped until the end.

Video buffers can be big, and the streaming interface requires at least
two of them. That's a lot of kmap'd pages. It seems to me that
kmap_atomic() is the way to go for something like this.

But, then, these are user-space buffers, and you're seemingly buffering
the data through kernel space buffers first? It seems like using
copy_to_user() in a workqueue (or a threaded interrupt handler) might be
a more straightforward way to go, unless I'm missing something.

jon

2009-07-26 21:50:54

by Laurent Pinchart

[permalink] [raw]
Subject: Re: Should I use kmap or kmap_atomic to map user pages that will be written in a loop ?

Hi Jonathan,

first of all thanks for your answer.

On Sunday 26 July 2009 23:26:55 Jonathan Corbet wrote:
> On Sat, 25 Jul 2009 23:41:47 +0200
>
> Laurent Pinchart <[email protected]> wrote:
> > Pages will be written to from the kernel in USB interrupt context. I can
> > then either kmap_atomic() pages before copying data and kunmap_atomic()
> > them right after, or kmap() them once at the beginning of the video
> > stream and keep them mapped until the end.
>
> Video buffers can be big, and the streaming interface requires at least
> two of them. That's a lot of kmap'd pages. It seems to me that
> kmap_atomic() is the way to go for something like this.

Ok thanks.

> But, then, these are user-space buffers, and you're seemingly buffering
> the data through kernel space buffers first? It seems like using
> copy_to_user() in a workqueue (or a threaded interrupt handler) might be
> a more straightforward way to go, unless I'm missing something.

I receive data from the USB subsystem in URB buffers, which are small kernel
buffers. As I have to strip headers from those buffers, I can't initialize the
URBs to copy data directly to the userspace buffers, so there's at least one
memcpy operation involved :-S

I could indeed append the URBs to a list in the callback called from interrupt
context, and process them from a threaded interrupt handler. Would it make
much difference ?

Regards,

Laurent Pinchart

2009-07-27 21:13:02

by Jonathan Corbet

[permalink] [raw]
Subject: Re: Should I use kmap or kmap_atomic to map user pages that will be written in a loop ?

On Sun, 26 Jul 2009 23:52:09 +0200
Laurent Pinchart <[email protected]> wrote:

> I receive data from the USB subsystem in URB buffers, which are small kernel
> buffers. As I have to strip headers from those buffers, I can't initialize the
> URBs to copy data directly to the userspace buffers, so there's at least one
> memcpy operation involved :-S
>
> I could indeed append the URBs to a list in the callback called from interrupt
> context, and process them from a threaded interrupt handler. Would it make
> much difference ?

Moving the actual copying out of interrupt context seems like a good
idea. And if you can get away from the whole get_user_pages() and
kmap() mess into a straight copy-to-user-space situation, you'll make
your life easier. So that would be my recommendation, yes.

jon

2009-07-29 08:57:00

by Laurent Pinchart

[permalink] [raw]
Subject: Re: Should I use kmap or kmap_atomic to map user pages that will be written in a loop ?

Hi Jonathan,

On Monday 27 July 2009 23:11:58 Jonathan Corbet wrote:
> On Sun, 26 Jul 2009 23:52:09 +0200 Laurent Pinchart wrote:
> > I receive data from the USB subsystem in URB buffers, which are small
> > kernel buffers. As I have to strip headers from those buffers, I can't
> > initialize the URBs to copy data directly to the userspace buffers, so
> > there's at least one memcpy operation involved :-S
> >
> > I could indeed append the URBs to a list in the callback called from
> > interrupt context, and process them from a threaded interrupt handler.
> > Would it make much difference ?
>
> Moving the actual copying out of interrupt context seems like a good
> idea. And if you can get away from the whole get_user_pages() and
> kmap() mess into a straight copy-to-user-space situation, you'll make
> your life easier. So that would be my recommendation, yes.

Thanks. I'll try that, it will make my life easier.

Regards,

Laurent Pinchart