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

tty: serial: qcom_geni_serial: Remove interrupt storm

Disable M_TX_FIFO_WATERMARK_EN after we've sent all data for a given
transaction so we don't continue to receive a flurry of free space
interrupts while waiting for the M_CMD_DONE notification. Re-enable the
watermark when establishing the next transaction.

Also clear the watermark interrupt after filling the FIFO so we do not
receive notification again prior to actually having free space.

Signed-off-by: Ryan Case <ryandcase@chromium.org>
Reviewed-by: Douglas Anderson <dianders@chromium.org>
Tested-by: Douglas Anderson <dianders@chromium.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Ryan Case and committed by
Greg Kroah-Hartman
64a42807 71ab1c03

+23 -2
+23 -2
drivers/tty/serial/qcom_geni_serial.c
··· 722 722 size_t pending; 723 723 int i; 724 724 u32 status; 725 + u32 irq_en; 725 726 unsigned int chunk; 726 727 int tail; 727 728 ··· 751 750 if (!port->tx_remaining) { 752 751 qcom_geni_serial_setup_tx(uport, pending); 753 752 port->tx_remaining = pending; 753 + 754 + irq_en = readl_relaxed(uport->membase + SE_GENI_M_IRQ_EN); 755 + if (!(irq_en & M_TX_FIFO_WATERMARK_EN)) 756 + writel_relaxed(irq_en | M_TX_FIFO_WATERMARK_EN, 757 + uport->membase + SE_GENI_M_IRQ_EN); 754 758 } 755 759 756 760 remaining = chunk; ··· 779 773 } 780 774 781 775 xmit->tail = tail & (UART_XMIT_SIZE - 1); 776 + 777 + /* 778 + * The tx fifo watermark is level triggered and latched. Though we had 779 + * cleared it in qcom_geni_serial_isr it will have already reasserted 780 + * so we must clear it again here after our writes. 781 + */ 782 + writel_relaxed(M_TX_FIFO_WATERMARK_EN, 783 + uport->membase + SE_GENI_M_IRQ_CLEAR); 784 + 782 785 out_write_wakeup: 786 + if (!port->tx_remaining) { 787 + irq_en = readl_relaxed(uport->membase + SE_GENI_M_IRQ_EN); 788 + if (irq_en & M_TX_FIFO_WATERMARK_EN) 789 + writel_relaxed(irq_en & ~M_TX_FIFO_WATERMARK_EN, 790 + uport->membase + SE_GENI_M_IRQ_EN); 791 + } 792 + 783 793 if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) 784 794 uart_write_wakeup(uport); 785 795 } ··· 831 809 tty_insert_flip_char(tport, 0, TTY_OVERRUN); 832 810 } 833 811 834 - if (m_irq_status & (M_TX_FIFO_WATERMARK_EN | M_CMD_DONE_EN) && 835 - m_irq_en & (M_TX_FIFO_WATERMARK_EN | M_CMD_DONE_EN)) 812 + if (m_irq_status & m_irq_en & (M_TX_FIFO_WATERMARK_EN | M_CMD_DONE_EN)) 836 813 qcom_geni_serial_handle_tx(uport, m_irq_status & M_CMD_DONE_EN, 837 814 geni_status & M_GENI_CMD_ACTIVE); 838 815