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

Commit 6b4be518 authored by Mukesh Kumar Savaliya's avatar Mukesh Kumar Savaliya Committed by Rama Krishna Phani A
Browse files

serial: msm_geni_serial: Fix wrap around of TX buffer

Before commit a1fee899e5bed ("tty: serial: qcom_geni_serial: Fix
softlock") the size of TX transfers was limited to the TX FIFO size,
and wrap arounds of the UART circular buffer were split into two
transfers. With the commit wrap around are allowed within a transfer.
The TX FIFO of the geni serial port uses a word size of 4 bytes. In
case of a circular buffer wrap within a transfer the driver currently
may write an incomplete word to the FIFO, with some bytes containing
data from the circular buffer and others being zero. Since the
transfer isn't completed yet the zero bytes are sent as if they were
actual data.

Handle wrap arounds of the TX buffer properly and ensure that words
written to the TX FIFO always contain valid data (unless the transfer
is completed).

(am from https://lore.kernel.org/patchwork/patch/1026544/

).

Change-Id: I3a3171c54f251478e07e8567d534f1570e83a062
Signed-off-by: default avatarMatthias Kaehlcke <mka@chromium.org>
Signed-off-by: default avatarMukesh Kumar Savaliya <msavaliy@codeaurora.org>
parent b1138789
Loading
Loading
Loading
Loading
+6 −6
Original line number Diff line number Diff line
@@ -1338,8 +1338,7 @@ static int msm_geni_serial_handle_tx(struct uart_port *uport, bool done,
		avail_fifo_bytes = 0;

	temp_tail = xmit->tail;
	xmit_size = min3((unsigned int)pending,
		(unsigned int)(UART_XMIT_SIZE - temp_tail), avail_fifo_bytes);
	xmit_size = min(avail_fifo_bytes, pending);
	if (!xmit_size)
		goto exit_handle_tx;

@@ -1358,20 +1357,21 @@ static int msm_geni_serial_handle_tx(struct uart_port *uport, bool done,
		tx_bytes = ((bytes_remaining < fifo_width_bytes) ?
					bytes_remaining : fifo_width_bytes);

		for (c = 0; c < tx_bytes ; c++)
			buf |= (xmit->buf[temp_tail + c] << (c * 8));
		for (c = 0; c < tx_bytes ; c++) {
			buf |= (xmit->buf[temp_tail++] << (c * 8));
			temp_tail &= UART_XMIT_SIZE - 1;
		}

		geni_write_reg_nolog(buf, uport->membase, SE_GENI_TX_FIFOn);

		i += tx_bytes;
		bytes_remaining -= tx_bytes;
		uport->icount.tx += tx_bytes;
		temp_tail += tx_bytes;
		msm_port->cur_tx_remaining -= tx_bytes;
		/* Ensure FIFO write goes through */
		wmb();
	}
	xmit->tail = temp_tail & (UART_XMIT_SIZE - 1);
	xmit->tail = temp_tail;
exit_handle_tx:
	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
		uart_write_wakeup(uport);