[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