diff mbox series

[v5,2/4] v4l2-compliance: Test queue maximum buffers allocation

Message ID 20231031152722.84444-3-benjamin.gaignard@collabora.com
State New
Headers show
Series [v5,1/4] v4l-utils: Add max_num_buffers field to v4l2_create_buffers struct | expand

Commit Message

Benjamin Gaignard Oct. 31, 2023, 3:27 p.m. UTC
If  V4L2_BUF_CAP_SUPPORTS_MAX_NUM_BUFFERS is set v4l2_create_buffers
'max_num_buffers' field reports the maximum number of buffers supported
by the queue.
Add a test to allocate this maximum value and make sure that one
more allocation is failing.
Display the flag in v4l2-ctl.

Signed-off-by: Benjamin Gaignard <benjamin.gaignard@collabora.com>
---
version 5:
- change g_max_buffers() to g_max_num_buffers().
- change v4l_queue_g_max_buffers() to v4l_queue_g_max_num_buffers().
- rename struct v4l_queue max_buffers field to max_num_buffers.
- fix V4L2_BUF_CAP_SUPPORTS_MAX_NUM_BUFFERS name in bufcap_def array.
- only test MMAP streaming mode.
- rework test code.

 utils/common/cv4l-helpers.h                 |  1 +
 utils/common/v4l-helpers.h                  |  5 +++
 utils/common/v4l2-info.cpp                  |  1 +
 utils/v4l2-compliance/v4l2-compliance.cpp   |  1 +
 utils/v4l2-compliance/v4l2-compliance.h     |  1 +
 utils/v4l2-compliance/v4l2-test-buffers.cpp | 41 +++++++++++++++++++++
 6 files changed, 50 insertions(+)

Comments

