MLK-19112 gpu: imx: lcdif: change 'rpm_suspended' to be atomic counter
authorFancy Fang <chen.fang@nxp.com>
Thu, 2 Aug 2018 06:08:56 +0000 (14:08 +0800)
committerLeonard Crestez <leonard.crestez@nxp.com>
Wed, 17 Apr 2019 23:51:34 +0000 (02:51 +0300)
Change the 'rpm_suspended' field to be an atomic type from
boolean type to make it have the counting ability which can
help to detect and avoid runtime suspend and resume calls
mismatch caused problems.

Signed-off-by: Fancy Fang <chen.fang@nxp.com>
(cherry picked from commit dece6fbe51f9c0ea3cd42c52e1c174bd26ae70f1)
(cherry picked from commit 909a7d18608224861ef7a0aca6ba1e736a7570fa)

drivers/gpu/imx/lcdif/lcdif-common.c

index fd0d010..a5f4e8b 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
 #include <linux/regmap.h>
+#include <linux/types.h>
 #include <drm/drm_fourcc.h>
 #include <video/imx-lcdif.h>
 #include <video/videomode.h>
@@ -49,7 +50,7 @@ struct lcdif_soc {
        int irq;
        void __iomem *base;
        struct regmap *gpr;
-       bool rpm_suspended;
+       atomic_t rpm_suspended;
 
        struct clk *clk_pix;
        struct clk *clk_disp_axi;
@@ -612,8 +613,9 @@ static int imx_lcdif_probe(struct platform_device *pdev)
        lcdif->dev = dev;
        platform_set_drvdata(pdev, lcdif);
 
+       atomic_set(&lcdif->rpm_suspended, 0);
        pm_runtime_enable(dev);
-       lcdif->rpm_suspended = true;
+       atomic_inc(&lcdif->rpm_suspended);
 
        dev_dbg(dev, "%s: probe end\n", __func__);
 
@@ -653,15 +655,13 @@ static int imx_lcdif_runtime_suspend(struct device *dev)
 {
        struct lcdif_soc *lcdif = dev_get_drvdata(dev);
 
-       if (lcdif->rpm_suspended == true)
+       if (atomic_inc_return(&lcdif->rpm_suspended) > 1)
                return 0;
 
        lcdif_disable_clocks(lcdif);
 
        release_bus_freq(BUS_FREQ_HIGH);
 
-       lcdif->rpm_suspended = true;
-
        return 0;
 }
 
@@ -670,7 +670,12 @@ static int imx_lcdif_runtime_resume(struct device *dev)
        int ret = 0;
        struct lcdif_soc *lcdif = dev_get_drvdata(dev);
 
-       if (lcdif->rpm_suspended == false)
+       if (unlikely(!atomic_read(&lcdif->rpm_suspended))) {
+               dev_warn(lcdif->dev, "Unbalanced %s!\n", __func__);
+               return 0;
+       }
+
+       if (!atomic_dec_and_test(&lcdif->rpm_suspended))
                return 0;
 
        request_bus_freq(BUS_FREQ_HIGH);
@@ -687,8 +692,6 @@ static int imx_lcdif_runtime_resume(struct device *dev)
        /* Pull LCDIF out of reset */
        writel(0x0, lcdif->base + LCDIF_CTRL);
 
-       lcdif->rpm_suspended = false;
-
        return ret;
 }
 #endif