Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9a83e2dc authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm-geni-serial: Use dma_alloc_coherent to avoid dma map/unmap"

parents 48965637 3d714ef3
Loading
Loading
Loading
Loading
+31 −6
Original line number Diff line number Diff line
@@ -1260,6 +1260,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.
@@ -1285,12 +1314,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);
+32 −37
Original line number Diff line number Diff line
@@ -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)
@@ -1091,7 +1092,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)
@@ -1099,17 +1099,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,
			geni_se_rx_dma_start(uport->membase, 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;
			}
		}
		msm_geni_serial_stop_rx(uport);
	}
@@ -1131,21 +1125,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));
@@ -1272,12 +1259,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);
}
@@ -1467,16 +1451,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);
@@ -1498,10 +1479,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;
}

@@ -1787,6 +1767,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);
@@ -1812,14 +1793,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
@@ -1841,12 +1823,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;
	/*
@@ -1854,6 +1836,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;
}
@@ -2805,6 +2795,11 @@ static int msm_geni_serial_remove(struct platform_device *pdev)

	wakeup_source_trash(&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;
}

+19 −0
Original line number Diff line number Diff line
@@ -667,6 +667,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.
@@ -795,6 +808,7 @@ int geni_se_iommu_free_buf(struct device *wrapper_dev, dma_addr_t *iova,
 */
void geni_se_dump_dbg_regs(struct se_geni_rsc *rsc, void __iomem *base,
				void *ipc);

#else
static inline unsigned int geni_read_reg_nolog(void __iomem *base, int offset)
{
@@ -981,5 +995,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