Merge tag 'usb-5.8-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb
Pull USB/PHY driver updates from Greg KH: "Here are the large set of USB and PHY driver updates for 5.8-rc1. Nothing huge, just lots of little things: - USB gadget fixes and additions all over the place - new PHY drivers - PHY driver fixes and updates - XHCI driver updates - musb driver updates - more USB-serial driver ids added - various USB quirks added - thunderbolt minor updates and fixes - typec updates and additions All of these have been in linux-next for a while with no reported issues" * tag 'usb-5.8-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (245 commits) usb: dwc3: meson-g12a: fix USB2 PHY initialization on G12A and A1 SoCs usb: dwc3: meson-g12a: fix error path when fetching the reset line fails Revert "dt-bindings: usb: qcom,dwc3: Convert USB DWC3 bindings" Revert "dt-bindings: usb: qcom,dwc3: Add compatible for SC7180" Revert "dt-bindings: usb: qcom,dwc3: Introduce interconnect properties for Qualcomm DWC3 driver" USB: serial: ch341: fix lockup of devices with limited prescaler USB: serial: ch341: add basis for quirk detection CDC-ACM: heed quirk also in error handling USB: serial: option: add Telit LE910C1-EUX compositions usb: musb: Fix runtime PM imbalance on error usb: musb: jz4740: Prevent lockup when CONFIG_SMP is set usb: musb: mediatek: add reset FADDR to zero in reset interrupt handle usb: musb: use true for 'use_dma' usb: musb: start session in resume for host port usb: musb: return -ESHUTDOWN in urb when three-strikes error happened USB: serial: qcserial: add DW5816e QDL support thunderbolt: Add trivial .shutdown usb: dwc3: keystone: Turn on USB3 PHY before controller dt-bindings: usb: ti,keystone-dwc3.yaml: Add USB3.0 PHY property dt-bindings: usb: convert keystone-usb.txt to YAML ...
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
@@ -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
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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;
|
||||
|
@@ -1,4 +1,4 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* f_uvc.h -- USB Video Class Gadget driver
|
||||
*
|
||||
|
@@ -1,4 +1,4 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* RNDIS Definitions for Remote NDIS
|
||||
*
|
||||
|
@@ -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
|
||||
*
|
||||
|
@@ -1,4 +1,4 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* u_ecm.h
|
||||
*
|
||||
|
@@ -1,4 +1,4 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* u_eem.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
|
||||
*
|
||||
|
@@ -1,4 +1,4 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* u_ether_configfs.h
|
||||
*
|
||||
|
@@ -1,4 +1,4 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* u_fs.h
|
||||
*
|
||||
|
@@ -1,4 +1,4 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* u_gether.h
|
||||
*
|
||||
|
@@ -1,4 +1,4 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* u_hid.h
|
||||
*
|
||||
|
@@ -1,4 +1,4 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* u_midi.h
|
||||
*
|
||||
|
@@ -1,4 +1,4 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* u_ncm.h
|
||||
*
|
||||
|
@@ -1,4 +1,4 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* u_phonet.h - interface to Phonet
|
||||
*
|
||||
|
@@ -1,4 +1,4 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* u_printer.h
|
||||
*
|
||||
|
@@ -1,4 +1,4 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* u_rndis.h
|
||||
*
|
||||
|
@@ -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;
|
||||
/* 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);
|
||||
pr_debug("gs_open: start ttyGS%d\n", port->port_num);
|
||||
gs_start_io(port);
|
||||
|
||||
if (gser->connect)
|
||||
gser->connect(gser);
|
||||
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;
|
||||
|
@@ -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
|
||||
*
|
||||
@@ -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);
|
||||
|
@@ -1,4 +1,4 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* u_tcm.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
|
||||
*
|
||||
|
@@ -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
|
||||
*
|
||||
|
@@ -1,4 +1,4 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* u_uac2.h
|
||||
*
|
||||
|
@@ -1,4 +1,4 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* u_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
|
||||
*
|
||||
@@ -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;
|
||||
|
@@ -1,4 +1,4 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* uvc_configfs.h
|
||||
*
|
||||
|
@@ -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
|
||||
|
@@ -1,4 +1,4 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* uvc_v4l2.h -- USB Video Class Gadget driver
|
||||
*
|
||||
|
@@ -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;
|
||||
|
@@ -1,4 +1,4 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* uvc_video.h -- USB Video Class Gadget driver
|
||||
*
|
||||
@@ -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);
|
||||
|
Reference in New Issue
Block a user