Commit fc9e0f71 authored by Mark Brown's avatar Mark Brown

spi: Only idle the message pump in the worker kthread

In order to avoid the situation where the kthread is waiting for another
context to make the hardware idle let the message pump know if it's being
called from the worker thread context and if it isn't then defer to the
worker thread instead of idling the hardware immediately. This will ensure
that if this situation happens we block rather than busy waiting.
Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent 0461a414
...@@ -875,8 +875,9 @@ void spi_finalize_current_transfer(struct spi_master *master) ...@@ -875,8 +875,9 @@ void spi_finalize_current_transfer(struct spi_master *master)
EXPORT_SYMBOL_GPL(spi_finalize_current_transfer); EXPORT_SYMBOL_GPL(spi_finalize_current_transfer);
/** /**
* spi_pump_messages - kthread work function which processes spi message queue * __spi_pump_messages - function which processes spi message queue
* @work: pointer to kthread work struct contained in the master struct * @master: master to process queue for
* @in_kthread: true if we are in the context of the message pump thread
* *
* This function checks if there is any spi message in the queue that * This function checks if there is any spi message in the queue that
* needs processing and if so call out to the driver to initialize hardware * needs processing and if so call out to the driver to initialize hardware
...@@ -886,10 +887,8 @@ EXPORT_SYMBOL_GPL(spi_finalize_current_transfer); ...@@ -886,10 +887,8 @@ EXPORT_SYMBOL_GPL(spi_finalize_current_transfer);
* inside spi_sync(); the queue extraction handling at the top of the * inside spi_sync(); the queue extraction handling at the top of the
* function should deal with this safely. * function should deal with this safely.
*/ */
static void spi_pump_messages(struct kthread_work *work) static void __spi_pump_messages(struct spi_master *master, bool in_kthread)
{ {
struct spi_master *master =
container_of(work, struct spi_master, pump_messages);
unsigned long flags; unsigned long flags;
bool was_busy = false; bool was_busy = false;
int ret; int ret;
...@@ -916,6 +915,15 @@ static void spi_pump_messages(struct kthread_work *work) ...@@ -916,6 +915,15 @@ static void spi_pump_messages(struct kthread_work *work)
spin_unlock_irqrestore(&master->queue_lock, flags); spin_unlock_irqrestore(&master->queue_lock, flags);
return; return;
} }
/* Only do teardown in the thread */
if (!in_kthread) {
queue_kthread_work(&master->kworker,
&master->pump_messages);
spin_unlock_irqrestore(&master->queue_lock, flags);
return;
}
master->busy = false; master->busy = false;
master->idling = true; master->idling = true;
spin_unlock_irqrestore(&master->queue_lock, flags); spin_unlock_irqrestore(&master->queue_lock, flags);
...@@ -1004,6 +1012,18 @@ static void spi_pump_messages(struct kthread_work *work) ...@@ -1004,6 +1012,18 @@ static void spi_pump_messages(struct kthread_work *work)
} }
} }
/**
* spi_pump_messages - kthread work function which processes spi message queue
* @work: pointer to kthread work struct contained in the master struct
*/
static void spi_pump_messages(struct kthread_work *work)
{
struct spi_master *master =
container_of(work, struct spi_master, pump_messages);
__spi_pump_messages(master, true);
}
static int spi_init_queue(struct spi_master *master) static int spi_init_queue(struct spi_master *master)
{ {
struct sched_param param = { .sched_priority = MAX_RT_PRIO - 1 }; struct sched_param param = { .sched_priority = MAX_RT_PRIO - 1 };
...@@ -2163,7 +2183,7 @@ static int __spi_sync(struct spi_device *spi, struct spi_message *message, ...@@ -2163,7 +2183,7 @@ static int __spi_sync(struct spi_device *spi, struct spi_message *message,
* can. * can.
*/ */
if (master->transfer == spi_queued_transfer) if (master->transfer == spi_queued_transfer)
spi_pump_messages(&master->pump_messages); __spi_pump_messages(master, false);
wait_for_completion(&done); wait_for_completion(&done);
status = message->status; status = message->status;
......
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