]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
usb: gadget: uvc: set req_length based on payload by nreqs instead of req_size
authorMichael Grzeschik <m.grzeschik@pengutronix.de>
Wed, 16 Oct 2024 13:58:11 +0000 (15:58 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 17 Oct 2024 06:42:22 +0000 (08:42 +0200)
Compressed formats generate content depending amount of data that is set
in the vb2 buffer by the payload_size. When streaming those formats it
is better to scatter that smaller data over all requests. This patch is
doing that by introducing the calculated req_payload_size which is
updated by each frame. It the uses this amount of data to fill the
isoc requests instead of the video->req_size.

For uncompressed formats it will not make a difference since the payload
size will be equal to the imagesize. Therefore the code will have no
effecta as req_payload_size will be equal to req_size.

Signed-off-by: Michael Grzeschik <m.grzeschik@pengutronix.de>
Link: https://lore.kernel.org/r/20240403-uvc_request_length_by_interval-v7-6-e224bb1035f0@pengutronix.de
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/usb/gadget/function/uvc.h
drivers/usb/gadget/function/uvc_queue.c
drivers/usb/gadget/function/uvc_queue.h
drivers/usb/gadget/function/uvc_video.c

index 099038f1088ef66bf3e17ce04820022349de3304..bedb4ef42864f15952fdecf5ca7df619dd03b202 100644 (file)
@@ -110,6 +110,8 @@ struct uvc_video {
 
        unsigned int uvc_num_requests;
 
+       unsigned int reqs_per_frame;
+
        /* Requests */
        bool is_enabled; /* tracks whether video stream is enabled */
        unsigned int req_size;
index 731e3b9d21accc6d9379630f0764c7090e656c48..6757a4e25a74348725eac0ccd3aa50217babe3ab 100644 (file)
@@ -58,6 +58,7 @@ static int uvc_queue_setup(struct vb2_queue *vq,
 static int uvc_buffer_prepare(struct vb2_buffer *vb)
 {
        struct uvc_video_queue *queue = vb2_get_drv_priv(vb->vb2_queue);
+       struct uvc_video *video = container_of(queue, struct uvc_video, queue);
        struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
        struct uvc_buffer *buf = container_of(vbuf, struct uvc_buffer, buf);
 
@@ -78,10 +79,15 @@ static int uvc_buffer_prepare(struct vb2_buffer *vb)
                buf->mem = vb2_plane_vaddr(vb, 0);
        }
        buf->length = vb2_plane_size(vb, 0);
-       if (vb->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
+       if (vb->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
                buf->bytesused = 0;
-       else
+       } else {
                buf->bytesused = vb2_get_plane_payload(vb, 0);
+               buf->req_payload_size =
+                         DIV_ROUND_UP(buf->bytesused +
+                                      (video->reqs_per_frame * UVCG_REQUEST_HEADER_LEN),
+                                      video->reqs_per_frame);
+       }
 
        return 0;
 }
index 41f87b917f6bc1a0e60f6a0afccbc9b1e59700db..b54becc570a38e23d915b6e7c08c23ef7d44f99f 100644 (file)
@@ -39,6 +39,8 @@ struct uvc_buffer {
        unsigned int offset;
        unsigned int length;
        unsigned int bytesused;
+       /* req_payload_size: only used with isoc */
+       unsigned int req_payload_size;
 };
 
 #define UVC_QUEUE_DISCONNECTED         (1 << 0)
index ecb32a3e0376054a8c9bc0ba70e5cc5781dc6b2c..677eaf5b7e4d0d166c0134282671f75349c4930a 100644 (file)
@@ -136,7 +136,7 @@ uvc_video_encode_isoc_sg(struct usb_request *req, struct uvc_video *video,
        unsigned int pending = buf->bytesused - video->queue.buf_used;
        struct uvc_request *ureq = req->context;
        struct scatterlist *sg, *iter;
-       unsigned int len = video->req_size;
+       unsigned int len = buf->req_payload_size;
        unsigned int sg_left, part = 0;
        unsigned int i;
        int header_len;
@@ -146,15 +146,15 @@ uvc_video_encode_isoc_sg(struct usb_request *req, struct uvc_video *video,
 
        /* Init the header. */
        header_len = uvc_video_encode_header(video, buf, ureq->header,
-                                     video->req_size);
+                                            buf->req_payload_size);
        sg_set_buf(sg, ureq->header, header_len);
        len -= header_len;
 
        if (pending <= len)
                len = pending;
 
-       req->length = (len == pending) ?
-               len + header_len : video->req_size;
+       req->length = (len == pending) ? len + header_len :
+               buf->req_payload_size;
 
        /* Init the pending sgs with payload */
        sg = sg_next(sg);
@@ -202,7 +202,7 @@ uvc_video_encode_isoc(struct usb_request *req, struct uvc_video *video,
 {
        void *mem = req->buf;
        struct uvc_request *ureq = req->context;
-       int len = video->req_size;
+       int len = buf->req_payload_size;
        int ret;
 
        /* Add the header. */
@@ -214,7 +214,7 @@ uvc_video_encode_isoc(struct usb_request *req, struct uvc_video *video,
        ret = uvc_video_encode_data(video, buf, mem, len);
        len -= ret;
 
-       req->length = video->req_size - len;
+       req->length = buf->req_payload_size - len;
 
        if (buf->bytesused == video->queue.buf_used ||
                        video->queue.flags & UVC_QUEUE_DROP_INCOMPLETE) {
@@ -504,7 +504,7 @@ uvc_video_prep_requests(struct uvc_video *video)
 
        if (!usb_endpoint_xfer_isoc(video->ep->desc)) {
                video->req_size = max_req_size;
-               video->uvc_num_requests =
+               video->reqs_per_frame = video->uvc_num_requests =
                        DIV_ROUND_UP(video->imagesize, max_req_size);
 
                return;
@@ -535,6 +535,7 @@ uvc_video_prep_requests(struct uvc_video *video)
         * able to fully encode one frame.
         */
        video->uvc_num_requests = nreq + UVCG_REQ_MAX_ZERO_COUNT;
+       video->reqs_per_frame = nreq;
 }
 
 static int