mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-27 19:29:37 +00:00
![Daniel Lezcano](/assets/img/avatar_default.png)
With the powercap dtpm controller, we are able to plug devices with power limitation features in the tree. The following patch introduces the CPU power limitation based on the energy model and the performance states. The power limitation is done at the performance domain level. If some CPUs are unplugged, the corresponding power will be subtracted from the performance domain total power. It is up to the platform to initialize the dtpm tree and add the CPU. Here is an example to create a simple tree with one root node called "pkg" and the CPU's performance domains. static int dtpm_register_pkg(struct dtpm_descr *descr) { struct dtpm *pkg; int ret; pkg = dtpm_alloc(NULL); if (!pkg) return -ENOMEM; ret = dtpm_register(descr->name, pkg, descr->parent); if (ret) return ret; return dtpm_register_cpu(pkg); } static struct dtpm_descr descr = { .name = "pkg", .init = dtpm_register_pkg, }; DTPM_DECLARE(descr); Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org> Reviewed-by: Lukasz Luba <lukasz.luba@arm.com> Tested-by: Lukasz Luba <lukasz.luba@arm.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
77 lines
1.6 KiB
C
77 lines
1.6 KiB
C
/* SPDX-License-Identifier: GPL-2.0-only */
|
|
/*
|
|
* Copyright (C) 2020 Linaro Ltd
|
|
*
|
|
* Author: Daniel Lezcano <daniel.lezcano@linaro.org>
|
|
*/
|
|
#ifndef ___DTPM_H__
|
|
#define ___DTPM_H__
|
|
|
|
#include <linux/powercap.h>
|
|
|
|
#define MAX_DTPM_DESCR 8
|
|
#define MAX_DTPM_CONSTRAINTS 1
|
|
|
|
struct dtpm {
|
|
struct powercap_zone zone;
|
|
struct dtpm *parent;
|
|
struct list_head sibling;
|
|
struct list_head children;
|
|
struct dtpm_ops *ops;
|
|
unsigned long flags;
|
|
u64 power_limit;
|
|
u64 power_max;
|
|
u64 power_min;
|
|
int weight;
|
|
void *private;
|
|
};
|
|
|
|
struct dtpm_ops {
|
|
u64 (*set_power_uw)(struct dtpm *, u64);
|
|
u64 (*get_power_uw)(struct dtpm *);
|
|
void (*release)(struct dtpm *);
|
|
};
|
|
|
|
struct dtpm_descr;
|
|
|
|
typedef int (*dtpm_init_t)(struct dtpm_descr *);
|
|
|
|
struct dtpm_descr {
|
|
struct dtpm *parent;
|
|
const char *name;
|
|
dtpm_init_t init;
|
|
};
|
|
|
|
/* Init section thermal table */
|
|
extern struct dtpm_descr *__dtpm_table[];
|
|
extern struct dtpm_descr *__dtpm_table_end[];
|
|
|
|
#define DTPM_TABLE_ENTRY(name) \
|
|
static typeof(name) *__dtpm_table_entry_##name \
|
|
__used __section("__dtpm_table") = &name
|
|
|
|
#define DTPM_DECLARE(name) DTPM_TABLE_ENTRY(name)
|
|
|
|
#define for_each_dtpm_table(__dtpm) \
|
|
for (__dtpm = __dtpm_table; \
|
|
__dtpm < __dtpm_table_end; \
|
|
__dtpm++)
|
|
|
|
static inline struct dtpm *to_dtpm(struct powercap_zone *zone)
|
|
{
|
|
return container_of(zone, struct dtpm, zone);
|
|
}
|
|
|
|
int dtpm_update_power(struct dtpm *dtpm, u64 power_min, u64 power_max);
|
|
|
|
int dtpm_release_zone(struct powercap_zone *pcz);
|
|
|
|
struct dtpm *dtpm_alloc(struct dtpm_ops *ops);
|
|
|
|
void dtpm_unregister(struct dtpm *dtpm);
|
|
|
|
int dtpm_register(const char *name, struct dtpm *dtpm, struct dtpm *parent);
|
|
|
|
int dtpm_register_cpu(struct dtpm *parent);
|
|
|
|
#endif
|