linux/kernel/power/energy_model.c

// SPDX-License-Identifier: GPL-2.0
/*
 * Energy Model of devices
 *
 * Copyright (c) 2018-2021, Arm ltd.
 * Written by: Quentin Perret, Arm ltd.
 * Improvements provided by: Lukasz Luba, Arm ltd.
 */

#define pr_fmt(fmt)

#include <linux/cpu.h>
#include <linux/cpufreq.h>
#include <linux/cpumask.h>
#include <linux/debugfs.h>
#include <linux/energy_model.h>
#include <linux/sched/topology.h>
#include <linux/slab.h>

/*
 * Mutex serializing the registrations of performance domains and letting
 * callbacks defined by drivers sleep.
 */
static DEFINE_MUTEX(em_pd_mutex);

static void em_cpufreq_update_efficiencies(struct device *dev,
					   struct em_perf_state *table);
static void em_check_capacity_update(void);
static void em_update_workfn(struct work_struct *work);
static DECLARE_DELAYED_WORK(em_update_work, em_update_workfn);

static bool _is_cpu_device(struct device *dev)
{}

#ifdef CONFIG_DEBUG_FS
static struct dentry *rootdir;

struct em_dbg_info {};

#define DEFINE_EM_DBG_SHOW(name, fname)

DEFINE_EM_DBG_SHOW();
DEFINE_EM_DBG_SHOW();
DEFINE_EM_DBG_SHOW();
DEFINE_EM_DBG_SHOW();
DEFINE_EM_DBG_SHOW();

static void em_debug_create_ps(struct em_perf_domain *em_pd,
			       struct em_dbg_info *em_dbg, int i,
			       struct dentry *pd)
{}

static int em_debug_cpus_show(struct seq_file *s, void *unused)
{}
DEFINE_SHOW_ATTRIBUTE();

static int em_debug_flags_show(struct seq_file *s, void *unused)
{}
DEFINE_SHOW_ATTRIBUTE();

static void em_debug_create_pd(struct device *dev)
{}

static void em_debug_remove_pd(struct device *dev)
{}

static int __init em_debug_init(void)
{}
fs_initcall(em_debug_init);
#else /* CONFIG_DEBUG_FS */
static void em_debug_create_pd(struct device *dev) {}
static void em_debug_remove_pd(struct device *dev) {}
#endif

static void em_destroy_table_rcu(struct rcu_head *rp)
{}

static void em_release_table_kref(struct kref *kref)
{}

/**
 * em_table_free() - Handles safe free of the EM table when needed
 * @table : EM table which is going to be freed
 *
 * No return values.
 */
void em_table_free(struct em_perf_table __rcu *table)
{}

/**
 * em_table_alloc() - Allocate a new EM table
 * @pd		: EM performance domain for which this must be done
 *
 * Allocate a new EM table and initialize its kref to indicate that it
 * has a user.
 * Returns allocated table or NULL.
 */
struct em_perf_table __rcu *em_table_alloc(struct em_perf_domain *pd)
{}

static void em_init_performance(struct device *dev, struct em_perf_domain *pd,
				struct em_perf_state *table, int nr_states)
{}

static int em_compute_costs(struct device *dev, struct em_perf_state *table,
			    struct em_data_callback *cb, int nr_states,
			    unsigned long flags)
{}

/**
 * em_dev_compute_costs() - Calculate cost values for new runtime EM table
 * @dev		: Device for which the EM table is to be updated
 * @table	: The new EM table that is going to get the costs calculated
 * @nr_states	: Number of performance states
 *
 * Calculate the em_perf_state::cost values for new runtime EM table. The
 * values are used for EAS during task placement. It also calculates and sets
 * the efficiency flag for each performance state. When the function finish
 * successfully the EM table is ready to be updated and used by EAS.
 *
 * Return 0 on success or a proper error in case of failure.
 */
int em_dev_compute_costs(struct device *dev, struct em_perf_state *table,
			 int nr_states)
{}

