On Thu, 2018-11-15 at 11:21 +0100, Hans Verkuil wrote: > On 11/14/18 15:38, Philipp Zabel wrote: > > Test that V4L2_BUF_CAP_SUPPORTS_ORPHANED_BUFS is reported equally for > > both MMAP and DMABUF memory types. If supported, try to orphan buffers > > by calling reqbufs(0) before unmapping or closing DMABUF fds. > > > > Also close exported DMABUF fds and free buffers in testDmaBuf if > > orphaned buffers are not supported. > > > > Signed-off-by: Philipp Zabel <p.zabel@xxxxxxxxxxxxxx> > > --- > > contrib/freebsd/include/linux/videodev2.h | 1 + > > include/linux/videodev2.h | 1 + > > utils/common/v4l2-info.cpp | 1 + > > utils/v4l2-compliance/v4l2-compliance.h | 1 + > > utils/v4l2-compliance/v4l2-test-buffers.cpp | 35 +++++++++++++++++---- > > 5 files changed, 33 insertions(+), 6 deletions(-) > > > > diff --git a/contrib/freebsd/include/linux/videodev2.h b/contrib/freebsd/include/linux/videodev2.h > > index 9928c00e4b68..33153b53c175 100644 > > --- a/contrib/freebsd/include/linux/videodev2.h > > +++ b/contrib/freebsd/include/linux/videodev2.h > > @@ -907,6 +907,7 @@ struct v4l2_requestbuffers { > > #define V4L2_BUF_CAP_SUPPORTS_USERPTR (1 << 1) > > #define V4L2_BUF_CAP_SUPPORTS_DMABUF (1 << 2) > > #define V4L2_BUF_CAP_SUPPORTS_REQUESTS (1 << 3) > > +#define V4L2_BUF_CAP_SUPPORTS_ORPHANED_BUFS (1 << 4) > > > > /** > > * struct v4l2_plane - plane info for multi-planar buffers > > diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h > > index 79418cd39480..a39300cacb6a 100644 > > --- a/include/linux/videodev2.h > > +++ b/include/linux/videodev2.h > > @@ -873,6 +873,7 @@ struct v4l2_requestbuffers { > > #define V4L2_BUF_CAP_SUPPORTS_USERPTR (1 << 1) > > #define V4L2_BUF_CAP_SUPPORTS_DMABUF (1 << 2) > > #define V4L2_BUF_CAP_SUPPORTS_REQUESTS (1 << 3) > > +#define V4L2_BUF_CAP_SUPPORTS_ORPHANED_BUFS (1 << 4) > > > > /** > > * struct v4l2_plane - plane info for multi-planar buffers > > diff --git a/utils/common/v4l2-info.cpp b/utils/common/v4l2-info.cpp > > index 258e5446f030..3699c35cb9d6 100644 > > --- a/utils/common/v4l2-info.cpp > > +++ b/utils/common/v4l2-info.cpp > > @@ -200,6 +200,7 @@ static const flag_def bufcap_def[] = { > > { V4L2_BUF_CAP_SUPPORTS_USERPTR, "userptr" }, > > { V4L2_BUF_CAP_SUPPORTS_DMABUF, "dmabuf" }, > > { V4L2_BUF_CAP_SUPPORTS_REQUESTS, "requests" }, > > + { V4L2_BUF_CAP_SUPPORTS_ORPHANED_BUFS, "orphaned-bufs" }, > > { 0, NULL } > > }; > > > > diff --git a/utils/v4l2-compliance/v4l2-compliance.h b/utils/v4l2-compliance/v4l2-compliance.h > > index def185f17261..88ec260a9bcc 100644 > > --- a/utils/v4l2-compliance/v4l2-compliance.h > > +++ b/utils/v4l2-compliance/v4l2-compliance.h > > @@ -119,6 +119,7 @@ struct base_node { > > __u32 valid_buftypes; > > __u32 valid_buftype; > > __u32 valid_memorytype; > > + bool has_orphaned_bufs; > > I'd rename that to supports_orphaned_bufs. Ok. > > }; > > > > struct node : public base_node, public cv4l_fd { > > diff --git a/utils/v4l2-compliance/v4l2-test-buffers.cpp b/utils/v4l2-compliance/v4l2-test-buffers.cpp > > index c59a56d9ced7..6174015cb4e7 100644 > > --- a/utils/v4l2-compliance/v4l2-test-buffers.cpp > > +++ b/utils/v4l2-compliance/v4l2-test-buffers.cpp > > @@ -400,8 +400,11 @@ int testReqBufs(struct node *node) > > mmap_valid = !ret; > > if (mmap_valid) > > caps = q.g_capabilities(); > > - if (caps) > > + if (caps) { > > fail_on_test(mmap_valid ^ !!(caps & V4L2_BUF_CAP_SUPPORTS_MMAP)); > > + if (caps & V4L2_BUF_CAP_SUPPORTS_ORPHANED_BUFS) > > + node->has_orphaned_bufs = true; > > + } > > > > q.init(i, V4L2_MEMORY_USERPTR); > > ret = q.reqbufs(node, 0); > > @@ -418,8 +421,11 @@ int testReqBufs(struct node *node) > > fail_on_test(!mmap_valid && dmabuf_valid); > > // Note: dmabuf is only supported with vb2, so we can assume a > > // non-0 caps value if dmabuf is supported. > > - if (caps || dmabuf_valid) > > + if (caps || dmabuf_valid) { > > fail_on_test(dmabuf_valid ^ !!(caps & V4L2_BUF_CAP_SUPPORTS_DMABUF)); > > + if (node->has_orphaned_bufs) > > + fail_on_test(userptr_valid ^ !!(caps & V4L2_BUF_CAP_SUPPORTS_ORPHANED_BUFS)); > > Huh? I'm not sure what you are testing here. I intended to test that if MMAP supports orphaned buffers, DMABUF should as well, but stopped halfway. Otherwise we'd have to keep separate flags for MMAP and DMABUF. > > + } > > > > fail_on_test((can_stream && !is_overlay) && !mmap_valid && !userptr_valid && !dmabuf_valid); > > fail_on_test((!can_stream || is_overlay) && (mmap_valid || userptr_valid || dmabuf_valid)); > > @@ -967,12 +973,22 @@ int testMmap(struct node *node, unsigned frame_count) > > The setupM2M function should check if m2m_q also sets the V4L2_BUF_CAP_SUPPORTS_ORPHANED_BUFS. > I.e. this capability for m2m_q must match node->has_orphaned_bufs. > > It makes no sense if it is set for the capture queue but not the output queue > for m2m devices. And since this has to be set manually in the drivers (at least > for now), this needs to be checked by v4l2-compliance. I'll add a check for this. > > fail_on_test(captureBufs(node, q, m2m_q, frame_count, true)); > > fail_on_test(node->streamoff(q.g_type())); > > fail_on_test(node->streamoff(q.g_type())); > > - q.munmap_bufs(node); > > - fail_on_test(q.reqbufs(node, 0)); > > + if (node->has_orphaned_bufs) { > > + fail_on_test(q.reqbufs(node, 0)); > > + q.munmap_bufs(node); > > + } else { > > + q.munmap_bufs(node); > > + fail_on_test(q.reqbufs(node, 0)); > > This 'else' can be improved: > > } else if (!q.reqbufs(node, 0)) { > // It's either a bug or this driver should set > // V4L2_BUF_CAP_SUPPORTS_ORPHANED_BUFS > warn("Can free buffers even if still mmap()ed\n"); > q.munmap_bufs(node); > } else { > q.munmap_bufs(node); > fail_on_test(q.reqbufs(node, 0)); Ok. > > + } > > if (node->is_m2m) { > > fail_on_test(node->streamoff(m2m_q.g_type())); > > - m2m_q.munmap_bufs(node); > > - fail_on_test(m2m_q.reqbufs(node, 0)); > > + if (node->has_orphaned_bufs) { > > + fail_on_test(m2m_q.reqbufs(node, 0)); > > + m2m_q.munmap_bufs(node); > > + } else { > > + m2m_q.munmap_bufs(node); > > + fail_on_test(m2m_q.reqbufs(node, 0)); > > + } > > } > > } > > return 0; > > @@ -1201,6 +1217,13 @@ int testDmaBuf(struct node *expbuf_node, struct node *node, unsigned frame_count > > fail_on_test(captureBufs(node, q, m2m_q, frame_count, true)); > > fail_on_test(node->streamoff(q.g_type())); > > fail_on_test(node->streamoff(q.g_type())); > > + if (node->has_orphaned_bufs) { > > + fail_on_test(q.reqbufs(node, 0)); > > + exp_q.close_exported_fds(); > > + } else { > > Something similar to the MMAP case should be done here as well. > > If nothing else, that checks that if V4L2_BUF_CAP_SUPPORTS_ORPHANED_BUFS > is *not* set, then q.reqbufs(node, 0) should fail. Will do. Thank you for the comments! regards Philipp