static int atmel_spi_next_xfer_dma_submit(struct spi_master *master,
struct spi_transfer *xfer,
u32 *plen)
- __must_hold(&as->lock)
{
struct atmel_spi *as = spi_master_get_devdata(master);
struct dma_chan *rxchan = master->dma_rx;
if (!rxchan || !txchan)
return -ENODEV;
- /* release lock for DMA operations */
- atmel_spi_unlock(as);
*plen = xfer->len;
rxchan->device->device_issue_pending(rxchan);
txchan->device->device_issue_pending(txchan);
- /* take back lock */
- atmel_spi_lock(as);
return 0;
err_dma:
spi_writel(as, IDR, SPI_BIT(OVRES));
atmel_spi_stop_dma(master);
err_exit:
- atmel_spi_lock(as);
return -ENOMEM;
}
/* Interrupt
*
- * No need for locking in this Interrupt handler: done_status is the
- * only information modified.
*/
static irqreturn_t
atmel_spi_pio_interrupt(int irq, void *dev_id)
unsigned long dma_timeout;
as = spi_master_get_devdata(master);
- /* This lock was orignally taken in atmel_spi_trasfer_one_message */
- atmel_spi_lock(as);
asd = spi->controller_state;
bits = (asd->csr >> 4) & 0xf;
reinit_completion(&as->xfer_completion);
if (as->use_pdc) {
+ atmel_spi_lock(as);
atmel_spi_pdc_next_xfer(master, xfer);
+ atmel_spi_unlock(as);
} else if (atmel_spi_use_dma(as, xfer)) {
len = as->current_remaining_bytes;
ret = atmel_spi_next_xfer_dma_submit(master,
as->current_remaining_bytes = 0;
}
} else {
+ atmel_spi_lock(as);
atmel_spi_next_xfer_pio(master, xfer);
+ atmel_spi_unlock(as);
}
- /* interrupts are disabled, so free the lock for schedule */
- atmel_spi_unlock(as);
dma_timeout = wait_for_completion_timeout(&as->xfer_completion,
SPI_DMA_TIMEOUT);
- atmel_spi_lock(as);
if (WARN_ON(dma_timeout == 0)) {
dev_err(&spi->dev, "spi transfer timeout\n");
as->done_status = -EIO;
if (as->use_pdc)
atmel_spi_disable_pdc_transfer(as);
- atmel_spi_unlock(as);
-
return as->done_status;
}