diff options
| author | Hans Verkuil <hverkuil+cisco@kernel.org> | 2026-06-16 14:42:16 +0200 |
|---|---|---|
| committer | Mauro Carvalho Chehab <mchehab+huawei@kernel.org> | 2026-07-14 08:01:52 +0200 |
| commit | 67f87b104f4ef3108607ac9d8fa2075b13ed314d (patch) | |
| tree | 3251bbe30ac926ec300c7b730b9b67460e1f7c19 | |
| parent | c132b07f7e5853c0df35a9b94b8e204cdc6afdef (diff) | |
| download | linux-next-67f87b104f4ef3108607ac9d8fa2075b13ed314d.tar.gz linux-next-67f87b104f4ef3108607ac9d8fa2075b13ed314d.zip | |
media: em28xx: requeue buffers if start_streaming fails
If start_streaming fails, then all queued buffers must be
returned to vb2 in state QUEUED.
Otherwise it will trigger a WARN_ON.
Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
Tested-by: Hans Verkuil <hverkuil+cisco@kernel.org>
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
| -rw-r--r-- | drivers/media/usb/em28xx/em28xx-video.c | 18 |
1 files changed, 16 insertions, 2 deletions
diff --git a/drivers/media/usb/em28xx/em28xx-video.c b/drivers/media/usb/em28xx/em28xx-video.c index e4554d015944..c418add65bb5 100644 --- a/drivers/media/usb/em28xx/em28xx-video.c +++ b/drivers/media/usb/em28xx/em28xx-video.c @@ -1213,6 +1213,9 @@ int em28xx_start_analog_streaming(struct vb2_queue *vq, unsigned int count) { struct em28xx *dev = vb2_get_drv_priv(vq); struct em28xx_v4l2 *v4l2 = dev->v4l2; + struct em28xx_dmaqueue *dmaq = vq->type == V4L2_BUF_TYPE_VBI_CAPTURE ? + &dev->vbiq : &dev->vidq; + unsigned long flags = 0; struct v4l2_frequency f; struct v4l2_fh *owner; int rc = 0; @@ -1227,7 +1230,7 @@ int em28xx_start_analog_streaming(struct vb2_queue *vq, unsigned int count) */ rc = res_get(dev, vq->type); if (rc) - return rc; + goto exit; if (v4l2->streaming_users == 0) { /* First active streaming user, so allocate all the URBs */ @@ -1250,7 +1253,7 @@ int em28xx_start_analog_streaming(struct vb2_queue *vq, unsigned int count) em28xx_urb_data_copy); if (rc < 0) { res_free(dev, vq->type); - return rc; + goto exit; } /* @@ -1275,7 +1278,18 @@ int em28xx_start_analog_streaming(struct vb2_queue *vq, unsigned int count) } v4l2->streaming_users++; + return 0; +exit: + spin_lock_irqsave(&dev->slock, flags); + while (!list_empty(&dmaq->active)) { + struct em28xx_buffer *buf; + + buf = list_entry(dmaq->active.next, struct em28xx_buffer, list); + list_del(&buf->list); + vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_QUEUED); + } + spin_unlock_irqrestore(&dev->slock, flags); return rc; } |
