]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
HSI: omap_ssi_port: avoid calling runtime_pm_*_sync inside spinlock
authorSebastian Reichel <sre@kernel.org>
Fri, 17 Jun 2016 20:03:00 +0000 (22:03 +0200)
committerSebastian Reichel <sre@kernel.org>
Mon, 27 Jun 2016 22:39:39 +0000 (00:39 +0200)
runtime_pm_*_sync can block when irq_safe flag is removed
from omap-ssi driver, so it may not be called while a
spinlock is held.

Signed-off-by: Sebastian Reichel <sre@kernel.org>
Tested-by: Pavel Machek <pavel@ucw.cz>
drivers/hsi/controllers/omap_ssi_port.c

index f7ed59ba3b2c4d976625999d6349a32f894cc1dd..92064221dbabe1901cbc5db690601a5361c030f7 100644 (file)
@@ -767,13 +767,12 @@ static int ssi_release(struct hsi_client *cl)
        struct omap_ssi_port *omap_port = hsi_port_drvdata(port);
        struct hsi_controller *ssi = to_hsi_controller(port->device.parent);
 
-       spin_lock_bh(&omap_port->lock);
        pm_runtime_get_sync(omap_port->pdev);
+       spin_lock_bh(&omap_port->lock);
        /* Stop all the pending DMA requests for that client */
        ssi_cleanup_gdd(ssi, cl);
        /* Now cleanup all the queues */
        ssi_cleanup_queues(cl);
-       pm_runtime_put_sync(omap_port->pdev);
        /* If it is the last client of the port, do extra checks and cleanup */
        if (port->claimed <= 1) {
                /*
@@ -782,15 +781,16 @@ static int ssi_release(struct hsi_client *cl)
                 */
                if (test_and_clear_bit(SSI_WAKE_EN, &omap_port->flags))
                        pm_runtime_put_sync(omap_port->pdev);
-               pm_runtime_get_sync(omap_port->pdev);
+               pm_runtime_get(omap_port->pdev);
                /* Stop any SSI TX/RX without a client */
                ssi_set_port_mode(omap_port, SSI_MODE_SLEEP);
                omap_port->sst.mode = SSI_MODE_SLEEP;
                omap_port->ssr.mode = SSI_MODE_SLEEP;
-               pm_runtime_put_sync(omap_port->pdev);
+               pm_runtime_put(omap_port->pdev);
                WARN_ON(omap_port->wk_refcount != 0);
        }
        spin_unlock_bh(&omap_port->lock);
+       pm_runtime_put_sync(omap_port->pdev);
 
        return 0;
 }