| From foo@baz Mon Apr 9 17:09:24 CEST 2018 |
| From: Petr Cvek <petr.cvek@tul.cz> |
| Date: Mon, 24 Apr 2017 22:51:58 -0300 |
| Subject: [media] pxa_camera: fix module remove codepath for v4l2 clock |
| |
| From: Petr Cvek <petr.cvek@tul.cz> |
| |
| |
| [ Upstream commit e3b4d10cc057522353c4a02f2f90dca6a52e006f ] |
| |
| The conversion from soc_camera omitted a correct handling of the clock |
| gating for a sensor. When the pxa_camera driver module was removed it |
| tried to unregister clk, but this caused a similar warning: |
| |
| WARNING: CPU: 0 PID: 6740 at drivers/media/v4l2-core/v4l2-clk.c:278 |
| v4l2_clk_unregister(): Refusing to unregister ref-counted 0-0030 clock! |
| |
| The clock was at time still refcounted by the sensor driver. Before |
| the removing of the pxa_camera the clock must be dropped by the sensor |
| driver. This should be triggered by v4l2_async_notifier_unregister() call |
| which removes sensor driver module too, calls unbind() function and then |
| tries to probe sensor driver again. Inside unbind() we can safely |
| unregister the v4l2 clock as the sensor driver got removed. The original |
| v4l2_clk_unregister() should be put inside test as the clock can be |
| already unregistered from unbind(). If there was not any bound sensor |
| the clock is still present. |
| |
| The codepath is practically a copy from the old soc_camera. The bug was |
| tested with a pxa_camera+ov9640 combination during the conversion |
| of the ov9640 from the soc_camera. |
| |
| Signed-off-by: Petr Cvek <petr.cvek@tul.cz> |
| Tested-by: Robert Jarzmik <robert.jarzmik@free.fr> |
| Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> |
| Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com> |
| Signed-off-by: Sasha Levin <alexander.levin@microsoft.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| drivers/media/platform/pxa_camera.c | 14 +++++++++++++- |
| 1 file changed, 13 insertions(+), 1 deletion(-) |
| |
| --- a/drivers/media/platform/pxa_camera.c |
| +++ b/drivers/media/platform/pxa_camera.c |
| @@ -2169,6 +2169,12 @@ static void pxa_camera_sensor_unbind(str |
| pxa_dma_stop_channels(pcdev); |
| |
| pxa_camera_destroy_formats(pcdev); |
| + |
| + if (pcdev->mclk_clk) { |
| + v4l2_clk_unregister(pcdev->mclk_clk); |
| + pcdev->mclk_clk = NULL; |
| + } |
| + |
| video_unregister_device(&pcdev->vdev); |
| pcdev->sensor = NULL; |
| |
| @@ -2495,7 +2501,13 @@ static int pxa_camera_remove(struct plat |
| dma_release_channel(pcdev->dma_chans[1]); |
| dma_release_channel(pcdev->dma_chans[2]); |
| |
| - v4l2_clk_unregister(pcdev->mclk_clk); |
| + v4l2_async_notifier_unregister(&pcdev->notifier); |
| + |
| + if (pcdev->mclk_clk) { |
| + v4l2_clk_unregister(pcdev->mclk_clk); |
| + pcdev->mclk_clk = NULL; |
| + } |
| + |
| v4l2_device_unregister(&pcdev->v4l2_dev); |
| |
| dev_info(&pdev->dev, "PXA Camera driver unloaded\n"); |