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

Commit f158ebf5 authored by Mayank Rana's avatar Mayank Rana
Browse files

usb: u_serial: Fix spin lockup issue



Commit f6fb2128 (usb: tty: Add more buffer space and make the
buffer use direct) has enable USB TTY port's low_latency flag to
true for high throughput data transfer. tty_flip_buffer_push() API
is using this flag to make decision about flushing flip buffer to
line discipline in same caller context (if port->low_latency is set)
or worker thread context (if port->low_latency is not set). This API
also calls (tty->ops->flush_chars) in same context from
n_tty_receive_buf() API which results into spin lockup where this
flag is set. Hence fix this issue by releasing spinlock before
calling tty_flip_buffer_push() based on this flag value.

CRs-Fixed: 768503
Change-Id: I9584668134a121913bf78a133ddfc769b20e4cab
Signed-off-by: default avatarMayank Rana <mrana@codeaurora.org>
parent 51c75088
Loading
Loading
Loading
Loading
+16 −3
Original line number Diff line number Diff line
@@ -615,11 +615,24 @@ static void gs_rx_push(struct work_struct *w)
		port->read_started--;
	}

	/* Push from tty to ldisc; without low_latency set this is handled by
	 * a workqueue, so we won't get callbacks and can hold port_lock
	/*
	 * Push from tty to ldisc:
	 * With low_latency set to 0:
	 * this is handled by a workqueue, so we won't get callbacks
	 * (tty->ops->flush_chars i.e. gs_flush_chars) and can hold
	 * port_lock.
	 * With low_latency set to 1:
	 * gs_flush_chars (tty->ops->flush_chars) is called synchronosly
	 * with port_lock held. Hence we need to release it temporarily
	 * to avoid recursive spinlock.
	 */
	if (do_push)
	if (do_push) {
		if (port->port.low_latency)
			spin_unlock(&port->port_lock);
		tty_flip_buffer_push(&port->port);
		if (port->port.low_latency)
			spin_lock(&port->port_lock);
	}

	/* We want our data queue to become empty ASAP, keeping data
	 * in the tty and ldisc (not here).  If we couldn't push any