PROBLEM: WARN_ON triggers in v4l_querycap with BlackMagic atem console connected via USB

From: Ulrich Drepper
Date: Sun Oct 06 2024 - 06:50:52 EST


I cannot really say when this problem started but I know that perhaps
six months back (or a bit more) I used the console successfully as a
video source device (webcam). This is a ATEM Mini Pro which has a
large number of USB interfaces. What trips up is videodev. Various
userlevel programs (uvcdynctrl, chromium) notice the device being
added and use ioctl(), triggering the problem.

This is with the current Fedora x86_64 kernel (6.10.12) but a) it
happens for a while now and b) as far as I can see this is just the
upstream code, no local changes.

The call trace is:

Call Trace:
<TASK>
? v4l_querycap+0x119/0x140 [videodev]
? __warn.cold+0x8e/0xe8
? v4l_querycap+0x119/0x140 [videodev]
? report_bug+0xff/0x140
? handle_bug+0x3c/0x80
? exc_invalid_op+0x17/0x70
? asm_exc_invalid_op+0x1a/0x20
? v4l_querycap+0x119/0x140 [videodev]
__video_do_ioctl+0x518/0x630 [videodev]
video_usercopy+0x1f1/0x7a0 [videodev]

I traced the offending code to an 'ud2' instruction (makes sense,
undefined) which is reached from this code in
drivers/media/v4l2-core/v4l2-ioctl.c (v4l_querycap):

WARN_ON((cap->capabilities &
(vfd->device_caps | V4L2_CAP_DEVICE_CAPS)) !=
(vfd->device_caps | V4L2_CAP_DEVICE_CAPS));

The asm code is:

747e: 8b 73 54 mov 0x54(%rbx),%esi
7481: 81 ca 00 00 00 80 or $0x80000000,%edx
7487: 48 b9 00 00 20 00 00 movabs $0x20000000200000,%rcx
748e: 00 20 00
7491: 48 0b 4b 54 or 0x54(%rbx),%rcx
7495: 21 d6 and %edx,%esi
7497: 39 f2 cmp %esi,%edx
7499: 75 6e jne 7509 <v4l_querycap+0x119>

where 7509 is the address of the ud2 instruction.

The register dump shows

RDX: 0000000085008003 RSI: 0000000085008002

which, if I'm right, means that cap->capabilities has the extra bit

#define V4L2_CAP_VIDEO_CAPTURE 0x00000001 /* Is a video
capture device */

set.

I don't know what 'ops' points to in the code. It seems to me that
the bit is set in the

ops->vidioc_querycap(file, fh, cap);

call just preceding the test.

Just going by the name of the capability, it seems that the bit should
be set as this device is used as a camera as well so maybe the
information which comes from the call the

struct video_device *vfd = video_devdata(file);

is incomplete? Or the test WARN_ON condition is actually incorrect?


Any idea? I can try to run more tests if someone can tell me how to proceed.

Thanks.