mirror of
git://nv-tegra.nvidia.com/linux-nvgpu.git
synced 2025-12-23 01:50:07 +03:00
gpu: nvgpu: cache gpu clk rate
Cache the rate used in clk_set_rate().
Return that cached rate on clk_get_rate(), don't read from hardware.
This cached rate is used to avoid duplicate requests to clk_set_rate().
Motivation is to support multiple governors for gpu clk.
Reading clock from hardware is unreliable in multi-governor situation.
Relying on hardware clock value could mislead the kernel gpu governor
in its scaling calculations.
Bug 2051688
Change-Id: I43fc056eea6f69fe0889c45640fcb892b658071c
Signed-off-by: Arun Kannan <akannan@nvidia.com>
(cherry picked from commit 7f819a9ba7)
Reviewed-on: https://git-master.nvidia.com/r/1662759
Reviewed-on: https://git-master.nvidia.com/r/1668919
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: svc-mobile-coverity <svc-mobile-coverity@nvidia.com>
GVS: Gerrit_Virtual_Submit
Reviewed-by: Terje Bergstrom <tbergstrom@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
This commit is contained in:
committed by
mobile promotions
parent
0e3181a5d7
commit
e9a6d179a4
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Linux clock support
|
* Linux clock support
|
||||||
*
|
*
|
||||||
* Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved.
|
* Copyright (c) 2017-2018, NVIDIA CORPORATION. All rights reserved.
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
* under the terms and conditions of the GNU General Public License,
|
* under the terms and conditions of the GNU General Public License,
|
||||||
@@ -34,9 +34,13 @@ static unsigned long nvgpu_linux_clk_get_rate(struct gk20a *g, u32 api_domain)
|
|||||||
switch (api_domain) {
|
switch (api_domain) {
|
||||||
case CTRL_CLK_DOMAIN_GPCCLK:
|
case CTRL_CLK_DOMAIN_GPCCLK:
|
||||||
if (g->clk.tegra_clk)
|
if (g->clk.tegra_clk)
|
||||||
ret = clk_get_rate(g->clk.tegra_clk);
|
ret = g->clk.cached_rate ?
|
||||||
|
g->clk.cached_rate :
|
||||||
|
clk_get_rate(g->clk.tegra_clk);
|
||||||
else
|
else
|
||||||
ret = clk_get_rate(platform->clk[0]);
|
ret = platform->cached_rate ?
|
||||||
|
platform->cached_rate :
|
||||||
|
clk_get_rate(platform->clk[0]);
|
||||||
break;
|
break;
|
||||||
case CTRL_CLK_DOMAIN_PWRCLK:
|
case CTRL_CLK_DOMAIN_PWRCLK:
|
||||||
ret = clk_get_rate(platform->clk[1]);
|
ret = clk_get_rate(platform->clk[1]);
|
||||||
@@ -58,10 +62,15 @@ static int nvgpu_linux_clk_set_rate(struct gk20a *g,
|
|||||||
|
|
||||||
switch (api_domain) {
|
switch (api_domain) {
|
||||||
case CTRL_CLK_DOMAIN_GPCCLK:
|
case CTRL_CLK_DOMAIN_GPCCLK:
|
||||||
if (g->clk.tegra_clk)
|
if (g->clk.tegra_clk) {
|
||||||
ret = clk_set_rate(g->clk.tegra_clk, rate);
|
ret = clk_set_rate(g->clk.tegra_clk, rate);
|
||||||
else
|
if (!ret)
|
||||||
|
g->clk.cached_rate = rate;
|
||||||
|
} else {
|
||||||
ret = clk_set_rate(platform->clk[0], rate);
|
ret = clk_set_rate(platform->clk[0], rate);
|
||||||
|
if (!ret)
|
||||||
|
platform->cached_rate = rate;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case CTRL_CLK_DOMAIN_PWRCLK:
|
case CTRL_CLK_DOMAIN_PWRCLK:
|
||||||
ret = clk_set_rate(platform->clk[1], rate);
|
ret = clk_set_rate(platform->clk[1], rate);
|
||||||
|
|||||||
@@ -256,6 +256,9 @@ struct gk20a_platform {
|
|||||||
|
|
||||||
/* stream id to use */
|
/* stream id to use */
|
||||||
u32 ltc_streamid;
|
u32 ltc_streamid;
|
||||||
|
|
||||||
|
/* scaling rate */
|
||||||
|
unsigned long cached_rate;
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline struct gk20a_platform *gk20a_get_platform(
|
static inline struct gk20a_platform *gk20a_get_platform(
|
||||||
|
|||||||
@@ -506,6 +506,8 @@ static int gk20a_tegra_get_clocks(struct device *dev)
|
|||||||
rate = clk_round_rate(c, rate);
|
rate = clk_round_rate(c, rate);
|
||||||
clk_set_rate(c, rate);
|
clk_set_rate(c, rate);
|
||||||
platform->clk[i] = c;
|
platform->clk[i] = c;
|
||||||
|
if (i == 0)
|
||||||
|
platform->cached_rate = rate;
|
||||||
}
|
}
|
||||||
platform->num_clks = i;
|
platform->num_clks = i;
|
||||||
|
|
||||||
|
|||||||
@@ -57,11 +57,13 @@ gp10b_freq_table[GP10B_MAX_SUPPORTED_FREQS / GP10B_FREQ_SELECT_STEP];
|
|||||||
|
|
||||||
#define EMC_BW_RATIO (TEGRA_GP10B_BW_PER_FREQ / TEGRA_DDR4_BW_PER_FREQ)
|
#define EMC_BW_RATIO (TEGRA_GP10B_BW_PER_FREQ / TEGRA_DDR4_BW_PER_FREQ)
|
||||||
|
|
||||||
|
#define GPCCLK_INIT_RATE 1000000000
|
||||||
|
|
||||||
static struct {
|
static struct {
|
||||||
char *name;
|
char *name;
|
||||||
unsigned long default_rate;
|
unsigned long default_rate;
|
||||||
} tegra_gp10b_clocks[] = {
|
} tegra_gp10b_clocks[] = {
|
||||||
{"gpu", 1000000000},
|
{"gpu", GPCCLK_INIT_RATE},
|
||||||
{"gpu_sys", 204000000} };
|
{"gpu_sys", 204000000} };
|
||||||
|
|
||||||
static void gr_gp10b_remove_sysfs(struct device *dev);
|
static void gr_gp10b_remove_sysfs(struct device *dev);
|
||||||
@@ -90,6 +92,8 @@ int gp10b_tegra_get_clocks(struct device *dev)
|
|||||||
} else {
|
} else {
|
||||||
clk_set_rate(c, rate);
|
clk_set_rate(c, rate);
|
||||||
platform->clk[i] = c;
|
platform->clk[i] = c;
|
||||||
|
if (i == 0)
|
||||||
|
platform->cached_rate = rate;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
platform->num_clks = i;
|
platform->num_clks = i;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2011 - 2017, NVIDIA CORPORATION. All rights reserved.
|
* Copyright (c) 2011 - 2018, NVIDIA CORPORATION. All rights reserved.
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
* copy of this software and associated documentation files (the "Software"),
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
@@ -96,6 +96,9 @@ struct clk_gk20a {
|
|||||||
#if defined(CONFIG_COMMON_CLK)
|
#if defined(CONFIG_COMMON_CLK)
|
||||||
struct clk *tegra_clk;
|
struct clk *tegra_clk;
|
||||||
struct clk_hw hw;
|
struct clk_hw hw;
|
||||||
|
|
||||||
|
/* scaling rate */
|
||||||
|
unsigned long cached_rate;
|
||||||
#endif
|
#endif
|
||||||
struct pll gpc_pll;
|
struct pll gpc_pll;
|
||||||
struct pll gpc_pll_last;
|
struct pll gpc_pll_last;
|
||||||
|
|||||||
Reference in New Issue
Block a user