misc: tegra-profiler: fix possible deadlock
Igor Nabirushkin [Fri, 2 Sep 2016 15:08:26 +0000 (18:08 +0300)]
power_clk: fix possible deadlock in read_source - move
cpufreq_get call out of power_clk_source lock.

Bug 200224828

Change-Id: Ia06159ccf5c084840818917ca10dcd667c347650
Signed-off-by: Igor Nabirushkin <inabirushkin@nvidia.com>
Reviewed-on: http://git-master/r/1216914
(cherry picked from commit 2d9bc2aa4fb102cb3f4064524503d76905240504)
Reviewed-on: http://git-master/r/1251883
(cherry picked from commit 3e413f90129a50346ccf6510033ec1715c1fcba8)

drivers/misc/tegra-profiler/power_clk.c

index 7be48ef..01c4d44 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * drivers/misc/tegra-profiler/power_clk.c
  *
- * Copyright (c) 2013-2015, NVIDIA CORPORATION.  All rights reserved.
+ * Copyright (c) 2013-2016, NVIDIA CORPORATION.  All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -229,7 +229,7 @@ out_unlock:
 static void
 read_source(struct power_clk_source *s, int cpu)
 {
-       mutex_lock(&s->lock);
+       unsigned int value;
 
        switch (s->type) {
        case QUADD_POWER_CLK_CPU:
@@ -239,13 +239,18 @@ read_source(struct power_clk_source *s, int cpu)
                        break;
                }
 
-               s->data[cpu].value = cpufreq_get(cpu);
+               value = cpufreq_get(cpu);
+
+               mutex_lock(&s->lock);
+               s->data[cpu].value = value;
                pr_debug("QUADD_POWER_CLK_CPU, cpu: %d, value: %lu\n",
                         cpu, s->data[cpu].value);
+               mutex_unlock(&s->lock);
                break;
 
        case QUADD_POWER_CLK_GPU:
                /* update gpu frequency */
+               mutex_lock(&s->lock);
                s->clkp = clk_get_sys("gm20b", "gbus");
                if (!IS_ERR_OR_NULL(s->clkp)) {
                        s->data[0].value =
@@ -254,10 +259,12 @@ read_source(struct power_clk_source *s, int cpu)
                }
                pr_debug("QUADD_POWER_CLK_GPU, value: %lu\n",
                         s->data[0].value);
+               mutex_unlock(&s->lock);
                break;
 
        case QUADD_POWER_CLK_EMC:
                /* update emc frequency */
+               mutex_lock(&s->lock);
                s->clkp = clk_get_sys("cpu", "emc");
                if (!IS_ERR_OR_NULL(s->clkp)) {
                        s->data[0].value =
@@ -266,14 +273,13 @@ read_source(struct power_clk_source *s, int cpu)
                }
                pr_debug("QUADD_POWER_CLK_EMC, value: %lu\n",
                         s->data[0].value);
+               mutex_unlock(&s->lock);
                break;
 
        default:
                pr_err_once("error: invalid power_clk type\n");
                break;
        }
-
-       mutex_unlock(&s->lock);
 }
 
 static int