spi: topcliff-pch: Prevent usage of potentially stale DMA device
authorAndy Shevchenko <andriy.shevchenko@linux.intel.com>
Mon, 7 Mar 2022 17:37:40 +0000 (19:37 +0200)
committerMark Brown <broonie@kernel.org>
Tue, 8 Mar 2022 12:28:07 +0000 (12:28 +0000)
DMA device is expected to be available while SPI transfer is ongoing.

Prevent usage of potentially stale DMA device by keeping reference
count till the end of the transfer.

Fixes: 4d986ffa036a ("spi: add missing pci_dev_put() before return")
Reported-by: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Link: https://lore.kernel.org/r/20220307173740.80996-1-andriy.shevchenko@linux.intel.com
Signed-off-by: Mark Brown <broonie@kernel.org>
drivers/spi/spi-topcliff-pch.c

index 8e1cc34..dfaa1d7 100644 (file)
 static int use_dma = 1;
 
 struct pch_spi_dma_ctrl {
+       struct pci_dev          *dma_dev;
        struct dma_async_tx_descriptor  *desc_tx;
        struct dma_async_tx_descriptor  *desc_rx;
        struct pch_dma_slave            param_tx;
@@ -876,7 +877,6 @@ static void pch_spi_request_dma(struct pch_spi_data *data, int bpw)
        if (!chan) {
                dev_err(&data->master->dev,
                        "ERROR: dma_request_channel FAILS(Tx)\n");
-               data->use_dma = 0;
                goto out;
        }
        dma->chan_tx = chan;
@@ -893,13 +893,15 @@ static void pch_spi_request_dma(struct pch_spi_data *data, int bpw)
                        "ERROR: dma_request_channel FAILS(Rx)\n");
                dma_release_channel(dma->chan_tx);
                dma->chan_tx = NULL;
-               data->use_dma = 0;
                goto out;
        }
        dma->chan_rx = chan;
 
+       dma->dma_dev = dma_dev;
+       return;
 out:
        pci_dev_put(dma_dev);
+       data->use_dma = 0;
 }
 
 static void pch_spi_release_dma(struct pch_spi_data *data)
@@ -915,6 +917,8 @@ static void pch_spi_release_dma(struct pch_spi_data *data)
                dma_release_channel(dma->chan_rx);
                dma->chan_rx = NULL;
        }
+
+       pci_dev_put(dma->dma_dev);
 }
 
 static void pch_spi_handle_dma(struct pch_spi_data *data, int *bpw)