[PATCH V1] spi: core: wake kworker only when there is a message in the queue

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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




[Index of Archives]     [Linux Kernel]     [Linux ARM (vger)]     [Linux ARM MSM]     [Linux Omap]     [Linux Arm]     [Linux Tegra]     [Fedora ARM]     [Linux for Samsung SOC]     [eCos]     [Linux Fastboot]     [Gcc Help]     [Git]     [DCCP]     [IETF Announce]     [Security]     [Linux MIPS]     [Yosemite Campsites]

  Powered by Linux