/**
 * em_dev_update_perf_domain() - Update runtime EM table for a device
 * @dev		: Device for which the EM is to be updated
 * @new_table	: The new EM table that is going to be used from now
 *
 * Update EM runtime modifiable table for the @dev using the provided @table.
 *
 * This function uses a mutex to serialize writers, so it must not be called
 * from a non-sleeping context.
 *
 * Return 0 on success or an error code on failure.
 */
int em_dev_update_perf_domain(struct device *dev,
			      struct em_perf_table __rcu *new_table)
{}
EXPORT_SYMBOL_GPL();

static int em_create_perf_table(struct device *dev, struct em_perf_domain *pd,
				struct em_perf_state *table,
				struct em_data_callback *cb,
				unsigned long flags)
{}

static int em_create_pd(struct device *dev, int nr_states,
			struct em_data_callback *cb, cpumask_t *cpus,
			unsigned long flags)
{}

static void
em_cpufreq_update_efficiencies(struct device *dev, struct em_perf_state *table)
{}

/**
 * em_pd_get() - Return the performance domain for a device
 * @dev : Device to find the performance domain for
 *
 * Returns the performance domain to which @dev belongs, or NULL if it doesn't
 * exist.
 */
struct em_perf_domain *em_pd_get(struct device *dev)
{}
EXPORT_SYMBOL_GPL();

/**
 * em_cpu_get() - Return the performance domain for a CPU
 * @cpu : CPU to find the performance domain for
 *
 * Returns the performance domain to which @cpu belongs, or NULL if it doesn't
 * exist.
 */
struct em_perf_domain *em_cpu_get(int cpu)
{}
EXPORT_SYMBOL_GPL();

/**
 * em_dev_register_perf_domain() - Register the Energy Model (EM) for a device
 * @dev		: Device for which the EM is to register
 * @nr_states	: Number of performance states to register
 * @cb		: Callback functions providing the data of the Energy Model
 * @cpus	: Pointer to cpumask_t, which in case of a CPU device is
 *		obligatory. It can be taken from i.e. 'policy->cpus'. For other
 *		type of devices this should be set to NULL.
 * @microwatts	: Flag indicating that the power values are in micro-Watts or
 *		in some other scale. It must be set properly.
 *
 * Create Energy Model tables for a performance domain using the callbacks
 * defined in cb.
 *
 * The @microwatts is important to set with correct value. Some kernel
 * sub-systems might rely on this flag and check if all devices in the EM are
 * using the same scale.
 *
 * If multiple clients register the same performance domain, all but the first
 * registration will be ignored.
 *
 * Return 0 on success
 */
int em_dev_register_perf_domain(struct device *dev, unsigned int nr_states,
				struct em_data_callback *cb, cpumask_t *cpus,
				bool microwatts)
{}
EXPORT_SYMBOL_GPL();

/**
 * em_dev_unregister_perf_domain() - Unregister Energy Model (EM) for a device
 * @dev		: Device for which the EM is registered
 *
 * Unregister the EM for the specified @dev (but not a CPU device).
 */
void em_dev_unregister_perf_domain(struct device *dev)
{}
EXPORT_SYMBOL_GPL();

static struct em_perf_table __rcu *em_table_dup(struct em_perf_domain *pd)
{}

static int em_recalc_and_update(struct device *dev, struct em_perf_domain *pd,
				struct em_perf_table __rcu *em_table)
{}

/*
 * Adjustment of CPU performance values after boot, when all CPUs capacites
 * are correctly calculated.
 */
static void em_adjust_new_capacity(struct device *dev,
				   struct em_perf_domain *pd,
				   u64 max_cap)
{}

static void em_check_capacity_update(void)
{}

static void em_update_workfn(struct work_struct *work)
{}

/**
 * em_dev_update_chip_binning() - Update Energy Model after the new voltage
 *				information is present in the OPPs.
 * @dev		: Device for which the Energy Model has to be updated.
 *
 * This function allows to update easily the EM with new values available in
 * the OPP framework and DT. It can be used after the chip has been properly
 * verified by device drivers and the voltages adjusted for the 'chip binning'.
 */
int em_dev_update_chip_binning(struct device *dev)
{}
EXPORT_SYMBOL_GPL();