spi: spi-msm-geni: Return error if setup transfer fails

setup_fifo_xfer/setup_gsi_xfer api may fail while transfer
preparation, return error to the client in such case instead
of advancing with the erroneous transfer to prevent unpredictable
transfer scenarios.

Change-Id: I559fbc1dd26248c639cd0f0e1844dafbada703ce
Signed-off-by: Mukesh Kumar Savaliya <msavaliy@codeaurora.org>
This commit is contained in:
Mukesh Kumar Savaliya 2020-08-11 15:12:42 +05:30
commit ff5005a866

View file

@ -1254,10 +1254,11 @@ static int spi_geni_unprepare_transfer_hardware(struct spi_master *spi)
return 0;
}
static void setup_fifo_xfer(struct spi_transfer *xfer,
static int setup_fifo_xfer(struct spi_transfer *xfer,
struct spi_geni_master *mas, u16 mode,
struct spi_master *spi)
{
int ret = 0;
u32 m_cmd = 0;
u32 m_param = 0;
u32 spi_tx_cfg = geni_read_reg(mas->base, SE_SPI_TRANS_CFG);
@ -1270,7 +1271,6 @@ static void setup_fifo_xfer(struct spi_transfer *xfer,
/* Speed and bits per word can be overridden per transfer */
if (xfer->speed_hz != mas->cur_speed_hz) {
int ret = 0;
u32 clk_sel = 0;
u32 m_clk_cfg = 0;
int idx = 0;
@ -1280,7 +1280,7 @@ static void setup_fifo_xfer(struct spi_transfer *xfer,
if (ret) {
dev_err(mas->dev, "%s:Err setting clks:%d\n",
__func__, ret);
return;
return ret;
}
mas->cur_speed_hz = xfer->speed_hz;
clk_sel |= (idx & CLK_SEL_MSK);
@ -1346,32 +1346,35 @@ static void setup_fifo_xfer(struct spi_transfer *xfer,
__func__, trans_len, xfer->len, spi_tx_cfg, m_cmd,
xfer->cs_change, mas->cur_xfer_mode);
if ((m_cmd & SPI_RX_ONLY) && (mas->cur_xfer_mode == SE_DMA)) {
int ret = 0;
ret = geni_se_rx_dma_prep(mas->wrapper_dev, mas->base,
xfer->rx_buf, xfer->len, &xfer->rx_dma);
if (ret)
if (ret) {
GENI_SE_ERR(mas->ipc, true, mas->dev,
"Failed to setup Rx dma %d\n", ret);
xfer->rx_dma = 0;
return ret;
}
}
if (m_cmd & SPI_TX_ONLY) {
if (mas->cur_xfer_mode == FIFO_MODE) {
geni_write_reg(mas->tx_wm, mas->base,
SE_GENI_TX_WATERMARK_REG);
} else if (mas->cur_xfer_mode == SE_DMA) {
int ret = 0;
ret = geni_se_tx_dma_prep(mas->wrapper_dev, mas->base,
(void *)xfer->tx_buf, xfer->len,
&xfer->tx_dma);
if (ret)
if (ret) {
GENI_SE_ERR(mas->ipc, true, mas->dev,
"Failed to setup tx dma %d\n", ret);
xfer->tx_dma = 0;
return ret;
}
}
}
/* Ensure all writes are done before the WM interrupt */
mb();
return ret;
}
static void handle_fifo_timeout(struct spi_geni_master *mas,
@ -1399,7 +1402,7 @@ static void handle_fifo_timeout(struct spi_geni_master *mas,
"Failed to cancel/abort m_cmd\n");
}
if (mas->cur_xfer_mode == SE_DMA) {
if (xfer->tx_buf) {
if (xfer->tx_buf && xfer->tx_dma) {
reinit_completion(&mas->xfer_done);
writel_relaxed(1, mas->base +
SE_DMA_TX_FSM_RST);
@ -1411,7 +1414,7 @@ static void handle_fifo_timeout(struct spi_geni_master *mas,
geni_se_tx_dma_unprep(mas->wrapper_dev,
xfer->tx_dma, xfer->len);
}
if (xfer->rx_buf) {
if (xfer->rx_buf && xfer->rx_dma) {
reinit_completion(&mas->xfer_done);
writel_relaxed(1, mas->base +
SE_DMA_RX_FSM_RST);
@ -1448,7 +1451,14 @@ static int spi_geni_transfer_one(struct spi_master *spi,
if (mas->cur_xfer_mode != GSI_DMA) {
reinit_completion(&mas->xfer_done);
setup_fifo_xfer(xfer, mas, slv->mode, spi);
ret = setup_fifo_xfer(xfer, mas, slv->mode, spi);
if (ret) {
GENI_SE_ERR(mas->ipc, true, mas->dev,
"setup_fifo_xfer failed: %d\n", ret);
mas->cur_xfer = NULL;
goto err_fifo_geni_transfer_one;
}
timeout = wait_for_completion_timeout(&mas->xfer_done,
msecs_to_jiffies(SPI_XFER_TIMEOUT_MS));
if (!timeout) {
@ -1477,7 +1487,13 @@ static int spi_geni_transfer_one(struct spi_master *spi,
reinit_completion(&mas->tx_cb);
reinit_completion(&mas->rx_cb);
setup_gsi_xfer(xfer, mas, slv, spi);
ret = setup_gsi_xfer(xfer, mas, slv, spi);
if (ret) {
GENI_SE_ERR(mas->ipc, true, mas->dev,
"setup_gsi_xfer failed: %d\n", ret);
mas->cur_xfer = NULL;
goto err_gsi_geni_transfer_one;
}
if ((mas->num_xfers >= NUM_SPI_XFER) ||
(list_is_last(&xfer->transfer_list,
&spi->cur_msg->transfers))) {