From: chenchangcheng chenchangcheng@kylinos.cn
[ Upstream commit 9764401bf6f8a20eb11c2e78470f20fee91a9ea7 ]
Some broken device return wrong dwMaxPayloadTransferSize fields as follows:
[ 218.632537] uvcvideo: Device requested 2752512 B/frame bandwidth. [ 218.632598] uvcvideo: No fast enough alt setting for requested bandwidth.
When dwMaxPayloadTransferSize is greater than maxpsize, it will prevent the camera from starting. So use the bandwidth of maxpsize.
Signed-off-by: chenchangcheng chenchangcheng@kylinos.cn Reviewed-by: Ricardo Ribalda ribalda@chromium.org Reviewed-by: Laurent Pinchart laurent.pinchart@ideasonboard.com Link: https://lore.kernel.org/r/20250510061803.811433-1-ccc194101@163.com Signed-off-by: Laurent Pinchart laurent.pinchart@ideasonboard.com Signed-off-by: Hans Verkuil hverkuil@xs4all.nl Signed-off-by: Sasha Levin sashal@kernel.org ---
LLM Generated explanations, may be completely bogus:
Based on my analysis of the commit and the surrounding code context, here is my determination:
**YES**
This commit should be backported to stable kernel trees for the following reasons:
1. **Fixes a real user-impacting bug**: The commit fixes a bandwidth issue that prevents certain USB cameras (specifically Alcor cameras) from starting. As shown in the commit message, devices can request unrealistic bandwidth values (2752512 B/frame), which causes the "No fast enough alt setting for requested bandwidth" error at line 2080 in uvc_video.c, preventing the camera from functioning.
2. **Small and contained fix**: The change is minimal - it adds only 8 lines of code that perform a simple bounds check. When `dwMaxPayloadTransferSize` exceeds `stream->maxpsize`, it caps the value to the maximum packet size. This is a defensive programming approach that doesn't change any core functionality.
3. **Low regression risk**: The fix is conservative and only triggers when: - The interface has multiple alternate settings (`stream->intf->num_altsetting > 1`) - The requested payload size exceeds the endpoint's maximum packet size - It simply clamps the value rather than rejecting it, allowing the device to work with reduced bandwidth
4. **Follows established pattern**: The code already has similar workarounds for broken devices (e.g., the Chicony device fix at lines 226-227 that masks invalid bandwidth values). This fix follows the same philosophy of working around non-compliant hardware.
5. **Hardware compatibility issue**: This fixes compatibility with specific hardware (Alcor cameras) that would otherwise be completely non-functional. Hardware compatibility fixes are typically good candidates for stable backports as they enable users to use their existing hardware.
6. **Clear problem and solution**: The issue is well-defined (devices returning wrong `dwMaxPayloadTransferSize`), and the solution is straightforward (cap to the actual maximum packet size). The warning message also provides visibility into when this workaround is applied.
7. **No architectural changes**: The fix doesn't introduce new features or change the driver architecture. It's purely a workaround for non- compliant hardware, similar to other quirks already present in the UVC driver.
The commit meets the stable kernel criteria of fixing an important bug (camera not working) with minimal risk and without introducing new features or architectural changes.
drivers/media/usb/uvc/uvc_video.c | 9 +++++++++ 1 file changed, 9 insertions(+)
diff --git a/drivers/media/usb/uvc/uvc_video.c b/drivers/media/usb/uvc/uvc_video.c index e3567aeb0007..11769a1832d2 100644 --- a/drivers/media/usb/uvc/uvc_video.c +++ b/drivers/media/usb/uvc/uvc_video.c @@ -262,6 +262,15 @@ static void uvc_fixup_video_ctrl(struct uvc_streaming *stream,
ctrl->dwMaxPayloadTransferSize = bandwidth; } + + if (stream->intf->num_altsetting > 1 && + ctrl->dwMaxPayloadTransferSize > stream->maxpsize) { + dev_warn_ratelimited(&stream->intf->dev, + "UVC non compliance: the max payload transmission size (%u) exceeds the size of the ep max packet (%u). Using the max size.\n", + ctrl->dwMaxPayloadTransferSize, + stream->maxpsize); + ctrl->dwMaxPayloadTransferSize = stream->maxpsize; + } }
static size_t uvc_video_ctrl_size(struct uvc_streaming *stream)