aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPhilipp Zabel <p.zabel@pengutronix.de>2018-11-15 16:53:47 +0100
committerHans Verkuil <hverkuil-cisco@xs4all.nl>2018-12-10 10:51:10 +0100
commit6300b376cb3ecce714ab604392f1468f3448d282 (patch)
tree91e61bdafebe7fb5fa6e788e1884232007d0e57b
parent74d4691313a485439e45dcd0881c91ccdd40ea9b (diff)
v4l2-compliance: test orphaned buffer support
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@pengutronix.de> Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl> [hverkuil-cisco: rebase, add missing m2m_q cleanup in testDmaBuf()]
-rw-r--r--utils/common/v4l2-info.cpp1
-rw-r--r--utils/v4l2-compliance/v4l2-compliance.h1
-rw-r--r--utils/v4l2-compliance/v4l2-test-buffers.cpp68
3 files changed, 64 insertions, 6 deletions
diff --git a/utils/common/v4l2-info.cpp b/utils/common/v4l2-info.cpp
index e163a78c..c0a4ba40 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 eb051adc..a12faeee 100644
--- a/utils/v4l2-compliance/v4l2-compliance.h
+++ b/utils/v4l2-compliance/v4l2-compliance.h
@@ -122,6 +122,7 @@ struct base_node {
__u32 valid_buftypes;
__u32 valid_buftype;
__u32 valid_memorytype;
+ bool supports_orphaned_bufs;
};
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 70e9301d..ad7d2a8d 100644
--- a/utils/v4l2-compliance/v4l2-test-buffers.cpp
+++ b/utils/v4l2-compliance/v4l2-test-buffers.cpp
@@ -565,8 +565,11 @@ int testReqBufs(struct node *node)
mmap_valid = !ret;
if (mmap_valid)
node->buf_caps = 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->supports_orphaned_bufs = true;
+ }
q.init(i, V4L2_MEMORY_USERPTR);
ret = q.reqbufs(node, 0);
@@ -581,6 +584,7 @@ int testReqBufs(struct node *node)
fail_on_test(ret && ret != EINVAL);
dmabuf_valid = !ret;
fail_on_test(!mmap_valid && dmabuf_valid);
+ fail_on_test(dmabuf_valid && (caps != q.g_capabilities()));
if (caps)
fail_on_test(dmabuf_valid ^ !!(caps & V4L2_BUF_CAP_SUPPORTS_DMABUF));
@@ -948,10 +952,14 @@ static int captureBufs(struct node *node, const cv4l_queue &q,
static int setupM2M(struct node *node, cv4l_queue &q)
{
+ __u32 caps;
+
last_m2m_seq.init();
fail_on_test(q.reqbufs(node, 2));
fail_on_test(q.mmap_bufs(node));
+ caps = q.g_capabilities();
+ fail_on_test(node->supports_orphaned_bufs ^ !!(caps & V4L2_BUF_CAP_SUPPORTS_ORPHANED_BUFS));
if (v4l_type_is_video(q.g_type())) {
cv4l_fmt fmt(q.g_type());
@@ -1177,12 +1185,34 @@ int testMmap(struct node *node, unsigned frame_count)
true, capture_count));
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->supports_orphaned_bufs) {
+ fail_on_test(q.reqbufs(node, 0));
+ q.munmap_bufs(node);
+ } else if (q.reqbufs(node, 0) != EBUSY) {
+ // 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));
+ }
+
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->supports_orphaned_bufs) {
+ fail_on_test(m2m_q.reqbufs(node, 0));
+ m2m_q.munmap_bufs(node);
+ } else if (m2m_q.reqbufs(node, 0) != EBUSY) {
+ // 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 {
+ m2m_q.munmap_bufs(node);
+ fail_on_test(m2m_q.reqbufs(node, 0));
+ }
fail_on_test(!capture_count);
}
stream_close();
@@ -1458,8 +1488,34 @@ int testDmaBuf(struct node *expbuf_node, struct node *node, unsigned frame_count
true, capture_count));
fail_on_test(node->streamoff(q.g_type()));
fail_on_test(node->streamoff(q.g_type()));
- if (node->is_m2m)
+ if (node->supports_orphaned_bufs) {
+ fail_on_test(q.reqbufs(node, 0));
+ exp_q.close_exported_fds();
+ } else if (q.reqbufs(node, 0) != EBUSY) {
+ // It's either a bug or this driver should set
+ // V4L2_BUF_CAP_SUPPORTS_ORPHANED_BUFS
+ warn("Can free buffers even if exported DMABUF fds still open\n");
+ q.munmap_bufs(node);
+ } else {
+ exp_q.close_exported_fds();
+ fail_on_test(q.reqbufs(node, 0));
+ }
+ if (node->is_m2m) {
+ fail_on_test(node->streamoff(m2m_q.g_type()));
+ if (node->supports_orphaned_bufs) {
+ fail_on_test(m2m_q.reqbufs(node, 0));
+ m2m_q.munmap_bufs(node);
+ } else if (m2m_q.reqbufs(node, 0) != EBUSY) {
+ // 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 {
+ m2m_q.munmap_bufs(node);
+ fail_on_test(m2m_q.reqbufs(node, 0));
+ }
fail_on_test(!capture_count);
+ }
stream_close();
}
return 0;

Privacy Policy