Received: by 2002:ad5:474a:0:0:0:0:0 with SMTP id i10csp5136535imu; Tue, 8 Jan 2019 12:10:11 -0800 (PST) X-Google-Smtp-Source: ALg8bN5IX0HHfnjJVhNheIlD/8n4IvFCghyt8WoE+nQU1/c0Ib9NUi2j13VVSXboseqOoHDtfixd X-Received: by 2002:a63:9843:: with SMTP id l3mr2728051pgo.413.1546978211517; Tue, 08 Jan 2019 12:10:11 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1546978211; cv=none; d=google.com; s=arc-20160816; b=F886S6El4HRpwpFhCTwoaHF29Hz4rWiREFbHc/CuIYH0T84dtZEM4um2HFMwY2RCD7 epUtv+GEAdcyydbBmJ+ujcCahP0HWK1qikJeYWYlB54vQKhchxmccxPrQpQHbA/MrWJr p6KSQEh+LSaoTbWj/n/T930ShO4316vCNwZtsFmVcasmXnHAk2IMVmwhnE9ggrJ/EBCi 3rsN/MS2YRKzbi9q4fwoBbpqWHSMshFI+Rmx/hdea7MCZK0+ghXPDWnkPD9DIO/cBx2v zxPwkXAIhoehPYiV5Q4W0qgESbXh1tKGgdZg5svgvEx2B9CPsBu6AjZug5NnRd2+oAPs +m/g== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=s+9ssqqHkbIWG1sfZlWIPL5iSjCpNpHE5R1GXKnDjbA=; b=yhI7YNFyWY9obHlKjQ/pn5mpRmOe0qrcrxwDtRaCqiRt5Sauitso5yr7YLSziAlEjf hVCXS5YIeDdhX7EOpYYOrhCccVIuutT4fRappkfji4xTKAyTifVZanm/oTceoHRZimCF fDuizMwxi6sKDJJKhHX4JWHiwfrnE4UlzCQ7A6XUjY+GlFE3kPL5Nvv3hDCdBPLiivP0 5nn+32BAnASuM80XLkSLk9LJ9az7CTIRUGhv4o+JyOwNDusWTIANRKBkVQ+h4I3cM1f0 hB5KT1/zZGw60SS+Dr6EB77VHtcwp4zJObamsbq+feX292e4ohaK+yWX/fB2N05WmJod l57A== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=BhtYJrZK; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id o21si62649322pgj.415.2019.01.08.12.09.56; Tue, 08 Jan 2019 12:10:11 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=BhtYJrZK; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1733068AbfAHUHL (ORCPT + 99 others); Tue, 8 Jan 2019 15:07:11 -0500 Received: from mail.kernel.org ([198.145.29.99]:34458 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729832AbfAHT1z (ORCPT ); Tue, 8 Jan 2019 14:27:55 -0500 Received: from sasha-vm.mshome.net (c-73-47-72-35.hsd1.nh.comcast.net [73.47.72.35]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 2FBDF2070B; Tue, 8 Jan 2019 19:27:54 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1546975674; bh=XUxiVeOZDM6uhBtX/vgb1svOnm7nDIu09V4UUXtei8E=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=BhtYJrZKA7Dy3aSv8RT9aSicdNlSIFS38nZMrNnlaxCM2quezi0NWGaeP4SjND8A4 Hem+Pv++SmlasrfjnRjJ84X3h+Jjms1lX/GWjHWXX8fHk+IaKkrM+/FDZqFKsQsqGk BU00OBT2mZbMKD4jO28A6FoeV3uM4C3z9423hLQ4= From: Sasha Levin To: linux-kernel@vger.kernel.org, stable@vger.kernel.org Cc: Daniel Axtens , Laurent Pinchart , Mauro Carvalho Chehab , Sasha Levin , linux-media@vger.kernel.org Subject: [PATCH AUTOSEL 4.20 046/117] media: uvcvideo: Refactor teardown of uvc on USB disconnect Date: Tue, 8 Jan 2019 14:25:14 -0500 Message-Id: <20190108192628.121270-46-sashal@kernel.org> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20190108192628.121270-1-sashal@kernel.org> References: <20190108192628.121270-1-sashal@kernel.org> MIME-Version: 1.0 X-Patchwork-Hint: Ignore Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Daniel Axtens [ Upstream commit 10e1fdb95809ed21406f53b5b4f064673a1b9ceb ] Currently, disconnecting a USB webcam while it is in use prints out a number of warnings, such as: WARNING: CPU: 2 PID: 3118 at /build/linux-ezBi1T/linux-4.8.0/fs/sysfs/group.c:237 sysfs_remove_group+0x8b/0x90 sysfs group ffffffffa7cd0780 not found for kobject 'event13' This has been noticed before. [0] This is because of the order in which things are torn down. If there are no streams active during a USB disconnect: - uvc_disconnect() is invoked via device_del() through the bus notifier mechanism. - this calls uvc_unregister_video(). - uvc_unregister_video() unregisters the video device for each stream, - because there are no streams open, it calls uvc_delete() - uvc_delete() calls uvc_status_cleanup(), which cleans up the status input device. - uvc_delete() calls media_device_unregister(), which cleans up the media device - uvc_delete(), uvc_unregister_video() and uvc_disconnect() all return, and we end up back in device_del(). - device_del() then cleans up the sysfs folder for the camera with dpm_sysfs_remove(). Because uvc_status_cleanup() and media_device_unregister() have already been called, this all works nicely. If, on the other hand, there *are* streams active during a USB disconnect: - uvc_disconnect() is invoked - this calls uvc_unregister_video() - uvc_unregister_video() unregisters the video device for each stream, - uvc_unregister_video() and uvc_disconnect() return, and we end up back in device_del(). - device_del() then cleans up the sysfs folder for the camera with dpm_sysfs_remove(). Because the status input device and the media device are children of the USB device, this also deletes their sysfs folders. - Sometime later, the final stream is closed, invoking uvc_release(). - uvc_release() calls uvc_delete() - uvc_delete() calls uvc_status_cleanup(), which cleans up the status input device. Because the sysfs directory has already been removed, this causes a WARNing. - uvc_delete() calls media_device_unregister(), which cleans up the media device. Because the sysfs directory has already been removed, this causes another WARNing. To fix this, we need to make sure the devices are always unregistered before the end of uvc_disconnect(). To this, move the unregistration into the disconnect path: - split uvc_status_cleanup() into two parts, one on disconnect that unregisters and one on delete that frees. - move v4l2_device_unregister() and media_device_unregister() into the disconnect path. [0]: https://lkml.org/lkml/2016/12/8/657 [Renamed uvc_input_cleanup() to uvc_input_unregister()] Signed-off-by: Daniel Axtens Acked-by: Greg Kroah-Hartman Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Sasha Levin --- drivers/media/usb/uvc/uvc_driver.c | 13 +++++++++---- drivers/media/usb/uvc/uvc_status.c | 12 ++++++++---- drivers/media/usb/uvc/uvcvideo.h | 1 + 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c index bc369a0934a3..76dc3ee8ca21 100644 --- a/drivers/media/usb/uvc/uvc_driver.c +++ b/drivers/media/usb/uvc/uvc_driver.c @@ -1824,11 +1824,7 @@ static void uvc_delete(struct kref *kref) usb_put_intf(dev->intf); usb_put_dev(dev->udev); - if (dev->vdev.dev) - v4l2_device_unregister(&dev->vdev); #ifdef CONFIG_MEDIA_CONTROLLER - if (media_devnode_is_registered(dev->mdev.devnode)) - media_device_unregister(&dev->mdev); media_device_cleanup(&dev->mdev); #endif @@ -1885,6 +1881,15 @@ static void uvc_unregister_video(struct uvc_device *dev) uvc_debugfs_cleanup_stream(stream); } + + uvc_status_unregister(dev); + + if (dev->vdev.dev) + v4l2_device_unregister(&dev->vdev); +#ifdef CONFIG_MEDIA_CONTROLLER + if (media_devnode_is_registered(dev->mdev.devnode)) + media_device_unregister(&dev->mdev); +#endif } int uvc_register_video_device(struct uvc_device *dev, diff --git a/drivers/media/usb/uvc/uvc_status.c b/drivers/media/usb/uvc/uvc_status.c index 0722dc684378..883e4cab45e7 100644 --- a/drivers/media/usb/uvc/uvc_status.c +++ b/drivers/media/usb/uvc/uvc_status.c @@ -54,7 +54,7 @@ static int uvc_input_init(struct uvc_device *dev) return ret; } -static void uvc_input_cleanup(struct uvc_device *dev) +static void uvc_input_unregister(struct uvc_device *dev) { if (dev->input) input_unregister_device(dev->input); @@ -71,7 +71,7 @@ static void uvc_input_report_key(struct uvc_device *dev, unsigned int code, #else #define uvc_input_init(dev) -#define uvc_input_cleanup(dev) +#define uvc_input_unregister(dev) #define uvc_input_report_key(dev, code, value) #endif /* CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV */ @@ -292,12 +292,16 @@ int uvc_status_init(struct uvc_device *dev) return 0; } -void uvc_status_cleanup(struct uvc_device *dev) +void uvc_status_unregister(struct uvc_device *dev) { usb_kill_urb(dev->int_urb); + uvc_input_unregister(dev); +} + +void uvc_status_cleanup(struct uvc_device *dev) +{ usb_free_urb(dev->int_urb); kfree(dev->status); - uvc_input_cleanup(dev); } int uvc_status_start(struct uvc_device *dev, gfp_t flags) diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h index c0cbd833d0a4..1db6634b2455 100644 --- a/drivers/media/usb/uvc/uvcvideo.h +++ b/drivers/media/usb/uvc/uvcvideo.h @@ -757,6 +757,7 @@ int uvc_register_video_device(struct uvc_device *dev, /* Status */ int uvc_status_init(struct uvc_device *dev); +void uvc_status_unregister(struct uvc_device *dev); void uvc_status_cleanup(struct uvc_device *dev); int uvc_status_start(struct uvc_device *dev, gfp_t flags); void uvc_status_stop(struct uvc_device *dev); -- 2.19.1