Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

media: atomisp: Fix "stop stream timeout." error

Commit c7194b21809e ("media: atomisp: On streamoff wait for buffers owned
by the CSS to be given back") added draining of the CSS buffer queue to
the beginning of atomisp_stop_stream().

But it turns out that when telling the CSS to stop streaming it needs at
least 1 buffer queued, because the CSS firmware waits for a frame to be
completed before stopping and without buffers it cannot complete a frame.

At the end of atomisp_stop_stream() it is always safe to return buffer
ownership to the videobuf2-core. Either atomisp_css_stop() has successfully
stopped the stream; or the atomisp_reset() later on which power-cycles
the ISP will definitely have stopped the stream.

Drop the draining of the CSS buffer queue to fix the "stop stream timeout."
error and move the atomisp_flush_video_pipe() call after atomisp_reset(),
passing false for the warn_on_css_frames flag since some buffers still
being marked as owned by the CSS expected on stream off.

Also increase the timeout in destroy_stream(), since this waits for
the last frame to be completed this can take longer then 40 ms. When e.g.
using a framerate of 15 fps, this could take 66ms, make the timeout 200 ms
to be on the safe side.

Signed-off-by: Hans de Goede <hansg@kernel.org>
Reviewed-by: Andy Shevchenko <andy@kernel.org>
Link: https://lore.kernel.org/r/20250505210008.152659-6-hdegoede@redhat.com
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>

authored by

Hans de Goede and committed by
Mauro Carvalho Chehab
0193cce5 f01d091c

+4 -26
+1 -1
drivers/staging/media/atomisp/pci/atomisp_compat_css20.c
··· 387 387 } 388 388 389 389 if (stream_env->stream_state == CSS_STREAM_STARTED) { 390 - timeout = jiffies + msecs_to_jiffies(40); 390 + timeout = jiffies + msecs_to_jiffies(200); 391 391 while (1) { 392 392 if (ia_css_stream_has_stopped(stream_env->stream)) 393 393 break;
+1 -4
drivers/staging/media/atomisp/pci/atomisp_fops.c
··· 234 234 if (WARN_ON(css_pipe_id >= IA_CSS_PIPE_ID_NUM)) 235 235 return -EINVAL; 236 236 237 - if (pipe->stopping) 238 - return -EINVAL; 239 - 240 237 space = ATOMISP_CSS_Q_DEPTH - atomisp_buffers_in_css(pipe); 241 238 while (space--) { 242 239 struct ia_css_frame *frame; ··· 364 367 mutex_lock(&asd->isp->mutex); 365 368 366 369 ret = atomisp_pipe_check(pipe, false); 367 - if (ret || pipe->stopping) { 370 + if (ret) { 368 371 spin_lock_irqsave(&pipe->irq_lock, irqflags); 369 372 atomisp_buffer_done(frame, VB2_BUF_STATE_ERROR); 370 373 spin_unlock_irqrestore(&pipe->irq_lock, irqflags);
+2 -18
drivers/staging/media/atomisp/pci/atomisp_ioctl.c
··· 865 865 unsigned long flags; 866 866 int ret; 867 867 868 - /* 869 - * There is no guarantee that the buffers queued to / owned by the ISP 870 - * will properly be returned to the queue when stopping. Set a flag to 871 - * avoid new buffers getting queued and then wait for all the current 872 - * buffers to finish. 873 - */ 874 - pipe->stopping = true; 875 - mutex_unlock(&isp->mutex); 876 - /* wait max 1 second */ 877 - ret = wait_event_timeout(pipe->vb_queue.done_wq, 878 - atomisp_buffers_in_css(pipe) == 0, HZ); 879 - mutex_lock(&isp->mutex); 880 - pipe->stopping = false; 881 - if (ret == 0) 882 - dev_warn(isp->dev, "Warning timeout waiting for CSS to return buffers\n"); 883 - 884 868 spin_lock_irqsave(&isp->lock, flags); 885 869 asd->streaming = false; 886 870 spin_unlock_irqrestore(&isp->lock, flags); ··· 873 889 atomisp_css_irq_enable(isp, IA_CSS_IRQ_INFO_CSS_RECEIVER_SOF, false); 874 890 875 891 atomisp_css_stop(asd, false); 876 - 877 - atomisp_flush_video_pipe(pipe, state, true); 878 892 879 893 atomisp_subdev_cleanup_pending_events(asd); 880 894 ··· 901 919 pci_write_config_dword(pdev, PCI_I_CONTROL, 902 920 isp->saved_regs.i_control | MRFLD_PCI_I_CONTROL_SRSE_RESET_MASK); 903 921 atomisp_reset(isp); 922 + 923 + atomisp_flush_video_pipe(pipe, state, false); 904 924 905 925 /* Streams were destroyed by atomisp_css_stop(), recreate them. */ 906 926 ret = atomisp_create_pipes_stream(&isp->asd);
-3
drivers/staging/media/atomisp/pci/atomisp_subdev.h
··· 57 57 /* Filled through atomisp_get_css_frame_info() on queue setup */ 58 58 struct ia_css_frame_info frame_info; 59 59 60 - /* Set from streamoff to disallow queuing further buffers in CSS */ 61 - bool stopping; 62 - 63 60 /* 64 61 * irq_lock is used to protect video buffer state change operations and 65 62 * also to make activeq and capq operations atomic.