mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-07 04:12:04 -04:00
msm-geni-serial: Use dma_alloc_coherent to avoid dma map/unmap
Use dma_alloc_coherent and dma_free_coherent to avoid dma_map/ dma_unmap calls for every UART rx transfer. Change-Id: Ia2d71d19dc26d96f3c2abe12e22d326d21a2e071 Signed-off-by: Mukesh Kumar Savaliya <msavaliy@codeaurora.org>
This commit is contained in:
parent
87279d8c5f
commit
c7ba4adfa9
3 changed files with 84 additions and 46 deletions
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2016-2019, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2016-2020, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/clk.h>
|
||||
|
|
@ -1244,6 +1244,35 @@ int geni_se_tx_dma_prep(struct device *wrapper_dev, void __iomem *base,
|
|||
}
|
||||
EXPORT_SYMBOL(geni_se_tx_dma_prep);
|
||||
|
||||
/**
|
||||
* geni_se_rx_dma_start() - Prepare the Serial Engine registers for RX DMA
|
||||
transfers.
|
||||
* @base: Base address of the SE register block.
|
||||
* @rx_len: Length of the RX buffer.
|
||||
* @rx_dma: Pointer to store the mapped DMA address.
|
||||
*
|
||||
* This function is used to prepare the Serial Engine registers for DMA RX.
|
||||
*
|
||||
* Return: None.
|
||||
*/
|
||||
void geni_se_rx_dma_start(void __iomem *base, int rx_len, dma_addr_t *rx_dma)
|
||||
{
|
||||
|
||||
if (!*rx_dma || !base || !rx_len)
|
||||
return;
|
||||
|
||||
geni_write_reg(7, base, SE_DMA_RX_IRQ_EN_SET);
|
||||
geni_write_reg(GENI_SE_DMA_PTR_L(*rx_dma), base, SE_DMA_RX_PTR_L);
|
||||
geni_write_reg(GENI_SE_DMA_PTR_H(*rx_dma), base, SE_DMA_RX_PTR_H);
|
||||
/* RX does not have EOT bit */
|
||||
geni_write_reg(0, base, SE_DMA_RX_ATTR);
|
||||
|
||||
/* Ensure that above register writes went through */
|
||||
mb();
|
||||
geni_write_reg(rx_len, base, SE_DMA_RX_LEN);
|
||||
}
|
||||
EXPORT_SYMBOL(geni_se_rx_dma_start);
|
||||
|
||||
/**
|
||||
* geni_se_rx_dma_prep() - Prepare the Serial Engine for RX DMA transfer
|
||||
* @wrapper_dev: QUPv3 Wrapper Device to which the RX buffer is mapped.
|
||||
|
|
@ -1269,12 +1298,8 @@ int geni_se_rx_dma_prep(struct device *wrapper_dev, void __iomem *base,
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
geni_write_reg(7, base, SE_DMA_RX_IRQ_EN_SET);
|
||||
geni_write_reg(GENI_SE_DMA_PTR_L(*rx_dma), base, SE_DMA_RX_PTR_L);
|
||||
geni_write_reg(GENI_SE_DMA_PTR_H(*rx_dma), base, SE_DMA_RX_PTR_H);
|
||||
/* RX does not have EOT bit */
|
||||
geni_write_reg(0, base, SE_DMA_RX_ATTR);
|
||||
geni_write_reg(rx_len, base, SE_DMA_RX_LEN);
|
||||
geni_se_rx_dma_start(base, rx_len, rx_dma);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(geni_se_rx_dma_prep);
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
#include <linux/tty_flip.h>
|
||||
#include <linux/ioctl.h>
|
||||
#include <linux/pinctrl/consumer.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
|
||||
/* UART specific GENI registers */
|
||||
#define SE_UART_LOOPBACK_CFG (0x22C)
|
||||
|
|
@ -1076,7 +1077,6 @@ static void start_rx_sequencer(struct uart_port *uport)
|
|||
unsigned int geni_m_irq_en;
|
||||
unsigned int geni_status;
|
||||
struct msm_geni_serial_port *port = GET_DEV_PORT(uport);
|
||||
int ret;
|
||||
u32 geni_se_param = UART_PARAM_RFR_OPEN;
|
||||
|
||||
if (port->startup_in_progress)
|
||||
|
|
@ -1084,17 +1084,11 @@ static void start_rx_sequencer(struct uart_port *uport)
|
|||
|
||||
geni_status = geni_read_reg_nolog(uport->membase, SE_GENI_STATUS);
|
||||
if (geni_status & S_GENI_CMD_ACTIVE) {
|
||||
if (port->xfer_mode == SE_DMA && !port->rx_dma) {
|
||||
if (port->xfer_mode == SE_DMA) {
|
||||
IPC_LOG_MSG(port->ipc_log_misc,
|
||||
"%s: GENI: 0x%x\n", __func__, geni_status);
|
||||
ret = geni_se_rx_dma_prep(port->wrapper_dev,
|
||||
uport->membase, port->rx_buf, DMA_RX_BUF_SIZE,
|
||||
&port->rx_dma);
|
||||
if (ret) {
|
||||
IPC_LOG_MSG(port->ipc_log_misc,
|
||||
"%s: RX buff Fail %d\n", __func__, ret);
|
||||
goto exit_start_rx_sequencer;
|
||||
}
|
||||
geni_se_rx_dma_start(uport->membase, DMA_RX_BUF_SIZE,
|
||||
&port->rx_dma);
|
||||
}
|
||||
msm_geni_serial_stop_rx(uport);
|
||||
}
|
||||
|
|
@ -1116,21 +1110,14 @@ static void start_rx_sequencer(struct uart_port *uport)
|
|||
geni_write_reg_nolog(geni_m_irq_en, uport->membase,
|
||||
SE_GENI_M_IRQ_EN);
|
||||
} else if (port->xfer_mode == SE_DMA) {
|
||||
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);
|
||||
msm_geni_serial_stop_rx(uport);
|
||||
goto exit_start_rx_sequencer;
|
||||
}
|
||||
geni_se_rx_dma_start(uport->membase, DMA_RX_BUF_SIZE,
|
||||
&port->rx_dma);
|
||||
}
|
||||
/*
|
||||
* Ensure the writes to the secondary sequencer and interrupt enables
|
||||
* go through.
|
||||
*/
|
||||
mb();
|
||||
exit_start_rx_sequencer:
|
||||
geni_status = geni_read_reg_nolog(uport->membase, SE_GENI_STATUS);
|
||||
IPC_LOG_MSG(port->ipc_log_misc, "%s: 0x%x, dma_dbg:0x%x\n", __func__,
|
||||
geni_status, geni_read_reg(uport->membase, SE_DMA_DEBUG_REG0));
|
||||
|
|
@ -1257,12 +1244,9 @@ static void stop_rx_sequencer(struct uart_port *uport)
|
|||
msm_geni_serial_abort_rx(uport);
|
||||
}
|
||||
exit_rx_seq:
|
||||
if (port->xfer_mode == SE_DMA && port->rx_dma) {
|
||||
if (port->xfer_mode == SE_DMA && port->rx_dma)
|
||||
msm_geni_serial_rx_fsm_rst(uport);
|
||||
geni_se_rx_dma_unprep(port->wrapper_dev, port->rx_dma,
|
||||
DMA_RX_BUF_SIZE);
|
||||
port->rx_dma = (dma_addr_t)NULL;
|
||||
}
|
||||
|
||||
geni_status = geni_read_reg_nolog(uport->membase, SE_GENI_STATUS);
|
||||
IPC_LOG_MSG(port->ipc_log_misc, "%s: 0x%x\n", __func__, geni_status);
|
||||
}
|
||||
|
|
@ -1443,7 +1427,7 @@ static int msm_geni_serial_handle_dma_rx(struct uart_port *uport, bool drop_rx)
|
|||
struct msm_geni_serial_port *msm_port = GET_DEV_PORT(uport);
|
||||
unsigned int rx_bytes = 0;
|
||||
struct tty_port *tport;
|
||||
int ret;
|
||||
int ret = 0;
|
||||
unsigned int geni_status;
|
||||
|
||||
geni_status = geni_read_reg_nolog(uport->membase, SE_GENI_STATUS);
|
||||
|
|
@ -1451,16 +1435,13 @@ static int msm_geni_serial_handle_dma_rx(struct uart_port *uport, bool drop_rx)
|
|||
if (!(geni_status & S_GENI_CMD_ACTIVE))
|
||||
return 0;
|
||||
|
||||
geni_se_rx_dma_unprep(msm_port->wrapper_dev, msm_port->rx_dma,
|
||||
DMA_RX_BUF_SIZE);
|
||||
msm_port->rx_dma = (dma_addr_t)NULL;
|
||||
|
||||
rx_bytes = geni_read_reg_nolog(uport->membase, SE_DMA_RX_LEN_IN);
|
||||
if (unlikely(!msm_port->rx_buf)) {
|
||||
IPC_LOG_MSG(msm_port->ipc_log_rx, "%s: NULL Rx_buf\n",
|
||||
__func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
rx_bytes = geni_read_reg_nolog(uport->membase, SE_DMA_RX_LEN_IN);
|
||||
if (unlikely(!rx_bytes)) {
|
||||
IPC_LOG_MSG(msm_port->ipc_log_rx, "%s: Size %d\n",
|
||||
__func__, rx_bytes);
|
||||
|
|
@ -1482,10 +1463,9 @@ static int msm_geni_serial_handle_dma_rx(struct uart_port *uport, bool drop_rx)
|
|||
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)
|
||||
IPC_LOG_MSG(msm_port->ipc_log_rx, "%s: %d\n", __func__, ret);
|
||||
geni_se_rx_dma_start(uport->membase, DMA_RX_BUF_SIZE,
|
||||
&msm_port->rx_dma);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -1771,6 +1751,7 @@ static int msm_geni_serial_port_setup(struct uart_port *uport)
|
|||
int ret = 0;
|
||||
struct msm_geni_serial_port *msm_port = GET_DEV_PORT(uport);
|
||||
unsigned long cfg0, cfg1;
|
||||
dma_addr_t dma_address;
|
||||
unsigned int rxstale = DEFAULT_BITS_PER_CHAR * STALE_TIMEOUT;
|
||||
|
||||
set_rfr_wm(msm_port);
|
||||
|
|
@ -1796,14 +1777,15 @@ static int msm_geni_serial_port_setup(struct uart_port *uport)
|
|||
goto exit_portsetup;
|
||||
}
|
||||
|
||||
msm_port->rx_buf = devm_kzalloc(uport->dev, DMA_RX_BUF_SIZE,
|
||||
GFP_KERNEL);
|
||||
msm_port->rx_buf = dma_alloc_coherent(msm_port->wrapper_dev,
|
||||
DMA_RX_BUF_SIZE, &dma_address, GFP_KERNEL);
|
||||
if (!msm_port->rx_buf) {
|
||||
devm_kfree(uport->dev, msm_port->rx_fifo);
|
||||
msm_port->rx_fifo = NULL;
|
||||
ret = -ENOMEM;
|
||||
goto exit_portsetup;
|
||||
}
|
||||
msm_port->rx_dma = dma_address;
|
||||
} else {
|
||||
/*
|
||||
* Make an unconditional cancel on the main sequencer to reset
|
||||
|
|
@ -1825,12 +1807,12 @@ static int msm_geni_serial_port_setup(struct uart_port *uport)
|
|||
ret = geni_se_init(uport->membase, msm_port->rx_wm, msm_port->rx_rfr);
|
||||
if (ret) {
|
||||
dev_err(uport->dev, "%s: Fail\n", __func__);
|
||||
goto exit_portsetup;
|
||||
goto free_dma;
|
||||
}
|
||||
|
||||
ret = geni_se_select_mode(uport->membase, msm_port->xfer_mode);
|
||||
if (ret)
|
||||
goto exit_portsetup;
|
||||
goto free_dma;
|
||||
|
||||
msm_port->port_setup = true;
|
||||
/*
|
||||
|
|
@ -1838,6 +1820,14 @@ static int msm_geni_serial_port_setup(struct uart_port *uport)
|
|||
* framework.
|
||||
*/
|
||||
mb();
|
||||
|
||||
return 0;
|
||||
free_dma:
|
||||
if (msm_port->rx_dma) {
|
||||
dma_free_coherent(msm_port->wrapper_dev, DMA_RX_BUF_SIZE,
|
||||
msm_port->rx_buf, msm_port->rx_dma);
|
||||
msm_port->rx_dma = (dma_addr_t)NULL;
|
||||
}
|
||||
exit_portsetup:
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -2806,6 +2796,11 @@ static int msm_geni_serial_remove(struct platform_device *pdev)
|
|||
if (!uart_console(&port->uport))
|
||||
wakeup_source_unregister(port->geni_wake);
|
||||
uart_remove_one_port(drv, &port->uport);
|
||||
if (port->rx_dma) {
|
||||
dma_free_coherent(port->wrapper_dev, DMA_RX_BUF_SIZE,
|
||||
port->rx_buf, port->rx_dma);
|
||||
port->rx_dma = (dma_addr_t)NULL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _LINUX_MSM_GENI_SE
|
||||
|
|
@ -665,6 +665,19 @@ int geni_se_clk_freq_match(struct se_geni_rsc *rsc, unsigned long req_freq,
|
|||
int geni_se_tx_dma_prep(struct device *wrapper_dev, void __iomem *base,
|
||||
void *tx_buf, int tx_len, dma_addr_t *tx_dma);
|
||||
|
||||
/**
|
||||
* geni_se_rx_dma_start() - Prepare the Serial Engine registers for RX DMA
|
||||
transfers.
|
||||
* @base: Base address of the SE register block.
|
||||
* @rx_len: Length of the RX buffer.
|
||||
* @rx_dma: Pointer to store the mapped DMA address.
|
||||
*
|
||||
* This function is used to prepare the Serial Engine registers for DMA RX.
|
||||
*
|
||||
* Return: None.
|
||||
*/
|
||||
void geni_se_rx_dma_start(void __iomem *base, int rx_len, dma_addr_t *rx_dma);
|
||||
|
||||
/**
|
||||
* geni_se_rx_dma_prep() - Prepare the Serial Engine for RX DMA transfer
|
||||
* @wrapper_dev: QUPv3 Wrapper Device to which the TX buffer is mapped.
|
||||
|
|
@ -979,5 +992,10 @@ static void geni_se_dump_dbg_regs(struct se_geni_rsc *rsc, void __iomem *base,
|
|||
{
|
||||
}
|
||||
|
||||
static void geni_se_rx_dma_start(void __iomem *base, int rx_len,
|
||||
dma_addr_t *rx_dma)
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Reference in a new issue