[PATCH v7] media: uvcvideo: Fix bandwidth issue

chenchangcheng posted 1 patch 8 months, 1 week ago
drivers/media/usb/uvc/uvc_video.c | 9 +++++++++
1 file changed, 9 insertions(+)
[PATCH v7] media: uvcvideo: Fix bandwidth issue
Posted by chenchangcheng 8 months, 1 week ago
From: chenchangcheng <chenchangcheng@kylinos.cn>

Some broken device return wrong dwMaxPayloadTransferSize fields
as follows:
    [  218.632537] [pid:20427,cpu6,guvcview,8]uvcvideo: Device requested 2752512 B/frame bandwidth.
    [  218.632598] [pid:20427,cpu6,guvcview,9]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>
---
 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..9b7e34e38b61 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_ratelimit(&stream->intf->dev,
+				   "the max payload transmission size (%d) exceededs the size of the ep max packet (%d). Using the max size.\n",
+				   ctrl->dwMaxPayloadTransferSize,
+				   stream->maxpsize);
+		ctrl->dwMaxPayloadTransferSize = stream->maxpsize;
+	}
 }
 
 static size_t uvc_video_ctrl_size(struct uvc_streaming *stream)

base-commit: 8ffd015db85fea3e15a77027fda6c02ced4d2444
-- 
2.25.1
Re: [PATCH v7] media: uvcvideo: Fix bandwidth issue
Posted by kernel test robot 7 months, 2 weeks ago
Hi chenchangcheng,

kernel test robot noticed the following build errors:

[auto build test ERROR on 8ffd015db85fea3e15a77027fda6c02ced4d2444]

