unsigned long flags;
        int ret;
 
+       /* Take the IO mutex */
+       mutex_lock(&ctlr->io_mutex);
+
        /* Lock queue */
        spin_lock_irqsave(&ctlr->queue_lock, flags);
 
        /* Make sure we are not already running a message */
        if (ctlr->cur_msg) {
                spin_unlock_irqrestore(&ctlr->queue_lock, flags);
-               return;
+               goto out_unlock;
        }
 
        /* If another context is idling the device then defer */
        if (ctlr->idling) {
                kthread_queue_work(ctlr->kworker, &ctlr->pump_messages);
                spin_unlock_irqrestore(&ctlr->queue_lock, flags);
-               return;
+               goto out_unlock;
        }
 
        /* Check if the queue is idle */
        if (list_empty(&ctlr->queue) || !ctlr->running) {
                if (!ctlr->busy) {
                        spin_unlock_irqrestore(&ctlr->queue_lock, flags);
-                       return;
+                       goto out_unlock;
                }
 
                /* Defer any non-atomic teardown to the thread */
                                                   &ctlr->pump_messages);
                        }
                        spin_unlock_irqrestore(&ctlr->queue_lock, flags);
-                       return;
+                       goto out_unlock;
                }
 
                ctlr->busy = false;
                ctlr->idling = false;
                ctlr->queue_empty = true;
                spin_unlock_irqrestore(&ctlr->queue_lock, flags);
-               return;
+               goto out_unlock;
        }
 
        /* Extract head of queue */
                ctlr->busy = true;
        spin_unlock_irqrestore(&ctlr->queue_lock, flags);
 
-       mutex_lock(&ctlr->io_mutex);
        ret = __spi_pump_transfer_message(ctlr, msg, was_busy);
        mutex_unlock(&ctlr->io_mutex);
 
        /* Prod the scheduler in case transfer_one() was busy waiting */
        if (!ret)
                cond_resched();
+       return;
+
+out_unlock:
+       mutex_unlock(&ctlr->io_mutex);
 }
 
 /**