From patchwork Thu Aug 2 20:48:45 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ezequiel Garcia X-Patchwork-Id: 10554221 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 4D63013B4 for ; Thu, 2 Aug 2018 20:49:04 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 39DAE2B184 for ; Thu, 2 Aug 2018 20:49:04 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 2DB8D2BE0C; Thu, 2 Aug 2018 20:49:04 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI,UNPARSEABLE_RELAY autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id B91332B184 for ; Thu, 2 Aug 2018 20:49:03 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730957AbeHBWlv (ORCPT ); Thu, 2 Aug 2018 18:41:51 -0400 Received: from bhuna.collabora.co.uk ([46.235.227.227]:50304 "EHLO bhuna.collabora.co.uk" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729763AbeHBWlv (ORCPT ); Thu, 2 Aug 2018 18:41:51 -0400 Received: from [127.0.0.1] (localhost [127.0.0.1]) (Authenticated sender: ezequiel) with ESMTPSA id C11EE27E20B From: Ezequiel Garcia To: linux-media@vger.kernel.org Cc: Hans Verkuil , kernel@collabora.com, paul.kocialkowski@bootlin.com, maxime.ripard@bootlin.com, Hans Verkuil , Shuah Khan , linux-kselftest@vger.kernel.org, Ezequiel Garcia Subject: [PATCH v4 1/6] mem2mem: Require capture and output mutexes to match Date: Thu, 2 Aug 2018 17:48:45 -0300 Message-Id: <20180802204850.31633-2-ezequiel@collabora.com> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20180802204850.31633-1-ezequiel@collabora.com> References: <20180802204850.31633-1-ezequiel@collabora.com> Sender: linux-kselftest-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kselftest@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Currently, all the mem2mem driver either use a single mutex to lock the capture and output videobuf2 queues, or don't set any mutex. This means the mutexes match, and so the mem2mem framework is able to set the m2m context lock. Enforce this by making it mandatory for drivers to set the same capture and output mutex, or not set any mutex at all. Signed-off-by: Ezequiel Garcia --- drivers/media/v4l2-core/v4l2-mem2mem.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/media/v4l2-core/v4l2-mem2mem.c b/drivers/media/v4l2-core/v4l2-mem2mem.c index 0a93c5b173c2..b7005894292c 100644 --- a/drivers/media/v4l2-core/v4l2-mem2mem.c +++ b/drivers/media/v4l2-core/v4l2-mem2mem.c @@ -887,12 +887,14 @@ struct v4l2_m2m_ctx *v4l2_m2m_ctx_init(struct v4l2_m2m_dev *m2m_dev, if (ret) goto err; /* - * If both queues use same mutex assign it as the common buffer - * queues lock to the m2m context. This lock is used in the - * v4l2_m2m_ioctl_* helpers. + * Both queues should use same the mutex to lock the m2m context. + * This lock is used in some v4l2_m2m_* helpers. */ - if (out_q_ctx->q.lock == cap_q_ctx->q.lock) - m2m_ctx->q_lock = out_q_ctx->q.lock; + if (WARN_ON(out_q_ctx->q.lock != cap_q_ctx->q.lock)) { + ret = -EINVAL; + goto err; + } + m2m_ctx->q_lock = out_q_ctx->q.lock; return m2m_ctx; err: From patchwork Thu Aug 2 20:48:46 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ezequiel Garcia X-Patchwork-Id: 10554225 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 263BC13B4 for ; Thu, 2 Aug 2018 20:49:08 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 124FB2B184 for ; Thu, 2 Aug 2018 20:49:08 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 063962BE0C; Thu, 2 Aug 2018 20:49:08 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI,UNPARSEABLE_RELAY autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 98B922B184 for ; Thu, 2 Aug 2018 20:49:07 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730431AbeHBWlz (ORCPT ); Thu, 2 Aug 2018 18:41:55 -0400 Received: from bhuna.collabora.co.uk ([46.235.227.227]:50316 "EHLO bhuna.collabora.co.uk" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729763AbeHBWlz (ORCPT ); Thu, 2 Aug 2018 18:41:55 -0400 Received: from [127.0.0.1] (localhost [127.0.0.1]) (Authenticated sender: ezequiel) with ESMTPSA id 0D06927E229 From: Ezequiel Garcia To: linux-media@vger.kernel.org Cc: Hans Verkuil , kernel@collabora.com, paul.kocialkowski@bootlin.com, maxime.ripard@bootlin.com, Hans Verkuil , Shuah Khan , linux-kselftest@vger.kernel.org, Ezequiel Garcia Subject: [PATCH v4 2/6] v4l2-ioctl.c: simplify locking for m2m devices Date: Thu, 2 Aug 2018 17:48:46 -0300 Message-Id: <20180802204850.31633-3-ezequiel@collabora.com> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20180802204850.31633-1-ezequiel@collabora.com> References: <20180802204850.31633-1-ezequiel@collabora.com> Sender: linux-kselftest-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kselftest@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Now that the mutexes for output and capture vb2 queues match, it is possible to refer to the context q_lock as the m2m lock for a given m2m context. Remove the output/capture lock selection. Signed-off-by: Ezequiel Garcia --- drivers/media/v4l2-core/v4l2-ioctl.c | 47 ++-------------------------- 1 file changed, 2 insertions(+), 45 deletions(-) diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c index 54afc9c7ee6e..c46c455df652 100644 --- a/drivers/media/v4l2-core/v4l2-ioctl.c +++ b/drivers/media/v4l2-core/v4l2-ioctl.c @@ -2677,45 +2677,6 @@ static bool v4l2_is_known_ioctl(unsigned int cmd) return v4l2_ioctls[_IOC_NR(cmd)].ioctl == cmd; } -#if IS_ENABLED(CONFIG_V4L2_MEM2MEM_DEV) -static bool v4l2_ioctl_m2m_queue_is_output(unsigned int cmd, void *arg) -{ - switch (cmd) { - case VIDIOC_CREATE_BUFS: { - struct v4l2_create_buffers *cbufs = arg; - - return V4L2_TYPE_IS_OUTPUT(cbufs->format.type); - } - case VIDIOC_REQBUFS: { - struct v4l2_requestbuffers *rbufs = arg; - - return V4L2_TYPE_IS_OUTPUT(rbufs->type); - } - case VIDIOC_QBUF: - case VIDIOC_DQBUF: - case VIDIOC_QUERYBUF: - case VIDIOC_PREPARE_BUF: { - struct v4l2_buffer *buf = arg; - - return V4L2_TYPE_IS_OUTPUT(buf->type); - } - case VIDIOC_EXPBUF: { - struct v4l2_exportbuffer *expbuf = arg; - - return V4L2_TYPE_IS_OUTPUT(expbuf->type); - } - case VIDIOC_STREAMON: - case VIDIOC_STREAMOFF: { - int *type = arg; - - return V4L2_TYPE_IS_OUTPUT(*type); - } - default: - return false; - } -} -#endif - static struct mutex *v4l2_ioctl_get_lock(struct video_device *vdev, struct v4l2_fh *vfh, unsigned int cmd, void *arg) @@ -2725,12 +2686,8 @@ static struct mutex *v4l2_ioctl_get_lock(struct video_device *vdev, #if IS_ENABLED(CONFIG_V4L2_MEM2MEM_DEV) if (vfh && vfh->m2m_ctx && (v4l2_ioctls[_IOC_NR(cmd)].flags & INFO_FL_QUEUE)) { - bool is_output = v4l2_ioctl_m2m_queue_is_output(cmd, arg); - struct v4l2_m2m_queue_ctx *ctx = is_output ? - &vfh->m2m_ctx->out_q_ctx : &vfh->m2m_ctx->cap_q_ctx; - - if (ctx->q.lock) - return ctx->q.lock; + if (vfh->m2m_ctx->q_lock) + return vfh->m2m_ctx->q_lock; } #endif if (vdev->queue && vdev->queue->lock && From patchwork Thu Aug 2 20:48:47 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ezequiel Garcia X-Patchwork-Id: 10554229 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 74B3C13BB for ; Thu, 2 Aug 2018 20:49:11 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 612F52BDFA for ; Thu, 2 Aug 2018 20:49:11 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 544792BE04; Thu, 2 Aug 2018 20:49:11 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI,UNPARSEABLE_RELAY autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 0C5092B184 for ; Thu, 2 Aug 2018 20:49:11 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729774AbeHBWl6 (ORCPT ); Thu, 2 Aug 2018 18:41:58 -0400 Received: from bhuna.collabora.co.uk ([46.235.227.227]:50326 "EHLO bhuna.collabora.co.uk" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729763AbeHBWl6 (ORCPT ); Thu, 2 Aug 2018 18:41:58 -0400 Received: from [127.0.0.1] (localhost [127.0.0.1]) (Authenticated sender: ezequiel) with ESMTPSA id 54300261486 From: Ezequiel Garcia To: linux-media@vger.kernel.org Cc: Hans Verkuil , kernel@collabora.com, paul.kocialkowski@bootlin.com, maxime.ripard@bootlin.com, Hans Verkuil , Shuah Khan , linux-kselftest@vger.kernel.org, Ezequiel Garcia Subject: [PATCH v4 3/6] v4l2-mem2mem: Avoid v4l2_m2m_prepare_buf from scheduling a job Date: Thu, 2 Aug 2018 17:48:47 -0300 Message-Id: <20180802204850.31633-4-ezequiel@collabora.com> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20180802204850.31633-1-ezequiel@collabora.com> References: <20180802204850.31633-1-ezequiel@collabora.com> Sender: linux-kselftest-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kselftest@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP There is no need for v4l2_m2m_prepare_buf to try to schedule a job, as it only prepares a buffer, but does not queue or changes the state of the queue. Remove the call to v4l2_m2m_try_schedule from v4l2_m2m_prepare_buf. Signed-off-by: Ezequiel Garcia --- drivers/media/v4l2-core/v4l2-mem2mem.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/media/v4l2-core/v4l2-mem2mem.c b/drivers/media/v4l2-core/v4l2-mem2mem.c index b7005894292c..6bdbdbfa8e6c 100644 --- a/drivers/media/v4l2-core/v4l2-mem2mem.c +++ b/drivers/media/v4l2-core/v4l2-mem2mem.c @@ -481,14 +481,9 @@ int v4l2_m2m_prepare_buf(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, struct v4l2_buffer *buf) { struct vb2_queue *vq; - int ret; vq = v4l2_m2m_get_vq(m2m_ctx, buf->type); - ret = vb2_prepare_buf(vq, buf); - if (!ret) - v4l2_m2m_try_schedule(m2m_ctx); - - return ret; + return vb2_prepare_buf(vq, buf); } EXPORT_SYMBOL_GPL(v4l2_m2m_prepare_buf); From patchwork Thu Aug 2 20:48:48 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ezequiel Garcia X-Patchwork-Id: 10554243 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 3721C13BB for ; Thu, 2 Aug 2018 20:49:25 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 232EF2C14A for ; Thu, 2 Aug 2018 20:49:25 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 154DC2C1CC; Thu, 2 Aug 2018 20:49:25 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI,UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id AB0002B184 for ; Thu, 2 Aug 2018 20:49:14 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1731423AbeHBWmC (ORCPT ); Thu, 2 Aug 2018 18:42:02 -0400 Received: from bhuna.collabora.co.uk ([46.235.227.227]:50336 "EHLO bhuna.collabora.co.uk" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729763AbeHBWmC (ORCPT ); Thu, 2 Aug 2018 18:42:02 -0400 Received: from [127.0.0.1] (localhost [127.0.0.1]) (Authenticated sender: ezequiel) with ESMTPSA id EE59227E20B From: Ezequiel Garcia To: linux-media@vger.kernel.org Cc: Hans Verkuil , kernel@collabora.com, paul.kocialkowski@bootlin.com, maxime.ripard@bootlin.com, Hans Verkuil , Shuah Khan , linux-kselftest@vger.kernel.org, Sakari Ailus , Ezequiel Garcia Subject: [PATCH v4 4/6] v4l2-mem2mem: Simplify exiting the function in __v4l2_m2m_try_schedule Date: Thu, 2 Aug 2018 17:48:48 -0300 Message-Id: <20180802204850.31633-5-ezequiel@collabora.com> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20180802204850.31633-1-ezequiel@collabora.com> References: <20180802204850.31633-1-ezequiel@collabora.com> Sender: linux-kselftest-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kselftest@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Sakari Ailus The __v4l2_m2m_try_schedule function acquires and releases multiple spinlocks. Simplify unlocking the job lock by adding labels to unlock the lock and exit the function. Signed-off-by: Sakari Ailus Signed-off-by: Ezequiel Garcia --- drivers/media/v4l2-core/v4l2-mem2mem.c | 29 ++++++++++++-------------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/drivers/media/v4l2-core/v4l2-mem2mem.c b/drivers/media/v4l2-core/v4l2-mem2mem.c index 6bdbdbfa8e6c..04e2c8357863 100644 --- a/drivers/media/v4l2-core/v4l2-mem2mem.c +++ b/drivers/media/v4l2-core/v4l2-mem2mem.c @@ -279,51 +279,48 @@ static void __v4l2_m2m_try_queue(struct v4l2_m2m_dev *m2m_dev, /* If the context is aborted then don't schedule it */ if (m2m_ctx->job_flags & TRANS_ABORT) { - spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags_job); dprintk("Aborted context\n"); - return; + goto job_unlock; } if (m2m_ctx->job_flags & TRANS_QUEUED) { - spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags_job); dprintk("On job queue already\n"); - return; + goto job_unlock; } spin_lock_irqsave(&m2m_ctx->out_q_ctx.rdy_spinlock, flags_out); if (list_empty(&m2m_ctx->out_q_ctx.rdy_queue) && !m2m_ctx->out_q_ctx.buffered) { - spin_unlock_irqrestore(&m2m_ctx->out_q_ctx.rdy_spinlock, - flags_out); - spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags_job); dprintk("No input buffers available\n"); - return; + goto out_unlock; } spin_lock_irqsave(&m2m_ctx->cap_q_ctx.rdy_spinlock, flags_cap); if (list_empty(&m2m_ctx->cap_q_ctx.rdy_queue) && !m2m_ctx->cap_q_ctx.buffered) { - spin_unlock_irqrestore(&m2m_ctx->cap_q_ctx.rdy_spinlock, - flags_cap); - spin_unlock_irqrestore(&m2m_ctx->out_q_ctx.rdy_spinlock, - flags_out); - spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags_job); dprintk("No output buffers available\n"); - return; + goto cap_unlock; } spin_unlock_irqrestore(&m2m_ctx->cap_q_ctx.rdy_spinlock, flags_cap); spin_unlock_irqrestore(&m2m_ctx->out_q_ctx.rdy_spinlock, flags_out); if (m2m_dev->m2m_ops->job_ready && (!m2m_dev->m2m_ops->job_ready(m2m_ctx->priv))) { - spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags_job); dprintk("Driver not ready\n"); - return; + goto job_unlock; } list_add_tail(&m2m_ctx->queue, &m2m_dev->job_queue); m2m_ctx->job_flags |= TRANS_QUEUED; spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags_job); + return; + +cap_unlock: + spin_unlock_irqrestore(&m2m_ctx->cap_q_ctx.rdy_spinlock, flags_cap); +out_unlock: + spin_unlock_irqrestore(&m2m_ctx->out_q_ctx.rdy_spinlock, flags_out); +job_unlock: + spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags_job); } /** From patchwork Thu Aug 2 20:48:49 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ezequiel Garcia X-Patchwork-Id: 10554237 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 0FF459093 for ; Thu, 2 Aug 2018 20:49:20 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id EB01E2C3B1 for ; Thu, 2 Aug 2018 20:49:19 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id E917A2C146; Thu, 2 Aug 2018 20:49:19 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI,UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 7E7DB2C146 for ; Thu, 2 Aug 2018 20:49:19 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1731952AbeHBWmH (ORCPT ); Thu, 2 Aug 2018 18:42:07 -0400 Received: from bhuna.collabora.co.uk ([46.235.227.227]:50348 "EHLO bhuna.collabora.co.uk" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729763AbeHBWmG (ORCPT ); Thu, 2 Aug 2018 18:42:06 -0400 Received: from [127.0.0.1] (localhost [127.0.0.1]) (Authenticated sender: ezequiel) with ESMTPSA id 805A6261486 From: Ezequiel Garcia To: linux-media@vger.kernel.org Cc: Hans Verkuil , kernel@collabora.com, paul.kocialkowski@bootlin.com, maxime.ripard@bootlin.com, Hans Verkuil , Shuah Khan , linux-kselftest@vger.kernel.org, Ezequiel Garcia Subject: [PATCH v4 5/6] v4l2-mem2mem: Avoid calling .device_run in v4l2_m2m_job_finish Date: Thu, 2 Aug 2018 17:48:49 -0300 Message-Id: <20180802204850.31633-6-ezequiel@collabora.com> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20180802204850.31633-1-ezequiel@collabora.com> References: <20180802204850.31633-1-ezequiel@collabora.com> Sender: linux-kselftest-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kselftest@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP v4l2_m2m_job_finish() is typically called in interrupt context. Some implementation of .device_run might sleep, and so it's desirable to avoid calling it directly from v4l2_m2m_job_finish(), thus avoiding .device_run from running in interrupt context. Implement a deferred context that calls v4l2_m2m_try_run, and gets scheduled by v4l2_m2m_job_finish(). Signed-off-by: Ezequiel Garcia --- drivers/media/v4l2-core/v4l2-mem2mem.c | 46 +++++++++++++++++++++++--- 1 file changed, 42 insertions(+), 4 deletions(-) diff --git a/drivers/media/v4l2-core/v4l2-mem2mem.c b/drivers/media/v4l2-core/v4l2-mem2mem.c index 04e2c8357863..020b2d8621d0 100644 --- a/drivers/media/v4l2-core/v4l2-mem2mem.c +++ b/drivers/media/v4l2-core/v4l2-mem2mem.c @@ -69,6 +69,7 @@ static const char * const m2m_entity_name[] = { * @curr_ctx: currently running instance * @job_queue: instances queued to run * @job_spinlock: protects job_queue + * @job_work: worker to run queued jobs. * @m2m_ops: driver callbacks */ struct v4l2_m2m_dev { @@ -85,6 +86,7 @@ struct v4l2_m2m_dev { struct list_head job_queue; spinlock_t job_spinlock; + struct work_struct job_work; const struct v4l2_m2m_ops *m2m_ops; }; @@ -224,10 +226,11 @@ EXPORT_SYMBOL(v4l2_m2m_get_curr_priv); /** * v4l2_m2m_try_run() - select next job to perform and run it if possible * @m2m_dev: per-device context + * @try_lock: indicates if the queue lock should be taken * * Get next transaction (if present) from the waiting jobs list and run it. */ -static void v4l2_m2m_try_run(struct v4l2_m2m_dev *m2m_dev) +static void v4l2_m2m_try_run(struct v4l2_m2m_dev *m2m_dev, bool try_lock) { unsigned long flags; @@ -250,7 +253,20 @@ static void v4l2_m2m_try_run(struct v4l2_m2m_dev *m2m_dev) spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags); dprintk("Running job on m2m_ctx: %p\n", m2m_dev->curr_ctx); + + /* + * A m2m context lock is taken only after a m2m context + * is picked from the queue and marked as running. + * The lock is only needed if v4l2_m2m_try_run is called + * from the async worker. + */ + if (try_lock && m2m_dev->curr_ctx->q_lock) + mutex_lock(m2m_dev->curr_ctx->q_lock); + m2m_dev->m2m_ops->device_run(m2m_dev->curr_ctx->priv); + + if (try_lock && m2m_dev->curr_ctx->q_lock) + mutex_unlock(m2m_dev->curr_ctx->q_lock); } /* @@ -330,7 +346,8 @@ static void __v4l2_m2m_try_queue(struct v4l2_m2m_dev *m2m_dev, * Check if this context is ready to queue a job. If suitable, * run the next queued job on the mem2mem device. * - * This function shouldn't run in interrupt context. + * This function shouldn't run in interrupt context, and must be called + * with the v4l2_m2m_ctx.q_lock mutex held. * * Note that v4l2_m2m_try_schedule() can schedule one job for this context, * and then run another job for another context. @@ -339,11 +356,26 @@ void v4l2_m2m_try_schedule(struct v4l2_m2m_ctx *m2m_ctx) { struct v4l2_m2m_dev *m2m_dev = m2m_ctx->m2m_dev; + if (m2m_ctx->q_lock) + WARN_ON(!mutex_is_locked(m2m_ctx->q_lock)); + __v4l2_m2m_try_queue(m2m_dev, m2m_ctx); - v4l2_m2m_try_run(m2m_dev); + v4l2_m2m_try_run(m2m_dev, false); } EXPORT_SYMBOL_GPL(v4l2_m2m_try_schedule); +/** + * v4l2_m2m_device_run_work() - run pending jobs for the context + * @work: Work structure used for scheduling the execution of this function. + */ +static void v4l2_m2m_device_run_work(struct work_struct *work) +{ + struct v4l2_m2m_dev *m2m_dev = + container_of(work, struct v4l2_m2m_dev, job_work); + + v4l2_m2m_try_run(m2m_dev, true); +} + /** * v4l2_m2m_cancel_job() - cancel pending jobs for the context * @m2m_ctx: m2m context with jobs to be canceled @@ -403,7 +435,12 @@ void v4l2_m2m_job_finish(struct v4l2_m2m_dev *m2m_dev, /* This instance might have more buffers ready, but since we do not * allow more than one job on the job_queue per instance, each has * to be scheduled separately after the previous one finishes. */ - v4l2_m2m_try_schedule(m2m_ctx); + __v4l2_m2m_try_queue(m2m_dev, m2m_ctx); + + /* We might be running in atomic context, + * but the job must be run in non-atomic context. + */ + schedule_work(&m2m_dev->job_work); } EXPORT_SYMBOL(v4l2_m2m_job_finish); @@ -837,6 +874,7 @@ struct v4l2_m2m_dev *v4l2_m2m_init(const struct v4l2_m2m_ops *m2m_ops) m2m_dev->m2m_ops = m2m_ops; INIT_LIST_HEAD(&m2m_dev->job_queue); spin_lock_init(&m2m_dev->job_spinlock); + INIT_WORK(&m2m_dev->job_work, v4l2_m2m_device_run_work); return m2m_dev; } From patchwork Thu Aug 2 20:48:50 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ezequiel Garcia X-Patchwork-Id: 10554239 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id A402C13B4 for ; Thu, 2 Aug 2018 20:49:23 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 90A722C14C for ; Thu, 2 Aug 2018 20:49:23 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 852F32C361; Thu, 2 Aug 2018 20:49:23 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI,UNPARSEABLE_RELAY autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id B52B52C28F for ; Thu, 2 Aug 2018 20:49:22 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1731638AbeHBWmK (ORCPT ); Thu, 2 Aug 2018 18:42:10 -0400 Received: from bhuna.collabora.co.uk ([46.235.227.227]:50356 "EHLO bhuna.collabora.co.uk" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729763AbeHBWmK (ORCPT ); Thu, 2 Aug 2018 18:42:10 -0400 Received: from [127.0.0.1] (localhost [127.0.0.1]) (Authenticated sender: ezequiel) with ESMTPSA id EA15B27E20B From: Ezequiel Garcia To: linux-media@vger.kernel.org Cc: Hans Verkuil , kernel@collabora.com, paul.kocialkowski@bootlin.com, maxime.ripard@bootlin.com, Hans Verkuil , Shuah Khan , linux-kselftest@vger.kernel.org, Ezequiel Garcia Subject: [PATCH v4 6/6] selftests: media_tests: Add a memory-to-memory concurrent stress test Date: Thu, 2 Aug 2018 17:48:50 -0300 Message-Id: <20180802204850.31633-7-ezequiel@collabora.com> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20180802204850.31633-1-ezequiel@collabora.com> References: <20180802204850.31633-1-ezequiel@collabora.com> Sender: linux-kselftest-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kselftest@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Add a test for the memory-to-memory framework, to exercise the scheduling of concurrent jobs, using multiple contexts. This test needs to be run using the vim2m virtual driver, and so needs no hardware. While here, rework the media_tests suite in order to make it useful for automatic tools. Those tests that need human intervention are now separated from those that can run automatically, needing only virtual drivers to work. Signed-off-by: Ezequiel Garcia --- .../testing/selftests/media_tests/.gitignore | 1 + tools/testing/selftests/media_tests/Makefile | 5 +- .../selftests/media_tests/m2m_job_test.c | 287 ++++++++++++++++++ .../selftests/media_tests/m2m_job_test.sh | 32 ++ 4 files changed, 324 insertions(+), 1 deletion(-) create mode 100644 tools/testing/selftests/media_tests/m2m_job_test.c create mode 100755 tools/testing/selftests/media_tests/m2m_job_test.sh diff --git a/tools/testing/selftests/media_tests/.gitignore b/tools/testing/selftests/media_tests/.gitignore index 8745eba39012..71c6508348ce 100644 --- a/tools/testing/selftests/media_tests/.gitignore +++ b/tools/testing/selftests/media_tests/.gitignore @@ -1,3 +1,4 @@ media_device_test media_device_open video_device_test +m2m_job_test diff --git a/tools/testing/selftests/media_tests/Makefile b/tools/testing/selftests/media_tests/Makefile index 60826d7d37d4..d25d4c3eb7d2 100644 --- a/tools/testing/selftests/media_tests/Makefile +++ b/tools/testing/selftests/media_tests/Makefile @@ -1,6 +1,9 @@ # SPDX-License-Identifier: GPL-2.0 # CFLAGS += -I../ -I../../../../usr/include/ -TEST_GEN_PROGS := media_device_test media_device_open video_device_test +TEST_GEN_PROGS_EXTENDED := media_device_test media_device_open video_device_test m2m_job_test +TEST_PROGS := m2m_job_test.sh include ../lib.mk + +LDLIBS += -lpthread diff --git a/tools/testing/selftests/media_tests/m2m_job_test.c b/tools/testing/selftests/media_tests/m2m_job_test.c new file mode 100644 index 000000000000..5800269567e6 --- /dev/null +++ b/tools/testing/selftests/media_tests/m2m_job_test.c @@ -0,0 +1,287 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Copyright (c) Collabora, Ltd. + +/* + * This file adds a test for the memory-to-memory + * framework. + * + * This test opens a user specified video device and then + * queues concurrent jobs. The jobs are totally dummy, + * its purpose is only to verify that each of the queued + * jobs is run, and is run only once. + * + * The vim2m driver is needed in order to run the test. + * + * Usage: + * ./m2m-job-test -d /dev/videoX + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "../kselftest.h" + +#define V4L2_CID_TRANS_TIME_MSEC (V4L2_CID_USER_BASE + 0x1000) +#define V4L2_CID_TRANS_NUM_BUFS (V4L2_CID_USER_BASE + 0x1001) + +#define MAX_TRANS_TIME_MSEC 500 +#define MAX_COUNT 50 +#define MAX_BUFFERS 5 +#define W 10 +#define H 10 + +#ifndef DEBUG +#define dprintf(fmt, arg...) \ + do { \ + } while (0) +#else +#define dprintf(fmt, arg...) printf(fmt, ## arg) +#endif + +static char video_device[256]; +static int thread_count; + +struct context { + int vfd; + unsigned int width; + unsigned int height; + int buffers; +}; + +static int req_src_buf(struct context *ctx, int buffers) +{ + struct v4l2_requestbuffers reqbuf; + struct v4l2_buffer buf; + int i, ret; + + memset(&reqbuf, 0, sizeof(reqbuf)); + memset(&buf, 0, sizeof(buf)); + + reqbuf.count = buffers; + reqbuf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; + reqbuf.memory = V4L2_MEMORY_MMAP; + ret = ioctl(ctx->vfd, VIDIOC_REQBUFS, &reqbuf); + if (ret) + return ret; + + for (i = 0; i < buffers; i++) { + buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; + buf.memory = V4L2_MEMORY_MMAP; + buf.index = i; + ret = ioctl(ctx->vfd, VIDIOC_QUERYBUF, &buf); + if (ret) + return ret; + buf.bytesused = W*H*2; + ret = ioctl(ctx->vfd, VIDIOC_QBUF, &buf); + if (ret) + return ret; + } + + return 0; +} + +static int req_dst_buf(struct context *ctx, int buffers) +{ + struct v4l2_requestbuffers reqbuf; + struct v4l2_buffer buf; + int i, ret; + + memset(&reqbuf, 0, sizeof(reqbuf)); + memset(&buf, 0, sizeof(buf)); + + reqbuf.count = buffers; + reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + reqbuf.memory = V4L2_MEMORY_MMAP; + + ret = ioctl(ctx->vfd, VIDIOC_REQBUFS, &reqbuf); + if (ret) + return ret; + + for (i = 0; i < buffers; i++) { + buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + buf.memory = V4L2_MEMORY_MMAP; + buf.index = i; + ret = ioctl(ctx->vfd, VIDIOC_QUERYBUF, &buf); + if (ret) + return ret; + ret = ioctl(ctx->vfd, VIDIOC_QBUF, &buf); + if (ret) + return ret; + } + return 0; +} + +static int streamon(struct context *ctx) +{ + enum v4l2_buf_type type; + int ret; + + type = V4L2_BUF_TYPE_VIDEO_OUTPUT; + ret = ioctl(ctx->vfd, VIDIOC_STREAMON, &type); + if (ret) + return ret; + + type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + ret = ioctl(ctx->vfd, VIDIOC_STREAMON, &type); + if (ret) + return ret; + + return ret; +} + +static int dqbuf(struct context *ctx) +{ + struct v4l2_buffer buf; + int i, ret, timeout; + + struct pollfd fds[] = { + { .fd = ctx->vfd, .events = POLLIN }, + }; + + for (i = 0; i < ctx->buffers; i++) { + timeout = (MAX_TRANS_TIME_MSEC + 10) * thread_count * 2; + ret = poll(fds, 1, timeout); + if (-1 == ret) { + if (errno == EINTR) + continue; + return -1; + } + + if (ret == 0) { + dprintf("%s: timeout on %p\n", __func__, ctx); + return -1; + } + + dprintf("%s: event on %p\n", __func__, ctx); + + memset(&buf, 0, sizeof(buf)); + buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; + buf.memory = V4L2_MEMORY_MMAP; + buf.index = i; + ret = ioctl(ctx->vfd, VIDIOC_DQBUF, &buf); + if (ret) { + dprintf("%s: VIDIOC_DQBUF failed %p\n", __func__, ctx); + return ret; + } + + memset(&buf, 0, sizeof(buf)); + buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + buf.memory = V4L2_MEMORY_MMAP; + buf.index = i; + ret = ioctl(ctx->vfd, VIDIOC_DQBUF, &buf); + if (ret) { + dprintf("%s: VIDIOC_DQBUF failed %p\n", __func__, ctx); + return ret; + } + } + + return 0; +} + +static void *job(void *arg) +{ + struct context *ctx = (struct context *)arg; + + dprintf("%s: %p running\n", __func__, ctx); + + assert(streamon(ctx) == 0); + assert(dqbuf(ctx) == 0); + assert(dqbuf(ctx) != 0); + close(ctx->vfd); + + dprintf("%s: %p done\n", __func__, ctx); + return NULL; +} + +static void init(struct context *ctx) +{ + struct v4l2_ext_controls ext_ctrls; + struct v4l2_ext_control ctrls[2]; + struct v4l2_capability cap; + int ret, buffers; + + memset(ctx, 0, sizeof(*ctx)); + + ctx->vfd = open(video_device, O_RDWR | O_NONBLOCK, 0); + ctx->width = W; + ctx->height = H; + assert(ctx->vfd >= 0); + + ret = ioctl(ctx->vfd, VIDIOC_QUERYCAP, &cap); + assert(ret == 0); + assert(cap.device_caps & V4L2_CAP_VIDEO_M2M); + if (strcmp((const char *)cap.driver, "vim2m") != 0) + ksft_exit_skip("Please run the test as root - Exiting.\n"); + + ctrls[0].id = V4L2_CID_TRANS_TIME_MSEC; + ctrls[0].value = rand() % MAX_TRANS_TIME_MSEC + 10; + ctrls[1].id = V4L2_CID_TRANS_NUM_BUFS; + ctrls[1].value = 1; + + memset(&ext_ctrls, 0, sizeof(ext_ctrls)); + ext_ctrls.count = 2; + ext_ctrls.controls = ctrls; + ret = ioctl(ctx->vfd, VIDIOC_S_EXT_CTRLS, &ext_ctrls); + assert(ret == 0); + + buffers = rand() % MAX_BUFFERS + 1; + assert(req_src_buf(ctx, buffers) == 0); + assert(req_dst_buf(ctx, buffers) == 0); + ctx->buffers = buffers; +} + +int main(int argc, char * const argv[]) +{ + int i, opt; + + if (argc < 2) { + printf("Usage: %s [-d ]\n", argv[0]); + exit(-1); + } + + /* Process arguments */ + while ((opt = getopt(argc, argv, "d:")) != -1) { + switch (opt) { + case 'd': + strncpy(video_device, optarg, sizeof(video_device) - 1); + video_device[sizeof(video_device)-1] = '\0'; + break; + default: + printf("Usage: %s [-d ]\n", argv[0]); + exit(-1); + } + } + + /* Generate random number of interations */ + srand((unsigned int) time(NULL)); + thread_count = rand() % MAX_COUNT + 1; + + pthread_t in_thread[thread_count]; + struct context ctx[thread_count]; + + printf("Running %d threads\n", thread_count); + + for (i = 0; i < thread_count; i++) + init(&ctx[i]); + + for (i = 0; i < thread_count; i++) + pthread_create(&in_thread[i], NULL, job, &ctx[i]); + + for (i = 0; i < thread_count; i++) + pthread_join(in_thread[i], NULL); + + return 0; +} diff --git a/tools/testing/selftests/media_tests/m2m_job_test.sh b/tools/testing/selftests/media_tests/m2m_job_test.sh new file mode 100755 index 000000000000..59777a7ac7d8 --- /dev/null +++ b/tools/testing/selftests/media_tests/m2m_job_test.sh @@ -0,0 +1,32 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 +TCID="media_device" + +# Kselftest framework requirement - SKIP code is 4. +ksft_skip=4 + +echo "-------------------" +echo "running media tests" +echo "-------------------" + +# Not needed, but does not hurt to have it +shopt -s nullglob + +v4l=/sys/class/video4linux + +if [ ! -d $v4l ]; then + echo "$TCID : video4linux support not present" + exit $ksft_skip +fi + +if [ -z `ls $v4l` ]; then + echo "$TCID : no video4linux drivers loaded, vim2m is needed" + exit $ksft_skip +fi + +for f in $v4l/*; do + dev_node=/dev/`basename $f` + if [ -c $dev_node ]; then + ./m2m_job_test -d $dev_node + fi +done