Unbinding the driver while streaming caused the driver to hang. The cause of this was failing to use the v4l2_device release function and the use of devm_kmalloc for the state structure. Signed-off-by: Hans Verkuil <hverkuil-cisco@xxxxxxxxx> --- drivers/media/platform/vicodec/vicodec-core.c | 23 +++++++++++++++---- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/drivers/media/platform/vicodec/vicodec-core.c b/drivers/media/platform/vicodec/vicodec-core.c index 1982e3f95f67..ee7f5b8b897f 100644 --- a/drivers/media/platform/vicodec/vicodec-core.c +++ b/drivers/media/platform/vicodec/vicodec-core.c @@ -2153,18 +2153,31 @@ static int register_instance(struct vicodec_dev *dev, return 0; } +static void vicodec_v4l2_dev_release(struct v4l2_device *v4l2_dev) +{ + struct vicodec_dev *dev = container_of(v4l2_dev, struct vicodec_dev, v4l2_dev); + + v4l2_device_unregister(&dev->v4l2_dev); + v4l2_m2m_release(dev->stateful_enc.m2m_dev); + v4l2_m2m_release(dev->stateful_dec.m2m_dev); + v4l2_m2m_release(dev->stateless_dec.m2m_dev); + kfree(dev); +} + static int vicodec_probe(struct platform_device *pdev) { struct vicodec_dev *dev; int ret; - dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL); + dev = kzalloc(sizeof(*dev), GFP_KERNEL); if (!dev) return -ENOMEM; ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev); if (ret) - return ret; + goto free_dev; + + dev->v4l2_dev.release = vicodec_v4l2_dev_release; #ifdef CONFIG_MEDIA_CONTROLLER dev->mdev.dev = &pdev->dev; @@ -2242,6 +2255,8 @@ static int vicodec_probe(struct platform_device *pdev) v4l2_m2m_release(dev->stateful_enc.m2m_dev); unreg_dev: v4l2_device_unregister(&dev->v4l2_dev); +free_dev: + kfree(dev); return ret; } @@ -2260,12 +2275,10 @@ static int vicodec_remove(struct platform_device *pdev) media_device_cleanup(&dev->mdev); #endif - v4l2_m2m_release(dev->stateful_enc.m2m_dev); - v4l2_m2m_release(dev->stateful_dec.m2m_dev); video_unregister_device(&dev->stateful_enc.vfd); video_unregister_device(&dev->stateful_dec.vfd); video_unregister_device(&dev->stateless_dec.vfd); - v4l2_device_unregister(&dev->v4l2_dev); + v4l2_device_put(&dev->v4l2_dev); return 0; } -- 2.20.1