summaryrefslogtreecommitdiffstats
path: root/drivers/spi/spi.c
diff options
context:
space:
mode:
authorMark Brown <broonie@linaro.org>2013-10-05 01:23:12 +0200
committerMark Brown <broonie@linaro.org>2013-10-11 21:09:13 +0200
commit2841a5fc375e9c573d10b82db30fa8a4cc25301c (patch)
tree07f5051d922f46a8640e6b2221390bd7be48b309 /drivers/spi/spi.c
parentspi/trace: Trace length of SPI messages on completion (diff)
downloadlinux-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.c22
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);