From: Martin Sperl <kernel@xxxxxxxxxxxxxxxx> Right now the worker thread running spi_pump_message is always woken during spi_finalize_current_message. When spi_sync is running alone with no other spi devices connected to the bus the worker thread is woken during spi_finalize_current_message. This is totally unnecessary in the case that there is no message queued. This is less of a problem when the worker kthread is used to control the spi bus, but even there it is unnecessary and wasting CPU cycles. So we only enable the worker thread when the queue is not empty. For spi_sync transfers in a tight loop (say 40k messages/s) this avoids the penalty of waking the worker thread 40k times/s. On a rasperry pi 3 with 4 cores the results in 32% of a single core only to find out that there is nothing in the queue and it can go back to sleep. With this patch applied the spi-worker is not even woken one! I believe I have also seen situations where during a spi_sync loop the worker thread (triggered by the last message finished) is slightly faster and _wins_ the race to process the message, so we are actually running the kthread and letting it do some work... This is also no longer observed with this patch applied as. Signed-off-by: Martin Sperl <kernel@xxxxxxxxxxxxxxxx> --- More details: The "running in threaded mode" while it is supposed to run immediately can be seen by these temporarily exposed extra counters: ==> /sys/class/spi_master/spi0/statistics/pump_message <== 16250 ==> /sys/class/spi_master/spi0/statistics/pump_message_already_running <== 8093 ==> /sys/class/spi_master/spi0/statistics/pump_message_idling <== 0 ==> /sys/class/spi_master/spi0/statistics/pump_message_in_kthread <== 8121 So out of 16250 times that pump_message is called 8121 times the call was in kthread and 8093 times the message pump was already running. That means that a few times the kthread must have won the race and the non-kthread version lost or might even have waited in spin_lock_irqsave. Signed-off-by: Martin Sperl <kernel@xxxxxxxxxxxxxxxx> --- drivers/spi/spi.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 6ca59406b0b7..0f473d1b01f9 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -1416,7 +1416,9 @@ void spi_finalize_current_message(struct spi_controller *ctlr) spin_lock_irqsave(&ctlr->queue_lock, flags); ctlr->cur_msg = NULL; ctlr->cur_msg_prepared = false; - kthread_queue_work(&ctlr->kworker, &ctlr->pump_messages); + /* only wake message_pump if there is anything in the queue */ + if (!list_empty(&ctlr->queue)) + kthread_queue_work(&ctlr->kworker, &ctlr->pump_messages); spin_unlock_irqrestore(&ctlr->queue_lock, flags); trace_spi_message_done(mesg); -- 2.11.0