Message ID | 20240620091505.359637-1-fusibrandon13@gmail.com (mailing list archive) |
---|---|
State | New |
Headers | show |
Series | [v4l-utils] common: Use posix_memalign for allocating userptr buffers | expand |
Hi Brandon, Thanks for the patch. On Thu, Jun 20, 2024 at 10:15:05AM +0100, Brandon Cheo Fusi wrote: > When dealing with a userptr pointing to a buffer in userspace, > videobuf2 swaps the corresponding physical pages with other pages > so we have a contiguous area of memory for DMA. This only works if > the userptr is page aligned. > > The current way of allocating user buffers using malloc only > guarantees alignment up to `alignof(max_align_t)`, which is usually > 16. So replace malloc with posix_memalign to ensure the returned > pointer is on a page boundary. > > Signed-off-by: Brandon Cheo Fusi <fusibrandon13@gmail.com> > --- > utils/common/v4l-helpers.h | 15 ++++++++++++++- > 1 file changed, 14 insertions(+), 1 deletion(-) > > diff --git a/utils/common/v4l-helpers.h b/utils/common/v4l-helpers.h > index cf0e92d..92a6fdc 100644 > --- a/utils/common/v4l-helpers.h > +++ b/utils/common/v4l-helpers.h > @@ -1652,6 +1652,19 @@ static inline int v4l_queue_munmap_bufs(struct v4l_fd *f, struct v4l_queue *q, > return 0; > } > > +static inline void *userptr_malloc(size_t size) > +{ > + int v4l2_page_size = getpagesize(); > + void *ptr_addr = 0; > + > + int ret = posix_memalign(&ptr_addr, v4l2_page_size, size); > + if (ret != 0) { > + fprintf(stderr, "malloc via posix_memalign failed\n"); > + return 0; > + } > + return ptr_addr; > +} > + > static inline int v4l_queue_alloc_bufs(struct v4l_fd *f, > struct v4l_queue *q, unsigned from) > { > @@ -1661,7 +1674,7 @@ static inline int v4l_queue_alloc_bufs(struct v4l_fd *f, > return 0; > for (b = from; b < v4l_queue_g_buffers(q); b++) { > for (p = 0; p < v4l_queue_g_num_planes(q); p++) { > - void *m = malloc(v4l_queue_g_length(q, p)); > + void *m = userptr_malloc(v4l_queue_g_length(q, p)); Could you call posix_memalign() here? I don't see a need to add a new function for this. Also no temporary varible for the page size is needed. > > if (m == NULL) > return errno;
diff --git a/utils/common/v4l-helpers.h b/utils/common/v4l-helpers.h index cf0e92d..92a6fdc 100644 --- a/utils/common/v4l-helpers.h +++ b/utils/common/v4l-helpers.h @@ -1652,6 +1652,19 @@ static inline int v4l_queue_munmap_bufs(struct v4l_fd *f, struct v4l_queue *q, return 0; } +static inline void *userptr_malloc(size_t size) +{ + int v4l2_page_size = getpagesize(); + void *ptr_addr = 0; + + int ret = posix_memalign(&ptr_addr, v4l2_page_size, size); + if (ret != 0) { + fprintf(stderr, "malloc via posix_memalign failed\n"); + return 0; + } + return ptr_addr; +} + static inline int v4l_queue_alloc_bufs(struct v4l_fd *f, struct v4l_queue *q, unsigned from) { @@ -1661,7 +1674,7 @@ static inline int v4l_queue_alloc_bufs(struct v4l_fd *f, return 0; for (b = from; b < v4l_queue_g_buffers(q); b++) { for (p = 0; p < v4l_queue_g_num_planes(q); p++) { - void *m = malloc(v4l_queue_g_length(q, p)); + void *m = userptr_malloc(v4l_queue_g_length(q, p)); if (m == NULL) return errno;
When dealing with a userptr pointing to a buffer in userspace, videobuf2 swaps the corresponding physical pages with other pages so we have a contiguous area of memory for DMA. This only works if the userptr is page aligned. The current way of allocating user buffers using malloc only guarantees alignment up to `alignof(max_align_t)`, which is usually 16. So replace malloc with posix_memalign to ensure the returned pointer is on a page boundary. Signed-off-by: Brandon Cheo Fusi <fusibrandon13@gmail.com> --- utils/common/v4l-helpers.h | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-)