diff options
author | Mark Brown <broonie@linaro.org> | 2013-10-05 01:23:12 +0200 |
---|---|---|
committer | Mark Brown <broonie@linaro.org> | 2013-10-11 21:09:13 +0200 |
commit | 2841a5fc375e9c573d10b82db30fa8a4cc25301c (patch) | |
tree | 07f5051d922f46a8640e6b2221390bd7be48b309 /drivers/spi/spi.c | |
parent | spi/trace: Trace length of SPI messages on completion (diff) | |
download | linux-2841a5fc375e9c573d10b82db30fa8a4cc25301c.tar.xz linux-2841a5fc375e9c573d10b82db30fa8a4cc25301c.zip |
spi: Provide per-message prepare and unprepare operations
Many SPI drivers perform setup and tear down on every message, usually
doing things like DMA mapping the message. Provide hooks for them to use
to provide such operations.
This is of limited value for drivers that implement transfer_one_message()
but will be of much greater utility with future factoring out of standard
implementations of that function.
Signed-off-by: Mark Brown <broonie@linaro.org>
Diffstat (limited to 'drivers/spi/spi.c')
-rw-r--r-- | drivers/spi/spi.c | 22 |
1 files changed, 22 insertions, 0 deletions
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 8bef0c9a7233..8a30c6b66a64 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -606,6 +606,18 @@ static void spi_pump_messages(struct kthread_work *work) trace_spi_message_start(master->cur_msg); + if (master->prepare_message) { + ret = master->prepare_message(master, master->cur_msg); + if (ret) { + dev_err(&master->dev, + "failed to prepare message: %d\n", ret); + master->cur_msg->status = ret; + spi_finalize_current_message(master); + return; + } + master->cur_msg_prepared = true; + } + ret = master->transfer_one_message(master, master->cur_msg); if (ret) { dev_err(&master->dev, @@ -687,6 +699,7 @@ void spi_finalize_current_message(struct spi_master *master) { struct spi_message *mesg; unsigned long flags; + int ret; spin_lock_irqsave(&master->queue_lock, flags); mesg = master->cur_msg; @@ -695,6 +708,15 @@ void spi_finalize_current_message(struct spi_master *master) queue_kthread_work(&master->kworker, &master->pump_messages); spin_unlock_irqrestore(&master->queue_lock, flags); + if (master->cur_msg_prepared && master->unprepare_message) { + ret = master->unprepare_message(master, mesg); + if (ret) { + dev_err(&master->dev, + "failed to unprepare message: %d\n", ret); + } + } + master->cur_msg_prepared = false; + mesg->state = NULL; if (mesg->complete) mesg->complete(mesg->context); |