Skip to contentSkip to conversation

spi/pl022: move device disable to workqueue thread

PATCH New Linus Walleij 4 participants 5 messages Nov 22, 2011 – Dec 7, 2011

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

PATCH 4/7 spi/pl022: move device disable to workqueue thread

From: Chris Blair <[email protected]>

Moves the disabling of the device and clocks to the same thread in which the device and clocks are enabled. This avoids SMP issues where the device can be enabled for a transfer by one thread and then disabled by the completion of the previous transfer in another thread.

---
ChangeLog v1->v2:
- Moved this patch before the block disable patch at request from Viresh.
- Insert blank line...

---
 drivers/spi/spi-pl022.c |   26 +++++++++++++++++---------
 1 files changed, 17 insertions(+), 9 deletions(-)
drivers/spi/spi-pl022.c +17 -9
index b4038f9..8cdf052 100644
@@ -512,8 +512,6 @@ static void giveback(struct pl022 *pl022)
 	msg->state = NULL;
 	if (msg->complete)
 		msg->complete(msg->context);
-	/* This message is completed, so let's turn off the clocks & power */
-	pm_runtime_put(&pl022->adev->dev);
 }
 
 /**
@@ -1509,14 +1507,19 @@ static void pump_messages(struct work_struct *work)
 	struct pl022 *pl022 =
 		container_of(work, struct pl022, pump_messages);
 	unsigned long flags;
+	bool was_busy = false;
 
 	/* Lock queue and check for queue work */
 	spin_lock_irqsave(&pl022->queue_lock, flags);
 	if (list_empty(&pl022->queue) || !pl022->running) {
+		if (pl022->busy) {
+			pm_runtime_put(&pl022->adev->dev);
+		}
 		pl022->busy = false;
 		spin_unlock_irqrestore(&pl022->queue_lock, flags);
 		return;
 	}
+
 	/* Make sure we are not already running a message */
 	if (pl022->cur_msg) {
 		spin_unlock_irqrestore(&pl022->queue_lock, flags);
@@ -1527,7 +1530,10 @@ static void pump_messages(struct work_struct *work)
 	    list_entry(pl022->queue.next, struct spi_message, queue);
 
 	list_del_init(&pl022->cur_msg->queue);
-	pl022->busy = true;
+	if (pl022->busy)
+		was_busy = true;
+	else
+		pl022->busy = true;
 	spin_unlock_irqrestore(&pl022->queue_lock, flags);
 
 	/* Initial message state */
@@ -1537,12 +1543,14 @@ static void pump_messages(struct work_struct *work)
 
 	/* Setup the SPI using the per chip configuration */
 	pl022->cur_chip = spi_get_ctldata(pl022->cur_msg->spi);
-	/*
-	 * We enable the core voltage and clocks here, then the clocks
-	 * and core will be disabled when giveback() is called in each method
-	 * (poll/interrupt/DMA)
-	 */
-	pm_runtime_get_sync(&pl022->adev->dev);
+	if (!was_busy)
+		/*
+		 * We enable the core voltage and clocks here, then the clocks
+		 * and core will be disabled when this workqueue is run again
+		 * and there is no more work to be done.
+		 */
+		pm_runtime_get_sync(&pl022->adev->dev);
+
 	restore_state(pl022);
 	flush(pl022);
 
Signature · 1 line
1.7.3.2
#1 lore raw

PATCH 4/7 spi/pl022: move device disable to workqueue thread

drivers/spi/spi-pl022.c static void pump_messages(struct work_struct *work) · line 1517

Quoted 4 lines · Linus WALLEIJ
drivers/spi/spi-pl022.c +3 -0
 	if (list_empty(&pl022->queue) || !pl022->running) {
+		if (pl022->busy) {
+			pm_runtime_put(&pl022->adev->dev);
+		}

We used to get warnings from checkpatch, for single line code inside {}. Don't we get them anymore?

Signature · 1 line
viresh
#2 lore raw

PATCH 4/7 spi/pl022: move device disable to workqueue thread

Quoted 8 lines · Viresh Kumar
Quoted 4 lines · Linus WALLEIJ

? ? ? if (list_empty(&pl022->queue) || !pl022->running) {
+ ? ? ? ? ? ? if (pl022->busy) {
+ ? ? ? ? ? ? ? ? ? ? pm_runtime_put(&pl022->adev->dev);
+ ? ? ? ? ? ? }

We used to get warnings from checkpatch, for single line code inside {}. Don't we get them anymore?

It's driven by heuristics, I think it only warns on the first level since elsewhere you may want braces for readability.

But I'll take it out when I add you Reviewed-by...

Linus

#3 lore raw

PATCH 4/7 spi/pl022: move device disable to workqueue thread

Hi Linus,

Quoted 7 lines · Linus Walleij
Quoted 6 lines · Viresh Kumar
Quoted 4 lines · Linus WALLEIJ

? ? ? if (list_empty(&pl022->queue) || !pl022->running) {
+ ? ? ? ? ? ? if (pl022->busy) {
+ ? ? ? ? ? ? ? ? ? ? pm_runtime_put(&pl022->adev->dev);
+ ? ? ? ? ? ? }

Quoted 7 lines
Quoted 2 lines

We used to get warnings from checkpatch, for single line code inside {}. Don't we get them anymore?

It's driven by heuristics, I think it only warns on the first level since elsewhere you may want braces for readability.

But I'll take it out when I add you Reviewed-by...

Does that imply you will send out a V3 of this series somewhen and I don't need to add this right now to the for-grant branch I am currently preparing?

Thanks,

Wolfram

Signature · 9 lines
Pengutronix e.K.                           | Wolfram Sang                |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 198 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20111207/b856cd69/attachment.sig>
#4 lore raw

PATCH 4/7 spi/pl022: move device disable to workqueue thread

Quoted 5 lines · Wolfram Sang
Quoted 1 line

But I'll take it out when I add you Reviewed-by...

Does that imply you will send out a V3 of this series somewhen and I don't need to add this right now to the for-grant branch I am currently preparing?

No I just added them to my branch and waited for Grant to get back online.

The patches and ACKs are accumulated on this branch:

git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-stericsson.git pl022

If you want to make a huge bundle to send to Grant, please pull this into your tree.

Thanks,
Linus Walleij