Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

msm_serial: Send more than 1 character at a time on UARTDM

UARTDM cores have a TX fifo that can accept more than one
character per register write, but the msm_serial driver currently
only supports 1 character mode. Add support for this mode of operation
to speed up the transmit path on DM devices.

Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
Acked-by: David Brown <davidb@codeaurora.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Stephen Boyd and committed by
Greg Kroah-Hartman
17fae28e 6909dadd

+32 -19
+32 -19
drivers/tty/serial/msm_serial.c
··· 195 195 tty_flip_buffer_push(tport); 196 196 } 197 197 198 - static void reset_dm_count(struct uart_port *port) 198 + static void reset_dm_count(struct uart_port *port, int count) 199 199 { 200 200 wait_for_xmitr(port); 201 - msm_write(port, 1, UARTDM_NCF_TX); 201 + msm_write(port, count, UARTDM_NCF_TX); 202 202 msm_read(port, UARTDM_NCF_TX); 203 203 } 204 204 ··· 206 206 { 207 207 struct circ_buf *xmit = &port->state->xmit; 208 208 struct msm_port *msm_port = UART_TO_MSM(port); 209 - int sent_tx; 209 + unsigned int tx_count, num_chars; 210 + unsigned int tf_pointer = 0; 211 + 212 + tx_count = uart_circ_chars_pending(xmit); 213 + tx_count = min3(tx_count, (unsigned int)UART_XMIT_SIZE - xmit->tail, 214 + port->fifosize); 210 215 211 216 if (port->x_char) { 212 217 if (msm_port->is_uartdm) 213 - reset_dm_count(port); 218 + reset_dm_count(port, tx_count + 1); 214 219 215 220 msm_write(port, port->x_char, 216 221 msm_port->is_uartdm ? UARTDM_TF : UART_TF); 217 222 port->icount.tx++; 218 223 port->x_char = 0; 224 + } else if (tx_count && msm_port->is_uartdm) { 225 + reset_dm_count(port, tx_count); 219 226 } 220 227 221 - if (msm_port->is_uartdm) 222 - reset_dm_count(port); 228 + while (tf_pointer < tx_count) { 229 + int i; 230 + char buf[4] = { 0 }; 231 + unsigned int *bf = (unsigned int *)&buf; 223 232 224 - while (msm_read(port, UART_SR) & UART_SR_TX_READY) { 225 - if (uart_circ_empty(xmit)) { 226 - /* disable tx interrupts */ 227 - msm_port->imr &= ~UART_IMR_TXLEV; 228 - msm_write(port, msm_port->imr, UART_IMR); 233 + if (!(msm_read(port, UART_SR) & UART_SR_TX_READY)) 229 234 break; 230 - } 231 - msm_write(port, xmit->buf[xmit->tail], 232 - msm_port->is_uartdm ? UARTDM_TF : UART_TF); 233 235 234 236 if (msm_port->is_uartdm) 235 - reset_dm_count(port); 237 + num_chars = min(tx_count - tf_pointer, sizeof(buf)); 238 + else 239 + num_chars = 1; 236 240 237 - xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); 238 - port->icount.tx++; 239 - sent_tx = 1; 241 + for (i = 0; i < num_chars; i++) { 242 + buf[i] = xmit->buf[xmit->tail + i]; 243 + port->icount.tx++; 244 + } 245 + 246 + msm_write(port, *bf, msm_port->is_uartdm ? UARTDM_TF : UART_TF); 247 + xmit->tail = (xmit->tail + num_chars) & (UART_XMIT_SIZE - 1); 248 + tf_pointer += num_chars; 240 249 } 250 + 251 + /* disable tx interrupts if nothing more to send */ 252 + if (uart_circ_empty(xmit)) 253 + msm_stop_tx(port); 241 254 242 255 if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) 243 256 uart_write_wakeup(port); ··· 772 759 struct msm_port *msm_port = UART_TO_MSM(port); 773 760 774 761 if (msm_port->is_uartdm) 775 - reset_dm_count(port); 762 + reset_dm_count(port, 1); 776 763 777 764 while (!(msm_read(port, UART_SR) & UART_SR_TX_READY)) 778 765 ;