From 2e75973832abe0c5230fd40ca886d03dc975d1d3 Mon Sep 17 00:00:00 2001 From: Nishad Kamdar Date: Sat, 28 Mar 2020 16:41:15 +0530 Subject: USB: gadget: Use the correct style for SPDX License Identifier This patch corrects the SPDX License Identifier style in header files related to USB peripheral controller drivers. For C header files Documentation/process/license-rules.rst mandates C-like comments (opposed to C source files where C++ style should be used). Changes made by using a script provided by Joe Perches here: https://lkml.org/lkml/2019/2/7/46. Suggested-by: Joe Perches Signed-off-by: Nishad Kamdar Signed-off-by: Felipe Balbi --- drivers/usb/gadget/function/f_uvc.h | 2 +- drivers/usb/gadget/function/rndis.h | 2 +- drivers/usb/gadget/function/u_audio.h | 2 +- drivers/usb/gadget/function/u_ecm.h | 2 +- drivers/usb/gadget/function/u_eem.h | 2 +- drivers/usb/gadget/function/u_ether.h | 2 +- drivers/usb/gadget/function/u_ether_configfs.h | 2 +- drivers/usb/gadget/function/u_fs.h | 2 +- drivers/usb/gadget/function/u_gether.h | 2 +- drivers/usb/gadget/function/u_hid.h | 2 +- drivers/usb/gadget/function/u_midi.h | 2 +- drivers/usb/gadget/function/u_ncm.h | 2 +- drivers/usb/gadget/function/u_phonet.h | 2 +- drivers/usb/gadget/function/u_printer.h | 2 +- drivers/usb/gadget/function/u_rndis.h | 2 +- drivers/usb/gadget/function/u_serial.h | 2 +- drivers/usb/gadget/function/u_tcm.h | 2 +- drivers/usb/gadget/function/u_uac1.h | 2 +- drivers/usb/gadget/function/u_uac1_legacy.h | 2 +- drivers/usb/gadget/function/u_uac2.h | 2 +- drivers/usb/gadget/function/u_uvc.h | 2 +- drivers/usb/gadget/function/uvc.h | 2 +- drivers/usb/gadget/function/uvc_configfs.h | 2 +- drivers/usb/gadget/function/uvc_v4l2.h | 2 +- drivers/usb/gadget/function/uvc_video.h | 2 +- 25 files changed, 25 insertions(+), 25 deletions(-) (limited to 'drivers/usb/gadget/function') diff --git a/drivers/usb/gadget/function/f_uvc.h b/drivers/usb/gadget/function/f_uvc.h index a81a17765558..1db972d4beeb 100644 --- a/drivers/usb/gadget/function/f_uvc.h +++ b/drivers/usb/gadget/function/f_uvc.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * f_uvc.h -- USB Video Class Gadget driver * diff --git a/drivers/usb/gadget/function/rndis.h b/drivers/usb/gadget/function/rndis.h index c7e3a70ce6c1..f6167f7fea82 100644 --- a/drivers/usb/gadget/function/rndis.h +++ b/drivers/usb/gadget/function/rndis.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /* * RNDIS Definitions for Remote NDIS * diff --git a/drivers/usb/gadget/function/u_audio.h b/drivers/usb/gadget/function/u_audio.h index 81d3d4ed6dfb..5ea6b86f1fda 100644 --- a/drivers/usb/gadget/function/u_audio.h +++ b/drivers/usb/gadget/function/u_audio.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * u_audio.h -- interface to USB gadget "ALSA sound card" utilities * diff --git a/drivers/usb/gadget/function/u_ecm.h b/drivers/usb/gadget/function/u_ecm.h index 098ece573a5e..77cfb89932be 100644 --- a/drivers/usb/gadget/function/u_ecm.h +++ b/drivers/usb/gadget/function/u_ecm.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /* * u_ecm.h * diff --git a/drivers/usb/gadget/function/u_eem.h b/drivers/usb/gadget/function/u_eem.h index 921386a375cf..3bd85dfcd71c 100644 --- a/drivers/usb/gadget/function/u_eem.h +++ b/drivers/usb/gadget/function/u_eem.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /* * u_eem.h * diff --git a/drivers/usb/gadget/function/u_ether.h b/drivers/usb/gadget/function/u_ether.h index 332307d54292..10dd640684e2 100644 --- a/drivers/usb/gadget/function/u_ether.h +++ b/drivers/usb/gadget/function/u_ether.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * u_ether.h -- interface to USB gadget "ethernet link" utilities * diff --git a/drivers/usb/gadget/function/u_ether_configfs.h b/drivers/usb/gadget/function/u_ether_configfs.h index d8b92485b727..bd92b5703013 100644 --- a/drivers/usb/gadget/function/u_ether_configfs.h +++ b/drivers/usb/gadget/function/u_ether_configfs.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /* * u_ether_configfs.h * diff --git a/drivers/usb/gadget/function/u_fs.h b/drivers/usb/gadget/function/u_fs.h index f9b0cf67360d..f102ec23f3af 100644 --- a/drivers/usb/gadget/function/u_fs.h +++ b/drivers/usb/gadget/function/u_fs.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /* * u_fs.h * diff --git a/drivers/usb/gadget/function/u_gether.h b/drivers/usb/gadget/function/u_gether.h index ce4f07626f96..2f7a373ed449 100644 --- a/drivers/usb/gadget/function/u_gether.h +++ b/drivers/usb/gadget/function/u_gether.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /* * u_gether.h * diff --git a/drivers/usb/gadget/function/u_hid.h b/drivers/usb/gadget/function/u_hid.h index 1594bfa312eb..84e6da302499 100644 --- a/drivers/usb/gadget/function/u_hid.h +++ b/drivers/usb/gadget/function/u_hid.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /* * u_hid.h * diff --git a/drivers/usb/gadget/function/u_midi.h b/drivers/usb/gadget/function/u_midi.h index 29bf006c0a13..f6e14af7f566 100644 --- a/drivers/usb/gadget/function/u_midi.h +++ b/drivers/usb/gadget/function/u_midi.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /* * u_midi.h * diff --git a/drivers/usb/gadget/function/u_ncm.h b/drivers/usb/gadget/function/u_ncm.h index 70da3201a1d0..5408854d8407 100644 --- a/drivers/usb/gadget/function/u_ncm.h +++ b/drivers/usb/gadget/function/u_ncm.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /* * u_ncm.h * diff --git a/drivers/usb/gadget/function/u_phonet.h b/drivers/usb/gadget/function/u_phonet.h index 12fb613f85d1..c53233b37192 100644 --- a/drivers/usb/gadget/function/u_phonet.h +++ b/drivers/usb/gadget/function/u_phonet.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * u_phonet.h - interface to Phonet * diff --git a/drivers/usb/gadget/function/u_printer.h b/drivers/usb/gadget/function/u_printer.h index 78797764f478..318205fb778e 100644 --- a/drivers/usb/gadget/function/u_printer.h +++ b/drivers/usb/gadget/function/u_printer.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /* * u_printer.h * diff --git a/drivers/usb/gadget/function/u_rndis.h b/drivers/usb/gadget/function/u_rndis.h index 1e148b76f339..a8c409b2f52f 100644 --- a/drivers/usb/gadget/function/u_rndis.h +++ b/drivers/usb/gadget/function/u_rndis.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /* * u_rndis.h * diff --git a/drivers/usb/gadget/function/u_serial.h b/drivers/usb/gadget/function/u_serial.h index e5b08ab8cf7a..dbe75b289be6 100644 --- a/drivers/usb/gadget/function/u_serial.h +++ b/drivers/usb/gadget/function/u_serial.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * u_serial.h - interface to USB gadget "serial port"/TTY utilities * diff --git a/drivers/usb/gadget/function/u_tcm.h b/drivers/usb/gadget/function/u_tcm.h index 3f7ccecb0f9b..2cd15d9a1c0d 100644 --- a/drivers/usb/gadget/function/u_tcm.h +++ b/drivers/usb/gadget/function/u_tcm.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /* * u_tcm.h * diff --git a/drivers/usb/gadget/function/u_uac1.h b/drivers/usb/gadget/function/u_uac1.h index 6f1a9d73defe..39c0e29e1b46 100644 --- a/drivers/usb/gadget/function/u_uac1.h +++ b/drivers/usb/gadget/function/u_uac1.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /* * u_uac1.h - Utility definitions for UAC1 function * diff --git a/drivers/usb/gadget/function/u_uac1_legacy.h b/drivers/usb/gadget/function/u_uac1_legacy.h index 5c1bdf46fe32..b5df9bcbbeba 100644 --- a/drivers/usb/gadget/function/u_uac1_legacy.h +++ b/drivers/usb/gadget/function/u_uac1_legacy.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * u_uac1.h -- interface to USB gadget "ALSA AUDIO" utilities * diff --git a/drivers/usb/gadget/function/u_uac2.h b/drivers/usb/gadget/function/u_uac2.h index 82048791eb6e..b5035711172d 100644 --- a/drivers/usb/gadget/function/u_uac2.h +++ b/drivers/usb/gadget/function/u_uac2.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /* * u_uac2.h * diff --git a/drivers/usb/gadget/function/u_uvc.h b/drivers/usb/gadget/function/u_uvc.h index 16da49a2fcf2..9a01a7d4f17f 100644 --- a/drivers/usb/gadget/function/u_uvc.h +++ b/drivers/usb/gadget/function/u_uvc.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /* * u_uvc.h * diff --git a/drivers/usb/gadget/function/uvc.h b/drivers/usb/gadget/function/uvc.h index 1473d25ff17a..920763b56f2e 100644 --- a/drivers/usb/gadget/function/uvc.h +++ b/drivers/usb/gadget/function/uvc.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * uvc_gadget.h -- USB Video Class Gadget driver * diff --git a/drivers/usb/gadget/function/uvc_configfs.h b/drivers/usb/gadget/function/uvc_configfs.h index 341391dbc81f..7e1d7ca29bf2 100644 --- a/drivers/usb/gadget/function/uvc_configfs.h +++ b/drivers/usb/gadget/function/uvc_configfs.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /* * uvc_configfs.h * diff --git a/drivers/usb/gadget/function/uvc_v4l2.h b/drivers/usb/gadget/function/uvc_v4l2.h index 452d71059b3f..1576005b61fd 100644 --- a/drivers/usb/gadget/function/uvc_v4l2.h +++ b/drivers/usb/gadget/function/uvc_v4l2.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /* * uvc_v4l2.h -- USB Video Class Gadget driver * diff --git a/drivers/usb/gadget/function/uvc_video.h b/drivers/usb/gadget/function/uvc_video.h index dff12103f696..3e87ac7e2c05 100644 --- a/drivers/usb/gadget/function/uvc_video.h +++ b/drivers/usb/gadget/function/uvc_video.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /* * uvc_video.h -- USB Video Class Gadget driver * -- cgit v1.2.3 From a54177d2dc76154546e5ff6395a65f25e069fdef Mon Sep 17 00:00:00 2001 From: Jason Yan Date: Sat, 18 Apr 2020 16:18:07 +0800 Subject: usb: gadget: f_fs: remove unneeded semicolon in __ffs_data_got_descs() Fix the following coccicheck warning: drivers/usb/gadget/function/f_fs.c:2507:2-3: Unneeded semicolon Reported-by: Hulk Robot Signed-off-by: Jason Yan Signed-off-by: Felipe Balbi --- drivers/usb/gadget/function/f_fs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/usb/gadget/function') diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c index 10f01f974f67..494f853f2206 100644 --- a/drivers/usb/gadget/function/f_fs.c +++ b/drivers/usb/gadget/function/f_fs.c @@ -2508,7 +2508,7 @@ static int __ffs_data_got_descs(struct ffs_data *ffs, os_descs_count = get_unaligned_le32(data); data += 4; len -= 4; - }; + } /* Read descriptors */ raw_descs = data; -- cgit v1.2.3 From 43cd0023872efbb6a86bdc03fb520de3de55c7b0 Mon Sep 17 00:00:00 2001 From: Michael Grzeschik Date: Tue, 21 Apr 2020 15:28:14 +0200 Subject: usb: gadget: uvc_video: add worker to handle the frame pumping This patch changes the function uvc_video_pump to be a separate scheduled worker. This way the completion handler of each usb request and every direct caller of the pump has only to schedule the worker instead of doing the request handling by itself. Moving the request handling to one thread solves the locking problems between the three queueing cases in the completion handler, v4l2_qbuf and video_enable. Many drivers handle the completion handlers directly in their interrupt handlers. This patch also reduces the workload on each interrupt. Signed-off-by: Michael Grzeschik Signed-off-by: Felipe Balbi --- drivers/usb/gadget/function/uvc.h | 2 + drivers/usb/gadget/function/uvc_v4l2.c | 4 +- drivers/usb/gadget/function/uvc_video.c | 76 ++++++--------------------------- drivers/usb/gadget/function/uvc_video.h | 2 - 4 files changed, 19 insertions(+), 65 deletions(-) (limited to 'drivers/usb/gadget/function') diff --git a/drivers/usb/gadget/function/uvc.h b/drivers/usb/gadget/function/uvc.h index 920763b56f2e..23ee25383c1f 100644 --- a/drivers/usb/gadget/function/uvc.h +++ b/drivers/usb/gadget/function/uvc.h @@ -77,6 +77,8 @@ struct uvc_video { struct uvc_device *uvc; struct usb_ep *ep; + struct work_struct pump; + /* Frame parameters */ u8 bpp; u32 fcc; diff --git a/drivers/usb/gadget/function/uvc_v4l2.c b/drivers/usb/gadget/function/uvc_v4l2.c index 495f0ec663ea..4ca89eab6159 100644 --- a/drivers/usb/gadget/function/uvc_v4l2.c +++ b/drivers/usb/gadget/function/uvc_v4l2.c @@ -169,7 +169,9 @@ uvc_v4l2_qbuf(struct file *file, void *fh, struct v4l2_buffer *b) if (ret < 0) return ret; - return uvcg_video_pump(video); + schedule_work(&video->pump); + + return ret; } static int diff --git a/drivers/usb/gadget/function/uvc_video.c b/drivers/usb/gadget/function/uvc_video.c index 5c042f380708..633e23d58d86 100644 --- a/drivers/usb/gadget/function/uvc_video.c +++ b/drivers/usb/gadget/function/uvc_video.c @@ -142,44 +142,12 @@ static int uvcg_video_ep_queue(struct uvc_video *video, struct usb_request *req) return ret; } -/* - * I somehow feel that synchronisation won't be easy to achieve here. We have - * three events that control USB requests submission: - * - * - USB request completion: the completion handler will resubmit the request - * if a video buffer is available. - * - * - USB interface setting selection: in response to a SET_INTERFACE request, - * the handler will start streaming if a video buffer is available and if - * video is not currently streaming. - * - * - V4L2 buffer queueing: the driver will start streaming if video is not - * currently streaming. - * - * Race conditions between those 3 events might lead to deadlocks or other - * nasty side effects. - * - * The "video currently streaming" condition can't be detected by the irqqueue - * being empty, as a request can still be in flight. A separate "queue paused" - * flag is thus needed. - * - * The paused flag will be set when we try to retrieve the irqqueue head if the - * queue is empty, and cleared when we queue a buffer. - * - * The USB request completion handler will get the buffer at the irqqueue head - * under protection of the queue spinlock. If the queue is empty, the streaming - * paused flag will be set. Right after releasing the spinlock a userspace - * application can queue a buffer. The flag will then cleared, and the ioctl - * handler will restart the video stream. - */ static void uvc_video_complete(struct usb_ep *ep, struct usb_request *req) { struct uvc_video *video = req->context; struct uvc_video_queue *queue = &video->queue; - struct uvc_buffer *buf; unsigned long flags; - int ret; switch (req->status) { case 0: @@ -188,39 +156,20 @@ uvc_video_complete(struct usb_ep *ep, struct usb_request *req) case -ESHUTDOWN: /* disconnect from host. */ uvcg_dbg(&video->uvc->func, "VS request cancelled.\n"); uvcg_queue_cancel(queue, 1); - goto requeue; + break; default: uvcg_info(&video->uvc->func, "VS request completed with status %d.\n", req->status); uvcg_queue_cancel(queue, 0); - goto requeue; } - spin_lock_irqsave(&video->queue.irqlock, flags); - buf = uvcg_queue_head(&video->queue); - if (buf == NULL) { - spin_unlock_irqrestore(&video->queue.irqlock, flags); - goto requeue; - } - - video->encode(req, video, buf); - - ret = uvcg_video_ep_queue(video, req); - spin_unlock_irqrestore(&video->queue.irqlock, flags); - - if (ret < 0) { - uvcg_queue_cancel(queue, 0); - goto requeue; - } - - return; - -requeue: spin_lock_irqsave(&video->req_lock, flags); list_add_tail(&req->list, &video->req_free); spin_unlock_irqrestore(&video->req_lock, flags); + + schedule_work(&video->pump); } static int @@ -294,18 +243,15 @@ error: * This function fills the available USB requests (listed in req_free) with * video data from the queued buffers. */ -int uvcg_video_pump(struct uvc_video *video) +static void uvcg_video_pump(struct work_struct *work) { + struct uvc_video *video = container_of(work, struct uvc_video, pump); struct uvc_video_queue *queue = &video->queue; struct usb_request *req; struct uvc_buffer *buf; unsigned long flags; int ret; - /* FIXME TODO Race between uvcg_video_pump and requests completion - * handler ??? - */ - while (1) { /* Retrieve the first available USB request, protected by the * request lock. @@ -313,7 +259,7 @@ int uvcg_video_pump(struct uvc_video *video) spin_lock_irqsave(&video->req_lock, flags); if (list_empty(&video->req_free)) { spin_unlock_irqrestore(&video->req_lock, flags); - return 0; + return; } req = list_first_entry(&video->req_free, struct usb_request, list); @@ -345,7 +291,7 @@ int uvcg_video_pump(struct uvc_video *video) spin_lock_irqsave(&video->req_lock, flags); list_add_tail(&req->list, &video->req_free); spin_unlock_irqrestore(&video->req_lock, flags); - return 0; + return; } /* @@ -363,6 +309,9 @@ int uvcg_video_enable(struct uvc_video *video, int enable) } if (!enable) { + cancel_work_sync(&video->pump); + uvcg_queue_cancel(&video->queue, 0); + for (i = 0; i < UVC_NUM_REQUESTS; ++i) if (video->req[i]) usb_ep_dequeue(video->ep, video->req[i]); @@ -384,7 +333,9 @@ int uvcg_video_enable(struct uvc_video *video, int enable) } else video->encode = uvc_video_encode_isoc; - return uvcg_video_pump(video); + schedule_work(&video->pump); + + return ret; } /* @@ -394,6 +345,7 @@ int uvcg_video_init(struct uvc_video *video, struct uvc_device *uvc) { INIT_LIST_HEAD(&video->req_free); spin_lock_init(&video->req_lock); + INIT_WORK(&video->pump, uvcg_video_pump); video->uvc = uvc; video->fcc = V4L2_PIX_FMT_YUYV; diff --git a/drivers/usb/gadget/function/uvc_video.h b/drivers/usb/gadget/function/uvc_video.h index 3e87ac7e2c05..03adeefa343b 100644 --- a/drivers/usb/gadget/function/uvc_video.h +++ b/drivers/usb/gadget/function/uvc_video.h @@ -14,8 +14,6 @@ struct uvc_video; -int uvcg_video_pump(struct uvc_video *video); - int uvcg_video_enable(struct uvc_video *video, int enable); int uvcg_video_init(struct uvc_video *video, struct uvc_device *uvc); -- cgit v1.2.3 From aba3a8d01d623a5efef48ab8e78752d58d4c90c3 Mon Sep 17 00:00:00 2001 From: Fabrice Gasnier Date: Thu, 23 Apr 2020 13:55:54 +0200 Subject: usb: gadget: u_serial: add suspend resume callbacks Add suspend resume callbacks to handle the case seen when the bus is suspended by the HOST, and the device opens the port (cat /dev/ttyGS0). Gadget controller (like DWC2) doesn't accept usb requests to be queued in this case (when in L2 state), from the gs_open() call. Error log is printed - configfs-gadget gadget: acm ttyGS0 can't notify serial state, -11 If the HOST resumes (opens) the bus, the port still isn't functional. Use suspend/resume callbacks to monitor the gadget suspended state by using 'suspended' flag. In case the port gets opened (cat /dev/ttyGS0), the I/O stream will be delayed until the bus gets resumed by the HOST. Signed-off-by: Fabrice Gasnier Signed-off-by: Felipe Balbi --- drivers/usb/gadget/function/u_serial.c | 57 +++++++++++++++++++++++++++++----- drivers/usb/gadget/function/u_serial.h | 2 ++ 2 files changed, 51 insertions(+), 8 deletions(-) (limited to 'drivers/usb/gadget/function') diff --git a/drivers/usb/gadget/function/u_serial.c b/drivers/usb/gadget/function/u_serial.c index 8167d379e115..3cfc6e2eba71 100644 --- a/drivers/usb/gadget/function/u_serial.c +++ b/drivers/usb/gadget/function/u_serial.c @@ -120,6 +120,8 @@ struct gs_port { wait_queue_head_t drain_wait; /* wait while writes drain */ bool write_busy; wait_queue_head_t close_wait; + bool suspended; /* port suspended */ + bool start_delayed; /* delay start when suspended */ /* REVISIT this state ... */ struct usb_cdc_line_coding port_line_coding; /* 8-N-1 etc */ @@ -630,13 +632,19 @@ static int gs_open(struct tty_struct *tty, struct file *file) /* if connected, start the I/O stream */ if (port->port_usb) { - struct gserial *gser = port->port_usb; - - pr_debug("gs_open: start ttyGS%d\n", port->port_num); - gs_start_io(port); - - if (gser->connect) - gser->connect(gser); + /* if port is suspended, wait resume to start I/0 stream */ + if (!port->suspended) { + struct gserial *gser = port->port_usb; + + pr_debug("gs_open: start ttyGS%d\n", port->port_num); + gs_start_io(port); + + if (gser->connect) + gser->connect(gser); + } else { + pr_debug("delay start of ttyGS%d\n", port->port_num); + port->start_delayed = true; + } } pr_debug("gs_open: ttyGS%d (%p,%p)\n", port->port_num, tty, file); @@ -680,7 +688,7 @@ raced_with_open: pr_debug("gs_close: ttyGS%d (%p,%p) ...\n", port->port_num, tty, file); gser = port->port_usb; - if (gser && gser->disconnect) + if (gser && !port->suspended && gser->disconnect) gser->disconnect(gser); /* wait for circular write buffer to drain, disconnect, or at @@ -708,6 +716,7 @@ raced_with_open: else kfifo_reset(&port->port_write_buf); + port->start_delayed = false; port->port.count = 0; port->port.tty = NULL; @@ -1403,6 +1412,38 @@ void gserial_disconnect(struct gserial *gser) } EXPORT_SYMBOL_GPL(gserial_disconnect); +void gserial_suspend(struct gserial *gser) +{ + struct gs_port *port = gser->ioport; + unsigned long flags; + + spin_lock_irqsave(&port->port_lock, flags); + port->suspended = true; + spin_unlock_irqrestore(&port->port_lock, flags); +} +EXPORT_SYMBOL_GPL(gserial_suspend); + +void gserial_resume(struct gserial *gser) +{ + struct gs_port *port = gser->ioport; + unsigned long flags; + + spin_lock_irqsave(&port->port_lock, flags); + port->suspended = false; + if (!port->start_delayed) { + spin_unlock_irqrestore(&port->port_lock, flags); + return; + } + + pr_debug("delayed start ttyGS%d\n", port->port_num); + gs_start_io(port); + if (gser->connect) + gser->connect(gser); + port->start_delayed = false; + spin_unlock_irqrestore(&port->port_lock, flags); +} +EXPORT_SYMBOL_GPL(gserial_resume); + static int userial_init(void) { unsigned i; diff --git a/drivers/usb/gadget/function/u_serial.h b/drivers/usb/gadget/function/u_serial.h index dbe75b289be6..cadb76eecbc7 100644 --- a/drivers/usb/gadget/function/u_serial.h +++ b/drivers/usb/gadget/function/u_serial.h @@ -68,6 +68,8 @@ ssize_t gserial_get_console(unsigned char port_num, char *page); /* connect/disconnect is handled by individual functions */ int gserial_connect(struct gserial *, u8 port_num); void gserial_disconnect(struct gserial *); +void gserial_suspend(struct gserial *p); +void gserial_resume(struct gserial *p); /* functions are bound to configurations by a config or gadget driver */ int gser_bind_config(struct usb_configuration *c, u8 port_num); -- cgit v1.2.3 From e702a7c346344733824e27c943cbef59b74aef6f Mon Sep 17 00:00:00 2001 From: Fabrice Gasnier Date: Thu, 23 Apr 2020 13:55:55 +0200 Subject: usb: gadget: f_serial: add suspend resume callbacks Add suspend resume callbacks to notify u_serial of the bus suspend/resume state. Signed-off-by: Fabrice Gasnier Signed-off-by: Felipe Balbi --- drivers/usb/gadget/function/f_serial.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'drivers/usb/gadget/function') diff --git a/drivers/usb/gadget/function/f_serial.c b/drivers/usb/gadget/function/f_serial.c index 1406255d0865..e62713846350 100644 --- a/drivers/usb/gadget/function/f_serial.c +++ b/drivers/usb/gadget/function/f_serial.c @@ -348,6 +348,20 @@ static void gser_unbind(struct usb_configuration *c, struct usb_function *f) usb_free_all_descriptors(f); } +static void gser_resume(struct usb_function *f) +{ + struct f_gser *gser = func_to_gser(f); + + gserial_resume(&gser->port); +} + +static void gser_suspend(struct usb_function *f) +{ + struct f_gser *gser = func_to_gser(f); + + gserial_suspend(&gser->port); +} + static struct usb_function *gser_alloc(struct usb_function_instance *fi) { struct f_gser *gser; @@ -369,6 +383,8 @@ static struct usb_function *gser_alloc(struct usb_function_instance *fi) gser->port.func.set_alt = gser_set_alt; gser->port.func.disable = gser_disable; gser->port.func.free_func = gser_free; + gser->port.func.resume = gser_resume; + gser->port.func.suspend = gser_suspend; return &gser->port.func; } -- cgit v1.2.3 From 3affccdd5ed118042553927654a8c8d897cc1a98 Mon Sep 17 00:00:00 2001 From: Fabrice Gasnier Date: Thu, 23 Apr 2020 13:55:56 +0200 Subject: usb: gadget: f_acm: add suspend resume callbacks Add suspend resume callbacks to notify u_serial of the bus suspend/resume state. Signed-off-by: Fabrice Gasnier Signed-off-by: Felipe Balbi --- drivers/usb/gadget/function/f_acm.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'drivers/usb/gadget/function') diff --git a/drivers/usb/gadget/function/f_acm.c b/drivers/usb/gadget/function/f_acm.c index 7c152c28b26c..200596ea9557 100644 --- a/drivers/usb/gadget/function/f_acm.c +++ b/drivers/usb/gadget/function/f_acm.c @@ -723,6 +723,20 @@ static void acm_free_func(struct usb_function *f) kfree(acm); } +static void acm_resume(struct usb_function *f) +{ + struct f_acm *acm = func_to_acm(f); + + gserial_resume(&acm->port); +} + +static void acm_suspend(struct usb_function *f) +{ + struct f_acm *acm = func_to_acm(f); + + gserial_suspend(&acm->port); +} + static struct usb_function *acm_alloc_func(struct usb_function_instance *fi) { struct f_serial_opts *opts; @@ -750,6 +764,8 @@ static struct usb_function *acm_alloc_func(struct usb_function_instance *fi) acm->port_num = opts->port_num; acm->port.func.unbind = acm_unbind; acm->port.func.free_func = acm_free_func; + acm->port.func.resume = acm_resume; + acm->port.func.suspend = acm_suspend; return &acm->port.func; } -- cgit v1.2.3 From ded0d399754dbcae7ca0153ba87c68e66021f36a Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Fri, 24 Apr 2020 12:35:06 +0100 Subject: usb: gadget: function: remove redundant assignment to variable 'status' The variable status is being assigned a value that is never read and it is being updated later with a new value. The assignment is redundant and can be removed. Addresses-Coverity: ("Unused value") Signed-off-by: Colin Ian King Signed-off-by: Felipe Balbi --- drivers/usb/gadget/function/f_eem.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/usb/gadget/function') diff --git a/drivers/usb/gadget/function/f_eem.c b/drivers/usb/gadget/function/f_eem.c index b81a91d504bd..cfcc4e81fb77 100644 --- a/drivers/usb/gadget/function/f_eem.c +++ b/drivers/usb/gadget/function/f_eem.c @@ -291,8 +291,6 @@ static int eem_bind(struct usb_configuration *c, struct usb_function *f) goto fail; eem->port.out_ep = ep; - status = -ENOMEM; - /* support all relevant hardware speeds... we expect that when * hardware is dual speed, all bulk-capable endpoints work at * both speeds -- cgit v1.2.3 From 27b31b91b04bf7b76103d222bd2cbe37c9e59ed0 Mon Sep 17 00:00:00 2001 From: Thinh Nguyen Date: Tue, 5 May 2020 19:46:19 -0700 Subject: usb: gadget: f_tcm: Inform last stream request Set the request->is_last to each stream request to indicate that the request is the last stream request of a transfer. The DWC3 controller needs to know this info to properly switch streams. The current implementation of f_tcm uses a single request per transfer, so every stream request is the last of its stream. Signed-off-by: Thinh Nguyen Signed-off-by: Felipe Balbi --- drivers/usb/gadget/function/f_tcm.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/usb/gadget/function') diff --git a/drivers/usb/gadget/function/f_tcm.c b/drivers/usb/gadget/function/f_tcm.c index 36504931b2d1..2979cbe4d95f 100644 --- a/drivers/usb/gadget/function/f_tcm.c +++ b/drivers/usb/gadget/function/f_tcm.c @@ -531,6 +531,7 @@ static int uasp_prepare_r_request(struct usbg_cmd *cmd) stream->req_in->sg = se_cmd->t_data_sg; } + stream->req_in->is_last = 1; stream->req_in->complete = uasp_status_data_cmpl; stream->req_in->length = se_cmd->data_length; stream->req_in->context = cmd; @@ -554,6 +555,7 @@ static void uasp_prepare_status(struct usbg_cmd *cmd) */ iu->len = cpu_to_be16(se_cmd->scsi_sense_length); iu->status = se_cmd->scsi_status; + stream->req_status->is_last = 1; stream->req_status->context = cmd; stream->req_status->length = se_cmd->scsi_sense_length + 16; stream->req_status->buf = iu; @@ -991,6 +993,7 @@ static int usbg_prepare_w_request(struct usbg_cmd *cmd, struct usb_request *req) req->sg = se_cmd->t_data_sg; } + req->is_last = 1; req->complete = usbg_data_write_cmpl; req->length = se_cmd->data_length; req->context = cmd; -- cgit v1.2.3