UPSTREAM: spi: rockchip: check return value of dmaengine_prep_slave_sg
authorShawn Lin <shawn.lin@rock-chips.com>
Wed, 9 Mar 2016 08:11:15 +0000 (16:11 +0800)
committerHuang, Tao <huangtao@rock-chips.com>
Thu, 16 Jun 2016 12:46:30 +0000 (20:46 +0800)
We should check return value of dmaengine_prep_slave_sg, otherwise
we take risk of null pointer.

Change-Id: I2cc468563d630169f314e353d835ad33091c0d3c
Signed-off-by: Shawn Lin <shawn.lin@rock-chips.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
Signed-off-by: Caesar Wang <wxt@rock-chips.com>
(cherry picked from git.kernel.org next/linux-next.git master
 commit ea98491133439773b69345eb9a314fc5f15e07a4)

drivers/spi/spi-rockchip.c

index 7f121e679a33dd0628734ea5e9834a4b2d9f9c24..b8a462b0ae566ed37b5439d3050676dc73ceab41 100644 (file)
@@ -436,7 +436,7 @@ static void rockchip_spi_dma_txcb(void *data)
        spin_unlock_irqrestore(&rs->lock, flags);
 }
 
-static void rockchip_spi_prepare_dma(struct rockchip_spi *rs)
+static int rockchip_spi_prepare_dma(struct rockchip_spi *rs)
 {
        unsigned long flags;
        struct dma_slave_config rxconf, txconf;
@@ -459,6 +459,8 @@ static void rockchip_spi_prepare_dma(struct rockchip_spi *rs)
                                rs->dma_rx.ch,
                                rs->rx_sg.sgl, rs->rx_sg.nents,
                                rs->dma_rx.direction, DMA_PREP_INTERRUPT);
+               if (!rxdesc)
+                       return -EINVAL;
 
                rxdesc->callback = rockchip_spi_dma_rxcb;
                rxdesc->callback_param = rs;
@@ -476,6 +478,11 @@ static void rockchip_spi_prepare_dma(struct rockchip_spi *rs)
                                rs->dma_tx.ch,
                                rs->tx_sg.sgl, rs->tx_sg.nents,
                                rs->dma_tx.direction, DMA_PREP_INTERRUPT);
+               if (!txdesc) {
+                       if (rxdesc)
+                               dmaengine_terminate_sync(rs->dma_rx.ch);
+                       return -EINVAL;
+               }
 
                txdesc->callback = rockchip_spi_dma_txcb;
                txdesc->callback_param = rs;
@@ -497,6 +504,8 @@ static void rockchip_spi_prepare_dma(struct rockchip_spi *rs)
                dmaengine_submit(txdesc);
                dma_async_issue_pending(rs->dma_tx.ch);
        }
+
+       return 0;
 }
 
 static void rockchip_spi_config(struct rockchip_spi *rs)
@@ -610,12 +619,12 @@ static int rockchip_spi_transfer_one(
        if (rs->use_dma) {
                if (rs->tmode == CR0_XFM_RO) {
                        /* rx: dma must be prepared first */
-                       rockchip_spi_prepare_dma(rs);
+                       ret = rockchip_spi_prepare_dma(rs);
                        spi_enable_chip(rs, 1);
                } else {
                        /* tx or tr: spi must be enabled first */
                        spi_enable_chip(rs, 1);
-                       rockchip_spi_prepare_dma(rs);
+                       ret = rockchip_spi_prepare_dma(rs);
                }
        } else {
                spi_enable_chip(rs, 1);