From patchwork Wed Oct 26 12:06:06 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ricardo Ribalda X-Patchwork-Id: 619375 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id C1212C38A2D for ; Wed, 26 Oct 2022 12:06:41 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233675AbiJZMGk (ORCPT ); Wed, 26 Oct 2022 08:06:40 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:47490 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233681AbiJZMGg (ORCPT ); Wed, 26 Oct 2022 08:06:36 -0400 Received: from mail-ed1-x534.google.com (mail-ed1-x534.google.com [IPv6:2a00:1450:4864:20::534]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 3ADAB9187D for ; Wed, 26 Oct 2022 05:06:35 -0700 (PDT) Received: by mail-ed1-x534.google.com with SMTP id a13so41138765edj.0 for ; Wed, 26 Oct 2022 05:06:35 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=fw978dyctQKYz24O/MzUIY5FG9WdD7MbzKHKlFXG3Qw=; b=RNEWO8yCqIDykMwTYHMv+kJVII6rNKH4/P/QPL/q6horof/ZVy7k5E+Ma6ijN5FZT7 15Hz+LQn182NqAizezzVe12b8E2TcHlZ8UUeH5FyDycQZSMucG2V5Gr3cU+9JEvtJGZp tEzlJwyl/DwxrWQSyYJ5ns/LBFAR1kaoiyTlM= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=fw978dyctQKYz24O/MzUIY5FG9WdD7MbzKHKlFXG3Qw=; b=bEPjrVBeNovDSyJx1uAMatHVaF9xi3SJzvxQgNUnBP3tqLAw1t4fkc+Kl78qm9TKix pl9PTvPqTr8B+ebnATlqco+NG8vRG9zu+wl+N/ztDNgVEwENKtRb7NyDaRjSAoEEpSDP OWjvvbJRN8sCgzM6OcP6KkTs+Wvcu8bqlk2Wp3Denb4/hyS1wgSi15qhrTZNPZCWvUCG disTR5MbTPDzN0htLbOclyJ+VTofDvcFDI2AaKtMb9HYhnRr1H2nnTToK5gtDrtMce6L 9rv/s497jiI54xNF09ge8gL+Y95vDTt/RT8AKtK6o+wJmZm1kU77mws/wbxcIGLbTrat +mOw== X-Gm-Message-State: ACrzQf3fO3v0Y9bhxYc9LoohSCSW6XEI65xLdOiVOYVLwvDV4HQbsY9u sMU7buFLbQ0qFuKy/GyTKHfXAA== X-Google-Smtp-Source: AMsMyM6Xj2p6hg+jvEJSya5BuwT4Kpx4qv8a/7+7k8P8wA5vbIE5slKApQ8bk9uGkNaEKuOKdjWM2A== X-Received: by 2002:a05:6402:550e:b0:456:f79f:2bed with SMTP id fi14-20020a056402550e00b00456f79f2bedmr41217834edb.106.1666785993850; Wed, 26 Oct 2022 05:06:33 -0700 (PDT) Received: from alco.roam.corp.google.com ([2620:0:1059:10:b47a:bedd:2941:1e3f]) by smtp.gmail.com with ESMTPSA id y18-20020a17090668d200b0079e11b8e891sm2892546ejr.125.2022.10.26.05.06.33 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 26 Oct 2022 05:06:33 -0700 (PDT) From: Ricardo Ribalda Date: Wed, 26 Oct 2022 14:06:06 +0200 Subject: [PATCH v3 1/7] media: uvcvideo: Refactor streamon/streamoff MIME-Version: 1.0 Message-Id: <20220920-resend-powersave-v3-1-c47856d8757e@chromium.org> References: <20220920-resend-powersave-v3-0-c47856d8757e@chromium.org> In-Reply-To: <20220920-resend-powersave-v3-0-c47856d8757e@chromium.org> To: Mauro Carvalho Chehab Cc: Tomasz Figa , Ricardo Ribalda , Guenter Roeck , Max Staudt , linux-kernel@vger.kernel.org, Alan Stern , Hans Verkuil , Laurent Pinchart , linux-media@vger.kernel.org X-Mailer: b4 0.11.0-dev-d93f8 X-Developer-Signature: v=1; a=openpgp-sha256; l=1977; i=ribalda@chromium.org; h=from:subject:message-id; bh=NB6aEyZdAyQsktG3au/4ny2fc8G0li6jsr2nryh8gpk=; b=owEBbQKS/ZANAwAKAdE30T7POsSIAcsmYgBjWSK7fJwo06bKVIb5CIAm+Y73zwAAOjAjBzBn92Px 23qElF2JAjMEAAEKAB0WIQREDzjr+/4oCDLSsx7RN9E+zzrEiAUCY1kiuwAKCRDRN9E+zzrEiISqEA CbHxpyUE2B5x4mM0Jf0jPg9SdgW+xI++1ntCUxoIRnXqxPMmXIvKLdeSh84cYwk0Tba8PEn987ucuX cOHnIiROzdBvCHx8/sos6Xwq27u15CW+h57TKUu8DMiZsns2Cs/RZxt429+WvWcBaoK1ZxKS9//yoU HG41ExZRMxLuM1CicJfeRuX5Hjct00ITxOEpnMTMKgTEzdhBabLPZi3AhsGOylblf/VlZetxkZJo+d XjZlh3t52MfQ08uePxFSFVk1/HcK2s3ameYdCM+/PUBk1mkKrfLyqwrPGvMle+Dos+8nZKpw1hMFxH Tt8SUkAvIVFbyic4pi40EVk4aEQc4wQ2UcRn9MdniJd4TBgzrvoYgrF0xNnWGEiV7CCrPMQjDJOLSl KFs3drtskxxw/rwCbY/pVbeeBOua2fLa9rVpEsmifcybknI0Ycr48fZdLa7VZ4JztxYpBJN8PbMWsa /QhxRRqlkzNVa1CnjZaQrY6WCMp0rjeePxnlxrCTI4eK9T5bqlYHjOvnB8m9hlMmEU96XaO72ExYyp N+laziNK4zI/MqMDrIoV33iuGAqOyAWtMkpMZXcEzH2wxiIlxLSPp9osWvIXPu4uGYnVNd/VMI5mbH 6EF/xKxx7/oduzVEpAab17WU+7T/CGfN2KIXkNNMXG4i2PLvvDwIF1XuE1eA== X-Developer-Key: i=ribalda@chromium.org; a=openpgp; fpr=9EC3BB66E2FC129A6F90B39556A0D81F9F782DA9 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org Add a new variable to handle the streaming state and handle the streamoff errors, that were not handled before. Suggested-by: Laurent Pinchart Signed-off-by: Ricardo Ribalda diff --git a/drivers/media/usb/uvc/uvc_v4l2.c b/drivers/media/usb/uvc/uvc_v4l2.c index f4d4c33b6dfb..1389a87b8ae1 100644 --- a/drivers/media/usb/uvc/uvc_v4l2.c +++ b/drivers/media/usb/uvc/uvc_v4l2.c @@ -840,13 +840,19 @@ static int uvc_ioctl_streamon(struct file *file, void *fh, { struct uvc_fh *handle = fh; struct uvc_streaming *stream = handle->stream; - int ret; + int ret = -EBUSY; if (!uvc_has_privileges(handle)) return -EBUSY; mutex_lock(&stream->mutex); + + if (handle->is_streaming) + goto unlock; ret = uvc_queue_streamon(&stream->queue, type); + handle->is_streaming = !ret; + +unlock: mutex_unlock(&stream->mutex); return ret; @@ -857,15 +863,22 @@ static int uvc_ioctl_streamoff(struct file *file, void *fh, { struct uvc_fh *handle = fh; struct uvc_streaming *stream = handle->stream; + int ret = 0; if (!uvc_has_privileges(handle)) return -EBUSY; mutex_lock(&stream->mutex); - uvc_queue_streamoff(&stream->queue, type); + + if (!handle->is_streaming) + goto unlock; + ret = uvc_queue_streamoff(&stream->queue, type); + handle->is_streaming = !!ret; + +unlock: mutex_unlock(&stream->mutex); - return 0; + return ret; } static int uvc_ioctl_enum_input(struct file *file, void *fh, diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h index df93db259312..45310f55475f 100644 --- a/drivers/media/usb/uvc/uvcvideo.h +++ b/drivers/media/usb/uvc/uvcvideo.h @@ -581,6 +581,7 @@ enum uvc_handle_state { struct uvc_fh { struct v4l2_fh vfh; + bool is_streaming; struct uvc_video_chain *chain; struct uvc_streaming *stream; enum uvc_handle_state state; From patchwork Wed Oct 26 12:06:07 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ricardo Ribalda X-Patchwork-Id: 619110 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 362F2C433FE for ; Wed, 26 Oct 2022 12:06:43 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233666AbiJZMGl (ORCPT ); Wed, 26 Oct 2022 08:06:41 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:47530 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233652AbiJZMGh (ORCPT ); Wed, 26 Oct 2022 08:06:37 -0400 Received: from mail-ed1-x52b.google.com (mail-ed1-x52b.google.com [IPv6:2a00:1450:4864:20::52b]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 97931895DE for ; Wed, 26 Oct 2022 05:06:36 -0700 (PDT) Received: by mail-ed1-x52b.google.com with SMTP id a13so41138859edj.0 for ; Wed, 26 Oct 2022 05:06:36 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=Y3aLAqx1UmJhgGtzBHcHb9QyFZFPiOEXRjvNmq6X8fw=; b=edNMJTQ85mCASuHS8h6GXdQovCDGcQOiwkAINEAoQc7dobAkUSum7FUP0pj5QGoo/8 q97pUfK7BZ4E1QgE4/WH4axRkc2WK1fSO5yKYoet+fzVxfx93As7nA0IDrsex22+9r5u Uy5Fcto4Q4dxugJZYUUQeevzbFd9oY+7AqdtU= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=Y3aLAqx1UmJhgGtzBHcHb9QyFZFPiOEXRjvNmq6X8fw=; b=sEL8VGZ9Tch+rAoLt/ERjs4y7tljHSlmIopfAOFangma3jdUC2jozl5yoBMSYL15FS 5ZKkJqAST6tivrVTVSs0nWFMISXsDkvCsRRJ7s12H4fsREy/5FjD6cSNqRC0hS8iH0Xl gjQZEjimrAUq0cR05+m3D/UISoGnhiJIBaQ7l6u7insM0vHcLDLA/RO90Q3XwB+uQv7B UgaPVLB44SOZzsk2u4W8jCDX1mi8pn2FCP7B7byi/ZYrriFCVmGl++XLg+WS50oq/vSz 5X10KIvKvJgG8wb6vjG0GVca49FgJaaN4CiLzxeVG4KGqgi/b/QUmBQxGQFUrJ5gUN2X LzAw== X-Gm-Message-State: ACrzQf0u6AABHBJ7miSO4E3phEsJrW/VImwngUFHccBkD8UuxiZPTrmc UKLuo4x2TJKmgvsxu9yi8J5poQ== X-Google-Smtp-Source: AMsMyM5UOg1JMiWz7k0aqd85PLsiuGf7bdy7MmYF5Sio47TrLWMyrhddQLp6ZcBiOyI1/H6/ItlKOQ== X-Received: by 2002:a05:6402:414f:b0:456:c2c1:23ec with SMTP id x15-20020a056402414f00b00456c2c123ecmr41613747eda.420.1666785994930; Wed, 26 Oct 2022 05:06:34 -0700 (PDT) Received: from alco.roam.corp.google.com ([2620:0:1059:10:b47a:bedd:2941:1e3f]) by smtp.gmail.com with ESMTPSA id y18-20020a17090668d200b0079e11b8e891sm2892546ejr.125.2022.10.26.05.06.34 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 26 Oct 2022 05:06:34 -0700 (PDT) From: Ricardo Ribalda Date: Wed, 26 Oct 2022 14:06:07 +0200 Subject: [PATCH v3 2/7] media: uvcvideo: Do power management granularly MIME-Version: 1.0 Message-Id: <20220920-resend-powersave-v3-2-c47856d8757e@chromium.org> References: <20220920-resend-powersave-v3-0-c47856d8757e@chromium.org> In-Reply-To: <20220920-resend-powersave-v3-0-c47856d8757e@chromium.org> To: Mauro Carvalho Chehab Cc: Tomasz Figa , Ricardo Ribalda , Guenter Roeck , Max Staudt , linux-kernel@vger.kernel.org, Alan Stern , Hans Verkuil , Laurent Pinchart , linux-media@vger.kernel.org X-Mailer: b4 0.11.0-dev-d93f8 X-Developer-Signature: v=1; a=openpgp-sha256; l=10240; i=ribalda@chromium.org; h=from:subject:message-id; bh=9JC+xKdhqfQ07Aja2WDiXvrtLcLtkT6rTXo67NjWgLI=; b=owEBbQKS/ZANAwAKAdE30T7POsSIAcsmYgBjWSK+e2m3BA+oc+r9uya55vadcNyhns4KU+wqqUKm jTbsZ/iJAjMEAAEKAB0WIQREDzjr+/4oCDLSsx7RN9E+zzrEiAUCY1kivgAKCRDRN9E+zzrEiJQ0D/ 93ifgleBrzC1Hwpo7lXAsu1p/qdaCm8+jyMElrtHrqmJsTPwKibAhbgC6C7tKcz0h8sL9CidluN2EZ wdS/fcl/uusZ0I9xmRvqN7JziD4opT9aNtsNj3/tNb5V0qULQtUpCMUFb/5D2T3iiP6a2QwKOucIfV 5wuUjJo7MVOjsjKOifljGvGeKAWPVZEIMjbFLtqNePTXQJrS9auVLQXp8CseFBvT93oRQq+xw0oMfR 958OFHRRGJ6IGsURsJGZzge4F9BXgqgwDpptE19odLYycPVzC0/Sp5gGzvwFS03tBGQnW0gCNMQ54c xaHqAwp63p7T33kN+07YpzAUfeFEFaQy2U4hiULs7qThA60OtEIND7u1zDLVKauC9pQrHjZyZgix9C Gr6PnuKaAMra6AFxA/+07iZQkvv5TWg26w6CvqH2ZrW/FhUtBGP0aKDdHUyntH35H24ITEbRNEH0D7 38S/XIqgWSKOlqInU/R299NfBMEb/N4QB36wBp4d8vYoc8YuLvTlHm9eA0PPVarUp6HSc88EWVQWfS zkYYL6tnWGs1a+LTlx82RZQ/fu9V1y6jw3ovUjLaYXFf5y514hPLWiT+EmzpI3S9qVatY84VafZHIG AfpkpE6cG3CC8D3qR73pWwLgBYGPBVBILSsYIL79BSLVAYz/SixM5P8oJtnw== X-Developer-Key: i=ribalda@chromium.org; a=openpgp; fpr=9EC3BB66E2FC129A6F90B39556A0D81F9F782DA9 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org Instead of suspending/resume the USB device at open()/close(), do it when the device is actually used. This way we can reduce the power consumption when a service is holding the video device and leaving it in an idle state. Reviewed-by: Tomasz Figa Signed-off-by: Ricardo Ribalda diff --git a/drivers/media/usb/uvc/uvc_v4l2.c b/drivers/media/usb/uvc/uvc_v4l2.c index 1389a87b8ae1..f5b0f1905962 100644 --- a/drivers/media/usb/uvc/uvc_v4l2.c +++ b/drivers/media/usb/uvc/uvc_v4l2.c @@ -25,6 +25,46 @@ #include "uvcvideo.h" +/* ------------------------------------------------------------------------ + * UVC power management + */ + +static int uvc_pm_get(struct uvc_streaming *stream) +{ + int ret; + + ret = usb_autopm_get_interface(stream->dev->intf); + if (ret) + return ret; + + mutex_lock(&stream->dev->lock); + if (!stream->dev->users) + ret = uvc_status_start(stream->dev, GFP_KERNEL); + if (!ret) + stream->dev->users++; + mutex_unlock(&stream->dev->lock); + + if (ret) + usb_autopm_put_interface(stream->dev->intf); + + return ret; +} + +static void uvc_pm_put(struct uvc_streaming *stream) +{ + mutex_lock(&stream->dev->lock); + if (WARN_ON(!stream->dev->users)) { + mutex_unlock(&stream->dev->lock); + return; + } + stream->dev->users--; + if (!stream->dev->users) + uvc_status_stop(stream->dev); + mutex_unlock(&stream->dev->lock); + + usb_autopm_put_interface(stream->dev->intf); +} + /* ------------------------------------------------------------------------ * UVC ioctls */ @@ -249,6 +289,9 @@ static int uvc_v4l2_try_format(struct uvc_streaming *stream, * developers test their webcams with the Linux driver as well as with * the Windows driver). */ + ret = uvc_pm_get(stream); + if (ret) + return ret; mutex_lock(&stream->mutex); if (stream->dev->quirks & UVC_QUIRK_PROBE_EXTRAFIELDS) probe->dwMaxVideoFrameSize = @@ -257,6 +300,7 @@ static int uvc_v4l2_try_format(struct uvc_streaming *stream, /* Probe the device. */ ret = uvc_probe_video(stream, probe); mutex_unlock(&stream->mutex); + uvc_pm_put(stream); if (ret < 0) return ret; @@ -468,7 +512,13 @@ static int uvc_v4l2_set_streamparm(struct uvc_streaming *stream, } /* Probe the device with the new settings. */ + ret = uvc_pm_get(stream); + if (ret) { + mutex_unlock(&stream->mutex); + return ret; + } ret = uvc_probe_video(stream, &probe); + uvc_pm_put(stream); if (ret < 0) { mutex_unlock(&stream->mutex); return ret; @@ -559,36 +609,29 @@ static int uvc_v4l2_open(struct file *file) { struct uvc_streaming *stream; struct uvc_fh *handle; - int ret = 0; stream = video_drvdata(file); uvc_dbg(stream->dev, CALLS, "%s\n", __func__); - ret = usb_autopm_get_interface(stream->dev->intf); - if (ret < 0) - return ret; - /* Create the device handle. */ handle = kzalloc(sizeof(*handle), GFP_KERNEL); - if (handle == NULL) { - usb_autopm_put_interface(stream->dev->intf); + if (!handle) return -ENOMEM; - } - mutex_lock(&stream->dev->lock); - if (stream->dev->users == 0) { - ret = uvc_status_start(stream->dev, GFP_KERNEL); - if (ret < 0) { - mutex_unlock(&stream->dev->lock); - usb_autopm_put_interface(stream->dev->intf); + /* + * If the uvc evdev exists we cannot suspend when the device + * is idle. Otherwise we will miss button actions. + */ + if (stream->dev->input) { + int ret; + + ret = uvc_pm_get(stream); + if (ret) { kfree(handle); return ret; } } - stream->dev->users++; - mutex_unlock(&stream->dev->lock); - v4l2_fh_init(&handle->vfh, &stream->vdev); v4l2_fh_add(&handle->vfh); handle->chain = stream->chain; @@ -610,6 +653,12 @@ static int uvc_v4l2_release(struct file *file) if (uvc_has_privileges(handle)) uvc_queue_release(&stream->queue); + if (handle->is_streaming) + uvc_pm_put(stream); + + if (stream->dev->input) + uvc_pm_put(stream); + /* Release the file handle. */ uvc_dismiss_privileges(handle); v4l2_fh_del(&handle->vfh); @@ -617,12 +666,6 @@ static int uvc_v4l2_release(struct file *file) kfree(handle); file->private_data = NULL; - mutex_lock(&stream->dev->lock); - if (--stream->dev->users == 0) - uvc_status_stop(stream->dev); - mutex_unlock(&stream->dev->lock); - - usb_autopm_put_interface(stream->dev->intf); return 0; } @@ -849,9 +892,17 @@ static int uvc_ioctl_streamon(struct file *file, void *fh, if (handle->is_streaming) goto unlock; + + ret = uvc_pm_get(stream); + if (ret) + goto unlock; + ret = uvc_queue_streamon(&stream->queue, type); handle->is_streaming = !ret; + if (!handle->is_streaming) + uvc_pm_put(stream); + unlock: mutex_unlock(&stream->mutex); @@ -875,6 +926,9 @@ static int uvc_ioctl_streamoff(struct file *file, void *fh, ret = uvc_queue_streamoff(&stream->queue, type); handle->is_streaming = !!ret; + if (!handle->is_streaming) + uvc_pm_put(stream); + unlock: mutex_unlock(&stream->mutex); @@ -928,6 +982,7 @@ static int uvc_ioctl_g_input(struct file *file, void *fh, unsigned int *input) { struct uvc_fh *handle = fh; struct uvc_video_chain *chain = handle->chain; + struct uvc_streaming *stream = handle->stream; u8 *buf; int ret; @@ -941,9 +996,16 @@ static int uvc_ioctl_g_input(struct file *file, void *fh, unsigned int *input) if (!buf) return -ENOMEM; + ret = uvc_pm_get(stream); + if (ret) { + kfree(buf); + return ret; + } + ret = uvc_query_ctrl(chain->dev, UVC_GET_CUR, chain->selector->id, chain->dev->intfnum, UVC_SU_INPUT_SELECT_CONTROL, buf, 1); + uvc_pm_put(stream); if (!ret) *input = *buf - 1; @@ -956,6 +1018,7 @@ static int uvc_ioctl_s_input(struct file *file, void *fh, unsigned int input) { struct uvc_fh *handle = fh; struct uvc_video_chain *chain = handle->chain; + struct uvc_streaming *stream = handle->stream; u8 *buf; int ret; @@ -977,10 +1040,17 @@ static int uvc_ioctl_s_input(struct file *file, void *fh, unsigned int input) if (!buf) return -ENOMEM; + ret = uvc_pm_get(stream); + if (ret) { + kfree(buf); + return ret; + } + *buf = input + 1; ret = uvc_query_ctrl(chain->dev, UVC_SET_CUR, chain->selector->id, chain->dev->intfnum, UVC_SU_INPUT_SELECT_CONTROL, buf, 1); + uvc_pm_put(stream); kfree(buf); return ret; @@ -991,8 +1061,15 @@ static int uvc_ioctl_queryctrl(struct file *file, void *fh, { struct uvc_fh *handle = fh; struct uvc_video_chain *chain = handle->chain; + struct uvc_streaming *stream = handle->stream; + int ret; - return uvc_query_v4l2_ctrl(chain, qc); + ret = uvc_pm_get(stream); + if (ret) + return ret; + ret = uvc_query_v4l2_ctrl(chain, qc); + uvc_pm_put(stream); + return ret; } static int uvc_ioctl_query_ext_ctrl(struct file *file, void *fh, @@ -1000,10 +1077,15 @@ static int uvc_ioctl_query_ext_ctrl(struct file *file, void *fh, { struct uvc_fh *handle = fh; struct uvc_video_chain *chain = handle->chain; + struct uvc_streaming *stream = handle->stream; struct v4l2_queryctrl qc = { qec->id }; int ret; + ret = uvc_pm_get(stream); + if (ret) + return ret; ret = uvc_query_v4l2_ctrl(chain, &qc); + uvc_pm_put(stream); if (ret) return ret; @@ -1049,6 +1131,7 @@ static int uvc_ioctl_g_ext_ctrls(struct file *file, void *fh, { struct uvc_fh *handle = fh; struct uvc_video_chain *chain = handle->chain; + struct uvc_streaming *stream = handle->stream; struct v4l2_ext_control *ctrl = ctrls->controls; unsigned int i; int ret; @@ -1073,22 +1156,30 @@ static int uvc_ioctl_g_ext_ctrls(struct file *file, void *fh, return 0; } + ret = uvc_pm_get(stream); + if (ret) + return ret; ret = uvc_ctrl_begin(chain); - if (ret < 0) + if (ret < 0) { + uvc_pm_put(stream); return ret; + } for (i = 0; i < ctrls->count; ++ctrl, ++i) { ret = uvc_ctrl_get(chain, ctrl); if (ret < 0) { uvc_ctrl_rollback(handle); ctrls->error_idx = i; - return ret; + goto done; } } ctrls->error_idx = 0; - return uvc_ctrl_rollback(handle); + ret = uvc_ctrl_rollback(handle); +done: + uvc_pm_put(stream); + return ret; } static int uvc_ioctl_s_try_ext_ctrls(struct uvc_fh *handle, @@ -1097,6 +1188,7 @@ static int uvc_ioctl_s_try_ext_ctrls(struct uvc_fh *handle, { struct v4l2_ext_control *ctrl = ctrls->controls; struct uvc_video_chain *chain = handle->chain; + struct uvc_streaming *stream = handle->stream; unsigned int i; int ret; @@ -1104,9 +1196,15 @@ static int uvc_ioctl_s_try_ext_ctrls(struct uvc_fh *handle, if (ret < 0) return ret; + ret = uvc_pm_get(stream); + if (ret) + return ret; + ret = uvc_ctrl_begin(chain); - if (ret < 0) + if (ret < 0) { + uvc_pm_put(stream); return ret; + } for (i = 0; i < ctrls->count; ++ctrl, ++i) { ret = uvc_ctrl_set(handle, ctrl); @@ -1114,16 +1212,20 @@ static int uvc_ioctl_s_try_ext_ctrls(struct uvc_fh *handle, uvc_ctrl_rollback(handle); ctrls->error_idx = ioctl == VIDIOC_S_EXT_CTRLS ? ctrls->count : i; - return ret; + goto done; } } ctrls->error_idx = 0; if (ioctl == VIDIOC_S_EXT_CTRLS) - return uvc_ctrl_commit(handle, ctrls); + ret = uvc_ctrl_commit(handle, ctrls); else - return uvc_ctrl_rollback(handle); + ret = uvc_ctrl_rollback(handle); + +done: + uvc_pm_put(stream); + return ret; } static int uvc_ioctl_s_ext_ctrls(struct file *file, void *fh, @@ -1147,8 +1249,16 @@ static int uvc_ioctl_querymenu(struct file *file, void *fh, { struct uvc_fh *handle = fh; struct uvc_video_chain *chain = handle->chain; + struct uvc_streaming *stream = handle->stream; + int ret; + + ret = uvc_pm_get(stream); + if (ret) + return ret; + ret = uvc_query_v4l2_menu(chain, qm); + uvc_pm_put(stream); - return uvc_query_v4l2_menu(chain, qm); + return ret; } static int uvc_ioctl_g_selection(struct file *file, void *fh, From patchwork Wed Oct 26 12:06:08 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ricardo Ribalda X-Patchwork-Id: 619374 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id CD850ECDFA1 for ; Wed, 26 Oct 2022 12:06:44 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233678AbiJZMGn (ORCPT ); Wed, 26 Oct 2022 08:06:43 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:47496 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233640AbiJZMGi (ORCPT ); Wed, 26 Oct 2022 08:06:38 -0400 Received: from mail-ej1-x62b.google.com (mail-ej1-x62b.google.com [IPv6:2a00:1450:4864:20::62b]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 9638089CE7 for ; Wed, 26 Oct 2022 05:06:37 -0700 (PDT) Received: by mail-ej1-x62b.google.com with SMTP id y14so20580351ejd.9 for ; Wed, 26 Oct 2022 05:06:37 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=AqAVGKJsGpAiDy8QH7vQCuUMfc+5BKxsR+DFSmRJpWo=; b=XDmKR2Z7KTJnbUjGeC8zmqBt0V198AEmIzxVjLZBBIVqjc+O5gri3l4XhykXTAfV8u vmAgUG4pNEciPdCyVOpgoteEN1gcSfQDBahjX6SkliA+Dz+P3qHnPhIZ+OleY/IBQnep QO40c8bISPt8xTR9RCsBVtOG/obMhv9CXcXBs= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=AqAVGKJsGpAiDy8QH7vQCuUMfc+5BKxsR+DFSmRJpWo=; b=Z938tDBwba9+LsE/pqjQBT8kdKg6QUKt0T2eurqU8kWiWSJ7Uz1hX2of3LMD1gwiPO VoXnoq7RZNtHCwjSWYTOSKzVwJu4AeZcanjtEfxwPxyemeDKomnntj8VAYZVwPoIi2Fs GCQlA8rkguIa+ZfPViP4DpOBgitvP7H7/6ur3N4m5DNhB/1UFYqVPcRJYmRJxMnx6kPX z+9ZKVvrGf0dpg9y1vrwIGs2IFeLg3ms/dexIHFg4Xb4zWCGqWYiObSmMOi4Q8i2p8HD DOC2yArDUFOmBx0BvoYBTdG0VUzKp4jlD4OK+DOpz67SrdtZwh0ga9As1awATBF6Znke q5UQ== X-Gm-Message-State: ACrzQf0oHTRoXR3T8DJpRo3Ck9wpGeb3bCkIo/1sCcORBUkA0OY7BCjj Jpygo9XoTDv7dcPQoTTTSuqv9A== X-Google-Smtp-Source: AMsMyM6pqwAq908Ifv/m8kcz/Hpbspm4mdhnPlreUe33TEqSOqF0j0v+5feOzeQ2AFKSCo+e3EQLIw== X-Received: by 2002:a17:907:3e85:b0:73d:60cc:5d06 with SMTP id hs5-20020a1709073e8500b0073d60cc5d06mr38359298ejc.722.1666785996191; Wed, 26 Oct 2022 05:06:36 -0700 (PDT) Received: from alco.roam.corp.google.com ([2620:0:1059:10:b47a:bedd:2941:1e3f]) by smtp.gmail.com with ESMTPSA id y18-20020a17090668d200b0079e11b8e891sm2892546ejr.125.2022.10.26.05.06.35 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 26 Oct 2022 05:06:35 -0700 (PDT) From: Ricardo Ribalda Date: Wed, 26 Oct 2022 14:06:08 +0200 Subject: [PATCH v3 3/7] media: uvcvideo: Only call status ep if hw supports it MIME-Version: 1.0 Message-Id: <20220920-resend-powersave-v3-3-c47856d8757e@chromium.org> References: <20220920-resend-powersave-v3-0-c47856d8757e@chromium.org> In-Reply-To: <20220920-resend-powersave-v3-0-c47856d8757e@chromium.org> To: Mauro Carvalho Chehab Cc: Tomasz Figa , Ricardo Ribalda , Guenter Roeck , Max Staudt , linux-kernel@vger.kernel.org, Alan Stern , Hans Verkuil , Laurent Pinchart , linux-media@vger.kernel.org X-Mailer: b4 0.11.0-dev-d93f8 X-Developer-Signature: v=1; a=openpgp-sha256; l=4446; i=ribalda@chromium.org; h=from:subject:message-id; bh=F8pfFKADrjPOkMpJU6y1lLHTtr/oz5pvCH4FNibFbG8=; b=owEBbQKS/ZANAwAKAdE30T7POsSIAcsmYgBjWSLAurZv8vh+QEbWr0OdhYu2rsG6+WOCxbGXwS+m ez176O+JAjMEAAEKAB0WIQREDzjr+/4oCDLSsx7RN9E+zzrEiAUCY1kiwAAKCRDRN9E+zzrEiF7tD/ 9ybn2voA0FAQGMcdiNEyxfLo+fjDkj1uSkmMHeoaYff48tRx0DaeQSsKFvyx+49aeafZK/t8ENhe3w WDzbLNac8KSI4hm3dmnDIO6hW7XzPUFX0hBHeAwvd4+2EizI+Ygg4nnG6uShEuUv/Wj4ELtwHUiTYI D+KrUErS4MTv5/x/Wyo7Ze4Uv+hv7IFr99slHLK+ObaGmSyJ8FWdp3OKadu0mNTKeiqHJgUpbWlT32 ODjIed2UZpL5A3JF4nG1DYhFPpAUxrA/xfsx3JM1wprfA2uVKJMdX9GcPaxBPaxEl8zW9NS0IiEW9p a9Pr0I/qFX4swCzz2Pj3xX3IUAG7qacFt2zj5CK8tzduxJpsgzhOL7B+7Gj0CHZUDNNtD4DrAObXh/ mGnwIAY9O1p6MaqfhygTrYEQb3OpUufC4rbDDvO4J0Y7106rKZflHf/7AGLi98Pjn82qb4Ouh7HNaI vYvE998QjUFRijxkqSGP+yP4W1FTsluiUTawzv9RmmG9KpjOAo3ak/nNH6j2J6WE+XswQ7EI0WWdAk PBju0sU7WmVsJAxz7Ori1HbLY0pUTkWxo/VI2B373jPmYID2/5cIhj9nzWna1stHzGZicB3irin0Vm zpjU6rcaRZPQtHJlKH09PCNb1Wy+D5uz6okKF120YbTC8kq5GLiYYkbcw4TQ== X-Developer-Key: i=ribalda@chromium.org; a=openpgp; fpr=9EC3BB66E2FC129A6F90B39556A0D81F9F782DA9 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org Instead of calling uvc_status_* regardless if the hw supports it or not, make all the calls conditional. This simplifies the locking during suspend/resume. Signed-off-by: Ricardo Ribalda diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c index bd3716a359b0..ac87dee77f44 100644 --- a/drivers/media/usb/uvc/uvc_driver.c +++ b/drivers/media/usb/uvc/uvc_driver.c @@ -1837,7 +1837,8 @@ static void uvc_delete(struct kref *kref) struct uvc_device *dev = container_of(kref, struct uvc_device, ref); struct list_head *p, *n; - uvc_status_cleanup(dev); + if (dev->int_ep) + uvc_status_cleanup(dev); uvc_ctrl_cleanup_device(dev); usb_put_intf(dev->intf); @@ -1898,7 +1899,8 @@ static void uvc_unregister_video(struct uvc_device *dev) uvc_debugfs_cleanup_stream(stream); } - uvc_status_unregister(dev); + if (dev->int_ep) + uvc_status_unregister(dev); if (dev->vdev.dev) v4l2_device_unregister(&dev->vdev); @@ -2199,10 +2201,13 @@ static int uvc_probe(struct usb_interface *intf, usb_set_intfdata(intf, dev); /* Initialize the interrupt URB. */ - if ((ret = uvc_status_init(dev)) < 0) { - dev_info(&dev->udev->dev, - "Unable to initialize the status endpoint (%d), status interrupt will not be supported.\n", - ret); + if (dev->int_ep) { + ret = uvc_status_init(dev); + if (ret < 0) { + dev_info(&dev->udev->dev, + "Unable to initialize the status endpoint (%d), status interrupt will not be supported.\n", + ret); + } } ret = uvc_gpio_init_irq(dev); @@ -2251,6 +2256,8 @@ static int uvc_suspend(struct usb_interface *intf, pm_message_t message) /* Controls are cached on the fly so they don't need to be saved. */ if (intf->cur_altsetting->desc.bInterfaceSubClass == UVC_SC_VIDEOCONTROL) { + if (!dev->int_ep) + return 0; mutex_lock(&dev->lock); if (dev->users) uvc_status_stop(dev); @@ -2285,6 +2292,9 @@ static int __uvc_resume(struct usb_interface *intf, int reset) return ret; } + if (!dev->int_ep) + return ret; + mutex_lock(&dev->lock); if (dev->users) ret = uvc_status_start(dev, GFP_NOIO); diff --git a/drivers/media/usb/uvc/uvc_status.c b/drivers/media/usb/uvc/uvc_status.c index cb90aff344bc..627cf11066e7 100644 --- a/drivers/media/usb/uvc/uvc_status.c +++ b/drivers/media/usb/uvc/uvc_status.c @@ -277,7 +277,7 @@ int uvc_status_init(struct uvc_device *dev) unsigned int pipe; int interval; - if (ep == NULL) + if (WARN_ON(!ep)) return 0; uvc_input_init(dev); @@ -312,19 +312,23 @@ int uvc_status_init(struct uvc_device *dev) void uvc_status_unregister(struct uvc_device *dev) { + if (WARN_ON(!dev->int_ep)) + return; usb_kill_urb(dev->int_urb); uvc_input_unregister(dev); } void uvc_status_cleanup(struct uvc_device *dev) { + if (WARN_ON(!dev->int_ep)) + return; usb_free_urb(dev->int_urb); kfree(dev->status); } int uvc_status_start(struct uvc_device *dev, gfp_t flags) { - if (dev->int_urb == NULL) + if (WARN_ON(!dev->int_ep) || !dev->int_urb) return 0; return usb_submit_urb(dev->int_urb, flags); @@ -332,5 +336,8 @@ int uvc_status_start(struct uvc_device *dev, gfp_t flags) void uvc_status_stop(struct uvc_device *dev) { + if (WARN_ON(!dev->int_ep) || !dev->int_urb) + return; + usb_kill_urb(dev->int_urb); } diff --git a/drivers/media/usb/uvc/uvc_v4l2.c b/drivers/media/usb/uvc/uvc_v4l2.c index f5b0f1905962..77b687c46082 100644 --- a/drivers/media/usb/uvc/uvc_v4l2.c +++ b/drivers/media/usb/uvc/uvc_v4l2.c @@ -37,6 +37,9 @@ static int uvc_pm_get(struct uvc_streaming *stream) if (ret) return ret; + if (!stream->dev->int_ep) + return 0; + mutex_lock(&stream->dev->lock); if (!stream->dev->users) ret = uvc_status_start(stream->dev, GFP_KERNEL); @@ -52,6 +55,9 @@ static int uvc_pm_get(struct uvc_streaming *stream) static void uvc_pm_put(struct uvc_streaming *stream) { + if (!stream->dev->int_ep) + goto done; + mutex_lock(&stream->dev->lock); if (WARN_ON(!stream->dev->users)) { mutex_unlock(&stream->dev->lock); @@ -62,6 +68,7 @@ static void uvc_pm_put(struct uvc_streaming *stream) uvc_status_stop(stream->dev); mutex_unlock(&stream->dev->lock); +done: usb_autopm_put_interface(stream->dev->intf); } From patchwork Wed Oct 26 12:06:09 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ricardo Ribalda X-Patchwork-Id: 619372 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id B1943C38A2D for ; Wed, 26 Oct 2022 12:07:27 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233800AbiJZMHY (ORCPT ); Wed, 26 Oct 2022 08:07:24 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:48880 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233750AbiJZMHP (ORCPT ); Wed, 26 Oct 2022 08:07:15 -0400 Received: from mail-lf1-x130.google.com (mail-lf1-x130.google.com [IPv6:2a00:1450:4864:20::130]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B01EEB2745 for ; Wed, 26 Oct 2022 05:06:49 -0700 (PDT) Received: by mail-lf1-x130.google.com with SMTP id b2so28090605lfp.6 for ; Wed, 26 Oct 2022 05:06:49 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=dhCAhO1KizZsj2zV3Y1+5lSZUzxRxUUnW3l6ylAL+HQ=; b=PariO7jBXkPxi7oaWf9UcPRM4x2uQhz0hxR0+FonRFFcZHjVos/FnvtjA2+bqitZ6o W8/kGkD0W67rfGi3V2wQwXRqlDB/CCEXMOqp37fpXblzvOEeXtRY8uWGPnJ3905RNRtt FVe8TFqdEUQ+heATy36Al/QFJSCaHzPcxD+u4= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=dhCAhO1KizZsj2zV3Y1+5lSZUzxRxUUnW3l6ylAL+HQ=; b=YEZj4QOMsVhsBKEIyjaYceic0LcveAMnOkgnK1SJSqXiQSOnhaXAAKqUyuW55s+Gbn GM7Tg8l4hywBp0iO3Fym5ZMeS3j6muqpgkRqHvAUhyLfPHItp3TfRbySHlLlaZNkjZEp Mep0sh/oG3Gf1xdprEzvKlKNeZ1tg3dKu9MPP7rGnvgU8Hs2U/5xTY86YNKPRRcZoqhw YnN4rc5IGUeobDlzkmLu7SeAw1h+yRluiBzLG58dyYAP9F59V0tGH7GhhpN08GICWWZ8 9zWMlmybVfyW3v5TxI1n/lu+pBuaGy8BF+JsIzMR6RTWy1k+ISuMQ3et1aV9xc5s2ZEk p3uQ== X-Gm-Message-State: ACrzQf3Np0LVQ3n8AaILFnlDyYcwbafwpkFqOIO4aYVI6r/I/5E5ab3v IDgEMIZ5uTNCxCDJRKNFx8zHp5dQEOLnyvyX X-Google-Smtp-Source: AMsMyM5LjzKcRywTls07k9t/YXG8rGkd19MTusoAXTQ+lJelo1ae3d4j3cRVczlardGMTGkyTaP7ig== X-Received: by 2002:a17:907:80d:b0:73d:a576:dfbd with SMTP id wv13-20020a170907080d00b0073da576dfbdmr36953678ejb.402.1666785997192; Wed, 26 Oct 2022 05:06:37 -0700 (PDT) Received: from alco.roam.corp.google.com ([2620:0:1059:10:b47a:bedd:2941:1e3f]) by smtp.gmail.com with ESMTPSA id y18-20020a17090668d200b0079e11b8e891sm2892546ejr.125.2022.10.26.05.06.36 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 26 Oct 2022 05:06:36 -0700 (PDT) From: Ricardo Ribalda Date: Wed, 26 Oct 2022 14:06:09 +0200 Subject: [PATCH v3 4/7] media: uvcvideo: Cancel async worker earlier MIME-Version: 1.0 Message-Id: <20220920-resend-powersave-v3-4-c47856d8757e@chromium.org> References: <20220920-resend-powersave-v3-0-c47856d8757e@chromium.org> In-Reply-To: <20220920-resend-powersave-v3-0-c47856d8757e@chromium.org> To: Mauro Carvalho Chehab Cc: Tomasz Figa , Ricardo Ribalda , Guenter Roeck , Max Staudt , linux-kernel@vger.kernel.org, Alan Stern , Hans Verkuil , Laurent Pinchart , linux-media@vger.kernel.org X-Mailer: b4 0.11.0-dev-d93f8 X-Developer-Signature: v=1; a=openpgp-sha256; l=3866; i=ribalda@chromium.org; h=from:subject:message-id; bh=0D1+Lk6BVHUTakJMT2e6YiV+9G/COKgarhcWvdj4pyo=; b=owEBbQKS/ZANAwAKAdE30T7POsSIAcsmYgBjWSLCY04skufuVZ8dA70NgBOex3XNb/EB82CUsCFi nvBzkMiJAjMEAAEKAB0WIQREDzjr+/4oCDLSsx7RN9E+zzrEiAUCY1kiwgAKCRDRN9E+zzrEiOmwEA CVSrcddwfF6QWTufc7Ys/ruPXJl5EmAjMv7h8sDxHvj9MegMHgfSZqgyWun/Pj6dLp3g3Lu+zi60re 3BvXaQmQgHK5SWKh4GXoEvkJH8DbIgLnFrrmm6GHCyXjkMyewtRIh2TN240Or6OR4Oxz98kio4RXmb NvvAl4fmmxh25Qlbjl9vK+aAQdUfS0EaXKavTzixC90e+OhW/cRxU9jktvDCxgHgzHIsynBJjTaMso +GfKwnGgZc4OVrg9FqrEebuxWADjJ1jz2iwSunKet3J/vhbu58Qkq5b4KI/5l4VEybIfs4TapiwPef BBRq+a2f+DeHf3iM3UhNgGgMIZwauMV4ajRruokJTcEvfutqQMN26oqoH+GvuduZGdoyI+yGKSTNz9 694Xl6SfVTtiJjdHBdM9DlfXcg8Hr2UInKsQNJFHfCoQ7mRsHZNSqesyJymUgdrVdBraBLsHoZiSGP kw0uua07zdGDb/IenWWXIZCqg/LM7sLBIp80gLdxGF9hh+IvGwQodXiVojSOy7lTwSsk3ALgYC3lUf QNE/eyVU6259QNKStKDplBSI1ZZzizlcg1Wsq3NqjXgHL50QTpaDCEyCmjLdSPUVSS3JjV3bqs9/zY ZJ0ZZLIg6JJacaYsDiaz+UcCin2d5gUG4a0na0fOo/BETa5nm//aRRRu9TxQ== X-Developer-Key: i=ribalda@chromium.org; a=openpgp; fpr=9EC3BB66E2FC129A6F90B39556A0D81F9F782DA9 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org From: Guenter Roeck So far the asynchronous control worker was canceled only in uvc_ctrl_cleanup_device. This is much later than the call to uvc_disconnect. However, after the call to uvc_disconnect returns, there must be no more USB activity. This can result in all kinds of problems in the USB code. One observed example: URB ffff993e83d0bc00 submitted while active WARNING: CPU: 0 PID: 4046 at drivers/usb/core/urb.c:364 usb_submit_urb+0x4ba/0x55e Modules linked in: <...> CPU: 0 PID: 4046 Comm: kworker/0:35 Not tainted 4.19.139 #18 Hardware name: Google Phaser/Phaser, BIOS Google_Phaser.10952.0.0 08/09/2018 Workqueue: events uvc_ctrl_status_event_work [uvcvideo] RIP: 0010:usb_submit_urb+0x4ba/0x55e Code: <...> RSP: 0018:ffffb08d471ebde8 EFLAGS: 00010246 RAX: a6da85d923ea5d00 RBX: ffff993e71985928 RCX: 0000000000000000 RDX: ffff993f37a1de90 RSI: ffff993f37a153d0 RDI: ffff993f37a153d0 RBP: ffffb08d471ebe28 R08: 000000000000003b R09: 001424bf85822e96 R10: 0000001000000000 R11: ffffffff975a4398 R12: ffff993e83d0b000 R13: ffff993e83d0bc00 R14: 0000000000000000 R15: 00000000fffffff0 FS: 0000000000000000(0000) GS:ffff993f37a00000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00000000ec9c0000 CR3: 000000025b160000 CR4: 0000000000340ef0 Call Trace: uvc_ctrl_status_event_work+0xd6/0x107 [uvcvideo] process_one_work+0x19b/0x4c5 worker_thread+0x10d/0x286 kthread+0x138/0x140 ? process_one_work+0x4c5/0x4c5 ? kthread_associate_blkcg+0xc1/0xc1 ret_from_fork+0x1f/0x40 Introduce new function uvc_ctrl_stop_device() to cancel the worker and call it from uvc_unregister_video() to solve the problem. Cc: Laurent Pinchart Cc: Alan Stern Cc: Hans Verkuil Signed-off-by: Guenter Roeck diff --git a/drivers/media/usb/uvc/uvc_ctrl.c b/drivers/media/usb/uvc/uvc_ctrl.c index c95a2229f4fa..c7af3e08b2c6 100644 --- a/drivers/media/usb/uvc/uvc_ctrl.c +++ b/drivers/media/usb/uvc/uvc_ctrl.c @@ -2597,14 +2597,17 @@ static void uvc_ctrl_cleanup_mappings(struct uvc_device *dev, } } -void uvc_ctrl_cleanup_device(struct uvc_device *dev) +void uvc_ctrl_stop_device(struct uvc_device *dev) { - struct uvc_entity *entity; - unsigned int i; - /* Can be uninitialized if we are aborting on probe error. */ if (dev->async_ctrl.work.func) cancel_work_sync(&dev->async_ctrl.work); +} + +void uvc_ctrl_cleanup_device(struct uvc_device *dev) +{ + struct uvc_entity *entity; + unsigned int i; /* Free controls and control mappings for all entities. */ list_for_each_entry(entity, &dev->entities, list) { diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c index ac87dee77f44..70d081c9a9fe 100644 --- a/drivers/media/usb/uvc/uvc_driver.c +++ b/drivers/media/usb/uvc/uvc_driver.c @@ -1901,6 +1901,7 @@ static void uvc_unregister_video(struct uvc_device *dev) if (dev->int_ep) uvc_status_unregister(dev); + uvc_ctrl_stop_device(dev); if (dev->vdev.dev) v4l2_device_unregister(&dev->vdev); diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h index 45310f55475f..6b07abac7034 100644 --- a/drivers/media/usb/uvc/uvcvideo.h +++ b/drivers/media/usb/uvc/uvcvideo.h @@ -739,6 +739,7 @@ int uvc_query_v4l2_menu(struct uvc_video_chain *chain, int uvc_ctrl_add_mapping(struct uvc_video_chain *chain, const struct uvc_control_mapping *mapping); int uvc_ctrl_init_device(struct uvc_device *dev); +void uvc_ctrl_stop_device(struct uvc_device *dev); void uvc_ctrl_cleanup_device(struct uvc_device *dev); int uvc_ctrl_restore_values(struct uvc_device *dev); bool uvc_ctrl_status_event_async(struct urb *urb, struct uvc_video_chain *chain, From patchwork Wed Oct 26 12:06:10 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ricardo Ribalda X-Patchwork-Id: 619109 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id B2791C433FE for ; Wed, 26 Oct 2022 12:06:56 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233704AbiJZMGz (ORCPT ); Wed, 26 Oct 2022 08:06:55 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:47736 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233695AbiJZMGl (ORCPT ); Wed, 26 Oct 2022 08:06:41 -0400 Received: from mail-ed1-x52c.google.com (mail-ed1-x52c.google.com [IPv6:2a00:1450:4864:20::52c]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id CA8B687685 for ; Wed, 26 Oct 2022 05:06:39 -0700 (PDT) Received: by mail-ed1-x52c.google.com with SMTP id 21so7093061edv.3 for ; Wed, 26 Oct 2022 05:06:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=OMOY9ddHOZwXHSgzFPquU4QOb1r0DNXtzkX5neLlEsI=; b=kUE7bsYQMQMslr9SolofhiwNBs8TPpXFluH96mlsBzX3wHR4CWHUl6rEU2XdqyI8JF 3GaE2bSFn9OtEcQjSct2AMtav+MXAZG5np1jC4bd0cBK4goPZRdJart7aq1xf7itlHkQ 3kdkEH+L3zHF7voS8BYCVAfCL2nc1bNTUEvsQ= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=OMOY9ddHOZwXHSgzFPquU4QOb1r0DNXtzkX5neLlEsI=; b=JTdue1DIjJnDAah1G2MVPMmtGAQLX0pBP4nCc5j235CpGTRnPiDnAZP4HTJq4tpp6r Fqvaic/EWVuFMumBnlAr+qL+NwaRNXeFivAPI1FD+rbFmWIEr7CNsqF5Lj0mWHwuwEBS KBu7Wt5Ocm/8BMw/Hd9yJyVlTkQa3Wc9HT3e0GtfpmosY6WZf4KjtQLZ1NwZEc5k4w/1 is/fMdOS1fpwhbIp3VjrJMvIayWKtHTrH/vxlpyzV7sSm/MRawHPpEPJxy66/VhXUJIu +JJsmprimpYRvw+eiX/IqBD5+maUmw1RhFmi09tEIyBCe0PW+XHvx7RxwD4lWNlFm4PJ 9FPQ== X-Gm-Message-State: ACrzQf1sPLLY8BHZy/nDMN2bfNcL3jHqyQrmy0HTSRDXdyFfQYZVjvrw NS73yr1rALedZiZq0cUtxmC1XA== X-Google-Smtp-Source: AMsMyM7VeS0kh9P1BpLFqqBPHDufZkoF0HozDYYJ2VuVzsoclMrg0RLsSjnK+gyV/hkARxka3ghbvQ== X-Received: by 2002:a05:6402:1cc1:b0:45c:3a90:9499 with SMTP id ds1-20020a0564021cc100b0045c3a909499mr41281169edb.61.1666785998227; Wed, 26 Oct 2022 05:06:38 -0700 (PDT) Received: from alco.roam.corp.google.com ([2620:0:1059:10:b47a:bedd:2941:1e3f]) by smtp.gmail.com with ESMTPSA id y18-20020a17090668d200b0079e11b8e891sm2892546ejr.125.2022.10.26.05.06.37 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 26 Oct 2022 05:06:37 -0700 (PDT) From: Ricardo Ribalda Date: Wed, 26 Oct 2022 14:06:10 +0200 Subject: [PATCH v3 5/7] media: uvcvideo: Release stream queue when unregistering video device MIME-Version: 1.0 Message-Id: <20220920-resend-powersave-v3-5-c47856d8757e@chromium.org> References: <20220920-resend-powersave-v3-0-c47856d8757e@chromium.org> In-Reply-To: <20220920-resend-powersave-v3-0-c47856d8757e@chromium.org> To: Mauro Carvalho Chehab Cc: Tomasz Figa , Ricardo Ribalda , Guenter Roeck , Max Staudt , linux-kernel@vger.kernel.org, Alan Stern , Hans Verkuil , Laurent Pinchart , linux-media@vger.kernel.org X-Mailer: b4 0.11.0-dev-d93f8 X-Developer-Signature: v=1; a=openpgp-sha256; l=3480; i=ribalda@chromium.org; h=from:subject:message-id; bh=APLvTWouHG6W7Hdh3pI6r+3IhJhwMwT1aCPAKGfmTl4=; b=owEBbQKS/ZANAwAKAdE30T7POsSIAcsmYgBjWSLDhfVyWypDVPC0JJxEfV0bmc/qRHVqOY3owrR7 RZYSEmeJAjMEAAEKAB0WIQREDzjr+/4oCDLSsx7RN9E+zzrEiAUCY1kiwwAKCRDRN9E+zzrEiINUD/ 9Tq8I83z6Lg6tNvcsuCkWyM5/KaT/QDyXaNaM/rrVS8WeXY8HFa798+mQi9RaZ7fgEBZXOt6VLiM9g DTmY3weROqImFZ3xkflgoJNpufYIDbdhtEYuhajS6ME/n3M1K3+DN6+Ij4Mf5XyAGa7dhT0SZiZGji OPNSrwRSuPn7Sn5aNs3l6i4NTrHJ2a7CNBXrXXNFfRsrBrUykckaiCDdru0wzSWSQHSgBNbcKFXu93 EzhOYnqUcR+AYKn66FiMf3oIcyJvVgQuN8hWosQNaH9oXmwi87XJzEP899lLnyXaw7D00qnYfbIKrt qbxtxNu2NXpzVFMNZwNADeafFOdmwAQsucdcUDdtZGqf0qxFYqEAqRIx7BXrEIt6z7pfBJMjR5lq9h Lc5oechRzpecNIvq56tMKMAWNNa+dwb8r7BLReXhD+0itNp/Ya2ucpRpnd5lTCEQna9EbrbR5VCmHB iDjfncy5wAKf5VzHIwJRU7z0dYy2K03etVb7gs9BKCNQ1ICQ/+A81KwECyHhlvpsnSNVkDjothNkBo E9HuAIQjml1+iWhPoQcmeXAey2NGqW4x+oe9LuTvHby1YJd2Kt7wQrjezb2cwC/OltXzNhp2F7FCa9 u2xgAXXeXbhooW8l6NbYztriySHHRAZksfEM/iLDhz1VFLNpKvnVfuYoTZmA== X-Developer-Key: i=ribalda@chromium.org; a=openpgp; fpr=9EC3BB66E2FC129A6F90B39556A0D81F9F782DA9 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org From: Guenter Roeck The following traceback was observed when stress testing the uvcvideo driver. config->interface[0] is NULL WARNING: CPU: 0 PID: 2757 at drivers/usb/core/usb.c:285 usb_ifnum_to_if+0x81/0x85 ^^^ added log message and WARN() to prevent crash Modules linked in: <...> CPU: 0 PID: 2757 Comm: inotify_reader Not tainted 4.19.139 #20 Hardware name: Google Phaser/Phaser, BIOS Google_Phaser.10952.0.0 08/09/2018 RIP: 0010:usb_ifnum_to_if+0x81/0x85 Code: <...> RSP: 0018:ffff9ee20141fa58 EFLAGS: 00010246 RAX: 438a0e5a525f1800 RBX: 0000000000000000 RCX: 0000000000000000 RDX: ffff975477a1de90 RSI: ffff975477a153d0 RDI: ffff975477a153d0 RBP: ffff9ee20141fa70 R08: 000000000000002c R09: 002daec189138d78 R10: 0000001000000000 R11: ffffffffa7da42e6 R12: ffff975459594800 R13: 0000000000000001 R14: 0000000000000001 R15: ffff975465376400 FS: 00007ddebffd6700(0000) GS:ffff975477a00000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 0000000012c83000 CR3: 00000001bbaf8000 CR4: 0000000000340ef0 Call Trace: usb_set_interface+0x3b/0x2f3 uvc_video_stop_streaming+0x38/0x81 [uvcvideo] uvc_stop_streaming+0x21/0x49 [uvcvideo] __vb2_queue_cancel+0x33/0x249 [videobuf2_common] vb2_core_queue_release+0x1c/0x45 [videobuf2_common] uvc_queue_release+0x26/0x32 [uvcvideo] uvc_v4l2_release+0x41/0xdd [uvcvideo] v4l2_release+0x99/0xed __fput+0xf0/0x1ea task_work_run+0x7f/0xa7 do_exit+0x1d1/0x6eb do_group_exit+0x9d/0xac get_signal+0x135/0x482 do_signal+0x4a/0x63c exit_to_usermode_loop+0x86/0xa5 do_syscall_64+0x171/0x269 ? __do_page_fault+0x272/0x474 entry_SYSCALL_64_after_hwframe+0x44/0xa9 RIP: 0033:0x7ddec156dc26 Code: Bad RIP value. RSP: 002b:00007ddebffd5c10 EFLAGS: 00000293 ORIG_RAX: 0000000000000017 RAX: fffffffffffffdfe RBX: 000000000000000a RCX: 00007ddec156dc26 RDX: 0000000000000000 RSI: 00007ddebffd5d28 RDI: 000000000000000a RBP: 00007ddebffd5c50 R08: 0000000000000000 R09: 0000000000000000 R10: 0000000000000000 R11: 0000000000000293 R12: 00007ddebffd5d28 R13: 0000000000000000 R14: 0000000000000000 R15: 0000000000000000 When this was observed, a USB disconnect was in progress, uvc_disconnect() had returned, but usb_disable_device() was still running. Drivers are not supposed to call any USB functions after the driver disconnect function has been called. The uvcvideo driver does not follow that convention and tries to write to the disconnected USB interface anyway. This results in a variety of race conditions. To solve this specific problem, release the uvc queue from uvc_unregister_video() after the associated video devices have been unregistered. Since the function already holds the uvc queue mutex, bypass uvc_queue_release() and call vb2_queue_release() directly. Cc: Laurent Pinchart Cc: Alan Stern Cc: Hans Verkuil Signed-off-by: Guenter Roeck diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c index 70d081c9a9fe..dc43100d0f95 100644 --- a/drivers/media/usb/uvc/uvc_driver.c +++ b/drivers/media/usb/uvc/uvc_driver.c @@ -1897,6 +1897,8 @@ static void uvc_unregister_video(struct uvc_device *dev) video_unregister_device(&stream->meta.vdev); uvc_debugfs_cleanup_stream(stream); + + vb2_queue_release(&stream->queue.queue); } if (dev->int_ep) From patchwork Wed Oct 26 12:06:11 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ricardo Ribalda X-Patchwork-Id: 619373 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 4EB6AC38A2D for ; Wed, 26 Oct 2022 12:06:59 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233696AbiJZMG5 (ORCPT ); Wed, 26 Oct 2022 08:06:57 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:48112 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233706AbiJZMGx (ORCPT ); Wed, 26 Oct 2022 08:06:53 -0400 Received: from mail-ed1-x532.google.com (mail-ed1-x532.google.com [IPv6:2a00:1450:4864:20::532]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 964C3900FE for ; Wed, 26 Oct 2022 05:06:40 -0700 (PDT) Received: by mail-ed1-x532.google.com with SMTP id z97so41030783ede.8 for ; Wed, 26 Oct 2022 05:06:40 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=DDPnZhTHnC4+BSDfJv5rTOVlgproVfPQyGRqh6zlgLY=; b=L+9Uc0J/EhrK8OXL1VuwO8chMxPeDc5rrdSRU7bLVh7gXOg+j31XSSr5DiIl/lMmAN Leo7OSLPnGCs6uKE3GSCPDhKgl4mvmbivEHVqaw/lYPmum8BN1+MTRaAOPzs3Zpb1Mws wNqqTVd2x7TgFdQTeLRu+rE8Vl421jPR+4BhU= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=DDPnZhTHnC4+BSDfJv5rTOVlgproVfPQyGRqh6zlgLY=; b=68FKgjJ3nXLqYUmS/CeGvudcFzkDz4i4UtEhUlnWskd6Cboz0UwUzsGmoW+3skYdzS swTakoR6mjVI3UzZ+9gAEi+4EPvYOvLrzsoEkSsvkMEAJim+/7z4exVtiHUjT4Enbc2F FBljCGboYeZVAhk9J5nvdebUwrBqpY93SYgbDA9lvt1r5N9JJfhS+zok0E04X0YrlCsM BKIKgOTUe8lvAsFrxTTV26lFfKikwRTqjK3kCvlSQVNCIWXVYLb6JNC6d5VcnIbbvZzE WqGPqvk42Aj6KhI/eVM+LUrlwDRtKvGKIMEqtIjzPdnxtoE6ZTWaSu5Q+fYfL61vovv5 viAA== X-Gm-Message-State: ACrzQf0V49aMWHEiVBcCtYEG3B1ruFVLLtJslAdEUWaVeU36XOLTVN/t A20napOSDk0sa4S7uYR0w5wuLQ== X-Google-Smtp-Source: AMsMyM6c0SM5TK9QH+63RO8Y8mYjtDa6DQmBHzN1JEXSorzEAwijzhy0A7secNMk0whm7axkCOCxGQ== X-Received: by 2002:a05:6402:4445:b0:461:b506:de51 with SMTP id o5-20020a056402444500b00461b506de51mr16295359edb.388.1666785999168; Wed, 26 Oct 2022 05:06:39 -0700 (PDT) Received: from alco.roam.corp.google.com ([2620:0:1059:10:b47a:bedd:2941:1e3f]) by smtp.gmail.com with ESMTPSA id y18-20020a17090668d200b0079e11b8e891sm2892546ejr.125.2022.10.26.05.06.38 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 26 Oct 2022 05:06:38 -0700 (PDT) From: Ricardo Ribalda Date: Wed, 26 Oct 2022 14:06:11 +0200 Subject: [PATCH v3 6/7] media: uvcvideo: Lock video streams and queues while unregistering MIME-Version: 1.0 Message-Id: <20220920-resend-powersave-v3-6-c47856d8757e@chromium.org> References: <20220920-resend-powersave-v3-0-c47856d8757e@chromium.org> In-Reply-To: <20220920-resend-powersave-v3-0-c47856d8757e@chromium.org> To: Mauro Carvalho Chehab Cc: Tomasz Figa , Ricardo Ribalda , Guenter Roeck , Max Staudt , linux-kernel@vger.kernel.org, Alan Stern , Hans Verkuil , Laurent Pinchart , linux-media@vger.kernel.org X-Mailer: b4 0.11.0-dev-d93f8 X-Developer-Signature: v=1; a=openpgp-sha256; l=4894; i=ribalda@chromium.org; h=from:subject:message-id; bh=HlIWUJ62M0kPqi0HzBoxVqaSaBvxV//ACPhATfL1bx8=; b=owEBbQKS/ZANAwAKAdE30T7POsSIAcsmYgBjWSLE8h3ON1ke3QBn4Z1ZWRgSwdPMJouexkwLx94p AANcweeJAjMEAAEKAB0WIQREDzjr+/4oCDLSsx7RN9E+zzrEiAUCY1kixAAKCRDRN9E+zzrEiAAjD/ wJh1z+QuEXCHql4pl30VsduTLXic9hcSwbyq7NHRhZEGbSy8u4m1BEQnpEfz1b3lxUcVLTAGfKVuQ6 M1Qcy3mOFJI6J42Rm2Ojs7lbEMT9ozmmNqD+5WR9jU7fki5zeY+QvKRNqIituokFvNe+vRIjut7oxB LO9Rm0T1ssFHXxNoKbt1F0/vsZ4J2WjKoNKf80+5P1O6s7aE4DTZDCFWpZMr1aPcp3RqsZI4Wb3l7A /Vo04sTVpaenIzPXHtiWWwI+Q/IepizKN8Cctp4wth1kbqY4z9wAYMqjbNdYssg5ei+hzrnED19rvG aARy73GY6tu+pU6+maVC+KyEezqIAayzTGAANAsYk1Liub0DSnRHi65F0rMUlmvTr7MLYPTqXeUWeO jzHhqB0X8fkzUsvHKjEzj1U8ACtjYRWbG3PRxQ8q7dyMnpsdhbSpsyqKL7Zp2vKeyNz0CRjttRDDch 7/g2hJxp36u4Ozn2ECTUfkODzsgQlO9DGQUxLUMQvu7vW/4wJ2WDm3sNM1QvqOgthyaxWvgZuQY816 9pMfXd8eGV1V4fQBEVneWcSMB0HZiv23pGg51Rgss3W9YGYG4hj8MasT/p3flG7P5ORaS/SFTS6G+G lDF7O+iCmcjZ6idEgKL3yVoLuP02GcfV5NGMabHflmus5jfnFTynjM9Ou28g== X-Developer-Key: i=ribalda@chromium.org; a=openpgp; fpr=9EC3BB66E2FC129A6F90B39556A0D81F9F782DA9 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org From: Guenter Roeck The call to uvc_disconnect() is not protected by any mutex. This means it can and will be called while other accesses to the video device are in progress. This can cause all kinds of race conditions, including crashes such as the following. usb 1-4: USB disconnect, device number 3 BUG: unable to handle kernel NULL pointer dereference at 0000000000000000 PGD 0 P4D 0 Oops: 0000 [#1] PREEMPT SMP PTI CPU: 0 PID: 5633 Comm: V4L2CaptureThre Not tainted 4.19.113-08536-g5d29ca36db06 #1 Hardware name: GOOGLE Edgar, BIOS Google_Edgar.7287.167.156 03/25/2019 RIP: 0010:usb_ifnum_to_if+0x29/0x40 Code: <...> RSP: 0018:ffffa46f42a47a80 EFLAGS: 00010246 RAX: 0000000000000000 RBX: 0000000000000000 RCX: ffff904a396c9000 RDX: ffff904a39641320 RSI: 0000000000000001 RDI: 0000000000000000 RBP: ffffa46f42a47a80 R08: 0000000000000002 R09: 0000000000000000 R10: 0000000000009975 R11: 0000000000000009 R12: 0000000000000000 R13: ffff904a396b3800 R14: ffff904a39e88000 R15: 0000000000000000 FS: 00007f396448e700(0000) GS:ffff904a3ba00000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 0000000000000000 CR3: 000000016cb46000 CR4: 00000000001006f0 Call Trace: usb_hcd_alloc_bandwidth+0x1ee/0x30f usb_set_interface+0x1a3/0x2b7 uvc_video_start_transfer+0x29b/0x4b8 [uvcvideo] uvc_video_start_streaming+0x91/0xdd [uvcvideo] uvc_start_streaming+0x28/0x5d [uvcvideo] vb2_start_streaming+0x61/0x143 [videobuf2_common] vb2_core_streamon+0xf7/0x10f [videobuf2_common] uvc_queue_streamon+0x2e/0x41 [uvcvideo] uvc_ioctl_streamon+0x42/0x5c [uvcvideo] __video_do_ioctl+0x33d/0x42a video_usercopy+0x34e/0x5ff ? video_ioctl2+0x16/0x16 v4l2_ioctl+0x46/0x53 do_vfs_ioctl+0x50a/0x76f ksys_ioctl+0x58/0x83 __x64_sys_ioctl+0x1a/0x1e do_syscall_64+0x54/0xde usb_set_interface() should not be called after the USB device has been unregistered. However, in the above case the disconnect happened after v4l2_ioctl() was called, but before the call to usb_ifnum_to_if(). Acquire various mutexes in uvc_unregister_video() to fix the majority (maybe all) of the observed race conditions. The uvc_device lock prevents races against suspend and resume calls and the poll function. The uvc_streaming lock prevents races against stream related functions; for the most part, those are ioctls. This lock also requires other functions using this lock to check if a video device is still registered after acquiring it. For example, it was observed that the video device was already unregistered by the time the stream lock was acquired in uvc_ioctl_streamon(). The uvc_queue lock prevents races against queue functions, Most of those are already protected by the uvc_streaming lock, but some are called directly. This is done as added protection; an actual race was not (yet) observed. Cc: Laurent Pinchart Cc: Alan Stern Cc: Hans Verkuil Signed-off-by: Guenter Roeck diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c index dc43100d0f95..b67d753d27ae 100644 --- a/drivers/media/usb/uvc/uvc_driver.c +++ b/drivers/media/usb/uvc/uvc_driver.c @@ -1889,16 +1889,24 @@ static void uvc_unregister_video(struct uvc_device *dev) { struct uvc_streaming *stream; + mutex_lock(&dev->lock); + list_for_each_entry(stream, &dev->streams, list) { if (!video_is_registered(&stream->vdev)) continue; + mutex_lock(&stream->mutex); + mutex_lock(&stream->queue.mutex); + video_unregister_device(&stream->vdev); video_unregister_device(&stream->meta.vdev); uvc_debugfs_cleanup_stream(stream); vb2_queue_release(&stream->queue.queue); + + mutex_unlock(&stream->queue.mutex); + mutex_unlock(&stream->mutex); } if (dev->int_ep) @@ -1911,6 +1919,8 @@ static void uvc_unregister_video(struct uvc_device *dev) if (media_devnode_is_registered(dev->mdev.devnode)) media_device_unregister(&dev->mdev); #endif + + mutex_unlock(&dev->lock); } int uvc_register_video_device(struct uvc_device *dev, diff --git a/drivers/media/usb/uvc/uvc_v4l2.c b/drivers/media/usb/uvc/uvc_v4l2.c index 77b687c46082..b4f2da336def 100644 --- a/drivers/media/usb/uvc/uvc_v4l2.c +++ b/drivers/media/usb/uvc/uvc_v4l2.c @@ -37,14 +37,20 @@ static int uvc_pm_get(struct uvc_streaming *stream) if (ret) return ret; + mutex_lock(&stream->dev->lock); + + if (!video_is_registered(&stream->vdev)) + goto done; + if (!stream->dev->int_ep) - return 0; + goto done; - mutex_lock(&stream->dev->lock); if (!stream->dev->users) ret = uvc_status_start(stream->dev, GFP_KERNEL); if (!ret) stream->dev->users++; + +done: mutex_unlock(&stream->dev->lock); if (ret) From patchwork Wed Oct 26 12:06:12 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ricardo Ribalda X-Patchwork-Id: 619108 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id EC6C4C38A2D for ; Wed, 26 Oct 2022 12:07:13 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233713AbiJZMHM (ORCPT ); Wed, 26 Oct 2022 08:07:12 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:48096 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233714AbiJZMGx (ORCPT ); Wed, 26 Oct 2022 08:06:53 -0400 Received: from mail-ed1-x52b.google.com (mail-ed1-x52b.google.com [IPv6:2a00:1450:4864:20::52b]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B3C298FD5C for ; Wed, 26 Oct 2022 05:06:41 -0700 (PDT) Received: by mail-ed1-x52b.google.com with SMTP id m15so41017921edb.13 for ; Wed, 26 Oct 2022 05:06:41 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=mMLlFka1I97WBpNYC6a4inYcni8WZqVzi63jLlkZWi4=; b=AH+RmoooS8UaFLHJXXnRxoJ2Jc5GkSas4KiebXOgW+50b9uocgReMAHmfeETP4vfif 6cWO0JIubDsaPFSSSR3FWtfmO8uWHTBSjdgOouYUwEz4MgKGonVtZiPXH50VnoRM1cjR Kv8MBusAP9Vj+S091rh8Fg0CUefagSrpnVQ18= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=mMLlFka1I97WBpNYC6a4inYcni8WZqVzi63jLlkZWi4=; b=fMX081PeZUHYTHBWbXYNb/ale6l8OyjB7LXzCxnZHKHLTonBztos3uBGoJzu1Rq4X3 y7mYOOGkZZekHEf6pzYe6RjMWgd4BeK8l/95kbZyy+I+RWnYmEIyr6LnAXxBKeOX0yx6 8mxvu2UGBnXzTKquJvq5+Ka8LATWeoKIxeefGzUF8EVdSJDhUEjvn2RAQ4SGg9lZrgGF JtVlg+V9/koBYBOKQZ2IgTaZEGEDnLaKCwKmnLocihwxFKIUEBdLDTvEx7zVGlqwdxG5 uYBrjVNwK5reKWKFuh7lhpfVM0WFIXS2bqZbi7aET22N8LgQO15o0yDJVq5K0oHOFB6M jCSw== X-Gm-Message-State: ACrzQf3rh4CsnQ2vLjPvKvkGOYIL48XQW7U11z+xR38W0/nK88uNz8yK B0cS/ebgvOK5XZiyHnO2cnzMsQ== X-Google-Smtp-Source: AMsMyM71cXxPxEDN4di7luqAVwmAUP4cd4/J6qh929jB55KOHr8jSvnqbgnRmH5SgiyYjmioTaS62Q== X-Received: by 2002:a05:6402:1a42:b0:458:b430:7e70 with SMTP id bf2-20020a0564021a4200b00458b4307e70mr40565070edb.293.1666786000295; Wed, 26 Oct 2022 05:06:40 -0700 (PDT) Received: from alco.roam.corp.google.com ([2620:0:1059:10:b47a:bedd:2941:1e3f]) by smtp.gmail.com with ESMTPSA id y18-20020a17090668d200b0079e11b8e891sm2892546ejr.125.2022.10.26.05.06.39 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 26 Oct 2022 05:06:39 -0700 (PDT) From: Ricardo Ribalda Date: Wed, 26 Oct 2022 14:06:12 +0200 Subject: [PATCH v3 7/7] media: uvcvideo: Protect uvc queue file operations against disconnect MIME-Version: 1.0 Message-Id: <20220920-resend-powersave-v3-7-c47856d8757e@chromium.org> References: <20220920-resend-powersave-v3-0-c47856d8757e@chromium.org> In-Reply-To: <20220920-resend-powersave-v3-0-c47856d8757e@chromium.org> To: Mauro Carvalho Chehab Cc: Tomasz Figa , Ricardo Ribalda , Guenter Roeck , Max Staudt , linux-kernel@vger.kernel.org, Alan Stern , Hans Verkuil , Laurent Pinchart , linux-media@vger.kernel.org X-Mailer: b4 0.11.0-dev-d93f8 X-Developer-Signature: v=1; a=openpgp-sha256; l=2373; i=ribalda@chromium.org; h=from:subject:message-id; bh=VNSZpEP9LE78JkEZDvuh4x3SXN68AOH2OfrHeEklewU=; b=owEBbQKS/ZANAwAKAdE30T7POsSIAcsmYgBjWSLFnSJAN39YLb7VMCp2rSXdTYaaZXR/J234HUWm EacyWCmJAjMEAAEKAB0WIQREDzjr+/4oCDLSsx7RN9E+zzrEiAUCY1kixQAKCRDRN9E+zzrEiCngD/ 9F98Rbghu+qvDGozMAenv8X0YPJt3WGjVSRv7vqfD+7VROtJ0PmclxYDizlw8tSkb8SiuPz7gTFdmE QXET5tNtKjC2A0qaUcyUkzmazEFQwFH6+rJHM1Ays6mCMVOIK3u0sGcaqyxhdynjybu0JJvjDLUdGi bnIKhzNc6ggNQrqNj90kaX1W2oAhYnMDlIpEygimeopmgJfEhLZ8Tsu4f9mb0brrKv6ztPsj8oatZ4 O96cFr0yYZ1D6ET68CpiJwSYWl0/a8fPSwKxzedb2SN1LUC70RMcb1cJWeJ+0n3iSRPTJXYBclQMf5 YmW0ns5APcng52VNrX6fSOpXHgmxhjTv/d95yw/n7vsMm6ASJ46itjKOBeZuhCB/Sy1Mc4j4g/d7XX YM9mWiXgN9WaXciV2/3h60xPsmpVvDAnWdVIf+aGkJZwJXuo+vvtp7tcYJyo6VsK8j9QTF61hV2HzS DX25L3L14xQ+5K9IUmBVgI3zBL/ovTPo/b0CMr2vgBbTB3/inFi6BfuUH161eBHd4W3Fw4DqmThiXr eMLhMhv9zCMlw17sJD1s2nBDtMsGszIc0nPuwXkgoVbH2IJPqLPaWcKSJvi8nFNLVSECU4MVaRhtsD H+LABx9UrTM9FrrjM+3f7QuLVw6G9/PuCGPBE6qT/AutyhY2z4b9i7DdlFVQ== X-Developer-Key: i=ribalda@chromium.org; a=openpgp; fpr=9EC3BB66E2FC129A6F90B39556A0D81F9F782DA9 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org From: Guenter Roeck uvc queue file operations have no mutex protection against USB disconnect. This is questionable at least for the poll operation, which has to wait for the uvc queue mutex. By the time that mutex has been acquired, is it possible that the video device has been unregistered. Protect all file operations by using the queue mutex to avoid possible race conditions. After acquiring the mutex, check if the video device is still registered, and bail out if not. Cc: Laurent Pinchart Cc: Alan Stern Cc: Hans Verkuil Signed-off-by: Guenter Roeck diff --git a/drivers/media/usb/uvc/uvc_queue.c b/drivers/media/usb/uvc/uvc_queue.c index 16fa17bbd15e..aed45cbc814e 100644 --- a/drivers/media/usb/uvc/uvc_queue.c +++ b/drivers/media/usb/uvc/uvc_queue.c @@ -354,24 +354,52 @@ int uvc_queue_streamoff(struct uvc_video_queue *queue, enum v4l2_buf_type type) int uvc_queue_mmap(struct uvc_video_queue *queue, struct vm_area_struct *vma) { - return vb2_mmap(&queue->queue, vma); + struct uvc_streaming *stream = uvc_queue_to_stream(queue); + int ret; + + mutex_lock(&queue->mutex); + if (!video_is_registered(&stream->vdev)) { + ret = -ENODEV; + goto unlock; + } + ret = vb2_mmap(&queue->queue, vma); +unlock: + mutex_unlock(&queue->mutex); + return ret; } #ifndef CONFIG_MMU unsigned long uvc_queue_get_unmapped_area(struct uvc_video_queue *queue, unsigned long pgoff) { - return vb2_get_unmapped_area(&queue->queue, 0, 0, pgoff, 0); + struct uvc_streaming *stream = uvc_queue_to_stream(queue); + unsigned long ret; + + mutex_lock(&queue->mutex); + if (!video_is_registered(&stream->vdev)) { + ret = -ENODEV; + goto unlock; + } + ret = vb2_get_unmapped_area(&queue->queue, 0, 0, pgoff, 0); +unlock: + mutex_unlock(&queue->mutex); + return ret; } #endif __poll_t uvc_queue_poll(struct uvc_video_queue *queue, struct file *file, poll_table *wait) { + struct uvc_streaming *stream = uvc_queue_to_stream(queue); __poll_t ret; mutex_lock(&queue->mutex); + if (!video_is_registered(&stream->vdev)) { + ret = EPOLLERR; + goto unlock; + } ret = vb2_poll(&queue->queue, file, wait); +unlock: mutex_unlock(&queue->mutex); return ret;