aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/spi
diff options
context:
space:
mode:
authorChris Blair <chris.blair@stericsson.com>2011-11-04 03:43:41 -0400
committerLinus Walleij <linus.walleij@linaro.org>2011-12-01 11:16:08 -0500
commitd4b6af2e0e29278f2353c7c8721ddf2f2446414f (patch)
tree4b900739272b0072c0a9057760de0a928c6c8962 /drivers/spi
parent4ca9fb46d8045b2473d608cd9e4580c6e0f7d5e0 (diff)
spi/pl022: move device disable to workqueue thread
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. Reviewed-by: Viresh Kumar <viresh.kumar@st.com> Signed-off-by: Chris Blair <chris.blair@stericsson.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'drivers/spi')
-rw-r--r--drivers/spi/spi-pl022.c25
1 files changed, 16 insertions, 9 deletions
diff --git a/drivers/spi/spi-pl022.c b/drivers/spi/spi-pl022.c
index b4038f97f6b0..d165c0bfcab5 100644
--- a/drivers/spi/spi-pl022.c
+++ b/drivers/spi/spi-pl022.c
@@ -512,8 +512,6 @@ static void giveback(struct pl022 *pl022)
512 msg->state = NULL; 512 msg->state = NULL;
513 if (msg->complete) 513 if (msg->complete)
514 msg->complete(msg->context); 514 msg->complete(msg->context);
515 /* This message is completed, so let's turn off the clocks & power */
516 pm_runtime_put(&pl022->adev->dev);
517} 515}
518 516
519/** 517/**
@@ -1509,14 +1507,18 @@ static void pump_messages(struct work_struct *work)
1509 struct pl022 *pl022 = 1507 struct pl022 *pl022 =
1510 container_of(work, struct pl022, pump_messages); 1508 container_of(work, struct pl022, pump_messages);
1511 unsigned long flags; 1509 unsigned long flags;
1510 bool was_busy = false;
1512 1511
1513 /* Lock queue and check for queue work */ 1512 /* Lock queue and check for queue work */
1514 spin_lock_irqsave(&pl022->queue_lock, flags); 1513 spin_lock_irqsave(&pl022->queue_lock, flags);
1515 if (list_empty(&pl022->queue) || !pl022->running) { 1514 if (list_empty(&pl022->queue) || !pl022->running) {
1515 if (pl022->busy)
1516 pm_runtime_put(&pl022->adev->dev);
1516 pl022->busy = false; 1517 pl022->busy = false;
1517 spin_unlock_irqrestore(&pl022->queue_lock, flags); 1518 spin_unlock_irqrestore(&pl022->queue_lock, flags);
1518 return; 1519 return;
1519 } 1520 }
1521
1520 /* Make sure we are not already running a message */ 1522 /* Make sure we are not already running a message */
1521 if (pl022->cur_msg) { 1523 if (pl022->cur_msg) {
1522 spin_unlock_irqrestore(&pl022->queue_lock, flags); 1524 spin_unlock_irqrestore(&pl022->queue_lock, flags);
@@ -1527,7 +1529,10 @@ static void pump_messages(struct work_struct *work)
1527 list_entry(pl022->queue.next, struct spi_message, queue); 1529 list_entry(pl022->queue.next, struct spi_message, queue);
1528 1530
1529 list_del_init(&pl022->cur_msg->queue); 1531 list_del_init(&pl022->cur_msg->queue);
1530 pl022->busy = true; 1532 if (pl022->busy)
1533 was_busy = true;
1534 else
1535 pl022->busy = true;
1531 spin_unlock_irqrestore(&pl022->queue_lock, flags); 1536 spin_unlock_irqrestore(&pl022->queue_lock, flags);
1532 1537
1533 /* Initial message state */ 1538 /* Initial message state */
@@ -1537,12 +1542,14 @@ static void pump_messages(struct work_struct *work)
1537 1542
1538 /* Setup the SPI using the per chip configuration */ 1543 /* Setup the SPI using the per chip configuration */
1539 pl022->cur_chip = spi_get_ctldata(pl022->cur_msg->spi); 1544 pl022->cur_chip = spi_get_ctldata(pl022->cur_msg->spi);
1540 /* 1545 if (!was_busy)
1541 * We enable the core voltage and clocks here, then the clocks 1546 /*
1542 * and core will be disabled when giveback() is called in each method 1547 * We enable the core voltage and clocks here, then the clocks
1543 * (poll/interrupt/DMA) 1548 * and core will be disabled when this workqueue is run again
1544 */ 1549 * and there is no more work to be done.
1545 pm_runtime_get_sync(&pl022->adev->dev); 1550 */
1551 pm_runtime_get_sync(&pl022->adev->dev);
1552
1546 restore_state(pl022); 1553 restore_state(pl022);
1547 flush(pl022); 1554 flush(pl022);
1548 1555