Merge "tty: serial: msm_geni_serial: Requeue buffer after handling the data"
diff --git a/drivers/tty/serial/msm_geni_serial.c b/drivers/tty/serial/msm_geni_serial.c
index cfc3762..d7355f0 100644
--- a/drivers/tty/serial/msm_geni_serial.c
+++ b/drivers/tty/serial/msm_geni_serial.c
@@ -124,7 +124,7 @@
ipc_log_string(ctx, x); \
} while (0)
-#define DMA_RX_BUF_SIZE (512)
+#define DMA_RX_BUF_SIZE (2048)
struct msm_geni_serial_port {
struct uart_port uport;
char name[20];
@@ -821,6 +821,25 @@
__func__, geni_ios);
}
+static void msm_geni_serial_tx_fsm_rst(struct uart_port *uport)
+{
+ unsigned int tx_irq_en;
+ int done = 0;
+ int tries = 0;
+
+ tx_irq_en = geni_read_reg_nolog(uport->membase, SE_DMA_TX_IRQ_EN);
+ geni_write_reg_nolog(0, uport->membase, SE_DMA_TX_IRQ_EN_SET);
+ geni_write_reg_nolog(1, uport->membase, SE_DMA_TX_FSM_RST);
+ do {
+ done = msm_geni_serial_poll_bit(uport, SE_DMA_TX_IRQ_STAT,
+ TX_RESET_DONE, true);
+ tries++;
+ } while (!done && tries < 5);
+ geni_write_reg_nolog(TX_DMA_DONE | TX_RESET_DONE, uport->membase,
+ SE_DMA_TX_IRQ_CLR);
+ geni_write_reg_nolog(tx_irq_en, uport->membase, SE_DMA_TX_IRQ_EN_SET);
+}
+
static void msm_geni_serial_stop_tx(struct uart_port *uport)
{
unsigned int geni_m_irq_en;
@@ -842,8 +861,7 @@
SE_GENI_TX_WATERMARK_REG);
} else if (port->xfer_mode == SE_DMA) {
if (port->tx_dma) {
- geni_write_reg_nolog(1, uport->membase,
- SE_DMA_TX_FSM_RST);
+ msm_geni_serial_tx_fsm_rst(uport);
geni_se_tx_dma_unprep(port->wrapper_dev, port->tx_dma,
port->xmit_size);
port->tx_dma = (dma_addr_t)NULL;
@@ -906,20 +924,11 @@
geni_write_reg_nolog(geni_m_irq_en, uport->membase,
SE_GENI_M_IRQ_EN);
} else if (port->xfer_mode == SE_DMA) {
- port->rx_buf = kzalloc(DMA_RX_BUF_SIZE, GFP_KERNEL);
- if (!port->rx_buf) {
- dev_err(uport->dev, "%s: kzalloc failed\n",
- __func__);
- msm_geni_serial_abort_rx(uport);
- return;
- }
-
ret = geni_se_rx_dma_prep(port->wrapper_dev, uport->membase,
port->rx_buf, DMA_RX_BUF_SIZE, &port->rx_dma);
if (ret) {
dev_err(uport->dev, "%s: RX Prep dma failed %d\n",
__func__, ret);
- kfree(port->rx_buf);
msm_geni_serial_abort_rx(uport);
return;
}
@@ -933,6 +942,25 @@
IPC_LOG_MSG(port->ipc_log_misc, "%s 0x%x\n", __func__, geni_status);
}
+static void msm_geni_serial_rx_fsm_rst(struct uart_port *uport)
+{
+ unsigned int rx_irq_en;
+ int done = 0;
+ int tries = 0;
+
+ rx_irq_en = geni_read_reg_nolog(uport->membase, SE_DMA_RX_IRQ_EN);
+ geni_write_reg_nolog(0, uport->membase, SE_DMA_RX_IRQ_EN_SET);
+ geni_write_reg_nolog(1, uport->membase, SE_DMA_RX_FSM_RST);
+ do {
+ done = msm_geni_serial_poll_bit(uport, SE_DMA_RX_IRQ_STAT,
+ RX_RESET_DONE, true);
+ tries++;
+ } while (!done && tries < 5);
+ geni_write_reg_nolog(RX_DMA_DONE | RX_RESET_DONE, uport->membase,
+ SE_DMA_RX_IRQ_CLR);
+ geni_write_reg_nolog(rx_irq_en, uport->membase, SE_DMA_RX_IRQ_EN_SET);
+}
+
static void msm_geni_serial_stop_rx(struct uart_port *uport)
{
unsigned int geni_s_irq_en;
@@ -960,11 +988,9 @@
geni_write_reg_nolog(geni_m_irq_en, uport->membase,
SE_GENI_M_IRQ_EN);
} else if (port->xfer_mode == SE_DMA && port->rx_dma) {
- geni_write_reg_nolog(1, uport->membase, SE_DMA_RX_FSM_RST);
+ msm_geni_serial_rx_fsm_rst(uport);
geni_se_rx_dma_unprep(port->wrapper_dev, port->rx_dma,
DMA_RX_BUF_SIZE);
- kfree(port->rx_buf);
- port->rx_buf = NULL;
port->rx_dma = (dma_addr_t)NULL;
}
@@ -1126,11 +1152,16 @@
geni_se_rx_dma_unprep(msm_port->wrapper_dev, msm_port->rx_dma,
DMA_RX_BUF_SIZE);
rx_bytes = geni_read_reg_nolog(uport->membase, SE_DMA_RX_LEN_IN);
- if (unlikely(!msm_port->rx_buf || !rx_bytes)) {
- IPC_LOG_MSG(msm_port->ipc_log_rx, "%s: Rx_buf %pK Size %d\n",
- __func__, msm_port->rx_buf, rx_bytes);
+ if (unlikely(!msm_port->rx_buf)) {
+ IPC_LOG_MSG(msm_port->ipc_log_rx, "%s: NULL Rx_buf\n",
+ __func__);
return 0;
}
+ if (unlikely(!rx_bytes)) {
+ IPC_LOG_MSG(msm_port->ipc_log_rx, "%s: Size %d\n",
+ __func__, rx_bytes);
+ goto exit_handle_dma_rx;
+ }
tport = &uport->state->port;
ret = tty_insert_flip_string(tport, (unsigned char *)(msm_port->rx_buf),
@@ -1144,6 +1175,7 @@
tty_flip_buffer_push(tport);
dump_ipc(msm_port->ipc_log_rx, "DMA Rx", (char *)msm_port->rx_buf, 0,
rx_bytes);
+exit_handle_dma_rx:
ret = geni_se_rx_dma_prep(msm_port->wrapper_dev, uport->membase,
msm_port->rx_buf, DMA_RX_BUF_SIZE, &msm_port->rx_dma);
if (ret)
@@ -1390,6 +1422,15 @@
ret = -ENOMEM;
goto exit_portsetup;
}
+
+ msm_port->rx_buf = devm_kzalloc(uport->dev, DMA_RX_BUF_SIZE,
+ GFP_KERNEL);
+ if (!msm_port->rx_buf) {
+ kfree(msm_port->rx_fifo);
+ msm_port->rx_fifo = NULL;
+ ret = -ENOMEM;
+ goto exit_portsetup;
+ }
} else {
/*
* Make an unconditional cancel on the main sequencer to reset