Commit 5003bc6c authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'spi-fix-v4.6-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi

Pull spi fixes from Mark Brown:
 "A couple of driver specific fixes here that came in since the merge
  window plus one core fix for locking in cases where a client driver
  grabs a lock on the whole bus for an extended series of operations
  that was introduced by the changes to support accelerated flash
  operations"

* tag 'spi-fix-v4.6-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi:
  spi: rockchip: fix probe deferral handling
  spi: omap2-mcspi: fix dma transfer for vmalloced buffer
  spi: fix possible deadlock between internal bus locks and bus_lock_flag
  spi: imx: Fix possible NULL pointer deref
  spi: imx: only do necessary changes to ECSPIx_CONFIGREG
  spi: rockchip: Spelling s/divsor/divisor/
parents 1b5caa3e cb39f732
...@@ -211,11 +211,15 @@ static bool spi_imx_can_dma(struct spi_master *master, struct spi_device *spi, ...@@ -211,11 +211,15 @@ static bool spi_imx_can_dma(struct spi_master *master, struct spi_device *spi,
struct spi_transfer *transfer) struct spi_transfer *transfer)
{ {
struct spi_imx_data *spi_imx = spi_master_get_devdata(master); struct spi_imx_data *spi_imx = spi_master_get_devdata(master);
unsigned int bpw = transfer->bits_per_word; unsigned int bpw;
if (!master->dma_rx) if (!master->dma_rx)
return false; return false;
if (!transfer)
return false;
bpw = transfer->bits_per_word;
if (!bpw) if (!bpw)
bpw = spi->bits_per_word; bpw = spi->bits_per_word;
...@@ -333,8 +337,9 @@ static void __maybe_unused mx51_ecspi_trigger(struct spi_imx_data *spi_imx) ...@@ -333,8 +337,9 @@ static void __maybe_unused mx51_ecspi_trigger(struct spi_imx_data *spi_imx)
static int __maybe_unused mx51_ecspi_config(struct spi_imx_data *spi_imx, static int __maybe_unused mx51_ecspi_config(struct spi_imx_data *spi_imx,
struct spi_imx_config *config) struct spi_imx_config *config)
{ {
u32 ctrl = MX51_ECSPI_CTRL_ENABLE, cfg = 0; u32 ctrl = MX51_ECSPI_CTRL_ENABLE;
u32 clk = config->speed_hz, delay, reg; u32 clk = config->speed_hz, delay, reg;
u32 cfg = readl(spi_imx->base + MX51_ECSPI_CONFIG);
/* /*
* The hardware seems to have a race condition when changing modes. The * The hardware seems to have a race condition when changing modes. The
...@@ -358,13 +363,20 @@ static int __maybe_unused mx51_ecspi_config(struct spi_imx_data *spi_imx, ...@@ -358,13 +363,20 @@ static int __maybe_unused mx51_ecspi_config(struct spi_imx_data *spi_imx,
if (config->mode & SPI_CPHA) if (config->mode & SPI_CPHA)
cfg |= MX51_ECSPI_CONFIG_SCLKPHA(config->cs); cfg |= MX51_ECSPI_CONFIG_SCLKPHA(config->cs);
else
cfg &= ~MX51_ECSPI_CONFIG_SCLKPHA(config->cs);
if (config->mode & SPI_CPOL) { if (config->mode & SPI_CPOL) {
cfg |= MX51_ECSPI_CONFIG_SCLKPOL(config->cs); cfg |= MX51_ECSPI_CONFIG_SCLKPOL(config->cs);
cfg |= MX51_ECSPI_CONFIG_SCLKCTL(config->cs); cfg |= MX51_ECSPI_CONFIG_SCLKCTL(config->cs);
} else {
cfg &= ~MX51_ECSPI_CONFIG_SCLKPOL(config->cs);
cfg &= ~MX51_ECSPI_CONFIG_SCLKCTL(config->cs);
} }
if (config->mode & SPI_CS_HIGH) if (config->mode & SPI_CS_HIGH)
cfg |= MX51_ECSPI_CONFIG_SSBPOL(config->cs); cfg |= MX51_ECSPI_CONFIG_SSBPOL(config->cs);
else
cfg &= ~MX51_ECSPI_CONFIG_SSBPOL(config->cs);
if (spi_imx->usedma) if (spi_imx->usedma)
ctrl |= MX51_ECSPI_CTRL_SMC; ctrl |= MX51_ECSPI_CTRL_SMC;
......
...@@ -423,16 +423,12 @@ static void omap2_mcspi_tx_dma(struct spi_device *spi, ...@@ -423,16 +423,12 @@ static void omap2_mcspi_tx_dma(struct spi_device *spi,
if (mcspi_dma->dma_tx) { if (mcspi_dma->dma_tx) {
struct dma_async_tx_descriptor *tx; struct dma_async_tx_descriptor *tx;
struct scatterlist sg;
dmaengine_slave_config(mcspi_dma->dma_tx, &cfg); dmaengine_slave_config(mcspi_dma->dma_tx, &cfg);
sg_init_table(&sg, 1); tx = dmaengine_prep_slave_sg(mcspi_dma->dma_tx, xfer->tx_sg.sgl,
sg_dma_address(&sg) = xfer->tx_dma; xfer->tx_sg.nents, DMA_MEM_TO_DEV,
sg_dma_len(&sg) = xfer->len; DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
tx = dmaengine_prep_slave_sg(mcspi_dma->dma_tx, &sg, 1,
DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
if (tx) { if (tx) {
tx->callback = omap2_mcspi_tx_callback; tx->callback = omap2_mcspi_tx_callback;
tx->callback_param = spi; tx->callback_param = spi;
...@@ -478,20 +474,15 @@ omap2_mcspi_rx_dma(struct spi_device *spi, struct spi_transfer *xfer, ...@@ -478,20 +474,15 @@ omap2_mcspi_rx_dma(struct spi_device *spi, struct spi_transfer *xfer,
if (mcspi_dma->dma_rx) { if (mcspi_dma->dma_rx) {
struct dma_async_tx_descriptor *tx; struct dma_async_tx_descriptor *tx;
struct scatterlist sg;
dmaengine_slave_config(mcspi_dma->dma_rx, &cfg); dmaengine_slave_config(mcspi_dma->dma_rx, &cfg);
if ((l & OMAP2_MCSPI_CHCONF_TURBO) && mcspi->fifo_depth == 0) if ((l & OMAP2_MCSPI_CHCONF_TURBO) && mcspi->fifo_depth == 0)
dma_count -= es; dma_count -= es;
sg_init_table(&sg, 1); tx = dmaengine_prep_slave_sg(mcspi_dma->dma_rx, xfer->rx_sg.sgl,
sg_dma_address(&sg) = xfer->rx_dma; xfer->rx_sg.nents, DMA_DEV_TO_MEM,
sg_dma_len(&sg) = dma_count; DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
tx = dmaengine_prep_slave_sg(mcspi_dma->dma_rx, &sg, 1,
DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT |
DMA_CTRL_ACK);
if (tx) { if (tx) {
tx->callback = omap2_mcspi_rx_callback; tx->callback = omap2_mcspi_rx_callback;
tx->callback_param = spi; tx->callback_param = spi;
...@@ -505,8 +496,6 @@ omap2_mcspi_rx_dma(struct spi_device *spi, struct spi_transfer *xfer, ...@@ -505,8 +496,6 @@ omap2_mcspi_rx_dma(struct spi_device *spi, struct spi_transfer *xfer,
omap2_mcspi_set_dma_req(spi, 1, 1); omap2_mcspi_set_dma_req(spi, 1, 1);
wait_for_completion(&mcspi_dma->dma_rx_completion); wait_for_completion(&mcspi_dma->dma_rx_completion);
dma_unmap_single(mcspi->dev, xfer->rx_dma, count,
DMA_FROM_DEVICE);
if (mcspi->fifo_depth > 0) if (mcspi->fifo_depth > 0)
return count; return count;
...@@ -619,8 +608,6 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer) ...@@ -619,8 +608,6 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer)
if (tx != NULL) { if (tx != NULL) {
wait_for_completion(&mcspi_dma->dma_tx_completion); wait_for_completion(&mcspi_dma->dma_tx_completion);
dma_unmap_single(mcspi->dev, xfer->tx_dma, xfer->len,
DMA_TO_DEVICE);
if (mcspi->fifo_depth > 0) { if (mcspi->fifo_depth > 0) {
irqstat_reg = mcspi->base + OMAP2_MCSPI_IRQSTATUS; irqstat_reg = mcspi->base + OMAP2_MCSPI_IRQSTATUS;
...@@ -1087,6 +1074,16 @@ static void omap2_mcspi_cleanup(struct spi_device *spi) ...@@ -1087,6 +1074,16 @@ static void omap2_mcspi_cleanup(struct spi_device *spi)
gpio_free(spi->cs_gpio); gpio_free(spi->cs_gpio);
} }
static bool omap2_mcspi_can_dma(struct spi_master *master,
struct spi_device *spi,
struct spi_transfer *xfer)
{
if (xfer->len < DMA_MIN_BYTES)
return false;
return true;
}
static int omap2_mcspi_work_one(struct omap2_mcspi *mcspi, static int omap2_mcspi_work_one(struct omap2_mcspi *mcspi,
struct spi_device *spi, struct spi_transfer *t) struct spi_device *spi, struct spi_transfer *t)
{ {
...@@ -1268,32 +1265,6 @@ static int omap2_mcspi_transfer_one(struct spi_master *master, ...@@ -1268,32 +1265,6 @@ static int omap2_mcspi_transfer_one(struct spi_master *master,
return -EINVAL; return -EINVAL;
} }
if (len < DMA_MIN_BYTES)
goto skip_dma_map;
if (mcspi_dma->dma_tx && tx_buf != NULL) {
t->tx_dma = dma_map_single(mcspi->dev, (void *) tx_buf,
len, DMA_TO_DEVICE);
if (dma_mapping_error(mcspi->dev, t->tx_dma)) {
dev_dbg(mcspi->dev, "dma %cX %d bytes error\n",
'T', len);
return -EINVAL;
}
}
if (mcspi_dma->dma_rx && rx_buf != NULL) {
t->rx_dma = dma_map_single(mcspi->dev, rx_buf, t->len,
DMA_FROM_DEVICE);
if (dma_mapping_error(mcspi->dev, t->rx_dma)) {
dev_dbg(mcspi->dev, "dma %cX %d bytes error\n",
'R', len);
if (tx_buf != NULL)
dma_unmap_single(mcspi->dev, t->tx_dma,
len, DMA_TO_DEVICE);
return -EINVAL;
}
}
skip_dma_map:
return omap2_mcspi_work_one(mcspi, spi, t); return omap2_mcspi_work_one(mcspi, spi, t);
} }
...@@ -1377,6 +1348,7 @@ static int omap2_mcspi_probe(struct platform_device *pdev) ...@@ -1377,6 +1348,7 @@ static int omap2_mcspi_probe(struct platform_device *pdev)
master->transfer_one = omap2_mcspi_transfer_one; master->transfer_one = omap2_mcspi_transfer_one;
master->set_cs = omap2_mcspi_set_cs; master->set_cs = omap2_mcspi_set_cs;
master->cleanup = omap2_mcspi_cleanup; master->cleanup = omap2_mcspi_cleanup;
master->can_dma = omap2_mcspi_can_dma;
master->dev.of_node = node; master->dev.of_node = node;
master->max_speed_hz = OMAP2_MCSPI_MAX_FREQ; master->max_speed_hz = OMAP2_MCSPI_MAX_FREQ;
master->min_speed_hz = OMAP2_MCSPI_MAX_FREQ >> 15; master->min_speed_hz = OMAP2_MCSPI_MAX_FREQ >> 15;
......
...@@ -534,7 +534,7 @@ static void rockchip_spi_config(struct rockchip_spi *rs) ...@@ -534,7 +534,7 @@ static void rockchip_spi_config(struct rockchip_spi *rs)
if (WARN_ON(rs->speed > MAX_SCLK_OUT)) if (WARN_ON(rs->speed > MAX_SCLK_OUT))
rs->speed = MAX_SCLK_OUT; rs->speed = MAX_SCLK_OUT;
/* the minimum divsor is 2 */ /* the minimum divisor is 2 */
if (rs->max_freq < 2 * rs->speed) { if (rs->max_freq < 2 * rs->speed) {
clk_set_rate(rs->spiclk, 2 * rs->speed); clk_set_rate(rs->spiclk, 2 * rs->speed);
rs->max_freq = clk_get_rate(rs->spiclk); rs->max_freq = clk_get_rate(rs->spiclk);
...@@ -730,23 +730,27 @@ static int rockchip_spi_probe(struct platform_device *pdev) ...@@ -730,23 +730,27 @@ static int rockchip_spi_probe(struct platform_device *pdev)
master->transfer_one = rockchip_spi_transfer_one; master->transfer_one = rockchip_spi_transfer_one;
master->handle_err = rockchip_spi_handle_err; master->handle_err = rockchip_spi_handle_err;
rs->dma_tx.ch = dma_request_slave_channel(rs->dev, "tx"); rs->dma_tx.ch = dma_request_chan(rs->dev, "tx");
if (IS_ERR_OR_NULL(rs->dma_tx.ch)) { if (IS_ERR(rs->dma_tx.ch)) {
/* Check tx to see if we need defer probing driver */ /* Check tx to see if we need defer probing driver */
if (PTR_ERR(rs->dma_tx.ch) == -EPROBE_DEFER) { if (PTR_ERR(rs->dma_tx.ch) == -EPROBE_DEFER) {
ret = -EPROBE_DEFER; ret = -EPROBE_DEFER;
goto err_get_fifo_len; goto err_get_fifo_len;
} }
dev_warn(rs->dev, "Failed to request TX DMA channel\n"); dev_warn(rs->dev, "Failed to request TX DMA channel\n");
rs->dma_tx.ch = NULL;
} }
rs->dma_rx.ch = dma_request_slave_channel(rs->dev, "rx"); rs->dma_rx.ch = dma_request_chan(rs->dev, "rx");
if (!rs->dma_rx.ch) { if (IS_ERR(rs->dma_rx.ch)) {
if (rs->dma_tx.ch) { if (PTR_ERR(rs->dma_rx.ch) == -EPROBE_DEFER) {
dma_release_channel(rs->dma_tx.ch); dma_release_channel(rs->dma_tx.ch);
rs->dma_tx.ch = NULL; rs->dma_tx.ch = NULL;
ret = -EPROBE_DEFER;
goto err_get_fifo_len;
} }
dev_warn(rs->dev, "Failed to request RX DMA channel\n"); dev_warn(rs->dev, "Failed to request RX DMA channel\n");
rs->dma_rx.ch = NULL;
} }
if (rs->dma_tx.ch && rs->dma_rx.ch) { if (rs->dma_tx.ch && rs->dma_rx.ch) {
......
...@@ -1209,7 +1209,7 @@ static void spi_pump_messages(struct kthread_work *work) ...@@ -1209,7 +1209,7 @@ static void spi_pump_messages(struct kthread_work *work)
struct spi_master *master = struct spi_master *master =
container_of(work, struct spi_master, pump_messages); container_of(work, struct spi_master, pump_messages);
__spi_pump_messages(master, true, false); __spi_pump_messages(master, true, master->bus_lock_flag);
} }
static int spi_init_queue(struct spi_master *master) static int spi_init_queue(struct spi_master *master)
...@@ -2853,7 +2853,7 @@ static int __spi_sync(struct spi_device *spi, struct spi_message *message, ...@@ -2853,7 +2853,7 @@ static int __spi_sync(struct spi_device *spi, struct spi_message *message,
*/ */
int spi_sync(struct spi_device *spi, struct spi_message *message) int spi_sync(struct spi_device *spi, struct spi_message *message)
{ {
return __spi_sync(spi, message, 0); return __spi_sync(spi, message, spi->master->bus_lock_flag);
} }
EXPORT_SYMBOL_GPL(spi_sync); EXPORT_SYMBOL_GPL(spi_sync);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment