From nobody Sun Sep 27 00:40:21 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 225C61E2834; Thu, 27 Aug 2026 17:45:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787852716; cv=none; b=J+0zsbYaDiK+X0iffzajzClVcL+MCp2WNRscLSv4494HgtHFCj8mCE3hrxALbuBDlWszPf66v5BgMrrWvl5Vtm7JpQyM+3Zv8SsnxrtgES96eo4SGtFDReqCbNU9QO2xBDJDN992HzffbV9EIIUsqs7qDHSnX26AnCuimww5bEI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787852716; c=relaxed/simple; bh=+//yfgAdNhN2T/MjkotwYjveO3prh9dEHrgiHF1jt08=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=cnMRsPx99B4p/qS6C01DlJlgZa3Ags47QQWXDjecchtEhq05oHPgpiskbii1fH56zrliuqq+NQduEKt1GRLQORnFqt+Mdz3NEY2Az2attbz2s31pnTCeu9S8/4NiEG88Db80WdiYQlV0qYivrNIE5yq3HQ01gKQBC5K63aiI3z0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=nUqhFrBe; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="nUqhFrBe" Received: by smtp.kernel.org (Postfix) with ESMTPS id 32B4FC2BCF4; Thu, 27 Aug 2026 17:45:15 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1787852715; bh=+//yfgAdNhN2T/MjkotwYjveO3prh9dEHrgiHF1jt08=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=nUqhFrBeMJ6q2lAxmmZHkcHbEBnsmP/rnHDUulNxeexTMN47aRyxqj0TJoA74TgMB UlTGgnnp0+/7pKA98yh5dRMCmKaU8oGD9LdIWPwGwSzcFXO8anqrJ9SxRatoDHEKaq 7IsctM/nRtQBOtAdS6BT1WMJod/ZDkHrv3ssiOy7kpIYmILu5Nw0JTZhGU/LtdxEyL uVZQluj0JwekZjq3ymSrI3dY+nn5J7RA9U5EKdP3SmQWYTgvtzlf+aZ5PKS5nHKPxW 4N2n+INuaii3nqsnBd7LIvKq8A+tGaz0F9T0P1WYV8Fn6CzzGlmaq+yfB8Kwx12JQb 1BZPpgZeDH0VQ== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 13D08C61DB9; Thu, 27 Aug 2026 17:45:15 +0000 (UTC) From: Nick Faro via B4 Relay Date: Thu, 27 Aug 2026 19:44:11 +0200 Subject: [PATCH 1/6] media: cx231xx: keep device state alive until final release Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260827-cx231xx-disconnect-lifetime-v1-1-7bbf946bbd36@hotmail.com> References: <20260827-cx231xx-disconnect-lifetime-v1-0-7bbf946bbd36@hotmail.com> In-Reply-To: <20260827-cx231xx-disconnect-lifetime-v1-0-7bbf946bbd36@hotmail.com> To: Mauro Carvalho Chehab , Hans Verkuil Cc: linux-media@vger.kernel.org, linux-kernel@vger.kernel.org, Nick Faro X-Mailer: b4 0.13.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1787852712; l=11644; i=yux50000@hotmail.com; s=20260827; h=from:subject:message-id; bh=w/AU95ECXvWftgDX5vGZLoQEfG7TvUvxOkb4vN+mino=; b=LxP2ECMWcPxM9xHsb5HBa7xMvoBYffnmi5qI3ue14yE9sepN1BEGYfHzpeqe+2JqZmkxDubT1 MLmoO9O6vquAwrd0S8XslokX6rjRWWY9tYHJ7exGULAk6JzBJI4p0j6 X-Developer-Key: i=yux50000@hotmail.com; a=ed25519; pk=FMSCCFHmUW8ylFpPOeaegUBqrRhzdMS2snqX/kNbLtM= X-Endpoint-Received: by B4 Relay for yux50000@hotmail.com/20260827 with auth_id=979 X-Original-From: Nick Faro Reply-To: yux50000@hotmail.com From: Nick Faro The USB interface can be unbound while userspace still has a V4L2 or ALSA device node open. Since struct cx231xx embeds the video devices and is referenced by ALSA callbacks, interface-managed allocations have a shorter lifetime than their users. Allocate the shared device state and endpoint arrays explicitly. Use the v4l2_device release callback as the single point that unregisters the V4L2 device and frees its backing storage. Registered video nodes keep their normal V4L2 references, while the ALSA card takes an additional reference and is registered only after its endpoint data is ready. Disconnect public interfaces during teardown, but defer control-handler and media-device cleanup until the final reference is dropped. Update probe unwinding to free directly before V4L2 registration and otherwise drop the initial V4L2 reference. Fixes: 184a82784d50 ("[media] cx231xx: use devm_ functions to allocate memo= ry") Assisted-by: Codex:gpt-5.6-sol Signed-off-by: Nick Faro --- drivers/media/usb/cx231xx/cx231xx-417.c | 1 - drivers/media/usb/cx231xx/cx231xx-audio.c | 32 +++++++---- drivers/media/usb/cx231xx/cx231xx-cards.c | 88 +++++++++++++++++++++++----= ---- drivers/media/usb/cx231xx/cx231xx-video.c | 2 - 4 files changed, 88 insertions(+), 35 deletions(-) diff --git a/drivers/media/usb/cx231xx/cx231xx-417.c b/drivers/media/usb/cx= 231xx/cx231xx-417.c index c695a97e202b..2323584bf818 100644 --- a/drivers/media/usb/cx231xx/cx231xx-417.c +++ b/drivers/media/usb/cx231xx/cx231xx-417.c @@ -1650,7 +1650,6 @@ void cx231xx_417_unregister(struct cx231xx *dev) =20 if (video_is_registered(&dev->v4l_device)) { video_unregister_device(&dev->v4l_device); - v4l2_ctrl_handler_free(&dev->mpeg_ctrl_handler.hdl); } } =20 diff --git a/drivers/media/usb/cx231xx/cx231xx-audio.c b/drivers/media/usb/= cx231xx/cx231xx-audio.c index b24ceef497e4..dd819a546af9 100644 --- a/drivers/media/usb/cx231xx/cx231xx-audio.c +++ b/drivers/media/usb/cx231xx/cx231xx-audio.c @@ -561,6 +561,15 @@ static const struct snd_pcm_ops snd_cx231xx_pcm_captur= e =3D { .pointer =3D snd_cx231xx_capture_pointer, }; =20 +static void cx231xx_audio_card_free(struct snd_card *card) +{ + struct cx231xx *dev =3D card->private_data; + + kfree(dev->adev.alt_max_pkt_size); + dev->adev.alt_max_pkt_size =3D NULL; + v4l2_device_put(&dev->v4l2_dev); +} + static int cx231xx_audio_init(struct cx231xx *dev) { struct cx231xx_audio *adev =3D &dev->adev; @@ -585,6 +594,9 @@ static int cx231xx_audio_init(struct cx231xx *dev) THIS_MODULE, 0, &card); if (err < 0) return err; + v4l2_device_get(&dev->v4l2_dev); + card->private_data =3D dev; + card->private_free =3D cx231xx_audio_card_free; =20 spin_lock_init(&adev->slock); err =3D snd_pcm_new(card, "Cx231xx Audio", 0, 0, 1, &pcm); @@ -603,11 +615,6 @@ static int cx231xx_audio_init(struct cx231xx *dev) =20 INIT_WORK(&dev->wq_trigger, audio_trigger); =20 - err =3D snd_card_register(card); - if (err < 0) - goto err_free_card; - - adev->sndcard =3D card; adev->udev =3D dev->udev; =20 /* compute alternate max packet sizes for Audio */ @@ -640,7 +647,7 @@ static int cx231xx_audio_init(struct cx231xx *dev) =20 if (uif->altsetting[i].desc.bNumEndpoints < isoc_pipe + 1) { err =3D -ENODEV; - goto err_free_pkt_size; + goto err_free_card; } =20 tmp =3D le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe].desc. @@ -652,10 +659,13 @@ static int cx231xx_audio_init(struct cx231xx *dev) adev->alt_max_pkt_size[i]); } =20 + err =3D snd_card_register(card); + if (err < 0) + goto err_free_card; + + adev->sndcard =3D card; return 0; =20 -err_free_pkt_size: - kfree(adev->alt_max_pkt_size); err_free_card: snd_card_free(card); =20 @@ -664,6 +674,8 @@ static int cx231xx_audio_init(struct cx231xx *dev) =20 static int cx231xx_audio_fini(struct cx231xx *dev) { + struct snd_card *card; + if (dev =3D=3D NULL) return 0; =20 @@ -675,9 +687,9 @@ static int cx231xx_audio_fini(struct cx231xx *dev) } =20 if (dev->adev.sndcard) { - snd_card_free_when_closed(dev->adev.sndcard); - kfree(dev->adev.alt_max_pkt_size); + card =3D dev->adev.sndcard; dev->adev.sndcard =3D NULL; + snd_card_free_when_closed(card); } =20 return 0; diff --git a/drivers/media/usb/cx231xx/cx231xx-cards.c b/drivers/media/usb/= cx231xx/cx231xx-cards.c index 69b24205bc56..1b1e7bca4c6d 100644 --- a/drivers/media/usb/cx231xx/cx231xx-cards.c +++ b/drivers/media/usb/cx231xx/cx231xx-cards.c @@ -1339,8 +1339,15 @@ void cx231xx_config_i2c(struct cx231xx *dev) static void cx231xx_unregister_media_device(struct cx231xx *dev) { #ifdef CONFIG_MEDIA_CONTROLLER - if (dev->media_dev) { + if (dev->media_dev) media_device_unregister(dev->media_dev); +#endif +} + +static void cx231xx_cleanup_media_device(struct cx231xx *dev) +{ +#ifdef CONFIG_MEDIA_CONTROLLER + if (dev->media_dev) { media_device_cleanup(dev->media_dev); kfree(dev->media_dev); dev->media_dev =3D NULL; @@ -1348,6 +1355,27 @@ static void cx231xx_unregister_media_device(struct c= x231xx *dev) #endif } =20 +static void cx231xx_free_device(struct cx231xx *dev) +{ + kfree(dev->video_mode.alt_max_pkt_size); + kfree(dev->vbi_mode.alt_max_pkt_size); + kfree(dev->sliced_cc_mode.alt_max_pkt_size); + kfree(dev->ts1_mode.alt_max_pkt_size); + kfree(dev); +} + +static void cx231xx_v4l2_release(struct v4l2_device *v4l2_dev) +{ + struct cx231xx *dev =3D container_of(v4l2_dev, struct cx231xx, v4l2_dev); + + v4l2_ctrl_handler_free(&dev->mpeg_ctrl_handler.hdl); + v4l2_ctrl_handler_free(&dev->radio_ctrl_handler); + v4l2_ctrl_handler_free(&dev->ctrl_handler); + v4l2_device_unregister(v4l2_dev); + cx231xx_cleanup_media_device(dev); + cx231xx_free_device(dev); +} + /* * cx231xx_realease_resources() * unregisters the v4l2,i2c and usb devices @@ -1359,18 +1387,23 @@ void cx231xx_release_resources(struct cx231xx *dev) =20 cx231xx_release_analog_resources(dev); =20 + /* Wait for file operations that started before node removal. */ + mutex_lock(&dev->lock); + v4l2_device_disconnect(&dev->v4l2_dev); + mutex_unlock(&dev->lock); + cx231xx_remove_from_devlist(dev); =20 /* Release I2C buses */ cx231xx_dev_uninit(dev); =20 - /* delete v4l2 device */ - v4l2_device_unregister(&dev->v4l2_dev); - cx231xx_unregister_media_device(dev); =20 - /* Mark device as unused */ + /* Mark the board slot unused before the final put can free dev. */ clear_bit(dev->devno, &cx231xx_devused); + + /* Drop the initial reference after all nodes are unregistered. */ + v4l2_device_put(&dev->v4l2_dev); } =20 static int cx231xx_media_device_init(struct cx231xx *dev, @@ -1544,7 +1577,6 @@ static void flush_request_modules(struct cx231xx *dev) =20 static int cx231xx_init_v4l2(struct cx231xx *dev, struct usb_device *udev, - struct usb_interface *interface, int isoc_pipe) { struct usb_interface *uif; @@ -1573,8 +1605,8 @@ static int cx231xx_init_v4l2(struct cx231xx *dev, dev->video_mode.end_point_addr, dev->video_mode.num_alt); =20 - dev->video_mode.alt_max_pkt_size =3D devm_kmalloc_array(&interface->dev, = 32, - dev->video_mode.num_alt, GFP_KERNEL); + dev->video_mode.alt_max_pkt_size =3D + kmalloc_array(32, dev->video_mode.num_alt, GFP_KERNEL); if (dev->video_mode.alt_max_pkt_size =3D=3D NULL) return -ENOMEM; =20 @@ -1615,8 +1647,8 @@ static int cx231xx_init_v4l2(struct cx231xx *dev, dev->vbi_mode.num_alt); =20 /* compute alternate max packet sizes for vbi */ - dev->vbi_mode.alt_max_pkt_size =3D devm_kmalloc_array(&interface->dev, 32, - dev->vbi_mode.num_alt, GFP_KERNEL); + dev->vbi_mode.alt_max_pkt_size =3D + kmalloc_array(32, dev->vbi_mode.num_alt, GFP_KERNEL); if (dev->vbi_mode.alt_max_pkt_size =3D=3D NULL) return -ENOMEM; =20 @@ -1658,9 +1690,8 @@ static int cx231xx_init_v4l2(struct cx231xx *dev, "sliced CC EndPoint Addr 0x%x, Alternate settings: %i\n", dev->sliced_cc_mode.end_point_addr, dev->sliced_cc_mode.num_alt); - dev->sliced_cc_mode.alt_max_pkt_size =3D devm_kmalloc_array(&interface->d= ev, 32, - dev->sliced_cc_mode.num_alt, - GFP_KERNEL); + dev->sliced_cc_mode.alt_max_pkt_size =3D + kmalloc_array(32, dev->sliced_cc_mode.num_alt, GFP_KERNEL); if (dev->sliced_cc_mode.alt_max_pkt_size =3D=3D NULL) return -ENOMEM; =20 @@ -1724,7 +1755,7 @@ static int cx231xx_usb_probe(struct usb_interface *in= terface, udev =3D interface_to_usbdev(interface); =20 /* allocate memory for our device state and initialize it */ - dev =3D devm_kzalloc(&interface->dev, sizeof(*dev), GFP_KERNEL); + dev =3D kzalloc_obj(*dev); if (dev =3D=3D NULL) { retval =3D -ENOMEM; goto err_if; @@ -1818,15 +1849,16 @@ static int cx231xx_usb_probe(struct usb_interface *= interface, dev_err(d, "v4l2_device_register failed\n"); goto err_v4l2; } + dev->v4l2_dev.release =3D cx231xx_v4l2_release; =20 /* allocate device struct */ retval =3D cx231xx_init_dev(dev, udev, nr); if (retval) goto err_init; =20 - retval =3D cx231xx_init_v4l2(dev, udev, interface, isoc_pipe); + retval =3D cx231xx_init_v4l2(dev, udev, isoc_pipe); if (retval) - goto err_init; + goto err_video_alt; =20 if (dev->current_pcb_config.ts1_source !=3D 0xff) { /* compute alternate max packet sizes for TS1 */ @@ -1854,9 +1886,8 @@ static int cx231xx_usb_probe(struct usb_interface *in= terface, dev->ts1_mode.end_point_addr, dev->ts1_mode.num_alt); =20 - dev->ts1_mode.alt_max_pkt_size =3D devm_kmalloc_array(&interface->dev, 3= 2, - dev->ts1_mode.num_alt, - GFP_KERNEL); + dev->ts1_mode.alt_max_pkt_size =3D + kmalloc_array(32, dev->ts1_mode.num_alt, GFP_KERNEL); if (dev->ts1_mode.alt_max_pkt_size =3D=3D NULL) { retval =3D -ENOMEM; goto err_video_alt; @@ -1900,12 +1931,18 @@ static int cx231xx_usb_probe(struct usb_interface *= interface, if (!retval) retval =3D media_device_register(dev->media_dev); #endif - if (retval < 0) + if (retval < 0) { + dev->state |=3D DEV_DISCONNECTED; + flush_request_modules(dev); + cx231xx_close_extension(dev); + usb_set_intfdata(interface, NULL); cx231xx_release_resources(dev); + } return retval; =20 err_video_alt: /* cx231xx_uninit_dev: */ + dev->state |=3D DEV_DISCONNECTED; cx231xx_close_extension(dev); cx231xx_ir_exit(dev); cx231xx_release_analog_resources(dev); @@ -1913,13 +1950,20 @@ static int cx231xx_usb_probe(struct usb_interface *= interface, cx231xx_remove_from_devlist(dev); cx231xx_dev_uninit(dev); err_init: - v4l2_device_unregister(&dev->v4l2_dev); + dev->state |=3D DEV_DISCONNECTED; + usb_set_intfdata(interface, NULL); + clear_bit(nr, &cx231xx_devused); + v4l2_device_disconnect(&dev->v4l2_dev); + v4l2_device_put(&dev->v4l2_dev); + return retval; err_v4l2: - cx231xx_unregister_media_device(dev); + cx231xx_cleanup_media_device(dev); err_media_init: usb_set_intfdata(interface, NULL); err_if: clear_bit(nr, &cx231xx_devused); + if (dev) + cx231xx_free_device(dev); return retval; } =20 diff --git a/drivers/media/usb/cx231xx/cx231xx-video.c b/drivers/media/usb/= cx231xx/cx231xx-video.c index 70aa99fead27..058e8eed2847 100644 --- a/drivers/media/usb/cx231xx/cx231xx-video.c +++ b/drivers/media/usb/cx231xx/cx231xx-video.c @@ -1567,8 +1567,6 @@ void cx231xx_release_analog_resources(struct cx231xx = *dev) =20 video_unregister_device(&dev->vdev); } - v4l2_ctrl_handler_free(&dev->ctrl_handler); - v4l2_ctrl_handler_free(&dev->radio_ctrl_handler); } =20 /* --=20 2.43.0 From nobody Sun Sep 27 00:40:21 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 22EF7415F3A; Thu, 27 Aug 2026 17:45:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787852716; cv=none; b=nkqkkA8SIPNIx8irXABC3jYfsrDzealg3SsRua+o879KsvM5tRtNDTH9CnPgdSGshp3iXtALuTYf80I8X/nLfn8ykj9pBZq2L9/+qTrcLkDfeySYOsESZFC1UugoOp9m6BwfE+YKaiOq4wddwIb2ckMLlUU3w2CDI1aYb6kFJ+4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787852716; c=relaxed/simple; bh=0nLkNLQiZlNB6CfK+Dg2+ehqZKw66lrJWjoHTco88+4=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=LOgcPQaHY1DdBOC/SiGW/tXVZCtX39mi5+Nsd1rU4fHHnUJ2PGOjCPrNZISK7B9i/rOvCrrcVl/haJJo27nFF4EreztLzl+pqD+Bx1atoStQTbjvgnMpvKVySHmIX4+KZh9+574w0BMlfKmLT73TSJ36sdsRRqgXI9UNvsqCdLw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=g40V6t1C; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="g40V6t1C" Received: by smtp.kernel.org (Postfix) with ESMTPS id 41AA8C2BCF5; Thu, 27 Aug 2026 17:45:15 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1787852715; bh=0nLkNLQiZlNB6CfK+Dg2+ehqZKw66lrJWjoHTco88+4=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=g40V6t1CWPTz6v9mLyHkDn7VDdrFxh3+In3HJzZEqKDJ7OYL+o+KiEyxZFxb/LH4Y Zf+3NeG+D8osrIZDoRRBFeslJ6cPU5+2SC/K3Um1GEFHfjtl0o3xTXZR/Rilj3lo8j XjlN7MbMWMWjU2aYRJaAQv/9TTnSgravi2w3a4Nd3hRLqZFyTJKSWGAz4T3v9ghX9g 5cByUJich006UTwsk46z1r6CYTGtmjgOdaLvdoectPHmSGIUcLs+/g9fXS/cGnjp/4 QfR4DDXmsyNzpQ+EmsT6gsg5DoL2yXzHOheLx3kbnq0JQCrIVkstRTMlgaKc4rTa54 GSOXClZSnsCfQ== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 22C0FC61DCB; Thu, 27 Aug 2026 17:45:15 +0000 (UTC) From: Nick Faro via B4 Relay Date: Thu, 27 Aug 2026 19:44:12 +0200 Subject: [PATCH 2/6] media: cx231xx: stop resubmitting URBs after disconnect Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260827-cx231xx-disconnect-lifetime-v1-2-7bbf946bbd36@hotmail.com> References: <20260827-cx231xx-disconnect-lifetime-v1-0-7bbf946bbd36@hotmail.com> In-Reply-To: <20260827-cx231xx-disconnect-lifetime-v1-0-7bbf946bbd36@hotmail.com> To: Mauro Carvalho Chehab , Hans Verkuil Cc: linux-media@vger.kernel.org, linux-kernel@vger.kernel.org, Nick Faro X-Mailer: b4 0.13.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1787852712; l=3674; i=yux50000@hotmail.com; s=20260827; h=from:subject:message-id; bh=2Ru5eg+WVX8Q1bap6mSISOc5AFov0+AcLBFgPkvKzfA=; b=uu6yy4V69LYNf4+ZbRl3wBC//XBslOO0v/du/JGOAy8HALqEsTJGO2Fg4QKF1ZVzO+aiqLNE+ oSPqDporgUAAWZnO3Z3HeLnwIPgeArPwbxZUSWxq227UO0nwfCA+UXc X-Developer-Key: i=yux50000@hotmail.com; a=ed25519; pk=FMSCCFHmUW8ylFpPOeaegUBqrRhzdMS2snqX/kNbLtM= X-Endpoint-Received: by B4 Relay for yux50000@hotmail.com/20260827 with auth_id=979 X-Original-From: Nick Faro Reply-To: yux50000@hotmail.com From: Nick Faro URB completion handlers normally resubmit transfers after processing. A completion can race with disconnect after the device has been marked gone, causing the transfer loop to continue while teardown kills and frees URBs. Return from the video and VBI completion handlers once the device is disconnected. Continue to kill and free existing transfers during teardown, but skip endpoint resets and capture commands that require live hardware. Fixes: e0d3bafd0258 ("V4L/DVB (10954): Add cx231xx USB driver") Assisted-by: Codex:gpt-5.6-sol Signed-off-by: Nick Faro --- drivers/media/usb/cx231xx/cx231xx-core.c | 16 ++++++++++++++-- drivers/media/usb/cx231xx/cx231xx-vbi.c | 6 ++++++ 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/drivers/media/usb/cx231xx/cx231xx-core.c b/drivers/media/usb/c= x231xx/cx231xx-core.c index d8312201694f..462eb4c7564e 100644 --- a/drivers/media/usb/cx231xx/cx231xx-core.c +++ b/drivers/media/usb/cx231xx/cx231xx-core.c @@ -785,6 +785,9 @@ static void cx231xx_isoc_irq_callback(struct urb *urb) unsigned long flags; int i; =20 + if (dev->state & DEV_DISCONNECTED) + return; + switch (urb->status) { case 0: /* success */ case -ETIMEDOUT: /* NAK */ @@ -830,6 +833,9 @@ static void cx231xx_bulk_irq_callback(struct urb *urb) struct cx231xx *dev =3D container_of(vmode, struct cx231xx, video_mode); unsigned long flags; =20 + if (dev->state & DEV_DISCONNECTED) + return; + switch (urb->status) { case 0: /* success */ case -ETIMEDOUT: /* NAK */ @@ -895,7 +901,7 @@ void cx231xx_uninit_isoc(struct cx231xx *dev) dev->video_mode.isoc_ctl.transfer_buffer[i] =3D NULL; } =20 - if (broken_pipe) { + if (broken_pipe && !(dev->state & DEV_DISCONNECTED)) { cx231xx_isocdbg("Reset endpoint to recover broken pipe."); usb_reset_endpoint(dev->udev, dev->video_mode.end_point_addr); } @@ -908,6 +914,9 @@ void cx231xx_uninit_isoc(struct cx231xx *dev) dev->video_mode.isoc_ctl.num_bufs =3D 0; dma_q->p_left_data =3D NULL; =20 + if (dev->state & DEV_DISCONNECTED) + return; + if (dev->mode_tv =3D=3D 0) cx231xx_capture_start(dev, 0, Raw_Video); else @@ -954,7 +963,7 @@ void cx231xx_uninit_bulk(struct cx231xx *dev) dev->video_mode.bulk_ctl.transfer_buffer[i] =3D NULL; } =20 - if (broken_pipe) { + if (broken_pipe && !(dev->state & DEV_DISCONNECTED)) { cx231xx_isocdbg("Reset endpoint to recover broken pipe."); usb_reset_endpoint(dev->udev, dev->video_mode.end_point_addr); } @@ -967,6 +976,9 @@ void cx231xx_uninit_bulk(struct cx231xx *dev) dev->video_mode.bulk_ctl.num_bufs =3D 0; dma_q->p_left_data =3D NULL; =20 + if (dev->state & DEV_DISCONNECTED) + return; + if (dev->mode_tv =3D=3D 0) cx231xx_capture_start(dev, 0, Raw_Video); else diff --git a/drivers/media/usb/cx231xx/cx231xx-vbi.c b/drivers/media/usb/cx= 231xx/cx231xx-vbi.c index 338e10148465..b51955f1dd30 100644 --- a/drivers/media/usb/cx231xx/cx231xx-vbi.c +++ b/drivers/media/usb/cx231xx/cx231xx-vbi.c @@ -260,6 +260,9 @@ static void cx231xx_irq_vbi_callback(struct urb *urb) struct cx231xx *dev =3D container_of(vmode, struct cx231xx, vbi_mode); unsigned long flags; =20 + if (dev->state & DEV_DISCONNECTED) + return; + switch (urb->status) { case 0: /* success */ case -ETIMEDOUT: /* NAK */ @@ -328,6 +331,9 @@ void cx231xx_uninit_vbi_isoc(struct cx231xx *dev) dev->vbi_mode.bulk_ctl.transfer_buffer =3D NULL; dev->vbi_mode.bulk_ctl.num_bufs =3D 0; =20 + if (dev->state & DEV_DISCONNECTED) + return; + cx231xx_capture_start(dev, 0, Vbi); } EXPORT_SYMBOL_GPL(cx231xx_uninit_vbi_isoc); --=20 2.43.0 From nobody Sun Sep 27 00:40:21 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 226CA285058; Thu, 27 Aug 2026 17:45:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787852716; cv=none; b=R0+1mqfXHufNsYOyyPnQLDTWCgc2HMmRS5buneomOjPWTGRCzTiRhnUWEIspRc4CL4rLcr/KHOYwJ+gLHsWW7bRdIyiRphaEL98A2sGnpMVvDolltSkeFibDxVrRm3Txp4bXTJC/HCFpEDaA9z2KJT2Kgt8A5vjCX24+SGl9wts= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787852716; c=relaxed/simple; bh=49hRGeJA5K9raDKlr6MHXea36nEmL7xchQhV5KXtNRU=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Gd+HRFpPjsJXnN/kE72Q8+jG1ihRTvpd6hvl/U9iQ+rlTkbyKIKwhhqywe8ABiJ+Dya8L8Gnum20Gwumoqdu9zVEO1/KwHusvKPFVQ3MwMl52msRTitcPuEZdXMA8saB1M/CuzPMx+rJvxjpGfLMSjEvMTqwGQwBhbBJ2L4+hpo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=TA3vJfvk; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="TA3vJfvk" Received: by smtp.kernel.org (Postfix) with ESMTPS id 4B2A3C2BCF7; Thu, 27 Aug 2026 17:45:15 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1787852715; bh=49hRGeJA5K9raDKlr6MHXea36nEmL7xchQhV5KXtNRU=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=TA3vJfvkLfiyfQKL0ph42KMiFmhgc/ARWEemG8Hasp5rRVERoc4nQ6v5aHa2fG0we 8sqVR+HgdKRIkHDKVATqNLn8PZt0rGGza9sz+9YCTrsKlIWtV0trH0jK24l1/I0ICy izl/asUy4xWIl3E13Tlxi0WUMSdpcaxZtURsQpNMAu3yqRSvZnq3RL2e2LfS8oWQpt TYBsAHgd1rsjfTzNxW2fzOwzs93Whv6wiP1nJra94d06GuYfM8ypcorOT8kHoSn3Co +tDm2Nde29aCIlxzR5r4VWLMsTYzBGeHxzLQTrV+V5ZDCbWiWPs/xUXS0bGfuzvILG XXDFgj1Qgk0rQ== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 31359C61DC4; Thu, 27 Aug 2026 17:45:15 +0000 (UTC) From: Nick Faro via B4 Relay Date: Thu, 27 Aug 2026 19:44:13 +0200 Subject: [PATCH 3/6] media: cx231xx: reject V4L2 operations after disconnect Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260827-cx231xx-disconnect-lifetime-v1-3-7bbf946bbd36@hotmail.com> References: <20260827-cx231xx-disconnect-lifetime-v1-0-7bbf946bbd36@hotmail.com> In-Reply-To: <20260827-cx231xx-disconnect-lifetime-v1-0-7bbf946bbd36@hotmail.com> To: Mauro Carvalho Chehab , Hans Verkuil Cc: linux-media@vger.kernel.org, linux-kernel@vger.kernel.org, Nick Faro X-Mailer: b4 0.13.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1787852712; l=5226; i=yux50000@hotmail.com; s=20260827; h=from:subject:message-id; bh=WUN+Os7QniMSebswPp2JQ6AqLYFuOZMfAt4jcJd3hok=; b=aqaY0I2Ks5ScoefqErcgF2lcgJNNCuFSx1MN+F9f7T2PxrIt6MhtY9AW5r0xFLuSJ1qaKbebL WjhkPFfAXYCByyxVcC6l77J+0lwzXPwt0zRInAgoRUCvKiM55CgiMZg X-Developer-Key: i=yux50000@hotmail.com; a=ed25519; pk=FMSCCFHmUW8ylFpPOeaegUBqrRhzdMS2snqX/kNbLtM= X-Endpoint-Received: by B4 Relay for yux50000@hotmail.com/20260827 with auth_id=979 X-Original-From: Nick Faro Reply-To: yux50000@hotmail.com From: Nick Faro An open V4L2 file can outlive USB disconnect, and VB2 can invoke its stop-streaming callback while releasing that file. The existing callbacks continue into subdevice and USB commands even though the hardware is gone. Reject new analog, VBI and MPEG opens or streams after disconnect. Let stop and close callbacks return queued buffers and release file state, but skip operations which require access to the disconnected device. Fixes: e0d3bafd0258 ("V4L/DVB (10954): Add cx231xx USB driver") Assisted-by: Codex:gpt-5.6-sol Signed-off-by: Nick Faro --- drivers/media/usb/cx231xx/cx231xx-417.c | 41 ++++++++++++++++++++++++---= ---- drivers/media/usb/cx231xx/cx231xx-vbi.c | 5 ++++ drivers/media/usb/cx231xx/cx231xx-video.c | 18 +++++++++++++- 3 files changed, 54 insertions(+), 10 deletions(-) diff --git a/drivers/media/usb/cx231xx/cx231xx-417.c b/drivers/media/usb/cx= 231xx/cx231xx-417.c index 2323584bf818..3a509e55f61d 100644 --- a/drivers/media/usb/cx231xx/cx231xx-417.c +++ b/drivers/media/usb/cx231xx/cx231xx-417.c @@ -1396,6 +1396,11 @@ static int start_streaming(struct vb2_queue *vq, uns= igned int count) struct cx231xx_dmaqueue *vidq =3D &dev->video_mode.vidq; int ret =3D 0; =20 + if (dev->state & DEV_DISCONNECTED) { + return_all_buffers(dev, VB2_BUF_STATE_QUEUED); + return -ENODEV; + } + vidq->sequence =3D 0; dev->mode_tv =3D 1; =20 @@ -1429,20 +1434,22 @@ static void stop_streaming(struct vb2_queue *vq) struct cx231xx *dev =3D vb2_get_drv_priv(vq); unsigned long flags; =20 - call_all(dev, video, s_stream, 0); - - cx231xx_stop_TS1(dev); + if (!(dev->state & DEV_DISCONNECTED)) { + call_all(dev, video, s_stream, 0); + cx231xx_stop_TS1(dev); + } =20 /* do this before setting alternate! */ if (dev->USE_ISO) cx231xx_uninit_isoc(dev); else cx231xx_uninit_bulk(dev); - cx231xx_set_mode(dev, CX231XX_SUSPEND); - - cx231xx_api_cmd(dev, CX2341X_ENC_STOP_CAPTURE, 3, 0, - CX231xx_END_NOW, CX231xx_MPEG_CAPTURE, - CX231xx_RAW_BITS_NONE); + if (!(dev->state & DEV_DISCONNECTED)) { + cx231xx_set_mode(dev, CX231XX_SUSPEND); + cx231xx_api_cmd(dev, CX2341X_ENC_STOP_CAPTURE, 3, 0, + CX231xx_END_NOW, CX231xx_MPEG_CAPTURE, + CX231xx_RAW_BITS_NONE); + } =20 spin_lock_irqsave(&dev->video_mode.slock, flags); if (dev->USE_ISO) @@ -1593,9 +1600,25 @@ static int vidioc_log_status(struct file *file, void= *priv) return v4l2_ctrl_log_status(file, priv); } =20 +static int cx231xx_mpeg_open(struct file *file) +{ + struct cx231xx *dev =3D video_drvdata(file); + int ret; + + if (mutex_lock_interruptible(&dev->lock)) + return -ERESTARTSYS; + if (dev->state & DEV_DISCONNECTED) + ret =3D -ENODEV; + else + ret =3D v4l2_fh_open(file); + mutex_unlock(&dev->lock); + + return ret; +} + static const struct v4l2_file_operations mpeg_fops =3D { .owner =3D THIS_MODULE, - .open =3D v4l2_fh_open, + .open =3D cx231xx_mpeg_open, .release =3D vb2_fop_release, .read =3D vb2_fop_read, .poll =3D vb2_fop_poll, diff --git a/drivers/media/usb/cx231xx/cx231xx-vbi.c b/drivers/media/usb/cx= 231xx/cx231xx-vbi.c index b51955f1dd30..6f28b969408f 100644 --- a/drivers/media/usb/cx231xx/cx231xx-vbi.c +++ b/drivers/media/usb/cx231xx/cx231xx-vbi.c @@ -220,6 +220,11 @@ static int vbi_start_streaming(struct vb2_queue *vq, u= nsigned int count) struct cx231xx_dmaqueue *vidq =3D &dev->vbi_mode.vidq; int ret; =20 + if (dev->state & DEV_DISCONNECTED) { + return_all_buffers(dev, VB2_BUF_STATE_QUEUED); + return -ENODEV; + } + vidq->sequence =3D 0; ret =3D cx231xx_init_vbi_isoc(dev, CX231XX_NUM_VBI_PACKETS, CX231XX_NUM_VBI_BUFS, diff --git a/drivers/media/usb/cx231xx/cx231xx-video.c b/drivers/media/usb/= cx231xx/cx231xx-video.c index 058e8eed2847..154bb4300392 100644 --- a/drivers/media/usb/cx231xx/cx231xx-video.c +++ b/drivers/media/usb/cx231xx/cx231xx-video.c @@ -767,6 +767,11 @@ static int start_streaming(struct vb2_queue *vq, unsig= ned int count) struct cx231xx_dmaqueue *vidq =3D &dev->video_mode.vidq; int ret =3D 0; =20 + if (dev->state & DEV_DISCONNECTED) { + return_all_buffers(dev, VB2_BUF_STATE_QUEUED); + return -ENODEV; + } + vidq->sequence =3D 0; dev->mode_tv =3D 0; =20 @@ -791,7 +796,8 @@ static void stop_streaming(struct vb2_queue *vq) { struct cx231xx *dev =3D vb2_get_drv_priv(vq); =20 - call_all(dev, video, s_stream, 0); + if (!(dev->state & DEV_DISCONNECTED)) + call_all(dev, video, s_stream, 0); return_all_buffers(dev, VB2_BUF_STATE_ERROR); } =20 @@ -1499,6 +1505,10 @@ static int cx231xx_v4l2_open(struct file *filp) =20 if (mutex_lock_interruptible(&dev->lock)) return -ERESTARTSYS; + if (dev->state & DEV_DISCONNECTED) { + mutex_unlock(&dev->lock); + return -ENODEV; + } =20 ret =3D v4l2_fh_open(filp); if (ret) { @@ -1581,6 +1591,12 @@ static int cx231xx_close(struct file *filp) =20 _vb2_fop_release(filp, NULL); =20 + if (dev->state & DEV_DISCONNECTED) { + --dev->users; + wake_up_interruptible(&dev->open); + return 0; + } + if (--dev->users =3D=3D 0) { /* Save some power by putting tuner to sleep */ call_all(dev, tuner, standby); --=20 2.43.0 From nobody Sun Sep 27 00:40:21 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2279932F749; Thu, 27 Aug 2026 17:45:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787852716; cv=none; b=FTujRDKIM/KeDuXZEH+hWACHaxRIdDjkZNEL/ZVtG8hMPZicoXTnFm+u0LPAQwAb7SCDRfRsuyIqFbEXgpkcKYRoDwuJhoOhBtEYU241iJUqEQJ5L8A7qvaH6s59UcHUGPMgmukZmMjIoCWDjWPYswmeef8cMyYzfOr5aN7k1e8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787852716; c=relaxed/simple; bh=iU1lx59IPAGOqCIDngai7VZTcW11MzqHcWxhFppTU/A=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=gm8xKZM+vzC1PzkAG3XTXg0ord/ZeScMN1xWWD3GwjZCcTuPxV9xx0xsSELJV5d+NoYtU/+IKbHO5IF7WtEU2MWx8BGLD+1h0Cfe/ogzJvwXPmTDAG87OmtLBBrpiPSNB9xqxtTD/is0809zpzaMIcmXRUWMlXoWoQ1ASFu2pLw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Grd53+SD; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="Grd53+SD" Received: by smtp.kernel.org (Postfix) with ESMTPS id 51E8AC2BCFC; Thu, 27 Aug 2026 17:45:15 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1787852715; bh=iU1lx59IPAGOqCIDngai7VZTcW11MzqHcWxhFppTU/A=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=Grd53+SDRTjP7hb1kORXCrfhayLcZNwh/FwwkLpyau8y+9PswWLsn+qb6xvNE4xA4 7pJCqvnnu3Mo2eCtyLeDhBp16xlUW5sqCVQWa1R1INo7LimQgwYrhrb3dlDQ5w73l/ FP0x5Niq+s5IImK9LiaUWT+NORN/3Usy0dT3YoBILWhRVijPlTlGeWpQ5O9z0HhK6y UmSM3YnltLVZUS359uJJuvJrsXMu0LUyGzMzv1RsUPQ523wOq/nDFAYak+oy3Eup70 MVL92p2WJmDxVMkxaycMuTYDqm9XMDeF0QyQQycScQldTy6vC4LYci1mRDmPNCmiOm EqZzWkpW4BQxQ== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 3ED84C61DD3; Thu, 27 Aug 2026 17:45:15 +0000 (UTC) From: Nick Faro via B4 Relay Date: Thu, 27 Aug 2026 19:44:14 +0200 Subject: [PATCH 4/6] media: cx231xx: make ALSA teardown disconnect-safe Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260827-cx231xx-disconnect-lifetime-v1-4-7bbf946bbd36@hotmail.com> References: <20260827-cx231xx-disconnect-lifetime-v1-0-7bbf946bbd36@hotmail.com> In-Reply-To: <20260827-cx231xx-disconnect-lifetime-v1-0-7bbf946bbd36@hotmail.com> To: Mauro Carvalho Chehab , Hans Verkuil Cc: linux-media@vger.kernel.org, linux-kernel@vger.kernel.org, Nick Faro X-Mailer: b4 0.13.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1787852712; l=3100; i=yux50000@hotmail.com; s=20260827; h=from:subject:message-id; bh=2wJ7fv8GuAFzsZR7lLL6TpM9/IcmchnjsNHHBj9K50o=; b=oo4zrYhdeUJ7VUQxDmUUJjozwjG0+7VrfPlglj1FLeSZ/YhyF2DETdgIdlDDkLPqSXnuIgfF4 RM8jj4GPt70BaO3VclaTVIhz5wz7NUMc/QwXlHFOZwvbcGZZDMOzGAd X-Developer-Key: i=yux50000@hotmail.com; a=ed25519; pk=FMSCCFHmUW8ylFpPOeaegUBqrRhzdMS2snqX/kNbLtM= X-Endpoint-Received: by B4 Relay for yux50000@hotmail.com/20260827 with auth_id=979 X-Original-From: Nick Faro Reply-To: yux50000@hotmail.com From: Nick Faro The ALSA card and an open PCM file can outlive the USB interface. Work items, PCM callbacks and close currently remain able to touch the hardware after disconnect, and card teardown does not actively disconnect userspace. Disconnect the ALSA card and stop its stream and transfers. Cancel its trigger work before deferring the final card release. Make late PCM callbacks report the disconnected state and let close release software state without issuing hardware commands. Fixes: e0d3bafd0258 ("V4L/DVB (10954): Add cx231xx USB driver") Assisted-by: Codex:gpt-5.6-sol Signed-off-by: Nick Faro --- drivers/media/usb/cx231xx/cx231xx-audio.c | 31 +++++++++++++++++++++++++++= ++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/drivers/media/usb/cx231xx/cx231xx-audio.c b/drivers/media/usb/= cx231xx/cx231xx-audio.c index dd819a546af9..a10b887edf51 100644 --- a/drivers/media/usb/cx231xx/cx231xx-audio.c +++ b/drivers/media/usb/cx231xx/cx231xx-audio.c @@ -448,10 +448,17 @@ static int snd_cx231xx_pcm_close(struct snd_pcm_subst= ream *substream) return -ENODEV; } =20 - dev_dbg(dev->dev, "closing device\n"); - /* inform hardware to stop streaming */ mutex_lock(&dev->lock); + dev->adev.capture_pcm_substream =3D NULL; + if (dev->state & DEV_DISCONNECTED) { + dev->adev.users--; + mutex_unlock(&dev->lock); + cancel_work_sync(&dev->wq_trigger); + return 0; + } + + dev_dbg(dev->dev, "closing device\n"); ret =3D cx231xx_capture_start(dev, 0, Audio); =20 /* set alternate setting for audio interface */ @@ -485,6 +492,9 @@ static int snd_cx231xx_prepare(struct snd_pcm_substream= *substream) { struct cx231xx *dev =3D snd_pcm_substream_chip(substream); =20 + if (dev->state & DEV_DISCONNECTED) + return -ENODEV; + dev->adev.hwptr_done_capture =3D 0; dev->adev.capture_transfer_done =3D 0; =20 @@ -495,6 +505,14 @@ static void audio_trigger(struct work_struct *work) { struct cx231xx *dev =3D container_of(work, struct cx231xx, wq_trigger); =20 + if (dev->state & DEV_DISCONNECTED) { + if (dev->USE_ISO) + cx231xx_isoc_audio_deinit(dev); + else + cx231xx_bulk_audio_deinit(dev); + return; + } + if (atomic_read(&dev->stream_started)) { dev_dbg(dev->dev, "starting capture"); if (is_fw_load(dev) =3D=3D 0) @@ -545,6 +563,8 @@ static snd_pcm_uframes_t snd_cx231xx_capture_pointer(st= ruct snd_pcm_substream snd_pcm_uframes_t hwptr_done; =20 dev =3D snd_pcm_substream_chip(substream); + if (dev->state & DEV_DISCONNECTED) + return SNDRV_PCM_POS_XRUN; =20 spin_lock_irqsave(&dev->adev.slock, flags); hwptr_done =3D dev->adev.hwptr_done_capture; @@ -689,6 +709,13 @@ static int cx231xx_audio_fini(struct cx231xx *dev) if (dev->adev.sndcard) { card =3D dev->adev.sndcard; dev->adev.sndcard =3D NULL; + snd_card_disconnect(card); + atomic_set(&dev->stream_started, 0); + cancel_work_sync(&dev->wq_trigger); + if (dev->USE_ISO) + cx231xx_isoc_audio_deinit(dev); + else + cx231xx_bulk_audio_deinit(dev); snd_card_free_when_closed(card); } =20 --=20 2.43.0 From nobody Sun Sep 27 00:40:21 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 64DCC4A33E6; Thu, 27 Aug 2026 17:45:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787852716; cv=none; b=c83886W7Mwc2yF61Bw9WpqbPxsnpsysuUkNbjFLB2PW6vYv0Nyl/DAV+5H3tvCmbD9RjX34ACaXEXD1GO9nR3hDdd5G/9XsKHNWPV7oBAXFiNwWfTw05Cpm2q9Rl+g+xWp2aY0oBsl2gZfrE44jFisupXYK2TDGpvks0bHNu9gY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787852716; c=relaxed/simple; bh=XHM40DblLd0zIUb9AIb+d0er/7ZzbUhvpS2O6PBcn5A=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=ZtBptL6gIi71urMql5BrBd58eC4nnQrpURQjxYvdJezqpu3z7dhILiAWkckMGscEl98xjMYU6wPfRGttsd55dj8+4zGkvfK3HzvhQuZDkcM9LjslXVn1pE+Qbc5YZIox64jMh6An8n8BKefmxq1Pni1/sTCmZ6Y2Gci2vyGDZ0A= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=j/Zl48jy; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="j/Zl48jy" Received: by smtp.kernel.org (Postfix) with ESMTPS id 5F518C2BCFB; Thu, 27 Aug 2026 17:45:15 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1787852715; bh=XHM40DblLd0zIUb9AIb+d0er/7ZzbUhvpS2O6PBcn5A=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=j/Zl48jye6zuxdh5fPNeqvDSbAKwSV7qgX3qT6tfKT4QwiyTw+j/EZyafzrBxiXaZ Nv4p/C+r/6zqgaeUSgo7Iy9/vOo22Qjo54BRgokTFlihUBCTSitU6lojXhnY1LJ9ck c/pCxB3cWD7Kd7jVVaoiBXPx1GEaBK5mxhOy4MJZcuU+h+COn/PyqrwgWNej6Lhrxt 5yTIXs7k0iNtnN5iXdFU0Dgqj5hlas34NG7xlpo2rdvfK0pyS8/08TV/XItx6zRxCp aokUUsmh0/SVgj913frcapUll8RC0NVjzI7fsFvWJ6K7/sGErxkytqoA+M2zqqTd4y vLSW5lZMWRcQw== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 4D368C61DCD; Thu, 27 Aug 2026 17:45:15 +0000 (UTC) From: Nick Faro via B4 Relay Date: Thu, 27 Aug 2026 19:44:15 +0200 Subject: [PATCH 5/6] media: cx231xx: always unregister nodes on USB disconnect Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260827-cx231xx-disconnect-lifetime-v1-5-7bbf946bbd36@hotmail.com> References: <20260827-cx231xx-disconnect-lifetime-v1-0-7bbf946bbd36@hotmail.com> In-Reply-To: <20260827-cx231xx-disconnect-lifetime-v1-0-7bbf946bbd36@hotmail.com> To: Mauro Carvalho Chehab , Hans Verkuil Cc: linux-media@vger.kernel.org, linux-kernel@vger.kernel.org, Nick Faro X-Mailer: b4 0.13.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1787852712; l=5250; i=yux50000@hotmail.com; s=20260827; h=from:subject:message-id; bh=lfYMdUVPkBvAiiFLQfWpvqyr8TfO0f8rtCgH5KZb5Kk=; b=QcsLRD7jwBhZLD3x9enMGFZKq90mt713EljTrvGk0P4MwqGVCBZViLyEhidR+GLnjZieYsSA0 1WoRYO08rwyDwEOkDm+Nh7ZfKcXMcsMWehf4Rb9Hf1g/K7OpFaENMeE X-Developer-Key: i=yux50000@hotmail.com; a=ed25519; pk=FMSCCFHmUW8ylFpPOeaegUBqrRhzdMS2snqX/kNbLtM= X-Endpoint-Received: by B4 Relay for yux50000@hotmail.com/20260827 with auth_id=979 X-Original-From: Nick Faro Reply-To: yux50000@hotmail.com From: Nick Faro The disconnect path skips cx231xx_release_resources() whenever an analog video file is open. No close path performs the deferred teardown, so the V4L2 nodes and I2C adapters remain registered and a later probe collides with the stale instance. The users counter also does not cover MPEG, ALSA or other framework references. Always unregister every device node and subsystem during disconnect. Use the VB2 unregister helper for queue-backed nodes so active streams are stopped, and serialize disconnection against in-flight file operations. The v4l2_device references now keep the backing memory alive until old file handles close. Fixes: e0d3bafd0258 ("V4L/DVB (10954): Add cx231xx USB driver") Assisted-by: Codex:gpt-5.6-sol Signed-off-by: Nick Faro --- drivers/media/usb/cx231xx/cx231xx-417.c | 2 +- drivers/media/usb/cx231xx/cx231xx-cards.c | 11 +++++------ drivers/media/usb/cx231xx/cx231xx-video.c | 10 +++++----- drivers/media/usb/cx231xx/cx231xx.h | 1 + 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/media/usb/cx231xx/cx231xx-417.c b/drivers/media/usb/cx= 231xx/cx231xx-417.c index 3a509e55f61d..9bda68666b05 100644 --- a/drivers/media/usb/cx231xx/cx231xx-417.c +++ b/drivers/media/usb/cx231xx/cx231xx-417.c @@ -1672,7 +1672,7 @@ void cx231xx_417_unregister(struct cx231xx *dev) dprintk(3, "%s()\n", __func__); =20 if (video_is_registered(&dev->v4l_device)) { - video_unregister_device(&dev->v4l_device); + vb2_video_unregister_device(&dev->v4l_device); } } =20 diff --git a/drivers/media/usb/cx231xx/cx231xx-cards.c b/drivers/media/usb/= cx231xx/cx231xx-cards.c index 1b1e7bca4c6d..8e23de4cddf8 100644 --- a/drivers/media/usb/cx231xx/cx231xx-cards.c +++ b/drivers/media/usb/cx231xx/cx231xx-cards.c @@ -1946,7 +1946,6 @@ static int cx231xx_usb_probe(struct usb_interface *in= terface, cx231xx_close_extension(dev); cx231xx_ir_exit(dev); cx231xx_release_analog_resources(dev); - cx231xx_417_unregister(dev); cx231xx_remove_from_devlist(dev); cx231xx_dev_uninit(dev); err_init: @@ -1970,7 +1969,8 @@ static int cx231xx_usb_probe(struct usb_interface *in= terface, /* * cx231xx_usb_disconnect() * called when the device gets disconnected - * video device will be unregistered on v4l2_close in case it is still open + * Device nodes are unregistered immediately. Their backing memory remains + * alive until the last open file descriptor is closed. */ static void cx231xx_usb_disconnect(struct usb_interface *interface) { @@ -1997,7 +1997,7 @@ static void cx231xx_usb_disconnect(struct usb_interfa= ce *interface) =20 if (dev->users) { dev_warn(dev->dev, - "device %s is open! Deregistration and memory deallocation are deferre= d on close.\n", + "device %s is open; disconnecting it now\n", video_device_node_name(&dev->vdev)); =20 /* Even having users, it is safe to remove the RC i2c driver */ @@ -2007,17 +2007,16 @@ static void cx231xx_usb_disconnect(struct usb_inter= face *interface) cx231xx_uninit_isoc(dev); else cx231xx_uninit_bulk(dev); + cx231xx_uninit_vbi_isoc(dev); wake_up_interruptible(&dev->wait_frame); wake_up_interruptible(&dev->wait_stream); - } else { } =20 cx231xx_close_extension(dev); =20 mutex_unlock(&dev->lock); =20 - if (!dev->users) - cx231xx_release_resources(dev); + cx231xx_release_resources(dev); } =20 static struct usb_driver cx231xx_usb_driver =3D { diff --git a/drivers/media/usb/cx231xx/cx231xx-video.c b/drivers/media/usb/= cx231xx/cx231xx-video.c index 154bb4300392..c8c460da2b9a 100644 --- a/drivers/media/usb/cx231xx/cx231xx-video.c +++ b/drivers/media/usb/cx231xx/cx231xx-video.c @@ -1561,21 +1561,21 @@ void cx231xx_release_analog_resources(struct cx231x= x *dev) =20 /*FIXME: I2C IR should be disconnected */ =20 + if (dev->board.has_417) + cx231xx_417_unregister(dev); + if (video_is_registered(&dev->radio_dev)) video_unregister_device(&dev->radio_dev); if (video_is_registered(&dev->vbi_dev)) { dev_info(dev->dev, "V4L2 device %s deregistered\n", video_device_node_name(&dev->vbi_dev)); - video_unregister_device(&dev->vbi_dev); + vb2_video_unregister_device(&dev->vbi_dev); } if (video_is_registered(&dev->vdev)) { dev_info(dev->dev, "V4L2 device %s deregistered\n", video_device_node_name(&dev->vdev)); =20 - if (dev->board.has_417) - cx231xx_417_unregister(dev); - - video_unregister_device(&dev->vdev); + vb2_video_unregister_device(&dev->vdev); } } =20 diff --git a/drivers/media/usb/cx231xx/cx231xx.h b/drivers/media/usb/cx231x= x/cx231xx.h index 19f5036a78d7..8fb1eb9d600e 100644 --- a/drivers/media/usb/cx231xx/cx231xx.h +++ b/drivers/media/usb/cx231xx/cx231xx.h @@ -873,6 +873,7 @@ void cx231xx_stop_TS1(struct cx231xx *dev); void cx231xx_start_TS1(struct cx231xx *dev); void cx231xx_uninit_isoc(struct cx231xx *dev); void cx231xx_uninit_bulk(struct cx231xx *dev); +void cx231xx_uninit_vbi_isoc(struct cx231xx *dev); int cx231xx_set_mode(struct cx231xx *dev, enum cx231xx_mode set_mode); int cx231xx_unmute_audio(struct cx231xx *dev); int cx231xx_ep5_bulkout(struct cx231xx *dev, u8 *firmware, u16 size); --=20 2.43.0 From nobody Sun Sep 27 00:40:21 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6926D4A33E9; Thu, 27 Aug 2026 17:45:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787852716; cv=none; b=pntlodHD6MvWiLWpgE72f7ifGc1hKP8SxWElZF8r9zAvx+I5DGqT2mhurvMBPOV4YD4WA53LxMGQgjMjruvND+yYp9dGgHQaMNkINtJcTy0KsrN5STum1QtyadLvM9mGvZQBSda7xkMgo7Lhbc9EsxM7C2HI9nCetemPqrbUpEg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787852716; c=relaxed/simple; bh=tBqmVQDcv0MCXnT2lJ0pm3kukIv1O5TjWqubxkLcpNE=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=ZTadJOYy3AhGFOSl8BPfk/ixF3vfznDiVJ5b7chATZgDilFUeUCqtRaxUmjPYE9K3/vh1VMZZI7yNFOIIzy976jWIgwyJUQSsUHFNHMLM2WrWoCQtdw+WGEZBK6k2BU10UMY6gh4kB2UvuDTx+InnaL17p4zI2qTGqc+JRZQltU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=mqjmAZa+; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="mqjmAZa+" Received: by smtp.kernel.org (Postfix) with ESMTPS id 6E0BAC2BCFF; Thu, 27 Aug 2026 17:45:15 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1787852715; bh=tBqmVQDcv0MCXnT2lJ0pm3kukIv1O5TjWqubxkLcpNE=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=mqjmAZa+tWgMWq2Vd7yIzlZZz5IQUlIojNJdOXYtkHSq+6NyN0kxNutCe6eSq16Ef 3+k3VpSq+YDHowBnIYVOjY9DrrQb76N9IfsvNNV2z0fNBuBivzEyusrcXgT1zcVAZK E9qKeXjDbKo2W7S4/CNB6d4W6Cn43P8vcqnhH4/tdKmEAuHRNcS5i5ZWBcfZ3oC64T iup+BN1h/pZ4Qk9Jodg21vkbsP0oBLC3L6vVnyR/LXdheh202jpbP0ACNZBMvvZDAm 9rgpOHvBRyiTxhReeigS/rCUhVJNOSwv8urTyfd1ufgBDzt/wvJnIgcal0hXjlS6qD 9IcSpiofBuuLQ== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 5BD34C61DD4; Thu, 27 Aug 2026 17:45:15 +0000 (UTC) From: Nick Faro via B4 Relay Date: Thu, 27 Aug 2026 19:44:16 +0200 Subject: [PATCH 6/6] media: cx231xx: size alternate-setting arrays by element count Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260827-cx231xx-disconnect-lifetime-v1-6-7bbf946bbd36@hotmail.com> References: <20260827-cx231xx-disconnect-lifetime-v1-0-7bbf946bbd36@hotmail.com> In-Reply-To: <20260827-cx231xx-disconnect-lifetime-v1-0-7bbf946bbd36@hotmail.com> To: Mauro Carvalho Chehab , Hans Verkuil Cc: linux-media@vger.kernel.org, linux-kernel@vger.kernel.org, Nick Faro X-Mailer: b4 0.13.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1787852712; l=3377; i=yux50000@hotmail.com; s=20260827; h=from:subject:message-id; bh=kLY4AOB7qHaFhPJKspXqxDDTNgxhM5uHaXa6/IBCVAU=; b=JLFKzpuefLQauppuvB7mF+R3+uw3MRQUz7Xbnfb2Ej0U8gzNTvZ0cL7/U6Hbdn4oGAjnpOjDH P7lmJqHh+ceDicrviTHBxEQZym2ZYhfRLJg5IeyIDDP+/f5dLhRepxU X-Developer-Key: i=yux50000@hotmail.com; a=ed25519; pk=FMSCCFHmUW8ylFpPOeaegUBqrRhzdMS2snqX/kNbLtM= X-Endpoint-Received: by B4 Relay for yux50000@hotmail.com/20260827 with auth_id=979 X-Original-From: Nick Faro Reply-To: yux50000@hotmail.com From: Nick Faro The arguments to kmalloc_array() are the number of elements followed by the size of each element. The driver instead passes 32 and the number of alternate settings, apparently confusing the width of the stored value with its size in bytes. Allocate one correctly sized element for each alternate setting in the video, VBI, sliced-caption, transport-stream and audio arrays. Fixes: e0d3bafd0258 ("V4L/DVB (10954): Add cx231xx USB driver") Assisted-by: Codex:gpt-5.6-sol Signed-off-by: Nick Faro --- drivers/media/usb/cx231xx/cx231xx-audio.c | 4 +++- drivers/media/usb/cx231xx/cx231xx-cards.c | 16 ++++++++++++---- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/drivers/media/usb/cx231xx/cx231xx-audio.c b/drivers/media/usb/= cx231xx/cx231xx-audio.c index a10b887edf51..eaddad793900 100644 --- a/drivers/media/usb/cx231xx/cx231xx-audio.c +++ b/drivers/media/usb/cx231xx/cx231xx-audio.c @@ -656,7 +656,9 @@ static int cx231xx_audio_init(struct cx231xx *dev) dev_info(dev->dev, "audio EndPoint Addr 0x%x, Alternate settings: %i\n", adev->end_point_addr, adev->num_alt); - adev->alt_max_pkt_size =3D kmalloc_array(32, adev->num_alt, GFP_KERNEL); + adev->alt_max_pkt_size =3D kmalloc_array(adev->num_alt, + sizeof(*adev->alt_max_pkt_size), + GFP_KERNEL); if (!adev->alt_max_pkt_size) { err =3D -ENOMEM; goto err_free_card; diff --git a/drivers/media/usb/cx231xx/cx231xx-cards.c b/drivers/media/usb/= cx231xx/cx231xx-cards.c index 8e23de4cddf8..3c4bbf724d63 100644 --- a/drivers/media/usb/cx231xx/cx231xx-cards.c +++ b/drivers/media/usb/cx231xx/cx231xx-cards.c @@ -1606,7 +1606,9 @@ static int cx231xx_init_v4l2(struct cx231xx *dev, dev->video_mode.num_alt); =20 dev->video_mode.alt_max_pkt_size =3D - kmalloc_array(32, dev->video_mode.num_alt, GFP_KERNEL); + kmalloc_array(dev->video_mode.num_alt, + sizeof(*dev->video_mode.alt_max_pkt_size), + GFP_KERNEL); if (dev->video_mode.alt_max_pkt_size =3D=3D NULL) return -ENOMEM; =20 @@ -1648,7 +1650,9 @@ static int cx231xx_init_v4l2(struct cx231xx *dev, =20 /* compute alternate max packet sizes for vbi */ dev->vbi_mode.alt_max_pkt_size =3D - kmalloc_array(32, dev->vbi_mode.num_alt, GFP_KERNEL); + kmalloc_array(dev->vbi_mode.num_alt, + sizeof(*dev->vbi_mode.alt_max_pkt_size), + GFP_KERNEL); if (dev->vbi_mode.alt_max_pkt_size =3D=3D NULL) return -ENOMEM; =20 @@ -1691,7 +1695,9 @@ static int cx231xx_init_v4l2(struct cx231xx *dev, dev->sliced_cc_mode.end_point_addr, dev->sliced_cc_mode.num_alt); dev->sliced_cc_mode.alt_max_pkt_size =3D - kmalloc_array(32, dev->sliced_cc_mode.num_alt, GFP_KERNEL); + kmalloc_array(dev->sliced_cc_mode.num_alt, + sizeof(*dev->sliced_cc_mode.alt_max_pkt_size), + GFP_KERNEL); if (dev->sliced_cc_mode.alt_max_pkt_size =3D=3D NULL) return -ENOMEM; =20 @@ -1887,7 +1893,9 @@ static int cx231xx_usb_probe(struct usb_interface *in= terface, dev->ts1_mode.num_alt); =20 dev->ts1_mode.alt_max_pkt_size =3D - kmalloc_array(32, dev->ts1_mode.num_alt, GFP_KERNEL); + kmalloc_array(dev->ts1_mode.num_alt, + sizeof(*dev->ts1_mode.alt_max_pkt_size), + GFP_KERNEL); if (dev->ts1_mode.alt_max_pkt_size =3D=3D NULL) { retval =3D -ENOMEM; goto err_video_alt; --=20 2.43.0