mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-07 12:25:00 -04:00
usb: gadget: u_serial: Dequeue request on gserial_disconnect
Consider a case where, during bus_reset or composition switch, due to some reason ENDXFER command timed out. Now, gadget driver won't be giving back the requests to function driver because of the timeout since controller can still access those requests. During function_disable gadget driver expects function driver to dequeue the requests so that the lists maintained by both gadget driver and function driver should free up all the request. Currently u_serial driver is just freeing the requests from read/write pool without any dequeue which is causing inconsistencies. Fix this by dequeueing requests from read/write pool on gserial_disconnect. Change-Id: I714c7fe681d42a68c864bf0e90748f117b258548 Signed-off-by: Pratham Pratap <quic_ppratap@quicinc.com>
This commit is contained in:
parent
37a3bfb6ec
commit
83626bc1f4
1 changed files with 26 additions and 2 deletions
|
|
@ -115,6 +115,8 @@ struct gs_port {
|
|||
struct list_head write_pool;
|
||||
int write_started;
|
||||
int write_allocated;
|
||||
struct list_head queued_read_pool;
|
||||
struct list_head queued_write_pool;
|
||||
struct kfifo port_write_buf;
|
||||
wait_queue_head_t drain_wait; /* wait while writes drain */
|
||||
bool write_busy;
|
||||
|
|
@ -252,7 +254,7 @@ __acquires(&port->port_lock)
|
|||
do_tty_wake = true;
|
||||
|
||||
req->length = len;
|
||||
list_del(&req->list);
|
||||
list_move_tail(&req->list, &port->queued_write_pool);
|
||||
req->zero = kfifo_is_empty(&port->port_write_buf);
|
||||
|
||||
pr_vdebug("ttyGS%d: tx len=%d, 0x%02x 0x%02x 0x%02x ...\n",
|
||||
|
|
@ -317,7 +319,7 @@ __acquires(&port->port_lock)
|
|||
break;
|
||||
|
||||
req = list_entry(pool->next, struct usb_request, list);
|
||||
list_del(&req->list);
|
||||
list_move_tail(&req->list, &port->queued_read_pool);
|
||||
req->length = out->maxpacket;
|
||||
|
||||
/* drop lock while we call out; the controller driver
|
||||
|
|
@ -1162,6 +1164,8 @@ gs_port_alloc(unsigned port_num, struct usb_cdc_line_coding *coding)
|
|||
INIT_LIST_HEAD(&port->read_pool);
|
||||
INIT_LIST_HEAD(&port->read_queue);
|
||||
INIT_LIST_HEAD(&port->write_pool);
|
||||
INIT_LIST_HEAD(&port->queued_read_pool);
|
||||
INIT_LIST_HEAD(&port->queued_write_pool);
|
||||
|
||||
port->port_num = port_num;
|
||||
port->port_line_coding = *coding;
|
||||
|
|
@ -1366,6 +1370,26 @@ void gserial_disconnect(struct gserial *gser)
|
|||
/* tell the TTY glue not to do I/O here any more */
|
||||
spin_lock_irqsave(&port->port_lock, flags);
|
||||
|
||||
while (!list_empty(&port->queued_read_pool)) {
|
||||
struct usb_request *read_req;
|
||||
|
||||
read_req = list_first_entry(&port->queued_read_pool,
|
||||
struct usb_request, list);
|
||||
spin_unlock(&port->port_lock);
|
||||
usb_ep_dequeue(port->port_usb->out, read_req);
|
||||
spin_lock(&port->port_lock);
|
||||
}
|
||||
|
||||
while (!list_empty(&port->queued_write_pool)) {
|
||||
struct usb_request *write_req;
|
||||
|
||||
write_req = list_first_entry(&port->queued_write_pool,
|
||||
struct usb_request, list);
|
||||
spin_unlock(&port->port_lock);
|
||||
usb_ep_dequeue(port->port_usb->in, write_req);
|
||||
spin_lock(&port->port_lock);
|
||||
}
|
||||
|
||||
/* REVISIT as above: how best to track this? */
|
||||
port->port_line_coding = gser->port_line_coding;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue