[COMMON] media: scaler: fix possible clk enable after shutdown
authorCho KyongHo <pullip.cho@samsung.com>
Mon, 9 Jan 2017 08:29:12 +0000 (17:29 +0900)
committerSeungchul Kim <sc377.kim@samsung.com>
Mon, 28 May 2018 05:28:22 +0000 (14:28 +0900)
sc_shutdown() is called during system shutdown and it marks drvdata
that it is under shutdown state. However, a task is requested to be
processed after sc_shutdown() is called, sc_run_next_job() enables
the power and the clocks of Scaler even though the power domain is
already detached.

Change-Id: Ib90ac0d870a381a4e3a99455a749ff42ff0d5565
Signed-off-by: Cho KyongHo <pullip.cho@samsung.com>
drivers/media/platform/exynos/scaler/scaler-core.c

index a64587095de08f6e2a1aefdeb7c218b455e90538..fcc201035f3b8390a0d63be419b694be2c46c4bb 100644 (file)
@@ -2468,15 +2468,10 @@ static int sc_run_next_job(struct sc_dev *sc)
        unsigned int h_shift, v_shift;
        int ret;
 
-       ret = sc_power_clk_enable(sc);
-       if (ret)
-               return ret;
-
        spin_lock_irqsave(&sc->ctxlist_lock, flags);
 
        if (sc->current_ctx || list_empty(&sc->context_list)) {
                /* a job is currently being processed or no job is to run */
-               sc_clk_power_disable(sc);
                spin_unlock_irqrestore(&sc->ctxlist_lock, flags);
                return 0;
        }
@@ -2491,7 +2486,6 @@ static int sc_run_next_job(struct sc_dev *sc)
 
        if (test_bit(DEV_SUSPEND, &sc->state)) {
                clear_bit(DEV_RUN, &sc->state);
-               sc_clk_power_disable(sc);
                spin_unlock_irqrestore(&sc->ctxlist_lock, flags);
                return 0;
        }
@@ -2505,6 +2499,34 @@ static int sc_run_next_job(struct sc_dev *sc)
 
        spin_unlock_irqrestore(&sc->ctxlist_lock, flags);
 
+       ret = sc_power_clk_enable(sc);
+       if (ret) {
+               /*
+                * Failed to enable the power and the clock. Let's push the task
+                * again for the later retry.
+                */
+               spin_lock_irqsave(&sc->ctxlist_lock, flags);
+
+               list_add(&ctx->node, &sc->context_list);
+               sc->current_ctx = NULL;
+
+               clear_bit(CTX_RUN, &ctx->flags);
+
+               spin_unlock_irqrestore(&sc->ctxlist_lock, flags);
+
+               clear_bit(DEV_RUN, &sc->state);
+
+               /*
+                * V4L2 mem2mem assumes that the tasks in device_run() are
+                * always succeed in processing in H/W while m2m1shot accepts
+                * failure in device_run(). m2m1shot2 returns failure to the
+                * users if devce_run() fails. To prevent returning failure to
+                * users and losing a task to run, we should assume that
+                * processing a task always succeeds.
+                */
+               return 0;
+       }
+
        s_frame = &ctx->s_frame;
        d_frame = &ctx->d_frame;