[Nouveau] [PATCH v3 1/3] nvbios/power_budget: Add basic power budget parsing

Karol Herbst karolherbst at gmail.com
Wed Nov 30 23:47:59 UTC 2016


2016-12-01 0:15 GMT+01:00 Ben Skeggs <skeggsb at gmail.com>:
> On 12/01/2016 08:56 AM, Karol Herbst wrote:
>> 2016-11-30 23:48 GMT+01:00 Ben Skeggs <skeggsb at gmail.com>:
>>> On 12/01/2016 05:48 AM, Karol Herbst wrote:
>>>> v2: Set entry to 0xff if not found
>>>>     Add cap entry for ver 0x30 tables
>>>>     Rework to fix memory leak
>>>> v3: More error checks
>>>>     Simplify check for invalid entries
>>>>
>>>> Signed-off-by: Karol Herbst <karolherbst at gmail.com>
>>>> ---
>>>>  .../include/nvkm/subdev/bios/power_budget.h        |  25 +++++
>>>>  drm/nouveau/nvkm/subdev/bios/Kbuild                |   1 +
>>>>  drm/nouveau/nvkm/subdev/bios/power_budget.c        | 125 +++++++++++++++++++++
>>>>  3 files changed, 151 insertions(+)
>>>>  create mode 100644 drm/nouveau/include/nvkm/subdev/bios/power_budget.h
>>>>  create mode 100644 drm/nouveau/nvkm/subdev/bios/power_budget.c
>>>>
>>>> diff --git a/drm/nouveau/include/nvkm/subdev/bios/power_budget.h b/drm/nouveau/include/nvkm/subdev/bios/power_budget.h
>>>> new file mode 100644
>>>> index 00000000..89fd4a7a
>>>> --- /dev/null
>>>> +++ b/drm/nouveau/include/nvkm/subdev/bios/power_budget.h
>>>> @@ -0,0 +1,25 @@
>>>> +#ifndef __NVBIOS_POWER_BUDGET_H__
>>>> +#define __NVBIOS_POWER_BUDGET_H__
>>>> +
>>>> +#include <nvkm/subdev/bios.h>
>>>> +
>>>> +struct nvbios_power_budget_entry {
>>>> +     u32 min_w;
>>>> +     u32 avg_w;
>>>> +     u32 max_w;
>>>> +};
>>>> +
>>>> +struct nvbios_power_budget {
>>>> +     u32 offset;
>>>> +     u8  hlen;
>>>> +     u8  elen;
>>>> +     u8  ecount;
>>>> +     u8  cap_entry;
>>>> +};
>>>> +
>>>> +int nvbios_power_budget_header(struct nvkm_bios *,
>>>> +                               struct nvbios_power_budget *);
>>>> +int nvbios_power_budget_entry(struct nvkm_bios *, struct nvbios_power_budget *,
>>>> +                              u8 idx, struct nvbios_power_budget_entry *);
>>>> +
>>>> +#endif
>>>> diff --git a/drm/nouveau/nvkm/subdev/bios/Kbuild b/drm/nouveau/nvkm/subdev/bios/Kbuild
>>>> index be57220a..6b4f1e06 100644
>>>> --- a/drm/nouveau/nvkm/subdev/bios/Kbuild
>>>> +++ b/drm/nouveau/nvkm/subdev/bios/Kbuild
>>>> @@ -19,6 +19,7 @@ nvkm-y += nvkm/subdev/bios/pcir.o
>>>>  nvkm-y += nvkm/subdev/bios/perf.o
>>>>  nvkm-y += nvkm/subdev/bios/pll.o
>>>>  nvkm-y += nvkm/subdev/bios/pmu.o
>>>> +nvkm-y += nvkm/subdev/bios/power_budget.o
>>>>  nvkm-y += nvkm/subdev/bios/ramcfg.o
>>>>  nvkm-y += nvkm/subdev/bios/rammap.o
>>>>  nvkm-y += nvkm/subdev/bios/shadow.o
>>>> diff --git a/drm/nouveau/nvkm/subdev/bios/power_budget.c b/drm/nouveau/nvkm/subdev/bios/power_budget.c
>>>> new file mode 100644
>>>> index 00000000..04c69095
>>>> --- /dev/null
>>>> +++ b/drm/nouveau/nvkm/subdev/bios/power_budget.c
>>>> @@ -0,0 +1,125 @@
>>>> +/*
>>>> + * Copyright 2016 Karol Herbst
>>>> + *
>>>> + * Permission is hereby granted, free of charge, to any person obtaining a
>>>> + * copy of this software and associated documentation files (the "Software"),
>>>> + * to deal in the Software without restriction, including without limitation
>>>> + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
>>>> + * and/or sell copies of the Software, and to permit persons to whom the
>>>> + * Software is furnished to do so, subject to the following conditions:
>>>> + *
>>>> + * The above copyright notice and this permission notice shall be included in
>>>> + * all copies or substantial portions of the Software.
>>>> + *
>>>> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
>>>> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
>>>> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
>>>> + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
>>>> + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
>>>> + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
>>>> + * OTHER DEALINGS IN THE SOFTWARE.
>>>> + *
>>>> + * Authors: Karol Herbst
>>>> + */
>>>> +#include <subdev/bios.h>
>>>> +#include <subdev/bios/bit.h>
>>>> +#include <subdev/bios/power_budget.h>
>>>> +
>>>> +static u32
>>>> +nvbios_power_budget_table(struct nvkm_bios *bios, u8 *ver, u8 *hdr, u8 *cnt,
>>>> +                       u8 *len)
>>>> +{
>>>> +     struct bit_entry bit_P;
>>>> +     u32 power_budget;
>>>> +
>>>> +     if (bit_entry(bios, 'P', &bit_P) || bit_P.version != 2 ||
>>>> +         bit_P.length < 0x2c)
>>>> +             return 0;
>>>> +
>>>> +     power_budget = nvbios_rd32(bios, bit_P.offset + 0x2c);
>>>> +     if (!power_budget)
>>>> +             return 0;
>>>> +
>>>> +     *ver = nvbios_rd08(bios, power_budget);
>>>> +     switch (*ver) {
>>>> +     case 0x10:
>>>> +     case 0x20:
>>>> +     case 0x30:
>>>> +             *hdr = nvbios_rd08(bios, power_budget + 0x1);
>>>> +             *len = nvbios_rd08(bios, power_budget + 0x2);
>>>> +             *cnt = nvbios_rd08(bios, power_budget + 0x3);
>>>> +             return power_budget;
>>>> +     default:
>>>> +             break;
>>>> +     }
>>>> +
>>>> +     return 0;
>>>> +}
>>>> +
>>>> +int
>>>> +nvbios_power_budget_header(struct nvkm_bios *bios,
>>>> +                           struct nvbios_power_budget *budget)
>>>> +{
>>>> +     struct nvkm_subdev *subdev = &bios->subdev;
>>>> +     u8 ver, hdr, cnt, len, cap_entry;
>>>> +     u32 header;
>>>> +
>>>> +     if (!bios || !budget)
>>>> +             return -EINVAL;
>>>> +
>>>> +     header = nvbios_power_budget_table(bios, &ver, &hdr, &cnt, &len);
>>>> +     if (!header || !cnt)
>>>> +             return -ENODEV;
>>>> +
>>>> +     budget->offset = header;
>>>> +     budget->hlen = hdr;
>>>> +     budget->elen = len;
>>>> +     budget->ecount = cnt;
>>>> +
>>>> +     switch (ver) {
>>>> +     case 0x20:
>>>> +             cap_entry = nvbios_rd08(bios, header + 0x9);
>>>> +             break;
>>>> +     case 0x30:
>>>> +             cap_entry = nvbios_rd08(bios, header + 0xa);
>>>> +             break;
>>>> +     default:
>>>> +             cap_entry = 0xff;
>>>> +     }
>>>> +
>>>> +     if (cap_entry >= cnt && cap_entry != 0xff) {
>>>> +             nvkm_warn(subdev,
>>>> +                       "invalid cap_entry in power budget table found\n");
>>>> +             budget->cap_entry = 0xff;
>>>> +             return -EINVAL;
>>>> +     }
>>>> +
>>>> +     budget->cap_entry = cap_entry;
>>>> +     return 0;
>>>> +}
>>>> +
>>>> +int
>>>> +nvbios_power_budget_entry(struct nvkm_bios *bios,
>>>> +                          struct nvbios_power_budget *budget,
>>>> +                          u8 idx, struct nvbios_power_budget_entry *entry)
>>>> +{
>>>> +     u32 entry_offset;
>>>> +
>>>> +     if (!bios || !budget || !budget->offset || idx >= budget->ecount
>>>> +             || !entry)
>>>> +             return -EINVAL;
>>>> +
>>>> +     entry_offset = budget->offset + budget->hlen + idx * budget->elen;
>>>> +
>>>> +     if (budget->elen >= 0xe) {
>>> I question this check.  Generally, when the layout of existing fields
>>> changes, there's a version bump to check against.  The length is
>>> increased when new fields are added without disturbing the previous ones.
>>>
>>
>> and I say this doesn't hold up with this table, because this one is stupid :p
>>
>> found lengths:
>>
>> version 10:
>> 0x0c, 0x1d
>>
>> version 20:
>> 0x0d, 0x1f
>>
>> version 30:
>> 0x1f, 0x22
> I'm not questioning there's different lengths, I'm questioning whether
> all <3.0 versions should have the max_w @ +0x2 layout.
>

ohh I see. Not quite sure, I don't think there is actually a 2.0 table
with smaller entries and I didn't really had time to confirm this on
1.0 tables.

>>
>>>> +             entry->min_w = nvbios_rd32(bios, entry_offset + 0x2);
>>>> +             entry->avg_w = nvbios_rd32(bios, entry_offset + 0x6);
>>>> +             entry->max_w = nvbios_rd32(bios, entry_offset + 0xa);
>>>> +     } else {
>>>> +             entry->min_w = 0;
>>>> +             entry->max_w = nvbios_rd32(bios, entry_offset + 0x2);
>>>> +             entry->avg_w = entry->max_w;
>>>> +     }
>>>> +
>>>> +     return 0;
>>>> +}
>>>>
>>>
>>>
>>> _______________________________________________
>>> Nouveau mailing list
>>> Nouveau at lists.freedesktop.org
>>> https://lists.freedesktop.org/mailman/listinfo/nouveau
>>>
>


More information about the Nouveau mailing list