Skip to content

Commit 9dfd0e5

Browse files
committed
usb: gadget: f_uvc: disallow the CPU to enter deeper sleep when streamon
I test on RK3399 IND EVB running Android R system, and set the USB gadget as UVC function via configfs, both the USB 2.0 and 3.0 UVC have preview abnormal problems. If the CPU enter deeper sleep, the USB DMA transfer gets corrupted, and the UVC ISOC transmission lost data. This patch puts in a "pm_qos_latency" requirement which will keep the CPU out of the deeper sleep states when UVC stream on. And allow the CPU to enter deeper sleep state after UVC stream off. Change-Id: I808290f124c6a32da3888819348093a205bfad61 Signed-off-by: William Wu <william.wu@rock-chips.com>
1 parent a55a8e9 commit 9dfd0e5

File tree

6 files changed

+20
-0
lines changed

6 files changed

+20
-0
lines changed

drivers/usb/gadget/function/f_uvc.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1112,6 +1112,7 @@ static struct usb_function_instance *uvc_alloc_inst(void)
11121112

11131113
opts->streaming_interval = 1;
11141114
opts->streaming_maxpacket = 1024;
1115+
opts->pm_qos_latency = 0;
11151116

11161117
ret = uvcg_attach_configfs(opts);
11171118
if (ret < 0) {

drivers/usb/gadget/function/u_uvc.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ struct f_uvc_opts {
8787
*/
8888
struct mutex lock;
8989
int refcnt;
90+
int pm_qos_latency;
9091
};
9192

9293
#endif /* U_UVC_H */

drivers/usb/gadget/function/uvc.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include <linux/spinlock.h>
1919
#include <linux/usb/composite.h>
2020
#include <linux/videodev2.h>
21+
#include <linux/pm_qos.h>
2122

2223
#include <media/v4l2-device.h>
2324
#include <media/v4l2-dev.h>
@@ -119,6 +120,8 @@ struct uvc_device {
119120
enum uvc_state state;
120121
struct usb_function func;
121122
struct uvc_video video;
123+
/* for creating and issuing QoS requests */
124+
struct pm_qos_request pm_qos;
122125

123126
/* Descriptors */
124127
struct {

drivers/usb/gadget/function/uvc_configfs.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
*/
1515

1616
#include <linux/sort.h>
17+
#include <linux/pm_qos.h>
1718

1819
#include "u_uvc.h"
1920
#include "uvc_configfs.h"
@@ -2768,6 +2769,7 @@ UVCG_OPTS_ATTR(streaming_bulk, streaming_bulk, 1);
27682769
UVCG_OPTS_ATTR(streaming_interval, streaming_interval, 16);
27692770
UVCG_OPTS_ATTR(streaming_maxpacket, streaming_maxpacket, 3072);
27702771
UVCG_OPTS_ATTR(streaming_maxburst, streaming_maxburst, 15);
2772+
UVCG_OPTS_ATTR(pm_qos_latency, pm_qos_latency, PM_QOS_LATENCY_ANY);
27712773

27722774
#undef UVCG_OPTS_ATTR
27732775

@@ -2776,6 +2778,7 @@ static struct configfs_attribute *uvc_attrs[] = {
27762778
&f_uvc_opts_attr_streaming_interval,
27772779
&f_uvc_opts_attr_streaming_maxpacket,
27782780
&f_uvc_opts_attr_streaming_maxburst,
2781+
&f_uvc_opts_attr_pm_qos_latency,
27792782
NULL,
27802783
};
27812784

drivers/usb/gadget/function/uvc_video.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,14 @@
1616
#include <linux/usb/ch9.h>
1717
#include <linux/usb/gadget.h>
1818
#include <linux/usb/video.h>
19+
#include <linux/pm_qos.h>
1920

2021
#include <media/v4l2-dev.h>
2122

2223
#include "uvc.h"
2324
#include "uvc_queue.h"
2425
#include "uvc_video.h"
26+
#include "u_uvc.h"
2527

2628
/* --------------------------------------------------------------------------
2729
* Video codecs
@@ -365,23 +367,32 @@ int uvcg_video_enable(struct uvc_video *video, int enable)
365367
{
366368
unsigned int i;
367369
int ret;
370+
struct uvc_device *uvc;
371+
struct f_uvc_opts *opts;
368372

369373
if (video->ep == NULL) {
370374
uvcg_info(&video->uvc->func,
371375
"Video enable failed, device is uninitialized.\n");
372376
return -ENODEV;
373377
}
374378

379+
uvc = container_of(video, struct uvc_device, video);
380+
opts = fi_to_f_uvc_opts(uvc->func.fi);
381+
375382
if (!enable) {
376383
for (i = 0; i < UVC_NUM_REQUESTS; ++i)
377384
if (video->req[i])
378385
usb_ep_dequeue(video->ep, video->req[i]);
379386

380387
uvc_video_free_requests(video);
381388
uvcg_queue_enable(&video->queue, 0);
389+
if (pm_qos_request_active(&uvc->pm_qos))
390+
pm_qos_remove_request(&uvc->pm_qos);
382391
return 0;
383392
}
384393

394+
pm_qos_add_request(&uvc->pm_qos, PM_QOS_CPU_DMA_LATENCY,
395+
opts->pm_qos_latency);
385396
if ((ret = uvcg_queue_enable(&video->queue, 1)) < 0)
386397
return ret;
387398

drivers/usb/gadget/legacy/webcam.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,7 @@ webcam_bind(struct usb_composite_dev *cdev)
386386
uvc_opts->fs_streaming = uvc_fs_streaming_cls;
387387
uvc_opts->hs_streaming = uvc_hs_streaming_cls;
388388
uvc_opts->ss_streaming = uvc_ss_streaming_cls;
389+
uvc_opts->pm_qos_latency = 0;
389390

390391
/* Allocate string descriptor numbers ... note that string contents
391392
* can be overridden by the composite_dev glue.

0 commit comments

Comments
 (0)