Merge "msm: wfd: Don't enforce FIFO ordering when buffers are returned"
diff --git a/drivers/media/platform/msm/wfd/vsg-subdev.c b/drivers/media/platform/msm/wfd/vsg-subdev.c
index e0a46cc..6ffaffa 100644
--- a/drivers/media/platform/msm/wfd/vsg-subdev.c
+++ b/drivers/media/platform/msm/wfd/vsg-subdev.c
@@ -462,8 +462,16 @@
static long vsg_return_ip_buffer(struct v4l2_subdev *sd, void *arg)
{
struct vsg_context *context = NULL;
- struct vsg_buf_info *buf_info = NULL, *last_buffer = NULL,
- *expected_buffer = NULL;
+ struct vsg_buf_info *buf_info = NULL, *temp = NULL,
+ /* last buffer sent for encoding */
+ *last_buffer = NULL,
+ /* buffer we expected to get back, ideally ==
+ * last_buffer, but might not be if sequence is
+ * encode, encode, return */
+ *expected_buffer = NULL,
+ /* buffer that we've sent for encoding at some point */
+ *known_buffer = NULL;
+ bool is_last_buffer = false;
int rc = 0;
if (!arg || !sd) {
@@ -477,41 +485,47 @@
buf_info = (struct vsg_buf_info *)arg;
last_buffer = context->last_buffer;
+ WFD_MSG_DBG("Return frame with paddr %p\n",
+ (void *)buf_info->mdp_buf_info.paddr);
+
if (!list_empty(&context->busy_queue.node)) {
expected_buffer = list_first_entry(&context->busy_queue.node,
struct vsg_buf_info, node);
}
- WFD_MSG_DBG("Return frame with paddr %p\n",
- (void *)buf_info->mdp_buf_info.paddr);
-
- if (!expected_buffer) {
- WFD_MSG_ERR("Unexpectedly received buffer from enc with "
- "paddr %p\n", (void *)buf_info->mdp_buf_info.paddr);
- goto return_ip_buf_bad_buf;
+ list_for_each_entry(temp, &context->busy_queue.node, node) {
+ if (mdp_buf_info_equals(&temp->mdp_buf_info,
+ &buf_info->mdp_buf_info)) {
+ known_buffer = temp;
+ break;
+ }
}
- expected_buffer->flags &= ~VSG_BUF_BEING_ENCODED;
- if (mdp_buf_info_equals(&expected_buffer->mdp_buf_info,
- &buf_info->mdp_buf_info)) {
- bool is_same_buffer = context->last_buffer &&
- mdp_buf_info_equals(
- &context->last_buffer->mdp_buf_info,
- &expected_buffer->mdp_buf_info);
-
- list_del(&expected_buffer->node);
- if (!is_same_buffer &&
- !(expected_buffer->flags & VSG_NEVER_RELEASE)) {
- vsg_release_input_buffer(context, expected_buffer);
- kfree(expected_buffer);
- }
- } else {
- WFD_MSG_ERR("Returned buffer %p is not latest buffer, "
- "expected %p\n",
- (void *)buf_info->mdp_buf_info.paddr,
- (void *)expected_buffer->mdp_buf_info.paddr);
- rc = -EINVAL;
+ if (!expected_buffer || !known_buffer) {
+ WFD_MSG_ERR("Unexpectedly received buffer from enc with "
+ "paddr %p\n", (void *)buf_info->mdp_buf_info.paddr);
+ rc = -EBADHANDLE;
goto return_ip_buf_bad_buf;
+ } else if (known_buffer != expected_buffer) {
+ /* Buffers can come back out of order if encoder decides to drop
+ * a frame */
+ WFD_MSG_DBG(
+ "Got a buffer (%p) out of order. Preferred to get %p\n",
+ (void *)known_buffer->mdp_buf_info.paddr,
+ (void *)expected_buffer->mdp_buf_info.paddr);
+ }
+
+ known_buffer->flags &= ~VSG_BUF_BEING_ENCODED;
+ is_last_buffer = context->last_buffer &&
+ mdp_buf_info_equals(
+ &context->last_buffer->mdp_buf_info,
+ &known_buffer->mdp_buf_info);
+
+ list_del(&known_buffer->node);
+ if (!is_last_buffer &&
+ !(known_buffer->flags & VSG_NEVER_RELEASE)) {
+ vsg_release_input_buffer(context, known_buffer);
+ kfree(known_buffer);
}
return_ip_buf_bad_buf: