linux/drivers/thermal/intel/intel_powerclamp.c

// SPDX-License-Identifier: GPL-2.0-only
/*
 * intel_powerclamp.c - package c-state idle injection
 *
 * Copyright (c) 2012-2023, Intel Corporation.
 *
 * Authors:
 *     Arjan van de Ven <[email protected]>
 *     Jacob Pan <[email protected]>
 *
 *	TODO:
 *           1. better handle wakeup from external interrupts, currently a fixed
 *              compensation is added to clamping duration when excessive amount
 *              of wakeups are observed during idle time. the reason is that in
 *              case of external interrupts without need for ack, clamping down
 *              cpu in non-irq context does not reduce irq. for majority of the
 *              cases, clamping down cpu does help reduce irq as well, we should
 *              be able to differentiate the two cases and give a quantitative
 *              solution for the irqs that we can control. perhaps based on
 *              get_cpu_iowait_time_us()
 *
 *	     2. synchronization with other hw blocks
 */

#define pr_fmt(fmt)

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/cpu.h>
#include <linux/thermal.h>
#include <linux/debugfs.h>
#include <linux/seq_file.h>
#include <linux/idle_inject.h>

#include <asm/msr.h>
#include <asm/mwait.h>
#include <asm/cpu_device_id.h>

#define MAX_TARGET_RATIO
/* For each undisturbed clamping period (no extra wake ups during idle time),
 * we increment the confidence counter for the given target ratio.
 * CONFIDENCE_OK defines the level where runtime calibration results are
 * valid.
 */
#define CONFIDENCE_OK
/* Default idle injection duration, driver adjust sleep time to meet target
 * idle ratio. Similar to frequency modulation.
 */
#define DEFAULT_DURATION_JIFFIES

static struct dentry *debug_dir;
static bool poll_pkg_cstate_enable;

/* Idle ratio observed using package C-state counters */
static unsigned int current_ratio;

/* Skip the idle injection till set to true */
static bool should_skip;

struct powerclamp_data {};

static struct powerclamp_data powerclamp_data;

static struct thermal_cooling_device *cooling_dev;

static DEFINE_MUTEX(powerclamp_lock);

/* This duration is in microseconds */
static unsigned int duration;
static unsigned int pkg_cstate_ratio_cur;
static unsigned int window_size;

static int duration_set(const char *arg, const struct kernel_param *kp)
{}

static int duration_get(char *buf, const struct kernel_param *kp)
{}

static const struct kernel_param_ops duration_ops =;

module_param_cb();
MODULE_PARM_DESC();

#define DEFAULT_MAX_IDLE
#define MAX_ALL_CPU_IDLE

static u8 max_idle =;

static cpumask_var_t idle_injection_cpu_mask;

static int allocate_copy_idle_injection_mask(const struct cpumask *copy_mask)
{}

/* Return true if the cpumask and idle percent combination is invalid */
static bool check_invalid(cpumask_var_t mask, u8 idle)
{}

static int cpumask_set(const char *arg, const struct kernel_param *kp)
{}

static int cpumask_get(char *buf, const struct kernel_param *kp)
{}

static const struct kernel_param_ops cpumask_ops =;

module_param_cb();
MODULE_PARM_DESC();

static int max_idle_set(const char *arg, const struct kernel_param *kp)
{}

static const struct kernel_param_ops max_idle_ops =;

module_param_cb();
MODULE_PARM_DESC();

struct powerclamp_calibration_data {};

static struct powerclamp_calibration_data cal_data[MAX_TARGET_RATIO];

static int window_size_set(const char *arg, const struct kernel_param *kp)
{}

static const struct kernel_param_ops window_size_ops =;

module_param_cb();
MODULE_PARM_DESC();

struct pkg_cstate_info {};

#define PKG_CSTATE_INIT(id)

static struct pkg_cstate_info pkg_cstates[] =;

static bool has_pkg_state_counter(void)
{}

static u64 pkg_state_counter(void)
{}

static unsigned int get_compensation(int ratio)
{}

static void adjust_compensation(int target_ratio, unsigned int win)
{}

static bool powerclamp_adjust_controls(unsigned int target_ratio,
				unsigned int guard, unsigned int win)
{}

/*
 * This function calculates runtime from the current target ratio.
 * This function gets called under powerclamp_lock.
 */
static unsigned int get_run_time(void)
{}

/*
 * 1 HZ polling while clamping is active, useful for userspace
 * to monitor actual idle ratio.
 */
static void poll_pkg_cstate(struct work_struct *dummy);
static DECLARE_DELAYED_WORK(poll_pkg_cstate_work, poll_pkg_cstate);
static void poll_pkg_cstate(struct work_struct *dummy)
{}

static struct idle_inject_device *ii_dev;

/*
 * This function is called from idle injection core on timer expiry
 * for the run duration. This allows powerclamp to readjust or skip
 * injecting idle for this cycle.
 */
static bool idle_inject_update(void)
{}

/* This function starts idle injection by calling idle_inject_start() */
static void trigger_idle_injection(void)
{}

/*
 * This function is called from start_power_clamp() to register
 * CPUS with powercap idle injection register and set default
 * idle duration and latency.
 */
static int powerclamp_idle_injection_register(void)
{}

/*
 * This function is called from end_power_clamp() to stop idle injection
 * and unregister CPUS from powercap idle injection core.
 */
static void remove_idle_injection(void)
{}

/*
 * This function is called when user change the cooling device
 * state from zero to some other value.
 */
static int start_power_clamp(void)
{}

/*
 * This function is called when user change the cooling device
 * state from non zero value zero.
 */
static void end_power_clamp(void)
{}

static int powerclamp_get_max_state(struct thermal_cooling_device *cdev,
				 unsigned long *state)
{}

static int powerclamp_get_cur_state(struct thermal_cooling_device *cdev,
				 unsigned long *state)
{}

static int powerclamp_set_cur_state(struct thermal_cooling_device *cdev,
				 unsigned long new_target_ratio)
{}

/* bind to generic thermal layer as cooling device*/
static const struct thermal_cooling_device_ops powerclamp_cooling_ops =;

static const struct x86_cpu_id __initconst intel_powerclamp_ids[] =;
MODULE_DEVICE_TABLE(x86cpu, intel_powerclamp_ids);

static int __init powerclamp_probe(void)
{}

static int powerclamp_debug_show(struct seq_file *m, void *unused)
{}

DEFINE_SHOW_ATTRIBUTE();

static inline void powerclamp_create_debug_files(void)
{}

static int __init powerclamp_init(void)
{}
module_init();

static void __exit powerclamp_exit(void)
{}
module_exit(powerclamp_exit);

MODULE_IMPORT_NS();

MODULE_LICENSE();
MODULE_AUTHOR();
MODULE_AUTHOR();
MODULE_DESCRIPTION();