summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRicardo Ribalda <ribalda@chromium.org>2026-05-13 14:49:23 +0300
committerHans Verkuil <hverkuil+cisco@kernel.org>2026-05-21 22:14:08 +0300
commitba649fff36c1fe68489a86d00285224907edd436 (patch)
treeb734e4ac051b7312adf1aa90dc5dc783ceaf2641
parent1719d78f832dda8dd3f09a867ba74e05d6f11308 (diff)
downloadlinux-ba649fff36c1fe68489a86d00285224907edd436.tar.xz
media: uvcvideo: Do not add clock samples with small sof delta
Some UVC 1.1 cameras running in fast isochronous mode tend to spam the USB host with a lot of empty packets. These packets contain clock information and are added to the clock buffer but do not add any accuracy to the calculation. In fact, it is quite the opposite, in our calculations, only the first and the last timestamp is used, and we only have 32 slots. Ignore the samples that will produce less than MIN_HW_TIMESTAMP_DIFF data. Fixes: 141270bd95d4 ("media: uvcvideo: Refactor clock circular buffer") Cc: stable@vger.kernel.org Tested-by: Yunke Cao <yunkec@google.com> Reviewed-by: Hans de Goede <johannes.goede@oss.qualcomm.com> Signed-off-by: Ricardo Ribalda <ribalda@chromium.org> Link: https://patch.msgid.link/20260513-uvc-hwtimestamp-v3-4-7a64838b0b02@chromium.org Signed-off-by: Hans de Goede <johannes.goede@oss.qualcomm.com> Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
-rw-r--r--drivers/media/usb/uvc/uvc_video.c14
1 files changed, 12 insertions, 2 deletions
diff --git a/drivers/media/usb/uvc/uvc_video.c b/drivers/media/usb/uvc/uvc_video.c
index d2e61be35bf6..09d6baf87ec5 100644
--- a/drivers/media/usb/uvc/uvc_video.c
+++ b/drivers/media/usb/uvc/uvc_video.c
@@ -544,6 +544,15 @@ static void uvc_video_clock_add_sample(struct uvc_clock *clock,
spin_unlock_irqrestore(&clock->lock, flags);
}
+static inline u16 sof_diff(u16 a, u16 b)
+{
+ /*
+ * Because the result is modulo 2048 (via & 2047), we do not need a
+ * special case for a < b.
+ */
+ return (a - b) & 2047;
+}
+
static void
uvc_video_clock_decode(struct uvc_streaming *stream, struct uvc_buffer *buf,
const u8 *data, int len)
@@ -664,12 +673,13 @@ uvc_video_clock_decode(struct uvc_streaming *stream, struct uvc_buffer *buf,
sample.dev_sof = (sample.dev_sof + stream->clock.sof_offset) & 2047;
/*
- * To limit the amount of data, drop SCRs with an SOF identical to the
+ * To limit the amount of data, drop SCRs with an SOF similar to the
* previous one. This filtering is also needed to support UVC 1.5, where
* all the data packets of the same frame contains the same SOF. In that
* case only the first one will match the host_sof.
*/
- if (sample.dev_sof == stream->clock.last_sof)
+ if (sof_diff(sample.dev_sof, stream->clock.last_sof) <=
+ (UVC_MIN_HW_TIMESTAMP_DIFF / stream->clock.size))
return;
uvc_video_clock_add_sample(&stream->clock, &sample);