Re: [Nouveau] [PATCH v4 15/37] clk: allow boosting only when NvBoost is set
On 18/04/16 22:13, Karol Herbst wrote: 0: base clock from the vbios is max clock 1: boost only to boost clock from the vbios (default) As commented upon on IRC, I would prefer us to play it super safe and stick to the base clock until we have power monitoring working, at which point we may make 1 the default. Please change it to keep my R-b :) 2: boost to max clock available v2: moved into nvkm_cstate_valid v4: check the existence of the clocks before limiting Signed-off-by: Karol Herbst Reviewed-by: Martin Peres --- drm/nouveau/include/nvkm/subdev/clk.h | 9 - drm/nouveau/nvkm/subdev/clk/base.c| 33 - drm/nouveau/nvkm/subdev/clk/gf100.c | 2 +- drm/nouveau/nvkm/subdev/clk/gk104.c | 2 +- 4 files changed, 42 insertions(+), 4 deletions(-) diff --git a/drm/nouveau/include/nvkm/subdev/clk.h b/drm/nouveau/include/nvkm/subdev/clk.h index 6226f0d..99ee05c 100644 --- a/drm/nouveau/include/nvkm/subdev/clk.h +++ b/drm/nouveau/include/nvkm/subdev/clk.h @@ -68,7 +68,8 @@ struct nvkm_pstate { struct nvkm_domain { enum nv_clk_src name; u8 bios; /* 0xff for none */ -#define NVKM_CLK_DOM_FLAG_CORE 0x01 +#define NVKM_CLK_DOM_FLAG_CORE0x01 +#define NVKM_CLK_DOM_FLAG_BASECLK 0x02 u8 flags; const char *mname; int mdiv; @@ -98,6 +99,12 @@ struct nvkm_clk { int dstate; /* display adjustment (min+) */ bool allow_reclock; +#define NVKM_CLK_BOOST_NONE 0x0 +#define NVKM_CLK_BOOST_AVG 0x1 +#define NVKM_CLK_BOOST_FULL 0x2 + u8 boost_mode; + u32 base_khz; + u32 boost_khz; /*XXX: die, these are here *only* to support the completely * bat-shit insane what-was-nouveau_hw.c code diff --git a/drm/nouveau/nvkm/subdev/clk/base.c b/drm/nouveau/nvkm/subdev/clk/base.c index 21f6369..a9a3666 100644 --- a/drm/nouveau/nvkm/subdev/clk/base.c +++ b/drm/nouveau/nvkm/subdev/clk/base.c @@ -24,6 +24,7 @@ #include "priv.h" #include +#include #include #include #include @@ -77,9 +78,25 @@ nvkm_clk_adjust(struct nvkm_clk *clk, bool adjust, static bool nvkm_cstate_valid(struct nvkm_clk *clk, struct nvkm_cstate *cstate, u32 max_volt, int temp) { + const struct nvkm_domain *domain = clk->domains; struct nvkm_volt *volt = clk->subdev.device->volt; int voltage; + while (domain && domain->name != nv_clk_src_max) { + if (domain->flags & NVKM_CLK_DOM_FLAG_BASECLK) { + u32 freq = cstate->domain[domain->name]; + switch (clk->boost_mode) { + case NVKM_CLK_BOOST_NONE: + if (clk->base_khz && freq > clk->base_khz) + return false; + case NVKM_CLK_BOOST_AVG: + if (clk->boost_khz && freq > clk->boost_khz) + return false; + } + } + domain++; + } + if (!volt) return true; @@ -641,10 +658,24 @@ int nvkm_clk_ctor(const struct nvkm_clk_func *func, struct nvkm_device *device, int index, bool allow_reclock, struct nvkm_clk *clk) { + struct nvkm_subdev *subdev = &clk->subdev; + struct nvkm_bios *bios = device->bios; int ret, idx, arglen; const char *mode; + struct nvbios_baseclk_header h; + + nvkm_subdev_ctor(&nvkm_clk, device, index, subdev); + + clk->boost_mode = nvkm_longopt(device->cfgopt, "NvBoost", + NVKM_CLK_BOOST_AVG); + if (bios && !nvbios_baseclock_parse(bios, &h)) { + struct nvbios_baseclk_entry base, boost; + if (!nvbios_baseclock_entry(bios, &h, h.boost_id, &boost)) + clk->boost_khz = boost.clock_mhz * 1000; + if (!nvbios_baseclock_entry(bios, &h, h.base_id, &base)) + clk->base_khz = base.clock_mhz * 1000; + } - nvkm_subdev_ctor(&nvkm_clk, device, index, &clk->subdev); clk->func = func; INIT_LIST_HEAD(&clk->states); clk->domains = func->domains; diff --git a/drm/nouveau/nvkm/subdev/clk/gf100.c b/drm/nouveau/nvkm/subdev/clk/gf100.c index 78c449b..71b7c9f 100644 --- a/drm/nouveau/nvkm/subdev/clk/gf100.c +++ b/drm/nouveau/nvkm/subdev/clk/gf100.c @@ -443,7 +443,7 @@ gf100_clk = { { nv_clk_src_hubk06 , 0x00 }, { nv_clk_src_hubk01 , 0x01 }, { nv_clk_src_copy , 0x02 }, - { nv_clk_src_gpc, 0x03, 0, "core", 2000 }, + { nv_clk_src_gpc, 0x03, NVKM_CLK_DOM_FLAG_BASECLK, "core", 2000 }, { nv_clk_src_rop, 0x04 }, { nv_clk_src_mem, 0x05, 0, "memory", 1000 }, { nv_clk_src_vdec , 0x06 }, diff --git a/drm/nouveau/nvkm/subdev/clk/gk104.c b/drm/nouveau/nvkm/subdev/clk/gk104.c index 9
[Nouveau] [PATCH v4 15/37] clk: allow boosting only when NvBoost is set
0: base clock from the vbios is max clock 1: boost only to boost clock from the vbios (default) 2: boost to max clock available v2: moved into nvkm_cstate_valid v4: check the existence of the clocks before limiting Signed-off-by: Karol Herbst Reviewed-by: Martin Peres --- drm/nouveau/include/nvkm/subdev/clk.h | 9 - drm/nouveau/nvkm/subdev/clk/base.c| 33 - drm/nouveau/nvkm/subdev/clk/gf100.c | 2 +- drm/nouveau/nvkm/subdev/clk/gk104.c | 2 +- 4 files changed, 42 insertions(+), 4 deletions(-) diff --git a/drm/nouveau/include/nvkm/subdev/clk.h b/drm/nouveau/include/nvkm/subdev/clk.h index 6226f0d..99ee05c 100644 --- a/drm/nouveau/include/nvkm/subdev/clk.h +++ b/drm/nouveau/include/nvkm/subdev/clk.h @@ -68,7 +68,8 @@ struct nvkm_pstate { struct nvkm_domain { enum nv_clk_src name; u8 bios; /* 0xff for none */ -#define NVKM_CLK_DOM_FLAG_CORE 0x01 +#define NVKM_CLK_DOM_FLAG_CORE0x01 +#define NVKM_CLK_DOM_FLAG_BASECLK 0x02 u8 flags; const char *mname; int mdiv; @@ -98,6 +99,12 @@ struct nvkm_clk { int dstate; /* display adjustment (min+) */ bool allow_reclock; +#define NVKM_CLK_BOOST_NONE 0x0 +#define NVKM_CLK_BOOST_AVG 0x1 +#define NVKM_CLK_BOOST_FULL 0x2 + u8 boost_mode; + u32 base_khz; + u32 boost_khz; /*XXX: die, these are here *only* to support the completely * bat-shit insane what-was-nouveau_hw.c code diff --git a/drm/nouveau/nvkm/subdev/clk/base.c b/drm/nouveau/nvkm/subdev/clk/base.c index 21f6369..a9a3666 100644 --- a/drm/nouveau/nvkm/subdev/clk/base.c +++ b/drm/nouveau/nvkm/subdev/clk/base.c @@ -24,6 +24,7 @@ #include "priv.h" #include +#include #include #include #include @@ -77,9 +78,25 @@ nvkm_clk_adjust(struct nvkm_clk *clk, bool adjust, static bool nvkm_cstate_valid(struct nvkm_clk *clk, struct nvkm_cstate *cstate, u32 max_volt, int temp) { + const struct nvkm_domain *domain = clk->domains; struct nvkm_volt *volt = clk->subdev.device->volt; int voltage; + while (domain && domain->name != nv_clk_src_max) { + if (domain->flags & NVKM_CLK_DOM_FLAG_BASECLK) { + u32 freq = cstate->domain[domain->name]; + switch (clk->boost_mode) { + case NVKM_CLK_BOOST_NONE: + if (clk->base_khz && freq > clk->base_khz) + return false; + case NVKM_CLK_BOOST_AVG: + if (clk->boost_khz && freq > clk->boost_khz) + return false; + } + } + domain++; + } + if (!volt) return true; @@ -641,10 +658,24 @@ int nvkm_clk_ctor(const struct nvkm_clk_func *func, struct nvkm_device *device, int index, bool allow_reclock, struct nvkm_clk *clk) { + struct nvkm_subdev *subdev = &clk->subdev; + struct nvkm_bios *bios = device->bios; int ret, idx, arglen; const char *mode; + struct nvbios_baseclk_header h; + + nvkm_subdev_ctor(&nvkm_clk, device, index, subdev); + + clk->boost_mode = nvkm_longopt(device->cfgopt, "NvBoost", + NVKM_CLK_BOOST_AVG); + if (bios && !nvbios_baseclock_parse(bios, &h)) { + struct nvbios_baseclk_entry base, boost; + if (!nvbios_baseclock_entry(bios, &h, h.boost_id, &boost)) + clk->boost_khz = boost.clock_mhz * 1000; + if (!nvbios_baseclock_entry(bios, &h, h.base_id, &base)) + clk->base_khz = base.clock_mhz * 1000; + } - nvkm_subdev_ctor(&nvkm_clk, device, index, &clk->subdev); clk->func = func; INIT_LIST_HEAD(&clk->states); clk->domains = func->domains; diff --git a/drm/nouveau/nvkm/subdev/clk/gf100.c b/drm/nouveau/nvkm/subdev/clk/gf100.c index 78c449b..71b7c9f 100644 --- a/drm/nouveau/nvkm/subdev/clk/gf100.c +++ b/drm/nouveau/nvkm/subdev/clk/gf100.c @@ -443,7 +443,7 @@ gf100_clk = { { nv_clk_src_hubk06 , 0x00 }, { nv_clk_src_hubk01 , 0x01 }, { nv_clk_src_copy , 0x02 }, - { nv_clk_src_gpc, 0x03, 0, "core", 2000 }, + { nv_clk_src_gpc, 0x03, NVKM_CLK_DOM_FLAG_BASECLK, "core", 2000 }, { nv_clk_src_rop, 0x04 }, { nv_clk_src_mem, 0x05, 0, "memory", 1000 }, { nv_clk_src_vdec , 0x06 }, diff --git a/drm/nouveau/nvkm/subdev/clk/gk104.c b/drm/nouveau/nvkm/subdev/clk/gk104.c index 975c401..639234f 100644 --- a/drm/nouveau/nvkm/subdev/clk/gk104.c +++ b/drm/nouveau/nvkm/subdev/clk/gk104.c @@ -485,7 +485,7 @@ gk104_clk = { .domains = { { nv_clk_src_crystal, 0xff }, { nv_clk_src_href , 0xff }, -