url:    https://github.com/intel-lab-lkp/linux/commits/chenchangcheng/media-uvcvideo-Fix-bandwidth-issue/20250416-140638
base:   8ffd015db85fea3e15a77027fda6c02ced4d2444
patch link:    https://lore.kernel.org/r/20250416031838.254061-1-ccc194101%40163.com
patch subject: [PATCH v7] media: uvcvideo: Fix bandwidth issue
config: i386-randconfig-012-20250424 (https://download.01.org/0day-ci/archive/20250507/202505072016.LlOxF8BG-lkp@intel.com/config)
compiler: gcc-11 (Debian 11.3.0-12) 11.3.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250507/202505072016.LlOxF8BG-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202505072016.LlOxF8BG-lkp@intel.com/

All errors (new ones prefixed by >>):

   drivers/media/usb/uvc/uvc_video.c: In function 'uvc_fixup_video_ctrl':
>> drivers/media/usb/uvc/uvc_video.c:268:17: error: implicit declaration of function 'dev_warn_ratelimit'; did you mean 'dev_warn_ratelimited'? [-Werror=implicit-function-declaration]
     268 |                 dev_warn_ratelimit(&stream->intf->dev,
         |                 ^~~~~~~~~~~~~~~~~~
         |                 dev_warn_ratelimited
   cc1: some warnings being treated as errors


vim +268 drivers/media/usb/uvc/uvc_video.c

   162	
   163	static void uvc_fixup_video_ctrl(struct uvc_streaming *stream,
   164		struct uvc_streaming_control *ctrl)
   165	{
   166		const struct uvc_format *format = NULL;
   167		const struct uvc_frame *frame = NULL;
   168		unsigned int i;
   169	
   170		/*
   171		 * The response of the Elgato Cam Link 4K is incorrect: The second byte
   172		 * contains bFormatIndex (instead of being the second byte of bmHint).
   173		 * The first byte is always zero. The third byte is always 1.
   174		 *
   175		 * The UVC 1.5 class specification defines the first five bits in the
   176		 * bmHint bitfield. The remaining bits are reserved and should be zero.
   177		 * Therefore a valid bmHint will be less than 32.
   178		 *
   179		 * Latest Elgato Cam Link 4K firmware as of 2021-03-23 needs this fix.
   180		 * MCU: 20.02.19, FPGA: 67
   181		 */
   182		if (usb_match_one_id(stream->dev->intf, &elgato_cam_link_4k) &&
   183		    ctrl->bmHint > 255) {
   184			u8 corrected_format_index = ctrl->bmHint >> 8;
   185	
   186			uvc_dbg(stream->dev, VIDEO,
   187				"Correct USB video probe response from {bmHint: 0x%04x, bFormatIndex: %u} to {bmHint: 0x%04x, bFormatIndex: %u}\n",
   188				ctrl->bmHint, ctrl->bFormatIndex,
   189				1, corrected_format_index);
   190			ctrl->bmHint = 1;
   191			ctrl->bFormatIndex = corrected_format_index;
   192		}
   193	
   194		for (i = 0; i < stream->nformats; ++i) {
   195			if (stream->formats[i].index == ctrl->bFormatIndex) {
   196				format = &stream->formats[i];
   197				break;
   198			}
   199		}
   200	
   201		if (format == NULL)
   202			return;
   203	
   204		for (i = 0; i < format->nframes; ++i) {
   205			if (format->frames[i].bFrameIndex == ctrl->bFrameIndex) {
   206				frame = &format->frames[i];
   207				break;
   208			}
   209		}
   210	
   211		if (frame == NULL)
   212			return;
   213	
   214		if (!(format->flags & UVC_FMT_FLAG_COMPRESSED) ||
   215		     (ctrl->dwMaxVideoFrameSize == 0 &&
   216		      stream->dev->uvc_version < 0x0110))
   217			ctrl->dwMaxVideoFrameSize =
   218				frame->dwMaxVideoFrameBufferSize;
   219	
   220		/*
   221		 * The "TOSHIBA Web Camera - 5M" Chicony device (04f2:b50b) seems to
   222		 * compute the bandwidth on 16 bits and erroneously sign-extend it to
   223		 * 32 bits, resulting in a huge bandwidth value. Detect and fix that
   224		 * condition by setting the 16 MSBs to 0 when they're all equal to 1.
   225		 */
   226		if ((ctrl->dwMaxPayloadTransferSize & 0xffff0000) == 0xffff0000)
   227			ctrl->dwMaxPayloadTransferSize &= ~0xffff0000;
   228	
   229		if (!(format->flags & UVC_FMT_FLAG_COMPRESSED) &&
   230		    stream->dev->quirks & UVC_QUIRK_FIX_BANDWIDTH &&
   231		    stream->intf->num_altsetting > 1) {
   232			u32 interval;
   233			u32 bandwidth;
   234	
   235			interval = (ctrl->dwFrameInterval > 100000)
   236				 ? ctrl->dwFrameInterval
   237				 : frame->dwFrameInterval[0];
   238	
   239			/*
   240			 * Compute a bandwidth estimation by multiplying the frame
   241			 * size by the number of video frames per second, divide the
   242			 * result by the number of USB frames (or micro-frames for
   243			 * high- and super-speed devices) per second and add the UVC
   244			 * header size (assumed to be 12 bytes long).
   245			 */
   246			bandwidth = frame->wWidth * frame->wHeight / 8 * format->bpp;
   247			bandwidth *= 10000000 / interval + 1;
   248			bandwidth /= 1000;
   249			if (stream->dev->udev->speed >= USB_SPEED_HIGH)
   250				bandwidth /= 8;
   251			bandwidth += 12;
   252	
   253			/*
   254			 * The bandwidth estimate is too low for many cameras. Don't use
   255			 * maximum packet sizes lower than 1024 bytes to try and work
   256			 * around the problem. According to measurements done on two
   257			 * different camera models, the value is high enough to get most
   258			 * resolutions working while not preventing two simultaneous
   259			 * VGA streams at 15 fps.
   260			 */
   261			bandwidth = max_t(u32, bandwidth, 1024);
   262	
   263			ctrl->dwMaxPayloadTransferSize = bandwidth;
   264		}
   265	
   266		if (stream->intf->num_altsetting > 1 &&
   267		    ctrl->dwMaxPayloadTransferSize > stream->maxpsize) {
 > 268			dev_warn_ratelimit(&stream->intf->dev,
   269					   "the max payload transmission size (%d) exceededs the size of the ep max packet (%d). Using the max size.\n",
   270					   ctrl->dwMaxPayloadTransferSize,
   271					   stream->maxpsize);
   272			ctrl->dwMaxPayloadTransferSize = stream->maxpsize;
   273		}
   274	}
   275	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki