Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 83626bc1 authored by Pratham Pratap's avatar Pratham Pratap Committed by Gerrit - the friendly Code Review server
Browse files

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: default avatarPratham Pratap <quic_ppratap@quicinc.com>
parent 37a3bfb6
Loading
Loading
Loading
Loading
+26 −2
Original line number Diff line number Diff line
@@ -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;