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

tty: serial: tegra: Handle RX transfer in PIO mode if DMA wasn't started

It is possible to get an instant RX timeout or end-of-transfer interrupt
before RX DMA was started, if transaction is less than 16 bytes. Transfer
should be handled in PIO mode in this case because DMA can't handle it.
This patch brings back the original behaviour of the driver that was
changed by accident by a previous commit, it fixes occasional Bluetooth HW
initialization failures which I started to notice recently.

Fixes: d5e3fadb7012 ("tty: serial: tegra: Activate RX DMA transfer by request")
Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
Link: https://lore.kernel.org/r/20200209164415.9632-1-digetx@gmail.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Dmitry Osipenko and committed by
Greg Kroah-Hartman
1f69a127 04b5bfe3

+16 -19
+16 -19
drivers/tty/serial/serial-tegra.c
··· 692 692 count, DMA_TO_DEVICE); 693 693 } 694 694 695 + static void do_handle_rx_pio(struct tegra_uart_port *tup) 696 + { 697 + struct tty_struct *tty = tty_port_tty_get(&tup->uport.state->port); 698 + struct tty_port *port = &tup->uport.state->port; 699 + 700 + tegra_uart_handle_rx_pio(tup, port); 701 + if (tty) { 702 + tty_flip_buffer_push(port); 703 + tty_kref_put(tty); 704 + } 705 + } 706 + 695 707 static void tegra_uart_rx_buffer_push(struct tegra_uart_port *tup, 696 708 unsigned int residue) 697 709 { 698 710 struct tty_port *port = &tup->uport.state->port; 699 - struct tty_struct *tty = tty_port_tty_get(port); 700 711 unsigned int count; 701 712 702 713 async_tx_ack(tup->rx_dma_desc); ··· 716 705 /* If we are here, DMA is stopped */ 717 706 tegra_uart_copy_rx_to_tty(tup, port, count); 718 707 719 - tegra_uart_handle_rx_pio(tup, port); 720 - if (tty) { 721 - tty_flip_buffer_push(port); 722 - tty_kref_put(tty); 723 - } 708 + do_handle_rx_pio(tup); 724 709 } 725 710 726 711 static void tegra_uart_rx_dma_complete(void *args) ··· 756 749 { 757 750 struct dma_tx_state state; 758 751 759 - if (!tup->rx_dma_active) 752 + if (!tup->rx_dma_active) { 753 + do_handle_rx_pio(tup); 760 754 return; 755 + } 761 756 762 757 dmaengine_terminate_all(tup->rx_dma_chan); 763 758 dmaengine_tx_status(tup->rx_dma_chan, tup->rx_cookie, &state); ··· 823 814 /* Will start/stop_tx accordingly */ 824 815 if (msr & UART_MSR_DCTS) 825 816 uart_handle_cts_change(&tup->uport, msr & UART_MSR_CTS); 826 - } 827 - 828 - static void do_handle_rx_pio(struct tegra_uart_port *tup) 829 - { 830 - struct tty_struct *tty = tty_port_tty_get(&tup->uport.state->port); 831 - struct tty_port *port = &tup->uport.state->port; 832 - 833 - tegra_uart_handle_rx_pio(tup, port); 834 - if (tty) { 835 - tty_flip_buffer_push(port); 836 - tty_kref_put(tty); 837 - } 838 817 } 839 818 840 819 static irqreturn_t tegra_uart_isr(int irq, void *data)