diff options
author | Jeremy Ho <jeremyh@nvidia.com> | 2019-07-02 04:43:17 -0400 |
---|---|---|
committer | mobile promotions <svcmobile_promotions@nvidia.com> | 2019-07-16 09:12:03 -0400 |
commit | 42c2bdfb9f1afed4b22f74cb635db52d5f3e7cd0 (patch) | |
tree | 72ee74708ebc835bca06aa1a38d023d8f060f098 | |
parent | 00b41b85389fe08be780d0e6134e9e891ea65399 (diff) |
gpu: nvgpu: remove reversed ordering for deadlock
In some cases, we would get deadlock issue due to there are two locks
acquisition on common clk driver's lock and nvgpu driver's locks. At
the bug, inconsistent lock ordering problem will come with one thread
gets "nvgpu lock -> clk lock" and the other thread gets "clk lock ->
nvgpu lock".
Slove the latter path with one-time initializing clk_parent entry
and use cached data afterward.
Bug 2555115
Change-Id: I31c5c2728f406307e7cfd4e555f4db0c163234d8
Signed-off-by: Jeremy Ho <jeremyh@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/2146727
Reviewed-by: Automatic_Commit_Validation_User
GVS: Gerrit_Virtual_Submit
Reviewed-by: Aleksandr Frid <afrid@nvidia.com>
Reviewed-by: Bibek Basu <bbasu@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/clk_gk20a.h | 1 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/os/linux/clk.c | 6 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/os/linux/platform_gk20a_tegra.c | 11 |
3 files changed, 14 insertions, 4 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/clk_gk20a.h b/drivers/gpu/nvgpu/gk20a/clk_gk20a.h index 03aa6ab7..b8ec9420 100644 --- a/drivers/gpu/nvgpu/gk20a/clk_gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/clk_gk20a.h | |||
@@ -95,6 +95,7 @@ struct clk_gk20a { | |||
95 | struct gk20a *g; | 95 | struct gk20a *g; |
96 | #if defined(CONFIG_COMMON_CLK) | 96 | #if defined(CONFIG_COMMON_CLK) |
97 | struct clk *tegra_clk; | 97 | struct clk *tegra_clk; |
98 | struct clk *tegra_clk_parent; | ||
98 | struct clk_hw hw; | 99 | struct clk_hw hw; |
99 | #endif | 100 | #endif |
100 | struct pll gpc_pll; | 101 | struct pll gpc_pll; |
diff --git a/drivers/gpu/nvgpu/os/linux/clk.c b/drivers/gpu/nvgpu/os/linux/clk.c index 6575a037..471f2aef 100644 --- a/drivers/gpu/nvgpu/os/linux/clk.c +++ b/drivers/gpu/nvgpu/os/linux/clk.c | |||
@@ -90,7 +90,7 @@ static unsigned long nvgpu_linux_get_fmax_at_vmin_safe(struct gk20a *g) | |||
90 | */ | 90 | */ |
91 | if (g->clk.tegra_clk) | 91 | if (g->clk.tegra_clk) |
92 | return tegra_dvfs_get_fmax_at_vmin_safe_t( | 92 | return tegra_dvfs_get_fmax_at_vmin_safe_t( |
93 | clk_get_parent(g->clk.tegra_clk)); | 93 | g->clk.tegra_clk_parent); |
94 | 94 | ||
95 | if (platform->maxmin_clk_id) | 95 | if (platform->maxmin_clk_id) |
96 | return tegra_bpmp_dvfs_get_fmax_at_vmin( | 96 | return tegra_bpmp_dvfs_get_fmax_at_vmin( |
@@ -116,7 +116,7 @@ static int nvgpu_linux_predict_mv_at_hz_cur_tfloor(struct clk_gk20a *clk, | |||
116 | unsigned long rate) | 116 | unsigned long rate) |
117 | { | 117 | { |
118 | return tegra_dvfs_predict_mv_at_hz_cur_tfloor( | 118 | return tegra_dvfs_predict_mv_at_hz_cur_tfloor( |
119 | clk_get_parent(clk->tegra_clk), rate); | 119 | clk->tegra_clk_parent, rate); |
120 | } | 120 | } |
121 | 121 | ||
122 | static unsigned long nvgpu_linux_get_maxrate(struct gk20a *g, u32 api_domain) | 122 | static unsigned long nvgpu_linux_get_maxrate(struct gk20a *g, u32 api_domain) |
@@ -125,7 +125,7 @@ static unsigned long nvgpu_linux_get_maxrate(struct gk20a *g, u32 api_domain) | |||
125 | 125 | ||
126 | switch (api_domain) { | 126 | switch (api_domain) { |
127 | case CTRL_CLK_DOMAIN_GPCCLK: | 127 | case CTRL_CLK_DOMAIN_GPCCLK: |
128 | ret = tegra_dvfs_get_maxrate(clk_get_parent(g->clk.tegra_clk)); | 128 | ret = tegra_dvfs_get_maxrate(g->clk.tegra_clk_parent); |
129 | break; | 129 | break; |
130 | default: | 130 | default: |
131 | nvgpu_err(g, "unknown clock: %u", api_domain); | 131 | nvgpu_err(g, "unknown clock: %u", api_domain); |
diff --git a/drivers/gpu/nvgpu/os/linux/platform_gk20a_tegra.c b/drivers/gpu/nvgpu/os/linux/platform_gk20a_tegra.c index 6a453096..0977e63a 100644 --- a/drivers/gpu/nvgpu/os/linux/platform_gk20a_tegra.c +++ b/drivers/gpu/nvgpu/os/linux/platform_gk20a_tegra.c | |||
@@ -649,7 +649,7 @@ int gk20a_tegra_init_secure_alloc(struct gk20a_platform *platform) | |||
649 | static struct clk *gk20a_clk_get(struct gk20a *g) | 649 | static struct clk *gk20a_clk_get(struct gk20a *g) |
650 | { | 650 | { |
651 | if (!g->clk.tegra_clk) { | 651 | if (!g->clk.tegra_clk) { |
652 | struct clk *clk; | 652 | struct clk *clk, *clk_parent; |
653 | char clk_dev_id[32]; | 653 | char clk_dev_id[32]; |
654 | struct device *dev = dev_from_gk20a(g); | 654 | struct device *dev = dev_from_gk20a(g); |
655 | 655 | ||
@@ -661,7 +661,16 @@ static struct clk *gk20a_clk_get(struct gk20a *g) | |||
661 | clk_dev_id); | 661 | clk_dev_id); |
662 | return NULL; | 662 | return NULL; |
663 | } | 663 | } |
664 | |||
665 | clk_parent = clk_get_parent(clk); | ||
666 | if (IS_ERR_OR_NULL(clk_parent)) { | ||
667 | nvgpu_err(g, "fail to get tegra gpu clk parent%s/gpu\n", | ||
668 | clk_dev_id); | ||
669 | return NULL; | ||
670 | } | ||
671 | |||
664 | g->clk.tegra_clk = clk; | 672 | g->clk.tegra_clk = clk; |
673 | g->clk.tegra_clk_parent = clk_parent; | ||
665 | } | 674 | } |
666 | 675 | ||
667 | return g->clk.tegra_clk; | 676 | return g->clk.tegra_clk; |