Benjamin Gaignard Nov. 7, 2023, 10:34 a.m. UTC | #1
Le 07/11/2023 à 11:18, Hans Verkuil a écrit :
> On 31/10/2023 16:27, Benjamin Gaignard wrote:
>> If  V4L2_BUF_CAP_SUPPORTS_MAX_NUM_BUFFERS is set v4l2_create_buffers
>> 'max_num_buffers' field reports the maximum number of buffers supported
>> by the queue.
>> Add a test to allocate this maximum value and make sure that one
>> more allocation is failing.
>> Display the flag in v4l2-ctl.
>>
>> Signed-off-by: Benjamin Gaignard <benjamin.gaignard@collabora.com>
>> ---
>> version 5:
>> - change g_max_buffers() to g_max_num_buffers().
>> - change v4l_queue_g_max_buffers() to v4l_queue_g_max_num_buffers().
>> - rename struct v4l_queue max_buffers field to max_num_buffers.
>> - fix V4L2_BUF_CAP_SUPPORTS_MAX_NUM_BUFFERS name in bufcap_def array.
>> - only test MMAP streaming mode.
>> - rework test code.
>>
>>   utils/common/cv4l-helpers.h                 |  1 +
>>   utils/common/v4l-helpers.h                  |  5 +++
>>   utils/common/v4l2-info.cpp                  |  1 +
>>   utils/v4l2-compliance/v4l2-compliance.cpp   |  1 +
>>   utils/v4l2-compliance/v4l2-compliance.h     |  1 +
>>   utils/v4l2-compliance/v4l2-test-buffers.cpp | 41 +++++++++++++++++++++
>>   6 files changed, 50 insertions(+)
>>
>> diff --git a/utils/common/cv4l-helpers.h b/utils/common/cv4l-helpers.h
>> index 91a04146..199aca36 100644
>> --- a/utils/common/cv4l-helpers.h
>> +++ b/utils/common/cv4l-helpers.h
>> @@ -743,6 +743,7 @@ public:
>>   	unsigned g_type() const { return v4l_queue_g_type(this); }
>>   	unsigned g_memory() const { return v4l_queue_g_memory(this); }
>>   	unsigned g_buffers() const { return v4l_queue_g_buffers(this); }
>> +	unsigned g_max_num_buffers() const { return v4l_queue_g_max_num_buffers(this); }
>>   	unsigned g_num_planes() const { return v4l_queue_g_num_planes(this); }
>>   	unsigned g_capabilities() const { return v4l_queue_g_capabilities(this); }
>>   	unsigned g_length(unsigned plane) const { return v4l_queue_g_length(this, plane); }
>> diff --git a/utils/common/v4l-helpers.h b/utils/common/v4l-helpers.h
>> index f8e96d58..cf0e92df 100644
>> --- a/utils/common/v4l-helpers.h
>> +++ b/utils/common/v4l-helpers.h
>> @@ -1429,6 +1429,7 @@ struct v4l_queue {
>>   	unsigned mappings;
>>   	unsigned num_planes;
>>   	unsigned capabilities;
>> +	unsigned max_num_buffers;
>>   
>>   	__u32 lengths[VIDEO_MAX_PLANES];
>>   	__u32 mem_offsets[VIDEO_MAX_FRAME][VIDEO_MAX_PLANES];
>> @@ -1453,6 +1454,7 @@ static inline void v4l_queue_init(struct v4l_queue *q,
>>   static inline unsigned v4l_queue_g_type(const struct v4l_queue *q) { return q->type; }
>>   static inline unsigned v4l_queue_g_memory(const struct v4l_queue *q) { return q->memory; }
>>   static inline unsigned v4l_queue_g_buffers(const struct v4l_queue *q) { return q->buffers; }
>> +static inline unsigned v4l_queue_g_max_num_buffers(const struct v4l_queue *q) { return q->max_num_buffers; }
>>   static inline unsigned v4l_queue_g_mappings(const struct v4l_queue *q) { return q->mappings; }
>>   static inline unsigned v4l_queue_g_num_planes(const struct v4l_queue *q) { return q->num_planes; }
>>   static inline unsigned v4l_queue_g_capabilities(const struct v4l_queue *q) { return q->capabilities; }
>> @@ -1587,6 +1589,9 @@ static inline int v4l_queue_create_bufs(struct v4l_fd *f,
>>   	if (ret)
>>   		return ret;
>>   	q->capabilities = createbufs.capabilities;
>> +	q->max_num_buffers = 32;
>> +	if (q->capabilities & V4L2_BUF_CAP_SUPPORTS_MAX_NUM_BUFFERS)
>> +		q->max_num_buffers = createbufs.max_num_buffers;
>>   	q->buffers += createbufs.count;
>>   	return v4l_queue_querybufs(f, q, q->buffers - createbufs.count);
>>   }
>> diff --git a/utils/common/v4l2-info.cpp b/utils/common/v4l2-info.cpp
>> index 4f8c2aa7..5fc92005 100644
>> --- a/utils/common/v4l2-info.cpp
>> +++ b/utils/common/v4l2-info.cpp
>> @@ -206,6 +206,7 @@ static constexpr flag_def bufcap_def[] = {
>>   	{ V4L2_BUF_CAP_SUPPORTS_ORPHANED_BUFS, "orphaned-bufs" },
>>   	{ V4L2_BUF_CAP_SUPPORTS_M2M_HOLD_CAPTURE_BUF, "m2m-hold-capture-buf" },
>>   	{ V4L2_BUF_CAP_SUPPORTS_MMAP_CACHE_HINTS, "mmap-cache-hints" },
>> +	{ V4L2_BUF_CAP_SUPPORTS_MAX_NUM_BUFFERS, "set-max-num-buffers" },
>>   	{ 0, nullptr }
>>   };
>>   
>> diff --git a/utils/v4l2-compliance/v4l2-compliance.cpp b/utils/v4l2-compliance/v4l2-compliance.cpp
>> index ac6a8f80..a165ef5a 100644
>> --- a/utils/v4l2-compliance/v4l2-compliance.cpp
>> +++ b/utils/v4l2-compliance/v4l2-compliance.cpp
>> @@ -1453,6 +1453,7 @@ void testNode(struct node &node, struct node &node_m2m_cap, struct node &expbuf_
>>   
>>   		printf("Buffer ioctls%s:\n", suffix);
>>   		printf("\ttest VIDIOC_REQBUFS/CREATE_BUFS/QUERYBUF: %s\n", ok(testReqBufs(&node)));
>> +		printf("\ttest CREATE_BUFS maximum buffers: %s\n", ok(testCreateBufsMax(&node)));
>>   		// Reopen after each streaming test to reset the streaming state
>>   		// in case of any errors in the preceeding test.
>>   		node.reopen();
>> diff --git a/utils/v4l2-compliance/v4l2-compliance.h b/utils/v4l2-compliance/v4l2-compliance.h
>> index 7e3860c8..4f9aa17e 100644
>> --- a/utils/v4l2-compliance/v4l2-compliance.h
>> +++ b/utils/v4l2-compliance/v4l2-compliance.h
>> @@ -383,6 +383,7 @@ int testReqBufs(struct node *node);
>>   int testReadWrite(struct node *node);
>>   int testExpBuf(struct node *node);
>>   int testBlockingWait(struct node *node);
>> +int testCreateBufsMax(struct node *node);
>>   
>>   // 32-bit architecture, 32/64-bit time_t tests
>>   int testTime32_64(struct node *node);
>> diff --git a/utils/v4l2-compliance/v4l2-test-buffers.cpp b/utils/v4l2-compliance/v4l2-test-buffers.cpp
>> index 6d592c9b..e3c3db46 100644
>> --- a/utils/v4l2-compliance/v4l2-test-buffers.cpp
>> +++ b/utils/v4l2-compliance/v4l2-test-buffers.cpp
>> @@ -761,6 +761,47 @@ int testReqBufs(struct node *node)
>>   	return 0;
>>   }
>>   
>> +int testCreateBufsMax(struct node *node)
>> +{
>> +	unsigned int i;
>> +	int ret;
>> +
>> +	node->reopen();
>> +
>> +	cv4l_queue q(0, 0);
>> +
>> +	for (i = 1; i <= V4L2_BUF_TYPE_LAST; i++) {
>> +		if (!(node->valid_buftypes & (1 << i)))
>> +			continue;
>> +
>> +		q.init(i, V4L2_MEMORY_USERPTR);
>> +		ret = q.create_bufs(node, 1);
>> +		if (!ret && (q.g_capabilities() & V4L2_BUF_CAP_SUPPORTS_MAX_NUM_BUFFERS)) {
>> +			fail_on_test(q.create_bufs(node, q.g_max_buffers() - q.g_buffers()));
> You didn't compile this, did you?
>
> This should be g_max_num_buffers...

I have compile the whole v5 branch
and this is fixed on the last patch of the series.
I'm fixing that.

>
> Regards,
>
> 	Hans
>
>> +			ret = q.create_bufs(node, 1);
>> +			fail_on_test(ret != ENOBUFS && (q.g_max_buffers() == q.g_buffers()));
>> +		}
>> +
>> +		q.init(i, V4L2_MEMORY_MMAP);
>> +		ret = q.create_bufs(node, 1);
>> +		if (!ret && (q.g_capabilities() & V4L2_BUF_CAP_SUPPORTS_MAX_NUM_BUFFERS)) {
>> +			fail_on_test(q.create_bufs(node, q.g_max_buffers() - q.g_buffers()));
>> +			ret = q.create_bufs(node, 1);
>> +			fail_on_test(ret != ENOBUFS && (q.g_max_buffers() == q.g_buffers()));
>> +		}
>> +
>> +		q.init(i, V4L2_MEMORY_DMABUF);
>> +		ret = q.create_bufs(node, 1);
>> +		if (!ret && (q.g_capabilities() & V4L2_BUF_CAP_SUPPORTS_MAX_NUM_BUFFERS)) {
>> +			fail_on_test(q.create_bufs(node, q.g_max_buffers() - q.g_buffers()));
>> +			ret = q.create_bufs(node, 1);
>> +			fail_on_test(ret != ENOBUFS && (q.g_max_buffers() == q.g_buffers()));
>> +		}
>> +	}
>> +
>> +	return 0;
>> +}
>> +
>>   int testExpBuf(struct node *node)
>>   {
>>   	bool have_expbuf = false;
> _______________________________________________
> Kernel mailing list -- kernel@mailman.collabora.com
> To unsubscribe send an email to kernel-leave@mailman.collabora.com
diff mbox series

Patch

diff --git a/utils/common/cv4l-helpers.h b/utils/common/cv4l-helpers.h
index 91a04146..199aca36 100644
--- a/utils/common/cv4l-helpers.h
+++ b/utils/common/cv4l-helpers.h
@@ -743,6 +743,7 @@  public:
 	unsigned g_type() const { return v4l_queue_g_type(this); }
 	unsigned g_memory() const { return v4l_queue_g_memory(this); }
 	unsigned g_buffers() const { return v4l_queue_g_buffers(this); }
+	unsigned g_max_num_buffers() const { return v4l_queue_g_max_num_buffers(this); }
 	unsigned g_num_planes() const { return v4l_queue_g_num_planes(this); }
 	unsigned g_capabilities() const { return v4l_queue_g_capabilities(this); }
 	unsigned g_length(unsigned plane) const { return v4l_queue_g_length(this, plane); }
diff --git a/utils/common/v4l-helpers.h b/utils/common/v4l-helpers.h
index f8e96d58..cf0e92df 100644
--- a/utils/common/v4l-helpers.h
+++ b/utils/common/v4l-helpers.h
@@ -1429,6 +1429,7 @@  struct v4l_queue {
 	unsigned mappings;
 	unsigned num_planes;
 	unsigned capabilities;
+	unsigned max_num_buffers;
 
 	__u32 lengths[VIDEO_MAX_PLANES];
 	__u32 mem_offsets[VIDEO_MAX_FRAME][VIDEO_MAX_PLANES];
@@ -1453,6 +1454,7 @@  static inline void v4l_queue_init(struct v4l_queue *q,
 static inline unsigned v4l_queue_g_type(const struct v4l_queue *q) { return q->type; }
 static inline unsigned v4l_queue_g_memory(const struct v4l_queue *q) { return q->memory; }
 static inline unsigned v4l_queue_g_buffers(const struct v4l_queue *q) { return q->buffers; }
+static inline unsigned v4l_queue_g_max_num_buffers(const struct v4l_queue *q) { return q->max_num_buffers; }
 static inline unsigned v4l_queue_g_mappings(const struct v4l_queue *q) { return q->mappings; }
 static inline unsigned v4l_queue_g_num_planes(const struct v4l_queue *q) { return q->num_planes; }
 static inline unsigned v4l_queue_g_capabilities(const struct v4l_queue *q) { return q->capabilities; }
@@ -1587,6 +1589,9 @@  static inline int v4l_queue_create_bufs(struct v4l_fd *f,
 	if (ret)
 		return ret;
 	q->capabilities = createbufs.capabilities;
+	q->max_num_buffers = 32;
+	if (q->capabilities & V4L2_BUF_CAP_SUPPORTS_MAX_NUM_BUFFERS)
+		q->max_num_buffers = createbufs.max_num_buffers;
 	q->buffers += createbufs.count;
 	return v4l_queue_querybufs(f, q, q->buffers - createbufs.count);
 }
diff --git a/utils/common/v4l2-info.cpp b/utils/common/v4l2-info.cpp
index 4f8c2aa7..5fc92005 100644
--- a/utils/common/v4l2-info.cpp
+++ b/utils/common/v4l2-info.cpp
@@ -206,6 +206,7 @@  static constexpr flag_def bufcap_def[] = {
 	{ V4L2_BUF_CAP_SUPPORTS_ORPHANED_BUFS, "orphaned-bufs" },
 	{ V4L2_BUF_CAP_SUPPORTS_M2M_HOLD_CAPTURE_BUF, "m2m-hold-capture-buf" },
 	{ V4L2_BUF_CAP_SUPPORTS_MMAP_CACHE_HINTS, "mmap-cache-hints" },
+	{ V4L2_BUF_CAP_SUPPORTS_MAX_NUM_BUFFERS, "set-max-num-buffers" },
 	{ 0, nullptr }
 };
 
diff --git a/utils/v4l2-compliance/v4l2-compliance.cpp b/utils/v4l2-compliance/v4l2-compliance.cpp
index ac6a8f80..a165ef5a 100644
--- a/utils/v4l2-compliance/v4l2-compliance.cpp
+++ b/utils/v4l2-compliance/v4l2-compliance.cpp
@@ -1453,6 +1453,7 @@  void testNode(struct node &node, struct node &node_m2m_cap, struct node &expbuf_
 
 		printf("Buffer ioctls%s:\n", suffix);
 		printf("\ttest VIDIOC_REQBUFS/CREATE_BUFS/QUERYBUF: %s\n", ok(testReqBufs(&node)));
+		printf("\ttest CREATE_BUFS maximum buffers: %s\n", ok(testCreateBufsMax(&node)));
 		// Reopen after each streaming test to reset the streaming state
 		// in case of any errors in the preceeding test.
 		node.reopen();
diff --git a/utils/v4l2-compliance/v4l2-compliance.h b/utils/v4l2-compliance/v4l2-compliance.h
index 7e3860c8..4f9aa17e 100644
--- a/utils/v4l2-compliance/v4l2-compliance.h
+++ b/utils/v4l2-compliance/v4l2-compliance.h
@@ -383,6 +383,7 @@  int testReqBufs(struct node *node);
 int testReadWrite(struct node *node);
 int testExpBuf(struct node *node);
 int testBlockingWait(struct node *node);
+int testCreateBufsMax(struct node *node);
 
 // 32-bit architecture, 32/64-bit time_t tests
 int testTime32_64(struct node *node);
diff --git a/utils/v4l2-compliance/v4l2-test-buffers.cpp b/utils/v4l2-compliance/v4l2-test-buffers.cpp
index 6d592c9b..e3c3db46 100644
--- a/utils/v4l2-compliance/v4l2-test-buffers.cpp
+++ b/utils/v4l2-compliance/v4l2-test-buffers.cpp
@@ -761,6 +761,47 @@  int testReqBufs(struct node *node)
 	return 0;
 }
 
+int testCreateBufsMax(struct node *node)
+{
+	unsigned int i;
+	int ret;
+
+	node->reopen();
+
+	cv4l_queue q(0, 0);
+
+	for (i = 1; i <= V4L2_BUF_TYPE_LAST; i++) {
+		if (!(node->valid_buftypes & (1 << i)))
+			continue;
+
+		q.init(i, V4L2_MEMORY_USERPTR);
+		ret = q.create_bufs(node, 1);
+		if (!ret && (q.g_capabilities() & V4L2_BUF_CAP_SUPPORTS_MAX_NUM_BUFFERS)) {
+			fail_on_test(q.create_bufs(node, q.g_max_buffers() - q.g_buffers()));
+			ret = q.create_bufs(node, 1);
+			fail_on_test(ret != ENOBUFS && (q.g_max_buffers() == q.g_buffers()));
+		}
+
+		q.init(i, V4L2_MEMORY_MMAP);
+		ret = q.create_bufs(node, 1);
+		if (!ret && (q.g_capabilities() & V4L2_BUF_CAP_SUPPORTS_MAX_NUM_BUFFERS)) {
+			fail_on_test(q.create_bufs(node, q.g_max_buffers() - q.g_buffers()));
+			ret = q.create_bufs(node, 1);
+			fail_on_test(ret != ENOBUFS && (q.g_max_buffers() == q.g_buffers()));
+		}
+
+		q.init(i, V4L2_MEMORY_DMABUF);
+		ret = q.create_bufs(node, 1);
+		if (!ret && (q.g_capabilities() & V4L2_BUF_CAP_SUPPORTS_MAX_NUM_BUFFERS)) {
+			fail_on_test(q.create_bufs(node, q.g_max_buffers() - q.g_buffers()));
+			ret = q.create_bufs(node, 1);
+			fail_on_test(ret != ENOBUFS && (q.g_max_buffers() == q.g_buffers()));
+		}
+	}
+
+	return 0;
+}
+
 int testExpBuf(struct node *node)
 {
 	bool have_expbuf = false;