usb: gadget: uvc: decrease the interrupt load to a quarter
authorMichael Grzeschik <m.grzeschik@pengutronix.de>
Mon, 28 Jun 2021 15:53:11 +0000 (17:53 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 27 Jul 2021 13:59:19 +0000 (15:59 +0200)
With usb3 we handle many more requests. Decrease the interrupt load by
only enabling the interrupt every quarter of the allocated requests.

Reviewed-by: Paul Elder <paul.elder@ideasonboard.com>
Signed-off-by: Michael Grzeschik <m.grzeschik@pengutronix.de>
--
v1 -> v2: - edited patch description
  - removed extra parantheses
  - added a comment for the logic
  - using unsigned int instead of int
  - reinitializing req_int_count in uvcg_video_enable
v2 -> v3: -
Link: https://lore.kernel.org/r/20210628155311.16762-6-m.grzeschik@pengutronix.de
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/usb/gadget/function/uvc.h
drivers/usb/gadget/function/uvc_video.c

index 36b78f8..255a61b 100644 (file)
@@ -101,6 +101,8 @@ struct uvc_video {
        struct list_head req_free;
        spinlock_t req_lock;
 
+       unsigned int req_int_count;
+
        void (*encode) (struct usb_request *req, struct uvc_video *video,
                        struct uvc_buffer *buf);
 
index 2cefb8b..b4a763e 100644 (file)
@@ -360,6 +360,19 @@ static void uvcg_video_pump(struct work_struct *work)
 
                video->encode(req, video, buf);
 
+               /* With usb3 we have more requests. This will decrease the
+                * interrupt load to a quarter but also catches the corner
+                * cases, which needs to be handled */
+               if (list_empty(&video->req_free) ||
+                   buf->state == UVC_BUF_STATE_DONE ||
+                   !(video->req_int_count %
+                      DIV_ROUND_UP(video->uvc_num_requests, 4))) {
+                       video->req_int_count = 0;
+                       req->no_interrupt = 0;
+               } else {
+                       req->no_interrupt = 1;
+               }
+
                /* Queue the USB request */
                ret = uvcg_video_ep_queue(video, req);
                spin_unlock_irqrestore(&queue->irqlock, flags);
@@ -368,6 +381,7 @@ static void uvcg_video_pump(struct work_struct *work)
                        uvcg_queue_cancel(queue, 0);
                        break;
                }
+               video->req_int_count++;
        }
 
        spin_lock_irqsave(&video->req_lock, flags);
@@ -416,6 +430,8 @@ int uvcg_video_enable(struct uvc_video *video, int enable)
                video->encode = video->queue.use_sg ?
                        uvc_video_encode_isoc_sg : uvc_video_encode_isoc;
 
+       video->req_int_count = 0;
+
        schedule_work(&video->pump);
 
        return ret;